@plumeria/utils 18.4.2 → 18.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ast.js +2 -2
- package/dist/dynamicKey.d.ts +1 -0
- package/dist/dynamicKey.js +27 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/parser.d.ts +1 -0
- package/dist/parser.js +433 -67
- 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
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,
|
|
@@ -137,6 +144,8 @@ const applyVarFallback = (style, cssVar, literal) => {
|
|
|
137
144
|
};
|
|
138
145
|
exports.applyVarFallback = applyVarFallback;
|
|
139
146
|
const resolveDynamicStyle = (func, runtimeParams, staticTable, tables) => {
|
|
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
151
|
const withDefault = Object.entries(func.defaults ?? {}).filter(([param]) => tempStaticTable[param] === undefined);
|
|
@@ -161,10 +170,24 @@ const resolveDynamicStyle = (func, runtimeParams, staticTable, tables) => {
|
|
|
161
170
|
varGroups.set(param, (0, exports.splitVarByUnit)(style, cssVar));
|
|
162
171
|
});
|
|
163
172
|
withDefault.forEach(([param, expr]) => {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
:
|
|
167
|
-
|
|
173
|
+
const resolved = (0, parser_1.objectExpressionToObject)({
|
|
174
|
+
type: 'ObjectExpression',
|
|
175
|
+
span: func.body.span,
|
|
176
|
+
properties: [
|
|
177
|
+
{
|
|
178
|
+
type: 'KeyValueProperty',
|
|
179
|
+
key: {
|
|
180
|
+
type: 'Identifier',
|
|
181
|
+
span: func.body.span,
|
|
182
|
+
value: 'value',
|
|
183
|
+
optional: false,
|
|
184
|
+
},
|
|
185
|
+
value: expr,
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
}, staticTable, tables.keyframesHashTable, tables.viewTransitionHashTable, tables.createThemeHashTable, tables.createThemeObjectTable, tables.createHashTable, tables.createStaticHashTable, tables.createStaticObjectTable, tables.variantsHashTable);
|
|
189
|
+
const literal = resolved.value;
|
|
190
|
+
if (typeof literal !== 'string' && typeof literal !== 'number')
|
|
168
191
|
return;
|
|
169
192
|
(varGroups.get(param) ?? []).forEach(({ cssVar }) => (0, exports.applyVarFallback)(style, cssVar, literal));
|
|
170
193
|
});
|
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;
|
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
|
}
|
|
@@ -189,21 +211,14 @@ function traverse(node, visitor) {
|
|
|
189
211
|
}
|
|
190
212
|
walk(node);
|
|
191
213
|
}
|
|
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
214
|
function objectExpressionToObject(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createHashTable, createStaticHashTable, createStaticObjectTable, variantsHashTable, resolveVariable) {
|
|
200
|
-
const obj =
|
|
215
|
+
const obj = Object.create(null);
|
|
201
216
|
node.properties.forEach((prop) => {
|
|
202
217
|
if (prop.type === 'SpreadElement') {
|
|
203
218
|
const arg = prop.arguments;
|
|
204
219
|
const spreadVal = evaluateExpression(arg, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
205
220
|
if (typeof spreadVal === 'object' && spreadVal !== null) {
|
|
206
|
-
Object.assign(obj,
|
|
221
|
+
Object.assign(obj, spreadVal);
|
|
207
222
|
}
|
|
208
223
|
return;
|
|
209
224
|
}
|
|
@@ -226,16 +241,20 @@ function objectExpressionToObject(node, staticTable, keyframesHashTable, viewTra
|
|
|
226
241
|
const key = getPropertyKey(prop.key, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
227
242
|
if (!key)
|
|
228
243
|
return;
|
|
229
|
-
const val = prop.value;
|
|
244
|
+
const val = unwrapExpression(prop.value);
|
|
230
245
|
if (exports.t.isIdentifier(val) || exports.t.isMemberExpression(val)) {
|
|
231
246
|
if (resolveVariable && exports.t.isMemberExpression(val)) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
247
|
+
const root = (0, exports.getRootIdentifier)(val);
|
|
248
|
+
const resolved = root ? resolveVariable(root) : undefined;
|
|
249
|
+
if (resolved !== undefined && root) {
|
|
250
|
+
const member = resolveStaticTableMemberExpression(val, {
|
|
251
|
+
...staticTable,
|
|
252
|
+
[root]: resolved,
|
|
253
|
+
});
|
|
254
|
+
if (member === undefined)
|
|
255
|
+
throw new Error(`[plumeria] Unknown style member on ${root}.`);
|
|
256
|
+
obj[key] = member;
|
|
257
|
+
return;
|
|
239
258
|
}
|
|
240
259
|
}
|
|
241
260
|
const resolvedKeyframe = resolveKeyframesTableMemberExpression(val, keyframesHashTable);
|
|
@@ -275,7 +294,7 @@ function objectExpressionToObject(node, staticTable, keyframesHashTable, viewTra
|
|
|
275
294
|
obj[key] = val.value;
|
|
276
295
|
}
|
|
277
296
|
else if (exports.t.isUnaryExpression(val)) {
|
|
278
|
-
obj[key] =
|
|
297
|
+
obj[key] = evaluateExpression(val, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
279
298
|
}
|
|
280
299
|
else if (exports.t.isObjectExpression(val)) {
|
|
281
300
|
obj[key] = objectExpressionToObject(val, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createHashTable, createStaticHashTable, createStaticObjectTable, variantsHashTable, resolveVariable);
|
|
@@ -331,7 +350,7 @@ function collectLocalConsts(ast) {
|
|
|
331
350
|
if (!decls.has(name) || visiting.has(name))
|
|
332
351
|
return undefined;
|
|
333
352
|
visiting.add(name);
|
|
334
|
-
const init = decls.get(name);
|
|
353
|
+
const init = unwrapExpression(decls.get(name));
|
|
335
354
|
let result;
|
|
336
355
|
try {
|
|
337
356
|
if (exports.t.isStringLiteral(init) ||
|
|
@@ -431,6 +450,10 @@ function literalFromValue(value, span) {
|
|
|
431
450
|
function inlineOuterScope(objExpression, resolveProperty) {
|
|
432
451
|
const rewriteProperty = (prop, params) => {
|
|
433
452
|
if (prop.type === 'KeyValueProperty') {
|
|
453
|
+
if (prop.key?.type === 'Computed') {
|
|
454
|
+
const expression = rewriteExpression(prop.key.expression, params);
|
|
455
|
+
prop = { ...prop, key: { ...prop.key, expression } };
|
|
456
|
+
}
|
|
434
457
|
const val = prop.value;
|
|
435
458
|
if (val.type === 'ObjectExpression') {
|
|
436
459
|
const rewritten = rewriteObject(val, params);
|
|
@@ -549,11 +572,26 @@ function inlineOuterScope(objExpression, resolveProperty) {
|
|
|
549
572
|
prop.value.type !== 'FunctionExpression'))
|
|
550
573
|
return prop;
|
|
551
574
|
const func = prop.value;
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
575
|
+
const names = paramNames(func);
|
|
576
|
+
const rewriteParam = (p) => {
|
|
577
|
+
if (!p || typeof p !== 'object')
|
|
578
|
+
return p;
|
|
579
|
+
if (p.type === 'AssignmentPattern')
|
|
580
|
+
return { ...p, right: rewriteExpression(p.right, names) };
|
|
581
|
+
if (p.type === 'AssignmentPatternProperty' && p.value)
|
|
582
|
+
return { ...p, value: rewriteExpression(p.value, names) };
|
|
583
|
+
if (p.pat)
|
|
584
|
+
return { ...p, pat: rewriteParam(p.pat) };
|
|
585
|
+
if (p.properties)
|
|
586
|
+
return { ...p, properties: p.properties.map(rewriteParam) };
|
|
587
|
+
if (p.type === 'KeyValuePatternProperty')
|
|
588
|
+
return { ...p, value: rewriteParam(p.value) };
|
|
589
|
+
return p;
|
|
590
|
+
};
|
|
591
|
+
const params = func.params.map(rewriteParam);
|
|
592
|
+
const body = rewriteBody(func.body, names);
|
|
555
593
|
changed = true;
|
|
556
|
-
return { ...prop, value: { ...func, body } };
|
|
594
|
+
return { ...prop, value: { ...func, body, params } };
|
|
557
595
|
});
|
|
558
596
|
return changed ? { ...objExpression, properties } : objExpression;
|
|
559
597
|
}
|
|
@@ -617,6 +655,8 @@ function evaluateTemplateLiteral(node, staticTable, keyframesHashTable, viewTran
|
|
|
617
655
|
if (i < node.expressions.length) {
|
|
618
656
|
const expr = node.expressions[i];
|
|
619
657
|
const evaluatedExpr = evaluateExpression(expr, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
658
|
+
if (evaluatedExpr === null || typeof evaluatedExpr === 'object')
|
|
659
|
+
throw new Error('[plumeria] Template value cannot be resolved to a primitive.');
|
|
620
660
|
result += String(evaluatedExpr);
|
|
621
661
|
}
|
|
622
662
|
}
|
|
@@ -624,7 +664,15 @@ function evaluateTemplateLiteral(node, staticTable, keyframesHashTable, viewTran
|
|
|
624
664
|
}
|
|
625
665
|
function evaluateBinaryExpression(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable) {
|
|
626
666
|
const left = evaluateExpression(node.left, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
667
|
+
if (node.operator === '&&' && !left)
|
|
668
|
+
return left;
|
|
669
|
+
if (node.operator === '||' && left)
|
|
670
|
+
return left;
|
|
671
|
+
if (node.operator === '??' && left !== null)
|
|
672
|
+
return left;
|
|
627
673
|
const right = evaluateExpression(node.right, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
674
|
+
if (['&&', '||', '??'].includes(node.operator))
|
|
675
|
+
return right;
|
|
628
676
|
if (typeof left === 'number' && typeof right === 'number') {
|
|
629
677
|
if (node.operator === '+') {
|
|
630
678
|
return left + right;
|
|
@@ -663,9 +711,19 @@ function evaluateBinaryExpression(node, staticTable, keyframesHashTable, viewTra
|
|
|
663
711
|
return left | right;
|
|
664
712
|
}
|
|
665
713
|
}
|
|
666
|
-
if (node.operator === '+'
|
|
714
|
+
if (node.operator === '+' &&
|
|
715
|
+
left !== null &&
|
|
716
|
+
right !== null &&
|
|
717
|
+
typeof left !== 'object' &&
|
|
718
|
+
typeof right !== 'object') {
|
|
667
719
|
return String(left) + String(right);
|
|
668
720
|
}
|
|
721
|
+
if (['+', '-', '*', '/', '%', '**', '&', '<<', '>>', '>>>', '^', '|'].includes(node.operator)) {
|
|
722
|
+
const expected = node.operator === '+' ? 'non-null primitive' : 'numeric';
|
|
723
|
+
const leftType = left === null ? 'null' : typeof left;
|
|
724
|
+
const rightType = right === null ? 'null' : typeof right;
|
|
725
|
+
throw new Error(`[plumeria] Binary operator ${node.operator} requires ${expected} operands; received ${leftType} and ${rightType}.`);
|
|
726
|
+
}
|
|
669
727
|
throw new Error(`[plumeria] Unsupported binary operator: ${node.operator}`);
|
|
670
728
|
}
|
|
671
729
|
function evaluateCallExpression(node, staticTable) {
|
|
@@ -708,6 +766,7 @@ function evaluateCallExpression(node, staticTable) {
|
|
|
708
766
|
return null;
|
|
709
767
|
}
|
|
710
768
|
function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable) {
|
|
769
|
+
node = unwrapExpression(node);
|
|
711
770
|
if (exports.t.isCallExpression(node)) {
|
|
712
771
|
return evaluateCallExpression(node, staticTable);
|
|
713
772
|
}
|
|
@@ -739,7 +798,7 @@ function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitio
|
|
|
739
798
|
return createStaticObjectTable[hash];
|
|
740
799
|
}
|
|
741
800
|
}
|
|
742
|
-
|
|
801
|
+
throw new Error(`[plumeria] Cannot resolve static value: ${node.value}`);
|
|
743
802
|
}
|
|
744
803
|
if (exports.t.isMemberExpression(node)) {
|
|
745
804
|
const resolved = resolveStaticTableMemberExpression(node, staticTable);
|
|
@@ -754,7 +813,7 @@ function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitio
|
|
|
754
813
|
if (resolvedStatic !== undefined) {
|
|
755
814
|
return resolvedStatic;
|
|
756
815
|
}
|
|
757
|
-
|
|
816
|
+
throw new Error('[plumeria] Cannot resolve static member expression.');
|
|
758
817
|
}
|
|
759
818
|
if (exports.t.isBinaryExpression(node)) {
|
|
760
819
|
return evaluateBinaryExpression(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
@@ -763,29 +822,24 @@ function evaluateExpression(node, staticTable, keyframesHashTable, viewTransitio
|
|
|
763
822
|
return evaluateTemplateLiteral(node, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
764
823
|
}
|
|
765
824
|
if (exports.t.isUnaryExpression(node)) {
|
|
766
|
-
|
|
825
|
+
const value = evaluateExpression(node.argument, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
826
|
+
if (node.operator === '!')
|
|
827
|
+
return !value;
|
|
828
|
+
if (typeof value === 'number') {
|
|
829
|
+
if (node.operator === '-')
|
|
830
|
+
return -value;
|
|
831
|
+
if (node.operator === '+')
|
|
832
|
+
return value;
|
|
833
|
+
if (node.operator === '~')
|
|
834
|
+
return ~value;
|
|
835
|
+
}
|
|
836
|
+
throw new Error(`[plumeria] Unsupported unary operand for ${node.operator}`);
|
|
767
837
|
}
|
|
768
838
|
if (exports.t.isParenthesisExpression(node)) {
|
|
769
839
|
return evaluateExpression(node.expression, staticTable, keyframesHashTable, viewTransitionHashTable, createThemeHashTable, createThemeObjectTable, createStaticHashTable, createStaticObjectTable);
|
|
770
840
|
}
|
|
771
841
|
throw new Error(`[plumeria] Unsupported expression type: ${node.type}`);
|
|
772
842
|
}
|
|
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
843
|
function resolveKeyframesTableMemberExpression(node, keyframesHashTable) {
|
|
790
844
|
if (exports.t.isIdentifier(node)) {
|
|
791
845
|
return keyframesHashTable[node.value];
|
|
@@ -810,11 +864,6 @@ function resolveCreateTableMemberExpression(node, createHashTable) {
|
|
|
810
864
|
if (exports.t.isIdentifier(node)) {
|
|
811
865
|
return createHashTable[node.value];
|
|
812
866
|
}
|
|
813
|
-
if (exports.t.isMemberExpression(node)) {
|
|
814
|
-
if (exports.t.isIdentifier(node.object)) {
|
|
815
|
-
return createHashTable[node.object.value];
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
867
|
}
|
|
819
868
|
function resolveVariantsTableMemberExpression(node, variantsHashTable) {
|
|
820
869
|
if (exports.t.isIdentifier(node)) {
|
|
@@ -830,16 +879,29 @@ function resolveStaticTableMemberExpression(node, staticTable) {
|
|
|
830
879
|
const keys = [];
|
|
831
880
|
let current = node;
|
|
832
881
|
while (exports.t.isMemberExpression(current)) {
|
|
833
|
-
|
|
882
|
+
const property = current.property;
|
|
883
|
+
const key = exports.t.isIdentifier(property)
|
|
884
|
+
? property.value
|
|
885
|
+
: property.type === 'Computed'
|
|
886
|
+
? unwrapExpression(property.expression)
|
|
887
|
+
: undefined;
|
|
888
|
+
const value = typeof key === 'string'
|
|
889
|
+
? key
|
|
890
|
+
: exports.t.isStringLiteral(key) || exports.t.isNumericLiteral(key)
|
|
891
|
+
? String(key.value)
|
|
892
|
+
: exports.t.isIdentifier(key)
|
|
893
|
+
? staticTable[key.value]
|
|
894
|
+
: undefined;
|
|
895
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
834
896
|
return undefined;
|
|
835
|
-
keys.unshift(
|
|
836
|
-
current = current.object;
|
|
897
|
+
keys.unshift(String(value));
|
|
898
|
+
current = unwrapExpression(current.object);
|
|
837
899
|
}
|
|
838
900
|
if (!exports.t.isIdentifier(current))
|
|
839
901
|
return undefined;
|
|
840
902
|
let value = staticTable[current.value];
|
|
841
903
|
for (const key of keys) {
|
|
842
|
-
if (!value || typeof value !== 'object' || !(key
|
|
904
|
+
if (!value || typeof value !== 'object' || !Object.hasOwn(value, key))
|
|
843
905
|
return undefined;
|
|
844
906
|
value = value[key];
|
|
845
907
|
}
|
|
@@ -907,8 +969,9 @@ const fileErrors = {};
|
|
|
907
969
|
const DIAGNOSTIC_PREFIX = '[plumeria] ';
|
|
908
970
|
function recordFileError(filePath, e) {
|
|
909
971
|
const message = e instanceof Error ? e.message : String(e);
|
|
910
|
-
|
|
911
|
-
|
|
972
|
+
fileErrors[filePath] = message.startsWith(DIAGNOSTIC_PREFIX)
|
|
973
|
+
? message.slice(DIAGNOSTIC_PREFIX.length)
|
|
974
|
+
: message;
|
|
912
975
|
}
|
|
913
976
|
function resolveFileError(actualPath, importedName) {
|
|
914
977
|
const resolved = resolveExport(actualPath, importedName);
|
|
@@ -960,8 +1023,33 @@ const globalAgregatedTables = {
|
|
|
960
1023
|
componentPropsTable: {},
|
|
961
1024
|
};
|
|
962
1025
|
let hasComputedOnce = false;
|
|
1026
|
+
let resolutionConfigStamp;
|
|
963
1027
|
const objectTableOwners = new Map();
|
|
1028
|
+
const fileObjectContributions = new Map();
|
|
1029
|
+
function snapshotTables() {
|
|
1030
|
+
return Object.fromEntries(Object.entries(globalAgregatedTables).map(([key, value]) => [
|
|
1031
|
+
key,
|
|
1032
|
+
{ ...value },
|
|
1033
|
+
]));
|
|
1034
|
+
}
|
|
1035
|
+
function releaseFileObjects(filePath) {
|
|
1036
|
+
const contributions = fileObjectContributions.get(filePath);
|
|
1037
|
+
if (!contributions)
|
|
1038
|
+
return;
|
|
1039
|
+
for (const [tableName, hashes] of contributions) {
|
|
1040
|
+
for (const hash of hashes)
|
|
1041
|
+
releaseObjectOwner(tableName, hash, filePath, globalAgregatedTables[tableName]);
|
|
1042
|
+
}
|
|
1043
|
+
fileObjectContributions.delete(filePath);
|
|
1044
|
+
}
|
|
964
1045
|
function registerObjectOwner(tableName, hash, filePath) {
|
|
1046
|
+
let contributions = fileObjectContributions.get(filePath);
|
|
1047
|
+
if (!contributions)
|
|
1048
|
+
fileObjectContributions.set(filePath, (contributions = new Map()));
|
|
1049
|
+
let hashes = contributions.get(tableName);
|
|
1050
|
+
if (!hashes)
|
|
1051
|
+
contributions.set(tableName, (hashes = new Set()));
|
|
1052
|
+
hashes.add(hash);
|
|
965
1053
|
const key = `${tableName}:${hash}`;
|
|
966
1054
|
let owners = objectTableOwners.get(key);
|
|
967
1055
|
if (!owners) {
|
|
@@ -982,8 +1070,17 @@ function releaseObjectOwner(tableName, hash, filePath, table) {
|
|
|
982
1070
|
}
|
|
983
1071
|
}
|
|
984
1072
|
function stripFileContributions(filePath, cached) {
|
|
985
|
-
|
|
986
|
-
|
|
1073
|
+
releaseFileObjects(filePath);
|
|
1074
|
+
for (const [name, table] of Object.entries(globalAgregatedTables)) {
|
|
1075
|
+
if (name.endsWith('ObjectTable') ||
|
|
1076
|
+
name === 'createAtomicMapTable' ||
|
|
1077
|
+
name === 'createThemeSelectorTable' ||
|
|
1078
|
+
name === 'componentPropsTable')
|
|
1079
|
+
continue;
|
|
1080
|
+
for (const key of Object.keys(table))
|
|
1081
|
+
if (key.startsWith(`${filePath}-`))
|
|
1082
|
+
delete table[key];
|
|
1083
|
+
}
|
|
987
1084
|
const localTables = globalAgregatedTables;
|
|
988
1085
|
for (const key of Object.keys(cached.staticTable)) {
|
|
989
1086
|
delete localTables.staticTable[`${filePath}-${key}`];
|
|
@@ -1057,10 +1154,40 @@ function stripFileContributions(filePath, cached) {
|
|
|
1057
1154
|
}
|
|
1058
1155
|
function scanAll() {
|
|
1059
1156
|
if (hasComputedOnce && process.env.NODE_ENV === 'production') {
|
|
1060
|
-
return
|
|
1157
|
+
return snapshotTables();
|
|
1061
1158
|
}
|
|
1062
1159
|
const localTables = globalAgregatedTables;
|
|
1063
|
-
const
|
|
1160
|
+
const configPath = path.join(process.cwd(), 'tsconfig.json');
|
|
1161
|
+
let configStamp = configPath;
|
|
1162
|
+
try {
|
|
1163
|
+
configStamp += `:${fs.statSync(configPath).mtimeMs}`;
|
|
1164
|
+
}
|
|
1165
|
+
catch {
|
|
1166
|
+
}
|
|
1167
|
+
const resolutionChanged = resolutionConfigStamp !== undefined &&
|
|
1168
|
+
resolutionConfigStamp !== configStamp;
|
|
1169
|
+
if (resolutionChanged)
|
|
1170
|
+
(0, resolver_1.resetImportResolutionCache)();
|
|
1171
|
+
resolutionConfigStamp = configStamp;
|
|
1172
|
+
const cwd = process.cwd();
|
|
1173
|
+
const segments = cwd.split(path.sep);
|
|
1174
|
+
const dependencyDirectory = segments.indexOf('node_modules');
|
|
1175
|
+
const root = dependencyDirectory < 0
|
|
1176
|
+
? cwd
|
|
1177
|
+
: segments.slice(0, dependencyDirectory).join(path.sep) ||
|
|
1178
|
+
path.parse(cwd).root;
|
|
1179
|
+
const files = rs
|
|
1180
|
+
.globSync(path.join(root, '**/*.{js,jsx,ts,tsx}'), {
|
|
1181
|
+
exclude: [
|
|
1182
|
+
'**/node_modules/**',
|
|
1183
|
+
'**/dist/**',
|
|
1184
|
+
'**/build/**',
|
|
1185
|
+
'**/.next/**',
|
|
1186
|
+
],
|
|
1187
|
+
cwd: root,
|
|
1188
|
+
sort: true,
|
|
1189
|
+
})
|
|
1190
|
+
.sort();
|
|
1064
1191
|
const currentFiles = new Set(files);
|
|
1065
1192
|
const deletedFiles = [];
|
|
1066
1193
|
for (const fp of knownFiles) {
|
|
@@ -1074,7 +1201,7 @@ function scanAll() {
|
|
|
1074
1201
|
try {
|
|
1075
1202
|
const stats = fs.statSync(filePath);
|
|
1076
1203
|
const cached = fileCache[filePath];
|
|
1077
|
-
if (!cached || cached.mtimeMs !== stats.mtimeMs) {
|
|
1204
|
+
if (resolutionChanged || !cached || cached.mtimeMs !== stats.mtimeMs) {
|
|
1078
1205
|
invalidated.add(filePath);
|
|
1079
1206
|
queue.push(filePath);
|
|
1080
1207
|
}
|
|
@@ -1084,6 +1211,26 @@ function scanAll() {
|
|
|
1084
1211
|
queue.push(filePath);
|
|
1085
1212
|
}
|
|
1086
1213
|
}
|
|
1214
|
+
for (const dependency of dependentsMap.keys()) {
|
|
1215
|
+
if (currentFiles.has(dependency))
|
|
1216
|
+
continue;
|
|
1217
|
+
const cached = fileCache[dependency];
|
|
1218
|
+
if (!cached)
|
|
1219
|
+
continue;
|
|
1220
|
+
let changed;
|
|
1221
|
+
try {
|
|
1222
|
+
changed =
|
|
1223
|
+
(cached.exportsMtimeMs ?? cached.mtimeMs) !==
|
|
1224
|
+
fs.statSync(dependency).mtimeMs;
|
|
1225
|
+
}
|
|
1226
|
+
catch {
|
|
1227
|
+
changed = true;
|
|
1228
|
+
}
|
|
1229
|
+
if (changed) {
|
|
1230
|
+
invalidated.add(dependency);
|
|
1231
|
+
queue.push(dependency);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1087
1234
|
for (const fp of deletedFiles) {
|
|
1088
1235
|
invalidated.add(fp);
|
|
1089
1236
|
queue.push(fp);
|
|
@@ -1101,7 +1248,7 @@ function scanAll() {
|
|
|
1101
1248
|
}
|
|
1102
1249
|
}
|
|
1103
1250
|
if (invalidated.size === 0 && hasComputedOnce) {
|
|
1104
|
-
return
|
|
1251
|
+
return snapshotTables();
|
|
1105
1252
|
}
|
|
1106
1253
|
for (const fp of deletedFiles) {
|
|
1107
1254
|
const cached = fileCache[fp];
|
|
@@ -1154,9 +1301,34 @@ function scanAll() {
|
|
|
1154
1301
|
parsedFiles.push({ filePath, ast, mtimeMs: stats.mtimeMs });
|
|
1155
1302
|
}
|
|
1156
1303
|
catch (e) {
|
|
1304
|
+
recordFileError(filePath, e);
|
|
1157
1305
|
}
|
|
1158
1306
|
}
|
|
1159
1307
|
const jsxPhaseQueue = [];
|
|
1308
|
+
for (const file of parsedFiles) {
|
|
1309
|
+
try {
|
|
1310
|
+
extractAndCacheExports(file.filePath, file.ast, file.mtimeMs);
|
|
1311
|
+
}
|
|
1312
|
+
catch (error) {
|
|
1313
|
+
recordFileError(file.filePath, error);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
const byPath = new Map(parsedFiles.map((file) => [file.filePath, file]));
|
|
1317
|
+
const ordered = [];
|
|
1318
|
+
const visitedFiles = new Set();
|
|
1319
|
+
const visitFile = (file) => {
|
|
1320
|
+
if (visitedFiles.has(file.filePath))
|
|
1321
|
+
return;
|
|
1322
|
+
visitedFiles.add(file.filePath);
|
|
1323
|
+
for (const dependency of getFileDependencies(file.filePath)) {
|
|
1324
|
+
const imported = byPath.get(dependency);
|
|
1325
|
+
if (imported)
|
|
1326
|
+
visitFile(imported);
|
|
1327
|
+
}
|
|
1328
|
+
ordered.push(file);
|
|
1329
|
+
};
|
|
1330
|
+
parsedFiles.forEach(visitFile);
|
|
1331
|
+
parsedFiles.splice(0, parsedFiles.length, ...ordered);
|
|
1160
1332
|
for (let passNumber = 1; passNumber <= 2; passNumber++) {
|
|
1161
1333
|
const isFirstPass = passNumber === 1;
|
|
1162
1334
|
for (const { filePath, ast, mtimeMs } of parsedFiles) {
|
|
@@ -1267,6 +1439,8 @@ function scanAll() {
|
|
|
1267
1439
|
if (localTables.createHashTable[uniqueKey]) {
|
|
1268
1440
|
const hash = localTables.createHashTable[uniqueKey];
|
|
1269
1441
|
localCreateHashTable[localName] = hash;
|
|
1442
|
+
localCreateObjectTable[hash] =
|
|
1443
|
+
localTables.createObjectTable[hash];
|
|
1270
1444
|
}
|
|
1271
1445
|
}
|
|
1272
1446
|
});
|
|
@@ -1290,6 +1464,28 @@ function scanAll() {
|
|
|
1290
1464
|
}
|
|
1291
1465
|
}
|
|
1292
1466
|
}
|
|
1467
|
+
const initializers = new Map();
|
|
1468
|
+
for (const statement of ast.body) {
|
|
1469
|
+
const declaration = statement.type === 'ExportDeclaration'
|
|
1470
|
+
? statement.declaration
|
|
1471
|
+
: statement;
|
|
1472
|
+
if (exports.t.isVariableDeclaration(declaration) &&
|
|
1473
|
+
declaration.kind === 'const') {
|
|
1474
|
+
for (const variable of declaration.declarations)
|
|
1475
|
+
if (exports.t.isIdentifier(variable.id) && variable.init)
|
|
1476
|
+
initializers.set(variable.id.value, variable.init);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
const objectArgument = (expression, visiting = new Set()) => {
|
|
1480
|
+
const value = unwrapExpression(expression);
|
|
1481
|
+
if (exports.t.isIdentifier(value) &&
|
|
1482
|
+
initializers.has(value.value) &&
|
|
1483
|
+
!visiting.has(value.value)) {
|
|
1484
|
+
visiting.add(value.value);
|
|
1485
|
+
return objectArgument(initializers.get(value.value), visiting);
|
|
1486
|
+
}
|
|
1487
|
+
return value;
|
|
1488
|
+
};
|
|
1293
1489
|
for (const node of ast.body) {
|
|
1294
1490
|
let declarations = [];
|
|
1295
1491
|
if (exports.t.isVariableDeclaration(node)) {
|
|
@@ -1300,6 +1496,11 @@ function scanAll() {
|
|
|
1300
1496
|
declarations = node.declaration.declarations;
|
|
1301
1497
|
}
|
|
1302
1498
|
for (const decl of declarations) {
|
|
1499
|
+
if (decl.init)
|
|
1500
|
+
decl.init = unwrapExpression(decl.init);
|
|
1501
|
+
if (exports.t.isCallExpression(decl.init))
|
|
1502
|
+
for (const arg of decl.init.arguments)
|
|
1503
|
+
arg.expression = unwrapExpression(arg.expression);
|
|
1303
1504
|
if (exports.t.isVariableDeclarator(decl) &&
|
|
1304
1505
|
exports.t.isIdentifier(decl.id) &&
|
|
1305
1506
|
decl.init &&
|
|
@@ -1323,6 +1524,18 @@ function scanAll() {
|
|
|
1323
1524
|
method = originalName;
|
|
1324
1525
|
}
|
|
1325
1526
|
}
|
|
1527
|
+
if (method &&
|
|
1528
|
+
[
|
|
1529
|
+
'create',
|
|
1530
|
+
'createTheme',
|
|
1531
|
+
'createStatic',
|
|
1532
|
+
'keyframes',
|
|
1533
|
+
'viewTransition',
|
|
1534
|
+
].includes(method)) {
|
|
1535
|
+
const argument = decl.init.arguments[method === 'createTheme' ? 1 : 0];
|
|
1536
|
+
if (argument)
|
|
1537
|
+
argument.expression = objectArgument(argument.expression);
|
|
1538
|
+
}
|
|
1326
1539
|
const isCreateTheme = method === 'createTheme';
|
|
1327
1540
|
if (method &&
|
|
1328
1541
|
decl.init.arguments.length > 0 &&
|
|
@@ -1383,6 +1596,8 @@ function scanAll() {
|
|
|
1383
1596
|
}
|
|
1384
1597
|
else if (method === 'createTheme') {
|
|
1385
1598
|
const selector = resolveThemeSelector(init.arguments[0].expression, scopedStaticTable, localCreateStaticHashTable, localCreateStaticObjectTable);
|
|
1599
|
+
if (!selector)
|
|
1600
|
+
throw new Error('[plumeria] createTheme requires a statically resolvable non-empty selector.');
|
|
1386
1601
|
const hash = (0, createTheme_1.themeHashOf)(selector, obj);
|
|
1387
1602
|
localTables.createThemeObjectTable[hash] = obj;
|
|
1388
1603
|
localCreateThemeObjectTable[hash] = obj;
|
|
@@ -1505,7 +1720,7 @@ function scanAll() {
|
|
|
1505
1720
|
variantsHashTable: localVariantsHashTable,
|
|
1506
1721
|
};
|
|
1507
1722
|
const dynamicStaticTable = {
|
|
1508
|
-
...
|
|
1723
|
+
...collectLocalConsts(ast),
|
|
1509
1724
|
...localStaticTable,
|
|
1510
1725
|
};
|
|
1511
1726
|
const resolveDynamicCallInScan = (expr) => {
|
|
@@ -1563,6 +1778,7 @@ function scanAll() {
|
|
|
1563
1778
|
return { style: resolved.style, hasVars };
|
|
1564
1779
|
};
|
|
1565
1780
|
const resolveCallStylePropInScan = (expr) => {
|
|
1781
|
+
expr = unwrapExpression(expr);
|
|
1566
1782
|
if (expr.type === 'ArrayExpression') {
|
|
1567
1783
|
let mergedStyle = {};
|
|
1568
1784
|
const classList = [];
|
|
@@ -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,39 @@ 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
|
+
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.');
|
|
1969
|
+
}
|
|
1970
|
+
if (!containsStyleReference(node))
|
|
1971
|
+
return;
|
|
1972
|
+
const list = ((table[compKey] ??= {})[propName] ??= []);
|
|
1973
|
+
for (const alternative of alternatives) {
|
|
1974
|
+
const atomMap = {};
|
|
1975
|
+
(0, create_1.getStyleRecords)(alternative.styleObj).forEach((record) => (atomMap[record.key] = record.hash));
|
|
1976
|
+
const classString = Object.values(atomMap).join(' ');
|
|
1977
|
+
list.push({
|
|
1978
|
+
key: (0, zss_engine_1.genBase36Hash)(classString, 1, 8),
|
|
1979
|
+
classString,
|
|
1980
|
+
styleObj: alternative.styleObj,
|
|
1981
|
+
spanStart: node.span.start,
|
|
1982
|
+
filePath,
|
|
1983
|
+
conditions: alternative.conditions,
|
|
1984
|
+
dynamicCalls: alternative.dynamicCalls,
|
|
1985
|
+
hasVars: alternative.dynamicCalls.length > 0,
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
if (node.type === 'BinaryExpression' &&
|
|
1991
|
+
(node.operator === '||' || node.operator === '??')) {
|
|
1992
|
+
if (!containsStyleReference(node))
|
|
1993
|
+
return;
|
|
1994
|
+
throw new Error('[plumeria] Style prop fallbacks using || or ?? cannot be resolved. Use a conditional expression with defined styles.');
|
|
1995
|
+
}
|
|
1655
1996
|
const resolved = resolveCallStylePropInScan(node);
|
|
1656
1997
|
if (resolved) {
|
|
1657
1998
|
if (!table[compKey]) {
|
|
@@ -1702,7 +2043,10 @@ function scanAll() {
|
|
|
1702
2043
|
const entries = localComponentPropsTable[compKey][propName];
|
|
1703
2044
|
for (const entry of entries) {
|
|
1704
2045
|
const exists = globalTable[compKey][propName].some((x) => x.spanStart === entry.spanStart &&
|
|
1705
|
-
x.filePath === entry.filePath
|
|
2046
|
+
x.filePath === entry.filePath &&
|
|
2047
|
+
x.key === entry.key &&
|
|
2048
|
+
JSON.stringify(x.conditions) ===
|
|
2049
|
+
JSON.stringify(entry.conditions));
|
|
1706
2050
|
if (!exists) {
|
|
1707
2051
|
globalTable[compKey][propName].push(entry);
|
|
1708
2052
|
}
|
|
@@ -1714,6 +2058,7 @@ function scanAll() {
|
|
|
1714
2058
|
mtimeMs: mtimeMs,
|
|
1715
2059
|
dependencies: Array.from(localDependencies),
|
|
1716
2060
|
exports: fileCache[filePath]?.exports,
|
|
2061
|
+
exportsMtimeMs: fileCache[filePath]?.exportsMtimeMs,
|
|
1717
2062
|
staticTable: localStaticTable,
|
|
1718
2063
|
keyframesHashTable: localKeyframesHashTable,
|
|
1719
2064
|
keyframesObjectTable: localKeyframesObjectTable,
|
|
@@ -1738,8 +2083,26 @@ function scanAll() {
|
|
|
1738
2083
|
recordFileError(entry.filePath, e);
|
|
1739
2084
|
}
|
|
1740
2085
|
}
|
|
2086
|
+
for (const entry of jsxPhaseQueue) {
|
|
2087
|
+
const cached = fileCache[entry.filePath];
|
|
2088
|
+
if (!cached?.hasCssUsage || fileErrors[entry.filePath])
|
|
2089
|
+
continue;
|
|
2090
|
+
const contributions = fileObjectContributions.get(entry.filePath);
|
|
2091
|
+
for (const [tableName, hashes] of contributions ?? []) {
|
|
2092
|
+
for (const hash of [...hashes]) {
|
|
2093
|
+
if (!Object.hasOwn(cached[tableName] ?? {}, hash)) {
|
|
2094
|
+
releaseObjectOwner(tableName, hash, entry.filePath, localTables[tableName]);
|
|
2095
|
+
hashes.delete(hash);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
for (const props of Object.values(localTables.componentPropsTable ?? {})) {
|
|
2101
|
+
for (const entries of Object.values(props))
|
|
2102
|
+
entries.sort((a, b) => a.filePath.localeCompare(b.filePath) || a.spanStart - b.spanStart);
|
|
2103
|
+
}
|
|
1741
2104
|
hasComputedOnce = true;
|
|
1742
|
-
return
|
|
2105
|
+
return snapshotTables();
|
|
1743
2106
|
}
|
|
1744
2107
|
function getFileDependencies(filePath) {
|
|
1745
2108
|
const visited = new Set();
|
|
@@ -1912,16 +2275,19 @@ function extractAndCacheExports(filePath, ast, mtimeMs) {
|
|
|
1912
2275
|
};
|
|
1913
2276
|
fileCache[filePath].dependencies = newDeps;
|
|
1914
2277
|
}
|
|
2278
|
+
fileCache[filePath].exportsMtimeMs = mtimeMs;
|
|
1915
2279
|
}
|
|
1916
2280
|
function resolveExport(filePath, exportName, visited = new Set()) {
|
|
1917
2281
|
const key = `${filePath}-${exportName}`;
|
|
1918
2282
|
if (visited.has(key))
|
|
1919
2283
|
return null;
|
|
1920
2284
|
visited.add(key);
|
|
1921
|
-
|
|
2285
|
+
{
|
|
1922
2286
|
try {
|
|
1923
2287
|
const stats = fs.statSync(filePath);
|
|
1924
|
-
if (
|
|
2288
|
+
if ((!fileCache[filePath]?.exports ||
|
|
2289
|
+
fileCache[filePath].exportsMtimeMs !== stats.mtimeMs) &&
|
|
2290
|
+
stats.isFile()) {
|
|
1925
2291
|
const source = fs.readFileSync(filePath, 'utf8');
|
|
1926
2292
|
const ast = (0, core_1.parseSync)(source, {
|
|
1927
2293
|
syntax: 'typescript',
|
|
@@ -2071,8 +2437,8 @@ function extractOndemandStyles(obj, extractedSheets, t) {
|
|
|
2071
2437
|
}
|
|
2072
2438
|
}
|
|
2073
2439
|
function deepMerge(target, source) {
|
|
2074
|
-
const result =
|
|
2075
|
-
for (const key
|
|
2440
|
+
const result = Object.assign(Object.create(null), target);
|
|
2441
|
+
for (const key of Object.keys(source)) {
|
|
2076
2442
|
const val = source[key];
|
|
2077
2443
|
if (val && typeof val === 'object' && !Array.isArray(val)) {
|
|
2078
2444
|
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() {
|
|
42
|
+
const configPath = path.join(process.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;
|