diff --git a/README.md b/README.md index 1d9339ca..ecc69612 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,27 @@ module.exports = { }; ``` +### 'Root-relative' urls + +For urls that start with a `/`, the default behavior is to not translate them: +* `url(/image.png)` => `url(/image.png)` + +If a `root` query parameter is set, however, it will be prepended to the url +and then translated: + +With a config like: + +``` javascript + loaders: [ + { test: /\.css/, loader: "style-loader!css-loader?root=." }, + ... + ] +``` + +The result is: + +* `url(/image.png)` => `require("./image.png")` + ## License MIT (http://www.opensource.org/licenses/mit-license.php) diff --git a/index.js b/index.js index a7335876..2ef49c93 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,10 @@ var loaderUtils = require("loader-utils"); module.exports = function(content) { this.cacheable && this.cacheable(); var result = []; + var query = loaderUtils.parseQuery(this.query); + var root = query.root; + if(root !== undefined && root !== false && typeof root !== "string") + throw new Error("Invalid value to query parameter root"); var tree = csso.parse(content, "stylesheet"); if(tree && this && this.minimize) { tree = csso.compress(tree); @@ -38,18 +42,19 @@ module.exports = function(content) { css = css.replace(uriRegExp, function(str) { var match = /^%CSSURL\[%(.*?)%\]CSSURL%$/.exec(str); if(/^data:|^(https?:)?\/\//.test(match[1])) return match[1]; + if((root === undefined || root === false) && /^\//.test(match[1])) return match[1]; var idx = match[1].indexOf("?"); if(idx < 0) idx = match[1].indexOf("#"); if(idx > 0) { // in cases like url('webfont.eot?#iefix') var url = JSON.parse("\"" + match[1].substr(0, idx) + "\""); - return "\"+require(" + JSON.stringify(urlToRequire(url)) + ")+\"" + match[1].substr(idx); + return "\"+require(" + JSON.stringify(urlToRequire(url, root)) + ")+\"" + match[1].substr(idx); } else if(idx === 0) { // only hash return match[1]; } var url = JSON.parse("\"" + match[1] + "\""); - return "\"+require(" + JSON.stringify(urlToRequire(url)) + ")+\""; + return "\"+require(" + JSON.stringify(urlToRequire(url, root)) + ")+\""; }); result.push(css); var cssRequest = loaderUtils.getRemainingRequest(this); @@ -63,9 +68,11 @@ module.exports = function(content) { this.callback(null, stringWithMap.code, stringWithMap.map.toJSON()); } -function urlToRequire(url) { +function urlToRequire(url, root) { if(/^~/.test(url)) return url.substring(1); + else if(root !== undefined && /^\//.test(url)) + return root.replace(/\/$/, '')+'/'+url.replace(/^\//, ''); else return "./"+url; } diff --git a/test/urlTest.js b/test/urlTest.js index 7c77feb5..7c86baad 100644 --- a/test/urlTest.js +++ b/test/urlTest.js @@ -2,13 +2,14 @@ var should = require("should"); var path = require("path"); var cssLoader = require("../index.js"); -function test(name, input, result) { +function test(name, input, result, query) { it(name, function() { var output; cssLoader.call({ loaders: [{request: "loader"}], loaderIndex: 0, resource: "test.css", + query: query, callback: function(err, result) { output = result; } @@ -58,6 +59,10 @@ describe("url", function() { ["\".class { background: green url( \"+require(\"./img.png\")+\" ) xyz }\""]); test("background img 2", ".class { background: green url(~img/png ) url(aaa) xyz }", ["\".class { background: green url(\"+require(\"img/png\")+\" ) url(\"+require(\"./aaa\")+\") xyz }\""]); + test("background img absolute", ".class { background: green url(/img.png) xyz }", + ["\".class { background: green url(/img.png) xyz }\""]); + test("background img absolute with root", ".class { background: green url(/img.png) xyz }", + ["\".class { background: green url(\"+require(\"./img.png\")+\") xyz }\""], "?root=."); test("background img external", ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", ["\".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }\""]);