@plumeria/unplugin 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/core.js +244 -43
- package/dist/core.mjs +245 -44
- package/package.json +2 -2
package/dist/core.js
CHANGED
|
@@ -87,6 +87,26 @@ const destructuredPropAliases = (fn) => {
|
|
|
87
87
|
}
|
|
88
88
|
return aliases;
|
|
89
89
|
};
|
|
90
|
+
const spreadStyleMessage = (source) => `Plumeria: Spread elements in a style array are not supported: "...${source}". ` +
|
|
91
|
+
`List each style explicitly.`;
|
|
92
|
+
const resolveLocalStyleAlias = (aliases, expression) => {
|
|
93
|
+
let current = expression;
|
|
94
|
+
const seen = new Set();
|
|
95
|
+
while (utils_1.t.isIdentifier(current)) {
|
|
96
|
+
const name = current.value;
|
|
97
|
+
if (seen.has(name))
|
|
98
|
+
break;
|
|
99
|
+
seen.add(name);
|
|
100
|
+
const candidates = aliases[name];
|
|
101
|
+
if (!candidates || candidates.length === 0)
|
|
102
|
+
break;
|
|
103
|
+
const candidate = candidates.find((candidate) => candidate.context === current.ctxt);
|
|
104
|
+
if (!candidate)
|
|
105
|
+
break;
|
|
106
|
+
current = candidate.expression;
|
|
107
|
+
}
|
|
108
|
+
return current;
|
|
109
|
+
};
|
|
90
110
|
const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
|
|
91
111
|
node.type === 'NumericLiteral' ||
|
|
92
112
|
node.type === 'BooleanLiteral' ||
|
|
@@ -273,11 +293,32 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
273
293
|
}
|
|
274
294
|
const components = [];
|
|
275
295
|
const propAliases = new Map();
|
|
296
|
+
const propDefaults = new Map();
|
|
297
|
+
const declaredProps = new Map();
|
|
276
298
|
const addComponent = (name, fn) => {
|
|
277
299
|
components.push({ name, node: fn });
|
|
300
|
+
const first = fn.params[0];
|
|
301
|
+
const pattern = unwrapPatternDefault(first?.pat ?? first);
|
|
302
|
+
const defaults = new Map();
|
|
303
|
+
for (const item of pattern?.properties ?? []) {
|
|
304
|
+
if (item.type === 'AssignmentPatternProperty' && item.value)
|
|
305
|
+
defaults.set(item.key.value, item.value);
|
|
306
|
+
if (item.type === 'KeyValuePatternProperty' &&
|
|
307
|
+
item.value?.type === 'AssignmentPattern')
|
|
308
|
+
defaults.set(item.key.value, item.value.right);
|
|
309
|
+
}
|
|
310
|
+
propDefaults.set(name, defaults);
|
|
278
311
|
const aliases = destructuredPropAliases(fn);
|
|
279
312
|
if (aliases.size > 0)
|
|
280
313
|
propAliases.set(name, aliases);
|
|
314
|
+
const declared = new Set();
|
|
315
|
+
for (const item of pattern?.properties ?? []) {
|
|
316
|
+
const key = item.key;
|
|
317
|
+
if (utils_1.t.isIdentifier(key) || utils_1.t.isStringLiteral(key))
|
|
318
|
+
declared.add(String(key.value));
|
|
319
|
+
}
|
|
320
|
+
if (declared.size > 0)
|
|
321
|
+
declaredProps.set(name, declared);
|
|
281
322
|
};
|
|
282
323
|
for (const node of ast.body) {
|
|
283
324
|
const statement = unwrapExport(node);
|
|
@@ -510,12 +551,15 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
510
551
|
const checkStyleAliasAssignment = (decl) => {
|
|
511
552
|
if (!utils_1.t.isIdentifier(decl.id) || !decl.init)
|
|
512
553
|
return;
|
|
513
|
-
const init = decl.init;
|
|
554
|
+
const init = (0, utils_1.unwrapExpression)(decl.init);
|
|
514
555
|
if (utils_1.t.isMemberExpression(init) && utils_1.t.isIdentifier(init.object)) {
|
|
515
556
|
const objName = init.object.value;
|
|
516
557
|
if (localCreateStyles[objName] !== undefined ||
|
|
517
558
|
mergedCreateTable[objName] !== undefined) {
|
|
518
|
-
localStyleAliases[decl.id.value]
|
|
559
|
+
(localStyleAliases[decl.id.value] ??= []).push({
|
|
560
|
+
expression: init,
|
|
561
|
+
context: decl.id.ctxt,
|
|
562
|
+
});
|
|
519
563
|
}
|
|
520
564
|
}
|
|
521
565
|
};
|
|
@@ -525,9 +569,43 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
525
569
|
const idSpans = new Set();
|
|
526
570
|
const excludedSpans = new Set();
|
|
527
571
|
const referenceIdents = (0, utils_1.collectReferenceIdentifiers)(ast);
|
|
572
|
+
const topLevelDeclarators = new Set();
|
|
573
|
+
for (const statement of ast.body) {
|
|
574
|
+
const declaration = unwrapExport(statement);
|
|
575
|
+
if (utils_1.t.isVariableDeclaration(declaration)) {
|
|
576
|
+
declaration.declarations.forEach((decl) => topLevelDeclarators.add(decl));
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const unwrapStyleExpression = (node) => {
|
|
580
|
+
while (node &&
|
|
581
|
+
[
|
|
582
|
+
'ParenthesisExpression',
|
|
583
|
+
'TsAsExpression',
|
|
584
|
+
'TsSatisfiesExpression',
|
|
585
|
+
'TsNonNullExpression',
|
|
586
|
+
'TsConstAssertion',
|
|
587
|
+
'TsTypeAssertion',
|
|
588
|
+
].includes(node.type))
|
|
589
|
+
node = node.expression;
|
|
590
|
+
return node;
|
|
591
|
+
};
|
|
592
|
+
const literalObjectArgument = (node, seen = new Set()) => {
|
|
593
|
+
node = unwrapStyleExpression(node);
|
|
594
|
+
if (utils_1.t.isObjectExpression(node))
|
|
595
|
+
return node;
|
|
596
|
+
if (!utils_1.t.isIdentifier(node) || seen.has(node.value))
|
|
597
|
+
return null;
|
|
598
|
+
seen.add(node.value);
|
|
599
|
+
const declaration = [...topLevelDeclarators].find((decl) => utils_1.t.isIdentifier(decl.id) &&
|
|
600
|
+
decl.id.value === node.value);
|
|
601
|
+
return declaration?.init
|
|
602
|
+
? literalObjectArgument(declaration.init, seen)
|
|
603
|
+
: null;
|
|
604
|
+
};
|
|
605
|
+
const registeredStyleCalls = new Set();
|
|
528
606
|
const registerStyle = (node, declSpan, isExported) => {
|
|
529
607
|
let propName;
|
|
530
|
-
const init = node.init;
|
|
608
|
+
const init = unwrapStyleExpression(node.init);
|
|
531
609
|
if (utils_1.t.isIdentifier(node.id) &&
|
|
532
610
|
init &&
|
|
533
611
|
utils_1.t.isCallExpression(init) &&
|
|
@@ -552,6 +630,19 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
552
630
|
}
|
|
553
631
|
}
|
|
554
632
|
if (propName && init && utils_1.t.isCallExpression(init)) {
|
|
633
|
+
if (['create', 'createTheme', 'createStatic'].includes(propName) &&
|
|
634
|
+
!topLevelDeclarators.has(node)) {
|
|
635
|
+
throwCompilationError(`Plumeria: css.${propName} must be assigned to a top-level variable so its styles can be resolved across files. Move this declaration outside the function or block.`, node);
|
|
636
|
+
}
|
|
637
|
+
if (['create', 'createTheme', 'createStatic'].includes(propName)) {
|
|
638
|
+
const argumentIndex = propName === 'createTheme' ? 1 : 0;
|
|
639
|
+
const argument = init.arguments[argumentIndex];
|
|
640
|
+
const object = argument && literalObjectArgument(argument.expression);
|
|
641
|
+
if (!object)
|
|
642
|
+
throwCompilationError(`Plumeria: css.${propName} needs a style object it can read at build time. Pass an object literal or a top-level constant containing one.`, init);
|
|
643
|
+
argument.expression = object;
|
|
644
|
+
registeredStyleCalls.add(init.span.start);
|
|
645
|
+
}
|
|
555
646
|
if (propName === 'create' &&
|
|
556
647
|
utils_1.t.isObjectExpression(init.arguments[0].expression)) {
|
|
557
648
|
const obj = (0, utils_1.objectExpressionToObject)(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
@@ -749,6 +840,10 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
749
840
|
}
|
|
750
841
|
}
|
|
751
842
|
if (propName) {
|
|
843
|
+
if (['create', 'createTheme', 'createStatic'].includes(propName) &&
|
|
844
|
+
!registeredStyleCalls.has(node.span.start)) {
|
|
845
|
+
throwCompilationError(`Plumeria: css.${propName} must be assigned to a named top-level variable. Destructuring, assignment statements, and default-exported calls cannot be compiled.`, node);
|
|
846
|
+
}
|
|
752
847
|
const args = node.arguments;
|
|
753
848
|
if (propName === 'keyframes' && args.length > 0) {
|
|
754
849
|
const expr = args[0].expression;
|
|
@@ -814,12 +909,17 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
814
909
|
const jsxOpeningElementMap = new Map();
|
|
815
910
|
const componentParamNames = new Set();
|
|
816
911
|
const addFirstParamName = (fn) => {
|
|
817
|
-
const
|
|
912
|
+
const first = fn.params[0];
|
|
913
|
+
const p = unwrapPatternDefault(first?.pat ?? first);
|
|
818
914
|
if (utils_1.t.isIdentifier(p)) {
|
|
819
915
|
componentParamNames.add(p.value);
|
|
820
916
|
}
|
|
821
|
-
else if (p?.
|
|
822
|
-
|
|
917
|
+
else if (p?.type === 'ObjectPattern') {
|
|
918
|
+
for (const item of p.properties) {
|
|
919
|
+
if (item.type === 'RestElement' && utils_1.t.isIdentifier(item.argument)) {
|
|
920
|
+
componentParamNames.add(item.argument.value);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
823
923
|
}
|
|
824
924
|
};
|
|
825
925
|
for (const node of ast.body) {
|
|
@@ -856,6 +956,22 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
856
956
|
return sourceBuffer.subarray(start, end).toString('utf-8');
|
|
857
957
|
};
|
|
858
958
|
const resolveStyleObject = (expr) => {
|
|
959
|
+
expr = (0, utils_1.unwrapExpression)(expr);
|
|
960
|
+
expr = resolveLocalStyleAlias(localStyleAliases, expr);
|
|
961
|
+
if (expr.type === 'ArrayExpression') {
|
|
962
|
+
let merged = {};
|
|
963
|
+
for (const element of expr.elements ?? []) {
|
|
964
|
+
if (!element)
|
|
965
|
+
continue;
|
|
966
|
+
if (element.spread)
|
|
967
|
+
throwCompilationError(spreadStyleMessage(getSource(element.expression)), element.expression);
|
|
968
|
+
const style = resolveStyleObject(element.expression);
|
|
969
|
+
if (!style)
|
|
970
|
+
return null;
|
|
971
|
+
merged = (0, utils_1.deepMerge)(merged, style);
|
|
972
|
+
}
|
|
973
|
+
return merged;
|
|
974
|
+
}
|
|
859
975
|
if (utils_1.t.isObjectExpression(expr)) {
|
|
860
976
|
return (0, utils_1.objectExpressionToObject)(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
861
977
|
}
|
|
@@ -915,6 +1031,26 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
915
1031
|
return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
|
|
916
1032
|
createFunctionImportMap[callee.object.value]?.[callee.property.value]);
|
|
917
1033
|
};
|
|
1034
|
+
const carriesStyleReference = (expression) => {
|
|
1035
|
+
const node = (0, utils_1.unwrapExpression)(expression);
|
|
1036
|
+
if (node.type === 'ArrayExpression')
|
|
1037
|
+
return node.elements.some((element) => !!element && carriesStyleReference(element.expression));
|
|
1038
|
+
if (isStyleFunctionCall(node))
|
|
1039
|
+
return true;
|
|
1040
|
+
if (utils_1.t.isObjectExpression(node))
|
|
1041
|
+
return false;
|
|
1042
|
+
return resolveStyleObject(node) !== null;
|
|
1043
|
+
};
|
|
1044
|
+
const assertNoStyleArraySpread = (expression) => {
|
|
1045
|
+
const node = (0, utils_1.unwrapExpression)(expression);
|
|
1046
|
+
if (node.type !== 'ArrayExpression')
|
|
1047
|
+
return;
|
|
1048
|
+
const spread = node.elements.find((element) => element?.spread);
|
|
1049
|
+
if (!spread)
|
|
1050
|
+
return;
|
|
1051
|
+
if (carriesStyleReference(node))
|
|
1052
|
+
throwCompilationError(spreadStyleMessage(getSource(spread.expression)), spread.expression);
|
|
1053
|
+
};
|
|
918
1054
|
const resolveDynamicCall = (expr, forceRuntime = false) => {
|
|
919
1055
|
if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
|
|
920
1056
|
return null;
|
|
@@ -930,8 +1066,14 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
930
1066
|
if (callArgs.some((a) => a.spread))
|
|
931
1067
|
return null;
|
|
932
1068
|
const tempStaticTable = { ...mergedStaticTable };
|
|
1069
|
+
const providedParams = new Set();
|
|
933
1070
|
const runtime = [];
|
|
934
|
-
const resolveObjectArg = (argExpr) => (0, utils_1.objectExpressionToObject)(
|
|
1071
|
+
const resolveObjectArg = (argExpr) => (0, utils_1.objectExpressionToObject)({
|
|
1072
|
+
...argExpr,
|
|
1073
|
+
properties: argExpr.properties.filter((prop) => prop.type === 'Identifier' ||
|
|
1074
|
+
(prop.type === 'KeyValueProperty' &&
|
|
1075
|
+
isStaticArgValue(prop.value))),
|
|
1076
|
+
}, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
935
1077
|
if (func.named) {
|
|
936
1078
|
const argExpr = callArgs[0]?.expression;
|
|
937
1079
|
if (callArgs.length > 1 ||
|
|
@@ -961,8 +1103,10 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
961
1103
|
}
|
|
962
1104
|
if (!forceRuntime &&
|
|
963
1105
|
isStaticArgValue(source) &&
|
|
964
|
-
argObj[key] !== undefined)
|
|
1106
|
+
argObj[key] !== undefined) {
|
|
965
1107
|
tempStaticTable[local] = argObj[key];
|
|
1108
|
+
providedParams.add(local);
|
|
1109
|
+
}
|
|
966
1110
|
else
|
|
967
1111
|
runtime.push({ param: local, source });
|
|
968
1112
|
});
|
|
@@ -973,8 +1117,10 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
973
1117
|
return null;
|
|
974
1118
|
const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
|
|
975
1119
|
func.params.forEach((p) => {
|
|
976
|
-
if (argObj[p] !== undefined)
|
|
1120
|
+
if (argObj[p] !== undefined) {
|
|
977
1121
|
tempStaticTable[p] = argObj[p];
|
|
1122
|
+
providedParams.add(p);
|
|
1123
|
+
}
|
|
978
1124
|
});
|
|
979
1125
|
}
|
|
980
1126
|
else {
|
|
@@ -985,7 +1131,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
985
1131
|
runtime.push({ param: p, source: callArg.expression });
|
|
986
1132
|
});
|
|
987
1133
|
}
|
|
988
|
-
const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables);
|
|
1134
|
+
const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables, providedParams);
|
|
989
1135
|
if (!resolved)
|
|
990
1136
|
return null;
|
|
991
1137
|
const { style, varGroups } = resolved;
|
|
@@ -1023,10 +1169,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1023
1169
|
};
|
|
1024
1170
|
const buildClassParts = (args, dynamicClassParts = [], existingClass = '', isStyleProp = false) => {
|
|
1025
1171
|
args.forEach((arg) => {
|
|
1026
|
-
|
|
1027
|
-
if (utils_1.t.isIdentifier(expr) && localStyleAliases[expr.value]) {
|
|
1028
|
-
arg.expression = localStyleAliases[expr.value];
|
|
1029
|
-
}
|
|
1172
|
+
arg.expression = resolveLocalStyleAlias(localStyleAliases, arg.expression);
|
|
1030
1173
|
});
|
|
1031
1174
|
const conditionals = [];
|
|
1032
1175
|
const dynamicVars = [];
|
|
@@ -1150,6 +1293,8 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1150
1293
|
return buildDecision(node, prefix, off, { n: 0 }, scoped);
|
|
1151
1294
|
};
|
|
1152
1295
|
const collectConditions = (node, currentTestStrings = [], argOrder) => {
|
|
1296
|
+
node = (0, utils_1.unwrapExpression)(node);
|
|
1297
|
+
node = resolveLocalStyleAlias(localStyleAliases, node);
|
|
1153
1298
|
if (isNoOpStyle(node))
|
|
1154
1299
|
return true;
|
|
1155
1300
|
let branchStyle = resolveStyleObject(node);
|
|
@@ -1228,6 +1373,12 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1228
1373
|
utils_1.t.isIdentifier(expr.property);
|
|
1229
1374
|
if (!utils_1.t.isIdentifier(expr) && !isParamMember)
|
|
1230
1375
|
return false;
|
|
1376
|
+
const paramObject = isParamMember
|
|
1377
|
+
? expr.object.value
|
|
1378
|
+
: undefined;
|
|
1379
|
+
const isPropsMember = Boolean(paramObject &&
|
|
1380
|
+
localCreateStyles[paramObject] === undefined &&
|
|
1381
|
+
mergedCreateTable[paramObject] === undefined);
|
|
1231
1382
|
const varName = utils_1.t.isIdentifier(expr)
|
|
1232
1383
|
? expr.value
|
|
1233
1384
|
: expr.property.value;
|
|
@@ -1252,8 +1403,43 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1252
1403
|
if (candidates.length > 0)
|
|
1253
1404
|
possibilities = candidates;
|
|
1254
1405
|
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1406
|
+
const fallback = owner && propDefaults.get(owner)?.get(propName);
|
|
1407
|
+
if (fallback) {
|
|
1408
|
+
const style = resolveStyleObject(fallback);
|
|
1409
|
+
if (style) {
|
|
1410
|
+
const atoms = {};
|
|
1411
|
+
(0, utils_1.getStyleRecords)(style).forEach((record) => {
|
|
1412
|
+
atoms[record.key] = record.hash;
|
|
1413
|
+
});
|
|
1414
|
+
const key = (0, zss_engine_1.genBase36Hash)(Object.values(atoms).join(' '), 1, 8);
|
|
1415
|
+
possibilities = [
|
|
1416
|
+
...(possibilities ?? []),
|
|
1417
|
+
{ key, styleObj: style },
|
|
1418
|
+
];
|
|
1419
|
+
const span = fallback.span;
|
|
1420
|
+
{
|
|
1421
|
+
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
1422
|
+
const replacement = replacements[i];
|
|
1423
|
+
if (replacement.start >= span.start - baseByteOffset &&
|
|
1424
|
+
replacement.end <= span.end - baseByteOffset)
|
|
1425
|
+
replacements.splice(i, 1);
|
|
1426
|
+
}
|
|
1427
|
+
excludeSubtreeSpans(fallback);
|
|
1428
|
+
replacements.push({
|
|
1429
|
+
start: span.start - baseByteOffset,
|
|
1430
|
+
end: span.end - baseByteOffset,
|
|
1431
|
+
content: JSON.stringify(key),
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
else {
|
|
1436
|
+
assertResolvable(fallback);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
if (!possibilities || possibilities.length === 0) {
|
|
1440
|
+
return Boolean(isPropsMember ||
|
|
1441
|
+
(owner && declaredProps.get(owner)?.has(propName)));
|
|
1442
|
+
}
|
|
1257
1443
|
const carriesVars = possibilities.some((entry) => entry.hasVars);
|
|
1258
1444
|
if (carriesVars && !isStyleProp) {
|
|
1259
1445
|
throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
|
|
@@ -1969,50 +2155,61 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1969
2155
|
}
|
|
1970
2156
|
}
|
|
1971
2157
|
if (compKey) {
|
|
2158
|
+
if (node.value?.type === 'JSXExpressionContainer')
|
|
2159
|
+
assertNoStyleArraySpread(node.value.expression);
|
|
1972
2160
|
const list = scannedTables.componentPropsTable?.[compKey]?.[attrName];
|
|
1973
2161
|
if (list &&
|
|
1974
2162
|
node.value &&
|
|
1975
2163
|
node.value.type === 'JSXExpressionContainer') {
|
|
1976
2164
|
const expr = node.value.expression;
|
|
1977
|
-
const carrierFor = (subNode) => {
|
|
2165
|
+
const carrierFor = (subNode, calls) => {
|
|
1978
2166
|
const vars = [];
|
|
1979
2167
|
let unresolved = false;
|
|
1980
|
-
(
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2168
|
+
for (const expression of calls ?? [subNode])
|
|
2169
|
+
(0, utils_1.traverse)(expression, {
|
|
2170
|
+
CallExpression({ node: call }) {
|
|
2171
|
+
if (!isStyleFunctionCall(call))
|
|
2172
|
+
return;
|
|
2173
|
+
const resolved = resolveDynamicCall(call, true);
|
|
2174
|
+
if (!resolved) {
|
|
2175
|
+
unresolved = true;
|
|
2176
|
+
return;
|
|
2177
|
+
}
|
|
2178
|
+
vars.push(...resolved.vars);
|
|
2179
|
+
},
|
|
2180
|
+
});
|
|
1992
2181
|
if (unresolved)
|
|
1993
2182
|
return null;
|
|
1994
2183
|
return `{ ${foldDynamicVars(vars).join(', ')} }`;
|
|
1995
2184
|
};
|
|
1996
2185
|
const replaceWithKey = (subNode) => {
|
|
1997
|
-
const
|
|
1998
|
-
|
|
1999
|
-
if (
|
|
2000
|
-
|
|
2186
|
+
const entries = list.filter((entry) => entry.spanStart === subNode.span.start &&
|
|
2187
|
+
entry.filePath === resourcePath);
|
|
2188
|
+
if (!entries.length)
|
|
2189
|
+
return false;
|
|
2190
|
+
let content = '""';
|
|
2191
|
+
for (const entry of [...entries].reverse()) {
|
|
2192
|
+
let value = JSON.stringify(entry.key);
|
|
2001
2193
|
if (entry.hasVars) {
|
|
2002
|
-
const carrier = carrierFor(subNode);
|
|
2194
|
+
const carrier = carrierFor(subNode, entry.dynamicCalls);
|
|
2003
2195
|
if (!carrier)
|
|
2004
2196
|
return false;
|
|
2005
|
-
|
|
2197
|
+
value = `{ key: ${value}, vars: ${carrier} }`;
|
|
2006
2198
|
}
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2199
|
+
const condition = entry.conditions
|
|
2200
|
+
?.map(({ test, truthy }) => `${truthy ? '' : '!'}(${getSource(test)})`)
|
|
2201
|
+
.join(' && ');
|
|
2202
|
+
content = condition
|
|
2203
|
+
? `((${condition}) ? ${value} : ${content})`
|
|
2204
|
+
: value;
|
|
2012
2205
|
processStyleRecords(entry.styleObj);
|
|
2013
|
-
return true;
|
|
2014
2206
|
}
|
|
2015
|
-
|
|
2207
|
+
replacements.push({
|
|
2208
|
+
start: subNode.span.start - baseByteOffset,
|
|
2209
|
+
end: subNode.span.end - baseByteOffset,
|
|
2210
|
+
content,
|
|
2211
|
+
});
|
|
2212
|
+
return true;
|
|
2016
2213
|
};
|
|
2017
2214
|
(0, utils_1.traverse)(expr, {
|
|
2018
2215
|
MemberExpression({ node: subNode }) {
|
|
@@ -2041,7 +2238,11 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2041
2238
|
const args = expr.type === 'ArrayExpression'
|
|
2042
2239
|
? expr.elements
|
|
2043
2240
|
.filter((el) => el !== undefined)
|
|
2044
|
-
.map((el) =>
|
|
2241
|
+
.map((el) => {
|
|
2242
|
+
if (el.spread)
|
|
2243
|
+
throwCompilationError(spreadStyleMessage(getSource(el.expression)), el.expression);
|
|
2244
|
+
return { expression: el.expression };
|
|
2245
|
+
})
|
|
2045
2246
|
: [{ expression: expr }];
|
|
2046
2247
|
const dynamicClassParts = [];
|
|
2047
2248
|
const existingStyleParts = [];
|
package/dist/core.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { createFilter } from '@rollup/pluginutils';
|
|
|
2
2
|
import { parseSync } from '@swc/core';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { applyCssValue, genBase36Hash, camelToKebabCase, isAtRule, } from 'zss-engine';
|
|
5
|
-
import { traverse, resolvePropertyPolicy, assertPropertyPolicy, collectReferenceIdentifiers, getStyleRecords, getStateWeights, collectLocalConsts, objectExpressionToObject, t, getRootIdentifier, extractOndemandStyles, deepMerge, scanAll, resolveFileError, resolveImportPath, getLeadingCommentLength, optimizer, styleFunctionsOf, isUnitlessProp, resolveDynamicStyle, themeHashOf, getFileDependencies, resolveExport, resolveComponentKey, resolveThemeSelector, DEFAULT_STYLE_PROP, } from '@plumeria/utils';
|
|
5
|
+
import { traverse, resolvePropertyPolicy, assertPropertyPolicy, collectReferenceIdentifiers, getStyleRecords, getStateWeights, collectLocalConsts, objectExpressionToObject, t, getRootIdentifier, unwrapExpression, extractOndemandStyles, deepMerge, scanAll, resolveFileError, resolveImportPath, getLeadingCommentLength, optimizer, styleFunctionsOf, isUnitlessProp, resolveDynamicStyle, themeHashOf, getFileDependencies, resolveExport, resolveComponentKey, resolveThemeSelector, DEFAULT_STYLE_PROP, } from '@plumeria/utils';
|
|
6
6
|
export const TARGET_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx'];
|
|
7
7
|
export const EXTENSION_PATTERN = /\.(ts|tsx|js|jsx)$/;
|
|
8
8
|
const unwrapExport = (node) => {
|
|
@@ -51,6 +51,26 @@ const destructuredPropAliases = (fn) => {
|
|
|
51
51
|
}
|
|
52
52
|
return aliases;
|
|
53
53
|
};
|
|
54
|
+
const spreadStyleMessage = (source) => `Plumeria: Spread elements in a style array are not supported: "...${source}". ` +
|
|
55
|
+
`List each style explicitly.`;
|
|
56
|
+
const resolveLocalStyleAlias = (aliases, expression) => {
|
|
57
|
+
let current = expression;
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
while (t.isIdentifier(current)) {
|
|
60
|
+
const name = current.value;
|
|
61
|
+
if (seen.has(name))
|
|
62
|
+
break;
|
|
63
|
+
seen.add(name);
|
|
64
|
+
const candidates = aliases[name];
|
|
65
|
+
if (!candidates || candidates.length === 0)
|
|
66
|
+
break;
|
|
67
|
+
const candidate = candidates.find((candidate) => candidate.context === current.ctxt);
|
|
68
|
+
if (!candidate)
|
|
69
|
+
break;
|
|
70
|
+
current = candidate.expression;
|
|
71
|
+
}
|
|
72
|
+
return current;
|
|
73
|
+
};
|
|
54
74
|
const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
|
|
55
75
|
node.type === 'NumericLiteral' ||
|
|
56
76
|
node.type === 'BooleanLiteral' ||
|
|
@@ -237,11 +257,32 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
237
257
|
}
|
|
238
258
|
const components = [];
|
|
239
259
|
const propAliases = new Map();
|
|
260
|
+
const propDefaults = new Map();
|
|
261
|
+
const declaredProps = new Map();
|
|
240
262
|
const addComponent = (name, fn) => {
|
|
241
263
|
components.push({ name, node: fn });
|
|
264
|
+
const first = fn.params[0];
|
|
265
|
+
const pattern = unwrapPatternDefault(first?.pat ?? first);
|
|
266
|
+
const defaults = new Map();
|
|
267
|
+
for (const item of pattern?.properties ?? []) {
|
|
268
|
+
if (item.type === 'AssignmentPatternProperty' && item.value)
|
|
269
|
+
defaults.set(item.key.value, item.value);
|
|
270
|
+
if (item.type === 'KeyValuePatternProperty' &&
|
|
271
|
+
item.value?.type === 'AssignmentPattern')
|
|
272
|
+
defaults.set(item.key.value, item.value.right);
|
|
273
|
+
}
|
|
274
|
+
propDefaults.set(name, defaults);
|
|
242
275
|
const aliases = destructuredPropAliases(fn);
|
|
243
276
|
if (aliases.size > 0)
|
|
244
277
|
propAliases.set(name, aliases);
|
|
278
|
+
const declared = new Set();
|
|
279
|
+
for (const item of pattern?.properties ?? []) {
|
|
280
|
+
const key = item.key;
|
|
281
|
+
if (t.isIdentifier(key) || t.isStringLiteral(key))
|
|
282
|
+
declared.add(String(key.value));
|
|
283
|
+
}
|
|
284
|
+
if (declared.size > 0)
|
|
285
|
+
declaredProps.set(name, declared);
|
|
245
286
|
};
|
|
246
287
|
for (const node of ast.body) {
|
|
247
288
|
const statement = unwrapExport(node);
|
|
@@ -474,12 +515,15 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
474
515
|
const checkStyleAliasAssignment = (decl) => {
|
|
475
516
|
if (!t.isIdentifier(decl.id) || !decl.init)
|
|
476
517
|
return;
|
|
477
|
-
const init = decl.init;
|
|
518
|
+
const init = unwrapExpression(decl.init);
|
|
478
519
|
if (t.isMemberExpression(init) && t.isIdentifier(init.object)) {
|
|
479
520
|
const objName = init.object.value;
|
|
480
521
|
if (localCreateStyles[objName] !== undefined ||
|
|
481
522
|
mergedCreateTable[objName] !== undefined) {
|
|
482
|
-
localStyleAliases[decl.id.value]
|
|
523
|
+
(localStyleAliases[decl.id.value] ??= []).push({
|
|
524
|
+
expression: init,
|
|
525
|
+
context: decl.id.ctxt,
|
|
526
|
+
});
|
|
483
527
|
}
|
|
484
528
|
}
|
|
485
529
|
};
|
|
@@ -489,9 +533,43 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
489
533
|
const idSpans = new Set();
|
|
490
534
|
const excludedSpans = new Set();
|
|
491
535
|
const referenceIdents = collectReferenceIdentifiers(ast);
|
|
536
|
+
const topLevelDeclarators = new Set();
|
|
537
|
+
for (const statement of ast.body) {
|
|
538
|
+
const declaration = unwrapExport(statement);
|
|
539
|
+
if (t.isVariableDeclaration(declaration)) {
|
|
540
|
+
declaration.declarations.forEach((decl) => topLevelDeclarators.add(decl));
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const unwrapStyleExpression = (node) => {
|
|
544
|
+
while (node &&
|
|
545
|
+
[
|
|
546
|
+
'ParenthesisExpression',
|
|
547
|
+
'TsAsExpression',
|
|
548
|
+
'TsSatisfiesExpression',
|
|
549
|
+
'TsNonNullExpression',
|
|
550
|
+
'TsConstAssertion',
|
|
551
|
+
'TsTypeAssertion',
|
|
552
|
+
].includes(node.type))
|
|
553
|
+
node = node.expression;
|
|
554
|
+
return node;
|
|
555
|
+
};
|
|
556
|
+
const literalObjectArgument = (node, seen = new Set()) => {
|
|
557
|
+
node = unwrapStyleExpression(node);
|
|
558
|
+
if (t.isObjectExpression(node))
|
|
559
|
+
return node;
|
|
560
|
+
if (!t.isIdentifier(node) || seen.has(node.value))
|
|
561
|
+
return null;
|
|
562
|
+
seen.add(node.value);
|
|
563
|
+
const declaration = [...topLevelDeclarators].find((decl) => t.isIdentifier(decl.id) &&
|
|
564
|
+
decl.id.value === node.value);
|
|
565
|
+
return declaration?.init
|
|
566
|
+
? literalObjectArgument(declaration.init, seen)
|
|
567
|
+
: null;
|
|
568
|
+
};
|
|
569
|
+
const registeredStyleCalls = new Set();
|
|
492
570
|
const registerStyle = (node, declSpan, isExported) => {
|
|
493
571
|
let propName;
|
|
494
|
-
const init = node.init;
|
|
572
|
+
const init = unwrapStyleExpression(node.init);
|
|
495
573
|
if (t.isIdentifier(node.id) &&
|
|
496
574
|
init &&
|
|
497
575
|
t.isCallExpression(init) &&
|
|
@@ -516,6 +594,19 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
516
594
|
}
|
|
517
595
|
}
|
|
518
596
|
if (propName && init && t.isCallExpression(init)) {
|
|
597
|
+
if (['create', 'createTheme', 'createStatic'].includes(propName) &&
|
|
598
|
+
!topLevelDeclarators.has(node)) {
|
|
599
|
+
throwCompilationError(`Plumeria: css.${propName} must be assigned to a top-level variable so its styles can be resolved across files. Move this declaration outside the function or block.`, node);
|
|
600
|
+
}
|
|
601
|
+
if (['create', 'createTheme', 'createStatic'].includes(propName)) {
|
|
602
|
+
const argumentIndex = propName === 'createTheme' ? 1 : 0;
|
|
603
|
+
const argument = init.arguments[argumentIndex];
|
|
604
|
+
const object = argument && literalObjectArgument(argument.expression);
|
|
605
|
+
if (!object)
|
|
606
|
+
throwCompilationError(`Plumeria: css.${propName} needs a style object it can read at build time. Pass an object literal or a top-level constant containing one.`, init);
|
|
607
|
+
argument.expression = object;
|
|
608
|
+
registeredStyleCalls.add(init.span.start);
|
|
609
|
+
}
|
|
519
610
|
if (propName === 'create' &&
|
|
520
611
|
t.isObjectExpression(init.arguments[0].expression)) {
|
|
521
612
|
const obj = objectExpressionToObject(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
@@ -713,6 +804,10 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
713
804
|
}
|
|
714
805
|
}
|
|
715
806
|
if (propName) {
|
|
807
|
+
if (['create', 'createTheme', 'createStatic'].includes(propName) &&
|
|
808
|
+
!registeredStyleCalls.has(node.span.start)) {
|
|
809
|
+
throwCompilationError(`Plumeria: css.${propName} must be assigned to a named top-level variable. Destructuring, assignment statements, and default-exported calls cannot be compiled.`, node);
|
|
810
|
+
}
|
|
716
811
|
const args = node.arguments;
|
|
717
812
|
if (propName === 'keyframes' && args.length > 0) {
|
|
718
813
|
const expr = args[0].expression;
|
|
@@ -778,12 +873,17 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
778
873
|
const jsxOpeningElementMap = new Map();
|
|
779
874
|
const componentParamNames = new Set();
|
|
780
875
|
const addFirstParamName = (fn) => {
|
|
781
|
-
const
|
|
876
|
+
const first = fn.params[0];
|
|
877
|
+
const p = unwrapPatternDefault(first?.pat ?? first);
|
|
782
878
|
if (t.isIdentifier(p)) {
|
|
783
879
|
componentParamNames.add(p.value);
|
|
784
880
|
}
|
|
785
|
-
else if (p?.
|
|
786
|
-
|
|
881
|
+
else if (p?.type === 'ObjectPattern') {
|
|
882
|
+
for (const item of p.properties) {
|
|
883
|
+
if (item.type === 'RestElement' && t.isIdentifier(item.argument)) {
|
|
884
|
+
componentParamNames.add(item.argument.value);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
787
887
|
}
|
|
788
888
|
};
|
|
789
889
|
for (const node of ast.body) {
|
|
@@ -820,6 +920,22 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
820
920
|
return sourceBuffer.subarray(start, end).toString('utf-8');
|
|
821
921
|
};
|
|
822
922
|
const resolveStyleObject = (expr) => {
|
|
923
|
+
expr = unwrapExpression(expr);
|
|
924
|
+
expr = resolveLocalStyleAlias(localStyleAliases, expr);
|
|
925
|
+
if (expr.type === 'ArrayExpression') {
|
|
926
|
+
let merged = {};
|
|
927
|
+
for (const element of expr.elements ?? []) {
|
|
928
|
+
if (!element)
|
|
929
|
+
continue;
|
|
930
|
+
if (element.spread)
|
|
931
|
+
throwCompilationError(spreadStyleMessage(getSource(element.expression)), element.expression);
|
|
932
|
+
const style = resolveStyleObject(element.expression);
|
|
933
|
+
if (!style)
|
|
934
|
+
return null;
|
|
935
|
+
merged = deepMerge(merged, style);
|
|
936
|
+
}
|
|
937
|
+
return merged;
|
|
938
|
+
}
|
|
823
939
|
if (t.isObjectExpression(expr)) {
|
|
824
940
|
return objectExpressionToObject(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
825
941
|
}
|
|
@@ -879,6 +995,26 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
879
995
|
return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
|
|
880
996
|
createFunctionImportMap[callee.object.value]?.[callee.property.value]);
|
|
881
997
|
};
|
|
998
|
+
const carriesStyleReference = (expression) => {
|
|
999
|
+
const node = unwrapExpression(expression);
|
|
1000
|
+
if (node.type === 'ArrayExpression')
|
|
1001
|
+
return node.elements.some((element) => !!element && carriesStyleReference(element.expression));
|
|
1002
|
+
if (isStyleFunctionCall(node))
|
|
1003
|
+
return true;
|
|
1004
|
+
if (t.isObjectExpression(node))
|
|
1005
|
+
return false;
|
|
1006
|
+
return resolveStyleObject(node) !== null;
|
|
1007
|
+
};
|
|
1008
|
+
const assertNoStyleArraySpread = (expression) => {
|
|
1009
|
+
const node = unwrapExpression(expression);
|
|
1010
|
+
if (node.type !== 'ArrayExpression')
|
|
1011
|
+
return;
|
|
1012
|
+
const spread = node.elements.find((element) => element?.spread);
|
|
1013
|
+
if (!spread)
|
|
1014
|
+
return;
|
|
1015
|
+
if (carriesStyleReference(node))
|
|
1016
|
+
throwCompilationError(spreadStyleMessage(getSource(spread.expression)), spread.expression);
|
|
1017
|
+
};
|
|
882
1018
|
const resolveDynamicCall = (expr, forceRuntime = false) => {
|
|
883
1019
|
if (!t.isCallExpression(expr) || !t.isMemberExpression(expr.callee))
|
|
884
1020
|
return null;
|
|
@@ -894,8 +1030,14 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
894
1030
|
if (callArgs.some((a) => a.spread))
|
|
895
1031
|
return null;
|
|
896
1032
|
const tempStaticTable = { ...mergedStaticTable };
|
|
1033
|
+
const providedParams = new Set();
|
|
897
1034
|
const runtime = [];
|
|
898
|
-
const resolveObjectArg = (argExpr) => objectExpressionToObject(
|
|
1035
|
+
const resolveObjectArg = (argExpr) => objectExpressionToObject({
|
|
1036
|
+
...argExpr,
|
|
1037
|
+
properties: argExpr.properties.filter((prop) => prop.type === 'Identifier' ||
|
|
1038
|
+
(prop.type === 'KeyValueProperty' &&
|
|
1039
|
+
isStaticArgValue(prop.value))),
|
|
1040
|
+
}, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
899
1041
|
if (func.named) {
|
|
900
1042
|
const argExpr = callArgs[0]?.expression;
|
|
901
1043
|
if (callArgs.length > 1 ||
|
|
@@ -925,8 +1067,10 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
925
1067
|
}
|
|
926
1068
|
if (!forceRuntime &&
|
|
927
1069
|
isStaticArgValue(source) &&
|
|
928
|
-
argObj[key] !== undefined)
|
|
1070
|
+
argObj[key] !== undefined) {
|
|
929
1071
|
tempStaticTable[local] = argObj[key];
|
|
1072
|
+
providedParams.add(local);
|
|
1073
|
+
}
|
|
930
1074
|
else
|
|
931
1075
|
runtime.push({ param: local, source });
|
|
932
1076
|
});
|
|
@@ -937,8 +1081,10 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
937
1081
|
return null;
|
|
938
1082
|
const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
|
|
939
1083
|
func.params.forEach((p) => {
|
|
940
|
-
if (argObj[p] !== undefined)
|
|
1084
|
+
if (argObj[p] !== undefined) {
|
|
941
1085
|
tempStaticTable[p] = argObj[p];
|
|
1086
|
+
providedParams.add(p);
|
|
1087
|
+
}
|
|
942
1088
|
});
|
|
943
1089
|
}
|
|
944
1090
|
else {
|
|
@@ -949,7 +1095,7 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
949
1095
|
runtime.push({ param: p, source: callArg.expression });
|
|
950
1096
|
});
|
|
951
1097
|
}
|
|
952
|
-
const resolved = resolveDynamicStyle(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables);
|
|
1098
|
+
const resolved = resolveDynamicStyle(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables, providedParams);
|
|
953
1099
|
if (!resolved)
|
|
954
1100
|
return null;
|
|
955
1101
|
const { style, varGroups } = resolved;
|
|
@@ -987,10 +1133,7 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
987
1133
|
};
|
|
988
1134
|
const buildClassParts = (args, dynamicClassParts = [], existingClass = '', isStyleProp = false) => {
|
|
989
1135
|
args.forEach((arg) => {
|
|
990
|
-
|
|
991
|
-
if (t.isIdentifier(expr) && localStyleAliases[expr.value]) {
|
|
992
|
-
arg.expression = localStyleAliases[expr.value];
|
|
993
|
-
}
|
|
1136
|
+
arg.expression = resolveLocalStyleAlias(localStyleAliases, arg.expression);
|
|
994
1137
|
});
|
|
995
1138
|
const conditionals = [];
|
|
996
1139
|
const dynamicVars = [];
|
|
@@ -1114,6 +1257,8 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1114
1257
|
return buildDecision(node, prefix, off, { n: 0 }, scoped);
|
|
1115
1258
|
};
|
|
1116
1259
|
const collectConditions = (node, currentTestStrings = [], argOrder) => {
|
|
1260
|
+
node = unwrapExpression(node);
|
|
1261
|
+
node = resolveLocalStyleAlias(localStyleAliases, node);
|
|
1117
1262
|
if (isNoOpStyle(node))
|
|
1118
1263
|
return true;
|
|
1119
1264
|
let branchStyle = resolveStyleObject(node);
|
|
@@ -1192,6 +1337,12 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1192
1337
|
t.isIdentifier(expr.property);
|
|
1193
1338
|
if (!t.isIdentifier(expr) && !isParamMember)
|
|
1194
1339
|
return false;
|
|
1340
|
+
const paramObject = isParamMember
|
|
1341
|
+
? expr.object.value
|
|
1342
|
+
: undefined;
|
|
1343
|
+
const isPropsMember = Boolean(paramObject &&
|
|
1344
|
+
localCreateStyles[paramObject] === undefined &&
|
|
1345
|
+
mergedCreateTable[paramObject] === undefined);
|
|
1195
1346
|
const varName = t.isIdentifier(expr)
|
|
1196
1347
|
? expr.value
|
|
1197
1348
|
: expr.property.value;
|
|
@@ -1216,8 +1367,43 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1216
1367
|
if (candidates.length > 0)
|
|
1217
1368
|
possibilities = candidates;
|
|
1218
1369
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1370
|
+
const fallback = owner && propDefaults.get(owner)?.get(propName);
|
|
1371
|
+
if (fallback) {
|
|
1372
|
+
const style = resolveStyleObject(fallback);
|
|
1373
|
+
if (style) {
|
|
1374
|
+
const atoms = {};
|
|
1375
|
+
getStyleRecords(style).forEach((record) => {
|
|
1376
|
+
atoms[record.key] = record.hash;
|
|
1377
|
+
});
|
|
1378
|
+
const key = genBase36Hash(Object.values(atoms).join(' '), 1, 8);
|
|
1379
|
+
possibilities = [
|
|
1380
|
+
...(possibilities ?? []),
|
|
1381
|
+
{ key, styleObj: style },
|
|
1382
|
+
];
|
|
1383
|
+
const span = fallback.span;
|
|
1384
|
+
{
|
|
1385
|
+
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
1386
|
+
const replacement = replacements[i];
|
|
1387
|
+
if (replacement.start >= span.start - baseByteOffset &&
|
|
1388
|
+
replacement.end <= span.end - baseByteOffset)
|
|
1389
|
+
replacements.splice(i, 1);
|
|
1390
|
+
}
|
|
1391
|
+
excludeSubtreeSpans(fallback);
|
|
1392
|
+
replacements.push({
|
|
1393
|
+
start: span.start - baseByteOffset,
|
|
1394
|
+
end: span.end - baseByteOffset,
|
|
1395
|
+
content: JSON.stringify(key),
|
|
1396
|
+
});
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
else {
|
|
1400
|
+
assertResolvable(fallback);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
if (!possibilities || possibilities.length === 0) {
|
|
1404
|
+
return Boolean(isPropsMember ||
|
|
1405
|
+
(owner && declaredProps.get(owner)?.has(propName)));
|
|
1406
|
+
}
|
|
1221
1407
|
const carriesVars = possibilities.some((entry) => entry.hasVars);
|
|
1222
1408
|
if (carriesVars && !isStyleProp) {
|
|
1223
1409
|
throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
|
|
@@ -1933,50 +2119,61 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1933
2119
|
}
|
|
1934
2120
|
}
|
|
1935
2121
|
if (compKey) {
|
|
2122
|
+
if (node.value?.type === 'JSXExpressionContainer')
|
|
2123
|
+
assertNoStyleArraySpread(node.value.expression);
|
|
1936
2124
|
const list = scannedTables.componentPropsTable?.[compKey]?.[attrName];
|
|
1937
2125
|
if (list &&
|
|
1938
2126
|
node.value &&
|
|
1939
2127
|
node.value.type === 'JSXExpressionContainer') {
|
|
1940
2128
|
const expr = node.value.expression;
|
|
1941
|
-
const carrierFor = (subNode) => {
|
|
2129
|
+
const carrierFor = (subNode, calls) => {
|
|
1942
2130
|
const vars = [];
|
|
1943
2131
|
let unresolved = false;
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
2132
|
+
for (const expression of calls ?? [subNode])
|
|
2133
|
+
traverse(expression, {
|
|
2134
|
+
CallExpression({ node: call }) {
|
|
2135
|
+
if (!isStyleFunctionCall(call))
|
|
2136
|
+
return;
|
|
2137
|
+
const resolved = resolveDynamicCall(call, true);
|
|
2138
|
+
if (!resolved) {
|
|
2139
|
+
unresolved = true;
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
vars.push(...resolved.vars);
|
|
2143
|
+
},
|
|
2144
|
+
});
|
|
1956
2145
|
if (unresolved)
|
|
1957
2146
|
return null;
|
|
1958
2147
|
return `{ ${foldDynamicVars(vars).join(', ')} }`;
|
|
1959
2148
|
};
|
|
1960
2149
|
const replaceWithKey = (subNode) => {
|
|
1961
|
-
const
|
|
1962
|
-
|
|
1963
|
-
if (
|
|
1964
|
-
|
|
2150
|
+
const entries = list.filter((entry) => entry.spanStart === subNode.span.start &&
|
|
2151
|
+
entry.filePath === resourcePath);
|
|
2152
|
+
if (!entries.length)
|
|
2153
|
+
return false;
|
|
2154
|
+
let content = '""';
|
|
2155
|
+
for (const entry of [...entries].reverse()) {
|
|
2156
|
+
let value = JSON.stringify(entry.key);
|
|
1965
2157
|
if (entry.hasVars) {
|
|
1966
|
-
const carrier = carrierFor(subNode);
|
|
2158
|
+
const carrier = carrierFor(subNode, entry.dynamicCalls);
|
|
1967
2159
|
if (!carrier)
|
|
1968
2160
|
return false;
|
|
1969
|
-
|
|
2161
|
+
value = `{ key: ${value}, vars: ${carrier} }`;
|
|
1970
2162
|
}
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
2163
|
+
const condition = entry.conditions
|
|
2164
|
+
?.map(({ test, truthy }) => `${truthy ? '' : '!'}(${getSource(test)})`)
|
|
2165
|
+
.join(' && ');
|
|
2166
|
+
content = condition
|
|
2167
|
+
? `((${condition}) ? ${value} : ${content})`
|
|
2168
|
+
: value;
|
|
1976
2169
|
processStyleRecords(entry.styleObj);
|
|
1977
|
-
return true;
|
|
1978
2170
|
}
|
|
1979
|
-
|
|
2171
|
+
replacements.push({
|
|
2172
|
+
start: subNode.span.start - baseByteOffset,
|
|
2173
|
+
end: subNode.span.end - baseByteOffset,
|
|
2174
|
+
content,
|
|
2175
|
+
});
|
|
2176
|
+
return true;
|
|
1980
2177
|
};
|
|
1981
2178
|
traverse(expr, {
|
|
1982
2179
|
MemberExpression({ node: subNode }) {
|
|
@@ -2005,7 +2202,11 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2005
2202
|
const args = expr.type === 'ArrayExpression'
|
|
2006
2203
|
? expr.elements
|
|
2007
2204
|
.filter((el) => el !== undefined)
|
|
2008
|
-
.map((el) =>
|
|
2205
|
+
.map((el) => {
|
|
2206
|
+
if (el.spread)
|
|
2207
|
+
throwCompilationError(spreadStyleMessage(getSource(el.expression)), el.expression);
|
|
2208
|
+
return { expression: el.expression };
|
|
2209
|
+
})
|
|
2009
2210
|
: [{ expression: expr }];
|
|
2010
2211
|
const dynamicClassParts = [];
|
|
2011
2212
|
const existingStyleParts = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumeria/unplugin",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.5.1",
|
|
4
4
|
"description": "Universal Plumeria plugin for various build tools",
|
|
5
5
|
"author": "Refirst 11",
|
|
6
6
|
"license": "MIT",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"dependencies": {
|
|
95
95
|
"@rollup/pluginutils": "^5.4.0",
|
|
96
96
|
"unplugin": "^3.0.0",
|
|
97
|
-
"@plumeria/utils": "^18.
|
|
97
|
+
"@plumeria/utils": "^18.5.1"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@swc/core": "1.15.47",
|