@plumeria/utils 21.1.8 → 21.2.1
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/dist/compile.js +12 -2
- package/dist/namespaceImport.d.ts +18 -0
- package/dist/namespaceImport.js +238 -0
- package/dist/parser.js +43 -20
- package/dist/references.d.ts +4 -1
- package/dist/references.js +28 -7
- package/dist/resolver.d.ts +10 -0
- package/dist/resolver.js +141 -0
- package/dist/transform.js +121 -15
- package/package.json +1 -1
package/dist/compile.js
CHANGED
|
@@ -37,6 +37,7 @@ exports.compileCSS = compileCSS;
|
|
|
37
37
|
const core_1 = require("@swc/core");
|
|
38
38
|
const zss_engine_1 = require("zss-engine");
|
|
39
39
|
const sourceCache_1 = require("./sourceCache");
|
|
40
|
+
const namespaceImport_1 = require("./namespaceImport");
|
|
40
41
|
const parser_1 = require("./parser");
|
|
41
42
|
const path = __importStar(require("path"));
|
|
42
43
|
const rs = __importStar(require("@rust-gear/glob"));
|
|
@@ -333,9 +334,18 @@ function compileCSS(options) {
|
|
|
333
334
|
propsByFile.set(file, entries);
|
|
334
335
|
}
|
|
335
336
|
const processFile = (filePath, writes) => {
|
|
336
|
-
const scannedTables = readTables(tables, writes);
|
|
337
337
|
const resourcePath = path.resolve(cwd, filePath);
|
|
338
|
-
const
|
|
338
|
+
const written = options.sources?.[resourcePath] ?? (0, sourceCache_1.readSource)(resourcePath);
|
|
339
|
+
const namespaces = (0, namespaceImport_1.expandNamespaces)(resourcePath, written);
|
|
340
|
+
try {
|
|
341
|
+
return extractFile(resourcePath, namespaces?.source ?? written, writes);
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
throw (0, namespaceImport_1.asWritten)(namespaces, error);
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
const extractFile = (resourcePath, source, writes) => {
|
|
348
|
+
const scannedTables = readTables(tables, writes);
|
|
339
349
|
const extractedSheets = [];
|
|
340
350
|
const ast = (0, core_1.parseSync)(source, {
|
|
341
351
|
syntax: 'typescript',
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface NamespaceImport {
|
|
2
|
+
local: string;
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
appendedStart: number;
|
|
6
|
+
appendedEnd: number;
|
|
7
|
+
unused: boolean;
|
|
8
|
+
dots: number[];
|
|
9
|
+
bindings: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface Namespaces {
|
|
12
|
+
source: string;
|
|
13
|
+
originalLength: number;
|
|
14
|
+
separated: boolean;
|
|
15
|
+
imports: NamespaceImport[];
|
|
16
|
+
}
|
|
17
|
+
export declare function asWritten<T>(namespaces: Namespaces | undefined, error: T): T;
|
|
18
|
+
export declare function expandNamespaces(filePath: string, source: string): Namespaces | undefined;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.asWritten = asWritten;
|
|
4
|
+
exports.expandNamespaces = expandNamespaces;
|
|
5
|
+
const core_1 = require("@swc/core");
|
|
6
|
+
const ast_1 = require("./ast");
|
|
7
|
+
const parser_1 = require("./parser");
|
|
8
|
+
const references_1 = require("./references");
|
|
9
|
+
const resolver_1 = require("./resolver");
|
|
10
|
+
const NAMESPACE_IMPORT = /import\s*\*\s*as\s+([\p{L}\p{N}_$]+)\s*from\s*(['"])(.*?)\2/gu;
|
|
11
|
+
const cache = new Map();
|
|
12
|
+
const LIMIT = 4096;
|
|
13
|
+
const sameTargets = (a, b) => a.length === b.length &&
|
|
14
|
+
a.every(([path, actualPath, exports], i) => path === b[i][0] &&
|
|
15
|
+
actualPath === b[i][1] &&
|
|
16
|
+
exports.length === b[i][2].length &&
|
|
17
|
+
exports.every((name, j) => name === b[i][2][j]));
|
|
18
|
+
const NAME = '[\\p{L}\\p{N}_$]';
|
|
19
|
+
function asWritten(namespaces, error) {
|
|
20
|
+
if (!namespaces)
|
|
21
|
+
return error;
|
|
22
|
+
const restore = (text) => {
|
|
23
|
+
for (const { local, bindings } of namespaces.imports)
|
|
24
|
+
for (const binding of bindings) {
|
|
25
|
+
const pattern = new RegExp(`(?<!${NAME})${binding.replace(/\$/g, '\\$')}(?!${NAME})`, 'gu');
|
|
26
|
+
const dotted = `${local}.${binding.slice(local.length + 1)}`;
|
|
27
|
+
text = text.replace(pattern, () => dotted);
|
|
28
|
+
}
|
|
29
|
+
return text;
|
|
30
|
+
};
|
|
31
|
+
if (typeof error === 'string')
|
|
32
|
+
return restore(error);
|
|
33
|
+
if (error instanceof Error) {
|
|
34
|
+
error.message = restore(error.message);
|
|
35
|
+
if (error.stack)
|
|
36
|
+
error.stack = restore(error.stack);
|
|
37
|
+
}
|
|
38
|
+
return error;
|
|
39
|
+
}
|
|
40
|
+
const unwrap = (node) => {
|
|
41
|
+
while (node?.type === 'ParenthesisExpression')
|
|
42
|
+
node = node.expression;
|
|
43
|
+
return node;
|
|
44
|
+
};
|
|
45
|
+
function expandNamespaces(filePath, source) {
|
|
46
|
+
const targets = [];
|
|
47
|
+
for (const [, local, , path] of source.matchAll(NAMESPACE_IMPORT)) {
|
|
48
|
+
if (path === '@plumeria/core' ||
|
|
49
|
+
!source.includes(`${local}.`) ||
|
|
50
|
+
targets.some(([seen]) => seen === path))
|
|
51
|
+
continue;
|
|
52
|
+
const actualPath = (0, resolver_1.resolveImportPath)(path, filePath);
|
|
53
|
+
if (!actualPath)
|
|
54
|
+
continue;
|
|
55
|
+
const exports = (0, parser_1.exportNames)(actualPath);
|
|
56
|
+
if (exports.length > 0)
|
|
57
|
+
targets.push([path, actualPath, exports]);
|
|
58
|
+
}
|
|
59
|
+
if (targets.length === 0)
|
|
60
|
+
return undefined;
|
|
61
|
+
const cached = cache.get(filePath);
|
|
62
|
+
if (cached &&
|
|
63
|
+
cached.source === source &&
|
|
64
|
+
sameTargets(cached.targets, targets))
|
|
65
|
+
return cached.namespaces;
|
|
66
|
+
const namespaces = expand(source, targets);
|
|
67
|
+
if (cache.size >= LIMIT)
|
|
68
|
+
cache.clear();
|
|
69
|
+
cache.set(filePath, { source, targets, namespaces });
|
|
70
|
+
return namespaces;
|
|
71
|
+
}
|
|
72
|
+
function expand(source, resolved) {
|
|
73
|
+
let ast;
|
|
74
|
+
try {
|
|
75
|
+
ast = (0, core_1.parseSync)(source, {
|
|
76
|
+
syntax: 'typescript',
|
|
77
|
+
tsx: true,
|
|
78
|
+
target: 'es2022',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const buffer = Buffer.from(source, 'utf-8');
|
|
85
|
+
const leadingBytes = Buffer.byteLength(source.slice(0, (0, ast_1.getLeadingCommentLength)(source)), 'utf-8');
|
|
86
|
+
const base = ast.span.start - leadingBytes;
|
|
87
|
+
const targets = new Map();
|
|
88
|
+
for (const statement of ast.body) {
|
|
89
|
+
if (statement.type !== 'ImportDeclaration' || statement.typeOnly)
|
|
90
|
+
continue;
|
|
91
|
+
const specifier = statement.specifiers[0];
|
|
92
|
+
if (specifier?.type !== 'ImportNamespaceSpecifier')
|
|
93
|
+
continue;
|
|
94
|
+
const target = resolved.find(([path]) => path === statement.source.value);
|
|
95
|
+
if (!target)
|
|
96
|
+
continue;
|
|
97
|
+
targets.set(specifier.local.value, {
|
|
98
|
+
decl: statement,
|
|
99
|
+
exports: new Set(target[2]),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (targets.size === 0)
|
|
103
|
+
return undefined;
|
|
104
|
+
const { names: references } = (0, references_1.collectReferenceIdentifiers)(ast, {
|
|
105
|
+
runtimeReads: true,
|
|
106
|
+
});
|
|
107
|
+
const kept = new Set();
|
|
108
|
+
const found = [];
|
|
109
|
+
const keyOf = (node) => `${node.span.start}:${node.span.end}`;
|
|
110
|
+
const keep = (node) => {
|
|
111
|
+
node = unwrap(node);
|
|
112
|
+
if (node?.type === 'MemberExpression')
|
|
113
|
+
kept.add(keyOf(node));
|
|
114
|
+
};
|
|
115
|
+
const walk = (n) => {
|
|
116
|
+
if (!n || typeof n !== 'object')
|
|
117
|
+
return;
|
|
118
|
+
if (Array.isArray(n)) {
|
|
119
|
+
n.forEach(walk);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
switch (n.type) {
|
|
123
|
+
case 'CallExpression':
|
|
124
|
+
keep(n.callee);
|
|
125
|
+
break;
|
|
126
|
+
case 'TaggedTemplateExpression':
|
|
127
|
+
keep(n.tag);
|
|
128
|
+
break;
|
|
129
|
+
case 'AssignmentExpression':
|
|
130
|
+
case 'AssignmentPattern':
|
|
131
|
+
case 'ForInStatement':
|
|
132
|
+
case 'ForOfStatement':
|
|
133
|
+
keep(n.left);
|
|
134
|
+
break;
|
|
135
|
+
case 'UpdateExpression':
|
|
136
|
+
case 'RestElement':
|
|
137
|
+
keep(n.argument);
|
|
138
|
+
break;
|
|
139
|
+
case 'UnaryExpression':
|
|
140
|
+
if (n.operator === 'delete')
|
|
141
|
+
keep(n.argument);
|
|
142
|
+
break;
|
|
143
|
+
case 'ArrayPattern':
|
|
144
|
+
n.elements?.forEach(keep);
|
|
145
|
+
break;
|
|
146
|
+
case 'KeyValuePatternProperty':
|
|
147
|
+
keep(n.value);
|
|
148
|
+
break;
|
|
149
|
+
case 'MemberExpression': {
|
|
150
|
+
const { object, property } = n;
|
|
151
|
+
const target = object?.type === 'Identifier' ? targets.get(object.value) : undefined;
|
|
152
|
+
if (target &&
|
|
153
|
+
references.get(object.span.start) === object.value &&
|
|
154
|
+
property?.type === 'Identifier' &&
|
|
155
|
+
target.exports.has(property.value)) {
|
|
156
|
+
found.push({
|
|
157
|
+
local: object.value,
|
|
158
|
+
name: property.value,
|
|
159
|
+
object,
|
|
160
|
+
key: keyOf(n),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
for (const key in n) {
|
|
167
|
+
if (key === 'span')
|
|
168
|
+
continue;
|
|
169
|
+
walk(n[key]);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
ast.body.forEach(walk);
|
|
173
|
+
const rewritten = new Set();
|
|
174
|
+
const names = new Map();
|
|
175
|
+
const dots = new Map();
|
|
176
|
+
const taken = new Map();
|
|
177
|
+
const isTaken = (binding) => {
|
|
178
|
+
let hit = taken.get(binding);
|
|
179
|
+
if (hit === undefined)
|
|
180
|
+
taken.set(binding, (hit = source.includes(binding)));
|
|
181
|
+
return hit;
|
|
182
|
+
};
|
|
183
|
+
for (const { local, name, object, key } of found) {
|
|
184
|
+
const dot = object.span.end - base;
|
|
185
|
+
if (kept.has(key) ||
|
|
186
|
+
buffer[dot] !== 0x2e ||
|
|
187
|
+
buffer.subarray(dot + 1, dot + 1 + Buffer.byteLength(name)).toString() !==
|
|
188
|
+
name ||
|
|
189
|
+
isTaken(`${local}$${name}`)) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
buffer[dot] = 0x24;
|
|
193
|
+
rewritten.add(object.span.start);
|
|
194
|
+
const list = names.get(local) ?? [];
|
|
195
|
+
if (!list.includes(name))
|
|
196
|
+
list.push(name);
|
|
197
|
+
names.set(local, list);
|
|
198
|
+
const at = dots.get(local) ?? [];
|
|
199
|
+
at.push(dot);
|
|
200
|
+
dots.set(local, at);
|
|
201
|
+
}
|
|
202
|
+
if (names.size === 0)
|
|
203
|
+
return undefined;
|
|
204
|
+
let output = buffer.toString('utf-8');
|
|
205
|
+
const originalLength = buffer.length;
|
|
206
|
+
const separated = !output.endsWith('\n');
|
|
207
|
+
if (separated)
|
|
208
|
+
output += '\n';
|
|
209
|
+
let length = Buffer.byteLength(output);
|
|
210
|
+
const imports = [];
|
|
211
|
+
const locals = [...names.keys()].sort((a, b) => targets.get(a).decl.span.start - targets.get(b).decl.span.start);
|
|
212
|
+
for (const local of locals) {
|
|
213
|
+
const { decl } = targets.get(local);
|
|
214
|
+
const raw = buffer
|
|
215
|
+
.subarray(decl.source.span.start - base, decl.source.span.end - base)
|
|
216
|
+
.toString('utf-8');
|
|
217
|
+
const specifiers = names
|
|
218
|
+
.get(local)
|
|
219
|
+
.map((name) => `${name} as ${local}$${name}`)
|
|
220
|
+
.join(', ');
|
|
221
|
+
const statement = `import { ${specifiers} } from ${raw};`;
|
|
222
|
+
output += statement;
|
|
223
|
+
const appendedStart = length;
|
|
224
|
+
length += Buffer.byteLength(statement);
|
|
225
|
+
const unused = [...references].every(([start, name]) => name !== local || rewritten.has(start));
|
|
226
|
+
imports.push({
|
|
227
|
+
local,
|
|
228
|
+
start: decl.span.start - base,
|
|
229
|
+
end: decl.span.end - base,
|
|
230
|
+
appendedStart,
|
|
231
|
+
appendedEnd: length,
|
|
232
|
+
unused,
|
|
233
|
+
dots: dots.get(local),
|
|
234
|
+
bindings: names.get(local).map((name) => `${local}$${name}`),
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return { source: output, originalLength, separated, imports };
|
|
238
|
+
}
|
package/dist/parser.js
CHANGED
|
@@ -55,6 +55,7 @@ exports.resolveExport = resolveExport;
|
|
|
55
55
|
exports.extractOndemandStyles = extractOndemandStyles;
|
|
56
56
|
exports.deepMerge = deepMerge;
|
|
57
57
|
const sourceCache_1 = require("./sourceCache");
|
|
58
|
+
const namespaceImport_1 = require("./namespaceImport");
|
|
58
59
|
const createTheme_1 = require("./createTheme");
|
|
59
60
|
const core_1 = require("@swc/core");
|
|
60
61
|
const path = __importStar(require("path"));
|
|
@@ -1328,9 +1329,16 @@ function runScan(scanCwd, styleProp) {
|
|
|
1328
1329
|
}
|
|
1329
1330
|
catch {
|
|
1330
1331
|
}
|
|
1331
|
-
const
|
|
1332
|
-
|
|
1333
|
-
|
|
1332
|
+
const manifestStamp = fs.statSync(path.join(cwd, 'package.json'), {
|
|
1333
|
+
throwIfNoEntry: false,
|
|
1334
|
+
});
|
|
1335
|
+
if (manifestStamp)
|
|
1336
|
+
configStamp += `:${manifestStamp.mtimeMs}`;
|
|
1337
|
+
const packagesStale = (0, resolver_1.sourcePackagesStale)();
|
|
1338
|
+
const resolutionChanged = packagesStale ||
|
|
1339
|
+
(resolutionConfigStamp !== undefined &&
|
|
1340
|
+
resolutionConfigStamp !== configStamp);
|
|
1341
|
+
if (packagesStale || resolutionConfigStamp !== configStamp)
|
|
1334
1342
|
(0, resolver_1.resetImportResolutionCache)(cwd);
|
|
1335
1343
|
resolutionConfigStamp = configStamp;
|
|
1336
1344
|
const segments = cwd.split(path.sep);
|
|
@@ -1339,18 +1347,26 @@ function runScan(scanCwd, styleProp) {
|
|
|
1339
1347
|
? cwd
|
|
1340
1348
|
: segments.slice(0, dependencyDirectory).join(path.sep) ||
|
|
1341
1349
|
path.parse(cwd).root;
|
|
1342
|
-
const
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1350
|
+
const exclude = [
|
|
1351
|
+
'**/node_modules/**',
|
|
1352
|
+
'**/dist/**',
|
|
1353
|
+
'**/build/**',
|
|
1354
|
+
'**/.next/**',
|
|
1355
|
+
];
|
|
1356
|
+
const files = [
|
|
1357
|
+
...new Set([
|
|
1358
|
+
...rs.globSync(path.join(root, '**/*.{js,jsx,ts,tsx}'), {
|
|
1359
|
+
exclude,
|
|
1360
|
+
cwd: root,
|
|
1361
|
+
sort: true,
|
|
1362
|
+
}),
|
|
1363
|
+
...(0, resolver_1.getSourcePackages)()
|
|
1364
|
+
.flatMap(resolver_1.sourceDirsOf)
|
|
1365
|
+
.flatMap((dir) => rs
|
|
1366
|
+
.globSync('**/*.{js,jsx,ts,tsx}', { exclude, cwd: dir })
|
|
1367
|
+
.map((file) => path.join(dir, file))),
|
|
1368
|
+
]),
|
|
1369
|
+
].sort();
|
|
1354
1370
|
const currentFiles = new Set(files);
|
|
1355
1371
|
const deletedFiles = [];
|
|
1356
1372
|
for (const fp of knownFiles) {
|
|
@@ -1451,6 +1467,7 @@ function runScan(scanCwd, styleProp) {
|
|
|
1451
1467
|
stripFileContributions(filePath, cached);
|
|
1452
1468
|
}
|
|
1453
1469
|
const parsedFiles = [];
|
|
1470
|
+
const expanded = new Map();
|
|
1454
1471
|
for (const filePath of uncachedFiles) {
|
|
1455
1472
|
try {
|
|
1456
1473
|
const stats = fs.statSync(filePath);
|
|
@@ -1478,7 +1495,10 @@ function runScan(scanCwd, styleProp) {
|
|
|
1478
1495
|
};
|
|
1479
1496
|
continue;
|
|
1480
1497
|
}
|
|
1481
|
-
const
|
|
1498
|
+
const namespaces = (0, namespaceImport_1.expandNamespaces)(filePath, source);
|
|
1499
|
+
if (namespaces)
|
|
1500
|
+
expanded.set(filePath, namespaces);
|
|
1501
|
+
const ast = (0, core_1.parseSync)(namespaces?.source ?? source, {
|
|
1482
1502
|
syntax: 'typescript',
|
|
1483
1503
|
tsx: true,
|
|
1484
1504
|
target: 'es2022',
|
|
@@ -1486,7 +1506,7 @@ function runScan(scanCwd, styleProp) {
|
|
|
1486
1506
|
parsedFiles.push({ filePath, ast, mtimeMs: stats.mtimeMs });
|
|
1487
1507
|
}
|
|
1488
1508
|
catch (e) {
|
|
1489
|
-
recordFileError(filePath, e);
|
|
1509
|
+
recordFileError(filePath, (0, namespaceImport_1.asWritten)(expanded.get(filePath), e));
|
|
1490
1510
|
}
|
|
1491
1511
|
}
|
|
1492
1512
|
const jsxPhaseQueue = [];
|
|
@@ -1495,7 +1515,7 @@ function runScan(scanCwd, styleProp) {
|
|
|
1495
1515
|
extractAndCacheExports(file.filePath, file.ast, file.mtimeMs);
|
|
1496
1516
|
}
|
|
1497
1517
|
catch (error) {
|
|
1498
|
-
recordFileError(file.filePath, error);
|
|
1518
|
+
recordFileError(file.filePath, (0, namespaceImport_1.asWritten)(expanded.get(file.filePath), error));
|
|
1499
1519
|
}
|
|
1500
1520
|
}
|
|
1501
1521
|
const byPath = new Map(parsedFiles.map((file) => [file.filePath, file]));
|
|
@@ -1908,7 +1928,7 @@ function runScan(scanCwd, styleProp) {
|
|
|
1908
1928
|
});
|
|
1909
1929
|
}
|
|
1910
1930
|
catch (e) {
|
|
1911
|
-
recordFileError(filePath, e);
|
|
1931
|
+
recordFileError(filePath, (0, namespaceImport_1.asWritten)(expanded.get(filePath), e));
|
|
1912
1932
|
}
|
|
1913
1933
|
}
|
|
1914
1934
|
}
|
|
@@ -2374,7 +2394,7 @@ function runScan(scanCwd, styleProp) {
|
|
|
2374
2394
|
updateDependencyEdges(filePath, prevDependencies, fileCache[filePath].dependencies);
|
|
2375
2395
|
}
|
|
2376
2396
|
catch (e) {
|
|
2377
|
-
recordFileError(entry.filePath, e);
|
|
2397
|
+
recordFileError(entry.filePath, (0, namespaceImport_1.asWritten)(expanded.get(entry.filePath), e));
|
|
2378
2398
|
}
|
|
2379
2399
|
}
|
|
2380
2400
|
for (const entry of jsxPhaseQueue) {
|
|
@@ -2596,7 +2616,10 @@ function refreshExports(filePath) {
|
|
|
2596
2616
|
tsx: true,
|
|
2597
2617
|
target: 'es2022',
|
|
2598
2618
|
});
|
|
2619
|
+
const known = filePath in fileCache;
|
|
2599
2620
|
extractAndCacheExports(filePath, ast, stats.mtimeMs);
|
|
2621
|
+
if (!known)
|
|
2622
|
+
fileCache[filePath].mtimeMs = undefined;
|
|
2600
2623
|
}
|
|
2601
2624
|
}
|
|
2602
2625
|
catch (e) {
|
package/dist/references.d.ts
CHANGED
|
@@ -2,5 +2,8 @@ import type { Module } from '@swc/core';
|
|
|
2
2
|
export interface ReferenceIdentifiers {
|
|
3
3
|
references: Set<number>;
|
|
4
4
|
shorthands: Set<number>;
|
|
5
|
+
names: Map<number, string>;
|
|
5
6
|
}
|
|
6
|
-
export declare function collectReferenceIdentifiers(ast: Module
|
|
7
|
+
export declare function collectReferenceIdentifiers(ast: Module, { runtimeReads }?: {
|
|
8
|
+
runtimeReads?: boolean;
|
|
9
|
+
}): ReferenceIdentifiers;
|
package/dist/references.js
CHANGED
|
@@ -133,11 +133,27 @@ const collectHoistedNames = (n, out) => {
|
|
|
133
133
|
collectHoistedNames(n[key], out);
|
|
134
134
|
}
|
|
135
135
|
};
|
|
136
|
-
function collectReferenceIdentifiers(ast) {
|
|
136
|
+
function collectReferenceIdentifiers(ast, { runtimeReads = false } = {}) {
|
|
137
137
|
const references = new Set();
|
|
138
138
|
const shorthands = new Set();
|
|
139
|
+
const names = new Map();
|
|
139
140
|
const scopes = [];
|
|
140
141
|
const isShadowed = (name) => scopes.some((scope) => scope.has(name));
|
|
142
|
+
const reference = (ident) => {
|
|
143
|
+
if (isShadowed(ident.value))
|
|
144
|
+
return false;
|
|
145
|
+
references.add(ident.span.start);
|
|
146
|
+
names.set(ident.span.start, ident.value);
|
|
147
|
+
return true;
|
|
148
|
+
};
|
|
149
|
+
const elementName = (name) => {
|
|
150
|
+
if (name?.type === 'Identifier' && /^[a-z]/.test(name.value))
|
|
151
|
+
return;
|
|
152
|
+
while (name?.type === 'JSXMemberExpression')
|
|
153
|
+
name = name.object;
|
|
154
|
+
if (name?.type === 'Identifier')
|
|
155
|
+
reference(name);
|
|
156
|
+
};
|
|
141
157
|
const walkPattern = (n) => {
|
|
142
158
|
if (!n || typeof n !== 'object')
|
|
143
159
|
return;
|
|
@@ -205,8 +221,7 @@ function collectReferenceIdentifiers(ast) {
|
|
|
205
221
|
}
|
|
206
222
|
const type = n.type;
|
|
207
223
|
if (type === 'Identifier') {
|
|
208
|
-
|
|
209
|
-
references.add(n.span.start);
|
|
224
|
+
reference(n);
|
|
210
225
|
return;
|
|
211
226
|
}
|
|
212
227
|
if (FUNCTION_TYPES.has(type)) {
|
|
@@ -214,6 +229,10 @@ function collectReferenceIdentifiers(ast) {
|
|
|
214
229
|
return;
|
|
215
230
|
}
|
|
216
231
|
switch (type) {
|
|
232
|
+
case 'ExportNamedDeclaration':
|
|
233
|
+
if (n.source)
|
|
234
|
+
return;
|
|
235
|
+
break;
|
|
217
236
|
case 'BlockStatement':
|
|
218
237
|
walkBlock(n, n.stmts);
|
|
219
238
|
return;
|
|
@@ -278,10 +297,8 @@ function collectReferenceIdentifiers(ast) {
|
|
|
278
297
|
case 'ObjectExpression':
|
|
279
298
|
n.properties?.forEach((prop) => {
|
|
280
299
|
if (prop?.type === 'Identifier') {
|
|
281
|
-
if (
|
|
282
|
-
references.add(prop.span.start);
|
|
300
|
+
if (reference(prop))
|
|
283
301
|
shorthands.add(prop.span.start);
|
|
284
|
-
}
|
|
285
302
|
return;
|
|
286
303
|
}
|
|
287
304
|
walk(prop);
|
|
@@ -306,11 +323,15 @@ function collectReferenceIdentifiers(ast) {
|
|
|
306
323
|
const child = n[key];
|
|
307
324
|
if (child?.type === 'Computed')
|
|
308
325
|
walk(child);
|
|
326
|
+
else if (runtimeReads && type === 'JSXOpeningElement')
|
|
327
|
+
elementName(child);
|
|
328
|
+
else if (runtimeReads && type === 'ExportSpecifier' && key === 'orig')
|
|
329
|
+
reference(child);
|
|
309
330
|
continue;
|
|
310
331
|
}
|
|
311
332
|
walk(n[key]);
|
|
312
333
|
}
|
|
313
334
|
}
|
|
314
335
|
ast.body.forEach(walk);
|
|
315
|
-
return { references, shorthands };
|
|
336
|
+
return { references, shorthands, names };
|
|
316
337
|
}
|
package/dist/resolver.d.ts
CHANGED
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
export interface SourcePackage {
|
|
2
|
+
name: string;
|
|
3
|
+
dir: string;
|
|
4
|
+
exports: unknown;
|
|
5
|
+
linked: string;
|
|
6
|
+
manifestMtime: number | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare function sourceDirsOf(pkg: SourcePackage): string[];
|
|
9
|
+
export declare function sourcePackagesStale(): boolean;
|
|
1
10
|
export declare function resetImportResolutionCache(cwd?: string): void;
|
|
11
|
+
export declare function getSourcePackages(): SourcePackage[];
|
|
2
12
|
export declare function resolveImportPath(importPath: string, importerPath: string): string | null;
|
package/dist/resolver.js
CHANGED
|
@@ -33,12 +33,17 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.sourceDirsOf = sourceDirsOf;
|
|
37
|
+
exports.sourcePackagesStale = sourcePackagesStale;
|
|
36
38
|
exports.resetImportResolutionCache = resetImportResolutionCache;
|
|
39
|
+
exports.getSourcePackages = getSourcePackages;
|
|
37
40
|
exports.resolveImportPath = resolveImportPath;
|
|
38
41
|
const fs = __importStar(require("fs"));
|
|
39
42
|
const path = __importStar(require("path"));
|
|
40
43
|
const CONFIG_DIR = '${configDir}';
|
|
41
44
|
let cachedPathsMatcher = undefined;
|
|
45
|
+
let cachedSourcePackages = undefined;
|
|
46
|
+
const SOURCE_CONDITION = 'plumeria';
|
|
42
47
|
function stripComments(text) {
|
|
43
48
|
let out = '';
|
|
44
49
|
let inString = false;
|
|
@@ -260,8 +265,141 @@ function loadPathsMatcher(configPath) {
|
|
|
260
265
|
const patterns = collectPatterns(configPath, new Set());
|
|
261
266
|
return patterns ? buildMatcher(patterns) : null;
|
|
262
267
|
}
|
|
268
|
+
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
269
|
+
const hasSubpaths = (exports) => isRecord(exports) && Object.keys(exports).some((key) => key.startsWith('.'));
|
|
270
|
+
const sourceTargetOf = (entry) => {
|
|
271
|
+
if (!isRecord(entry))
|
|
272
|
+
return null;
|
|
273
|
+
const target = entry[SOURCE_CONDITION];
|
|
274
|
+
return typeof target === 'string' ? target : null;
|
|
275
|
+
};
|
|
276
|
+
function sourceTarget(pkg, subpath) {
|
|
277
|
+
const { exports } = pkg;
|
|
278
|
+
if (!hasSubpaths(exports))
|
|
279
|
+
return subpath === '.' ? sourceTargetOf(exports) : null;
|
|
280
|
+
if (Object.hasOwn(exports, subpath))
|
|
281
|
+
return sourceTargetOf(exports[subpath]);
|
|
282
|
+
let best = null;
|
|
283
|
+
for (const key of Object.keys(exports)) {
|
|
284
|
+
const star = key.indexOf('*');
|
|
285
|
+
if (star < 0 || key.indexOf('*', star + 1) >= 0)
|
|
286
|
+
continue;
|
|
287
|
+
const suffix = key.slice(star + 1);
|
|
288
|
+
if (subpath.length < key.length ||
|
|
289
|
+
!subpath.startsWith(key.slice(0, star)) ||
|
|
290
|
+
!subpath.endsWith(suffix))
|
|
291
|
+
continue;
|
|
292
|
+
if (best &&
|
|
293
|
+
(star < best.star ||
|
|
294
|
+
(star === best.star && key.length <= best.key.length)))
|
|
295
|
+
continue;
|
|
296
|
+
best = {
|
|
297
|
+
key,
|
|
298
|
+
star,
|
|
299
|
+
matched: subpath.slice(star, subpath.length - suffix.length),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
if (!best)
|
|
303
|
+
return null;
|
|
304
|
+
const target = sourceTargetOf(exports[best.key]);
|
|
305
|
+
return target === null ? null : target.replaceAll('*', best.matched);
|
|
306
|
+
}
|
|
307
|
+
const sourceDirOf = (dir, target) => {
|
|
308
|
+
const star = target.indexOf('*');
|
|
309
|
+
if (star < 0)
|
|
310
|
+
return path.dirname(path.resolve(dir, target));
|
|
311
|
+
const base = target.slice(0, star);
|
|
312
|
+
return base.endsWith('/')
|
|
313
|
+
? path.resolve(dir, base)
|
|
314
|
+
: path.dirname(path.resolve(dir, base));
|
|
315
|
+
};
|
|
316
|
+
function sourceDirsOf(pkg) {
|
|
317
|
+
const entries = hasSubpaths(pkg.exports)
|
|
318
|
+
? Object.values(pkg.exports)
|
|
319
|
+
: [pkg.exports];
|
|
320
|
+
const dirs = [
|
|
321
|
+
...new Set(entries
|
|
322
|
+
.map(sourceTargetOf)
|
|
323
|
+
.filter((target) => target !== null)
|
|
324
|
+
.map((target) => sourceDirOf(pkg.dir, target))
|
|
325
|
+
.filter((dir) => dir === pkg.dir || dir.startsWith(pkg.dir + path.sep))),
|
|
326
|
+
].sort();
|
|
327
|
+
return dirs.filter((dir) => !dirs.some((other) => other !== dir && dir.startsWith(other + path.sep)));
|
|
328
|
+
}
|
|
329
|
+
const manifestMtimeOf = (dir) => fs.statSync(path.join(dir, 'package.json'), { throwIfNoEntry: false })
|
|
330
|
+
?.mtimeMs;
|
|
331
|
+
const realpathOf = (linked) => {
|
|
332
|
+
try {
|
|
333
|
+
return fs.realpathSync(linked);
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
function sourcePackagesStale() {
|
|
340
|
+
return (cachedSourcePackages?.some((pkg) => realpathOf(pkg.linked) !== pkg.dir ||
|
|
341
|
+
manifestMtimeOf(pkg.dir) !== pkg.manifestMtime) ?? false);
|
|
342
|
+
}
|
|
343
|
+
function loadSourcePackages(cwd) {
|
|
344
|
+
const manifest = readConfig(path.join(cwd, 'package.json'));
|
|
345
|
+
if (!manifest)
|
|
346
|
+
return [];
|
|
347
|
+
const names = [
|
|
348
|
+
...new Set([
|
|
349
|
+
'dependencies',
|
|
350
|
+
'devDependencies',
|
|
351
|
+
'peerDependencies',
|
|
352
|
+
'optionalDependencies',
|
|
353
|
+
].flatMap((field) => isRecord(manifest[field]) ? Object.keys(manifest[field]) : [])),
|
|
354
|
+
].sort();
|
|
355
|
+
const packages = [];
|
|
356
|
+
for (const name of names) {
|
|
357
|
+
let linked = null;
|
|
358
|
+
for (let dir = cwd;; dir = path.dirname(dir)) {
|
|
359
|
+
const candidate = path.join(dir, 'node_modules', name);
|
|
360
|
+
if (fs.statSync(candidate, { throwIfNoEntry: false })?.isDirectory()) {
|
|
361
|
+
linked = candidate;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
if (dir === path.dirname(dir))
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
if (!linked)
|
|
368
|
+
continue;
|
|
369
|
+
const dir = fs.realpathSync(linked);
|
|
370
|
+
const exports = readConfig(path.join(dir, 'package.json'))?.exports;
|
|
371
|
+
if (exports === undefined)
|
|
372
|
+
continue;
|
|
373
|
+
const pkg = {
|
|
374
|
+
name,
|
|
375
|
+
dir,
|
|
376
|
+
exports,
|
|
377
|
+
linked,
|
|
378
|
+
manifestMtime: manifestMtimeOf(dir),
|
|
379
|
+
};
|
|
380
|
+
if (sourceDirsOf(pkg).length > 0)
|
|
381
|
+
packages.push(pkg);
|
|
382
|
+
}
|
|
383
|
+
return packages;
|
|
384
|
+
}
|
|
263
385
|
function resetImportResolutionCache(cwd = process.cwd()) {
|
|
264
386
|
cachedPathsMatcher = loadPathsMatcher(path.join(cwd, 'tsconfig.json'));
|
|
387
|
+
cachedSourcePackages = loadSourcePackages(cwd);
|
|
388
|
+
}
|
|
389
|
+
function getSourcePackages() {
|
|
390
|
+
cachedSourcePackages ??= loadSourcePackages(process.cwd());
|
|
391
|
+
return cachedSourcePackages;
|
|
392
|
+
}
|
|
393
|
+
function resolveSourcePackage(importPath) {
|
|
394
|
+
const name = packageNameOf(importPath);
|
|
395
|
+
const pkg = getSourcePackages().find((p) => p.name === name);
|
|
396
|
+
if (!pkg)
|
|
397
|
+
return null;
|
|
398
|
+
const target = sourceTarget(pkg, `.${importPath.slice(name.length)}`);
|
|
399
|
+
if (target === null)
|
|
400
|
+
return null;
|
|
401
|
+
const resolved = path.resolve(pkg.dir, target);
|
|
402
|
+
return isFile(resolved) ? resolved : null;
|
|
265
403
|
}
|
|
266
404
|
function getPathsMatcher() {
|
|
267
405
|
if (cachedPathsMatcher !== undefined)
|
|
@@ -319,6 +457,9 @@ function resolveImportPath(importPath, importerPath) {
|
|
|
319
457
|
return result;
|
|
320
458
|
}
|
|
321
459
|
}
|
|
460
|
+
const sourcePackage = resolveSourcePackage(importPath);
|
|
461
|
+
if (sourcePackage)
|
|
462
|
+
return sourcePackage;
|
|
322
463
|
let currentDir = path.dirname(importerPath);
|
|
323
464
|
while (currentDir !== path.parse(currentDir).root) {
|
|
324
465
|
if (fs.existsSync(path.join(currentDir, 'package.json'))) {
|
package/dist/transform.js
CHANGED
|
@@ -82,6 +82,7 @@ const createTheme_1 = require("./createTheme");
|
|
|
82
82
|
const resolver_1 = require("./resolver");
|
|
83
83
|
const ast_1 = require("./ast");
|
|
84
84
|
const references_1 = require("./references");
|
|
85
|
+
const namespaceImport_1 = require("./namespaceImport");
|
|
85
86
|
const propertyPolicy_1 = require("./propertyPolicy");
|
|
86
87
|
const unwrapExport = (node) => {
|
|
87
88
|
if (node?.type === 'ExportDeclaration')
|
|
@@ -182,9 +183,21 @@ const foldDynamicVars = (vars) => {
|
|
|
182
183
|
});
|
|
183
184
|
};
|
|
184
185
|
const transformSource = async (env) => {
|
|
185
|
-
const
|
|
186
|
+
const scannedTables = (0, parser_1.scanOverlay)(undefined, env.styleProp);
|
|
187
|
+
const namespaces = (0, namespaceImport_1.expandNamespaces)(env.moduleId, env.source);
|
|
188
|
+
try {
|
|
189
|
+
return await transformExpanded(env, scannedTables, namespaces);
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
throw (0, namespaceImport_1.asWritten)(namespaces, error);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
exports.transformSource = transformSource;
|
|
196
|
+
const transformExpanded = async (env, scannedTables, namespaces) => {
|
|
197
|
+
const { root, styleProp, propertyPolicy, isDev, addDependency } = env;
|
|
186
198
|
const classProp = env.classProp ?? 'className';
|
|
187
199
|
const id = env.moduleId;
|
|
200
|
+
const source = namespaces?.source ?? env.source;
|
|
188
201
|
const resourcePath = env.moduleId;
|
|
189
202
|
const baseId = env.filePath;
|
|
190
203
|
const ast = (0, core_1.parseSync)(source, {
|
|
@@ -244,12 +257,13 @@ const transformSource = async (env) => {
|
|
|
244
257
|
}
|
|
245
258
|
}
|
|
246
259
|
};
|
|
247
|
-
const scannedTables = (0, parser_1.scanOverlay)(undefined, styleProp);
|
|
248
260
|
const ownFailure = (0, parser_1.resolveFileError)(baseId, '');
|
|
249
261
|
if (ownFailure)
|
|
250
262
|
throwCompilationError(`[plumeria] ${ownFailure.message}`);
|
|
263
|
+
const appended = namespaces?.originalLength ?? Infinity;
|
|
251
264
|
for (const node of ast.body) {
|
|
252
|
-
if (node.type === 'ImportDeclaration'
|
|
265
|
+
if (node.type === 'ImportDeclaration' &&
|
|
266
|
+
node.span.start - baseByteOffset < appended) {
|
|
253
267
|
const sourcePath = node.source.value;
|
|
254
268
|
const actualPath = (0, resolver_1.resolveImportPath)(sourcePath, id);
|
|
255
269
|
if (actualPath) {
|
|
@@ -2685,17 +2699,109 @@ const transformSource = async (env) => {
|
|
|
2685
2699
|
for (const replacement of replacements)
|
|
2686
2700
|
replacement.content = replacement.content.replaceAll(deferred.token, content);
|
|
2687
2701
|
}
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2702
|
+
const splice = (list) => {
|
|
2703
|
+
let offset = 0;
|
|
2704
|
+
const parts = [];
|
|
2705
|
+
list.forEach((r) => {
|
|
2706
|
+
if (r.start < offset)
|
|
2707
|
+
return;
|
|
2708
|
+
parts.push(sourceBuffer.subarray(offset, r.start));
|
|
2709
|
+
parts.push(Buffer.from(r.content));
|
|
2710
|
+
offset = r.end;
|
|
2711
|
+
});
|
|
2712
|
+
parts.push(sourceBuffer.subarray(offset));
|
|
2713
|
+
return Buffer.concat(parts).toString();
|
|
2714
|
+
};
|
|
2715
|
+
const transformedSource = splice(replacements);
|
|
2716
|
+
const elided = elidedImports(ast, baseByteOffset, replacements, transformedSource);
|
|
2717
|
+
if (namespaces)
|
|
2718
|
+
namespaceElisions(namespaces, replacements, elided, splice);
|
|
2719
|
+
if (elided.length === 0)
|
|
2720
|
+
return { code: transformedSource };
|
|
2721
|
+
replacements.push(...elided);
|
|
2722
|
+
replacements.sort((a, b) => a.start - b.start || b.end - a.end);
|
|
2723
|
+
return { code: splice(replacements) };
|
|
2724
|
+
};
|
|
2725
|
+
const namespaceElisions = (namespaces, replacements, elided, splice) => {
|
|
2726
|
+
const covered = (at) => replacements.some((r) => r.start <= at && at < r.end);
|
|
2727
|
+
const removed = ({ appendedStart }) => elided.some((r) => r.start === appendedStart);
|
|
2728
|
+
const appended = ({ appendedStart, appendedEnd }) => ({
|
|
2729
|
+
start: appendedStart,
|
|
2730
|
+
end: appendedEnd,
|
|
2731
|
+
content: '',
|
|
2696
2732
|
});
|
|
2697
|
-
|
|
2698
|
-
const
|
|
2699
|
-
|
|
2733
|
+
const extra = [];
|
|
2734
|
+
for (const namespace of namespaces.imports) {
|
|
2735
|
+
if (removed(namespace)) {
|
|
2736
|
+
if (namespace.unused)
|
|
2737
|
+
extra.push({ start: namespace.start, end: namespace.end, content: '' });
|
|
2738
|
+
continue;
|
|
2739
|
+
}
|
|
2740
|
+
for (const dot of namespace.dots)
|
|
2741
|
+
if (!covered(dot))
|
|
2742
|
+
extra.push({ start: dot, end: dot + 1, content: '.' });
|
|
2743
|
+
}
|
|
2744
|
+
const pending = namespaces.imports.filter((namespace) => !removed(namespace));
|
|
2745
|
+
const draft = splice([...replacements, ...elided, ...extra, ...pending.map(appended)].sort((a, b) => a.start - b.start || b.end - a.end));
|
|
2746
|
+
let kept = false;
|
|
2747
|
+
for (const namespace of pending) {
|
|
2748
|
+
if (namespace.bindings.some((binding) => draft.includes(binding)))
|
|
2749
|
+
kept = true;
|
|
2750
|
+
else
|
|
2751
|
+
extra.push(appended(namespace));
|
|
2752
|
+
}
|
|
2753
|
+
elided.push(...extra);
|
|
2754
|
+
if (!kept && namespaces.separated) {
|
|
2755
|
+
const first = namespaces.imports[0].appendedStart;
|
|
2756
|
+
for (const replacement of elided)
|
|
2757
|
+
if (replacement.start === first)
|
|
2758
|
+
replacement.start = namespaces.originalLength;
|
|
2759
|
+
}
|
|
2760
|
+
};
|
|
2761
|
+
const elidedImports = (ast, baseByteOffset, replacements, transformedSource) => {
|
|
2762
|
+
if (replacements.length === 0)
|
|
2763
|
+
return [];
|
|
2764
|
+
const overlaps = (start, end) => replacements.some((r) => r.start <= end && r.end >= start);
|
|
2765
|
+
const covered = (position) => replacements.some((r) => r.start <= position && r.end > position);
|
|
2766
|
+
const imports = ast.body.filter((statement) => statement.type === 'ImportDeclaration' &&
|
|
2767
|
+
!statement.typeOnly &&
|
|
2768
|
+
statement.specifiers.length > 0 &&
|
|
2769
|
+
statement.specifiers.every((specifier) => specifier.type !== 'ImportSpecifier' || !specifier.isTypeOnly) &&
|
|
2770
|
+
!overlaps(statement.span.start - baseByteOffset, statement.span.end - baseByteOffset));
|
|
2771
|
+
if (imports.length === 0)
|
|
2772
|
+
return [];
|
|
2773
|
+
const positionsOf = new Map();
|
|
2774
|
+
const { names } = (0, references_1.collectReferenceIdentifiers)(ast, { runtimeReads: true });
|
|
2775
|
+
for (const [start, name] of names) {
|
|
2776
|
+
const positions = positionsOf.get(name);
|
|
2777
|
+
if (positions)
|
|
2778
|
+
positions.push(start - baseByteOffset);
|
|
2779
|
+
else
|
|
2780
|
+
positionsOf.set(name, [start - baseByteOffset]);
|
|
2781
|
+
}
|
|
2782
|
+
const candidates = imports.filter((node) => node.specifiers.every(({ local }) => {
|
|
2783
|
+
const positions = positionsOf.get(local.value);
|
|
2784
|
+
return positions !== undefined && positions.every(covered);
|
|
2785
|
+
}));
|
|
2786
|
+
if (candidates.length === 0)
|
|
2787
|
+
return [];
|
|
2788
|
+
let output;
|
|
2789
|
+
try {
|
|
2790
|
+
output = (0, core_1.parseSync)(transformedSource, {
|
|
2791
|
+
syntax: 'typescript',
|
|
2792
|
+
tsx: true,
|
|
2793
|
+
target: 'es2022',
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
catch {
|
|
2797
|
+
return [];
|
|
2798
|
+
}
|
|
2799
|
+
const remaining = new Set((0, references_1.collectReferenceIdentifiers)(output, { runtimeReads: true }).names.values());
|
|
2800
|
+
return candidates
|
|
2801
|
+
.filter((node) => node.specifiers.every(({ local }) => !remaining.has(local.value)))
|
|
2802
|
+
.map((node) => ({
|
|
2803
|
+
start: node.span.start - baseByteOffset,
|
|
2804
|
+
end: node.span.end - baseByteOffset,
|
|
2805
|
+
content: '',
|
|
2806
|
+
}));
|
|
2700
2807
|
};
|
|
2701
|
-
exports.transformSource = transformSource;
|