Skip to content

Commit 724717e

Browse files
committed
async api
postcss 5 fixes webpack-contrib#95
1 parent 5c5bc39 commit 724717e

File tree

6 files changed

+238
-210
lines changed

6 files changed

+238
-210
lines changed

lib/loader.js

+84-81
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ var getImportPrefix = require("./getImportPrefix");
1010

1111
module.exports = function(content, map) {
1212
if(this.cacheable) this.cacheable();
13+
var callback = this.async();
1314
var query = loaderUtils.parseQuery(this.query);
1415
var root = query.root;
1516
var moduleMode = query.modules || query.module;
@@ -18,102 +19,104 @@ module.exports = function(content, map) {
1819
map = JSON.stringify(map);
1920
}
2021

21-
var result = processCss(content, map, {
22+
processCss(content, map, {
2223
mode: moduleMode ? "local" : "global",
2324
from: loaderUtils.getRemainingRequest(this),
2425
to: loaderUtils.getCurrentRequest(this),
2526
query: query,
2627
minimize: this.minimize,
2728
loaderContext: this
28-
});
29+
}, function(err, result) {
30+
if(err) return callback(err);
2931

30-
var cssAsString = JSON.stringify(result.source);
32+
var cssAsString = JSON.stringify(result.source);
3133

32-
// for importing CSS
33-
var importUrlPrefix = getImportPrefix(this, query);
34+
// for importing CSS
35+
var importUrlPrefix = getImportPrefix(this, query);
3436

35-
var alreadyImported = {};
36-
var importJs = result.importItems.filter(function(imp) {
37-
if(!imp.mediaQuery) {
38-
if(alreadyImported[imp.url])
39-
return false;
40-
alreadyImported[imp.url] = true;
41-
}
42-
return true;
43-
}).map(function(imp) {
44-
if(!loaderUtils.isUrlRequest(imp.url, root)) {
45-
return "exports.push([module.id, " +
46-
JSON.stringify("@import url(" + imp.url + ");") + ", " +
47-
JSON.stringify(imp.mediaQuery) + "]);";
48-
} else {
49-
var importUrl = importUrlPrefix + imp.url;
50-
return "exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + JSON.stringify(imp.mediaQuery) + ");";
37+
var alreadyImported = {};
38+
var importJs = result.importItems.filter(function(imp) {
39+
if(!imp.mediaQuery) {
40+
if(alreadyImported[imp.url])
41+
return false;
42+
alreadyImported[imp.url] = true;
43+
}
44+
return true;
45+
}).map(function(imp) {
46+
if(!loaderUtils.isUrlRequest(imp.url, root)) {
47+
return "exports.push([module.id, " +
48+
JSON.stringify("@import url(" + imp.url + ");") + ", " +
49+
JSON.stringify(imp.mediaQuery) + "]);";
50+
} else {
51+
var importUrl = importUrlPrefix + imp.url;
52+
return "exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + JSON.stringify(imp.mediaQuery) + ");";
53+
}
54+
}, this).join("\n");
55+
56+
function importItemMatcher(item) {
57+
var match = result.importItemRegExp.exec(item);
58+
var idx = +match[1];
59+
var importItem = result.importItems[idx];
60+
var importUrl = importUrlPrefix + importItem.url;
61+
return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ").locals" +
62+
"[" + JSON.stringify(importItem.export) + "] + \"";
5163
}
52-
}, this).join("\n");
5364

54-
function importItemMatcher(item) {
55-
var match = result.importItemRegExp.exec(item);
56-
var idx = +match[1];
57-
var importItem = result.importItems[idx];
58-
var importUrl = importUrlPrefix + importItem.url;
59-
return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ").locals" +
60-
"[" + JSON.stringify(importItem.export) + "] + \"";
61-
}
65+
cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this)).replace(result.urlItemRegExpG, function(item) {
66+
var match = result.urlItemRegExp.exec(item);
67+
var idx = +match[1];
68+
var urlItem = result.urlItems[idx];
69+
var url = urlItem.url;
70+
idx = url.indexOf("?#");
71+
if(idx < 0) idx = url.indexOf("#");
72+
var urlRequest;
73+
if(idx > 0) { // idx === 0 is catched by isUrlRequest
74+
// in cases like url('webfont.eot?#iefix')
75+
urlRequest = url.substr(0, idx);
76+
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"" +
77+
url.substr(idx);
78+
}
79+
urlRequest = url;
80+
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"";
81+
}.bind(this));
6282

63-
cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this)).replace(result.urlItemRegExpG, function(item) {
64-
var match = result.urlItemRegExp.exec(item);
65-
var idx = +match[1];
66-
var urlItem = result.urlItems[idx];
67-
var url = urlItem.url;
68-
idx = url.indexOf("?#");
69-
if(idx < 0) idx = url.indexOf("#");
70-
var urlRequest;
71-
if(idx > 0) { // idx === 0 is catched by isUrlRequest
72-
// in cases like url('webfont.eot?#iefix')
73-
urlRequest = url.substr(0, idx);
74-
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"" +
75-
url.substr(idx);
83+
var exportJs = "";
84+
if(Object.keys(result.exports).length > 0) {
85+
exportJs = Object.keys(result.exports).map(function(key) {
86+
var valueAsString = JSON.stringify(result.exports[key]);
87+
valueAsString = valueAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this));
88+
return "\t" + JSON.stringify(key) + ": " + valueAsString;
89+
}.bind(this)).join(",\n");
90+
exportJs = "exports.locals = {\n" + exportJs + "\n};";
7691
}
77-
urlRequest = url;
78-
return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"";
79-
}.bind(this));
8092

81-
var exportJs = "";
82-
if(Object.keys(result.exports).length > 0) {
83-
exportJs = Object.keys(result.exports).map(function(key) {
84-
var valueAsString = JSON.stringify(result.exports[key]);
85-
valueAsString = valueAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this));
86-
return "\t" + JSON.stringify(key) + ": " + valueAsString;
87-
}.bind(this)).join(",\n");
88-
exportJs = "exports.locals = {\n" + exportJs + "\n};";
89-
}
9093

91-
92-
var moduleJs;
93-
if(query.sourceMap && result.map) {
94-
// add a SourceMap
95-
map = result.map;
96-
if(map.sources) {
97-
map.sources = map.sources.map(function(source) {
98-
var p = path.relative(query.context || this.options.context, source).replace(/\\/g, "/");
99-
if(p.indexOf("../") !== 0)
100-
p = "./" + p;
101-
return "/" + p;
102-
}, this);
103-
map.sourceRoot = "webpack://";
94+
var moduleJs;
95+
if(query.sourceMap && result.map) {
96+
// add a SourceMap
97+
map = result.map;
98+
if(map.sources) {
99+
map.sources = map.sources.map(function(source) {
100+
var p = path.relative(query.context || this.options.context, source).replace(/\\/g, "/");
101+
if(p.indexOf("../") !== 0)
102+
p = "./" + p;
103+
return "/" + p;
104+
}, this);
105+
map.sourceRoot = "webpack://";
106+
}
107+
map = JSON.stringify(map);
108+
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\", " + map + "]);";
109+
} else {
110+
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\"]);";
104111
}
105-
map = JSON.stringify(map);
106-
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\", " + map + "]);";
107-
} else {
108-
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\"]);";
109-
}
110112

111-
// embed runtime
112-
return "exports = module.exports = require(" + loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) + ")();\n" +
113-
"// imports\n" +
114-
importJs + "\n\n" +
115-
"// module\n" +
116-
moduleJs + "\n\n" +
117-
"// exports\n" +
118-
exportJs;
113+
// embed runtime
114+
callback(null, "exports = module.exports = require(" + loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) + ")();\n" +
115+
"// imports\n" +
116+
importJs + "\n\n" +
117+
"// module\n" +
118+
moduleJs + "\n\n" +
119+
"// exports\n" +
120+
exportJs);
121+
}.bind(this));
119122
};

lib/localsLoader.js

+25-22
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,40 @@ var getImportPrefix = require("./getImportPrefix");
99

1010
module.exports = function(content) {
1111
if(this.cacheable) this.cacheable();
12+
var callback = this.async();
1213
var query = loaderUtils.parseQuery(this.query);
1314
var moduleMode = query.modules || query.module;
1415

15-
var result = processCss(content, null, {
16+
processCss(content, null, {
1617
mode: moduleMode ? "local" : "global",
1718
query: query,
1819
minimize: this.minimize,
1920
loaderContext: this
20-
});
21+
}, function(err, result) {
22+
if(err) return callback(err);
2123

22-
// for importing CSS
23-
var importUrlPrefix = getImportPrefix(this, query);
24+
// for importing CSS
25+
var importUrlPrefix = getImportPrefix(this, query);
2426

25-
function importItemMatcher(item) {
26-
var match = result.importItemRegExp.exec(item);
27-
var idx = +match[1];
28-
var importItem = result.importItems[idx];
29-
var importUrl = importUrlPrefix + importItem.url;
30-
return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ")" +
31-
"[" + JSON.stringify(importItem.export) + "] + \"";
32-
}
27+
function importItemMatcher(item) {
28+
var match = result.importItemRegExp.exec(item);
29+
var idx = +match[1];
30+
var importItem = result.importItems[idx];
31+
var importUrl = importUrlPrefix + importItem.url;
32+
return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ")" +
33+
"[" + JSON.stringify(importItem.export) + "] + \"";
34+
}
3335

34-
var exportJs = "";
35-
if(Object.keys(result.exports).length > 0) {
36-
exportJs = Object.keys(result.exports).map(function(key) {
37-
var valueAsString = JSON.stringify(result.exports[key]);
38-
valueAsString = valueAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this));
39-
return "\t" + JSON.stringify(key) + ": " + valueAsString;
40-
}.bind(this)).join(",\n");
41-
exportJs = "module.exports = {\n" + exportJs + "\n};";
42-
}
36+
var exportJs = "";
37+
if(Object.keys(result.exports).length > 0) {
38+
exportJs = Object.keys(result.exports).map(function(key) {
39+
var valueAsString = JSON.stringify(result.exports[key]);
40+
valueAsString = valueAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this));
41+
return "\t" + JSON.stringify(key) + ": " + valueAsString;
42+
}.bind(this)).join(",\n");
43+
exportJs = "module.exports = {\n" + exportJs + "\n};";
44+
}
4345

44-
return exportJs;
46+
callback(null, exportJs);
47+
}.bind(this));
4548
};

lib/processCss.js

+41-19
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,28 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
3131
return tokens.join("");
3232
}
3333

34-
css.eachAtRule("import", function(rule) {
34+
function walkAtRules(a, b) {
35+
if(css.walkAtRules)
36+
css.walkAtRules(a, b);
37+
else
38+
css.eachAtRule(a, b);
39+
}
40+
41+
function walkRules(fn) {
42+
if(css.walkRules)
43+
css.walkRules(fn);
44+
else
45+
css.eachRule(fn);
46+
}
47+
48+
function walkDecls(fn) {
49+
if(css.walkDecls)
50+
css.walkDecls(fn);
51+
else
52+
css.eachDecl(fn);
53+
}
54+
55+
walkAtRules("import", function(rule) {
3556
var values = Tokenizer.parseValues(rule.params);
3657
var url = values.nodes[0].nodes[0];
3758
if(url.type === "url") {
@@ -51,7 +72,7 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
5172
rule.removeSelf();
5273
});
5374

54-
css.eachRule(function(rule) {
75+
walkRules(function(rule) {
5576
if(rule.selector === ":export") {
5677
rule.eachDecl(function(decl) {
5778
exports[decl.prop] = decl.value;
@@ -75,7 +96,7 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
7596
exports[exportName] = replaceImportsInString(exports[exportName]);
7697
});
7798

78-
css.eachDecl(function(decl) {
99+
walkDecls(function(decl) {
79100
var values = Tokenizer.parseValues(decl.value);
80101
values.nodes.forEach(function(value) {
81102
value.nodes.forEach(function(item) {
@@ -103,7 +124,7 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
103124
});
104125
decl.value = Tokenizer.stringifyValues(values);
105126
});
106-
css.eachAtRule(function(atrule) {
127+
walkAtRules(function(atrule) {
107128
if(typeof atrule.params === "string") {
108129
atrule.params = replaceImportsInString(atrule.params);
109130
}
@@ -115,7 +136,7 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
115136
};
116137
});
117138

118-
module.exports = function processCss(inputSource, inputMap, options) {
139+
module.exports = function processCss(inputSource, inputMap, options, callback) {
119140

120141
var query = options.query;
121142
var root = query.root;
@@ -162,7 +183,7 @@ module.exports = function processCss(inputSource, inputMap, options) {
162183
pipeline.use(cssnano(minimizeOptions));
163184
}
164185

165-
var result = pipeline.process(inputSource, {
186+
pipeline.process(inputSource, {
166187
from: options.from,
167188
to: options.to,
168189
map: {
@@ -171,18 +192,19 @@ module.exports = function processCss(inputSource, inputMap, options) {
171192
inline: false,
172193
annotation: false
173194
}
195+
}).then(function(result) {
196+
callback(null, {
197+
source: result.css,
198+
map: result.map && result.map.toJSON(),
199+
exports: parserOptions.exports,
200+
importItems: parserOptions.importItems,
201+
importItemRegExpG: /___CSS_LOADER_IMPORT___([0-9]+)___/g,
202+
importItemRegExp: /___CSS_LOADER_IMPORT___([0-9]+)___/,
203+
urlItems: parserOptions.urlItems,
204+
urlItemRegExpG: /___CSS_LOADER_URL___([0-9]+)___/g,
205+
urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/
206+
});
207+
}).catch(function(err) {
208+
callback(err);
174209
});
175-
176-
177-
return {
178-
source: result.css,
179-
map: result.map && result.map.toJSON(),
180-
exports: parserOptions.exports,
181-
importItems: parserOptions.importItems,
182-
importItemRegExpG: /___CSS_LOADER_IMPORT___([0-9]+)___/g,
183-
importItemRegExp: /___CSS_LOADER_IMPORT___([0-9]+)___/,
184-
urlItems: parserOptions.urlItems,
185-
urlItemRegExpG: /___CSS_LOADER_URL___([0-9]+)___/g,
186-
urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/
187-
};
188210
};

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
"description": "css loader module for webpack",
66
"dependencies": {
77
"css-selector-tokenizer": "^0.5.1",
8-
"cssnano": "^2.6.1",
8+
"cssnano": ">=2.6.1 <4",
99
"loader-utils": "~0.2.2",
10-
"postcss": "^4.1.11",
10+
"postcss": ">=4.1.11 <6",
1111
"postcss-modules-extract-imports": "0.0.5",
1212
"postcss-modules-local-by-default": "0.0.12",
1313
"postcss-modules-scope": "0.0.8",

0 commit comments

Comments
 (0)