|
3 | 3 | Author Tobias Koppers @sokra |
4 | 4 | */ |
5 | 5 | var formatCodeFrame = require("babel-code-frame"); |
6 | | -var Tokenizer = require("css-selector-tokenizer"); |
7 | 6 | var postcss = require("postcss"); |
8 | | -var loaderUtils = require("loader-utils"); |
9 | | - |
10 | | -var icssUtils = require('icss-utils'); |
11 | | -var valueParser = require('postcss-value-parser'); |
12 | | - |
13 | | -var parserPlugin = postcss.plugin("css-loader-parser", function(options) { |
14 | | - return function(css) { |
15 | | - var imports = {}; |
16 | | - var exports = {}; |
17 | | - var importItems = []; |
18 | | - var urlItems = []; |
19 | | - |
20 | | - function replaceImportsInString(str) { |
21 | | - if(options.import) { |
22 | | - var tokens = valueParser(str); |
23 | | - tokens.walk(function (node) { |
24 | | - if (node.type !== 'word') { |
25 | | - return; |
26 | | - } |
27 | | - var token = node.value; |
28 | | - var importIndex = imports["$" + token]; |
29 | | - if(typeof importIndex === "number") { |
30 | | - node.value = "___CSS_LOADER_IMPORT___" + importIndex + "___"; |
31 | | - } |
32 | | - }) |
33 | | - return tokens.toString(); |
34 | | - } |
35 | | - return str; |
36 | | - } |
37 | | - |
38 | | - if(options.import) { |
39 | | - css.walkAtRules(/^import$/i, function(rule) { |
40 | | - var values = Tokenizer.parseValues(rule.params); |
41 | | - var url = values.nodes[0].nodes[0]; |
42 | | - if(url && url.type === "url") { |
43 | | - url = url.url; |
44 | | - } else if(url && url.type === "string") { |
45 | | - url = url.value; |
46 | | - } else throw rule.error("Unexpected format " + rule.params); |
47 | | - if (!url.replace(/\s/g, '').length) { |
48 | | - return; |
49 | | - } |
50 | | - values.nodes[0].nodes.shift(); |
51 | | - var mediaQuery = Tokenizer.stringifyValues(values); |
52 | | - |
53 | | - if(loaderUtils.isUrlRequest(url)) { |
54 | | - url = loaderUtils.urlToRequest(url); |
55 | | - } |
56 | | - |
57 | | - importItems.push({ |
58 | | - url: url, |
59 | | - mediaQuery: mediaQuery |
60 | | - }); |
61 | | - rule.remove(); |
62 | | - }); |
63 | | - } |
64 | | - |
65 | | - var icss = icssUtils.extractICSS(css); |
66 | | - exports = icss.icssExports; |
67 | | - Object.keys(icss.icssImports).forEach(function(key) { |
68 | | - var url = loaderUtils.parseString(key); |
69 | | - Object.keys(icss.icssImports[key]).forEach(function(prop) { |
70 | | - imports["$" + prop] = importItems.length; |
71 | | - importItems.push({ |
72 | | - url: url, |
73 | | - export: icss.icssImports[key][prop] |
74 | | - }); |
75 | | - }) |
76 | | - }); |
77 | | - |
78 | | - Object.keys(exports).forEach(function(exportName) { |
79 | | - exports[exportName] = replaceImportsInString(exports[exportName]); |
80 | | - }); |
81 | | - |
82 | | - function processNode(item) { |
83 | | - switch (item.type) { |
84 | | - case "value": |
85 | | - item.nodes.forEach(processNode); |
86 | | - break; |
87 | | - case "nested-item": |
88 | | - item.nodes.forEach(processNode); |
89 | | - break; |
90 | | - case "item": |
91 | | - var importIndex = imports["$" + item.name]; |
92 | | - if (typeof importIndex === "number") { |
93 | | - item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___"; |
94 | | - } |
95 | | - break; |
96 | | - case "url": |
97 | | - if (options.url && item.url.replace(/\s/g, '').length && !/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url)) { |
98 | | - // Strip quotes, they will be re-added if the module needs them |
99 | | - item.stringType = ""; |
100 | | - delete item.innerSpacingBefore; |
101 | | - delete item.innerSpacingAfter; |
102 | | - // For backward-compat after dropping css modules |
103 | | - var url = loaderUtils.urlToRequest(item.url.trim()); |
104 | | - item.url = "___CSS_LOADER_URL___" + urlItems.length + "___"; |
105 | | - urlItems.push({ |
106 | | - url: url |
107 | | - }); |
108 | | - } |
109 | | - break; |
110 | | - } |
111 | | - } |
112 | | - |
113 | | - css.walkDecls(function(decl) { |
114 | | - var values = Tokenizer.parseValues(decl.value); |
115 | | - values.nodes.forEach(function(value) { |
116 | | - value.nodes.forEach(processNode); |
117 | | - }); |
118 | | - decl.value = Tokenizer.stringifyValues(values); |
119 | | - }); |
120 | | - css.walkAtRules(function(atrule) { |
121 | | - if(typeof atrule.params === "string") { |
122 | | - atrule.params = replaceImportsInString(atrule.params); |
123 | | - } |
124 | | - }); |
125 | | - |
126 | | - options.importItems = importItems; |
127 | | - options.urlItems = urlItems; |
128 | | - options.exports = exports; |
129 | | - }; |
130 | | -}); |
| 7 | +var plugin = require("./plugin"); |
131 | 8 |
|
132 | 9 | module.exports = function processCss(inputSource, inputMap, options, callback) { |
133 | | - var query = options.query; |
134 | | - |
135 | | - var parserOptions = { |
136 | | - url: query.url !== false, |
137 | | - import: query.import !== false, |
138 | | - resolve: options.resolve |
139 | | - }; |
140 | | - |
141 | | - var pipeline = postcss([ |
142 | | - parserPlugin(parserOptions) |
143 | | - ]); |
144 | | - |
145 | | - pipeline.process(inputSource, { |
146 | | - // we need a prefix to avoid path rewriting of PostCSS |
147 | | - from: "/css-loader!" + options.from, |
148 | | - to: options.to, |
149 | | - map: options.sourceMap ? { |
150 | | - prev: inputMap, |
151 | | - sourcesContent: true, |
152 | | - inline: false, |
153 | | - annotation: false |
154 | | - } : null |
155 | | - }).then(function(result) { |
156 | | - callback(null, { |
157 | | - source: result.css, |
158 | | - map: result.map && result.map.toJSON(), |
159 | | - exports: parserOptions.exports, |
160 | | - importItems: parserOptions.importItems, |
161 | | - importItemRegExpG: /___CSS_LOADER_IMPORT___([0-9]+)___/g, |
162 | | - importItemRegExp: /___CSS_LOADER_IMPORT___([0-9]+)___/, |
163 | | - urlItems: parserOptions.urlItems, |
164 | | - urlItemRegExpG: /___CSS_LOADER_URL___([0-9]+)___/g, |
165 | | - urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/ |
166 | | - }); |
167 | | - }).catch(function(err) { |
168 | | - if (err.name === 'CssSyntaxError') { |
169 | | - var wrappedError = new CSSLoaderError( |
170 | | - 'Syntax Error', |
171 | | - err.reason, |
172 | | - err.line != null && err.column != null |
173 | | - ? {line: err.line, column: err.column} |
174 | | - : null, |
175 | | - err.input.source |
176 | | - ); |
177 | | - callback(wrappedError); |
178 | | - } else { |
179 | | - callback(err); |
180 | | - } |
181 | | - }); |
| 10 | + var query = options.query; |
| 11 | + var parserOptions = { |
| 12 | + url: query.url !== false, |
| 13 | + import: query.import !== false, |
| 14 | + resolve: options.resolve |
| 15 | + }; |
| 16 | + |
| 17 | + postcss([plugin(parserOptions)]) |
| 18 | + .process(inputSource, { |
| 19 | + // we need a prefix to avoid path rewriting of PostCSS |
| 20 | + from: "/css-loader!" + options.from, |
| 21 | + to: options.to, |
| 22 | + map: options.sourceMap |
| 23 | + ? { |
| 24 | + prev: inputMap, |
| 25 | + sourcesContent: true, |
| 26 | + inline: false, |
| 27 | + annotation: false |
| 28 | + } |
| 29 | + : null |
| 30 | + }) |
| 31 | + .then(function(result) { |
| 32 | + callback(null, { |
| 33 | + source: result.css, |
| 34 | + map: result.map && result.map.toJSON(), |
| 35 | + exports: parserOptions.exports, |
| 36 | + importItems: parserOptions.importItems, |
| 37 | + importItemRegExpG: /___CSS_LOADER_IMPORT___([0-9]+)___/g, |
| 38 | + importItemRegExp: /___CSS_LOADER_IMPORT___([0-9]+)___/, |
| 39 | + urlItems: parserOptions.urlItems, |
| 40 | + urlItemRegExpG: /___CSS_LOADER_URL___([0-9]+)___/g, |
| 41 | + urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/ |
| 42 | + }); |
| 43 | + }) |
| 44 | + .catch(function(err) { |
| 45 | + if (err.name === "CssSyntaxError") { |
| 46 | + var wrappedError = new CSSLoaderError( |
| 47 | + "Syntax Error", |
| 48 | + err.reason, |
| 49 | + err.line != null && err.column != null |
| 50 | + ? { line: err.line, column: err.column } |
| 51 | + : null, |
| 52 | + err.input.source |
| 53 | + ); |
| 54 | + callback(wrappedError); |
| 55 | + } else { |
| 56 | + callback(err); |
| 57 | + } |
| 58 | + }); |
182 | 59 | }; |
183 | 60 |
|
184 | 61 | function formatMessage(message, loc, source) { |
185 | | - var formatted = message; |
186 | | - if (loc) { |
187 | | - formatted = formatted |
188 | | - + ' (' + loc.line + ':' + loc.column + ')'; |
189 | | - } |
190 | | - if (loc && source) { |
191 | | - formatted = formatted |
192 | | - + '\n\n' + formatCodeFrame(source, loc.line, loc.column) + '\n'; |
193 | | - } |
194 | | - return formatted; |
| 62 | + var formatted = message; |
| 63 | + if (loc) { |
| 64 | + formatted = formatted + " (" + loc.line + ":" + loc.column + ")"; |
| 65 | + } |
| 66 | + if (loc && source) { |
| 67 | + formatted = |
| 68 | + formatted + "\n\n" + formatCodeFrame(source, loc.line, loc.column) + "\n"; |
| 69 | + } |
| 70 | + return formatted; |
195 | 71 | } |
196 | 72 |
|
197 | 73 | function CSSLoaderError(name, message, loc, source, error) { |
198 | | - Error.call(this); |
199 | | - Error.captureStackTrace(this, CSSLoaderError); |
200 | | - this.name = name; |
201 | | - this.error = error; |
202 | | - this.message = formatMessage(message, loc, source); |
203 | | - this.hideStack = true; |
| 74 | + Error.call(this); |
| 75 | + Error.captureStackTrace(this, CSSLoaderError); |
| 76 | + this.name = name; |
| 77 | + this.error = error; |
| 78 | + this.message = formatMessage(message, loc, source); |
| 79 | + this.hideStack = true; |
204 | 80 | } |
205 | 81 |
|
206 | 82 | CSSLoaderError.prototype = Object.create(Error.prototype); |
|
0 commit comments