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