@plumeria/compiler 18.2.24 → 18.2.26

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 +104 -31
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
47
47
  (node.type === 'TemplateLiteral' && node.expressions.length === 0) ||
48
48
  utils_1.t.isIdentifier(node) ||
49
49
  utils_1.t.isMemberExpression(node);
50
- const namedParamsOf = (params) => {
50
+ const namedParamsOf = (params, defaults) => {
51
51
  if (params.length !== 1)
52
52
  return undefined;
53
53
  const first = params[0];
@@ -56,22 +56,43 @@ const namedParamsOf = (params) => {
56
56
  return undefined;
57
57
  const named = [];
58
58
  for (const prop of pattern.properties ?? []) {
59
- if (prop.type === 'AssignmentPatternProperty' &&
60
- utils_1.t.isIdentifier(prop.key) &&
61
- !prop.value) {
59
+ if (prop.type === 'AssignmentPatternProperty' && utils_1.t.isIdentifier(prop.key)) {
62
60
  named.push({ key: prop.key.value, local: prop.key.value });
61
+ if (prop.value)
62
+ defaults[prop.key.value] = prop.value;
63
63
  }
64
64
  else if (prop.type === 'KeyValuePatternProperty' &&
65
65
  utils_1.t.isIdentifier(prop.key) &&
66
66
  utils_1.t.isIdentifier(prop.value)) {
67
67
  named.push({ key: prop.key.value, local: prop.value.value });
68
68
  }
69
+ else if (prop.type === 'KeyValuePatternProperty' &&
70
+ utils_1.t.isIdentifier(prop.key) &&
71
+ prop.value?.type === 'AssignmentPattern' &&
72
+ utils_1.t.isIdentifier(prop.value.left)) {
73
+ named.push({ key: String(prop.key.value), local: prop.value.left.value });
74
+ defaults[prop.value.left.value] = prop.value.right;
75
+ }
69
76
  else {
70
77
  return undefined;
71
78
  }
72
79
  }
73
80
  return named.length > 0 ? named : undefined;
74
81
  };
82
+ const applyVarFallback = (style, cssVar, literal) => {
83
+ for (const [prop, value] of Object.entries(style)) {
84
+ if (typeof value === 'string' && value.includes(cssVar)) {
85
+ style[prop] =
86
+ `var(${cssVar}, ${(0, zss_engine_1.applyCssValue)(literal, (0, zss_engine_1.camelToKebabCase)(prop))})`;
87
+ return true;
88
+ }
89
+ if (value !== null && typeof value === 'object') {
90
+ if (applyVarFallback(value, cssVar, literal))
91
+ return true;
92
+ }
93
+ }
94
+ return false;
95
+ };
75
96
  const styleFunctionsOf = (objExpr) => {
76
97
  const styleFunctions = {};
77
98
  objExpr.properties.forEach((prop) => {
@@ -81,14 +102,16 @@ const styleFunctionsOf = (objExpr) => {
81
102
  if (func.type !== 'ArrowFunctionExpression' &&
82
103
  func.type !== 'FunctionExpression')
83
104
  return;
105
+ const defaults = {};
84
106
  const params = func.params.map((p) => {
85
- if (utils_1.t.isIdentifier(p))
86
- return p.value;
87
- if (typeof p === 'object' &&
88
- p !== null &&
89
- 'pat' in p &&
90
- utils_1.t.isIdentifier(p.pat))
91
- return p.pat.value;
107
+ const pattern = (typeof p === 'object' && p !== null && 'pat' in p ? p.pat : p);
108
+ if (utils_1.t.isIdentifier(pattern))
109
+ return pattern.value;
110
+ if (pattern?.type === 'AssignmentPattern' &&
111
+ utils_1.t.isIdentifier(pattern.left)) {
112
+ defaults[pattern.left.value] = pattern.right;
113
+ return pattern.left.value;
114
+ }
92
115
  return 'arg';
93
116
  });
94
117
  let actualBody = func.body;
@@ -104,7 +127,8 @@ const styleFunctionsOf = (objExpr) => {
104
127
  if (actualBody && actualBody.type === 'ObjectExpression') {
105
128
  styleFunctions[prop.key.value] = {
106
129
  params,
107
- named: namedParamsOf(func.params),
130
+ named: namedParamsOf(func.params, defaults),
131
+ defaults,
108
132
  body: actualBody,
109
133
  };
110
134
  }
@@ -432,6 +456,24 @@ function compileCSS(options) {
432
456
  }
433
457
  }
434
458
  }
459
+ const components = [];
460
+ for (const node of ast.body) {
461
+ const statement = utils_1.t.isExportDeclaration(node) ? node.declaration : node;
462
+ if (statement.type === 'FunctionDeclaration' && statement.identifier) {
463
+ components.push({ name: statement.identifier.value, node: statement });
464
+ }
465
+ else if (utils_1.t.isVariableDeclaration(statement)) {
466
+ for (const decl of statement.declarations) {
467
+ if (utils_1.t.isIdentifier(decl.id) &&
468
+ (decl.init?.type === 'ArrowFunctionExpression' ||
469
+ decl.init?.type === 'FunctionExpression')) {
470
+ components.push({ name: decl.id.value, node: decl.init });
471
+ }
472
+ }
473
+ }
474
+ }
475
+ const ownerComponentOf = (at) => components.find((c) => at.span.start >= c.node.span.start &&
476
+ at.span.start <= c.node.span.end)?.name;
435
477
  const processStyle = (style) => {
436
478
  (0, utils_1.extractOndemandStyles)(style, extractedSheets, scannedTables);
437
479
  const records = (0, utils_1.getStyleRecords)(style);
@@ -551,17 +593,18 @@ function compileCSS(options) {
551
593
  if (!func)
552
594
  return null;
553
595
  const callArgs = expr.arguments;
554
- if (callArgs.some((a) => a.spread) || callArgs.length === 0)
596
+ if (callArgs.some((a) => a.spread))
555
597
  return null;
556
598
  const tempStaticTable = { ...ctx.mergedStaticTable };
557
599
  const runtime = [];
558
600
  if (func.named) {
559
- const argExpr = callArgs[0].expression;
560
- if (callArgs.length !== 1 || argExpr.type !== 'ObjectExpression') {
601
+ const argExpr = callArgs[0]?.expression;
602
+ if (callArgs.length > 1 ||
603
+ (argExpr && argExpr.type !== 'ObjectExpression')) {
561
604
  throw new Error(`[plumeria] ${getSource(expr)} takes one object argument, because ${callee.property.value} destructures its parameter.\n`);
562
605
  }
563
606
  const given = new Map();
564
- argExpr.properties.forEach((prop) => {
607
+ (argExpr?.properties ?? []).forEach((prop) => {
565
608
  if (prop.type === 'Identifier') {
566
609
  given.set(prop.value, prop);
567
610
  }
@@ -570,10 +613,14 @@ function compileCSS(options) {
570
613
  given.set(String(prop.key.value), prop.value);
571
614
  }
572
615
  });
573
- const argObj = (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) ?? {};
616
+ const argObj = !argExpr
617
+ ? {}
618
+ : ((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) ?? {});
574
619
  func.named.forEach(({ key, local }) => {
575
620
  const source = given.get(key);
576
621
  if (!source) {
622
+ if (func.defaults?.[local])
623
+ return;
577
624
  throw new Error(`[plumeria] ${getSource(expr)} leaves "${key}" unset, and a dynamic style function has no value to fall back on.\n`);
578
625
  }
579
626
  if (isStaticArgValue(source) && argObj[key] !== undefined)
@@ -598,15 +645,34 @@ function compileCSS(options) {
598
645
  runtime.push(p);
599
646
  });
600
647
  }
601
- if (runtime.length > 0) {
602
- runtime.forEach((p) => (tempStaticTable[p] = p));
648
+ const withDefault = Object.entries(func.defaults ?? {}).filter(([param]) => tempStaticTable[param] === undefined);
649
+ const cssVars = {};
650
+ const varParams = Array.from(new Set([...runtime, ...withDefault.map(([param]) => param)]));
651
+ if (varParams.length > 0) {
652
+ varParams.forEach((p) => (tempStaticTable[p] = p));
603
653
  const probe = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable);
604
654
  const hash = (0, zss_engine_1.genBase36Hash)(probe ?? {}, 1, 8);
605
- runtime.forEach((p) => {
606
- tempStaticTable[p] = `var(--${hash}-${p})`;
655
+ varParams.forEach((p) => {
656
+ const cssVar = `--${hash}-${p}`;
657
+ tempStaticTable[p] = `var(${cssVar})`;
658
+ cssVars[p] = cssVar;
607
659
  });
608
660
  }
609
- return ((0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable) ?? null);
661
+ const style = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, ctx.mergedKeyframesTable, ctx.mergedViewTransitionTable, ctx.mergedCreateThemeHashTable, ctx.scannedTables.createThemeObjectTable, ctx.mergedCreateTable, ctx.mergedCreateStaticHashTable, ctx.scannedTables.createStaticObjectTable, ctx.mergedVariantsTable);
662
+ if (!style)
663
+ return null;
664
+ withDefault.forEach(([param, expr]) => {
665
+ const cssVar = cssVars[param];
666
+ if (!cssVar)
667
+ return;
668
+ const literal = expr.type === 'StringLiteral' || expr.type === 'NumericLiteral'
669
+ ? expr.value
670
+ : undefined;
671
+ if (literal === undefined)
672
+ return;
673
+ applyVarFallback(style, cssVar, literal);
674
+ });
675
+ return style;
610
676
  };
611
677
  const collectConditions = (node, currentTestStrings = []) => {
612
678
  if (node.type === 'ConditionalExpression') {
@@ -724,17 +790,24 @@ function compileCSS(options) {
724
790
  const varName = utils_1.t.isIdentifier(expr)
725
791
  ? expr.value
726
792
  : expr.property.value;
727
- let propPossibilities;
728
- for (const key of Object.keys(ctx.scannedTables.componentPropsTable || {})) {
729
- if (key.startsWith(`${resourcePath}-`)) {
730
- if (ctx.scannedTables.componentPropsTable?.[key]?.[varName]) {
731
- propPossibilities =
732
- ctx.scannedTables.componentPropsTable?.[key]?.[varName];
733
- break;
734
- }
793
+ const owner = ownerComponentOf(expr);
794
+ const propPossibilities = [];
795
+ if (owner) {
796
+ const entries = ctx.scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[varName];
797
+ if (entries)
798
+ propPossibilities.push(...entries);
799
+ }
800
+ else {
801
+ const filePrefix = `${resourcePath}-`;
802
+ for (const key of Object.keys(ctx.scannedTables.componentPropsTable || {})) {
803
+ if (!key.startsWith(filePrefix))
804
+ continue;
805
+ const entries = ctx.scannedTables.componentPropsTable?.[key]?.[varName];
806
+ if (entries)
807
+ propPossibilities.push(...entries);
735
808
  }
736
809
  }
737
- if (propPossibilities && propPossibilities.length > 0) {
810
+ if (propPossibilities.length > 0) {
738
811
  const uniqueEntries = [];
739
812
  propPossibilities.forEach((entry) => {
740
813
  if (!uniqueEntries.some((x) => x.key === entry.key)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/compiler",
3
- "version": "18.2.24",
3
+ "version": "18.2.26",
4
4
  "description": "Plumeria swc based compiler for statically extracting css",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -21,10 +21,10 @@
21
21
  "dist/"
22
22
  ],
23
23
  "dependencies": {
24
- "@plumeria/utils": "^18.2.24"
24
+ "@plumeria/utils": "^18.2.26"
25
25
  },
26
26
  "devDependencies": {
27
- "@rust-gear/glob": "1.1.0",
27
+ "@rust-gear/glob": "1.1.1",
28
28
  "@swc/core": "1.15.47",
29
29
  "zss-engine": "2.6.0"
30
30
  },