@plumeria/compiler 18.5.0 → 18.5.2

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.
Files changed (2) hide show
  1. package/dist/index.js +269 -91
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -65,6 +65,56 @@ const componentFunctionOf = (node) => {
65
65
  }
66
66
  return undefined;
67
67
  };
68
+ const unwrapPatternDefault = (pattern) => pattern?.type === 'AssignmentPattern' ? pattern.left : pattern;
69
+ const resolveLocalStyleAlias = (aliases, expression) => {
70
+ let current = expression;
71
+ const seen = new Set();
72
+ while (utils_1.t.isIdentifier(current)) {
73
+ const name = current.value;
74
+ if (seen.has(name))
75
+ break;
76
+ seen.add(name);
77
+ const candidates = aliases[name];
78
+ if (!candidates || candidates.length === 0)
79
+ break;
80
+ const candidate = candidates.find((candidate) => candidate.context === current.ctxt);
81
+ if (!candidate)
82
+ break;
83
+ current = candidate.expression;
84
+ }
85
+ return current;
86
+ };
87
+ const destructuredPropAliases = (fn) => {
88
+ const aliases = new Map();
89
+ const first = fn.params[0];
90
+ const pattern = unwrapPatternDefault(first?.pat ?? first);
91
+ if (pattern?.type !== 'ObjectPattern')
92
+ return aliases;
93
+ for (const item of pattern.properties ?? []) {
94
+ if (item.type !== 'KeyValuePatternProperty')
95
+ continue;
96
+ const local = unwrapPatternDefault(item.value);
97
+ const key = item.key;
98
+ if (!utils_1.t.isIdentifier(local))
99
+ continue;
100
+ if (!utils_1.t.isIdentifier(key) && !utils_1.t.isStringLiteral(key))
101
+ continue;
102
+ const name = String(key.value);
103
+ if (name !== local.value)
104
+ aliases.set(local.value, name);
105
+ }
106
+ return aliases;
107
+ };
108
+ const sourceOf = (node, sourceBuffer, baseByteOffset) => sourceBuffer
109
+ .subarray(node.span.start - baseByteOffset, node.span.end - baseByteOffset)
110
+ .toString('utf-8');
111
+ const isNoOpStyle = (node) => utils_1.t.isNullLiteral(node) ||
112
+ (utils_1.t.isBooleanLiteral(node) && node.value === false) ||
113
+ (utils_1.t.isIdentifier(node) && node.value === 'undefined');
114
+ const propDefaultError = (source, fileName) => new Error(`[plumeria] A style prop default must be a defined style: "${source}". ` +
115
+ `Apply a conditional or dynamic style where the element is styled. (${fileName})`);
116
+ const spreadStyleError = (source, fileName) => new Error(`[plumeria] Spread elements in a style array are not supported: "...${source}". ` +
117
+ `List each style explicitly. (${fileName})`);
68
118
  const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
69
119
  node.type === 'NumericLiteral' ||
70
120
  node.type === 'BooleanLiteral' ||
@@ -83,10 +133,9 @@ const dynamicTablesOf = (ctx) => ({
83
133
  });
84
134
  function extractStylesFromExpression(expression, ctx) {
85
135
  let expr = expression;
86
- if (ctx.localStyleAliases &&
87
- utils_1.t.isIdentifier(expr) &&
88
- ctx.localStyleAliases[expr.value]) {
89
- expr = ctx.localStyleAliases[expr.value];
136
+ expr = (0, utils_1.unwrapExpression)(expr);
137
+ if (ctx.localStyleAliases) {
138
+ expr = resolveLocalStyleAlias(ctx.localStyleAliases, expr);
90
139
  }
91
140
  const results = [];
92
141
  if (utils_1.t.isMemberExpression(expr)) {
@@ -155,6 +204,25 @@ function extractStylesFromExpression(expression, ctx) {
155
204
  }
156
205
  }
157
206
  }
207
+ else if (expr.type === 'ArrayExpression') {
208
+ const spreads = [];
209
+ const elementStyles = [];
210
+ for (const element of expr.elements ?? []) {
211
+ if (!element)
212
+ continue;
213
+ if (element.spread) {
214
+ spreads.push(element.expression);
215
+ continue;
216
+ }
217
+ elementStyles.push(...extractStylesFromExpression(element.expression, ctx));
218
+ }
219
+ for (const spread of spreads) {
220
+ if (elementStyles.length > 0 ||
221
+ extractStylesFromExpression(spread, ctx).length > 0)
222
+ throw spreadStyleError(sourceOf(spread, ctx.sourceBuffer, ctx.baseByteOffset), path.basename(ctx.resourcePath));
223
+ }
224
+ results.push(...elementStyles);
225
+ }
158
226
  else if (utils_1.t.isConditionalExpression(expr)) {
159
227
  const condExpr = expr;
160
228
  results.push(...extractStylesFromExpression(condExpr.consequent, ctx));
@@ -181,7 +249,7 @@ function compileCSS(options) {
181
249
  exclude: exclude,
182
250
  sort: true,
183
251
  });
184
- const scannedTables = (0, utils_1.scanAll)();
252
+ const scannedTables = (0, utils_1.scanAll)(cwd);
185
253
  const processFile = (filePath) => {
186
254
  const resourcePath = path.resolve(cwd, filePath);
187
255
  const source = fs.readFileSync(resourcePath, 'utf-8');
@@ -354,6 +422,7 @@ function compileCSS(options) {
354
422
  mergedVariantsTable[key] = variantsImportMap[key];
355
423
  }
356
424
  const ctx = {
425
+ resourcePath,
357
426
  mergedStaticTable,
358
427
  mergedKeyframesTable,
359
428
  mergedViewTransitionTable,
@@ -370,15 +439,17 @@ function compileCSS(options) {
370
439
  };
371
440
  const componentParamNames = new Set();
372
441
  const addFirstParamName = (fn) => {
373
- const p = fn.params[0];
442
+ const first = fn.params[0];
443
+ const p = unwrapPatternDefault(first?.pat ?? first);
374
444
  if (utils_1.t.isIdentifier(p)) {
375
445
  componentParamNames.add(p.value);
376
446
  }
377
- else if (typeof p === 'object' &&
378
- p !== null &&
379
- 'pat' in p &&
380
- utils_1.t.isIdentifier(p.pat)) {
381
- componentParamNames.add(p.pat.value);
447
+ else if (p?.type === 'ObjectPattern') {
448
+ for (const item of p.properties ?? []) {
449
+ if (item.type === 'RestElement' && utils_1.t.isIdentifier(item.argument)) {
450
+ componentParamNames.add(item.argument.value);
451
+ }
452
+ }
382
453
  }
383
454
  };
384
455
  for (const node of ast.body) {
@@ -402,18 +473,43 @@ function compileCSS(options) {
402
473
  }
403
474
  }
404
475
  const components = [];
476
+ const propAliases = new Map();
477
+ const propDefaults = new Map();
478
+ const declaredProps = new Map();
479
+ const addComponent = (name, fn) => {
480
+ components.push({ name, node: fn });
481
+ const first = fn.params[0];
482
+ const pattern = unwrapPatternDefault(first?.pat ?? first);
483
+ const defaults = new Map();
484
+ for (const item of pattern?.properties ?? []) {
485
+ if (item.type === 'AssignmentPatternProperty' && item.value)
486
+ defaults.set(item.key.value, item.value);
487
+ if (item.type === 'KeyValuePatternProperty' &&
488
+ item.value?.type === 'AssignmentPattern')
489
+ defaults.set(item.key.value, item.value.right);
490
+ }
491
+ propDefaults.set(name, defaults);
492
+ const aliases = destructuredPropAliases(fn);
493
+ if (aliases.size > 0)
494
+ propAliases.set(name, aliases);
495
+ const declared = new Set();
496
+ for (const item of pattern?.properties ?? []) {
497
+ const key = item.key;
498
+ if (utils_1.t.isIdentifier(key) || utils_1.t.isStringLiteral(key))
499
+ declared.add(String(key.value));
500
+ }
501
+ if (declared.size > 0)
502
+ declaredProps.set(name, declared);
503
+ };
405
504
  for (const node of ast.body) {
406
505
  const statement = unwrapExport(node);
407
506
  if (isFunctionNode(statement)) {
408
- components.push({
409
- name: statement.identifier?.value ?? 'default',
410
- node: statement,
411
- });
507
+ addComponent(statement.identifier?.value ?? 'default', statement);
412
508
  }
413
509
  else if (statement?.type === 'CallExpression') {
414
510
  const fn = componentFunctionOf(statement);
415
511
  if (fn)
416
- components.push({ name: 'default', node: fn });
512
+ addComponent('default', fn);
417
513
  }
418
514
  else if (utils_1.t.isVariableDeclaration(statement)) {
419
515
  for (const decl of statement.declarations) {
@@ -421,7 +517,7 @@ function compileCSS(options) {
421
517
  continue;
422
518
  const fn = componentFunctionOf(decl.init);
423
519
  if (fn)
424
- components.push({ name: decl.id.value, node: fn });
520
+ addComponent(decl.id.value, fn);
425
521
  }
426
522
  }
427
523
  }
@@ -434,14 +530,26 @@ function compileCSS(options) {
434
530
  };
435
531
  const extractAndProcessConditionals = (args) => {
436
532
  args.forEach((arg) => {
437
- if (utils_1.t.isIdentifier(arg.expression) &&
438
- localStyleAliases[arg.expression.value]) {
439
- arg.expression = localStyleAliases[arg.expression.value];
440
- }
533
+ arg.expression = resolveLocalStyleAlias(localStyleAliases, arg.expression);
441
534
  });
442
535
  const conditionals = [];
443
536
  let baseStyle = {};
444
537
  const resolveStyleObject = (expr) => {
538
+ expr = resolveLocalStyleAlias(localStyleAliases, (0, utils_1.unwrapExpression)(expr));
539
+ if (expr.type === 'ArrayExpression') {
540
+ let merged = {};
541
+ for (const element of expr.elements ?? []) {
542
+ if (!element)
543
+ continue;
544
+ if (element.spread)
545
+ throw spreadStyleError(getSource(element.expression), path.basename(resourcePath));
546
+ const style = resolveStyleObject(element.expression);
547
+ if (!style)
548
+ return null;
549
+ merged = (0, utils_1.deepMerge)(merged, style);
550
+ }
551
+ return merged;
552
+ }
445
553
  if (utils_1.t.isObjectExpression(expr)) {
446
554
  return (0, utils_1.objectExpressionToObject)(expr, ctx.mergedStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable);
447
555
  }
@@ -490,9 +598,7 @@ function compileCSS(options) {
490
598
  }
491
599
  return null;
492
600
  };
493
- const getSource = (node) => ctx.sourceBuffer
494
- .subarray(node.span.start - ctx.baseByteOffset, node.span.end - ctx.baseByteOffset)
495
- .toString('utf-8');
601
+ const getSource = (node) => sourceOf(node, ctx.sourceBuffer, ctx.baseByteOffset);
496
602
  const assertResolvable = (node) => {
497
603
  if (utils_1.t.isIdentifier(node) && node.value === 'undefined')
498
604
  return;
@@ -555,7 +661,14 @@ function compileCSS(options) {
555
661
  if (callArgs.some((a) => a.spread))
556
662
  return null;
557
663
  const tempStaticTable = { ...ctx.mergedStaticTable };
664
+ const providedParams = new Set();
558
665
  const runtime = [];
666
+ const resolveObjectArg = (argExpr) => (0, utils_1.objectExpressionToObject)({
667
+ ...argExpr,
668
+ properties: argExpr.properties.filter((prop) => prop.type === 'Identifier' ||
669
+ (prop.type === 'KeyValueProperty' &&
670
+ isStaticArgValue(prop.value))),
671
+ }, ctx.mergedStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable);
559
672
  if (func.named) {
560
673
  const argExpr = callArgs[0]?.expression;
561
674
  if (callArgs.length > 1 ||
@@ -572,9 +685,9 @@ function compileCSS(options) {
572
685
  given.set(String(prop.key.value), prop.value);
573
686
  }
574
687
  });
575
- const argObj = !argExpr
576
- ? {}
577
- : ((0, utils_1.objectExpressionToObject)(argExpr, ctx.mergedStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable) ?? {});
688
+ const argObj = argExpr
689
+ ? (resolveObjectArg(argExpr) ?? {})
690
+ : {};
578
691
  func.named.forEach(({ key, local }) => {
579
692
  const source = given.get(key);
580
693
  if (!source) {
@@ -582,18 +695,22 @@ function compileCSS(options) {
582
695
  return;
583
696
  throw new Error(`[plumeria] ${getSource(expr)} leaves "${key}" unset, and a dynamic style function has no value to fall back on.\n`);
584
697
  }
585
- if (isStaticArgValue(source) && argObj[key] !== undefined)
698
+ if (isStaticArgValue(source) && argObj[key] !== undefined) {
586
699
  tempStaticTable[local] = argObj[key];
700
+ providedParams.add(local);
701
+ }
587
702
  else
588
703
  runtime.push(local);
589
704
  });
590
705
  }
591
706
  else if (callArgs.length === 1 &&
592
707
  callArgs[0].expression.type === 'ObjectExpression') {
593
- const argObj = (0, utils_1.objectExpressionToObject)(callArgs[0].expression, ctx.mergedStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable);
708
+ const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
594
709
  func.params.forEach((p) => {
595
- if (argObj[p] !== undefined)
710
+ if (argObj[p] !== undefined) {
596
711
  tempStaticTable[p] = argObj[p];
712
+ providedParams.add(p);
713
+ }
597
714
  });
598
715
  }
599
716
  else {
@@ -604,13 +721,88 @@ function compileCSS(options) {
604
721
  runtime.push(p);
605
722
  });
606
723
  }
607
- const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime, tempStaticTable, dynamicTablesOf(ctx));
724
+ const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime, tempStaticTable, dynamicTablesOf(ctx), providedParams);
608
725
  if (!resolved)
609
726
  return null;
610
727
  const { style } = resolved;
611
728
  return style;
612
729
  };
730
+ const collectPropStyles = (expr) => {
731
+ const isParamMember = utils_1.t.isMemberExpression(expr) &&
732
+ utils_1.t.isIdentifier(expr.object) &&
733
+ componentParamNames.has(expr.object.value) &&
734
+ utils_1.t.isIdentifier(expr.property);
735
+ if (!utils_1.t.isIdentifier(expr) && !isParamMember)
736
+ return false;
737
+ const paramObject = isParamMember
738
+ ? expr.object.value
739
+ : undefined;
740
+ const isPropsMember = Boolean(paramObject &&
741
+ ctx.localCreateStyles[paramObject] === undefined &&
742
+ ctx.mergedCreateTable[paramObject] === undefined);
743
+ const varName = utils_1.t.isIdentifier(expr)
744
+ ? expr.value
745
+ : expr.property.value;
746
+ const owner = ownerComponentOf(expr);
747
+ const propName = (utils_1.t.isIdentifier(expr) && owner
748
+ ? propAliases.get(owner)?.get(varName)
749
+ : undefined) ?? varName;
750
+ const possibilities = [];
751
+ if (owner) {
752
+ const entries = ctx.scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[propName];
753
+ if (entries)
754
+ possibilities.push(...entries);
755
+ }
756
+ if (possibilities.length === 0) {
757
+ const filePrefix = `${resourcePath}-`;
758
+ for (const key of Object.keys(ctx.scannedTables.componentPropsTable || {})) {
759
+ if (!key.startsWith(filePrefix))
760
+ continue;
761
+ const entries = ctx.scannedTables.componentPropsTable?.[key]?.[propName];
762
+ if (entries)
763
+ possibilities.push(...entries);
764
+ }
765
+ }
766
+ const fallback = owner && propDefaults.get(owner)?.get(propName);
767
+ if (fallback && !isNoOpStyle((0, utils_1.unwrapExpression)(fallback))) {
768
+ const style = resolveStyleObject(fallback);
769
+ if (!style)
770
+ throw propDefaultError(getSource(fallback), path.basename(resourcePath));
771
+ processStyle(style);
772
+ }
773
+ if (possibilities.length > 0) {
774
+ const uniqueEntries = [];
775
+ possibilities.forEach((entry) => {
776
+ if (!uniqueEntries.some((x) => x.key === entry.key)) {
777
+ uniqueEntries.push(entry);
778
+ }
779
+ });
780
+ uniqueEntries.forEach((entry) => {
781
+ if (entry.styleObj && Object.keys(entry.styleObj).length > 0) {
782
+ processStyle(entry.styleObj);
783
+ }
784
+ });
785
+ return true;
786
+ }
787
+ if (fallback)
788
+ return true;
789
+ return Boolean(isPropsMember || (owner && declaredProps.get(owner)?.has(propName)));
790
+ };
613
791
  const collectConditions = (node, currentTestStrings = []) => {
792
+ node = resolveLocalStyleAlias(localStyleAliases, (0, utils_1.unwrapExpression)(node));
793
+ if (node.type === 'ArrayExpression') {
794
+ let handled = true;
795
+ for (const element of node.elements ?? []) {
796
+ if (!element)
797
+ continue;
798
+ if (element.spread)
799
+ throw spreadStyleError(getSource(element.expression), path.basename(resourcePath));
800
+ handled =
801
+ collectConditions(element.expression, currentTestStrings) &&
802
+ handled;
803
+ }
804
+ return handled;
805
+ }
614
806
  if (node.type === 'ConditionalExpression') {
615
807
  const testSource = getSource(node.test);
616
808
  if (currentTestStrings.length === 0) {
@@ -647,6 +839,8 @@ function compileCSS(options) {
647
839
  else if (node.type === 'ParenthesisExpression') {
648
840
  return collectConditions(node.expression, currentTestStrings);
649
841
  }
842
+ if (collectPropStyles(node))
843
+ return true;
650
844
  const staticStyle = resolveStyleObject(node) ?? resolveDynamicCall(node);
651
845
  if (staticStyle) {
652
846
  if (currentTestStrings.length === 0) {
@@ -681,46 +875,8 @@ function compileCSS(options) {
681
875
  };
682
876
  for (const arg of args) {
683
877
  const expr = arg.expression;
684
- if (utils_1.t.isIdentifier(expr) ||
685
- (utils_1.t.isMemberExpression(expr) &&
686
- utils_1.t.isIdentifier(expr.object) &&
687
- componentParamNames.has(expr.object.value) &&
688
- utils_1.t.isIdentifier(expr.property))) {
689
- const varName = utils_1.t.isIdentifier(expr)
690
- ? expr.value
691
- : expr.property.value;
692
- const owner = ownerComponentOf(expr);
693
- const propPossibilities = [];
694
- if (owner) {
695
- const entries = ctx.scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[varName];
696
- if (entries)
697
- propPossibilities.push(...entries);
698
- }
699
- if (propPossibilities.length === 0) {
700
- const filePrefix = `${resourcePath}-`;
701
- for (const key of Object.keys(ctx.scannedTables.componentPropsTable || {})) {
702
- if (!key.startsWith(filePrefix))
703
- continue;
704
- const entries = ctx.scannedTables.componentPropsTable?.[key]?.[varName];
705
- if (entries)
706
- propPossibilities.push(...entries);
707
- }
708
- }
709
- if (propPossibilities.length > 0) {
710
- const uniqueEntries = [];
711
- propPossibilities.forEach((entry) => {
712
- if (!uniqueEntries.some((x) => x.key === entry.key)) {
713
- uniqueEntries.push(entry);
714
- }
715
- });
716
- uniqueEntries.forEach((entry) => {
717
- if (entry.styleObj && Object.keys(entry.styleObj).length > 0) {
718
- processStyle(entry.styleObj);
719
- }
720
- });
721
- continue;
722
- }
723
- }
878
+ if (collectPropStyles(expr))
879
+ continue;
724
880
  const dynamicStyle = resolveDynamicCall(expr);
725
881
  if (dynamicStyle) {
726
882
  baseStyle = (0, utils_1.deepMerge)(baseStyle, dynamicStyle);
@@ -789,6 +945,10 @@ function compileCSS(options) {
789
945
  throw new Error(`[plumeria] createTheme needs a selector it can read at build time. ` +
790
946
  `Pass a string literal such as ".dark", or a name this file declares as one. (${path.basename(resourcePath)})`);
791
947
  }
948
+ if (selector.startsWith('@') && !(0, zss_engine_1.isAtRule)(selector)) {
949
+ throw new Error(`[plumeria] Unsupported at-rule: "${selector}". createTheme only supports ` +
950
+ `nesting at-rules such as @media, @container, @supports, @layer, and @scope. (${path.basename(resourcePath)})`);
951
+ }
792
952
  const obj = (0, utils_1.objectExpressionToObject)(args[1].expression, ctx.mergedStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable);
793
953
  const hash = (0, utils_1.themeHashOf)(selector, obj);
794
954
  ctx.scannedTables.createThemeObjectTable[hash] = obj;
@@ -817,7 +977,7 @@ function compileCSS(options) {
817
977
  (0, utils_1.traverse)(ast, {
818
978
  VariableDeclarator({ node }) {
819
979
  if (utils_1.t.isIdentifier(node.id) && node.init) {
820
- const init = node.init;
980
+ const init = (0, utils_1.unwrapExpression)(node.init);
821
981
  if (utils_1.t.isCallExpression(init)) {
822
982
  const callee = init.callee;
823
983
  let pName;
@@ -832,17 +992,18 @@ function compileCSS(options) {
832
992
  pName = plumeriaAliases[callee.value];
833
993
  }
834
994
  const isTheme = pName === 'createTheme';
995
+ const definitionArg = pName === 'createTheme'
996
+ ? init.arguments[1]?.expression
997
+ : init.arguments[0]?.expression;
998
+ const unwrappedDefinitionArg = definitionArg
999
+ ? (0, utils_1.unwrapExpression)(definitionArg)
1000
+ : undefined;
835
1001
  if (pName &&
836
- init.arguments.length > 0 &&
837
- ((!isTheme &&
838
- init.arguments.length === 1 &&
839
- utils_1.t.isObjectExpression(init.arguments[0].expression)) ||
840
- (isTheme &&
841
- init.arguments.length >= 2 &&
842
- utils_1.t.isObjectExpression(init.arguments[1].expression)))) {
843
- const arg = isTheme
844
- ? init.arguments[1].expression
845
- : init.arguments[0].expression;
1002
+ unwrappedDefinitionArg &&
1003
+ utils_1.t.isObjectExpression(unwrappedDefinitionArg) &&
1004
+ ((!isTheme && init.arguments.length === 1) ||
1005
+ (isTheme && init.arguments.length >= 2))) {
1006
+ const arg = unwrappedDefinitionArg;
846
1007
  const resolveVariable = (name) => ctx.localCreateStyles[name]?.obj ||
847
1008
  (ctx.mergedCreateThemeHashTable[name]
848
1009
  ? ctx.scannedTables.createAtomicMapTable[ctx.mergedCreateThemeHashTable[name]]
@@ -865,6 +1026,10 @@ function compileCSS(options) {
865
1026
  throw new Error(`[plumeria] createTheme needs a selector it can read at build time. ` +
866
1027
  `Pass a string literal such as ".dark", or a name this file declares as one. (${path.basename(resourcePath)})`);
867
1028
  }
1029
+ if (selector.startsWith('@') && !(0, zss_engine_1.isAtRule)(selector)) {
1030
+ throw new Error(`[plumeria] Unsupported at-rule: "${selector}". createTheme only supports ` +
1031
+ `nesting at-rules such as @media, @container, @supports, @layer, and @scope. (${path.basename(resourcePath)})`);
1032
+ }
868
1033
  const obj = (0, utils_1.objectExpressionToObject)(arg, ctx.mergedStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable);
869
1034
  const hash = (0, utils_1.themeHashOf)(selector, obj);
870
1035
  const uKey = `${resourcePath}-${node.id.value}`;
@@ -902,7 +1067,10 @@ function compileCSS(options) {
902
1067
  const objName = init.object.value;
903
1068
  if (ctx.localCreateStyles[objName] !== undefined ||
904
1069
  ctx.mergedCreateTable[objName] !== undefined) {
905
- localStyleAliases[node.id.value] = init;
1070
+ (localStyleAliases[node.id.value] ??= []).push({
1071
+ expression: init,
1072
+ context: node.id.ctxt,
1073
+ });
906
1074
  }
907
1075
  }
908
1076
  }
@@ -944,9 +1112,7 @@ function compileCSS(options) {
944
1112
  if (value.expression.type === 'JSXEmptyExpression')
945
1113
  return;
946
1114
  let expr = value.expression;
947
- if (utils_1.t.isIdentifier(expr) && localStyleAliases[expr.value]) {
948
- expr = localStyleAliases[expr.value];
949
- }
1115
+ expr = resolveLocalStyleAlias(localStyleAliases, expr);
950
1116
  extractStylesFromExpression(expr, ctx).forEach(processStyle);
951
1117
  });
952
1118
  },
@@ -960,11 +1126,23 @@ function compileCSS(options) {
960
1126
  if (node.value.expression.type === 'JSXEmptyExpression')
961
1127
  return;
962
1128
  const expr = node.value.expression;
963
- const args = expr.type === 'ArrayExpression'
964
- ? expr.elements
965
- .filter((el) => el !== undefined)
966
- .map((el) => ({ expression: el.expression }))
967
- : [{ expression: expr }];
1129
+ const args = [];
1130
+ const addArgs = (node) => {
1131
+ node = (0, utils_1.unwrapExpression)(node);
1132
+ if (node.type === 'ArrayExpression') {
1133
+ for (const element of node.elements ?? []) {
1134
+ if (!element)
1135
+ continue;
1136
+ if (element.spread)
1137
+ throw spreadStyleError(sourceOf(element.expression, sourceBuffer, baseByteOffset), path.basename(resourcePath));
1138
+ addArgs(element.expression);
1139
+ }
1140
+ }
1141
+ else {
1142
+ args.push({ expression: node });
1143
+ }
1144
+ };
1145
+ addArgs(expr);
968
1146
  extractAndProcessConditionals(args);
969
1147
  },
970
1148
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/compiler",
3
- "version": "18.5.0",
3
+ "version": "18.5.2",
4
4
  "description": "Plumeria swc based compiler for statically extracting css",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  "dist/"
22
22
  ],
23
23
  "dependencies": {
24
- "@plumeria/utils": "^18.5.0"
24
+ "@plumeria/utils": "^18.5.2"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@rust-gear/glob": "1.1.1",