@plumeria/utils 19.2.13 → 19.2.15

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/parser.d.ts CHANGED
@@ -43,6 +43,7 @@ export declare function traverse(node: Module | JSXExpression, visitor: {
43
43
  }) => void;
44
44
  }): void;
45
45
  export declare function objectExpressionToObject(node: ObjectExpression, staticTable: StaticTable, keyframesHashTable: KeyframesHashTable, viewTransitionHashTable: ViewTransitionHashTable, createThemeHashTable: CreateThemeHashTable, createThemeObjectTable: CreateThemeObjectTable, createHashTable: CreateHashTable, createStaticHashTable: CreateStaticHashTable, createStaticObjectTable: CreateStaticObjectTable, resolveVariable?: (name: string) => any): CSSObject;
46
+ export declare function collectLocalConstNodes(ast: Module): Map<string, any>;
46
47
  export declare function collectLocalConsts(ast: Module): Record<string, any>;
47
48
  export declare function resolveThemeSelector(node: Expression, staticTable: StaticTable, createStaticHashTable: CreateStaticHashTable, createStaticObjectTable: CreateStaticObjectTable): string;
48
49
  export declare function resolveFileError(actualPath: string, importedName: string): {
package/dist/parser.js CHANGED
@@ -39,6 +39,7 @@ exports.resolveOriginError = resolveOriginError;
39
39
  exports.resolveComponentKey = resolveComponentKey;
40
40
  exports.traverse = traverse;
41
41
  exports.objectExpressionToObject = objectExpressionToObject;
42
+ exports.collectLocalConstNodes = collectLocalConstNodes;
42
43
  exports.collectLocalConsts = collectLocalConsts;
43
44
  exports.resolveThemeSelector = resolveThemeSelector;
44
45
  exports.resolveFileError = resolveFileError;
@@ -343,8 +344,7 @@ function objectExpressionToObject(node, staticTable, keyframesHashTable, viewTra
343
344
  });
344
345
  return obj;
345
346
  }
346
- function collectLocalConsts(ast) {
347
- const localConsts = {};
347
+ function collectLocalConstNodes(ast) {
348
348
  const decls = new Map();
349
349
  for (const node of ast.body) {
350
350
  let declarations = [];
@@ -363,6 +363,11 @@ function collectLocalConsts(ast) {
363
363
  }
364
364
  }
365
365
  }
366
+ return decls;
367
+ }
368
+ function collectLocalConsts(ast) {
369
+ const localConsts = {};
370
+ const decls = collectLocalConstNodes(ast);
366
371
  const visiting = new Set();
367
372
  function resolveValue(name) {
368
373
  if (localConsts[name] !== undefined)
@@ -5,6 +5,7 @@ export type TransformEnv = {
5
5
  filePath: string;
6
6
  root: string;
7
7
  styleProp: string;
8
+ classProp?: string;
8
9
  propertyPolicy: PropertyPolicy | undefined;
9
10
  isDev: boolean;
10
11
  collectOndemandSheets: boolean;
package/dist/transform.js CHANGED
@@ -38,6 +38,42 @@ const core_1 = require("@swc/core");
38
38
  const path = __importStar(require("path"));
39
39
  const zss_engine_1 = require("zss-engine");
40
40
  const parser_1 = require("./parser");
41
+ const unresolvableValue_1 = require("./unresolvableValue");
42
+ const spreadValues = (tables, constNodes) => {
43
+ const spread = (prop) => {
44
+ let values;
45
+ try {
46
+ values = (0, parser_1.objectExpressionToObject)({ properties: [prop] }, ...tables);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ const argument = prop.arguments;
52
+ const declared = argument?.type === 'Identifier'
53
+ ? constNodes.get(argument.value)
54
+ : undefined;
55
+ const source = declared && parser_1.t.isObjectExpression(declared) ? declared : undefined;
56
+ return { values, source };
57
+ };
58
+ const resolvesValue = (value) => {
59
+ try {
60
+ const probe = (0, parser_1.objectExpressionToObject)({
61
+ properties: [
62
+ {
63
+ type: 'KeyValueProperty',
64
+ key: { type: 'Identifier', value: '__probe' },
65
+ value,
66
+ },
67
+ ],
68
+ }, ...tables);
69
+ return '__probe' in probe;
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ };
75
+ return { spread, resolvesValue };
76
+ };
41
77
  const create_1 = require("./create");
42
78
  const dynamicKey_1 = require("./dynamicKey");
43
79
  const escalation_1 = require("./escalation");
@@ -146,6 +182,7 @@ const foldDynamicVars = (vars) => {
146
182
  };
147
183
  const transformSource = async (env) => {
148
184
  const { source, root, styleProp, propertyPolicy, isDev, collectOndemandSheets, addDependency, } = env;
185
+ const classProp = env.classProp ?? 'className';
149
186
  const id = env.moduleId;
150
187
  const resourcePath = env.moduleId;
151
188
  const baseId = env.filePath;
@@ -308,6 +345,7 @@ const transformSource = async (env) => {
308
345
  return records;
309
346
  };
310
347
  const localConsts = (0, parser_1.collectLocalConsts)(ast);
348
+ const localConstNodes = (0, parser_1.collectLocalConstNodes)(ast);
311
349
  const importMap = {};
312
350
  const keyframesImportMap = {};
313
351
  const viewTransitionImportMap = {};
@@ -581,6 +619,16 @@ const transformSource = async (env) => {
581
619
  if (propName === 'create' &&
582
620
  parser_1.t.isObjectExpression(init.arguments[0].expression)) {
583
621
  const obj = (0, parser_1.objectExpressionToObject)(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
622
+ (0, unresolvableValue_1.assertNoDroppedValues)(init.arguments[0].expression, obj, spreadValues([
623
+ mergedStaticTable,
624
+ mergedKeyframesTable,
625
+ mergedViewTransitionTable,
626
+ mergedCreateThemeHashTable,
627
+ scannedTables.createThemeObjectTable,
628
+ mergedCreateTable,
629
+ mergedCreateStaticHashTable,
630
+ scannedTables.createStaticObjectTable,
631
+ ], localConstNodes));
584
632
  if (obj) {
585
633
  const hashMap = {};
586
634
  Object.entries(obj).forEach(([key, style]) => {
@@ -631,6 +679,16 @@ const transformSource = async (env) => {
631
679
  throwCompilationError(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`, selectorExpr);
632
680
  }
633
681
  const obj = (0, parser_1.objectExpressionToObject)(init.arguments[1].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
682
+ (0, unresolvableValue_1.assertNoDroppedValues)(init.arguments[1].expression, obj, spreadValues([
683
+ mergedStaticTable,
684
+ mergedKeyframesTable,
685
+ mergedViewTransitionTable,
686
+ mergedCreateThemeHashTable,
687
+ scannedTables.createThemeObjectTable,
688
+ mergedCreateTable,
689
+ mergedCreateStaticHashTable,
690
+ scannedTables.createStaticObjectTable,
691
+ ], localConstNodes));
634
692
  const hash = (0, createTheme_1.themeHashOf)(selector, obj);
635
693
  if (parser_1.t.isIdentifier(node.id)) {
636
694
  const uniqueKey = `${resourcePath}-${node.id.value}`;
@@ -669,6 +727,16 @@ const transformSource = async (env) => {
669
727
  idSpans.add(node.id.span.start);
670
728
  }
671
729
  const obj = (0, parser_1.objectExpressionToObject)(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
730
+ (0, unresolvableValue_1.assertNoDroppedValues)(init.arguments[0].expression, obj, spreadValues([
731
+ mergedStaticTable,
732
+ mergedKeyframesTable,
733
+ mergedViewTransitionTable,
734
+ mergedCreateThemeHashTable,
735
+ scannedTables.createThemeObjectTable,
736
+ mergedCreateTable,
737
+ mergedCreateStaticHashTable,
738
+ scannedTables.createStaticObjectTable,
739
+ ], localConstNodes));
672
740
  const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
673
741
  if (parser_1.t.isIdentifier(node.id)) {
674
742
  const uniqueKey = `${resourcePath}-${node.id.value}`;
@@ -781,6 +849,16 @@ const transformSource = async (env) => {
781
849
  const expr = args[0].expression;
782
850
  if (parser_1.t.isObjectExpression(expr)) {
783
851
  const obj = (0, parser_1.objectExpressionToObject)(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
852
+ (0, unresolvableValue_1.assertNoDroppedValues)(expr, obj, spreadValues([
853
+ mergedStaticTable,
854
+ mergedKeyframesTable,
855
+ mergedViewTransitionTable,
856
+ mergedCreateThemeHashTable,
857
+ scannedTables.createThemeObjectTable,
858
+ mergedCreateTable,
859
+ mergedCreateStaticHashTable,
860
+ scannedTables.createStaticObjectTable,
861
+ ], localConstNodes));
784
862
  const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
785
863
  scannedTables.keyframesObjectTable[hash] = obj;
786
864
  replacements.push({
@@ -794,6 +872,16 @@ const transformSource = async (env) => {
794
872
  args.length > 0 &&
795
873
  parser_1.t.isObjectExpression(args[0].expression)) {
796
874
  const obj = (0, parser_1.objectExpressionToObject)(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
875
+ (0, unresolvableValue_1.assertNoDroppedValues)(args[0].expression, obj, spreadValues([
876
+ mergedStaticTable,
877
+ mergedKeyframesTable,
878
+ mergedViewTransitionTable,
879
+ mergedCreateThemeHashTable,
880
+ scannedTables.createThemeObjectTable,
881
+ mergedCreateTable,
882
+ mergedCreateStaticHashTable,
883
+ scannedTables.createStaticObjectTable,
884
+ ], localConstNodes));
797
885
  const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
798
886
  scannedTables.viewTransitionObjectTable[hash] = obj;
799
887
  replacements.push({
@@ -815,6 +903,16 @@ const transformSource = async (env) => {
815
903
  throwCompilationError(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`, selectorExpr);
816
904
  }
817
905
  const obj = (0, parser_1.objectExpressionToObject)(args[1].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
906
+ (0, unresolvableValue_1.assertNoDroppedValues)(args[1].expression, obj, spreadValues([
907
+ mergedStaticTable,
908
+ mergedKeyframesTable,
909
+ mergedViewTransitionTable,
910
+ mergedCreateThemeHashTable,
911
+ scannedTables.createThemeObjectTable,
912
+ mergedCreateTable,
913
+ mergedCreateStaticHashTable,
914
+ scannedTables.createStaticObjectTable,
915
+ ], localConstNodes));
818
916
  const hash = (0, createTheme_1.themeHashOf)(selector, obj);
819
917
  scannedTables.createThemeObjectTable[hash] = obj;
820
918
  if (scannedTables.createThemeSelectorTable) {
@@ -825,6 +923,16 @@ const transformSource = async (env) => {
825
923
  args.length > 0 &&
826
924
  parser_1.t.isObjectExpression(args[0].expression)) {
827
925
  const obj = (0, parser_1.objectExpressionToObject)(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
926
+ (0, unresolvableValue_1.assertNoDroppedValues)(args[0].expression, obj, spreadValues([
927
+ mergedStaticTable,
928
+ mergedKeyframesTable,
929
+ mergedViewTransitionTable,
930
+ mergedCreateThemeHashTable,
931
+ scannedTables.createThemeObjectTable,
932
+ mergedCreateTable,
933
+ mergedCreateStaticHashTable,
934
+ scannedTables.createStaticObjectTable,
935
+ ], localConstNodes));
828
936
  const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
829
937
  scannedTables.createStaticObjectTable[hash] = obj;
830
938
  }
@@ -2127,7 +2235,7 @@ const transformSource = async (env) => {
2127
2235
  const attributes = jsxAttributeOwnerMap.get(node.span.start)?.attributes ?? [];
2128
2236
  const classNameAttr = attributes.find((attr) => attr.type === 'JSXAttribute' &&
2129
2237
  attr.name.type === 'Identifier' &&
2130
- attr.name.value === 'className');
2238
+ attr.name.value === classProp);
2131
2239
  let existingClassExpr = '';
2132
2240
  if (classNameAttr) {
2133
2241
  replacements.push({
@@ -2186,12 +2294,12 @@ const transformSource = async (env) => {
2186
2294
  replacements.push({
2187
2295
  start: node.span.start - baseByteOffset,
2188
2296
  end: node.span.end - baseByteOffset,
2189
- content: `className={${replacement}}${styleAttr}`,
2297
+ content: `${classProp}={${replacement}}${styleAttr}`,
2190
2298
  });
2191
2299
  }
2192
2300
  else {
2193
2301
  const keptClass = existingClassExpr
2194
- ? `className={${existingClassExpr}}`
2302
+ ? `${classProp}={${existingClassExpr}}`
2195
2303
  : '';
2196
2304
  replacements.push({
2197
2305
  start: node.span.start - baseByteOffset,
@@ -0,0 +1,14 @@
1
+ import type { ObjectExpression, SpreadElement } from '@swc/core';
2
+ type SourceObject = ObjectExpression;
3
+ type StaticValues = Record<string, unknown>;
4
+ type SpreadInfo = {
5
+ values: StaticValues;
6
+ source?: SourceObject;
7
+ };
8
+ type ResolveSpread = (prop: SpreadElement) => SpreadInfo | null;
9
+ export type StyleContext = {
10
+ spread: ResolveSpread;
11
+ resolvesValue: (value: unknown) => boolean;
12
+ };
13
+ export declare const assertNoDroppedValues: (node: SourceObject, resolved: StaticValues | null | undefined, context?: StyleContext, ignore?: Set<string>) => void;
14
+ export {};
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertNoDroppedValues = void 0;
4
+ const keyValue = (key) => {
5
+ if (!key || typeof key !== 'object' || !('value' in key))
6
+ return;
7
+ const value = key.value;
8
+ return typeof value === 'string' || typeof value === 'number'
9
+ ? value
10
+ : undefined;
11
+ };
12
+ const unresolvableValue = (key, node) => new Error(`[plumeria] Cannot resolve the value of "${key}" at build time (${node.type}). ` +
13
+ `Values in css.create must be statically known; pass a runtime value through the ` +
14
+ `function form, css.create({ name: (value) => ({ ... }) }).`);
15
+ const overwrittenLater = (properties, index, key, context) => {
16
+ for (let i = index + 1; i < properties.length; i++) {
17
+ const later = properties[i];
18
+ if (later.type === 'SpreadElement') {
19
+ const provided = context?.spread(later);
20
+ if (!provided)
21
+ return true;
22
+ if (String(key) in provided.values)
23
+ return true;
24
+ continue;
25
+ }
26
+ if (later.type === 'KeyValueProperty' && keyValue(later.key) === key)
27
+ return true;
28
+ }
29
+ return false;
30
+ };
31
+ const RUNTIME_ONLY = new Set([
32
+ 'CallExpression',
33
+ 'NewExpression',
34
+ 'AwaitExpression',
35
+ 'TaggedTemplateExpression',
36
+ 'YieldExpression',
37
+ ]);
38
+ const readsAnyOf = (node, names) => {
39
+ if (!node || typeof node !== 'object')
40
+ return false;
41
+ const value = node;
42
+ if (value.type === 'Identifier' && typeof value.value === 'string')
43
+ return names.has(value.value);
44
+ for (const key of Object.keys(value)) {
45
+ if (key === 'span')
46
+ continue;
47
+ const child = value[key];
48
+ if (Array.isArray(child)) {
49
+ for (const item of child)
50
+ if (readsAnyOf(item, names))
51
+ return true;
52
+ }
53
+ else if (readsAnyOf(child, names))
54
+ return true;
55
+ }
56
+ return false;
57
+ };
58
+ const parameterNames = (func) => {
59
+ const names = new Set();
60
+ const add = (pattern) => {
61
+ if (!pattern || typeof pattern !== 'object')
62
+ return;
63
+ if (pattern.type === 'Identifier' && typeof pattern.value === 'string')
64
+ names.add(pattern.value);
65
+ for (const key of ['pat', 'left', 'argument', 'value', 'key'])
66
+ if (pattern[key])
67
+ add(pattern[key]);
68
+ for (const key of ['properties', 'elements'])
69
+ if (Array.isArray(pattern[key]))
70
+ pattern[key].forEach(add);
71
+ };
72
+ (func.params ?? []).forEach((param) => add(param?.pat ?? param));
73
+ return names;
74
+ };
75
+ const assertStyleFunction = (func, context) => {
76
+ const params = parameterNames(func);
77
+ const body = func.body;
78
+ const returned = body?.type === 'ObjectExpression'
79
+ ? body
80
+ : body?.type === 'ParenthesisExpression' &&
81
+ body.expression?.type === 'ObjectExpression'
82
+ ? body.expression
83
+ : null;
84
+ if (!returned)
85
+ return;
86
+ const walk = (object) => {
87
+ const properties = object.properties ?? [];
88
+ for (let index = 0; index < properties.length; index++) {
89
+ const prop = properties[index];
90
+ if (prop.type !== 'KeyValueProperty')
91
+ continue;
92
+ const key = keyValue(prop.key);
93
+ if ((typeof key === 'string' || typeof key === 'number') &&
94
+ overwrittenLater(properties, index, key, context))
95
+ continue;
96
+ const value = prop.value;
97
+ if (!value)
98
+ continue;
99
+ if (value.type === 'ObjectExpression') {
100
+ walk(value);
101
+ continue;
102
+ }
103
+ if (RUNTIME_ONLY.has(value.type) && !readsAnyOf(value, params))
104
+ throw unresolvableValue(key ?? '', value);
105
+ if ((value.type === 'Identifier' || value.type === 'MemberExpression') &&
106
+ context &&
107
+ !readsAnyOf(value, params) &&
108
+ !context.resolvesValue(value))
109
+ throw unresolvableValue(key ?? '', value);
110
+ }
111
+ };
112
+ walk(returned);
113
+ };
114
+ const keysSuppliedAfter = (properties, index, context) => {
115
+ const keys = new Set();
116
+ for (let i = index + 1; i < properties.length; i++) {
117
+ const later = properties[i];
118
+ if (later.type === 'SpreadElement') {
119
+ const provided = context?.spread(later);
120
+ if (!provided)
121
+ return null;
122
+ for (const name of Object.keys(provided.values))
123
+ keys.add(name);
124
+ continue;
125
+ }
126
+ if (later.type !== 'KeyValueProperty')
127
+ continue;
128
+ const key = keyValue(later.key);
129
+ if (typeof key !== 'string' && typeof key !== 'number')
130
+ return null;
131
+ keys.add(String(key));
132
+ }
133
+ return keys;
134
+ };
135
+ const assertNoDroppedValues = (node, resolved, context, ignore) => {
136
+ if (!resolved)
137
+ return;
138
+ for (let index = 0; index < node.properties.length; index++) {
139
+ const prop = node.properties[index];
140
+ if (prop.type === 'SpreadElement') {
141
+ const provided = context?.spread(prop);
142
+ if (!provided?.source)
143
+ continue;
144
+ const replaced = keysSuppliedAfter(node.properties, index, context);
145
+ if (replaced)
146
+ (0, exports.assertNoDroppedValues)(provided.source, provided.values, context, replaced);
147
+ continue;
148
+ }
149
+ if (prop.type !== 'KeyValueProperty')
150
+ continue;
151
+ const key = keyValue(prop.key);
152
+ if (typeof key !== 'string' && typeof key !== 'number')
153
+ continue;
154
+ if (ignore?.has(String(key)))
155
+ continue;
156
+ if (overwrittenLater(node.properties, index, key, context))
157
+ continue;
158
+ const value = prop.value;
159
+ if (!value)
160
+ continue;
161
+ if (value.type === 'ArrowFunctionExpression' ||
162
+ value.type === 'FunctionExpression') {
163
+ assertStyleFunction(value, context);
164
+ continue;
165
+ }
166
+ if (value.type === 'NullLiteral')
167
+ continue;
168
+ if (!(key in resolved))
169
+ throw unresolvableValue(key, value);
170
+ if (value.type === 'ObjectExpression') {
171
+ const nested = resolved[key];
172
+ if (nested && typeof nested === 'object')
173
+ (0, exports.assertNoDroppedValues)(value, nested, context);
174
+ }
175
+ }
176
+ };
177
+ exports.assertNoDroppedValues = assertNoDroppedValues;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/utils",
3
- "version": "19.2.13",
3
+ "version": "19.2.15",
4
4
  "description": "Plumeria Utils",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",