Skip to content

Commit

Permalink
TAP5-2606 - Updating YUI CssCompressor to the latest version from its…
Browse files Browse the repository at this point in the history
… github master branch
  • Loading branch information
balapal committed Jan 17, 2019
1 parent 0f4cd36 commit 0b3a8c5
Showing 1 changed file with 83 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.ArrayList;

public class CssCompressor {

Expand All @@ -30,28 +30,33 @@ public CssCompressor(Reader in) throws IOException {
}
}

// Leave data urls alone to increase parse performance.
protected String extractDataUrls(String css, ArrayList preservedTokens) {
/**
* @param css - full css string
* @param preservedToken - token to preserve
* @param tokenRegex - regex to find token
* @param removeWhiteSpace - remove any white space in the token
* @param preservedTokens - array of token values
* @return
*/
protected String preserveToken(String css, String preservedToken,
String tokenRegex, boolean removeWhiteSpace, ArrayList preservedTokens) {

int maxIndex = css.length() - 1;
int appendIndex = 0;

StringBuffer sb = new StringBuffer();

Pattern p = Pattern.compile("(?i)url\\(\\s*([\"']?)data\\:");
Pattern p = Pattern.compile(tokenRegex);
Matcher m = p.matcher(css);

/*
* Since we need to account for non-base64 data urls, we need to handle
* ' and ) being part of the data string. Hence switching to indexOf,
* to determine whether or not we have matching string terminators and
* handling sb appends directly, instead of using matcher.append* methods.
*/

while (m.find()) {
int startIndex = m.start() + (preservedToken.length() + 1);
String terminator = m.group(1);

int startIndex = m.start() + 4; // "url(".length()
String terminator = m.group(1); // ', " or empty (not quoted)
// skip this, if CSS was already copied to "sb" upto this position
if (m.start() < appendIndex) {
continue;
}

if (terminator.length() == 0) {
terminator = ")";
Expand All @@ -63,7 +68,9 @@ protected String extractDataUrls(String css, ArrayList preservedTokens) {
while(foundTerminator == false && endIndex+1 <= maxIndex) {
endIndex = css.indexOf(terminator, endIndex+1);

if ((endIndex > 0) && (css.charAt(endIndex-1) != '\\')) {
if (endIndex <= 0) {
break;
} else if ((endIndex > 0) && (css.charAt(endIndex-1) != '\\')) {
foundTerminator = true;
if (!")".equals(terminator)) {
endIndex = css.indexOf(")", endIndex);
Expand All @@ -76,10 +83,11 @@ protected String extractDataUrls(String css, ArrayList preservedTokens) {

if (foundTerminator) {
String token = css.substring(startIndex, endIndex);
token = token.replaceAll("\\s+", "");
if(removeWhiteSpace)
token = token.replaceAll("\\s+", "");
preservedTokens.add(token);

String preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___)";
String preserver = preservedToken + "(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___)";
sb.append(preserver);

appendIndex = endIndex + 1;
Expand All @@ -95,20 +103,6 @@ protected String extractDataUrls(String css, ArrayList preservedTokens) {
return sb.toString();
}

private String preserveOldIESpecificMatrixDefinition(String css, ArrayList preservedTokens) {
StringBuffer sb = new StringBuffer();
Pattern p = Pattern.compile("\\s*filter:\\s*progid:DXImageTransform.Microsoft.Matrix\\(([^\\)]+)\\);");
Matcher m = p.matcher(css);
while (m.find()) {
String token = m.group(1);
preservedTokens.add(token);
String preserver = "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___";
m.appendReplacement(sb, "filter:progid:DXImageTransform.Microsoft.Matrix(" + preserver + ");");
}
m.appendTail(sb);
return sb.toString();
}

public void compress(Writer out, int linebreakpos)
throws IOException {

Expand All @@ -126,7 +120,6 @@ public void compress(Writer out, int linebreakpos)
int totallen = css.length();
String placeholder;

css = this.extractDataUrls(css, preservedTokens);

StringBuffer sb = new StringBuffer(css);

Expand All @@ -144,6 +137,12 @@ public void compress(Writer out, int linebreakpos)
}
css = sb.toString();


css = this.preserveToken(css, "url", "(?i)url\\(\\s*([\"']?)data\\:", true, preservedTokens);
css = this.preserveToken(css, "calc", "(?i)calc\\(\\s*([\"']?)", false, preservedTokens);
css = this.preserveToken(css, "progid:DXImageTransform.Microsoft.Matrix", "(?i)progid:DXImageTransform.Microsoft.Matrix\\s*([\"']?)", false, preservedTokens);


// preserve strings so their content doesn't get accidentally minified
sb = new StringBuffer();
p = Pattern.compile("(\"([^\\\\\"]|\\\\.|\\\\)*\")|(\'([^\\\\\']|\\\\.|\\\\)*\')");
Expand Down Expand Up @@ -213,17 +212,21 @@ public void compress(Writer out, int linebreakpos)
css = css.replace("/*" + placeholder + "*/", "");
}


// preserve \9 IE hack
final String backslash9 = "\\9";
while (css.indexOf(backslash9) > -1) {
preservedTokens.add(backslash9);
css = css.replace(backslash9, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.size() - 1) + "___");
}

// Normalize all whitespace strings to single spaces. Easier to work with that way.
css = css.replaceAll("\\s+", " ");

css = this.preserveOldIESpecificMatrixDefinition(css, preservedTokens);

// Remove the spaces before the things that should not have spaces before them.
// But, be careful not to turn "p :link {...}" into "p:link{...}"
// Swap out any pseudo-class colons with the token, and then swap back.
sb = new StringBuffer();
p = Pattern.compile("(^|\\})(([^\\{:])+:)+([^\\{]*\\{)");
p = Pattern.compile("(^|\\})((^|([^\\{:])+):)+([^\\{]*\\{)");
m = p.matcher(css);
while (m.find()) {
String s = m.group();
Expand Down Expand Up @@ -258,7 +261,8 @@ public void compress(Writer out, int linebreakpos)
p = Pattern.compile("(?i)^(.*)(@charset)( \"[^\"]*\";)");
m = p.matcher(css);
while (m.find()) {
m.appendReplacement(sb, m.group(2).toLowerCase() + m.group(3) + m.group(1));
String s = m.group(1).replaceAll("\\\\", "\\\\\\\\").replaceAll("\\$", "\\\\\\$");
m.appendReplacement(sb, m.group(2).toLowerCase() + m.group(3) + s);
}
m.appendTail(sb);
css = sb.toString();
Expand Down Expand Up @@ -325,12 +329,29 @@ public void compress(Writer out, int linebreakpos)
css = css.replaceAll(";+}", "}");

// Replace 0(px,em,%) with 0.
css = css.replaceAll("(?i)(^|[^0-9])(?:0?\\.)?0(?:px|em|in|cm|mm|pc|pt|ex|deg|g?rad|m?s|k?hz)", "$10");
String oldCss;
p = Pattern.compile("(?i)(^|: ?)((?:[0-9a-z-.]+ )*?)?(?:0?\\.)?0(?:px|em|%|in|cm|mm|pc|pt|ex|deg|g?rad|m?s|k?hz)");
do {
oldCss = css;
m = p.matcher(css);
css = m.replaceAll("$1$20");
} while (!(css.equals(oldCss)));

// Replace 0(px,em,%) with 0 inside groups (e.g. -MOZ-RADIAL-GRADIENT(CENTER 45DEG, CIRCLE CLOSEST-SIDE, ORANGE 0%, RED 100%))
p = Pattern.compile("(?i)\\( ?((?:[0-9a-z-.]+[ ,])*)?(?:0?\\.)?0(?:px|em|%|in|cm|mm|pc|pt|ex|deg|g?rad|m?s|k?hz)");
do {
oldCss = css;
m = p.matcher(css);
css = m.replaceAll("($10");
} while (!(css.equals(oldCss)));

// Replace x.0(px,em,%) with x(px,em,%).
css = css.replaceAll("([0-9])\\.0(px|em|%|in|cm|mm|pc|pt|ex|deg|g?rad|m?s|k?hz| |;)", "$1$2");

// Replace 0 0 0 0; with 0.
css = css.replaceAll(":0 0 0 0(;|})", ":0$1");
css = css.replaceAll(":0 0 0(;|})", ":0$1");
css = css.replaceAll(":0 0(;|})", ":0$1");
css = css.replaceAll("(?<!flex):0 0(;|})", ":0$1");


// Replace background-position:0; with background-position:0 0;
Expand Down Expand Up @@ -398,8 +419,8 @@ public void compress(Writer out, int linebreakpos)
sb.append(m.group(1) + "#" + m.group(2) + m.group(3) + m.group(4) + m.group(5) + m.group(6) + m.group(7));
} else {
if( m.group(2).equalsIgnoreCase(m.group(3)) &&
m.group(4).equalsIgnoreCase(m.group(5)) &&
m.group(6).equalsIgnoreCase(m.group(7))) {
m.group(4).equalsIgnoreCase(m.group(5)) &&
m.group(6).equalsIgnoreCase(m.group(7))) {

// #AABBCC pattern
sb.append("#" + (m.group(3) + m.group(5) + m.group(7)).toLowerCase());
Expand Down Expand Up @@ -477,14 +498,33 @@ public void compress(Writer out, int linebreakpos)
css = css.replaceAll(";;+", ";");

// restore preserved comments and strings
for(i = preservedTokens.size() - 1; i >= 0 ; i--) {
for(i = 0, max = preservedTokens.size(); i < max; i++) {
css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens.get(i).toString());
}

// Add spaces back in between operators for css calc function
// https://developer.mozilla.org/en-US/docs/Web/CSS/calc
// Added by Eric Arnol-Martin ([email protected])
sb = new StringBuffer();
p = Pattern.compile("calc\\([^\\)]*\\)");
m = p.matcher(css);
while (m.find()) {
String s = m.group();

s = s.replaceAll("(?<=[-|%|px|em|rem|vw|\\d]+)\\+", " + ");
s = s.replaceAll("(?<=[-|%|px|em|rem|vw|\\d]+)\\-", " - ");
s = s.replaceAll("(?<=[-|%|px|em|rem|vw|\\d]+)\\*", " * ");
s = s.replaceAll("(?<=[-|%|px|em|rem|vw|\\d]+)\\/", " / ");

m.appendReplacement(sb, s);
}
m.appendTail(sb);
css = sb.toString();

// Trim the final string (for any leading or trailing white spaces)
css = css.trim();

// Write the output...
out.write(css);
}
}
}

0 comments on commit 0b3a8c5

Please sign in to comment.