Ignores `@import` at-rules if after content.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Mon, 12 Dec 2016 13:12:22 +0000 (14:12 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Mon, 12 Dec 2016 15:06:05 +0000 (16:06 +0100)
Why:

* This is what browsers do and we should respect it.

History.md
lib/clean.js
lib/selectors/simple.js
test/module-test.js
test/protocol-imports-test.js
test/test-helper.js

index d800bff..2aeaa7a 100644 (file)
@@ -7,6 +7,7 @@
 ==================
 
 * Fixed issue [#841](https://github.com/jakubpawlowicz/clean-css/issues/841) - disabled importing and files passed as array.
+* Ignores `@import` at-rules if appearing after any non-`@import` rules.
 
 [3.4.21 / 2016-11-16](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.20...v3.4.21)
 ==================
index 4838c8d..1fe9390 100644 (file)
@@ -222,7 +222,7 @@ function minify(context, data) {
 
   var tokens = tokenize(data, context);
 
-  simpleOptimize(tokens, options);
+  simpleOptimize(tokens, options, context);
 
   if (options.advanced)
     advancedOptimize(tokens, options, context, true);
index 5e6fd3c..b5753e1 100644 (file)
@@ -14,6 +14,7 @@ var removeUnused = require('../properties/remove-unused');
 var DEFAULT_ROUNDING_PRECISION = 2;
 var CHARSET_TOKEN = '@charset';
 var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i');
+var IMPORT_REGEXP = /^@import["'\s]/i;
 
 var FONT_NUMERAL_WEIGHTS = ['100', '200', '300', '400', '500', '600', '700', '800', '900'];
 var FONT_NAME_WEIGHTS = ['normal', 'bold', 'bolder', 'lighter'];
@@ -404,11 +405,12 @@ function buildPrecision(options) {
   return precision;
 }
 
-function optimize(tokens, options) {
+function optimize(tokens, options, context) {
   var ie7Hack = options.compatibility.selectors.ie7Hack;
   var adjacentSpace = options.compatibility.selectors.adjacentSpace;
   var spaceAfterClosingBrace = options.compatibility.properties.spaceAfterClosingBrace;
   var mayHaveCharset = false;
+  var afterContent = false;
 
   options.unitsRegexp = buildUnitRegexp(options);
   options.precision = buildPrecision(options);
@@ -420,20 +422,28 @@ function optimize(tokens, options) {
       case 'selector':
         token[1] = cleanUpSelectors(token[1], !ie7Hack, adjacentSpace);
         optimizeBody(token[2], options);
+        afterContent = true;
         break;
       case 'block':
         cleanUpBlock(token[1], spaceAfterClosingBrace);
-        optimize(token[2], options);
+        optimize(token[2], options, context);
+        afterContent = true;
         break;
       case 'flat-block':
         cleanUpBlock(token[1], spaceAfterClosingBrace);
         optimizeBody(token[2], options);
+        afterContent = true;
         break;
       case 'at-rule':
         cleanUpAtRule(token[1]);
         mayHaveCharset = true;
     }
 
+    if (token[0] == 'at-rule' && IMPORT_REGEXP.test(token[1]) && afterContent) {
+      context.warnings.push('Ignoring @import rule "' + token[1] + '" as it appears after rules thus browsers will ignore them.');
+      token[1] = '';
+    }
+
     if (token[1].length === 0 || (token[2] && token[2].length === 0)) {
       tokens.splice(i, 1);
       i--;
index 7fac792..695ac22 100644 (file)
@@ -482,6 +482,14 @@ vows.describe('module tests').addBatch({
         'should give right output': function (minified) {
           assert.equal(minified.styles, '@import url(http://jakubpawlowicz.com/styles.css);@import url(./extra/sub.css);.base{margin:0}');
         }
+      },
+      'off - many files with content': {
+        'topic': function () {
+          return new CleanCSS({ processImport: false }).minify(['./test/fixtures/partials/two.css', './test/fixtures/partials-absolute/base.css']);
+        },
+        'should give right output': function (minified) {
+          assert.equal(minified.styles, '@import url(one.css);@import url(extra/three.css);@import url(./extra/four.css);.two{color:#fff}.base{margin:0}');
+        }
       }
     }
   },
index 54e3ede..4564878 100644 (file)
@@ -789,7 +789,7 @@ vows.describe('protocol imports').addBatch({
     'should not raise errors': function (error, minified) {
       assert.isEmpty(minified.errors);
     },
-    'should not raise warnings': function (error, minified) {
+    'should raise a warning': function (error, minified) {
       assert.lengthOf(minified.warnings, 1);
     },
     'should process imports': function (error, minified) {
index 12e7a76..19eaa67 100644 (file)
@@ -35,7 +35,7 @@ function selectorContext(group, specs, options) {
   function optimized(selectors) {
     return function (source) {
       var tokens = tokenize(source, { options: {} });
-      simpleOptimize(tokens, options);
+      simpleOptimize(tokens, options, {});
 
       assert.deepEqual(tokens[0] ? tokens[0][1] : null, selectors);
     };
@@ -59,7 +59,7 @@ function propertyContext(group, specs, options) {
   function optimized(selectors) {
     return function (source) {
       var tokens = tokenize(source, { options: {} });
-      simpleOptimize(tokens, options);
+      simpleOptimize(tokens, options, {});
 
       var value = tokens[0] ?
         tokens[0][2].map(function (property) {