Fixes #590 - an edge case in import processing.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Tue, 2 Jun 2015 18:51:24 +0000 (19:51 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Tue, 2 Jun 2015 20:02:52 +0000 (21:02 +0100)
Rebasing import statements without url had a nasty edge case where
a subsequent content ended up wrapped into a `url()`.

History.md
lib/urls/reduce.js
test/integration-test.js

index ff0dd8f..5f370a0 100644 (file)
@@ -1,3 +1,8 @@
+[3.3.1 / 2015-xx-xx](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.0...3.3)
+==================
+
+* Fixed issue [#590](https://github.com/jakubpawlowicz/clean-css/issues/590) - edge case in `@import` processing.
+
 [3.3.0 / 2015-05-31](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.11...v3.3.0)
 ==================
 
index ded0bf7..4a5fa54 100644 (file)
@@ -59,28 +59,30 @@ function byUrl(data, context, callback) {
 }
 
 function byImport(data, context, callback) {
+  var nextImport = 0;
+  var nextImportUpperCase = 0;
   var nextStart = 0;
-  var nextStartUpperCase = 0;
   var nextEnd = 0;
   var cursor = 0;
   var tempData = [];
   var nextSingleQuote = 0;
   var nextDoubleQuote = 0;
+  var untilNextQuote;
   var withQuote;
   var SINGLE_QUOTE = '\'';
   var DOUBLE_QUOTE = '"';
 
   for (; nextEnd < data.length;) {
-    nextStart = data.indexOf(IMPORT_URL_PREFIX, nextEnd);
-    nextStartUpperCase = data.indexOf(UPPERCASE_IMPORT_URL_PREFIX, nextEnd);
-    if (nextStart == -1 && nextStartUpperCase == -1)
+    nextImport = data.indexOf(IMPORT_URL_PREFIX, nextEnd);
+    nextImportUpperCase = data.indexOf(UPPERCASE_IMPORT_URL_PREFIX, nextEnd);
+    if (nextImport == -1 && nextImportUpperCase == -1)
       break;
 
-    if (nextStart > -1 && nextStartUpperCase > -1 && nextStartUpperCase < nextStart)
-      nextStart = nextStartUpperCase;
+    if (nextImport > -1 && nextImportUpperCase > -1 && nextImportUpperCase < nextImport)
+      nextImport = nextImportUpperCase;
 
-    nextSingleQuote = data.indexOf(SINGLE_QUOTE, nextStart);
-    nextDoubleQuote = data.indexOf(DOUBLE_QUOTE, nextStart);
+    nextSingleQuote = data.indexOf(SINGLE_QUOTE, nextImport);
+    nextDoubleQuote = data.indexOf(DOUBLE_QUOTE, nextImport);
 
     if (nextSingleQuote > -1 && nextDoubleQuote > -1 && nextSingleQuote < nextDoubleQuote) {
       nextStart = nextSingleQuote;
@@ -94,12 +96,15 @@ function byImport(data, context, callback) {
     } else if (nextDoubleQuote > -1) {
       nextStart = nextDoubleQuote;
       withQuote = DOUBLE_QUOTE;
+    } else {
+      break;
     }
 
     tempData.push(data.substring(cursor, nextStart));
-
     nextEnd = data.indexOf(withQuote, nextStart + 1);
-    if (nextEnd == -1) {
+
+    untilNextQuote = data.substring(nextImport, nextEnd);
+    if (nextEnd == -1 || /^@import\s+(url\(|__ESCAPED)/i.test(untilNextQuote)) {
       cursor = nextStart;
       break;
     }
index 576b4b9..8534acf 100644 (file)
@@ -1674,6 +1674,12 @@ title']{display:block}",
     ],
     'no empty body': '@import url(//fonts.googleapis.com/css?family=Domine:700);body{color:red}body h1{font-family:Domine}'
   }, { processImport: false, advanced: false }),
+  '@import with no url': cssContext({
+    'matching too much': [
+      '@import url(test.css);@font-face{font-family:"icomoon"}',
+      '@import url(test.css);@font-face{font-family:icomoon}'
+    ]
+  }, { processImport: false, root: process.cwd(), relativeTo: process.cwd() }),
   'duplicate selectors with disabled advanced processing': cssContext({
     'of a duplicate selector': [
       'a,a{color:red}',