@parcel/transformer-stylus 2.0.0-nightly.97 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/StylusTransformer.js +256 -45
- package/package.json +11 -9
- package/src/StylusTransformer.js +177 -53
package/lib/StylusTransformer.js
CHANGED
|
@@ -5,23 +5,132 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
function _plugin() {
|
|
9
|
+
const data = require("@parcel/plugin");
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
_plugin = function () {
|
|
12
|
+
return data;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function _utils() {
|
|
19
|
+
const data = require("@parcel/utils");
|
|
20
|
+
|
|
21
|
+
_utils = function () {
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return data;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function _path() {
|
|
29
|
+
const data = _interopRequireDefault(require("path"));
|
|
30
|
+
|
|
31
|
+
_path = function () {
|
|
32
|
+
return data;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return data;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function _fs() {
|
|
39
|
+
const data = _interopRequireDefault(require("fs"));
|
|
11
40
|
|
|
12
|
-
|
|
41
|
+
_fs = function () {
|
|
42
|
+
return data;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function _stylus() {
|
|
49
|
+
const data = _interopRequireDefault(require("stylus"));
|
|
50
|
+
|
|
51
|
+
_stylus = function () {
|
|
52
|
+
return data;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return data;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function _parser() {
|
|
59
|
+
const data = _interopRequireDefault(require("stylus/lib/parser"));
|
|
60
|
+
|
|
61
|
+
_parser = function () {
|
|
62
|
+
return data;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return data;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function _depsResolver() {
|
|
69
|
+
const data = _interopRequireDefault(require("stylus/lib/visitor/deps-resolver"));
|
|
70
|
+
|
|
71
|
+
_depsResolver = function () {
|
|
72
|
+
return data;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return data;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function _nodes() {
|
|
79
|
+
const data = _interopRequireDefault(require("stylus/lib/nodes"));
|
|
80
|
+
|
|
81
|
+
_nodes = function () {
|
|
82
|
+
return data;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return data;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function _utils2() {
|
|
89
|
+
const data = _interopRequireDefault(require("stylus/lib/utils"));
|
|
90
|
+
|
|
91
|
+
_utils2 = function () {
|
|
92
|
+
return data;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function _evaluator() {
|
|
99
|
+
const data = _interopRequireDefault(require("stylus/lib/visitor/evaluator"));
|
|
100
|
+
|
|
101
|
+
_evaluator = function () {
|
|
102
|
+
return data;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return data;
|
|
106
|
+
}
|
|
13
107
|
|
|
14
108
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
109
|
|
|
16
110
|
const URL_RE = /^(?:url\s*\(\s*)?['"]?(?:[#/]|(?:https?:)?\/\/)/i;
|
|
17
111
|
|
|
18
|
-
var _default = new _plugin.Transformer({
|
|
19
|
-
|
|
20
|
-
|
|
112
|
+
var _default = new (_plugin().Transformer)({
|
|
113
|
+
async loadConfig({
|
|
114
|
+
config
|
|
21
115
|
}) {
|
|
22
|
-
|
|
116
|
+
let configFile = await config.getConfig(['.stylusrc', '.stylusrc.js'], {
|
|
23
117
|
packageKey: 'stylus'
|
|
24
118
|
});
|
|
119
|
+
|
|
120
|
+
if (configFile) {
|
|
121
|
+
let isJavascript = _path().default.extname(configFile.filePath) === '.js';
|
|
122
|
+
|
|
123
|
+
if (isJavascript) {
|
|
124
|
+
config.invalidateOnStartup();
|
|
125
|
+
} // Resolve relative paths from config file
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if (configFile.contents.paths) {
|
|
129
|
+
configFile.contents.paths = configFile.contents.paths.map(p => _path().default.resolve(_path().default.dirname(configFile.filePath), p));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return configFile.contents;
|
|
133
|
+
}
|
|
25
134
|
},
|
|
26
135
|
|
|
27
136
|
async transform({
|
|
@@ -30,18 +139,27 @@ var _default = new _plugin.Transformer({
|
|
|
30
139
|
config,
|
|
31
140
|
options
|
|
32
141
|
}) {
|
|
33
|
-
|
|
34
|
-
let stylus = await options.packageManager.require('stylus', asset.filePath);
|
|
142
|
+
let stylusConfig = config !== null && config !== void 0 ? config : {};
|
|
35
143
|
let code = await asset.getCode();
|
|
36
|
-
let style =
|
|
144
|
+
let style = (0, _stylus().default)(code, { ...stylusConfig
|
|
145
|
+
});
|
|
37
146
|
style.set('filename', asset.filePath);
|
|
38
147
|
style.set('include css', true); // Setup a handler for the URL function so we add dependencies for linked assets.
|
|
39
148
|
|
|
40
149
|
style.define('url', node => {
|
|
41
|
-
let filename = asset.addURLDependency(node.val,
|
|
42
|
-
|
|
150
|
+
let filename = asset.addURLDependency(node.val, {
|
|
151
|
+
loc: (0, _utils().createDependencyLocation)({
|
|
152
|
+
line: node.lineno,
|
|
153
|
+
column: node.column
|
|
154
|
+
}, node.val)
|
|
155
|
+
});
|
|
156
|
+
return new (_stylus().default.nodes.Literal)(`url(${JSON.stringify(filename)})`);
|
|
43
157
|
});
|
|
44
|
-
|
|
158
|
+
let {
|
|
159
|
+
resolved: stylusPath
|
|
160
|
+
} = await options.packageManager.resolve('stylus', __filename);
|
|
161
|
+
let nativeGlob = await options.packageManager.require('glob', stylusPath);
|
|
162
|
+
style.set('Evaluator', await createEvaluator(code, asset, resolve, style.options, options, nativeGlob));
|
|
45
163
|
asset.type = 'css';
|
|
46
164
|
asset.setCode(style.render());
|
|
47
165
|
asset.meta.hasDependencies = false;
|
|
@@ -52,29 +170,48 @@ var _default = new _plugin.Transformer({
|
|
|
52
170
|
|
|
53
171
|
exports.default = _default;
|
|
54
172
|
|
|
55
|
-
|
|
173
|
+
function attemptResolve(importedPath, filepath, asset, resolve, deps) {
|
|
174
|
+
if (deps.has(importedPath)) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if ((0, _utils().isGlob)(importedPath)) {
|
|
179
|
+
// Invalidate when new files are created that match the glob pattern.
|
|
180
|
+
let absoluteGlob = _path().default.resolve(_path().default.dirname(filepath), importedPath);
|
|
181
|
+
|
|
182
|
+
asset.invalidateOnFileCreate({
|
|
183
|
+
glob: absoluteGlob
|
|
184
|
+
});
|
|
185
|
+
deps.set(importedPath, (0, _utils().glob)(absoluteGlob, asset.fs, {
|
|
186
|
+
onlyFiles: true
|
|
187
|
+
}).then(entries => Promise.all(entries.map(entry => resolve(filepath, './' + _path().default.relative(_path().default.dirname(filepath), entry))))));
|
|
188
|
+
} else {
|
|
189
|
+
deps.set(importedPath, resolve(filepath, importedPath));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function getDependencies(code, filepath, asset, resolve, options, parcelOptions, nativeGlob, seen = new Set(), includeImports = true) {
|
|
56
194
|
seen.add(filepath);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let parser = new Parser(code, options);
|
|
195
|
+
_nodes().default.filename = asset.filePath;
|
|
196
|
+
let parser = new (_parser().default)(code, options);
|
|
60
197
|
let ast = parser.parse();
|
|
61
198
|
let deps = new Map();
|
|
62
|
-
|
|
199
|
+
|
|
200
|
+
if (includeImports && options.imports) {
|
|
201
|
+
for (let importedPath of options.imports) {
|
|
202
|
+
attemptResolve(importedPath, filepath, asset, resolve, deps);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
class ImportVisitor extends _depsResolver().default {
|
|
63
207
|
visitImport(imported) {
|
|
64
208
|
let importedPath = imported.path.first.string;
|
|
65
|
-
|
|
66
|
-
if (!deps.has(importedPath)) {
|
|
67
|
-
if ((0, _utils.isGlob)(importedPath)) {
|
|
68
|
-
deps.set(importedPath, (0, _utils.glob)(_path.default.resolve(_path.default.dirname(filepath), importedPath), parcelOptions.inputFS, {
|
|
69
|
-
onlyFiles: true
|
|
70
|
-
}).then(entries => Promise.all(entries.map(entry => resolve(filepath, './' + _path.default.relative(_path.default.dirname(filepath), entry))))));
|
|
71
|
-
} else {
|
|
72
|
-
deps.set(importedPath, resolve(filepath, importedPath));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
209
|
+
attemptResolve(importedPath, filepath, asset, resolve, deps);
|
|
75
210
|
}
|
|
76
211
|
|
|
77
|
-
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
new ImportVisitor(ast, options).visit(ast); // Recursively process depdendencies, and return a map with all resolved paths.
|
|
78
215
|
|
|
79
216
|
let res = new Map();
|
|
80
217
|
await Promise.all(Array.from(deps.entries()).map(async ([importedPath, resolved]) => {
|
|
@@ -86,7 +223,7 @@ async function getDependencies(code, filepath, asset, resolve, options, parcelOp
|
|
|
86
223
|
|
|
87
224
|
let found;
|
|
88
225
|
|
|
89
|
-
if (resolved) {
|
|
226
|
+
if (resolved && (!Array.isArray(resolved) || resolved.length > 0)) {
|
|
90
227
|
found = Array.isArray(resolved) ? resolved : [resolved];
|
|
91
228
|
res.set(importedPath, resolved);
|
|
92
229
|
} else {
|
|
@@ -97,13 +234,20 @@ async function getDependencies(code, filepath, asset, resolve, options, parcelOp
|
|
|
97
234
|
|
|
98
235
|
if (!/\.styl$/i.test(importedPath)) {
|
|
99
236
|
importedPath += '.styl';
|
|
100
|
-
}
|
|
237
|
+
} // Patch the native FS so we use Parcel's FS, and track files that are
|
|
238
|
+
// checked so we invalidate the cache when they are created.
|
|
239
|
+
|
|
101
240
|
|
|
102
|
-
let
|
|
103
|
-
|
|
241
|
+
let restore = patchNativeFS(asset.fs, nativeGlob);
|
|
242
|
+
let paths = [...new Set((options.paths || []).concat(_path().default.dirname(filepath || '.')))];
|
|
243
|
+
found = _utils2().default.find(importedPath, paths, filepath);
|
|
104
244
|
|
|
105
245
|
if (!found) {
|
|
106
|
-
found =
|
|
246
|
+
found = _utils2().default.lookupIndex(originalPath, paths, filepath);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
for (let invalidation of restore()) {
|
|
250
|
+
asset.invalidateOnFileCreate(invalidation);
|
|
107
251
|
}
|
|
108
252
|
|
|
109
253
|
if (!found) {
|
|
@@ -114,12 +258,10 @@ async function getDependencies(code, filepath, asset, resolve, options, parcelOp
|
|
|
114
258
|
|
|
115
259
|
for (let resolved of found) {
|
|
116
260
|
if (!seen.has(resolved)) {
|
|
117
|
-
await asset.
|
|
118
|
-
filePath: resolved
|
|
119
|
-
});
|
|
261
|
+
await asset.invalidateOnFileChange(resolved);
|
|
120
262
|
let code = await asset.fs.readFile(resolved, 'utf8');
|
|
121
263
|
|
|
122
|
-
for (let [path, resolvedPath] of await getDependencies(code, resolved, asset, resolve, options, parcelOptions, seen)) {
|
|
264
|
+
for (let [path, resolvedPath] of await getDependencies(code, resolved, asset, resolve, options, parcelOptions, nativeGlob, seen, false)) {
|
|
123
265
|
res.set(path, resolvedPath);
|
|
124
266
|
}
|
|
125
267
|
}
|
|
@@ -128,13 +270,12 @@ async function getDependencies(code, filepath, asset, resolve, options, parcelOp
|
|
|
128
270
|
return res;
|
|
129
271
|
}
|
|
130
272
|
|
|
131
|
-
async function createEvaluator(code, asset, resolve, options, parcelOptions) {
|
|
132
|
-
const deps = await getDependencies(code, asset.filePath, asset, resolve, options, parcelOptions);
|
|
133
|
-
const Evaluator = await parcelOptions.packageManager.require('stylus/lib/visitor/evaluator', asset.filePath); // This is a custom stylus evaluator that extends stylus with support for the node
|
|
273
|
+
async function createEvaluator(code, asset, resolve, options, parcelOptions, nativeGlob) {
|
|
274
|
+
const deps = await getDependencies(code, asset.filePath, asset, resolve, options, parcelOptions, nativeGlob); // This is a custom stylus evaluator that extends stylus with support for the node
|
|
134
275
|
// require resolution algorithm. It also adds all dependencies to the parcel asset
|
|
135
276
|
// tree so the file watcher works correctly, etc.
|
|
136
277
|
|
|
137
|
-
|
|
278
|
+
class CustomEvaluator extends _evaluator().default {
|
|
138
279
|
visitImport(imported) {
|
|
139
280
|
let node = this.visit(imported.path).first;
|
|
140
281
|
let path = node.string;
|
|
@@ -152,16 +293,86 @@ async function createEvaluator(code, asset, resolve, options, parcelOptions) {
|
|
|
152
293
|
// replace it with a separate import node for each file
|
|
153
294
|
return mergeBlocks(resolved.map(resolvedPath => {
|
|
154
295
|
node.string = resolvedPath;
|
|
155
|
-
|
|
296
|
+
let restore = patchNativeFS(asset.fs, nativeGlob);
|
|
297
|
+
let res = super.visitImport(imported.clone());
|
|
298
|
+
restore();
|
|
299
|
+
return res;
|
|
156
300
|
}));
|
|
157
301
|
}
|
|
158
302
|
}
|
|
159
|
-
} //
|
|
303
|
+
} // Patch the native FS so stylus uses Parcel's FS to read the file.
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
let restore = patchNativeFS(asset.fs, nativeGlob); // Done. Let stylus do its thing.
|
|
307
|
+
|
|
308
|
+
let res = super.visitImport(imported);
|
|
309
|
+
restore();
|
|
310
|
+
return res;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return CustomEvaluator;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function patchNativeFS(fs, nativeGlob) {
|
|
319
|
+
let invalidations = [];
|
|
320
|
+
|
|
321
|
+
let readFileSync = _fs().default.readFileSync;
|
|
322
|
+
|
|
323
|
+
let statSync = _fs().default.statSync; // $FlowFixMe
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
_fs().default.readFileSync = (filename, encoding) => {
|
|
327
|
+
return fs.readFileSync(filename, encoding);
|
|
328
|
+
}; // $FlowFixMe
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
_fs().default.statSync = p => {
|
|
332
|
+
try {
|
|
333
|
+
return fs.statSync(p);
|
|
334
|
+
} catch (err) {
|
|
335
|
+
// Track files that were checked but don't exist so that we watch for their creation.
|
|
336
|
+
if (!p.includes(`node_modules${_path().default.sep}stylus`)) {
|
|
337
|
+
invalidations.push({
|
|
338
|
+
filePath: p
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
throw err;
|
|
343
|
+
}
|
|
344
|
+
}; // Patch the `glob` module as well so we use the Parcel FS and track invalidations.
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
let glob = nativeGlob.sync;
|
|
160
348
|
|
|
349
|
+
nativeGlob.sync = p => {
|
|
350
|
+
let res = (0, _utils().globSync)(p, fs);
|
|
161
351
|
|
|
162
|
-
|
|
352
|
+
if (!p.includes(`node_modules${_path().default.sep}stylus`)) {
|
|
353
|
+
// Sometimes stylus passes file paths with no glob parts to the `glob` module.
|
|
354
|
+
// We want to avoid treating these as globs for performance.
|
|
355
|
+
if ((0, _utils().isGlob)(p)) {
|
|
356
|
+
invalidations.push({
|
|
357
|
+
glob: p
|
|
358
|
+
});
|
|
359
|
+
} else if (res.length === 0) {
|
|
360
|
+
invalidations.push({
|
|
361
|
+
filePath: p
|
|
362
|
+
});
|
|
363
|
+
}
|
|
163
364
|
}
|
|
164
365
|
|
|
366
|
+
return res;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
return () => {
|
|
370
|
+
// $FlowFixMe
|
|
371
|
+
_fs().default.readFileSync = readFileSync; // $FlowFixMe
|
|
372
|
+
|
|
373
|
+
_fs().default.statSync = statSync;
|
|
374
|
+
nativeGlob.sync = glob;
|
|
375
|
+
return invalidations;
|
|
165
376
|
};
|
|
166
377
|
}
|
|
167
378
|
/**
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parcel/transformer-stylus",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
+
"funding": {
|
|
9
|
+
"type": "opencollective",
|
|
10
|
+
"url": "https://opencollective.com/parcel"
|
|
11
|
+
},
|
|
8
12
|
"repository": {
|
|
9
13
|
"type": "git",
|
|
10
14
|
"url": "https://github.com/parcel-bundler/parcel.git"
|
|
@@ -12,15 +16,13 @@
|
|
|
12
16
|
"main": "lib/StylusTransformer.js",
|
|
13
17
|
"source": "src/StylusTransformer.js",
|
|
14
18
|
"engines": {
|
|
15
|
-
"node": ">=
|
|
16
|
-
"parcel": "^2.
|
|
19
|
+
"node": ">= 12.0.0",
|
|
20
|
+
"parcel": "^2.1.0"
|
|
17
21
|
},
|
|
18
22
|
"dependencies": {
|
|
19
|
-
"@parcel/plugin": "2.
|
|
20
|
-
"@parcel/utils": "2.
|
|
21
|
-
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"stylus": "^0.54.5"
|
|
23
|
+
"@parcel/plugin": "^2.1.0",
|
|
24
|
+
"@parcel/utils": "^2.1.0",
|
|
25
|
+
"stylus": "^0.55.0"
|
|
24
26
|
},
|
|
25
|
-
"gitHead": "
|
|
27
|
+
"gitHead": "5a80fbe4af8797d0aab248a66f5254f42f00e83e"
|
|
26
28
|
}
|
package/src/StylusTransformer.js
CHANGED
|
@@ -1,34 +1,74 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
3
|
import {Transformer} from '@parcel/plugin';
|
|
4
|
-
import {isGlob, glob} from '@parcel/utils';
|
|
4
|
+
import {createDependencyLocation, isGlob, glob, globSync} from '@parcel/utils';
|
|
5
5
|
import path from 'path';
|
|
6
|
+
import nativeFS from 'fs';
|
|
7
|
+
import stylus from 'stylus';
|
|
8
|
+
import Parser from 'stylus/lib/parser';
|
|
9
|
+
import DepsResolver from 'stylus/lib/visitor/deps-resolver';
|
|
10
|
+
import nodes from 'stylus/lib/nodes';
|
|
11
|
+
import utils from 'stylus/lib/utils';
|
|
12
|
+
import Evaluator from 'stylus/lib/visitor/evaluator';
|
|
6
13
|
|
|
7
14
|
const URL_RE = /^(?:url\s*\(\s*)?['"]?(?:[#/]|(?:https?:)?\/\/)/i;
|
|
8
15
|
|
|
9
|
-
export default new Transformer({
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
export default (new Transformer({
|
|
17
|
+
async loadConfig({config}) {
|
|
18
|
+
let configFile = await config.getConfig(['.stylusrc', '.stylusrc.js'], {
|
|
12
19
|
packageKey: 'stylus',
|
|
13
20
|
});
|
|
21
|
+
|
|
22
|
+
if (configFile) {
|
|
23
|
+
let isJavascript = path.extname(configFile.filePath) === '.js';
|
|
24
|
+
if (isJavascript) {
|
|
25
|
+
config.invalidateOnStartup();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Resolve relative paths from config file
|
|
29
|
+
if (configFile.contents.paths) {
|
|
30
|
+
configFile.contents.paths = configFile.contents.paths.map(p =>
|
|
31
|
+
path.resolve(path.dirname(configFile.filePath), p),
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return configFile.contents;
|
|
36
|
+
}
|
|
14
37
|
},
|
|
15
38
|
|
|
16
39
|
async transform({asset, resolve, config, options}) {
|
|
17
|
-
|
|
18
|
-
let stylus = await options.packageManager.require('stylus', asset.filePath);
|
|
19
|
-
|
|
40
|
+
let stylusConfig = config ?? {};
|
|
20
41
|
let code = await asset.getCode();
|
|
21
|
-
let style = stylus(code,
|
|
42
|
+
let style = stylus(code, {...stylusConfig});
|
|
22
43
|
style.set('filename', asset.filePath);
|
|
23
44
|
style.set('include css', true);
|
|
24
45
|
// Setup a handler for the URL function so we add dependencies for linked assets.
|
|
25
|
-
style.define('url', node => {
|
|
26
|
-
let filename = asset.addURLDependency(node.val,
|
|
46
|
+
style.define('url', (node: stylus.nodes.String | stylus.nodes.Literal) => {
|
|
47
|
+
let filename = asset.addURLDependency(node.val, {
|
|
48
|
+
loc: createDependencyLocation(
|
|
49
|
+
{line: node.lineno, column: node.column},
|
|
50
|
+
node.val,
|
|
51
|
+
),
|
|
52
|
+
});
|
|
27
53
|
return new stylus.nodes.Literal(`url(${JSON.stringify(filename)})`);
|
|
28
54
|
});
|
|
55
|
+
|
|
56
|
+
let {resolved: stylusPath} = await options.packageManager.resolve(
|
|
57
|
+
'stylus',
|
|
58
|
+
__filename,
|
|
59
|
+
);
|
|
60
|
+
let nativeGlob = await options.packageManager.require('glob', stylusPath);
|
|
61
|
+
|
|
29
62
|
style.set(
|
|
30
63
|
'Evaluator',
|
|
31
|
-
await createEvaluator(
|
|
64
|
+
await createEvaluator(
|
|
65
|
+
code,
|
|
66
|
+
asset,
|
|
67
|
+
resolve,
|
|
68
|
+
style.options,
|
|
69
|
+
options,
|
|
70
|
+
nativeGlob,
|
|
71
|
+
),
|
|
32
72
|
);
|
|
33
73
|
|
|
34
74
|
asset.type = 'css';
|
|
@@ -36,7 +76,37 @@ export default new Transformer({
|
|
|
36
76
|
asset.meta.hasDependencies = false;
|
|
37
77
|
return [asset];
|
|
38
78
|
},
|
|
39
|
-
});
|
|
79
|
+
}): Transformer);
|
|
80
|
+
|
|
81
|
+
function attemptResolve(importedPath, filepath, asset, resolve, deps) {
|
|
82
|
+
if (deps.has(importedPath)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (isGlob(importedPath)) {
|
|
87
|
+
// Invalidate when new files are created that match the glob pattern.
|
|
88
|
+
let absoluteGlob = path.resolve(path.dirname(filepath), importedPath);
|
|
89
|
+
asset.invalidateOnFileCreate({glob: absoluteGlob});
|
|
90
|
+
|
|
91
|
+
deps.set(
|
|
92
|
+
importedPath,
|
|
93
|
+
glob(absoluteGlob, asset.fs, {
|
|
94
|
+
onlyFiles: true,
|
|
95
|
+
}).then(entries =>
|
|
96
|
+
Promise.all(
|
|
97
|
+
entries.map(entry =>
|
|
98
|
+
resolve(
|
|
99
|
+
filepath,
|
|
100
|
+
'./' + path.relative(path.dirname(filepath), entry),
|
|
101
|
+
),
|
|
102
|
+
),
|
|
103
|
+
),
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
deps.set(importedPath, resolve(filepath, importedPath));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
40
110
|
|
|
41
111
|
async function getDependencies(
|
|
42
112
|
code,
|
|
@@ -45,14 +115,11 @@ async function getDependencies(
|
|
|
45
115
|
resolve,
|
|
46
116
|
options,
|
|
47
117
|
parcelOptions,
|
|
118
|
+
nativeGlob,
|
|
48
119
|
seen = new Set(),
|
|
120
|
+
includeImports = true,
|
|
49
121
|
) {
|
|
50
122
|
seen.add(filepath);
|
|
51
|
-
const [Parser, DepsResolver, nodes, utils] = await Promise.all(
|
|
52
|
-
['parser', 'visitor/deps-resolver', 'nodes', 'utils'].map(dep =>
|
|
53
|
-
parcelOptions.packageManager.require('stylus/lib/' + dep, filepath),
|
|
54
|
-
),
|
|
55
|
-
);
|
|
56
123
|
|
|
57
124
|
nodes.filename = asset.filePath;
|
|
58
125
|
|
|
@@ -60,35 +127,16 @@ async function getDependencies(
|
|
|
60
127
|
let ast = parser.parse();
|
|
61
128
|
let deps = new Map();
|
|
62
129
|
|
|
130
|
+
if (includeImports && options.imports) {
|
|
131
|
+
for (let importedPath of options.imports) {
|
|
132
|
+
attemptResolve(importedPath, filepath, asset, resolve, deps);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
63
136
|
class ImportVisitor extends DepsResolver {
|
|
64
137
|
visitImport(imported) {
|
|
65
138
|
let importedPath = imported.path.first.string;
|
|
66
|
-
|
|
67
|
-
if (!deps.has(importedPath)) {
|
|
68
|
-
if (isGlob(importedPath)) {
|
|
69
|
-
deps.set(
|
|
70
|
-
importedPath,
|
|
71
|
-
glob(
|
|
72
|
-
path.resolve(path.dirname(filepath), importedPath),
|
|
73
|
-
parcelOptions.inputFS,
|
|
74
|
-
{
|
|
75
|
-
onlyFiles: true,
|
|
76
|
-
},
|
|
77
|
-
).then(entries =>
|
|
78
|
-
Promise.all(
|
|
79
|
-
entries.map(entry =>
|
|
80
|
-
resolve(
|
|
81
|
-
filepath,
|
|
82
|
-
'./' + path.relative(path.dirname(filepath), entry),
|
|
83
|
-
),
|
|
84
|
-
),
|
|
85
|
-
),
|
|
86
|
-
),
|
|
87
|
-
);
|
|
88
|
-
} else {
|
|
89
|
-
deps.set(importedPath, resolve(filepath, importedPath));
|
|
90
|
-
}
|
|
91
|
-
}
|
|
139
|
+
attemptResolve(importedPath, filepath, asset, resolve, deps);
|
|
92
140
|
}
|
|
93
141
|
}
|
|
94
142
|
|
|
@@ -105,7 +153,7 @@ async function getDependencies(
|
|
|
105
153
|
}
|
|
106
154
|
|
|
107
155
|
let found;
|
|
108
|
-
if (resolved) {
|
|
156
|
+
if (resolved && (!Array.isArray(resolved) || resolved.length > 0)) {
|
|
109
157
|
found = Array.isArray(resolved) ? resolved : [resolved];
|
|
110
158
|
res.set(importedPath, resolved);
|
|
111
159
|
} else {
|
|
@@ -118,12 +166,24 @@ async function getDependencies(
|
|
|
118
166
|
importedPath += '.styl';
|
|
119
167
|
}
|
|
120
168
|
|
|
121
|
-
|
|
169
|
+
// Patch the native FS so we use Parcel's FS, and track files that are
|
|
170
|
+
// checked so we invalidate the cache when they are created.
|
|
171
|
+
let restore = patchNativeFS(asset.fs, nativeGlob);
|
|
172
|
+
|
|
173
|
+
let paths = [
|
|
174
|
+
...new Set(
|
|
175
|
+
(options.paths || []).concat(path.dirname(filepath || '.')),
|
|
176
|
+
),
|
|
177
|
+
];
|
|
122
178
|
found = utils.find(importedPath, paths, filepath);
|
|
123
179
|
if (!found) {
|
|
124
180
|
found = utils.lookupIndex(originalPath, paths, filepath);
|
|
125
181
|
}
|
|
126
182
|
|
|
183
|
+
for (let invalidation of restore()) {
|
|
184
|
+
asset.invalidateOnFileCreate(invalidation);
|
|
185
|
+
}
|
|
186
|
+
|
|
127
187
|
if (!found) {
|
|
128
188
|
throw new Error('failed to locate file ' + originalPath);
|
|
129
189
|
}
|
|
@@ -132,7 +192,7 @@ async function getDependencies(
|
|
|
132
192
|
// Recursively process resolved files as well to get nested deps
|
|
133
193
|
for (let resolved of found) {
|
|
134
194
|
if (!seen.has(resolved)) {
|
|
135
|
-
await asset.
|
|
195
|
+
await asset.invalidateOnFileChange(resolved);
|
|
136
196
|
|
|
137
197
|
let code = await asset.fs.readFile(resolved, 'utf8');
|
|
138
198
|
for (let [path, resolvedPath] of await getDependencies(
|
|
@@ -142,7 +202,9 @@ async function getDependencies(
|
|
|
142
202
|
resolve,
|
|
143
203
|
options,
|
|
144
204
|
parcelOptions,
|
|
205
|
+
nativeGlob,
|
|
145
206
|
seen,
|
|
207
|
+
false,
|
|
146
208
|
)) {
|
|
147
209
|
res.set(path, resolvedPath);
|
|
148
210
|
}
|
|
@@ -154,7 +216,14 @@ async function getDependencies(
|
|
|
154
216
|
return res;
|
|
155
217
|
}
|
|
156
218
|
|
|
157
|
-
async function createEvaluator(
|
|
219
|
+
async function createEvaluator(
|
|
220
|
+
code,
|
|
221
|
+
asset,
|
|
222
|
+
resolve,
|
|
223
|
+
options,
|
|
224
|
+
parcelOptions,
|
|
225
|
+
nativeGlob,
|
|
226
|
+
) {
|
|
158
227
|
const deps = await getDependencies(
|
|
159
228
|
code,
|
|
160
229
|
asset.filePath,
|
|
@@ -162,10 +231,7 @@ async function createEvaluator(code, asset, resolve, options, parcelOptions) {
|
|
|
162
231
|
resolve,
|
|
163
232
|
options,
|
|
164
233
|
parcelOptions,
|
|
165
|
-
|
|
166
|
-
const Evaluator = await parcelOptions.packageManager.require(
|
|
167
|
-
'stylus/lib/visitor/evaluator',
|
|
168
|
-
asset.filePath,
|
|
234
|
+
nativeGlob,
|
|
169
235
|
);
|
|
170
236
|
|
|
171
237
|
// This is a custom stylus evaluator that extends stylus with support for the node
|
|
@@ -190,21 +256,79 @@ async function createEvaluator(code, asset, resolve, options, parcelOptions) {
|
|
|
190
256
|
return mergeBlocks(
|
|
191
257
|
resolved.map(resolvedPath => {
|
|
192
258
|
node.string = resolvedPath;
|
|
193
|
-
|
|
259
|
+
let restore = patchNativeFS(asset.fs, nativeGlob);
|
|
260
|
+
let res = super.visitImport(imported.clone());
|
|
261
|
+
restore();
|
|
262
|
+
return res;
|
|
194
263
|
}),
|
|
195
264
|
);
|
|
196
265
|
}
|
|
197
266
|
}
|
|
198
267
|
}
|
|
199
268
|
|
|
269
|
+
// Patch the native FS so stylus uses Parcel's FS to read the file.
|
|
270
|
+
let restore = patchNativeFS(asset.fs, nativeGlob);
|
|
271
|
+
|
|
200
272
|
// Done. Let stylus do its thing.
|
|
201
|
-
|
|
273
|
+
let res = super.visitImport(imported);
|
|
274
|
+
|
|
275
|
+
restore();
|
|
276
|
+
return res;
|
|
202
277
|
}
|
|
203
278
|
}
|
|
204
279
|
|
|
205
280
|
return CustomEvaluator;
|
|
206
281
|
}
|
|
207
282
|
|
|
283
|
+
function patchNativeFS(fs, nativeGlob) {
|
|
284
|
+
let invalidations = [];
|
|
285
|
+
let readFileSync = nativeFS.readFileSync;
|
|
286
|
+
let statSync = nativeFS.statSync;
|
|
287
|
+
|
|
288
|
+
// $FlowFixMe
|
|
289
|
+
nativeFS.readFileSync = (filename, encoding) => {
|
|
290
|
+
return fs.readFileSync(filename, encoding);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
// $FlowFixMe
|
|
294
|
+
nativeFS.statSync = p => {
|
|
295
|
+
try {
|
|
296
|
+
return fs.statSync(p);
|
|
297
|
+
} catch (err) {
|
|
298
|
+
// Track files that were checked but don't exist so that we watch for their creation.
|
|
299
|
+
if (!p.includes(`node_modules${path.sep}stylus`)) {
|
|
300
|
+
invalidations.push({filePath: p});
|
|
301
|
+
}
|
|
302
|
+
throw err;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
// Patch the `glob` module as well so we use the Parcel FS and track invalidations.
|
|
307
|
+
let glob = nativeGlob.sync;
|
|
308
|
+
nativeGlob.sync = p => {
|
|
309
|
+
let res = globSync(p, fs);
|
|
310
|
+
if (!p.includes(`node_modules${path.sep}stylus`)) {
|
|
311
|
+
// Sometimes stylus passes file paths with no glob parts to the `glob` module.
|
|
312
|
+
// We want to avoid treating these as globs for performance.
|
|
313
|
+
if (isGlob(p)) {
|
|
314
|
+
invalidations.push({glob: p});
|
|
315
|
+
} else if (res.length === 0) {
|
|
316
|
+
invalidations.push({filePath: p});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return res;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
return () => {
|
|
323
|
+
// $FlowFixMe
|
|
324
|
+
nativeFS.readFileSync = readFileSync;
|
|
325
|
+
// $FlowFixMe
|
|
326
|
+
nativeFS.statSync = statSync;
|
|
327
|
+
nativeGlob.sync = glob;
|
|
328
|
+
return invalidations;
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
208
332
|
/**
|
|
209
333
|
* Puts the content of all given node blocks into the first one, essentially merging them.
|
|
210
334
|
*/
|