@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 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
  }
@@ -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;
@@ -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]) => tempStaticTable[param] === undefined);
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 literal = expr.type === 'StringLiteral' || expr.type === 'NumericLiteral'
165
- ? expr.value
166
- : undefined;
167
- if (literal === undefined)
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, deepMerge(obj, spreadVal));
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
- if (exports.t.isIdentifier(val.object) && exports.t.isIdentifier(val.property)) {
233
- const resolved = resolveVariable(val.object.value);
234
- const prop = val.property.value;
235
- if (resolved && resolved[prop]) {
236
- obj[key] = resolved[prop];
237
- return;
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] = evaluateUnaryExpression(val);
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 body = rewriteBody(func.body, paramNames(func));
553
- if (body === func.body)
554
- return prop;
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
- return '';
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
- return '';
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
- return evaluateUnaryExpression(node);
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
- if (!exports.t.isIdentifier(current.property))
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(current.property.value);
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 in value))
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
- if (message.startsWith(DIAGNOSTIC_PREFIX))
911
- fileErrors[filePath] = message.slice(DIAGNOSTIC_PREFIX.length);
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
- if (!cached.hasCssUsage)
986
- return;
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
- if (hasComputedOnce && process.env.NODE_ENV === 'production') {
1060
- return globalAgregatedTables;
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
- const files = rs.globSync(PATTERN_PATH, GLOB_OPTIONS);
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 localTables;
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
- ...localTables.staticTable,
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 localTables;
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
- if (!fileCache[filePath] || !fileCache[filePath].exports) {
2287
+ {
1922
2288
  try {
1923
2289
  const stats = fs.statSync(filePath);
1924
- if (stats.isFile()) {
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 = { ...target };
2075
- for (const key in source) {
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') {
@@ -1 +1,2 @@
1
+ export declare function resetImportResolutionCache(cwd?: string): void;
1
2
  export declare function resolveImportPath(importPath: string, importerPath: string): string | null;
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/utils",
3
- "version": "18.4.2",
3
+ "version": "18.5.1",
4
4
  "description": "Plumeria Utils",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",