Fixes #436 - refactors URI rewriting.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 19 Apr 2015 15:56:42 +0000 (16:56 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 19 Apr 2015 15:56:42 +0000 (16:56 +0100)
Now it's way easier to understand.

History.md
lib/images/rewrite-urls.js [new file with mode: 0644]
lib/images/url-rebase.js
lib/images/url-rewriter.js [deleted file]
lib/imports/inliner.js
lib/utils/source-reader.js

index 745c18b..6adba11 100644 (file)
@@ -1,3 +1,8 @@
+[3.3.0 / 2015-xx-xx](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.0...HEAD)
+==================
+
+* Fixed issue [#436](https://github.com/jakubpawlowicz/clean-css/issues/436) - refactors URI rewriting.
+
 [3.2.0 / 2015-04-19](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.9...v3.2.0)
 ==================
 
diff --git a/lib/images/rewrite-urls.js b/lib/images/rewrite-urls.js
new file mode 100644 (file)
index 0000000..bae44d1
--- /dev/null
@@ -0,0 +1,74 @@
+var path = require('path');
+var url = require('url');
+
+var UrlScanner = require('../utils/url-scanner');
+
+var isWindows = process.platform == 'win32';
+
+function isAbsolute(uri) {
+  return uri[0] == '/';
+}
+
+function isSVGMarker(uri) {
+  return uri[0] == '#';
+}
+
+function isEscaped(uri) {
+  return uri.indexOf('__ESCAPED_URL_CLEAN_CSS__') === 0;
+}
+
+function isRemote(uri) {
+  return uri.indexOf('http://') === 0 || uri.indexOf('https://') === 0;
+}
+
+function isImport(uri) {
+  return uri.lastIndexOf('.css') === uri.length - 4;
+}
+
+function isData(uri) {
+  return uri.indexOf('data:') === 0;
+}
+
+function absolute(uri, options) {
+  return path
+    .resolve(path.join(options.fromBase, uri))
+    .replace(options.toBase, '');
+}
+
+function relative(uri, options) {
+  return path.relative(options.toBase, path.join(options.fromBase, uri));
+}
+
+function normalize(uri) {
+  return isWindows ? uri.replace(/\\/g, '/') : uri;
+}
+
+function rebase(uri, options) {
+  if (isAbsolute(uri) || isSVGMarker(uri) || isEscaped(uri))
+    return uri;
+
+  if (options.rebase === false && !isImport(uri))
+    return uri;
+
+  if (!options.imports && isImport(uri))
+    return uri;
+
+  if (isData(uri))
+    return '\'' + uri + '\'';
+
+  if (isRemote(uri) || isRemote(options.toBase))
+    return url.resolve(options.toBase, uri);
+
+  return options.absolute ?
+    normalize(absolute(uri, options)) :
+    normalize(relative(uri, options));
+}
+
+function rewriteUrls(data, options, context) {
+  return new UrlScanner(data, context).reduce(function (url, tempData) {
+    url = url.replace(/^url\(\s*['"]?|['"]?\s*\)$/g, '');
+    tempData.push('url(' + rebase(url, options) + ')');
+  });
+}
+
+module.exports = rewriteUrls;
index aa8cc0b..193c7e9 100644 (file)
@@ -1,6 +1,6 @@
 var path = require('path');
 
-var UrlRewriter = require('./url-rewriter');
+var rewriteUrls = require('./rewrite-urls');
 
 function UrlRebase(outerContext) {
   this.outerContext = outerContext;
@@ -30,7 +30,7 @@ UrlRebase.prototype.process = function (data) {
   if (!rebaseOpts.fromBase || !rebaseOpts.toBase)
     return data;
 
-  return new UrlRewriter(rebaseOpts).process(data);
+  return rewriteUrls(data, rebaseOpts, this.outerContext);
 };
 
 module.exports = UrlRebase;
diff --git a/lib/images/url-rewriter.js b/lib/images/url-rewriter.js
deleted file mode 100644 (file)
index be4a5eb..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-var path = require('path');
-var url = require('url');
-
-var UrlScanner = require('../utils/url-scanner');
-
-function UrlRewriter(options, context) {
-  this.options = options;
-  this.context = context;
-}
-
-UrlRewriter.prototype.process = function (data) {
-  var self = this;
-
-  return new UrlScanner(data, this.context).reduce(function (url, tempData) {
-    url = url.replace(/^url\(\s*['"]?|['"]?\s*\)$/g, '');
-    tempData.push('url(' + rebase(url, self.options) + ')');
-  });
-};
-
-function rebase(resource, options) {
-  // TODO: this is getting insane now - pending refactor in #436
-  var importUrl = resource.substring(resource.length - 4) == '.css';
-  var dataUri = resource.indexOf('data:') === 0;
-  var specialUrl = resource[0] == '/' ||
-    resource[0] == '#' ||
-    (!options.imports && importUrl) ||
-    dataUri ||
-    /^https?:\/\//.exec(resource) !== null ||
-    /__\w+__/.exec(resource) !== null;
-  var rebased;
-
-  if (false === options.urls) {
-    if (options.imports && importUrl)
-      specialUrl = false;
-    else
-      specialUrl = true;
-  }
-
-  if (specialUrl)
-    return dataUri ? '\'' + resource + '\'' : resource;
-
-  if (/https?:\/\//.test(options.toBase))
-    return url.resolve(options.toBase, resource);
-
-  if (options.absolute) {
-    rebased = path
-      .resolve(path.join(options.fromBase, resource))
-      .replace(options.toBase, '');
-  } else {
-    rebased = path.relative(options.toBase, path.join(options.fromBase, resource));
-  }
-
-  return process.platform == 'win32' ?
-    rebased.replace(/\\/g, '/') :
-    rebased;
-}
-
-module.exports = UrlRewriter;
index 553a847..8f774b9 100644 (file)
@@ -4,7 +4,7 @@ var http = require('http');
 var https = require('https');
 var url = require('url');
 
-var UrlRewriter = require('../images/url-rewriter');
+var rewriteUrls = require('../images/rewrite-urls');
 var Splitter = require('../utils/splitter.js');
 var override = require('../utils/object.js').override;
 
@@ -263,7 +263,7 @@ function inlineRemoteResource(importedFile, mediaQuery, context) {
     res.on('end', function() {
       var importedData = chunks.join('');
       if (context.rebase)
-        importedData = new UrlRewriter({ toBase: importedUrl }, context).process(importedData);
+        importedData = rewriteUrls(importedData, { toBase: importedUrl }, context);
       context.sourceReader.trackSource(importedUrl, importedData);
       importedData = context.sourceTracker.store(importedUrl, importedData);
       importedData = rebaseMap(importedData, importedUrl);
@@ -314,12 +314,12 @@ function inlineLocalResource(importedFile, mediaQuery, context) {
   var importRelativeTo = path.dirname(fullPath);
   var importedData = fs.readFileSync(fullPath, 'utf8');
   if (context.rebase) {
-    var rewriter = new UrlRewriter({
+    var rewriteOptions = {
       relative: true,
       fromBase: importRelativeTo,
       toBase: context.baseRelativeTo
-    }, context);
-    importedData = rewriter.process(importedData);
+    };
+    importedData = rewriteUrls(importedData, rewriteOptions, context);
   }
 
   var relativePath = path.relative(context.root, fullPath);
index 9393157..89a2406 100644 (file)
@@ -1,5 +1,5 @@
 var path = require('path');
-var UrlRewriter = require('../images/url-rewriter');
+var rewriteUrls = require('../images/rewrite-urls');
 
 var REMOTE_RESOURCE = /^(https?:)?\/\//;
 
@@ -68,15 +68,15 @@ function fromHash(self) {
     var absoluteSource = isRemote ? source : path.resolve(source);
     var absoluteSourcePath = path.dirname(absoluteSource);
 
-    var rewriter = new UrlRewriter({
+    var rewriteOptions = {
       absolute: self.outerContext.options.explicitRoot,
       relative: !self.outerContext.options.explicitRoot,
       imports: true,
-      urls: self.outerContext.options.rebase,
+      rebase: self.outerContext.options.rebase,
       fromBase: absoluteSourcePath,
       toBase: isRemote ? absoluteSourcePath : toBase
-    }, self.outerContext);
-    styles = rewriter.process(styles);
+    };
+    styles = rewriteUrls(styles, rewriteOptions, self.outerContext);
 
     self.trackSource(source, styles);