1 | "use strict";
|
2 |
|
3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4 |
|
5 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
6 |
|
7 | var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
8 |
|
9 | var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray"));
|
10 |
|
11 | const Asset = require('../Asset');
|
12 |
|
13 | const postcss = require('postcss');
|
14 |
|
15 | const valueParser = require('postcss-value-parser');
|
16 |
|
17 | const postcssTransform = require('../transforms/postcss');
|
18 |
|
19 | const CssSyntaxError = require('postcss/lib/css-syntax-error');
|
20 |
|
21 | const SourceMap = require('../SourceMap');
|
22 |
|
23 | const loadSourceMap = require('../utils/loadSourceMap');
|
24 |
|
25 | const path = require('path');
|
26 |
|
27 | const urlJoin = require('../utils/urlJoin');
|
28 |
|
29 | const isURL = require('../utils/is-url');
|
30 |
|
31 | const URL_RE = /url\s*\("?(?![a-z]+:)/;
|
32 | const IMPORT_RE = /@import/;
|
33 | const COMPOSES_RE = /composes:.+from\s*("|').*("|')\s*;?/;
|
34 | const FROM_IMPORT_RE = /.+from\s*(?:"|')(.*)(?:"|')\s*;?/;
|
35 | const PROTOCOL_RE = /^[a-z]+:/;
|
36 |
|
37 | class CSSAsset extends Asset {
|
38 | constructor(name, options) {
|
39 | super(name, options);
|
40 | this.type = 'css';
|
41 | this.previousSourceMap = this.options.rendition ? this.options.rendition.map : null;
|
42 | }
|
43 |
|
44 | mightHaveDependencies() {
|
45 | return !/\.css$/.test(this.name) || IMPORT_RE.test(this.contents) || COMPOSES_RE.test(this.contents) || URL_RE.test(this.contents);
|
46 | }
|
47 |
|
48 | parse(code) {
|
49 | let root = postcss.parse(code, {
|
50 | from: this.name
|
51 | });
|
52 | return new CSSAst(code, root);
|
53 | }
|
54 |
|
55 | collectDependencies() {
|
56 | this.ast.root.walkAtRules('import', rule => {
|
57 | let params = valueParser(rule.params);
|
58 |
|
59 | let _params$nodes = (0, _toArray2.default)(params.nodes),
|
60 | name = _params$nodes[0],
|
61 | media = _params$nodes.slice(1);
|
62 |
|
63 | let dep;
|
64 |
|
65 | if (name.type === 'function' && name.value === 'url' && name.nodes.length) {
|
66 | name = name.nodes[0];
|
67 | }
|
68 |
|
69 | dep = name.value;
|
70 |
|
71 | if (!dep) {
|
72 | throw new Error('Could not find import name for ' + rule);
|
73 | }
|
74 |
|
75 | if (PROTOCOL_RE.test(dep)) {
|
76 | return;
|
77 | }
|
78 |
|
79 |
|
80 |
|
81 | let inlineHTML = this.options.rendition && this.options.rendition.inlineHTML;
|
82 |
|
83 | if (inlineHTML) {
|
84 | name.value = this.addURLDependency(dep, {
|
85 | loc: rule.source.start
|
86 | });
|
87 | rule.params = params.toString();
|
88 | } else {
|
89 | media = valueParser.stringify(media).trim();
|
90 | this.addDependency(dep, {
|
91 | media,
|
92 | loc: rule.source.start
|
93 | });
|
94 | rule.remove();
|
95 | }
|
96 |
|
97 | this.ast.dirty = true;
|
98 | });
|
99 | this.ast.root.walkDecls(decl => {
|
100 | if (URL_RE.test(decl.value)) {
|
101 | let parsed = valueParser(decl.value);
|
102 | let dirty = false;
|
103 | parsed.walk(node => {
|
104 | if (node.type === 'function' && node.value === 'url' && node.nodes.length) {
|
105 | let url = this.addURLDependency(node.nodes[0].value, {
|
106 | loc: decl.source.start
|
107 | });
|
108 |
|
109 | if (!isURL(url)) {
|
110 | url = urlJoin(this.options.publicURL, url);
|
111 | }
|
112 |
|
113 | dirty = node.nodes[0].value !== url;
|
114 | node.nodes[0].value = url;
|
115 | }
|
116 | });
|
117 |
|
118 | if (dirty) {
|
119 | decl.value = parsed.toString();
|
120 | this.ast.dirty = true;
|
121 | }
|
122 | }
|
123 |
|
124 | if (decl.prop === 'composes' && FROM_IMPORT_RE.test(decl.value)) {
|
125 | let parsed = valueParser(decl.value);
|
126 | parsed.walk(node => {
|
127 | if (node.type === 'string') {
|
128 | const _FROM_IMPORT_RE$exec = FROM_IMPORT_RE.exec(decl.value),
|
129 | _FROM_IMPORT_RE$exec2 = (0, _slicedToArray2.default)(_FROM_IMPORT_RE$exec, 2),
|
130 | importPath = _FROM_IMPORT_RE$exec2[1];
|
131 |
|
132 | this.addURLDependency(importPath, {
|
133 | dynamic: false,
|
134 | loc: decl.source.start
|
135 | });
|
136 | }
|
137 | });
|
138 | }
|
139 | });
|
140 | }
|
141 |
|
142 | pretransform() {
|
143 | var _this = this;
|
144 |
|
145 | return (0, _asyncToGenerator2.default)(function* () {
|
146 | if (_this.options.sourceMaps && !_this.previousSourceMap) {
|
147 | _this.previousSourceMap = yield loadSourceMap(_this);
|
148 | }
|
149 | })();
|
150 | }
|
151 |
|
152 | transform() {
|
153 | var _this2 = this;
|
154 |
|
155 | return (0, _asyncToGenerator2.default)(function* () {
|
156 | yield postcssTransform(_this2);
|
157 | })();
|
158 | }
|
159 |
|
160 | getCSSAst() {
|
161 |
|
162 | if (!(this.ast instanceof CSSAst)) {
|
163 | this.ast = CSSAsset.prototype.parse.call(this, this.ast.render(this.name));
|
164 | }
|
165 |
|
166 | return this.ast.root;
|
167 | }
|
168 |
|
169 | generate() {
|
170 | var _this3 = this;
|
171 |
|
172 | return (0, _asyncToGenerator2.default)(function* () {
|
173 | let css;
|
174 |
|
175 | if (_this3.ast) {
|
176 | let result = _this3.ast.render(_this3.name);
|
177 |
|
178 | css = result.css;
|
179 | if (result.map) _this3.sourceMap = result.map;
|
180 | } else {
|
181 | css = _this3.contents;
|
182 | }
|
183 |
|
184 | let js = '';
|
185 |
|
186 | if (_this3.options.hmr) {
|
187 | _this3.addDependency('_css_loader');
|
188 |
|
189 | js = `
|
190 | var reloadCSS = require('_css_loader');
|
191 | module.hot.dispose(reloadCSS);
|
192 | module.hot.accept(reloadCSS);
|
193 | `;
|
194 | }
|
195 |
|
196 | if (_this3.cssModules) {
|
197 | js += 'module.exports = ' + JSON.stringify(_this3.cssModules, null, 2) + ';';
|
198 | }
|
199 |
|
200 | if (_this3.options.sourceMaps) {
|
201 | if (_this3.sourceMap) {
|
202 | _this3.sourceMap = yield new SourceMap().addMap(_this3.sourceMap);
|
203 | }
|
204 |
|
205 | if (_this3.previousSourceMap) {
|
206 | _this3.previousSourceMap.sources = _this3.previousSourceMap.sources.map(v => path.join(path.dirname(_this3.relativeName), _this3.previousSourceMap.sourceRoot || '', v));
|
207 |
|
208 | if (_this3.sourceMap) {
|
209 | _this3.sourceMap = yield new SourceMap().extendSourceMap(_this3.previousSourceMap, _this3.sourceMap);
|
210 | } else {
|
211 | _this3.sourceMap = yield new SourceMap().addMap(_this3.previousSourceMap);
|
212 | }
|
213 | } else if (!_this3.sourceMap) {
|
214 | _this3.sourceMap = new SourceMap().generateEmptyMap(_this3.relativeName, css);
|
215 | }
|
216 | }
|
217 |
|
218 | return [{
|
219 | type: 'css',
|
220 | value: css,
|
221 | cssModules: _this3.cssModules,
|
222 | map: _this3.sourceMap
|
223 | }, {
|
224 | type: 'js',
|
225 | value: js,
|
226 | hasDependencies: false
|
227 | }];
|
228 | })();
|
229 | }
|
230 |
|
231 | generateErrorMessage(err) {
|
232 |
|
233 | if (err.loc && !err.showSourceCode) {
|
234 | err = new CssSyntaxError(err.message, err.loc.line, err.loc.column, this.contents);
|
235 | }
|
236 |
|
237 | err.message = err.reason || err.message;
|
238 | err.loc = {
|
239 | line: err.line,
|
240 | column: err.column
|
241 | };
|
242 |
|
243 | if (err.showSourceCode) {
|
244 | err.codeFrame = err.showSourceCode();
|
245 | err.highlightedCodeFrame = err.showSourceCode(true);
|
246 | }
|
247 |
|
248 | return err;
|
249 | }
|
250 |
|
251 | }
|
252 |
|
253 | class CSSAst {
|
254 | constructor(css, root) {
|
255 | this.css = css;
|
256 | this.root = root;
|
257 | this.dirty = false;
|
258 | }
|
259 |
|
260 | render(name) {
|
261 | if (this.dirty) {
|
262 | let _this$root$toResult = this.root.toResult({
|
263 | to: name,
|
264 | map: {
|
265 | inline: false,
|
266 | annotation: false,
|
267 | sourcesContent: true
|
268 | }
|
269 | }),
|
270 | css = _this$root$toResult.css,
|
271 | map = _this$root$toResult.map;
|
272 |
|
273 | this.css = css;
|
274 | return {
|
275 | css: this.css,
|
276 | map: map ? map.toJSON() : null
|
277 | };
|
278 | }
|
279 |
|
280 | return {
|
281 | css: this.css
|
282 | };
|
283 | }
|
284 |
|
285 | }
|
286 |
|
287 | module.exports = CSSAsset; |
\ | No newline at end of file |