Fixes #218 - gets rid of @import statements appearing after CSS content.
authorGoalSmashers <jakub@goalsmashers.com>
Sat, 1 Feb 2014 07:30:24 +0000 (07:30 +0000)
committerGoalSmashers <jakub@goalsmashers.com>
Sat, 1 Feb 2014 07:34:31 +0000 (07:34 +0000)
See www.w3.org/TR/CSS21/cascade.html#at-import for details.

History.md
lib/imports/inliner.js
test/unit-test.js

index 20c49f4..0c6e632 100644 (file)
@@ -13,6 +13,7 @@
 * Fixed issue [#186](https://github.com/GoalSmashers/clean-css/issues/186) - strip unit from 0rem.
 * Fixed issue [#207](https://github.com/GoalSmashers/clean-css/issues/207) - bug in parsing protocol `@import`s.
 * Fixed issue [#213](https://github.com/GoalSmashers/clean-css/issues/213) - faster rgb to hex transforms.
+* Fixed issue [#218](https://github.com/GoalSmashers/clean-css/issues/218) - `@import` statements cleanup.
 
 [2.0.7 / 2014-01-16](https://github.com/GoalSmashers/clean-css/compare/v2.0.6...v2.0.7)
 ==================
index 29d309c..2b9d5f0 100644 (file)
@@ -34,6 +34,7 @@ module.exports = function Inliner(context, options) {
     var nextEnd = 0;
     var cursor = 0;
     var isComment = commentScanner(data);
+    var afterContent = contentScanner(data);
 
     options.relativeTo = options.relativeTo || options.root;
     options._baseRelativeTo = options._baseRelativeTo || options.relativeTo;
@@ -59,7 +60,9 @@ module.exports = function Inliner(context, options) {
       shared.done.push(data.substring(cursor, nextStart));
       shared.left.unshift([data.substring(nextEnd + 1), options]);
 
-      return inline(data, nextStart, nextEnd, options);
+      return afterContent(nextStart) ?
+        processNext(options) :
+        inline(data, nextStart, nextEnd, options);
     }
 
     // no @import matched in current data
@@ -125,6 +128,22 @@ module.exports = function Inliner(context, options) {
     return scanner;
   };
 
+  var contentScanner = function(data) {
+    var isComment = commentScanner(data);
+    var firstContentIdx = -1;
+    while (true) {
+      firstContentIdx = data.indexOf('{', firstContentIdx + 1);
+      if (firstContentIdx == -1 || !isComment(firstContentIdx))
+        break;
+    }
+
+    return function(idx) {
+      return firstContentIdx > -1 ?
+        idx > firstContentIdx :
+        false;
+    };
+  };
+
   var inline = function(data, nextStart, nextEnd, options) {
     var importDeclaration = data
       .substring(data.indexOf(' ', nextStart) + 1, nextEnd)
index 1a56bf8..6f3bb30 100644 (file)
@@ -1082,8 +1082,8 @@ title']{display:block}",
       ''
     ],
     'of more files': [
-      "@import url(test/data/partials/one.css);\n\na{display:block}\n\n@import url(test/data/partials/extra/three.css);",
-      ".one{color:red}a{display:block}.three{color:#0f0}"
+      "@import url(test/data/partials/one.css);\n\n@import url(test/data/partials/extra/three.css);\n\na{display:block}",
+      ".one{color:red}.three{color:#0f0}a{display:block}"
     ],
     'of more files with media': [
       "@import url(test/data/partials/one.css) screen;@import url(test/data/partials/extra/three.css) tv;",
@@ -1128,6 +1128,14 @@ title']{display:block}",
     'of a file (with media) with a comment': [
       '@import url(test/data/partials/comment.css) screen and (device-height: 600px);',
       '@media screen and (device-height:600px){a{display:block}}'
+    ],
+    'after standard content': [
+      "a{display:block}@import url(test/data/partials/one.css);body{margin:0}",
+      "a{display:block}body{margin:0}"
+    ],
+    'after quoted content': [
+      "/*a{display:block}*/@import url(test/data/partials/one.css);",
+      ".one{color:red}"
     ]
   }, { root: process.cwd() }),
   '@import with absolute paths': cssContext({
@@ -1144,8 +1152,8 @@ title']{display:block}",
       ".one{color:red}"
     ],
     'of two files with mixed paths': [
-      "@import url(/partials/one.css);a{display:block}@import url(partials/extra/three.css);",
-      ".one{color:red}a{display:block}.three{color:#0f0}"
+      "@import url(/partials/one.css);@import url(partials/extra/three.css);a{display:block}",
+      ".one{color:red}.three{color:#0f0}a{display:block}"
     ],
     'of a multi-level, circular dependency file': [
       "@import url(/partials/two.css);",