Skip to content

Commit d8ff7a7

Browse files
refactor: merge code from processCss with loader code
1 parent b130031 commit d8ff7a7

File tree

3 files changed

+245
-188
lines changed

3 files changed

+245
-188
lines changed

.eslintrc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ rules:
3838
- error
3939
- never
4040
consistent-return: 'off'
41-
consistent-this: error
41+
consistent-this: 'off'
4242
curly: 'off'
4343
default-case: 'off'
4444
dot-location: 'off'

lib/loader.js

+244-128
Original file line numberDiff line numberDiff line change
@@ -3,136 +3,252 @@
33
Author Tobias Koppers @sokra
44
*/
55
var loaderUtils = require("loader-utils");
6-
var processCss = require("./processCss");
6+
var postcss = require("postcss");
7+
var plugin = require("./plugin");
78
var getImportPrefix = require("./getImportPrefix");
89
var compileExports = require("./compile-exports");
9-
10+
var CssLoaderError = require("./CssLoaderError");
1011

1112
module.exports = function(content, map) {
12-
var callback = this.async();
13-
var query = loaderUtils.getOptions(this) || {};
14-
var camelCaseKeys = query.camelCase;
15-
var sourceMap = query.sourceMap || false;
16-
17-
if(sourceMap) {
18-
if (map) {
19-
if (typeof map === "string") {
20-
map = JSON.stringify(map);
21-
}
22-
23-
if (map.sources) {
24-
map.sources = map.sources.map(function (source) {
25-
return source.replace(/\\/g, '/');
26-
});
27-
map.sourceRoot = '';
28-
}
29-
}
30-
} else {
31-
// Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it
32-
map = null;
33-
}
34-
35-
processCss(content, map, {
36-
from: loaderUtils.getRemainingRequest(this).split("!").pop(),
37-
to: loaderUtils.getCurrentRequest(this).split("!").pop(),
38-
query: query,
39-
loaderContext: this,
40-
sourceMap: sourceMap
41-
}, function(err, result) {
42-
if(err) return callback(err);
43-
44-
var cssAsString = JSON.stringify(result.source);
45-
46-
// for importing CSS
47-
var importUrlPrefix = getImportPrefix(this, query);
48-
49-
var alreadyImported = {};
50-
var importJs = result.importItems.filter(function(imp) {
51-
if(!imp.mediaQuery) {
52-
if(alreadyImported[imp.url])
53-
return false;
54-
alreadyImported[imp.url] = true;
55-
}
56-
return true;
57-
}).map(function(imp) {
58-
if(!loaderUtils.isUrlRequest(imp.url)) {
59-
return "exports.push([module.id, " +
60-
JSON.stringify("@import url(" + imp.url + ");") + ", " +
61-
JSON.stringify(imp.mediaQuery) + "]);";
62-
} else {
63-
var importUrl = importUrlPrefix + imp.url;
64-
return "exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + JSON.stringify(imp.mediaQuery) + ");";
65-
}
66-
}, this).join("\n");
67-
68-
function importItemMatcher(item) {
69-
var match = result.importItemRegExp.exec(item);
70-
var idx = +match[1];
71-
var importItem = result.importItems[idx];
72-
var importUrl = importUrlPrefix + importItem.url;
73-
return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ").locals" +
74-
"[" + JSON.stringify(importItem.export) + "] + \"";
75-
}
76-
77-
cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this));
78-
79-
// helper for ensuring valid CSS strings from requires
80-
var urlEscapeHelper = "";
81-
82-
if(query.url !== false && result.urlItems.length > 0) {
83-
urlEscapeHelper = "var escape = require(" + loaderUtils.stringifyRequest(this, require.resolve("./url/escape.js")) + ");\n";
84-
85-
cssAsString = cssAsString.replace(result.urlItemRegExpG, function(item) {
86-
var match = result.urlItemRegExp.exec(item);
87-
var idx = +match[1];
88-
var urlItem = result.urlItems[idx];
89-
var url = urlItem.url;
90-
idx = url.indexOf("?#");
91-
if(idx < 0) idx = url.indexOf("#");
92-
var urlRequest;
93-
if(idx > 0) { // idx === 0 is catched by isUrlRequest
94-
// in cases like url('webfont.eot?#iefix')
95-
urlRequest = url.substr(0, idx);
96-
return "\" + escape(require(" + loaderUtils.stringifyRequest(this, urlRequest) + ")) + \"" +
97-
url.substr(idx);
98-
}
99-
urlRequest = url;
100-
return "\" + escape(require(" + loaderUtils.stringifyRequest(this, urlRequest) + ")) + \"";
101-
}.bind(this));
102-
}
103-
104-
var exportJs = compileExports(result, importItemMatcher.bind(this), camelCaseKeys);
105-
if (exportJs) {
106-
exportJs = "exports.locals = " + exportJs + ";";
107-
}
108-
109-
var moduleJs;
110-
if(sourceMap && result.map) {
111-
// add a SourceMap
112-
map = result.map;
113-
if(map.sources) {
114-
map.sources = map.sources.map(function(source) {
115-
return source.split("!").pop().replace(/\\/g, '/');
116-
}, this);
117-
map.sourceRoot = "";
118-
}
119-
map.file = map.file.split("!").pop().replace(/\\/g, '/');
120-
map = JSON.stringify(map);
121-
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\", " + map + "]);";
122-
} else {
123-
moduleJs = "exports.push([module.id, " + cssAsString + ", \"\"]);";
124-
}
125-
126-
// embed runtime
127-
callback(null, urlEscapeHelper +
128-
"exports = module.exports = require(" +
129-
loaderUtils.stringifyRequest(this, require.resolve("./runtime.js")) +
130-
")(" + sourceMap + ");\n" +
131-
"// imports\n" +
132-
importJs + "\n\n" +
133-
"// module\n" +
134-
moduleJs + "\n\n" +
135-
"// exports\n" +
136-
exportJs);
137-
}.bind(this));
13+
var callback = this.async();
14+
var query = loaderUtils.getOptions(this) || {};
15+
var camelCaseKeys = query.camelCase;
16+
var sourceMap = query.sourceMap || false;
17+
var loaderContext = this;
18+
19+
if (sourceMap) {
20+
if (map) {
21+
if (typeof map === "string") {
22+
map = JSON.stringify(map);
23+
}
24+
25+
if (map.sources) {
26+
map.sources = map.sources.map(function(source) {
27+
return source.replace(/\\/g, "/");
28+
});
29+
map.sourceRoot = "";
30+
}
31+
}
32+
} else {
33+
// Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it
34+
map = null;
35+
}
36+
37+
var parserOptions = {
38+
url: query.url !== false,
39+
import: query.import !== false,
40+
resolve: loaderContext.resolve
41+
};
42+
43+
postcss([plugin(parserOptions)])
44+
.process(content, {
45+
// we need a prefix to avoid path rewriting of PostCSS
46+
from:
47+
"/css-loader!" +
48+
loaderUtils
49+
.getRemainingRequest(loaderContext)
50+
.split("!")
51+
.pop(),
52+
to: loaderUtils
53+
.getCurrentRequest(loaderContext)
54+
.split("!")
55+
.pop(),
56+
map: sourceMap
57+
? {
58+
prev: map,
59+
sourcesContent: true,
60+
inline: false,
61+
annotation: false
62+
}
63+
: null
64+
})
65+
.then(function(result) {
66+
var cssAsString = JSON.stringify(result.css);
67+
// for importing CSS
68+
var importUrlPrefix = getImportPrefix(loaderContext, query);
69+
var alreadyImported = {};
70+
var importItems = parserOptions.importItems;
71+
var importJs = importItems
72+
.filter(function(imp) {
73+
if (!imp.mediaQuery) {
74+
if (alreadyImported[imp.url]) {
75+
return false;
76+
}
77+
78+
alreadyImported[imp.url] = true;
79+
}
80+
81+
return true;
82+
})
83+
.map(function(imp) {
84+
if (!loaderUtils.isUrlRequest(imp.url)) {
85+
return (
86+
"exports.push([module.id, " +
87+
JSON.stringify("@import url(" + imp.url + ");") +
88+
", " +
89+
JSON.stringify(imp.mediaQuery) +
90+
"]);"
91+
);
92+
} else {
93+
var importUrl = importUrlPrefix + imp.url;
94+
95+
return (
96+
"exports.i(require(" +
97+
loaderUtils.stringifyRequest(this, importUrl) +
98+
"), " +
99+
JSON.stringify(imp.mediaQuery) +
100+
");"
101+
);
102+
}
103+
}, loaderContext)
104+
.join("\n");
105+
106+
function importItemMatcher(item) {
107+
var match = /___CSS_LOADER_IMPORT___([0-9]+)___/.exec(item);
108+
var idx = +match[1];
109+
var importItem = parserOptions.importItems[idx];
110+
var importUrl = importUrlPrefix + importItem.url;
111+
112+
return (
113+
'" + require(' +
114+
loaderUtils.stringifyRequest(this, importUrl) +
115+
").locals" +
116+
"[" +
117+
JSON.stringify(importItem.export) +
118+
'] + "'
119+
);
120+
}
121+
122+
cssAsString = cssAsString.replace(
123+
/___CSS_LOADER_IMPORT___([0-9]+)___/g,
124+
importItemMatcher
125+
);
126+
127+
// helper for ensuring valid CSS strings from requires
128+
var urlEscapeHelper = "";
129+
var urlItems = parserOptions.urlItems;
130+
131+
if (query.url !== false && urlItems.length > 0) {
132+
urlEscapeHelper =
133+
"var escape = require(" +
134+
loaderUtils.stringifyRequest(
135+
loaderContext,
136+
require.resolve("./url/escape.js")
137+
) +
138+
");\n";
139+
140+
cssAsString = cssAsString.replace(
141+
/___CSS_LOADER_URL___([0-9]+)___/g,
142+
function(item) {
143+
var match = /___CSS_LOADER_URL___([0-9]+)___/.exec(item);
144+
var idx = +match[1];
145+
var urlItem = urlItems[idx];
146+
var url = urlItem.url;
147+
148+
idx = url.indexOf("?#");
149+
150+
if (idx < 0) {
151+
idx = url.indexOf("#");
152+
}
153+
154+
var urlRequest;
155+
156+
if (idx > 0) {
157+
// idx === 0 is catched by isUrlRequest
158+
// in cases like url('webfont.eot?#iefix')
159+
urlRequest = url.substr(0, idx);
160+
161+
return (
162+
'" + escape(require(' +
163+
loaderUtils.stringifyRequest(loaderContext, urlRequest) +
164+
')) + "' +
165+
url.substr(idx)
166+
);
167+
}
168+
169+
urlRequest = url;
170+
171+
return (
172+
'" + escape(require(' +
173+
loaderUtils.stringifyRequest(loaderContext, urlRequest) +
174+
')) + "'
175+
);
176+
}
177+
);
178+
}
179+
180+
var exportJs = compileExports(
181+
parserOptions,
182+
importItemMatcher,
183+
camelCaseKeys
184+
);
185+
186+
if (exportJs) {
187+
exportJs = "exports.locals = " + exportJs + ";";
188+
}
189+
190+
var moduleJs;
191+
192+
if (sourceMap && result.map) {
193+
// add a SourceMap
194+
map = result.map.toJSON();
195+
196+
if (map.sources) {
197+
map.sources = map.sources.map(function(source) {
198+
return source
199+
.split("!")
200+
.pop()
201+
.replace(/\\/g, "/");
202+
}, loaderContext);
203+
map.sourceRoot = "";
204+
}
205+
206+
map.file = map.file
207+
.split("!")
208+
.pop()
209+
.replace(/\\/g, "/");
210+
map = JSON.stringify(map);
211+
212+
moduleJs =
213+
"exports.push([module.id, " + cssAsString + ', "", ' + map + "]);";
214+
} else {
215+
moduleJs = "exports.push([module.id, " + cssAsString + ', ""]);';
216+
}
217+
218+
// embed runtime
219+
callback(
220+
null,
221+
urlEscapeHelper +
222+
"exports = module.exports = require(" +
223+
loaderUtils.stringifyRequest(
224+
loaderContext,
225+
require.resolve("./runtime.js")
226+
) +
227+
")(" +
228+
sourceMap +
229+
");\n" +
230+
"// imports\n" +
231+
importJs +
232+
"\n\n" +
233+
"// module\n" +
234+
moduleJs +
235+
"\n\n" +
236+
"// exports\n" +
237+
exportJs
238+
);
239+
})
240+
.catch(function(error) {
241+
callback(
242+
error.name === "CssSyntaxError"
243+
? new CssLoaderError(
244+
"Syntax Error",
245+
error.reason,
246+
error.line != null && error.column != null
247+
? { line: error.line, column: error.column }
248+
: null,
249+
error.input.source
250+
)
251+
: error
252+
);
253+
});
138254
};

0 commit comments

Comments
 (0)