@plumeria/turbopack-loader 18.4.0 → 18.4.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.
Files changed (2) hide show
  1. package/dist/index.js +90 -170
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -111,81 +111,6 @@ const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
111
111
  (node.type === 'TemplateLiteral' && node.expressions.length === 0) ||
112
112
  utils_1.t.isIdentifier(node) ||
113
113
  utils_1.t.isMemberExpression(node);
114
- const namedParamsOf = (params, defaults) => {
115
- if (params.length !== 1)
116
- return undefined;
117
- const first = params[0];
118
- const pattern = (first?.pat ?? first);
119
- if (pattern?.type !== 'ObjectPattern')
120
- return undefined;
121
- const named = [];
122
- for (const prop of pattern.properties ?? []) {
123
- if (prop.type === 'AssignmentPatternProperty' && utils_1.t.isIdentifier(prop.key)) {
124
- named.push({ key: prop.key.value, local: prop.key.value });
125
- if (prop.value)
126
- defaults[prop.key.value] = prop.value;
127
- }
128
- else if (prop.type === 'KeyValuePatternProperty' &&
129
- utils_1.t.isIdentifier(prop.key) &&
130
- utils_1.t.isIdentifier(prop.value)) {
131
- named.push({ key: prop.key.value, local: prop.value.value });
132
- }
133
- else if (prop.type === 'KeyValuePatternProperty' &&
134
- utils_1.t.isIdentifier(prop.key) &&
135
- prop.value?.type === 'AssignmentPattern' &&
136
- utils_1.t.isIdentifier(prop.value.left)) {
137
- const pattern = prop.value;
138
- named.push({ key: String(prop.key.value), local: pattern.left.value });
139
- defaults[pattern.left.value] = pattern.right;
140
- }
141
- else {
142
- return undefined;
143
- }
144
- }
145
- return named.length > 0 ? named : undefined;
146
- };
147
- const styleFunctionsOf = (objExpr) => {
148
- const styleFunctions = {};
149
- objExpr.properties.forEach((prop) => {
150
- if (prop.type !== 'KeyValueProperty' || prop.key.type !== 'Identifier')
151
- return;
152
- const func = prop.value;
153
- if (func.type !== 'ArrowFunctionExpression' &&
154
- func.type !== 'FunctionExpression')
155
- return;
156
- const defaults = {};
157
- const params = func.params.map((p) => {
158
- const pattern = typeof p === 'object' && p !== null && 'pat' in p ? p.pat : p;
159
- if (utils_1.t.isIdentifier(pattern))
160
- return pattern.value;
161
- if (pattern?.type === 'AssignmentPattern' &&
162
- utils_1.t.isIdentifier(pattern.left)) {
163
- defaults[pattern.left.value] = pattern.right;
164
- return pattern.left.value;
165
- }
166
- return 'arg';
167
- });
168
- let actualBody = func.body;
169
- if (actualBody?.type === 'ParenthesisExpression')
170
- actualBody = actualBody.expression;
171
- if (actualBody?.type === 'BlockStatement') {
172
- const first = actualBody.stmts?.[0];
173
- if (first?.type === 'ReturnStatement')
174
- actualBody = first.argument;
175
- if (actualBody?.type === 'ParenthesisExpression')
176
- actualBody = actualBody.expression;
177
- }
178
- if (actualBody && actualBody.type === 'ObjectExpression') {
179
- styleFunctions[prop.key.value] = {
180
- params,
181
- named: namedParamsOf(func.params, defaults),
182
- defaults,
183
- body: actualBody,
184
- };
185
- }
186
- });
187
- return styleFunctions;
188
- };
189
114
  const foldDynamicVars = (vars) => {
190
115
  const grouped = new Map();
191
116
  [...vars]
@@ -207,59 +132,6 @@ const foldDynamicVars = (vars) => {
207
132
  return `"${cssVar}": ${value}`;
208
133
  });
209
134
  };
210
- const isUnitlessProp = (prop) => zss_engine_1.exceptionCamelCase.includes(prop) || prop.startsWith('--');
211
- const collectVarProps = (style, cssVar, props) => {
212
- const reference = `var(${cssVar})`;
213
- for (const [prop, value] of Object.entries(style)) {
214
- if (typeof value === 'string' && value.includes(reference))
215
- props.push(prop);
216
- else if (value !== null && typeof value === 'object')
217
- collectVarProps(value, cssVar, props);
218
- }
219
- };
220
- const retargetVar = (style, cssVar, next, unitless) => {
221
- const reference = `var(${cssVar})`;
222
- for (const [prop, value] of Object.entries(style)) {
223
- if (typeof value === 'string' && value.includes(reference)) {
224
- if (isUnitlessProp(prop) === unitless)
225
- style[prop] = value
226
- .split(reference)
227
- .join(`var(${next})`);
228
- }
229
- else if (value !== null && typeof value === 'object') {
230
- retargetVar(value, cssVar, next, unitless);
231
- }
232
- }
233
- };
234
- const splitVarByUnit = (style, cssVar) => {
235
- const props = [];
236
- collectVarProps(style, cssVar, props);
237
- if (props.length === 0)
238
- return [];
239
- const lead = props[0];
240
- const split = props.find((prop) => isUnitlessProp(prop) !== isUnitlessProp(lead));
241
- if (!split)
242
- return [{ cssVar, prop: lead }];
243
- const splitVar = `${cssVar}-${(0, zss_engine_1.camelToKebabCase)(split).replace(/^-+/, '')}`;
244
- retargetVar(style, cssVar, splitVar, isUnitlessProp(split));
245
- return [
246
- { cssVar, prop: lead },
247
- { cssVar: splitVar, prop: split },
248
- ];
249
- };
250
- const applyVarFallback = (style, cssVar, literal) => {
251
- const reference = `var(${cssVar})`;
252
- for (const [prop, value] of Object.entries(style)) {
253
- if (typeof value === 'string' && value.includes(reference)) {
254
- style[prop] = value
255
- .split(reference)
256
- .join(`var(${cssVar}, ${(0, zss_engine_1.applyCssValue)(literal, (0, zss_engine_1.camelToKebabCase)(prop))})`);
257
- }
258
- else if (value !== null && typeof value === 'object') {
259
- applyVarFallback(value, cssVar, literal);
260
- }
261
- }
262
- };
263
135
  async function loader(source) {
264
136
  const callback = this.async();
265
137
  const loaderOptions = this.getOptions?.() ??
@@ -484,7 +356,7 @@ async function loader(source) {
484
356
  scannedTables.createHashTable[uniqueKey];
485
357
  }
486
358
  if (scannedTables.createFunctionTable[uniqueKey]) {
487
- createFunctionImportMap[localName] = styleFunctionsOf(scannedTables.createFunctionTable[uniqueKey]);
359
+ createFunctionImportMap[localName] = (0, utils_1.styleFunctionsOf)(scannedTables.createFunctionTable[uniqueKey]);
488
360
  }
489
361
  if (scannedTables.variantsHashTable[uniqueKey]) {
490
362
  variantsImportMap[localName] =
@@ -584,6 +456,16 @@ async function loader(source) {
584
456
  for (const key of Object.keys(createStaticImportMap)) {
585
457
  mergedCreateStaticHashTable[key] = createStaticImportMap[key];
586
458
  }
459
+ const dynamicStyleTables = {
460
+ keyframesHashTable: mergedKeyframesTable,
461
+ viewTransitionHashTable: mergedViewTransitionTable,
462
+ createThemeHashTable: mergedCreateThemeHashTable,
463
+ createThemeObjectTable: scannedTables.createThemeObjectTable,
464
+ createHashTable: mergedCreateTable,
465
+ createStaticHashTable: mergedCreateStaticHashTable,
466
+ createStaticObjectTable: scannedTables.createStaticObjectTable,
467
+ variantsHashTable: mergedVariantsTable,
468
+ };
587
469
  const localCreateStyles = {};
588
470
  const localStyleAliases = {};
589
471
  const checkStyleAliasAssignment = (decl) => {
@@ -644,7 +526,7 @@ async function loader(source) {
644
526
  records.forEach((r) => (atomMap[r.key] = r.hash));
645
527
  hashMap[key] = atomMap;
646
528
  });
647
- const styleFunctions = styleFunctionsOf(init.arguments[0].expression);
529
+ const styleFunctions = (0, utils_1.styleFunctionsOf)(init.arguments[0].expression);
648
530
  if (utils_1.t.isIdentifier(node.id)) {
649
531
  idSpans.add(node.id.span.start);
650
532
  }
@@ -983,7 +865,16 @@ async function loader(source) {
983
865
  }
984
866
  return null;
985
867
  };
986
- const resolveDynamicCall = (expr) => {
868
+ const isStyleFunctionCall = (expr) => {
869
+ if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
870
+ return false;
871
+ const callee = expr.callee;
872
+ if (!utils_1.t.isIdentifier(callee.object) || !utils_1.t.isIdentifier(callee.property))
873
+ return false;
874
+ return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
875
+ createFunctionImportMap[callee.object.value]?.[callee.property.value]);
876
+ };
877
+ const resolveDynamicCall = (expr, forceRuntime = false) => {
987
878
  if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
988
879
  return null;
989
880
  const callee = expr.callee;
@@ -1027,7 +918,9 @@ async function loader(source) {
1027
918
  throwCompilationError(`Plumeria: ${getSource(expr)} leaves "${key}" unset, and a dynamic style function has no value to fall back on.`, expr);
1028
919
  return;
1029
920
  }
1030
- if (isStaticArgValue(source) && argObj[key] !== undefined)
921
+ if (!forceRuntime &&
922
+ isStaticArgValue(source) &&
923
+ argObj[key] !== undefined)
1031
924
  tempStaticTable[local] = argObj[key];
1032
925
  else
1033
926
  runtime.push({ param: local, source });
@@ -1035,6 +928,8 @@ async function loader(source) {
1035
928
  }
1036
929
  else if (callArgs.length === 1 &&
1037
930
  callArgs[0].expression.type === 'ObjectExpression') {
931
+ if (forceRuntime)
932
+ return null;
1038
933
  const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
1039
934
  func.params.forEach((p) => {
1040
935
  if (argObj[p] !== undefined)
@@ -1049,39 +944,10 @@ async function loader(source) {
1049
944
  runtime.push({ param: p, source: callArg.expression });
1050
945
  });
1051
946
  }
1052
- const withDefault = Object.entries(func.defaults ?? {}).filter(([param]) => tempStaticTable[param] === undefined);
1053
- const cssVars = {};
1054
- const varParams = Array.from(new Set([
1055
- ...runtime.map(({ param }) => param),
1056
- ...withDefault.map(([param]) => param),
1057
- ]));
1058
- if (varParams.length > 0) {
1059
- varParams.forEach((param) => (tempStaticTable[param] = param));
1060
- const probe = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
1061
- const hash = (0, zss_engine_1.genBase36Hash)(probe ?? {}, 1, 8);
1062
- varParams.forEach((param) => {
1063
- const cssVar = `--${hash}-${param}`;
1064
- tempStaticTable[param] = `var(${cssVar})`;
1065
- cssVars[param] = cssVar;
1066
- });
1067
- }
1068
- const style = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
1069
- if (!style)
947
+ const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables);
948
+ if (!resolved)
1070
949
  return null;
1071
- const varGroups = new Map();
1072
- varParams.forEach((param) => {
1073
- const cssVar = cssVars[param];
1074
- if (cssVar)
1075
- varGroups.set(param, splitVarByUnit(style, cssVar));
1076
- });
1077
- withDefault.forEach(([param, expr]) => {
1078
- const literal = expr.type === 'StringLiteral' || expr.type === 'NumericLiteral'
1079
- ? expr.value
1080
- : undefined;
1081
- if (literal === undefined)
1082
- return;
1083
- (varGroups.get(param) ?? []).forEach(({ cssVar }) => applyVarFallback(style, cssVar, literal));
1084
- });
950
+ const { style, varGroups } = resolved;
1085
951
  const vars = [];
1086
952
  runtime.forEach(({ param, source }) => {
1087
953
  const groups = varGroups.get(param);
@@ -1104,7 +970,7 @@ async function loader(source) {
1104
970
  valueExpr = JSON.stringify((0, zss_engine_1.applyCssValue)(argSource.slice(1, -1), kebabProp));
1105
971
  }
1106
972
  else {
1107
- valueExpr = isUnitlessProp(prop)
973
+ valueExpr = (0, utils_1.isUnitlessProp)(prop)
1108
974
  ? argSource
1109
975
  : `(typeof (${argSource}) === 'number' ? (${argSource}) + 'px' : (${argSource}))`;
1110
976
  }
@@ -1122,6 +988,7 @@ async function loader(source) {
1122
988
  });
1123
989
  const conditionals = [];
1124
990
  const dynamicVars = [];
991
+ const propVarSpreads = [];
1125
992
  let groupIdCounter = 0;
1126
993
  let sourceOrder = 0;
1127
994
  const baseChunks = [];
@@ -1336,9 +1203,23 @@ async function loader(source) {
1336
1203
  }
1337
1204
  if (!possibilities || possibilities.length === 0)
1338
1205
  return false;
1339
- const testLHS = gates.length
1340
- ? `((${gates.join(' && ')}) ? ${source} : "")`
1206
+ const carriesVars = possibilities.some((entry) => entry.hasVars);
1207
+ if (carriesVars && !isStyleProp) {
1208
+ throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
1209
+ `Apply it to ${styleProp} on the element instead.`, expr);
1210
+ }
1211
+ const gate = gates.length ? `(${gates.join(' && ')}) && ` : '';
1212
+ if (carriesVars) {
1213
+ const spread = `...(${gate}${source} && ${source}.vars)`;
1214
+ if (!propVarSpreads.includes(spread))
1215
+ propVarSpreads.push(spread);
1216
+ }
1217
+ const token = carriesVars
1218
+ ? `((${source} && ${source}.key) || ${source})`
1341
1219
  : source;
1220
+ const testLHS = gates.length
1221
+ ? `((${gates.join(' && ')}) ? ${token} : "")`
1222
+ : token;
1342
1223
  const currentGroupId = ++groupIdCounter;
1343
1224
  const currentOrder = sourceOrder++;
1344
1225
  const seen = new Set();
@@ -1577,6 +1458,7 @@ async function loader(source) {
1577
1458
  isOptimizable,
1578
1459
  baseStyle,
1579
1460
  dynamicVars,
1461
+ propVarSpreads,
1580
1462
  };
1581
1463
  }
1582
1464
  const stateSources = baseChunks.map(({ order, style }) => ({ order, style: style }));
@@ -1832,7 +1714,13 @@ async function loader(source) {
1832
1714
  classParts.push(`(${JSON.stringify(results)}[${masterKeyExpr || '""'}] || ${baseConflictClass ? JSON.stringify(baseConflictClass) : '""'})`);
1833
1715
  }
1834
1716
  classParts.push(...dynamicClassParts);
1835
- return { classParts, isOptimizable, baseStyle, dynamicVars };
1717
+ return {
1718
+ classParts,
1719
+ isOptimizable,
1720
+ baseStyle,
1721
+ dynamicVars,
1722
+ propVarSpreads,
1723
+ };
1836
1724
  };
1837
1725
  (0, utils_1.traverse)(ast, {
1838
1726
  JSXOpeningElement({ node }) {
@@ -2033,14 +1921,40 @@ async function loader(source) {
2033
1921
  node.value &&
2034
1922
  node.value.type === 'JSXExpressionContainer') {
2035
1923
  const expr = node.value.expression;
1924
+ const carrierFor = (subNode) => {
1925
+ const vars = [];
1926
+ let unresolved = false;
1927
+ (0, utils_1.traverse)(subNode, {
1928
+ CallExpression({ node: call }) {
1929
+ if (!isStyleFunctionCall(call))
1930
+ return;
1931
+ const resolved = resolveDynamicCall(call, true);
1932
+ if (!resolved) {
1933
+ unresolved = true;
1934
+ return;
1935
+ }
1936
+ vars.push(...resolved.vars);
1937
+ },
1938
+ });
1939
+ if (unresolved)
1940
+ return null;
1941
+ return `{ ${foldDynamicVars(vars).join(', ')} }`;
1942
+ };
2036
1943
  const replaceWithKey = (subNode) => {
2037
1944
  const entry = list.find((x) => x.spanStart === subNode.span.start &&
2038
1945
  x.filePath === resourcePath);
2039
1946
  if (entry) {
1947
+ let content = JSON.stringify(entry.key);
1948
+ if (entry.hasVars) {
1949
+ const carrier = carrierFor(subNode);
1950
+ if (!carrier)
1951
+ return false;
1952
+ content = `{ key: ${content}, vars: ${carrier} }`;
1953
+ }
2040
1954
  replacements.push({
2041
1955
  start: subNode.span.start - baseByteOffset,
2042
1956
  end: subNode.span.end - baseByteOffset,
2043
- content: JSON.stringify(entry.key),
1957
+ content,
2044
1958
  });
2045
1959
  processStyleRecords(entry.styleObj);
2046
1960
  return true;
@@ -2058,6 +1972,11 @@ async function loader(source) {
2058
1972
  excludeSubtreeSpans(subNode);
2059
1973
  }
2060
1974
  },
1975
+ CallExpression({ node: subNode }) {
1976
+ if (replaceWithKey(subNode)) {
1977
+ excludeSubtreeSpans(subNode);
1978
+ }
1979
+ },
2061
1980
  });
2062
1981
  }
2063
1982
  }
@@ -2133,10 +2052,11 @@ async function loader(source) {
2133
2052
  }
2134
2053
  }
2135
2054
  }
2136
- const { classParts, isOptimizable, baseStyle, dynamicVars } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
2055
+ const { classParts, isOptimizable, baseStyle, dynamicVars, propVarSpreads, } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
2137
2056
  const styleParts = [
2138
2057
  ...existingStyleParts,
2139
2058
  ...foldDynamicVars(dynamicVars),
2059
+ ...propVarSpreads,
2140
2060
  ];
2141
2061
  const styleAttr = styleParts.length > 0 || existingStyleExpr
2142
2062
  ? ` style={{ ${[existingStyleExpr, ...styleParts].filter(Boolean).join(', ')} }}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/turbopack-loader",
3
- "version": "18.4.0",
3
+ "version": "18.4.1",
4
4
  "description": "Plumeria Turbopack-loader",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -29,8 +29,8 @@
29
29
  "zero-virtual.css"
30
30
  ],
31
31
  "dependencies": {
32
- "@plumeria/compiler": "^18.4.0",
33
- "@plumeria/utils": "^18.4.0"
32
+ "@plumeria/compiler": "^18.4.1",
33
+ "@plumeria/utils": "^18.4.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@swc/core": "1.15.47",