support minifyCSS on media queries
authoralexlamsl <alexlamsl@gmail.com>
Sun, 26 Jun 2016 11:39:02 +0000 (19:39 +0800)
committeralexlamsl <alexlamsl@gmail.com>
Sun, 26 Jun 2016 11:39:02 +0000 (19:39 +0800)
fixes #669

src/htmlminifier.js
tests/minifier.js

index 6793187..4bf2908 100644 (file)
@@ -228,17 +228,21 @@ function isNumberTypeAttribute(attrName, tag) {
   );
 }
 
-function isCanonicalURL(tag, attrs) {
+function isLinkType(tag, attrs, value) {
   if (tag !== 'link') {
     return false;
   }
   for (var i = 0, len = attrs.length; i < len; i++) {
-    if (attrs[i].name === 'rel' && attrs[i].value === 'canonical') {
+    if (attrs[i].name === 'rel' && attrs[i].value === value) {
       return true;
     }
   }
 }
 
+function isMediaQuery(tag, attrs, attrName) {
+  return attrName === 'media' && (isLinkType(tag, attrs, 'stylesheet') || isStyleSheet(tag, attrs));
+}
+
 var srcsetTags = createMapFromString('img,source');
 
 function isSrcset(attrName, tag) {
@@ -262,7 +266,7 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
   }
   else if (isUriTypeAttribute(attrName, tag)) {
     attrValue = trimWhitespace(attrValue);
-    return isCanonicalURL(tag, attrs) ? attrValue : options.minifyURLs(attrValue);
+    return isLinkType(tag, attrs, 'canonical') ? attrValue : options.minifyURLs(attrValue);
   }
   else if (isNumberTypeAttribute(attrName, tag)) {
     return trimWhitespace(attrValue);
@@ -308,6 +312,10 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
   else if (tag === 'script' && attrName === 'type') {
     attrValue = trimWhitespace(attrValue.replace(/\s*;\s*/g, ';'));
   }
+  else if (isMediaQuery(tag, attrs, attrName)) {
+    attrValue = trimWhitespace(attrValue);
+    return unwrapMediaQuery(options.minifyCSS(wrapMediaQuery(attrValue)));
+  }
   return attrValue;
 }
 
@@ -333,6 +341,15 @@ function unwrapInlineCSS(text) {
   return matches ? matches[1] : text;
 }
 
+function wrapMediaQuery(text) {
+  return '@media ' + text + '{a{top:0}}';
+}
+
+function unwrapMediaQuery(text) {
+  var matches = text.match(/^@media ([\s\S]*?)\s*{[\s\S]*}$/);
+  return matches ? matches[1] : text;
+}
+
 function cleanConditionalComment(comment, options) {
   return options.processConditionalComments ? comment.replace(/^(\[if\s[^\]]+\]>)([\s\S]*?)(<!\[endif\])$/, function(match, prefix, text, suffix) {
     return prefix + minify(text, options, true) + suffix;
index d335d84..df8bcea 100644 (file)
@@ -713,6 +713,20 @@ QUnit.test('custom processors', function(assert) {
   output = '<p style="Some CSS"></p>';
   assert.equal(minify(input, { minifyCSS: css }), output);
 
+  input = '<link rel="stylesheet" href="css/style-mobile.css" media="(max-width: 737px)">';
+  assert.equal(minify(input), input);
+  assert.equal(minify(input, { minifyCSS: null }), input);
+  assert.equal(minify(input, { minifyCSS: false }), input);
+  output = '<link rel="stylesheet" href="css/style-mobile.css" media="Some CSS">';
+  assert.equal(minify(input, { minifyCSS: css }), output);
+
+  input = '<style media="(max-width: 737px)"></style>';
+  assert.equal(minify(input), input);
+  assert.equal(minify(input, { minifyCSS: null }), input);
+  assert.equal(minify(input, { minifyCSS: false }), input);
+  output = '<style media="Some CSS">Some CSS</style>';
+  assert.equal(minify(input, { minifyCSS: css }), output);
+
   function js(text, inline) {
     return inline ? 'Inline JS' : 'Normal JS';
   }
@@ -1997,6 +2011,26 @@ QUnit.test('style minification', function(assert) {
     collapseWhitespace: true,
     minifyCSS: true
   }), output);
+
+  input = '<link rel="stylesheet" href="css/style-mobile.css" media="(max-width: 737px)">';
+  assert.equal(minify(input), input);
+  output = '<link rel="stylesheet" href="css/style-mobile.css" media="(max-width:737px)">';
+  assert.equal(minify(input, { minifyCSS: true }), output);
+  output = '<link rel=stylesheet href=css/style-mobile.css media=(max-width:737px)>';
+  assert.equal(minify(input, {
+    minifyCSS: true,
+    removeAttributeQuotes: true
+  }), output);
+
+  input = '<style media="(max-width: 737px)"></style>';
+  assert.equal(minify(input), input);
+  output = '<style media="(max-width:737px)"></style>';
+  assert.equal(minify(input, { minifyCSS: true }), output);
+  output = '<style media=(max-width:737px)></style>';
+  assert.equal(minify(input, {
+    minifyCSS: true,
+    removeAttributeQuotes: true
+  }), output);
 });
 
 QUnit.test('style attribute minification', function(assert) {