diff --git a/lib/loader.js b/lib/loader.js index f5508d81..702bb307 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -64,23 +64,28 @@ module.exports = function(content, map) { "[" + JSON.stringify(importItem.export) + "] + \""; } - cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this)).replace(result.urlItemRegExpG, function(item) { - var match = result.urlItemRegExp.exec(item); - var idx = +match[1]; - var urlItem = result.urlItems[idx]; - var url = urlItem.url; - idx = url.indexOf("?#"); - if(idx < 0) idx = url.indexOf("#"); - var urlRequest; - if(idx > 0) { // idx === 0 is catched by isUrlRequest - // in cases like url('webfont.eot?#iefix') - urlRequest = url.substr(0, idx); - return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"" + - url.substr(idx); - } - urlRequest = url; - return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \""; - }.bind(this)); + if(query.import !== false) { + cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this)); + } + if(query.url !== false) { + cssAsString = cssAsString.replace(result.urlItemRegExpG, function(item) { + var match = result.urlItemRegExp.exec(item); + var idx = +match[1]; + var urlItem = result.urlItems[idx]; + var url = urlItem.url; + idx = url.indexOf("?#"); + if(idx < 0) idx = url.indexOf("#"); + var urlRequest; + if(idx > 0) { // idx === 0 is catched by isUrlRequest + // in cases like url('webfont.eot?#iefix') + urlRequest = url.substr(0, idx); + return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"" + + url.substr(idx); + } + urlRequest = url; + return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \""; + }.bind(this)); + } var exportJs = compileExports(result, importItemMatcher.bind(this), camelCaseKeys); diff --git a/lib/processCss.js b/lib/processCss.js index 2e946827..20e25327 100644 --- a/lib/processCss.js +++ b/lib/processCss.js @@ -22,15 +22,18 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) { var urlItems = []; function replaceImportsInString(str) { - var tokens = str.split(/(\S+)/); - tokens = tokens.map(function(token) { - var importIndex = imports["$" + token]; - if(typeof importIndex === "number") { - return "___CSS_LOADER_IMPORT___" + importIndex + "___"; - } - return token; - }); - return tokens.join(""); + if(options.import) { + var tokens = str.split(/(\S+)/); + tokens = tokens.map(function (token) { + var importIndex = imports["$" + token]; + if(typeof importIndex === "number") { + return "___CSS_LOADER_IMPORT___" + importIndex + "___"; + } + return token; + }); + return tokens.join(""); + } + return str; } css.walkAtRules("import", function(rule) { @@ -83,21 +86,25 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) { value.nodes.forEach(function(item) { switch(item.type) { case "item": - var importIndex = imports["$" + item.name]; - if(typeof importIndex === "number") { - item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___"; + if(options.import) { + var importIndex = imports["$" + item.name]; + if(typeof importIndex === "number") { + item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___"; + } } break; case "url": - if(!/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url, options.root)) { - item.stringType = ""; - delete item.innerSpacingBefore; - delete item.innerSpacingAfter; - var url = item.url; - item.url = "___CSS_LOADER_URL___" + urlItems.length + "___"; - urlItems.push({ - url: url - }); + if(options.url) { + if(!/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url, options.root)) { + item.stringType = ""; + delete item.innerSpacingBefore; + delete item.innerSpacingAfter; + var url = item.url; + item.url = "___CSS_LOADER_URL___" + urlItems.length + "___"; + urlItems.push({ + url: url + }); + } } break; } @@ -129,18 +136,22 @@ module.exports = function processCss(inputSource, inputMap, options, callback) { var parserOptions = { root: root, - mode: options.mode + mode: options.mode, + url: query.url !== false, + import: query.import !== false }; var pipeline = postcss([ localByDefault({ mode: options.mode, rewriteUrl: function(global, url) { - if(!loaderUtils.isUrlRequest(url, root)) { - return url; - } - if(global) { - return loaderUtils.urlToRequest(url, root); + if(parserOptions.url){ + if(!loaderUtils.isUrlRequest(url, root)) { + return url; + } + if(global) { + return loaderUtils.urlToRequest(url, root); + } } return url; } diff --git a/test/urlTest.js b/test/urlTest.js index 3e583b94..29a070a7 100644 --- a/test/urlTest.js +++ b/test/urlTest.js @@ -50,4 +50,49 @@ describe("url", function() { test("keyframe background img", "@keyframes anim { background: green url('img.png') xyz }", [ [1, "@keyframes anim { background: green url({./img.png}) xyz }", ""] ]); + + test("background img with url", ".class { background: green url( \"img.png\" ) xyz }", [ + [1, ".class { background: green url( \"img.png\" ) xyz }", ""] + ], "?-url"); + test("background img 2 with url", ".class { background: green url(~img/png) url(aaa) xyz }", [ + [1, ".class { background: green url(~img/png) url(aaa) xyz }", ""] + ], "?-url"); + test("background img 3 with url", ".class { background: green url( 'img.png' ) xyz }", [ + [1, ".class { background: green url( 'img.png' ) xyz }", ""] + ], "?-url"); + test("background img absolute with url", ".class { background: green url(/img.png) xyz }", [ + [1, ".class { background: green url(/img.png) xyz }", ""] + ], "?-url"); + test("background img external with url", + ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", [ + [1, ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", ""] + ], "?-url"); + test("background img external data with url", + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", [ + [1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", ""] + ], "?-url"); + test("data url in filter with url", + ".class { filter: url('data:image/svg+xml;charset=utf-8,#filter'); }", [ + [1, ".class { filter: url('data:image/svg+xml;charset=utf-8,#filter'); }", ""] + ], "?-url"); + test("filter hash with url", + ".highlight { filter: url(#highlight); }", [ + [1, ".highlight { filter: url(#highlight); }", ""] + ], "?-url"); + test("filter hash quotation marks with url", + ".highlight { filter: url('#line-marker'); }", [ + [1, ".highlight { filter: url('#line-marker'); }", ""] + ], "?-url"); + test("font face with url", "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", [ + [1, "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", ""] + ], "?-url"); + test("media query with url", "@media (min-width: 500px) { body { background: url(image.png); } }", [ + [1, "@media (min-width: 500px) { body { background: url(image.png); } }", ""] + ], "?-url"); + test("url in string with url", "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", [ + [1, "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", ""] + ], "?-url"); + test("keyframe background img with url", "@keyframes anim { background: green url('img.png') xyz }", [ + [1, "@keyframes anim { background: green url('img.png') xyz }", ""] + ], "?-url"); });