Fixes #352 - honors `rebase: false` / `--skip-rebase` in imported stylesheets.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Tue, 9 Dec 2014 22:06:27 +0000 (22:06 +0000)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Tue, 9 Dec 2014 22:09:35 +0000 (22:09 +0000)
History.md
lib/clean.js
lib/imports/inliner.js
test/binary-test.js
test/integration-test.js
test/protocol-imports-test.js

index 119afca..8fb2b5d 100644 (file)
@@ -18,6 +18,7 @@
 * Speeds up advanced processing by shortening optimize loop.
 * Fixed issue [#125](https://github.com/GoalSmashers/clean-css/issues/125) - source maps!
 * Fixed issue [#344](https://github.com/GoalSmashers/clean-css/issues/344) - merging background-size into shorthand.
+* Fixed issue [#352](https://github.com/GoalSmashers/clean-css/issues/352) - honors rebasing in imported stylesheets.
 * Fixed issue [#360](https://github.com/GoalSmashers/clean-css/issues/360) - adds 7 extra CSS colors.
 * Fixed issue [#363](https://github.com/GoalSmashers/clean-css/issues/363) - `rem` units overriding `px`.
 * Fixed issue [#395](https://github.com/GoalSmashers/clean-css/issues/395) - unescaped brackets in data URIs.
index 4374f57..dbb02ae 100644 (file)
@@ -65,7 +65,7 @@ CleanCSS.prototype.minify = function(data, callback) {
       function (callback) { return callback(); };
 
     return runner(function () {
-      return new ImportInliner(self.context, options.inliner).process(data, {
+      return new ImportInliner(self.context, options.inliner, options.rebase).process(data, {
         localOnly: !callback,
         root: options.root || process.cwd(),
         relativeTo: options.relativeTo,
index fc1a3cc..ddf84f9 100644 (file)
@@ -34,7 +34,7 @@ function wrap(data, source) {
     '__ESCAPED_SOURCE_END_CLEAN_CSS__';
 }
 
-module.exports = function Inliner(context, options) {
+module.exports = function Inliner(context, options, rebase) {
   var defaultOptions = {
     timeout: 5000,
     request: {}
@@ -60,6 +60,7 @@ module.exports = function Inliner(context, options) {
     var isComment = commentScanner(data);
     var afterContent = contentScanner(data);
 
+    options.rebase = rebase;
     options.relativeTo = options.relativeTo || options.root;
     options._baseRelativeTo = options._baseRelativeTo || options.relativeTo;
     options.visited = options.visited || [];
@@ -263,7 +264,8 @@ module.exports = function Inliner(context, options) {
       });
       res.on('end', function() {
         var importedData = chunks.join('');
-        importedData = UrlRewriter.process(importedData, { toBase: importedUrl });
+        if (options.rebase)
+          importedData = UrlRewriter.process(importedData, { toBase: importedUrl });
         importedData = rebaseMap(wrap(importedData, importedUrl), importedUrl);
 
         if (mediaQuery.length > 0)
@@ -309,13 +311,15 @@ module.exports = function Inliner(context, options) {
 
     options.visited.push(fullPath);
 
-    var importedData = fs.readFileSync(fullPath, 'utf8');
     var importRelativeTo = path.dirname(fullPath);
-    importedData = UrlRewriter.process(importedData, {
-      relative: true,
-      fromBase: importRelativeTo,
-      toBase: options._baseRelativeTo
-    });
+    var importedData = fs.readFileSync(fullPath, 'utf8');
+    if (options.rebase) {
+      importedData = UrlRewriter.process(importedData, {
+        relative: true,
+        fromBase: importRelativeTo,
+        toBase: options._baseRelativeTo
+      });
+    }
     importedData = wrap(importedData, path.resolve(options.relativeTo, fullPath));
 
     if (mediaQuery.length > 0)
index c580cbb..9c3aeb1 100644 (file)
@@ -235,9 +235,9 @@ exports.commandsSuite = vows.describe('binary commands').addBatch({
     absolute: binaryContext('-r ./test/data/129-assets --skip-rebase ./test/data/129-assets/assets/ui.css', {
       'should rebase urls correctly': function(error, stdout) {
         assert.equal(error, null);
-        assert.include(stdout, 'url(../components/bootstrap/images/glyphs.gif)');
-        assert.include(stdout, 'url(../components/jquery-ui/images/prev.gif)');
-        assert.include(stdout, 'url(../components/jquery-ui/images/next.gif)');
+        assert.include(stdout, 'url(../images/glyphs.gif)');
+        assert.include(stdout, 'url(../images/prev.gif)');
+        assert.include(stdout, 'url(../images/next.gif)');
       }
     })
   },
index f565f62..2900936 100644 (file)
@@ -1021,6 +1021,16 @@ path")}',
     target: path.join(process.cwd(), 'test.css'),
     relativeTo: path.join('test', 'data', 'partials-relative')
   }),
+  'urls rewriting - rebase off': cssContext({
+    'keeps urls the same': [
+      '@import url(base.css);',
+      'a{background:url(../partials/extra/down.gif) no-repeat}'
+    ],
+  }, {
+    target: path.join(process.cwd(), 'test.css'),
+    relativeTo: path.join('test', 'data', 'partials-relative'),
+    rebase: false
+  }),
   'fonts': cssContext({
     'keep format quotation': "@font-face{font-family:PublicVintage;src:url(/PublicVintage.otf) format('opentype')}",
     'remove font family quotation': [
index ad25a53..4e951c5 100644 (file)
@@ -215,6 +215,27 @@ vows.describe('protocol imports').addBatch({
       nock.cleanAll();
     }
   },
+  'of an existing file with relative URLs and rebase turned off': {
+    topic: function() {
+      this.reqMocks = nock('http://127.0.0.1')
+        .get('/base.css')
+        .reply(200, '@import url(deeply/nested/urls.css);')
+        .get('/deeply/nested/urls.css')
+        .reply(200, 'a{background:url(../images/test.png)}');
+
+      new CleanCSS({ rebase: false }).minify('@import url(http://127.0.0.1/base.css);', this.callback);
+    },
+    'should not raise errors': function(errors, minified) {
+      assert.isNull(errors);
+    },
+    'should process @import': function(errors, minified) {
+      assert.equal(minified.styles, 'a{background:url(../images/test.png)}');
+    },
+    teardown: function() {
+      assert.equal(this.reqMocks.isDone(), true);
+      nock.cleanAll();
+    }
+  },
   'of a non-resolvable domain': {
     topic: function() {
       new CleanCSS().minify('@import url(http://notdefined.127.0.0.1/custom.css);a{color:red}', this.callback);