@plumeria/utils 18.4.2 → 18.5.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/ast.js +2 -2
- package/dist/dynamicKey.d.ts +2 -1
- package/dist/dynamicKey.js +31 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/parser.d.ts +2 -1
- package/dist/parser.js +444 -76
- package/dist/resolver.d.ts +1 -0
- package/dist/resolver.js +14 -0
- package/dist/types.d.ts +6 -1
- package/package.json +1 -1
package/dist/ast.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getLeadingCommentLength = getLeadingCommentLength;
|
|
4
4
|
function getLeadingCommentLength(source) {
|
|
5
|
-
let i = 0;
|
|
5
|
+
let i = source.charCodeAt(0) === 0xfeff ? 1 : 0;
|
|
6
6
|
const len = source.length;
|
|
7
|
-
if (source.startsWith('#!')) {
|
|
7
|
+
if (source.startsWith('#!', i)) {
|
|
8
8
|
while (i < len && source[i] !== '\n')
|
|
9
9
|
i++;
|
|
10
10
|
}
|
package/dist/dynamicKey.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type NamedParam = {
|
|
|
6
6
|
};
|
|
7
7
|
export type StyleFunction = {
|
|
8
8
|
params: string[];
|
|
9
|
+
unsupportedParams?: boolean;
|
|
9
10
|
named?: NamedParam[];
|
|
10
11
|
defaults?: Record<string, Expression>;
|
|
11
12
|
body: ObjectExpression;
|
|
@@ -35,4 +36,4 @@ export type DynamicStyleResult = {
|
|
|
35
36
|
prop: string;
|
|
36
37
|
}>>;
|
|
37
38
|
};
|
|
38
|
-
export declare const resolveDynamicStyle: (func: StyleFunction, runtimeParams: string[], staticTable: StaticTable, tables: DynamicStyleTables) => DynamicStyleResult | null;
|
|
39
|
+
export declare const resolveDynamicStyle: (func: StyleFunction, runtimeParams: string[], staticTable: StaticTable, tables: DynamicStyleTables, providedParams?: ReadonlySet<string>) => DynamicStyleResult | null;
|
package/dist/dynamicKey.js
CHANGED
|
@@ -71,6 +71,13 @@ const styleFunctionsOf = (objExpr) => {
|
|
|
71
71
|
if (actualBody && actualBody.type === 'ObjectExpression') {
|
|
72
72
|
styleFunctions[prop.key.value] = {
|
|
73
73
|
params,
|
|
74
|
+
unsupportedParams: func.params.some((p) => {
|
|
75
|
+
const pattern = p?.pat ?? p;
|
|
76
|
+
return (pattern?.type === 'ArrayPattern' ||
|
|
77
|
+
pattern?.type === 'RestElement' ||
|
|
78
|
+
(pattern?.type === 'ObjectPattern' &&
|
|
79
|
+
!namedParamsOf(func.params, {})));
|
|
80
|
+
}),
|
|
74
81
|
named: namedParamsOf(func.params, defaults),
|
|
75
82
|
defaults,
|
|
76
83
|
body: actualBody,
|
|
@@ -136,10 +143,14 @@ const applyVarFallback = (style, cssVar, literal) => {
|
|
|
136
143
|
}
|
|
137
144
|
};
|
|
138
145
|
exports.applyVarFallback = applyVarFallback;
|
|
139
|
-
const resolveDynamicStyle = (func, runtimeParams, staticTable, tables) => {
|
|
146
|
+
const resolveDynamicStyle = (func, runtimeParams, staticTable, tables, providedParams) => {
|
|
147
|
+
if (func.unsupportedParams)
|
|
148
|
+
throw new Error('[plumeria] Dynamic styles require named parameters or object destructuring; array and rest parameters are not supported.');
|
|
140
149
|
const tempStaticTable = { ...staticTable };
|
|
141
150
|
const resolveBody = () => (0, parser_1.objectExpressionToObject)(func.body, tempStaticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.createThemeHashTable, tables.createThemeObjectTable, tables.createHashTable, tables.createStaticHashTable, tables.createStaticObjectTable, tables.variantsHashTable);
|
|
142
|
-
const withDefault = Object.entries(func.defaults ?? {}).filter(([param]) =>
|
|
151
|
+
const withDefault = Object.entries(func.defaults ?? {}).filter(([param]) => providedParams
|
|
152
|
+
? !providedParams.has(param)
|
|
153
|
+
: tempStaticTable[param] === undefined);
|
|
143
154
|
const cssVars = {};
|
|
144
155
|
const varParams = Array.from(new Set([...runtimeParams, ...withDefault.map(([param]) => param)]));
|
|
145
156
|
if (varParams.length > 0) {
|
|
@@ -161,10 +172,24 @@ const resolveDynamicStyle = (func, runtimeParams, staticTable, tables) => {
|
|
|
161
172
|
varGroups.set(param, (0, exports.splitVarByUnit)(style, cssVar));
|
|
162
173
|
});
|
|
163
174
|
withDefault.forEach(([param, expr]) => {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
:
|
|
167
|
-
|
|
175
|
+
const resolved = (0, parser_1.objectExpressionToObject)({
|
|
176
|
+
type: 'ObjectExpression',
|
|
177
|
+
span: func.body.span,
|
|
178
|
+
properties: [
|
|
179
|
+
{
|
|
180
|
+
type: 'KeyValueProperty',
|
|
181
|
+
key: {
|
|
182
|
+
type: 'Identifier',
|
|
183
|
+
span: func.body.span,
|
|
184
|
+
value: 'value',
|
|
185
|
+
optional: false,
|
|
186
|
+
},
|
|
187
|
+
value: expr,
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
}, staticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.createThemeHashTable, tables.createThemeObjectTable, tables.createHashTable, tables.createStaticHashTable, tables.createStaticObjectTable, tables.variantsHashTable);
|
|
191
|
+
const literal = resolved.value;
|
|
192
|
+
if (typeof literal !== 'string' && typeof literal !== 'number')
|
|
168
193
|
return;
|
|
169
194
|
(varGroups.get(param) ?? []).forEach(({ cssVar }) => (0, exports.applyVarFallback)(style, cssVar, literal));
|
|
170
195
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { CSSObject, StaticTable, KeyframesHashTable, ViewTransitionHashTable, CreateHashTable, CreateFunctionTable, VariantsHashTable, CreateThemeHashTable, CreateStaticHashTable, } from './types';
|
|
2
|
-
export { objectExpressionToObject, collectLocalConsts, traverse, t, getRootIdentifier, extractOndemandStyles, deepMerge, scanAll, resolveFileError, getFileDependencies, resolveExport, resolveComponentKey, resolveThemeSelector, } from './parser';
|
|
2
|
+
export { objectExpressionToObject, collectLocalConsts, traverse, t, getRootIdentifier, unwrapExpression, extractOndemandStyles, deepMerge, scanAll, resolveFileError, getFileDependencies, resolveExport, resolveComponentKey, resolveThemeSelector, } from './parser';
|
|
3
3
|
export type { StyleRecord } from './create';
|
|
4
4
|
export { getStyleRecords } from './create';
|
|
5
5
|
export type { NamedParam, StyleFunction, StyleFunctions, DynamicStyleTables, DynamicStyleResult, } from './dynamicKey';
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assertPropertyPolicy = exports.resolvePropertyPolicy = exports.DEFAULT_STYLE_PROP = exports.timedAsync = exports.timed = exports.tally = exports.measure = exports.mark = exports.profiling = exports.collectReferenceIdentifiers = exports.getLeadingCommentLength = exports.processVariants = exports.optimizer = exports.resolveImportPath = exports.themeHashOf = exports.getStateWeights = exports.getPseudoElement = exports.getSpecificity = exports.resolveDynamicStyle = exports.applyVarFallback = exports.splitVarByUnit = exports.isUnitlessProp = exports.styleFunctionsOf = exports.getStyleRecords = exports.resolveThemeSelector = exports.resolveComponentKey = exports.resolveExport = exports.getFileDependencies = exports.resolveFileError = exports.scanAll = exports.deepMerge = exports.extractOndemandStyles = exports.getRootIdentifier = exports.t = exports.traverse = exports.collectLocalConsts = exports.objectExpressionToObject = void 0;
|
|
3
|
+
exports.assertPropertyPolicy = exports.resolvePropertyPolicy = exports.DEFAULT_STYLE_PROP = exports.timedAsync = exports.timed = exports.tally = exports.measure = exports.mark = exports.profiling = exports.collectReferenceIdentifiers = exports.getLeadingCommentLength = exports.processVariants = exports.optimizer = exports.resolveImportPath = exports.themeHashOf = exports.getStateWeights = exports.getPseudoElement = exports.getSpecificity = exports.resolveDynamicStyle = exports.applyVarFallback = exports.splitVarByUnit = exports.isUnitlessProp = exports.styleFunctionsOf = exports.getStyleRecords = exports.resolveThemeSelector = exports.resolveComponentKey = exports.resolveExport = exports.getFileDependencies = exports.resolveFileError = exports.scanAll = exports.deepMerge = exports.extractOndemandStyles = exports.unwrapExpression = exports.getRootIdentifier = exports.t = exports.traverse = exports.collectLocalConsts = exports.objectExpressionToObject = void 0;
|
|
4
4
|
var parser_1 = require("./parser");
|
|
5
5
|
Object.defineProperty(exports, "objectExpressionToObject", { enumerable: true, get: function () { return parser_1.objectExpressionToObject; } });
|
|
6
6
|
Object.defineProperty(exports, "collectLocalConsts", { enumerable: true, get: function () { return parser_1.collectLocalConsts; } });
|
|
7
7
|
Object.defineProperty(exports, "traverse", { enumerable: true, get: function () { return parser_1.traverse; } });
|
|
8
8
|
Object.defineProperty(exports, "t", { enumerable: true, get: function () { return parser_1.t; } });
|
|
9
9
|
Object.defineProperty(exports, "getRootIdentifier", { enumerable: true, get: function () { return parser_1.getRootIdentifier; } });
|
|
10
|
+
Object.defineProperty(exports, "unwrapExpression", { enumerable: true, get: function () { return parser_1.unwrapExpression; } });
|
|
10
11
|
Object.defineProperty(exports, "extractOndemandStyles", { enumerable: true, get: function () { return parser_1.extractOndemandStyles; } });
|
|
11
12
|
Object.defineProperty(exports, "deepMerge", { enumerable: true, get: function () { return parser_1.deepMerge; } });
|
|
12
13
|
Object.defineProperty(exports, "scanAll", { enumerable: true, get: function () { return parser_1.scanAll; } });
|
package/dist/parser.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CSSObject, Tables, StaticTable, KeyframesHashTable, ViewTransitionHashTable, CreateHashTable, VariantsHashTable, CreateThemeHashTable, CreateThemeObjectTable, CreateStaticHashTable, CreateStaticObjectTable } from './types';
|
|
2
2
|
import type { Module, Expression, CallExpression, Identifier, KeyValueProperty, StringLiteral, NumericLiteral, BooleanLiteral, ObjectExpression, MemberExpression, TemplateLiteral, BinaryExpression, UnaryExpression, ParenthesisExpression, VariableDeclaration, VariableDeclarator, ExportDeclaration, ConditionalExpression, JSXExpression, ArrowFunctionExpression, FunctionExpression } from '@swc/core';
|
|
3
|
+
export declare function unwrapExpression(node: any): any;
|
|
3
4
|
export declare const getRootIdentifier: (node: Expression) => string | null;
|
|
4
5
|
export declare function resolveComponentKey(nameNode: any, filePath: string, localImports: Record<string, {
|
|
5
6
|
actualPath: string;
|
|
@@ -41,7 +42,7 @@ export declare function resolveFileError(actualPath: string, importedName: strin
|
|
|
41
42
|
filePath: string;
|
|
42
43
|
message: string;
|
|
43
44
|
} | undefined;
|
|
44
|
-
export declare function scanAll(): Tables;
|
|
45
|
+
export declare function scanAll(scanCwd?: string): Tables;
|
|
45
46
|
export declare function getFileDependencies(filePath: string): string[];
|
|
46
47
|
export declare function resolveExport(filePath: string, exportName: string, visited?: Set<string>): {
|
|
47
48
|
filePath: string;
|
package/dist/parser.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.t = exports.getRootIdentifier = void 0;
|
|
37
|
+
exports.unwrapExpression = unwrapExpression;
|
|
37
38
|
exports.resolveComponentKey = resolveComponentKey;
|
|
38
39
|
exports.traverse = traverse;
|
|
39
40
|
exports.objectExpressionToObject = objectExpressionToObject;
|
|
@@ -55,12 +56,33 @@ const viewTransition_1 = require("./viewTransition");
|
|
|
55
56
|
const create_1 = require("./create");
|
|
56
57
|
const dynamicKey_1 = require("./dynamicKey");
|
|
57
58
|
const resolver_1 = require("./resolver");
|
|
59
|
+
function unwrapExpression(node) {
|
|
60
|
+
while (node &&
|
|
61
|
+
[
|
|
62
|
+
'ParenthesisExpression',
|
|
63
|
+
'TsConstAssertion',
|
|
64
|
+
'TsAsExpression',
|
|
65
|
+
'TsSatisfiesExpression',
|
|
66
|
+
'TsNonNullExpression',
|
|
67
|
+
'TsTypeAssertion',
|
|
68
|
+
].includes(node.type))
|
|
69
|
+
node = node.expression;
|
|
70
|
+
if (node?.type === 'OptionalChainingExpression')
|
|
71
|
+
return unwrapExpression(node.base);
|
|
72
|
+
if (node?.type === 'MemberExpression') {
|
|
73
|
+
const object = unwrapExpression(node.object);
|
|
74
|
+
if (object !== node.object)
|
|
75
|
+
return { ...node, object };
|
|
76
|
+
}
|
|
77
|
+
return node;
|
|
78
|
+
}
|
|
58
79
|
const toIdent = (value) => value.replace(/[^A-Za-z0-9-]/g, '');
|
|
59
80
|
const getMarkerVar = (id, pseudo) => {
|
|
60
81
|
const hash = (0, zss_engine_1.genBase36Hash)({ [id]: pseudo }, 1, 8);
|
|
61
82
|
return `--${hash}-${toIdent(id)}-${toIdent(pseudo.split('(')[0])}`;
|
|
62
83
|
};
|
|
63
84
|
const getRootIdentifier = (node) => {
|
|
85
|
+
node = unwrapExpression(node);
|
|
64
86
|
if (exports.t.isIdentifier(node)) {
|
|
65
87
|
return node.value;
|
|
66
88
|
}
|
|
@@ -73,9 +95,6 @@ const getRootIdentifier = (node) => {
|
|
|
73
95
|
return (0, exports.getRootIdentifier)(callee);
|
|
74
96
|
}
|
|
75
97
|
}
|
|
76
|
-
if (node.type === 'ParenthesisExpression') {
|
|
77
|
-
return (0, exports.getRootIdentifier)(node.expression);
|
|
78
|
-
}
|
|
79
98
|
return null;
|
|
80
99
|
};
|
|
81
100
|
exports.getRootIdentifier = getRootIdentifier;
|
|
@@ -189,21 +208,14 @@ function traverse(node, visitor) {
|
|
|
189
208
|
}
|
|
190
209
|
walk(node);
|
|
191
210
|
}
|
|
192
|
-
const PROJECT_ROOT = process.cwd().split('node_modules')[0];
|
|
193
|
-
const PATTERN_PATH = path.join(PROJECT_ROOT, '**/*.{js,jsx,ts,tsx}');
|
|
194
|
-
const GLOB_OPTIONS = {
|
|
195
|
-
exclude: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.next/**'],
|
|
196
|
-
cwd: PROJECT_ROOT,
|
|
197
|
-
sort: true,
|
|
198
|
-
};
|
|
199
211
|
function objectExpressionToObject(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createHashTable, createStaticHashTable, createStaticObjectTable, variantsHashTable, resolveVariable) {
|
|
200
|
-
const obj =
|
|
212
|
+
const obj = Object.create(null);
|
|
201
213
|
node.properties.forEach((prop) => {
|
|
202
214
|
if (prop.type === 'SpreadElement') {
|
|
203
215
|
const arg = prop.arguments;
|
|
204
216
|
const spreadVal = evaluateExpression(arg, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
205
217
|
if (typeof spreadVal === 'object' && spreadVal !== null) {
|
|
206
|
-
Object.assign(obj,
|
|
218
|
+
Object.assign(obj, spreadVal);
|
|
207
219
|
}
|
|
208
220
|
return;
|
|
209
221
|
}
|
|
@@ -226,16 +238,20 @@ function objectExpressionToObject(node, staticTable, keyframesHashTable, viewTra
|
|
|
226
238
|
const key = getPropertyKey(prop.key, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
227
239
|
if (!key)
|
|
228
240
|
return;
|
|
229
|
-
const val = prop.value;
|
|
241
|
+
const val = unwrapExpression(prop.value);
|
|
230
242
|
if (exports.t.isIdentifier(val) || exports.t.isMemberExpression(val)) {
|
|
231
243
|
if (resolveVariable && exports.t.isMemberExpression(val)) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
244
|
+
const root = (0, exports.getRootIdentifier)(val);
|
|
245
|
+
const resolved = root ? resolveVariable(root) : undefined;
|
|
246
|
+
if (resolved !== undefined && root) {
|
|
247
|
+
const member = resolveStaticTableMemberExpression(val, {
|
|
248
|
+
...staticTable,
|
|
249
|
+
[root]: resolved,
|
|
250
|
+
});
|
|
251
|
+
if (member === undefined)
|
|
252
|
+
throw new Error(`[plumeria] Unknown style member on ${root}.`);
|
|
253
|
+
obj[key] = member;
|
|
254
|
+
return;
|
|
239
255
|
}
|
|
240
256
|
}
|
|
241
257
|
const resolvedKeyframe = resolveKeyframesTableMemberExpression(val, keyframesHashTable);
|
|
@@ -275,7 +291,7 @@ function objectExpressionToObject(node, staticTable, keyframesHashTable, viewTra
|
|
|
275
291
|
obj[key] = val.value;
|
|
276
292
|
}
|
|
277
293
|
else if (exports.t.isUnaryExpression(val)) {
|
|
278
|
-
obj[key] =
|
|
294
|
+
obj[key] = evaluateExpression(val, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
279
295
|
}
|
|
280
296
|
else if (exports.t.isObjectExpression(val)) {
|
|
281
297
|
obj[key] = objectExpressionToObject(val, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createHashTable, createStaticHashTable, createStaticObjectTable, variantsHashTable, resolveVariable);
|
|
@@ -331,7 +347,7 @@ function collectLocalConsts(ast) {
|
|
|
331
347
|
if (!decls.has(name) || visiting.has(name))
|
|
332
348
|
return undefined;
|
|
333
349
|
visiting.add(name);
|
|
334
|
-
const init = decls.get(name);
|
|
350
|
+
const init = unwrapExpression(decls.get(name));
|
|
335
351
|
let result;
|
|
336
352
|
try {
|
|
337
353
|
if (exports.t.isStringLiteral(init) ||
|
|
@@ -431,6 +447,10 @@ function literalFromValue(value, span) {
|
|
|
431
447
|
function inlineOuterScope(objExpression, resolveProperty) {
|
|
432
448
|
const rewriteProperty = (prop, params) => {
|
|
433
449
|
if (prop.type === 'KeyValueProperty') {
|
|
450
|
+
if (prop.key?.type === 'Computed') {
|
|
451
|
+
const expression = rewriteExpression(prop.key.expression, params);
|
|
452
|
+
prop = { ...prop, key: { ...prop.key, expression } };
|
|
453
|
+
}
|
|
434
454
|
const val = prop.value;
|
|
435
455
|
if (val.type === 'ObjectExpression') {
|
|
436
456
|
const rewritten = rewriteObject(val, params);
|
|
@@ -549,11 +569,26 @@ function inlineOuterScope(objExpression, resolveProperty) {
|
|
|
549
569
|
prop.value.type !== 'FunctionExpression'))
|
|
550
570
|
return prop;
|
|
551
571
|
const func = prop.value;
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
572
|
+
const names = paramNames(func);
|
|
573
|
+
const rewriteParam = (p) => {
|
|
574
|
+
if (!p || typeof p !== 'object')
|
|
575
|
+
return p;
|
|
576
|
+
if (p.type === 'AssignmentPattern')
|
|
577
|
+
return { ...p, right: rewriteExpression(p.right, names) };
|
|
578
|
+
if (p.type === 'AssignmentPatternProperty' && p.value)
|
|
579
|
+
return { ...p, value: rewriteExpression(p.value, names) };
|
|
580
|
+
if (p.pat)
|
|
581
|
+
return { ...p, pat: rewriteParam(p.pat) };
|
|
582
|
+
if (p.properties)
|
|
583
|
+
return { ...p, properties: p.properties.map(rewriteParam) };
|
|
584
|
+
if (p.type === 'KeyValuePatternProperty')
|
|
585
|
+
return { ...p, value: rewriteParam(p.value) };
|
|
586
|
+
return p;
|
|
587
|
+
};
|
|
588
|
+
const params = func.params.map(rewriteParam);
|
|
589
|
+
const body = rewriteBody(func.body, names);
|
|
555
590
|
changed = true;
|
|
556
|
-
return { ...prop, value: { ...func, body } };
|
|
591
|
+
return { ...prop, value: { ...func, body, params } };
|
|
557
592
|
});
|
|
558
593
|
return changed ? { ...objExpression, properties } : objExpression;
|
|
559
594
|
}
|
|
@@ -617,6 +652,8 @@ function evaluateTemplateLiteral(node, staticTable, keyframesHashTable, viewTran
|
|
|
617
652
|
if (i < node.expressions.length) {
|
|
618
653
|
const expr = node.expressions[i];
|
|
619
654
|
const evaluatedExpr = evaluateExpression(expr, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
655
|
+
if (evaluatedExpr === null || typeof evaluatedExpr === 'object')
|
|
656
|
+
throw new Error('[plumeria] Template value cannot be resolved to a primitive.');
|
|
620
657
|
result += String(evaluatedExpr);
|
|
621
658
|
}
|
|
622
659
|
}
|
|
@@ -624,7 +661,15 @@ function evaluateTemplateLiteral(node, staticTable, keyframesHashTable, viewTran
|
|
|
624
661
|
}
|
|
625
662
|
function evaluateBinaryExpression(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable) {
|
|
626
663
|
const left = evaluateExpression(node.left, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
664
|
+
if (node.operator === '&&' && !left)
|
|
665
|
+
return left;
|
|
666
|
+
if (node.operator === '||' && left)
|
|
667
|
+
return left;
|
|
668
|
+
if (node.operator === '??' && left !== null)
|
|
669
|
+
return left;
|
|
627
670
|
const right = evaluateExpression(node.right, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
671
|
+
if (['&&', '||', '??'].includes(node.operator))
|
|
672
|
+
return right;
|
|
628
673
|
if (typeof left === 'number' && typeof right === 'number') {
|
|
629
674
|
if (node.operator === '+') {
|
|
630
675
|
return left + right;
|
|
@@ -663,9 +708,19 @@ function evaluateBinaryExpression(node, staticTable, keyframesHashTable, viewTra
|
|
|
663
708
|
return left | right;
|
|
664
709
|
}
|
|
665
710
|
}
|
|
666
|
-
if (node.operator === '+'
|
|
711
|
+
if (node.operator === '+' &&
|
|
712
|
+
left !== null &&
|
|
713
|
+
right !== null &&
|
|
714
|
+
typeof left !== 'object' &&
|
|
715
|
+
typeof right !== 'object') {
|
|
667
716
|
return String(left) + String(right);
|
|
668
717
|
}
|
|
718
|
+
if (['+', '-', '*', '/', '%', '**', '&', '<<', '>>', '>>>', '^', '|'].includes(node.operator)) {
|
|
719
|
+
const expected = node.operator === '+' ? 'non-null primitive' : 'numeric';
|
|
720
|
+
const leftType = left === null ? 'null' : typeof left;
|
|
721
|
+
const rightType = right === null ? 'null' : typeof right;
|
|
722
|
+
throw new Error(`[plumeria] Binary operator ${node.operator} requires ${expected} operands; received ${leftType} and ${rightType}.`);
|
|
723
|
+
}
|
|
669
724
|
throw new Error(`[plumeria] Unsupported binary operator: ${node.operator}`);
|
|
670
725
|
}
|
|
671
726
|
function evaluateCallExpression(node, staticTable) {
|
|
@@ -708,6 +763,7 @@ function evaluateCallExpression(node, staticTable) {
|
|
|
708
763
|
return null;
|
|
709
764
|
}
|
|
710
765
|
function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable) {
|
|
766
|
+
node = unwrapExpression(node);
|
|
711
767
|
if (exports.t.isCallExpression(node)) {
|
|
712
768
|
return evaluateCallExpression(node, staticTable);
|
|
713
769
|
}
|
|
@@ -739,7 +795,7 @@ function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitio
|
|
|
739
795
|
return createStaticObjectTable[hash];
|
|
740
796
|
}
|
|
741
797
|
}
|
|
742
|
-
|
|
798
|
+
throw new Error(`[plumeria] Cannot resolve static value: ${node.value}`);
|
|
743
799
|
}
|
|
744
800
|
if (exports.t.isMemberExpression(node)) {
|
|
745
801
|
const resolved = resolveStaticTableMemberExpression(node, staticTable);
|
|
@@ -754,7 +810,7 @@ function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitio
|
|
|
754
810
|
if (resolvedStatic !== undefined) {
|
|
755
811
|
return resolvedStatic;
|
|
756
812
|
}
|
|
757
|
-
|
|
813
|
+
throw new Error('[plumeria] Cannot resolve static member expression.');
|
|
758
814
|
}
|
|
759
815
|
if (exports.t.isBinaryExpression(node)) {
|
|
760
816
|
return evaluateBinaryExpression(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
@@ -763,29 +819,24 @@ function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitio
|
|
|
763
819
|
return evaluateTemplateLiteral(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
764
820
|
}
|
|
765
821
|
if (exports.t.isUnaryExpression(node)) {
|
|
766
|
-
|
|
822
|
+
const value = evaluateExpression(node.argument, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
823
|
+
if (node.operator === '!')
|
|
824
|
+
return !value;
|
|
825
|
+
if (typeof value === 'number') {
|
|
826
|
+
if (node.operator === '-')
|
|
827
|
+
return -value;
|
|
828
|
+
if (node.operator === '+')
|
|
829
|
+
return value;
|
|
830
|
+
if (node.operator === '~')
|
|
831
|
+
return ~value;
|
|
832
|
+
}
|
|
833
|
+
throw new Error(`[plumeria] Unsupported unary operand for ${node.operator}`);
|
|
767
834
|
}
|
|
768
835
|
if (exports.t.isParenthesisExpression(node)) {
|
|
769
836
|
return evaluateExpression(node.expression, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
770
837
|
}
|
|
771
838
|
throw new Error(`[plumeria] Unsupported expression type: ${node.type}`);
|
|
772
839
|
}
|
|
773
|
-
function evaluateUnaryExpression(node) {
|
|
774
|
-
const arg = node.argument;
|
|
775
|
-
switch (node.operator) {
|
|
776
|
-
case '-':
|
|
777
|
-
if (exports.t.isNumericLiteral(arg))
|
|
778
|
-
return -arg.value;
|
|
779
|
-
break;
|
|
780
|
-
case '+':
|
|
781
|
-
if (exports.t.isNumericLiteral(arg))
|
|
782
|
-
return +arg.value;
|
|
783
|
-
break;
|
|
784
|
-
default:
|
|
785
|
-
throw new Error(`[plumeria] Unsupported unary operator: ${node.operator}`);
|
|
786
|
-
}
|
|
787
|
-
throw new Error(`[plumeria] Unsupported UnaryExpression argument type: ${arg.type}`);
|
|
788
|
-
}
|
|
789
840
|
function resolveKeyframesTableMemberExpression(node, keyframesHashTable) {
|
|
790
841
|
if (exports.t.isIdentifier(node)) {
|
|
791
842
|
return keyframesHashTable[node.value];
|
|
@@ -810,11 +861,6 @@ function resolveCreateTableMemberExpression(node, createHashTable) {
|
|
|
810
861
|
if (exports.t.isIdentifier(node)) {
|
|
811
862
|
return createHashTable[node.value];
|
|
812
863
|
}
|
|
813
|
-
if (exports.t.isMemberExpression(node)) {
|
|
814
|
-
if (exports.t.isIdentifier(node.object)) {
|
|
815
|
-
return createHashTable[node.object.value];
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
864
|
}
|
|
819
865
|
function resolveVariantsTableMemberExpression(node, variantsHashTable) {
|
|
820
866
|
if (exports.t.isIdentifier(node)) {
|
|
@@ -830,16 +876,29 @@ function resolveStaticTableMemberExpression(node, staticTable) {
|
|
|
830
876
|
const keys = [];
|
|
831
877
|
let current = node;
|
|
832
878
|
while (exports.t.isMemberExpression(current)) {
|
|
833
|
-
|
|
879
|
+
const property = current.property;
|
|
880
|
+
const key = exports.t.isIdentifier(property)
|
|
881
|
+
? property.value
|
|
882
|
+
: property.type === 'Computed'
|
|
883
|
+
? unwrapExpression(property.expression)
|
|
884
|
+
: undefined;
|
|
885
|
+
const value = typeof key === 'string'
|
|
886
|
+
? key
|
|
887
|
+
: exports.t.isStringLiteral(key) || exports.t.isNumericLiteral(key)
|
|
888
|
+
? String(key.value)
|
|
889
|
+
: exports.t.isIdentifier(key)
|
|
890
|
+
? staticTable[key.value]
|
|
891
|
+
: undefined;
|
|
892
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
834
893
|
return undefined;
|
|
835
|
-
keys.unshift(
|
|
836
|
-
current = current.object;
|
|
894
|
+
keys.unshift(String(value));
|
|
895
|
+
current = unwrapExpression(current.object);
|
|
837
896
|
}
|
|
838
897
|
if (!exports.t.isIdentifier(current))
|
|
839
898
|
return undefined;
|
|
840
899
|
let value = staticTable[current.value];
|
|
841
900
|
for (const key of keys) {
|
|
842
|
-
if (!value || typeof value !== 'object' || !(key
|
|
901
|
+
if (!value || typeof value !== 'object' || !Object.hasOwn(value, key))
|
|
843
902
|
return undefined;
|
|
844
903
|
value = value[key];
|
|
845
904
|
}
|
|
@@ -907,8 +966,9 @@ const fileErrors = {};
|
|
|
907
966
|
const DIAGNOSTIC_PREFIX = '[plumeria] ';
|
|
908
967
|
function recordFileError(filePath, e) {
|
|
909
968
|
const message = e instanceof Error ? e.message : String(e);
|
|
910
|
-
|
|
911
|
-
|
|
969
|
+
fileErrors[filePath] = message.startsWith(DIAGNOSTIC_PREFIX)
|
|
970
|
+
? message.slice(DIAGNOSTIC_PREFIX.length)
|
|
971
|
+
: message;
|
|
912
972
|
}
|
|
913
973
|
function resolveFileError(actualPath, importedName) {
|
|
914
974
|
const resolved = resolveExport(actualPath, importedName);
|
|
@@ -960,8 +1020,34 @@ const globalAgregatedTables = {
|
|
|
960
1020
|
componentPropsTable: {},
|
|
961
1021
|
};
|
|
962
1022
|
let hasComputedOnce = false;
|
|
1023
|
+
let resolutionConfigStamp;
|
|
1024
|
+
let scannedCwd;
|
|
963
1025
|
const objectTableOwners = new Map();
|
|
1026
|
+
const fileObjectContributions = new Map();
|
|
1027
|
+
function snapshotTables() {
|
|
1028
|
+
return Object.fromEntries(Object.entries(globalAgregatedTables).map(([key, value]) => [
|
|
1029
|
+
key,
|
|
1030
|
+
{ ...value },
|
|
1031
|
+
]));
|
|
1032
|
+
}
|
|
1033
|
+
function releaseFileObjects(filePath) {
|
|
1034
|
+
const contributions = fileObjectContributions.get(filePath);
|
|
1035
|
+
if (!contributions)
|
|
1036
|
+
return;
|
|
1037
|
+
for (const [tableName, hashes] of contributions) {
|
|
1038
|
+
for (const hash of hashes)
|
|
1039
|
+
releaseObjectOwner(tableName, hash, filePath, globalAgregatedTables[tableName]);
|
|
1040
|
+
}
|
|
1041
|
+
fileObjectContributions.delete(filePath);
|
|
1042
|
+
}
|
|
964
1043
|
function registerObjectOwner(tableName, hash, filePath) {
|
|
1044
|
+
let contributions = fileObjectContributions.get(filePath);
|
|
1045
|
+
if (!contributions)
|
|
1046
|
+
fileObjectContributions.set(filePath, (contributions = new Map()));
|
|
1047
|
+
let hashes = contributions.get(tableName);
|
|
1048
|
+
if (!hashes)
|
|
1049
|
+
contributions.set(tableName, (hashes = new Set()));
|
|
1050
|
+
hashes.add(hash);
|
|
965
1051
|
const key = `${tableName}:${hash}`;
|
|
966
1052
|
let owners = objectTableOwners.get(key);
|
|
967
1053
|
if (!owners) {
|
|
@@ -982,8 +1068,17 @@ function releaseObjectOwner(tableName, hash, filePath, table) {
|
|
|
982
1068
|
}
|
|
983
1069
|
}
|
|
984
1070
|
function stripFileContributions(filePath, cached) {
|
|
985
|
-
|
|
986
|
-
|
|
1071
|
+
releaseFileObjects(filePath);
|
|
1072
|
+
for (const [name, table] of Object.entries(globalAgregatedTables)) {
|
|
1073
|
+
if (name.endsWith('ObjectTable') ||
|
|
1074
|
+
name === 'createAtomicMapTable' ||
|
|
1075
|
+
name === 'createThemeSelectorTable' ||
|
|
1076
|
+
name === 'componentPropsTable')
|
|
1077
|
+
continue;
|
|
1078
|
+
for (const key of Object.keys(table))
|
|
1079
|
+
if (key.startsWith(`${filePath}-`))
|
|
1080
|
+
delete table[key];
|
|
1081
|
+
}
|
|
987
1082
|
const localTables = globalAgregatedTables;
|
|
988
1083
|
for (const key of Object.keys(cached.staticTable)) {
|
|
989
1084
|
delete localTables.staticTable[`${filePath}-${key}`];
|
|
@@ -1055,12 +1150,45 @@ function stripFileContributions(filePath, cached) {
|
|
|
1055
1150
|
}
|
|
1056
1151
|
}
|
|
1057
1152
|
}
|
|
1058
|
-
function scanAll() {
|
|
1059
|
-
|
|
1060
|
-
|
|
1153
|
+
function scanAll(scanCwd = process.cwd()) {
|
|
1154
|
+
const cwd = path.resolve(scanCwd);
|
|
1155
|
+
if (hasComputedOnce &&
|
|
1156
|
+
process.env.NODE_ENV === 'production' &&
|
|
1157
|
+
scannedCwd === cwd) {
|
|
1158
|
+
return snapshotTables();
|
|
1061
1159
|
}
|
|
1062
1160
|
const localTables = globalAgregatedTables;
|
|
1063
|
-
|
|
1161
|
+
scannedCwd = cwd;
|
|
1162
|
+
const configPath = path.join(cwd, 'tsconfig.json');
|
|
1163
|
+
let configStamp = configPath;
|
|
1164
|
+
try {
|
|
1165
|
+
configStamp += `:${fs.statSync(configPath).mtimeMs}`;
|
|
1166
|
+
}
|
|
1167
|
+
catch {
|
|
1168
|
+
}
|
|
1169
|
+
const resolutionChanged = resolutionConfigStamp !== undefined &&
|
|
1170
|
+
resolutionConfigStamp !== configStamp;
|
|
1171
|
+
if (resolutionConfigStamp !== configStamp)
|
|
1172
|
+
(0, resolver_1.resetImportResolutionCache)(cwd);
|
|
1173
|
+
resolutionConfigStamp = configStamp;
|
|
1174
|
+
const segments = cwd.split(path.sep);
|
|
1175
|
+
const dependencyDirectory = segments.indexOf('node_modules');
|
|
1176
|
+
const root = dependencyDirectory < 0
|
|
1177
|
+
? cwd
|
|
1178
|
+
: segments.slice(0, dependencyDirectory).join(path.sep) ||
|
|
1179
|
+
path.parse(cwd).root;
|
|
1180
|
+
const files = rs
|
|
1181
|
+
.globSync(path.join(root, '**/*.{js,jsx,ts,tsx}'), {
|
|
1182
|
+
exclude: [
|
|
1183
|
+
'**/node_modules/**',
|
|
1184
|
+
'**/dist/**',
|
|
1185
|
+
'**/build/**',
|
|
1186
|
+
'**/.next/**',
|
|
1187
|
+
],
|
|
1188
|
+
cwd: root,
|
|
1189
|
+
sort: true,
|
|
1190
|
+
})
|
|
1191
|
+
.sort();
|
|
1064
1192
|
const currentFiles = new Set(files);
|
|
1065
1193
|
const deletedFiles = [];
|
|
1066
1194
|
for (const fp of knownFiles) {
|
|
@@ -1074,7 +1202,7 @@ function scanAll() {
|
|
|
1074
1202
|
try {
|
|
1075
1203
|
const stats = fs.statSync(filePath);
|
|
1076
1204
|
const cached = fileCache[filePath];
|
|
1077
|
-
if (!cached || cached.mtimeMs !== stats.mtimeMs) {
|
|
1205
|
+
if (resolutionChanged || !cached || cached.mtimeMs !== stats.mtimeMs) {
|
|
1078
1206
|
invalidated.add(filePath);
|
|
1079
1207
|
queue.push(filePath);
|
|
1080
1208
|
}
|
|
@@ -1084,6 +1212,26 @@ function scanAll() {
|
|
|
1084
1212
|
queue.push(filePath);
|
|
1085
1213
|
}
|
|
1086
1214
|
}
|
|
1215
|
+
for (const dependency of dependentsMap.keys()) {
|
|
1216
|
+
if (currentFiles.has(dependency))
|
|
1217
|
+
continue;
|
|
1218
|
+
const cached = fileCache[dependency];
|
|
1219
|
+
if (!cached)
|
|
1220
|
+
continue;
|
|
1221
|
+
let changed;
|
|
1222
|
+
try {
|
|
1223
|
+
changed =
|
|
1224
|
+
(cached.exportsMtimeMs ?? cached.mtimeMs) !==
|
|
1225
|
+
fs.statSync(dependency).mtimeMs;
|
|
1226
|
+
}
|
|
1227
|
+
catch {
|
|
1228
|
+
changed = true;
|
|
1229
|
+
}
|
|
1230
|
+
if (changed) {
|
|
1231
|
+
invalidated.add(dependency);
|
|
1232
|
+
queue.push(dependency);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1087
1235
|
for (const fp of deletedFiles) {
|
|
1088
1236
|
invalidated.add(fp);
|
|
1089
1237
|
queue.push(fp);
|
|
@@ -1101,7 +1249,7 @@ function scanAll() {
|
|
|
1101
1249
|
}
|
|
1102
1250
|
}
|
|
1103
1251
|
if (invalidated.size === 0 && hasComputedOnce) {
|
|
1104
|
-
return
|
|
1252
|
+
return snapshotTables();
|
|
1105
1253
|
}
|
|
1106
1254
|
for (const fp of deletedFiles) {
|
|
1107
1255
|
const cached = fileCache[fp];
|
|
@@ -1154,9 +1302,34 @@ function scanAll() {
|
|
|
1154
1302
|
parsedFiles.push({ filePath, ast, mtimeMs: stats.mtimeMs });
|
|
1155
1303
|
}
|
|
1156
1304
|
catch (e) {
|
|
1305
|
+
recordFileError(filePath, e);
|
|
1157
1306
|
}
|
|
1158
1307
|
}
|
|
1159
1308
|
const jsxPhaseQueue = [];
|
|
1309
|
+
for (const file of parsedFiles) {
|
|
1310
|
+
try {
|
|
1311
|
+
extractAndCacheExports(file.filePath, file.ast, file.mtimeMs);
|
|
1312
|
+
}
|
|
1313
|
+
catch (error) {
|
|
1314
|
+
recordFileError(file.filePath, error);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
const byPath = new Map(parsedFiles.map((file) => [file.filePath, file]));
|
|
1318
|
+
const ordered = [];
|
|
1319
|
+
const visitedFiles = new Set();
|
|
1320
|
+
const visitFile = (file) => {
|
|
1321
|
+
if (visitedFiles.has(file.filePath))
|
|
1322
|
+
return;
|
|
1323
|
+
visitedFiles.add(file.filePath);
|
|
1324
|
+
for (const dependency of getFileDependencies(file.filePath)) {
|
|
1325
|
+
const imported = byPath.get(dependency);
|
|
1326
|
+
if (imported)
|
|
1327
|
+
visitFile(imported);
|
|
1328
|
+
}
|
|
1329
|
+
ordered.push(file);
|
|
1330
|
+
};
|
|
1331
|
+
parsedFiles.forEach(visitFile);
|
|
1332
|
+
parsedFiles.splice(0, parsedFiles.length, ...ordered);
|
|
1160
1333
|
for (let passNumber = 1; passNumber <= 2; passNumber++) {
|
|
1161
1334
|
const isFirstPass = passNumber === 1;
|
|
1162
1335
|
for (const { filePath, ast, mtimeMs } of parsedFiles) {
|
|
@@ -1267,6 +1440,8 @@ function scanAll() {
|
|
|
1267
1440
|
if (localTables.createHashTable[uniqueKey]) {
|
|
1268
1441
|
const hash = localTables.createHashTable[uniqueKey];
|
|
1269
1442
|
localCreateHashTable[localName] = hash;
|
|
1443
|
+
localCreateObjectTable[hash] =
|
|
1444
|
+
localTables.createObjectTable[hash];
|
|
1270
1445
|
}
|
|
1271
1446
|
}
|
|
1272
1447
|
});
|
|
@@ -1290,6 +1465,28 @@ function scanAll() {
|
|
|
1290
1465
|
}
|
|
1291
1466
|
}
|
|
1292
1467
|
}
|
|
1468
|
+
const initializers = new Map();
|
|
1469
|
+
for (const statement of ast.body) {
|
|
1470
|
+
const declaration = statement.type === 'ExportDeclaration'
|
|
1471
|
+
? statement.declaration
|
|
1472
|
+
: statement;
|
|
1473
|
+
if (exports.t.isVariableDeclaration(declaration) &&
|
|
1474
|
+
declaration.kind === 'const') {
|
|
1475
|
+
for (const variable of declaration.declarations)
|
|
1476
|
+
if (exports.t.isIdentifier(variable.id) && variable.init)
|
|
1477
|
+
initializers.set(variable.id.value, variable.init);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
const objectArgument = (expression, visiting = new Set()) => {
|
|
1481
|
+
const value = unwrapExpression(expression);
|
|
1482
|
+
if (exports.t.isIdentifier(value) &&
|
|
1483
|
+
initializers.has(value.value) &&
|
|
1484
|
+
!visiting.has(value.value)) {
|
|
1485
|
+
visiting.add(value.value);
|
|
1486
|
+
return objectArgument(initializers.get(value.value), visiting);
|
|
1487
|
+
}
|
|
1488
|
+
return value;
|
|
1489
|
+
};
|
|
1293
1490
|
for (const node of ast.body) {
|
|
1294
1491
|
let declarations = [];
|
|
1295
1492
|
if (exports.t.isVariableDeclaration(node)) {
|
|
@@ -1300,6 +1497,11 @@ function scanAll() {
|
|
|
1300
1497
|
declarations = node.declaration.declarations;
|
|
1301
1498
|
}
|
|
1302
1499
|
for (const decl of declarations) {
|
|
1500
|
+
if (decl.init)
|
|
1501
|
+
decl.init = unwrapExpression(decl.init);
|
|
1502
|
+
if (exports.t.isCallExpression(decl.init))
|
|
1503
|
+
for (const arg of decl.init.arguments)
|
|
1504
|
+
arg.expression = unwrapExpression(arg.expression);
|
|
1303
1505
|
if (exports.t.isVariableDeclarator(decl) &&
|
|
1304
1506
|
exports.t.isIdentifier(decl.id) &&
|
|
1305
1507
|
decl.init &&
|
|
@@ -1323,6 +1525,18 @@ function scanAll() {
|
|
|
1323
1525
|
method = originalName;
|
|
1324
1526
|
}
|
|
1325
1527
|
}
|
|
1528
|
+
if (method &&
|
|
1529
|
+
[
|
|
1530
|
+
'create',
|
|
1531
|
+
'createTheme',
|
|
1532
|
+
'createStatic',
|
|
1533
|
+
'keyframes',
|
|
1534
|
+
'viewTransition',
|
|
1535
|
+
].includes(method)) {
|
|
1536
|
+
const argument = decl.init.arguments[method === 'createTheme' ? 1 : 0];
|
|
1537
|
+
if (argument)
|
|
1538
|
+
argument.expression = objectArgument(argument.expression);
|
|
1539
|
+
}
|
|
1326
1540
|
const isCreateTheme = method === 'createTheme';
|
|
1327
1541
|
if (method &&
|
|
1328
1542
|
decl.init.arguments.length > 0 &&
|
|
@@ -1383,6 +1597,8 @@ function scanAll() {
|
|
|
1383
1597
|
}
|
|
1384
1598
|
else if (method === 'createTheme') {
|
|
1385
1599
|
const selector = resolveThemeSelector(init.arguments[0].expression, scopedStaticTable, localCreateStaticHashTable, localCreateStaticObjectTable);
|
|
1600
|
+
if (!selector)
|
|
1601
|
+
throw new Error('[plumeria] createTheme requires a statically resolvable non-empty selector.');
|
|
1386
1602
|
const hash = (0, createTheme_1.themeHashOf)(selector, obj);
|
|
1387
1603
|
localTables.createThemeObjectTable[hash] = obj;
|
|
1388
1604
|
localCreateThemeObjectTable[hash] = obj;
|
|
@@ -1505,7 +1721,7 @@ function scanAll() {
|
|
|
1505
1721
|
variantsHashTable: localVariantsHashTable,
|
|
1506
1722
|
};
|
|
1507
1723
|
const dynamicStaticTable = {
|
|
1508
|
-
...
|
|
1724
|
+
...collectLocalConsts(ast),
|
|
1509
1725
|
...localStaticTable,
|
|
1510
1726
|
};
|
|
1511
1727
|
const resolveDynamicCallInScan = (expr) => {
|
|
@@ -1556,13 +1772,14 @@ function scanAll() {
|
|
|
1556
1772
|
runtime.push(param);
|
|
1557
1773
|
});
|
|
1558
1774
|
}
|
|
1559
|
-
const resolved = (0, dynamicKey_1.resolveDynamicStyle)(func, runtime, dynamicStaticTable, dynamicStyleTables);
|
|
1775
|
+
const resolved = (0, dynamicKey_1.resolveDynamicStyle)(func, runtime, dynamicStaticTable, dynamicStyleTables, new Set());
|
|
1560
1776
|
if (!resolved)
|
|
1561
1777
|
return null;
|
|
1562
1778
|
const hasVars = runtime.some((param) => (resolved.varGroups.get(param) ?? []).length > 0);
|
|
1563
1779
|
return { style: resolved.style, hasVars };
|
|
1564
1780
|
};
|
|
1565
1781
|
const resolveCallStylePropInScan = (expr) => {
|
|
1782
|
+
expr = unwrapExpression(expr);
|
|
1566
1783
|
if (expr.type === 'ArrayExpression') {
|
|
1567
1784
|
let mergedStyle = {};
|
|
1568
1785
|
const classList = [];
|
|
@@ -1570,6 +1787,8 @@ function scanAll() {
|
|
|
1570
1787
|
let hasVars = false;
|
|
1571
1788
|
for (const el of expr.elements) {
|
|
1572
1789
|
if (el && el.expression) {
|
|
1790
|
+
if (el.spread)
|
|
1791
|
+
return null;
|
|
1573
1792
|
const res = resolveCallStylePropInScan(el.expression);
|
|
1574
1793
|
if (!res)
|
|
1575
1794
|
continue;
|
|
@@ -1613,9 +1832,6 @@ function scanAll() {
|
|
|
1613
1832
|
}
|
|
1614
1833
|
}
|
|
1615
1834
|
}
|
|
1616
|
-
if (expr.type === 'ParenthesisExpression') {
|
|
1617
|
-
return resolveCallStylePropInScan(expr.expression);
|
|
1618
|
-
}
|
|
1619
1835
|
if (expr.type === 'MemberExpression' &&
|
|
1620
1836
|
expr.object.type === 'Identifier') {
|
|
1621
1837
|
const varName = expr.object.value;
|
|
@@ -1637,6 +1853,98 @@ function scanAll() {
|
|
|
1637
1853
|
}
|
|
1638
1854
|
return null;
|
|
1639
1855
|
};
|
|
1856
|
+
const containsStyleReference = (expr) => {
|
|
1857
|
+
let found = false;
|
|
1858
|
+
traverse(expr, {
|
|
1859
|
+
Identifier({ node }) {
|
|
1860
|
+
if (localCreateHashTable[node.value] ||
|
|
1861
|
+
localTables.createHashTable[`${filePath}-${node.value}`])
|
|
1862
|
+
found = true;
|
|
1863
|
+
},
|
|
1864
|
+
});
|
|
1865
|
+
return found;
|
|
1866
|
+
};
|
|
1867
|
+
const propAlternatives = (expr) => {
|
|
1868
|
+
expr = unwrapExpression(expr);
|
|
1869
|
+
const empty = {
|
|
1870
|
+
styleObj: {},
|
|
1871
|
+
conditions: [],
|
|
1872
|
+
dynamicCalls: [],
|
|
1873
|
+
};
|
|
1874
|
+
if (expr.type === 'NullLiteral' ||
|
|
1875
|
+
(expr.type === 'BooleanLiteral' && !expr.value) ||
|
|
1876
|
+
(expr.type === 'Identifier' && expr.value === 'undefined'))
|
|
1877
|
+
return [empty];
|
|
1878
|
+
if (expr.type === 'ConditionalExpression') {
|
|
1879
|
+
if (expr.test.type === 'BooleanLiteral')
|
|
1880
|
+
return propAlternatives(expr.test.value ? expr.consequent : expr.alternate);
|
|
1881
|
+
const truthy = propAlternatives(expr.consequent);
|
|
1882
|
+
const falsy = propAlternatives(expr.alternate);
|
|
1883
|
+
if (!truthy || !falsy)
|
|
1884
|
+
return null;
|
|
1885
|
+
return [
|
|
1886
|
+
...truthy.map((entry) => ({
|
|
1887
|
+
...entry,
|
|
1888
|
+
conditions: [
|
|
1889
|
+
{ test: expr.test, truthy: true },
|
|
1890
|
+
...entry.conditions,
|
|
1891
|
+
],
|
|
1892
|
+
})),
|
|
1893
|
+
...falsy.map((entry) => ({
|
|
1894
|
+
...entry,
|
|
1895
|
+
conditions: [
|
|
1896
|
+
{ test: expr.test, truthy: false },
|
|
1897
|
+
...entry.conditions,
|
|
1898
|
+
],
|
|
1899
|
+
})),
|
|
1900
|
+
];
|
|
1901
|
+
}
|
|
1902
|
+
if (expr.type === 'BinaryExpression' && expr.operator === '&&') {
|
|
1903
|
+
if (expr.left.type === 'BooleanLiteral')
|
|
1904
|
+
return expr.left.value ? propAlternatives(expr.right) : [empty];
|
|
1905
|
+
const truthy = propAlternatives(expr.right);
|
|
1906
|
+
if (!truthy)
|
|
1907
|
+
return null;
|
|
1908
|
+
return [
|
|
1909
|
+
...truthy.map((entry) => ({
|
|
1910
|
+
...entry,
|
|
1911
|
+
conditions: [
|
|
1912
|
+
{ test: expr.left, truthy: true },
|
|
1913
|
+
...entry.conditions,
|
|
1914
|
+
],
|
|
1915
|
+
})),
|
|
1916
|
+
{ ...empty, conditions: [{ test: expr.left, truthy: false }] },
|
|
1917
|
+
];
|
|
1918
|
+
}
|
|
1919
|
+
if (expr.type === 'ArrayExpression') {
|
|
1920
|
+
let result = [empty];
|
|
1921
|
+
for (const element of expr.elements) {
|
|
1922
|
+
if (!element)
|
|
1923
|
+
continue;
|
|
1924
|
+
if (element.spread)
|
|
1925
|
+
return null;
|
|
1926
|
+
const choices = propAlternatives(element.expression);
|
|
1927
|
+
if (!choices)
|
|
1928
|
+
return null;
|
|
1929
|
+
result = result.flatMap((base) => choices.map((choice) => ({
|
|
1930
|
+
styleObj: deepMerge(base.styleObj, choice.styleObj),
|
|
1931
|
+
conditions: [...base.conditions, ...choice.conditions],
|
|
1932
|
+
dynamicCalls: [...base.dynamicCalls, ...choice.dynamicCalls],
|
|
1933
|
+
})));
|
|
1934
|
+
}
|
|
1935
|
+
return result;
|
|
1936
|
+
}
|
|
1937
|
+
const resolved = resolveCallStylePropInScan(expr);
|
|
1938
|
+
return resolved
|
|
1939
|
+
? [
|
|
1940
|
+
{
|
|
1941
|
+
styleObj: resolved.styleObj,
|
|
1942
|
+
conditions: [],
|
|
1943
|
+
dynamicCalls: resolved.hasVars ? [expr] : [],
|
|
1944
|
+
},
|
|
1945
|
+
]
|
|
1946
|
+
: null;
|
|
1947
|
+
};
|
|
1640
1948
|
const localComponentPropsTable = {};
|
|
1641
1949
|
const registerStyles = (node, propName, compKey, table) => {
|
|
1642
1950
|
if (node.type === 'ConditionalExpression') {
|
|
@@ -1652,6 +1960,41 @@ function scanAll() {
|
|
|
1652
1960
|
registerStyles(node.expression, propName, compKey, table);
|
|
1653
1961
|
return;
|
|
1654
1962
|
}
|
|
1963
|
+
if (node.type === 'ArrayExpression') {
|
|
1964
|
+
const alternatives = propAlternatives(node);
|
|
1965
|
+
if (!alternatives) {
|
|
1966
|
+
if (!containsStyleReference(node))
|
|
1967
|
+
return;
|
|
1968
|
+
if (node.elements.some((element) => element?.spread))
|
|
1969
|
+
throw new Error('[plumeria] Spread elements in a style array are not supported. List each style explicitly.');
|
|
1970
|
+
throw new Error('[plumeria] A style prop array contains an unsupported style expression. Use defined styles, null, false, undefined, or conditional branches of defined styles.');
|
|
1971
|
+
}
|
|
1972
|
+
if (!containsStyleReference(node))
|
|
1973
|
+
return;
|
|
1974
|
+
const list = ((table[compKey] ??= {})[propName] ??= []);
|
|
1975
|
+
for (const alternative of alternatives) {
|
|
1976
|
+
const atomMap = {};
|
|
1977
|
+
(0, create_1.getStyleRecords)(alternative.styleObj).forEach((record) => (atomMap[record.key] = record.hash));
|
|
1978
|
+
const classString = Object.values(atomMap).join(' ');
|
|
1979
|
+
list.push({
|
|
1980
|
+
key: (0, zss_engine_1.genBase36Hash)(classString, 1, 8),
|
|
1981
|
+
classString,
|
|
1982
|
+
styleObj: alternative.styleObj,
|
|
1983
|
+
spanStart: node.span.start,
|
|
1984
|
+
filePath,
|
|
1985
|
+
conditions: alternative.conditions,
|
|
1986
|
+
dynamicCalls: alternative.dynamicCalls,
|
|
1987
|
+
hasVars: alternative.dynamicCalls.length > 0,
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
if (node.type === 'BinaryExpression' &&
|
|
1993
|
+
(node.operator === '||' || node.operator === '??')) {
|
|
1994
|
+
if (!containsStyleReference(node))
|
|
1995
|
+
return;
|
|
1996
|
+
throw new Error('[plumeria] Style prop fallbacks using || or ?? cannot be resolved. Use a conditional expression with defined styles.');
|
|
1997
|
+
}
|
|
1655
1998
|
const resolved = resolveCallStylePropInScan(node);
|
|
1656
1999
|
if (resolved) {
|
|
1657
2000
|
if (!table[compKey]) {
|
|
@@ -1702,7 +2045,10 @@ function scanAll() {
|
|
|
1702
2045
|
const entries = localComponentPropsTable[compKey][propName];
|
|
1703
2046
|
for (const entry of entries) {
|
|
1704
2047
|
const exists = globalTable[compKey][propName].some((x) => x.spanStart === entry.spanStart &&
|
|
1705
|
-
x.filePath === entry.filePath
|
|
2048
|
+
x.filePath === entry.filePath &&
|
|
2049
|
+
x.key === entry.key &&
|
|
2050
|
+
JSON.stringify(x.conditions) ===
|
|
2051
|
+
JSON.stringify(entry.conditions));
|
|
1706
2052
|
if (!exists) {
|
|
1707
2053
|
globalTable[compKey][propName].push(entry);
|
|
1708
2054
|
}
|
|
@@ -1714,6 +2060,7 @@ function scanAll() {
|
|
|
1714
2060
|
mtimeMs: mtimeMs,
|
|
1715
2061
|
dependencies: Array.from(localDependencies),
|
|
1716
2062
|
exports: fileCache[filePath]?.exports,
|
|
2063
|
+
exportsMtimeMs: fileCache[filePath]?.exportsMtimeMs,
|
|
1717
2064
|
staticTable: localStaticTable,
|
|
1718
2065
|
keyframesHashTable: localKeyframesHashTable,
|
|
1719
2066
|
keyframesObjectTable: localKeyframesObjectTable,
|
|
@@ -1738,8 +2085,26 @@ function scanAll() {
|
|
|
1738
2085
|
recordFileError(entry.filePath, e);
|
|
1739
2086
|
}
|
|
1740
2087
|
}
|
|
2088
|
+
for (const entry of jsxPhaseQueue) {
|
|
2089
|
+
const cached = fileCache[entry.filePath];
|
|
2090
|
+
if (!cached?.hasCssUsage || fileErrors[entry.filePath])
|
|
2091
|
+
continue;
|
|
2092
|
+
const contributions = fileObjectContributions.get(entry.filePath);
|
|
2093
|
+
for (const [tableName, hashes] of contributions ?? []) {
|
|
2094
|
+
for (const hash of [...hashes]) {
|
|
2095
|
+
if (!Object.hasOwn(cached[tableName] ?? {}, hash)) {
|
|
2096
|
+
releaseObjectOwner(tableName, hash, entry.filePath, localTables[tableName]);
|
|
2097
|
+
hashes.delete(hash);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
for (const props of Object.values(localTables.componentPropsTable ?? {})) {
|
|
2103
|
+
for (const entries of Object.values(props))
|
|
2104
|
+
entries.sort((a, b) => a.filePath.localeCompare(b.filePath) || a.spanStart - b.spanStart);
|
|
2105
|
+
}
|
|
1741
2106
|
hasComputedOnce = true;
|
|
1742
|
-
return
|
|
2107
|
+
return snapshotTables();
|
|
1743
2108
|
}
|
|
1744
2109
|
function getFileDependencies(filePath) {
|
|
1745
2110
|
const visited = new Set();
|
|
@@ -1912,16 +2277,19 @@ function extractAndCacheExports(filePath, ast, mtimeMs) {
|
|
|
1912
2277
|
};
|
|
1913
2278
|
fileCache[filePath].dependencies = newDeps;
|
|
1914
2279
|
}
|
|
2280
|
+
fileCache[filePath].exportsMtimeMs = mtimeMs;
|
|
1915
2281
|
}
|
|
1916
2282
|
function resolveExport(filePath, exportName, visited = new Set()) {
|
|
1917
2283
|
const key = `${filePath}-${exportName}`;
|
|
1918
2284
|
if (visited.has(key))
|
|
1919
2285
|
return null;
|
|
1920
2286
|
visited.add(key);
|
|
1921
|
-
|
|
2287
|
+
{
|
|
1922
2288
|
try {
|
|
1923
2289
|
const stats = fs.statSync(filePath);
|
|
1924
|
-
if (
|
|
2290
|
+
if ((!fileCache[filePath]?.exports ||
|
|
2291
|
+
fileCache[filePath].exportsMtimeMs !== stats.mtimeMs) &&
|
|
2292
|
+
stats.isFile()) {
|
|
1925
2293
|
const source = fs.readFileSync(filePath, 'utf8');
|
|
1926
2294
|
const ast = (0, core_1.parseSync)(source, {
|
|
1927
2295
|
syntax: 'typescript',
|
|
@@ -2071,8 +2439,8 @@ function extractOndemandStyles(obj, extractedSheets, t) {
|
|
|
2071
2439
|
}
|
|
2072
2440
|
}
|
|
2073
2441
|
function deepMerge(target, source) {
|
|
2074
|
-
const result =
|
|
2075
|
-
for (const key
|
|
2442
|
+
const result = Object.assign(Object.create(null), target);
|
|
2443
|
+
for (const key of Object.keys(source)) {
|
|
2076
2444
|
const val = source[key];
|
|
2077
2445
|
if (val && typeof val === 'object' && !Array.isArray(val)) {
|
|
2078
2446
|
if (result[key] && typeof result[key] === 'object') {
|
package/dist/resolver.d.ts
CHANGED
package/dist/resolver.js
CHANGED
|
@@ -33,10 +33,24 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resetImportResolutionCache = resetImportResolutionCache;
|
|
36
37
|
exports.resolveImportPath = resolveImportPath;
|
|
37
38
|
const fs = __importStar(require("fs"));
|
|
38
39
|
const path = __importStar(require("path"));
|
|
39
40
|
let cachedTsConfig = undefined;
|
|
41
|
+
function resetImportResolutionCache(cwd = process.cwd()) {
|
|
42
|
+
const configPath = path.join(cwd, 'tsconfig.json');
|
|
43
|
+
try {
|
|
44
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
45
|
+
cachedTsConfig = {
|
|
46
|
+
config: config.compilerOptions || null,
|
|
47
|
+
basePath: path.dirname(configPath),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
cachedTsConfig = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
40
54
|
function getTsConfig() {
|
|
41
55
|
if (cachedTsConfig !== undefined) {
|
|
42
56
|
return cachedTsConfig;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CSSProperties } from 'zss-engine';
|
|
2
|
-
import type { ObjectExpression } from '@swc/core';
|
|
2
|
+
import type { ObjectExpression, Expression } from '@swc/core';
|
|
3
3
|
type CSSPrimitive = string | number | boolean;
|
|
4
4
|
export type CSSValue = CSSPrimitive | CSSObject;
|
|
5
5
|
export type CSSObject = {
|
|
@@ -28,6 +28,11 @@ export interface TableEntry {
|
|
|
28
28
|
spanStart: number;
|
|
29
29
|
filePath: string;
|
|
30
30
|
hasVars?: boolean;
|
|
31
|
+
conditions?: Array<{
|
|
32
|
+
test: Expression;
|
|
33
|
+
truthy: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
dynamicCalls?: Expression[];
|
|
31
36
|
}
|
|
32
37
|
export interface Tables {
|
|
33
38
|
staticTable: StaticTable;
|