Skip to content

Commit 253e3a9

Browse files
Ben SolumBen Solum
authored andcommitted
Merge branch 'master' of https://github.com/webpack/css-loader
2 parents c096484 + 7d2abba commit 253e3a9

File tree

6 files changed

+151
-74
lines changed

6 files changed

+151
-74
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,12 @@ You can also disable or enforce minification with the `minimize` query parameter
227227

228228
`require("css-loader?-minimize!./file.css")` (disabled)
229229

230+
### Disable behavior
231+
232+
`css-loader?-url` disables `url(...)` handling.
233+
234+
`css-loader?-import` disables `@import` handling.
235+
230236
## License
231237

232238
MIT (http://www.opensource.org/licenses/mit-license.php)

lib/loader.js

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,26 @@ module.exports = function(content, map) {
6464
"[" + JSON.stringify(importItem.export) + "] + \"";
6565
}
6666

67-
cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this)).replace(result.urlItemRegExpG, function(item) {
68-
var match = result.urlItemRegExp.exec(item);
69-
var idx = +match[1];
70-
var urlItem = result.urlItems[idx];
71-
var url = urlItem.url;
72-
idx = url.indexOf("?#");
73-
if(idx < 0) idx = url.indexOf("#");
74-
var urlRequest;
75-
if(idx > 0) { // idx === 0 is catched by isUrlRequest
76-
// in cases like url('webfont.eot?#iefix')
77-
urlRequest = url.substr(0, idx);
78-
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"" +
79-
url.substr(idx);
80-
}
81-
urlRequest = url;
82-
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"";
83-
}.bind(this));
67+
cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this));
68+
if(query.url !== false) {
69+
cssAsString = cssAsString.replace(result.urlItemRegExpG, function(item) {
70+
var match = result.urlItemRegExp.exec(item);
71+
var idx = +match[1];
72+
var urlItem = result.urlItems[idx];
73+
var url = urlItem.url;
74+
idx = url.indexOf("?#");
75+
if(idx < 0) idx = url.indexOf("#");
76+
var urlRequest;
77+
if(idx > 0) { // idx === 0 is catched by isUrlRequest
78+
// in cases like url('webfont.eot?#iefix')
79+
urlRequest = url.substr(0, idx);
80+
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"" +
81+
url.substr(idx);
82+
}
83+
urlRequest = url;
84+
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"";
85+
}.bind(this));
86+
}
8487

8588

8689
var exportJs = compileExports(result, importItemMatcher.bind(this), camelCaseKeys);

lib/processCss.js

Lines changed: 72 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,41 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
2222
var urlItems = [];
2323

2424
function replaceImportsInString(str) {
25-
var tokens = str.split(/(\S+)/);
26-
tokens = tokens.map(function(token) {
27-
var importIndex = imports["$" + token];
28-
if(typeof importIndex === "number") {
29-
return "___CSS_LOADER_IMPORT___" + importIndex + "___";
30-
}
31-
return token;
32-
});
33-
return tokens.join("");
25+
if(options.import) {
26+
var tokens = str.split(/(\S+)/);
27+
tokens = tokens.map(function (token) {
28+
var importIndex = imports["$" + token];
29+
if(typeof importIndex === "number") {
30+
return "___CSS_LOADER_IMPORT___" + importIndex + "___";
31+
}
32+
return token;
33+
});
34+
return tokens.join("");
35+
}
36+
return str;
3437
}
3538

36-
css.walkAtRules("import", function(rule) {
37-
var values = Tokenizer.parseValues(rule.params);
38-
var url = values.nodes[0].nodes[0];
39-
if(url.type === "url") {
40-
url = url.url;
41-
} else if(url.type === "string") {
42-
url = url.value;
43-
} else throw rule.error("Unexpected format" + rule.params);
44-
values.nodes[0].nodes.shift();
45-
var mediaQuery = Tokenizer.stringifyValues(values);
46-
if(loaderUtils.isUrlRequest(url, options.root) && options.mode === "global") {
47-
url = loaderUtils.urlToRequest(url, options.root);
48-
}
49-
importItems.push({
50-
url: url,
51-
mediaQuery: mediaQuery
39+
if(options.import) {
40+
css.walkAtRules("import", function(rule) {
41+
var values = Tokenizer.parseValues(rule.params);
42+
var url = values.nodes[0].nodes[0];
43+
if(url.type === "url") {
44+
url = url.url;
45+
} else if(url.type === "string") {
46+
url = url.value;
47+
} else throw rule.error("Unexpected format" + rule.params);
48+
values.nodes[0].nodes.shift();
49+
var mediaQuery = Tokenizer.stringifyValues(values);
50+
if(loaderUtils.isUrlRequest(url, options.root) && options.mode === "global") {
51+
url = loaderUtils.urlToRequest(url, options.root);
52+
}
53+
importItems.push({
54+
url: url,
55+
mediaQuery: mediaQuery
56+
});
57+
rule.remove();
5258
});
53-
rule.remove();
54-
});
59+
}
5560

5661
css.walkRules(function(rule) {
5762
if(rule.selector === ":export") {
@@ -77,31 +82,39 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
7782
exports[exportName] = replaceImportsInString(exports[exportName]);
7883
});
7984

85+
function processNode(item) {
86+
switch (item.type) {
87+
case "value":
88+
item.nodes.forEach(processNode);
89+
break;
90+
case "nested-item":
91+
item.nodes.forEach(processNode);
92+
break;
93+
case "item":
94+
var importIndex = imports["$" + item.name];
95+
if (typeof importIndex === "number") {
96+
item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___";
97+
}
98+
break;
99+
case "url":
100+
if (options.url && !/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url, options.root)) {
101+
item.stringType = "";
102+
delete item.innerSpacingBefore;
103+
delete item.innerSpacingAfter;
104+
var url = item.url;
105+
item.url = "___CSS_LOADER_URL___" + urlItems.length + "___";
106+
urlItems.push({
107+
url: url
108+
});
109+
}
110+
break;
111+
}
112+
}
113+
80114
css.walkDecls(function(decl) {
81115
var values = Tokenizer.parseValues(decl.value);
82116
values.nodes.forEach(function(value) {
83-
value.nodes.forEach(function(item) {
84-
switch(item.type) {
85-
case "item":
86-
var importIndex = imports["$" + item.name];
87-
if(typeof importIndex === "number") {
88-
item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___";
89-
}
90-
break;
91-
case "url":
92-
if(!/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url, options.root)) {
93-
item.stringType = "";
94-
delete item.innerSpacingBefore;
95-
delete item.innerSpacingAfter;
96-
var url = item.url;
97-
item.url = "___CSS_LOADER_URL___" + urlItems.length + "___";
98-
urlItems.push({
99-
url: url
100-
});
101-
}
102-
break;
103-
}
104-
});
117+
value.nodes.forEach(processNode);
105118
});
106119
decl.value = Tokenizer.stringifyValues(values);
107120
});
@@ -129,18 +142,22 @@ module.exports = function processCss(inputSource, inputMap, options, callback) {
129142

130143
var parserOptions = {
131144
root: root,
132-
mode: options.mode
145+
mode: options.mode,
146+
url: query.url !== false,
147+
import: query.import !== false
133148
};
134149

135150
var pipeline = postcss([
136151
localByDefault({
137152
mode: options.mode,
138153
rewriteUrl: function(global, url) {
139-
if(!loaderUtils.isUrlRequest(url, root)) {
140-
return url;
141-
}
142-
if(global) {
143-
return loaderUtils.urlToRequest(url, root);
154+
if(parserOptions.url){
155+
if(!loaderUtils.isUrlRequest(url, root)) {
156+
return url;
157+
}
158+
if(global) {
159+
return loaderUtils.urlToRequest(url, root);
160+
}
144161
}
145162
return url;
146163
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "css-loader",
3-
"version": "0.23.0",
3+
"version": "0.23.1",
44
"author": "Tobias Koppers @sokra",
55
"description": "css loader module for webpack",
66
"dependencies": {
@@ -11,7 +11,7 @@
1111
"lodash.camelcase": "^3.0.1",
1212
"postcss": "^5.0.6",
1313
"postcss-modules-extract-imports": "^1.0.0",
14-
"postcss-modules-local-by-default": "^1.0.0",
14+
"postcss-modules-local-by-default": "^1.0.1",
1515
"postcss-modules-scope": "^1.0.0",
1616
"postcss-modules-values": "^1.1.0",
1717
"source-list-map": "^0.1.4"

test/importTest.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ describe("import", function() {
3636
[1, "@import url(//example.com/style.css);", ""],
3737
[1, "", ""]
3838
]);
39+
test("import disabled", "@import url(test.css);\n.class { a: b c d; }", [
40+
[1, "@import url(test.css);\n.class { a: b c d; }", ""]
41+
], "?-import");
3942
});

test/urlTest.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,52 @@ describe("url", function() {
5050
test("keyframe background img", "@keyframes anim { background: green url('img.png') xyz }", [
5151
[1, "@keyframes anim { background: green url({./img.png}) xyz }", ""]
5252
]);
53+
test("-webkit-image-set", ".a { background-image: -webkit-image-set(url('url1x.png') 1x, url('url2x.png') 2x) }", [
54+
[1, ".a { background-image: -webkit-image-set(url({./url1x.png}) 1x, url({./url2x.png}) 2x) }", ""]
55+
]);
56+
57+
test("background img with url", ".class { background: green url( \"img.png\" ) xyz }", [
58+
[1, ".class { background: green url( \"img.png\" ) xyz }", ""]
59+
], "?-url");
60+
test("background img 2 with url", ".class { background: green url(~img/png) url(aaa) xyz }", [
61+
[1, ".class { background: green url(~img/png) url(aaa) xyz }", ""]
62+
], "?-url");
63+
test("background img 3 with url", ".class { background: green url( 'img.png' ) xyz }", [
64+
[1, ".class { background: green url( 'img.png' ) xyz }", ""]
65+
], "?-url");
66+
test("background img absolute with url", ".class { background: green url(/img.png) xyz }", [
67+
[1, ".class { background: green url(/img.png) xyz }", ""]
68+
], "?-url");
69+
test("background img external with url",
70+
".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", [
71+
[1, ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", ""]
72+
], "?-url");
73+
test("background img external data with url",
74+
".class { background-image: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 42 26' fill='%23007aff'><rect width='4' height='4'/><rect x='8' y='1' width='34' height='2'/><rect y='11' width='4' height='4'/><rect x='8' y='12' width='34' height='2'/><rect y='22' width='4' height='4'/><rect x='8' y='23' width='34' height='2'/></svg>\") }", [
75+
[1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 42 26' fill='%23007aff'><rect width='4' height='4'/><rect x='8' y='1' width='34' height='2'/><rect y='11' width='4' height='4'/><rect x='8' y='12' width='34' height='2'/><rect y='22' width='4' height='4'/><rect x='8' y='23' width='34' height='2'/></svg>\") }", ""]
76+
], "?-url");
77+
test("data url in filter with url",
78+
".class { filter: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\"><filter id=\"filter\"><feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"0\" /><feOffset dx=\"1\" dy=\"2\" result=\"offsetblur\" /><feFlood flood-color=\"rgba(255,255,255,1)\" /><feComposite in2=\"offsetblur\" operator=\"in\" /><feMerge><feMergeNode /><feMergeNode in=\"SourceGraphic\" /></feMerge></filter></svg>#filter'); }", [
79+
[1, ".class { filter: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\"><filter id=\"filter\"><feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"0\" /><feOffset dx=\"1\" dy=\"2\" result=\"offsetblur\" /><feFlood flood-color=\"rgba(255,255,255,1)\" /><feComposite in2=\"offsetblur\" operator=\"in\" /><feMerge><feMergeNode /><feMergeNode in=\"SourceGraphic\" /></feMerge></filter></svg>#filter'); }", ""]
80+
], "?-url");
81+
test("filter hash with url",
82+
".highlight { filter: url(#highlight); }", [
83+
[1, ".highlight { filter: url(#highlight); }", ""]
84+
], "?-url");
85+
test("filter hash quotation marks with url",
86+
".highlight { filter: url('#line-marker'); }", [
87+
[1, ".highlight { filter: url('#line-marker'); }", ""]
88+
], "?-url");
89+
test("font face with url", "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", [
90+
[1, "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", ""]
91+
], "?-url");
92+
test("media query with url", "@media (min-width: 500px) { body { background: url(image.png); } }", [
93+
[1, "@media (min-width: 500px) { body { background: url(image.png); } }", ""]
94+
], "?-url");
95+
test("url in string with url", "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", [
96+
[1, "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", ""]
97+
], "?-url");
98+
test("keyframe background img with url", "@keyframes anim { background: green url('img.png') xyz }", [
99+
[1, "@keyframes anim { background: green url('img.png') xyz }", ""]
100+
], "?-url");
53101
});

0 commit comments

Comments
 (0)