Skip to content

Commit 63fcd33

Browse files
committed
version 0.2: support url(...) require with loader
1 parent b7785fb commit 63fcd33

File tree

5 files changed

+116
-10
lines changed

5 files changed

+116
-10
lines changed

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
test

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,20 @@
44

55
``` javascript
66
var css = require("css!./file.css");
7-
// => returns css code from file.css, resolves imports
7+
// => returns css code from file.css, resolves imports and url(...)
88
```
99

10+
`@import` will be required with this css loader.
11+
12+
`url(...)` will be required with the loader specified in the options.
13+
If `options.css.requireUrl` is a string it will be prefixed to the required url.
14+
If it isn't a string `url(...)` will not be replaced.
15+
`options.css.requireUrl` defaults to `"file/auto!"`.
16+
17+
A alternative to the file-loader is the
18+
[url-loader](https://github.com/sokra/webpack-url-loader) which can use Data Urls.
19+
The use it specify `"url/auto!"`.
20+
1021
Don't forget to polyfill `require` if you want to use it in node.
1122
See `webpack` documentation.
1223

index.js

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,43 @@
33
Author Tobias Koppers @sokra
44
*/
55
var csso = require("csso");
6+
var uriRegExp = /%CSSURL\[%(.*)%\]CSSURL%/g;
67
module.exports = function(content) {
7-
var options = this;
8+
var isRequireUrl = !this || !this.options || !this.options.css ||
9+
typeof this.options.css.requireUrl === "string";
10+
var requireUrl = this && this.options && this.options.css &&
11+
this.options.css.requireUrl ||
12+
"file/auto!";
813
var result = [];
914
var tree = csso.parse(content, "stylesheet");
10-
if(options.minimize)
15+
if(this && this.minimize)
1116
tree = csso.compress(tree);
1217
tree = csso.cleanInfo(tree);
13-
18+
1419
var imports = extractImports(tree);
15-
20+
if(isRequireUrl)
21+
annotateUrls(tree);
22+
1623
imports.forEach(function(imp) {
1724
if(imp.media.length > 0) {
18-
result.push(JSON.stringify("@media " + imp.media.join("") + "{"));
25+
result.push(JSON.stringify("@media(" + imp.media.join("") + "){"));
1926
}
20-
result.push("require(" + JSON.stringify(__filename) + " + \"!\" + " + JSON.stringify(urlToRequire(imp.url)) + ")");
27+
result.push("require(" + JSON.stringify(__filename + "!" + urlToRequire(imp.url)) + ")");
2128
if(imp.media.length > 0) {
2229
result.push(JSON.stringify("}"));
2330
}
2431
});
25-
26-
result.push(JSON.stringify(csso.translate(tree)));
32+
33+
var css = JSON.stringify(csso.translate(tree));
34+
if(isRequireUrl) {
35+
css = css.replace(uriRegExp, function(match) {
36+
match = uriRegExp.exec(match);
37+
var url = JSON.parse("\"" + match[1] + "\"");
38+
return "\"+require(" + JSON.stringify(requireUrl + urlToRequire(url)) + ")+\"";
39+
});
40+
41+
}
42+
result.push(css);
2743
return "module.exports =\n\t" + result.join(" +\n\t") + ";";
2844
}
2945

@@ -71,4 +87,31 @@ function extractImports(tree) {
7187
tree.splice(i, 1);
7288
});
7389
return results;
90+
}
91+
function annotateUrls(tree) {
92+
function iterateChildren() {
93+
for(var i = 1; i < tree.length; i++) {
94+
annotateUrls(tree[i]);
95+
}
96+
}
97+
switch(tree[0]) {
98+
case "stylesheet": return iterateChildren();
99+
case "ruleset": return iterateChildren();
100+
case "block": return iterateChildren();
101+
case "declaration": return iterateChildren();
102+
case "value": return iterateChildren();
103+
case "uri":
104+
for(var i = 1; i < tree.length; i++) {
105+
var item = tree[i];
106+
switch(item[0]) {
107+
case "ident":
108+
case "raw":
109+
item[1] = "%CSSURL[%" + item[1] + "%]CSSURL%";
110+
return;
111+
case "string":
112+
item[1] = "%CSSURL[%" + item[1].substring(1, item[1].length-1) + "%]CSSURL%";
113+
return;
114+
}
115+
}
116+
}
74117
}

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
{
22
"name": "css-loader",
3-
"version": "0.1.2",
3+
"version": "0.2.0",
44
"author": "Tobias Koppers @sokra",
55
"description": "css loader module for webpack",
66
"dependencies": {
77
"csso": "1.2.x"
88
},
9+
"devDependencies": {
10+
"vows": "0.6.2"
11+
},
12+
"scripts": {
13+
"test": "node node_modules/vows/bin/vows"
14+
},
915
"licenses": [
1016
{
1117
"type": "MIT",

test/url_test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
var vows = require("vows");
2+
var assert = require("assert");
3+
var path = require("path");
4+
var cssLoader = require("../index.js");
5+
6+
function test(input, result) {
7+
return {
8+
topic: function() {
9+
var context = {
10+
options: {
11+
}
12+
}
13+
return cssLoader.call(context, input);
14+
},
15+
16+
isCorrect: function(output) {
17+
if(output instanceof Error)
18+
throw output;
19+
assert.equal(output, "module.exports =\n\t" + result.join(" +\n\t") + ";");
20+
}
21+
}
22+
}
23+
24+
vows.describe("url").addBatch({
25+
"simple": test(".class { a: b c d; }",
26+
["\".class { a: b c d; }\""]),
27+
"simple2": test(".class { a: b c d; }\n.two {}",
28+
["\".class { a: b c d; }\\n.two {}\""]),
29+
"import": test("@import url(test.css);\n.class { a: b c d; }",
30+
["require("+JSON.stringify(path.join(__dirname, "..", "index.js")+"!./test.css")+")",
31+
"\"\\n.class { a: b c d; }\""]),
32+
"import with media":
33+
test("@import url(~test/css) screen and print;\n.class { a: b c d; }",
34+
["\"@media(screen and print){\"",
35+
"require("+JSON.stringify(path.join(__dirname, "..", "index.js")+"!test/css")+")",
36+
"\"}\"",
37+
"\"\\n.class { a: b c d; }\""]),
38+
"background img":
39+
test(".class { background: green url( \"img.png\" ) xyz }",
40+
["\".class { background: green url( \"+require(\"file/auto!./img.png\")+\" ) xyz }\""]),
41+
"background img 2":
42+
test(".class { background: green url(~img/png ) xyz }",
43+
["\".class { background: green url(\"+require(\"file/auto!img/png\")+\" ) xyz }\""])
44+
}).export(module);

0 commit comments

Comments
 (0)