@plumeria/unplugin 18.4.0 → 18.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.js +143 -182
- package/dist/core.mjs +142 -181
- package/package.json +2 -2
package/dist/core.js
CHANGED
|
@@ -65,87 +65,37 @@ const componentFunctionOf = (node) => {
|
|
|
65
65
|
}
|
|
66
66
|
return undefined;
|
|
67
67
|
};
|
|
68
|
+
const unwrapPatternDefault = (pattern) => pattern?.type === 'AssignmentPattern' ? pattern.left : pattern;
|
|
69
|
+
const destructuredPropAliases = (fn) => {
|
|
70
|
+
const aliases = new Map();
|
|
71
|
+
const first = fn.params[0];
|
|
72
|
+
const pattern = unwrapPatternDefault(first?.pat ?? first);
|
|
73
|
+
if (pattern?.type !== 'ObjectPattern')
|
|
74
|
+
return aliases;
|
|
75
|
+
for (const item of pattern.properties ?? []) {
|
|
76
|
+
if (item.type !== 'KeyValuePatternProperty')
|
|
77
|
+
continue;
|
|
78
|
+
const local = unwrapPatternDefault(item.value);
|
|
79
|
+
const key = item.key;
|
|
80
|
+
if (!utils_1.t.isIdentifier(local))
|
|
81
|
+
continue;
|
|
82
|
+
if (!utils_1.t.isIdentifier(key) && !utils_1.t.isStringLiteral(key))
|
|
83
|
+
continue;
|
|
84
|
+
const name = String(key.value);
|
|
85
|
+
if (name !== local.value)
|
|
86
|
+
aliases.set(local.value, name);
|
|
87
|
+
}
|
|
88
|
+
return aliases;
|
|
89
|
+
};
|
|
68
90
|
const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
|
|
69
91
|
node.type === 'NumericLiteral' ||
|
|
70
92
|
node.type === 'BooleanLiteral' ||
|
|
71
93
|
(node.type === 'TemplateLiteral' && node.expressions.length === 0) ||
|
|
72
94
|
utils_1.t.isIdentifier(node) ||
|
|
73
95
|
utils_1.t.isMemberExpression(node);
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const first = params[0];
|
|
78
|
-
const pattern = (first?.pat ?? first);
|
|
79
|
-
if (pattern?.type !== 'ObjectPattern')
|
|
80
|
-
return undefined;
|
|
81
|
-
const named = [];
|
|
82
|
-
for (const prop of pattern.properties ?? []) {
|
|
83
|
-
if (prop.type === 'AssignmentPatternProperty' && utils_1.t.isIdentifier(prop.key)) {
|
|
84
|
-
named.push({ key: prop.key.value, local: prop.key.value });
|
|
85
|
-
if (prop.value)
|
|
86
|
-
defaults[prop.key.value] = prop.value;
|
|
87
|
-
}
|
|
88
|
-
else if (prop.type === 'KeyValuePatternProperty' &&
|
|
89
|
-
utils_1.t.isIdentifier(prop.key) &&
|
|
90
|
-
utils_1.t.isIdentifier(prop.value)) {
|
|
91
|
-
named.push({ key: prop.key.value, local: prop.value.value });
|
|
92
|
-
}
|
|
93
|
-
else if (prop.type === 'KeyValuePatternProperty' &&
|
|
94
|
-
utils_1.t.isIdentifier(prop.key) &&
|
|
95
|
-
prop.value?.type === 'AssignmentPattern' &&
|
|
96
|
-
utils_1.t.isIdentifier(prop.value.left)) {
|
|
97
|
-
const pattern = prop.value;
|
|
98
|
-
named.push({ key: String(prop.key.value), local: pattern.left.value });
|
|
99
|
-
defaults[pattern.left.value] = pattern.right;
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
return undefined;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return named.length > 0 ? named : undefined;
|
|
106
|
-
};
|
|
107
|
-
const styleFunctionsOf = (objExpr) => {
|
|
108
|
-
const styleFunctions = {};
|
|
109
|
-
objExpr.properties.forEach((prop) => {
|
|
110
|
-
if (prop.type !== 'KeyValueProperty' || prop.key.type !== 'Identifier')
|
|
111
|
-
return;
|
|
112
|
-
const func = prop.value;
|
|
113
|
-
if (func.type !== 'ArrowFunctionExpression' &&
|
|
114
|
-
func.type !== 'FunctionExpression')
|
|
115
|
-
return;
|
|
116
|
-
const defaults = {};
|
|
117
|
-
const params = func.params.map((p) => {
|
|
118
|
-
const pattern = typeof p === 'object' && p !== null && 'pat' in p ? p.pat : p;
|
|
119
|
-
if (utils_1.t.isIdentifier(pattern))
|
|
120
|
-
return pattern.value;
|
|
121
|
-
if (pattern?.type === 'AssignmentPattern' &&
|
|
122
|
-
utils_1.t.isIdentifier(pattern.left)) {
|
|
123
|
-
defaults[pattern.left.value] = pattern.right;
|
|
124
|
-
return pattern.left.value;
|
|
125
|
-
}
|
|
126
|
-
return 'arg';
|
|
127
|
-
});
|
|
128
|
-
let actualBody = func.body;
|
|
129
|
-
if (actualBody?.type === 'ParenthesisExpression')
|
|
130
|
-
actualBody = actualBody.expression;
|
|
131
|
-
if (actualBody?.type === 'BlockStatement') {
|
|
132
|
-
const first = actualBody.stmts?.[0];
|
|
133
|
-
if (first?.type === 'ReturnStatement')
|
|
134
|
-
actualBody = first.argument;
|
|
135
|
-
if (actualBody?.type === 'ParenthesisExpression')
|
|
136
|
-
actualBody = actualBody.expression;
|
|
137
|
-
}
|
|
138
|
-
if (actualBody && actualBody.type === 'ObjectExpression') {
|
|
139
|
-
styleFunctions[prop.key.value] = {
|
|
140
|
-
params,
|
|
141
|
-
named: namedParamsOf(func.params, defaults),
|
|
142
|
-
defaults,
|
|
143
|
-
body: actualBody,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
return styleFunctions;
|
|
148
|
-
};
|
|
96
|
+
const isNoOpStyle = (node) => utils_1.t.isNullLiteral(node) ||
|
|
97
|
+
(utils_1.t.isBooleanLiteral(node) && node.value === false) ||
|
|
98
|
+
(utils_1.t.isIdentifier(node) && node.value === 'undefined');
|
|
149
99
|
const foldDynamicVars = (vars) => {
|
|
150
100
|
const grouped = new Map();
|
|
151
101
|
[...vars]
|
|
@@ -167,59 +117,6 @@ const foldDynamicVars = (vars) => {
|
|
|
167
117
|
return `"${cssVar}": ${value}`;
|
|
168
118
|
});
|
|
169
119
|
};
|
|
170
|
-
const isUnitlessProp = (prop) => zss_engine_1.exceptionCamelCase.includes(prop) || prop.startsWith('--');
|
|
171
|
-
const collectVarProps = (style, cssVar, props) => {
|
|
172
|
-
const reference = `var(${cssVar})`;
|
|
173
|
-
for (const [prop, value] of Object.entries(style)) {
|
|
174
|
-
if (typeof value === 'string' && value.includes(reference))
|
|
175
|
-
props.push(prop);
|
|
176
|
-
else if (value !== null && typeof value === 'object')
|
|
177
|
-
collectVarProps(value, cssVar, props);
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
const retargetVar = (style, cssVar, next, unitless) => {
|
|
181
|
-
const reference = `var(${cssVar})`;
|
|
182
|
-
for (const [prop, value] of Object.entries(style)) {
|
|
183
|
-
if (typeof value === 'string' && value.includes(reference)) {
|
|
184
|
-
if (isUnitlessProp(prop) === unitless)
|
|
185
|
-
style[prop] = value
|
|
186
|
-
.split(reference)
|
|
187
|
-
.join(`var(${next})`);
|
|
188
|
-
}
|
|
189
|
-
else if (value !== null && typeof value === 'object') {
|
|
190
|
-
retargetVar(value, cssVar, next, unitless);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
const splitVarByUnit = (style, cssVar) => {
|
|
195
|
-
const props = [];
|
|
196
|
-
collectVarProps(style, cssVar, props);
|
|
197
|
-
if (props.length === 0)
|
|
198
|
-
return [];
|
|
199
|
-
const lead = props[0];
|
|
200
|
-
const split = props.find((prop) => isUnitlessProp(prop) !== isUnitlessProp(lead));
|
|
201
|
-
if (!split)
|
|
202
|
-
return [{ cssVar, prop: lead }];
|
|
203
|
-
const splitVar = `${cssVar}-${(0, zss_engine_1.camelToKebabCase)(split).replace(/^-+/, '')}`;
|
|
204
|
-
retargetVar(style, cssVar, splitVar, isUnitlessProp(split));
|
|
205
|
-
return [
|
|
206
|
-
{ cssVar, prop: lead },
|
|
207
|
-
{ cssVar: splitVar, prop: split },
|
|
208
|
-
];
|
|
209
|
-
};
|
|
210
|
-
const applyVarFallback = (style, cssVar, literal) => {
|
|
211
|
-
const reference = `var(${cssVar})`;
|
|
212
|
-
for (const [prop, value] of Object.entries(style)) {
|
|
213
|
-
if (typeof value === 'string' && value.includes(reference)) {
|
|
214
|
-
style[prop] = value
|
|
215
|
-
.split(reference)
|
|
216
|
-
.join(`var(${cssVar}, ${(0, zss_engine_1.applyCssValue)(literal, (0, zss_engine_1.camelToKebabCase)(prop))})`);
|
|
217
|
-
}
|
|
218
|
-
else if (value !== null && typeof value === 'object') {
|
|
219
|
-
applyVarFallback(value, cssVar, literal);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
120
|
const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
224
121
|
const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
|
|
225
122
|
const propertyPolicy = (0, utils_1.resolvePropertyPolicy)(options);
|
|
@@ -375,18 +272,22 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
375
272
|
}
|
|
376
273
|
}
|
|
377
274
|
const components = [];
|
|
275
|
+
const propAliases = new Map();
|
|
276
|
+
const addComponent = (name, fn) => {
|
|
277
|
+
components.push({ name, node: fn });
|
|
278
|
+
const aliases = destructuredPropAliases(fn);
|
|
279
|
+
if (aliases.size > 0)
|
|
280
|
+
propAliases.set(name, aliases);
|
|
281
|
+
};
|
|
378
282
|
for (const node of ast.body) {
|
|
379
283
|
const statement = unwrapExport(node);
|
|
380
284
|
if (isFunctionNode(statement)) {
|
|
381
|
-
|
|
382
|
-
name: statement.identifier?.value ?? 'default',
|
|
383
|
-
node: statement,
|
|
384
|
-
});
|
|
285
|
+
addComponent(statement.identifier?.value ?? 'default', statement);
|
|
385
286
|
}
|
|
386
287
|
else if (statement?.type === 'CallExpression') {
|
|
387
288
|
const fn = componentFunctionOf(statement);
|
|
388
289
|
if (fn)
|
|
389
|
-
|
|
290
|
+
addComponent('default', fn);
|
|
390
291
|
}
|
|
391
292
|
else if (utils_1.t.isVariableDeclaration(statement)) {
|
|
392
293
|
for (const decl of statement.declarations) {
|
|
@@ -394,7 +295,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
394
295
|
continue;
|
|
395
296
|
const fn = componentFunctionOf(decl.init);
|
|
396
297
|
if (fn)
|
|
397
|
-
|
|
298
|
+
addComponent(decl.id.value, fn);
|
|
398
299
|
}
|
|
399
300
|
}
|
|
400
301
|
}
|
|
@@ -493,7 +394,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
493
394
|
scannedTables.createHashTable[uniqueKey];
|
|
494
395
|
}
|
|
495
396
|
if (scannedTables.createFunctionTable[uniqueKey]) {
|
|
496
|
-
createFunctionImportMap[localName] = styleFunctionsOf(scannedTables.createFunctionTable[uniqueKey]);
|
|
397
|
+
createFunctionImportMap[localName] = (0, utils_1.styleFunctionsOf)(scannedTables.createFunctionTable[uniqueKey]);
|
|
497
398
|
}
|
|
498
399
|
if (scannedTables.variantsHashTable[uniqueKey]) {
|
|
499
400
|
variantsImportMap[localName] =
|
|
@@ -594,6 +495,16 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
594
495
|
for (const key of Object.keys(createStaticImportMap)) {
|
|
595
496
|
mergedCreateStaticHashTable[key] = createStaticImportMap[key];
|
|
596
497
|
}
|
|
498
|
+
const dynamicStyleTables = {
|
|
499
|
+
keyframesHashTable: mergedKeyframesTable,
|
|
500
|
+
viewTransitionHashTable: mergedViewTransitionTable,
|
|
501
|
+
createThemeHashTable: mergedCreateThemeHashTable,
|
|
502
|
+
createThemeObjectTable: scannedTables.createThemeObjectTable,
|
|
503
|
+
createHashTable: mergedCreateTable,
|
|
504
|
+
createStaticHashTable: mergedCreateStaticHashTable,
|
|
505
|
+
createStaticObjectTable: scannedTables.createStaticObjectTable,
|
|
506
|
+
variantsHashTable: mergedVariantsTable,
|
|
507
|
+
};
|
|
597
508
|
const localCreateStyles = {};
|
|
598
509
|
const localStyleAliases = {};
|
|
599
510
|
const checkStyleAliasAssignment = (decl) => {
|
|
@@ -654,7 +565,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
654
565
|
records.forEach((r) => (atomMap[r.key] = r.hash));
|
|
655
566
|
hashMap[key] = atomMap;
|
|
656
567
|
});
|
|
657
|
-
const styleFunctions = styleFunctionsOf(init.arguments[0].expression);
|
|
568
|
+
const styleFunctions = (0, utils_1.styleFunctionsOf)(init.arguments[0].expression);
|
|
658
569
|
if (utils_1.t.isIdentifier(node.id)) {
|
|
659
570
|
idSpans.add(node.id.span.start);
|
|
660
571
|
}
|
|
@@ -995,7 +906,16 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
995
906
|
}
|
|
996
907
|
return null;
|
|
997
908
|
};
|
|
998
|
-
const
|
|
909
|
+
const isStyleFunctionCall = (expr) => {
|
|
910
|
+
if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
|
|
911
|
+
return false;
|
|
912
|
+
const callee = expr.callee;
|
|
913
|
+
if (!utils_1.t.isIdentifier(callee.object) || !utils_1.t.isIdentifier(callee.property))
|
|
914
|
+
return false;
|
|
915
|
+
return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
|
|
916
|
+
createFunctionImportMap[callee.object.value]?.[callee.property.value]);
|
|
917
|
+
};
|
|
918
|
+
const resolveDynamicCall = (expr, forceRuntime = false) => {
|
|
999
919
|
if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
|
|
1000
920
|
return null;
|
|
1001
921
|
const callee = expr.callee;
|
|
@@ -1039,7 +959,9 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1039
959
|
throwCompilationError(`Plumeria: ${getSource(expr)} leaves "${key}" unset, and a dynamic style function has no value to fall back on.`, expr);
|
|
1040
960
|
return;
|
|
1041
961
|
}
|
|
1042
|
-
if (
|
|
962
|
+
if (!forceRuntime &&
|
|
963
|
+
isStaticArgValue(source) &&
|
|
964
|
+
argObj[key] !== undefined)
|
|
1043
965
|
tempStaticTable[local] = argObj[key];
|
|
1044
966
|
else
|
|
1045
967
|
runtime.push({ param: local, source });
|
|
@@ -1047,6 +969,8 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1047
969
|
}
|
|
1048
970
|
else if (callArgs.length === 1 &&
|
|
1049
971
|
callArgs[0].expression.type === 'ObjectExpression') {
|
|
972
|
+
if (forceRuntime)
|
|
973
|
+
return null;
|
|
1050
974
|
const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
|
|
1051
975
|
func.params.forEach((p) => {
|
|
1052
976
|
if (argObj[p] !== undefined)
|
|
@@ -1061,39 +985,10 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1061
985
|
runtime.push({ param: p, source: callArg.expression });
|
|
1062
986
|
});
|
|
1063
987
|
}
|
|
1064
|
-
const
|
|
1065
|
-
|
|
1066
|
-
const varParams = Array.from(new Set([
|
|
1067
|
-
...runtime.map(({ param }) => param),
|
|
1068
|
-
...withDefault.map(([param]) => param),
|
|
1069
|
-
]));
|
|
1070
|
-
if (varParams.length > 0) {
|
|
1071
|
-
varParams.forEach((param) => (tempStaticTable[param] = param));
|
|
1072
|
-
const probe = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
1073
|
-
const hash = (0, zss_engine_1.genBase36Hash)(probe ?? {}, 1, 8);
|
|
1074
|
-
varParams.forEach((param) => {
|
|
1075
|
-
const cssVar = `--${hash}-${param}`;
|
|
1076
|
-
tempStaticTable[param] = `var(${cssVar})`;
|
|
1077
|
-
cssVars[param] = cssVar;
|
|
1078
|
-
});
|
|
1079
|
-
}
|
|
1080
|
-
const style = (0, utils_1.objectExpressionToObject)(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
1081
|
-
if (!style)
|
|
988
|
+
const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables);
|
|
989
|
+
if (!resolved)
|
|
1082
990
|
return null;
|
|
1083
|
-
const varGroups =
|
|
1084
|
-
varParams.forEach((param) => {
|
|
1085
|
-
const cssVar = cssVars[param];
|
|
1086
|
-
if (cssVar)
|
|
1087
|
-
varGroups.set(param, splitVarByUnit(style, cssVar));
|
|
1088
|
-
});
|
|
1089
|
-
withDefault.forEach(([param, expr]) => {
|
|
1090
|
-
const literal = expr.type === 'StringLiteral' || expr.type === 'NumericLiteral'
|
|
1091
|
-
? expr.value
|
|
1092
|
-
: undefined;
|
|
1093
|
-
if (literal === undefined)
|
|
1094
|
-
return;
|
|
1095
|
-
(varGroups.get(param) ?? []).forEach(({ cssVar }) => applyVarFallback(style, cssVar, literal));
|
|
1096
|
-
});
|
|
991
|
+
const { style, varGroups } = resolved;
|
|
1097
992
|
const vars = [];
|
|
1098
993
|
runtime.forEach(({ param, source }) => {
|
|
1099
994
|
const groups = varGroups.get(param);
|
|
@@ -1117,7 +1012,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1117
1012
|
valueExpr = JSON.stringify((0, zss_engine_1.applyCssValue)(argSource.slice(1, -1), kebabProp));
|
|
1118
1013
|
}
|
|
1119
1014
|
else {
|
|
1120
|
-
valueExpr = isUnitlessProp(prop)
|
|
1015
|
+
valueExpr = (0, utils_1.isUnitlessProp)(prop)
|
|
1121
1016
|
? argSource
|
|
1122
1017
|
: `(typeof (${argSource}) === 'number' ? (${argSource}) + 'px' : (${argSource}))`;
|
|
1123
1018
|
}
|
|
@@ -1135,6 +1030,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1135
1030
|
});
|
|
1136
1031
|
const conditionals = [];
|
|
1137
1032
|
const dynamicVars = [];
|
|
1033
|
+
const propVarSpreads = [];
|
|
1138
1034
|
let groupIdCounter = 0;
|
|
1139
1035
|
let sourceOrder = 0;
|
|
1140
1036
|
const baseChunks = [];
|
|
@@ -1254,6 +1150,8 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1254
1150
|
return buildDecision(node, prefix, off, { n: 0 }, scoped);
|
|
1255
1151
|
};
|
|
1256
1152
|
const collectConditions = (node, currentTestStrings = [], argOrder) => {
|
|
1153
|
+
if (isNoOpStyle(node))
|
|
1154
|
+
return true;
|
|
1257
1155
|
let branchStyle = resolveStyleObject(node);
|
|
1258
1156
|
if (!branchStyle) {
|
|
1259
1157
|
const dynamic = resolveDynamicCall(node);
|
|
@@ -1334,17 +1232,20 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1334
1232
|
? expr.value
|
|
1335
1233
|
: expr.property.value;
|
|
1336
1234
|
const source = utils_1.t.isIdentifier(expr) ? varName : getSource(expr);
|
|
1337
|
-
markStylePropApplied(varName, expr);
|
|
1338
1235
|
const owner = ownerComponentOf(expr);
|
|
1236
|
+
const propName = (utils_1.t.isIdentifier(expr) && owner
|
|
1237
|
+
? propAliases.get(owner)?.get(varName)
|
|
1238
|
+
: undefined) ?? varName;
|
|
1239
|
+
markStylePropApplied(propName, expr);
|
|
1339
1240
|
let possibilities = owner
|
|
1340
|
-
? scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[
|
|
1241
|
+
? scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[propName]
|
|
1341
1242
|
: undefined;
|
|
1342
1243
|
if (!possibilities) {
|
|
1343
1244
|
const candidates = [];
|
|
1344
1245
|
for (const key of Object.keys(scannedTables.componentPropsTable || {})) {
|
|
1345
1246
|
if (!key.startsWith(`${resourcePath}-`))
|
|
1346
1247
|
continue;
|
|
1347
|
-
const entries = scannedTables.componentPropsTable?.[key]?.[
|
|
1248
|
+
const entries = scannedTables.componentPropsTable?.[key]?.[propName];
|
|
1348
1249
|
if (entries)
|
|
1349
1250
|
candidates.push(...entries);
|
|
1350
1251
|
}
|
|
@@ -1353,9 +1254,23 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1353
1254
|
}
|
|
1354
1255
|
if (!possibilities || possibilities.length === 0)
|
|
1355
1256
|
return false;
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1257
|
+
const carriesVars = possibilities.some((entry) => entry.hasVars);
|
|
1258
|
+
if (carriesVars && !isStyleProp) {
|
|
1259
|
+
throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
|
|
1260
|
+
`Apply it to ${styleProp} on the element instead.`, expr);
|
|
1261
|
+
}
|
|
1262
|
+
const gate = gates.length ? `(${gates.join(' && ')}) && ` : '';
|
|
1263
|
+
if (carriesVars) {
|
|
1264
|
+
const spread = `...(${gate}${source} && ${source}.vars)`;
|
|
1265
|
+
if (!propVarSpreads.includes(spread))
|
|
1266
|
+
propVarSpreads.push(spread);
|
|
1267
|
+
}
|
|
1268
|
+
const token = carriesVars
|
|
1269
|
+
? `((${source} && ${source}.key) || ${source})`
|
|
1358
1270
|
: source;
|
|
1271
|
+
const testLHS = gates.length
|
|
1272
|
+
? `((${gates.join(' && ')}) ? ${token} : "")`
|
|
1273
|
+
: token;
|
|
1359
1274
|
const currentGroupId = ++groupIdCounter;
|
|
1360
1275
|
const currentOrder = sourceOrder++;
|
|
1361
1276
|
const seen = new Set();
|
|
@@ -1385,6 +1300,8 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1385
1300
|
};
|
|
1386
1301
|
for (const arg of args) {
|
|
1387
1302
|
const expr = arg.expression;
|
|
1303
|
+
if (isNoOpStyle(expr))
|
|
1304
|
+
continue;
|
|
1388
1305
|
if (pushPropPossibilities(expr, []))
|
|
1389
1306
|
continue;
|
|
1390
1307
|
if (utils_1.t.isCallExpression(expr) && utils_1.t.isIdentifier(expr.callee)) {
|
|
@@ -1594,6 +1511,7 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1594
1511
|
isOptimizable,
|
|
1595
1512
|
baseStyle,
|
|
1596
1513
|
dynamicVars,
|
|
1514
|
+
propVarSpreads,
|
|
1597
1515
|
};
|
|
1598
1516
|
}
|
|
1599
1517
|
const stateSources = baseChunks.map(({ order, style }) => ({ order, style: style }));
|
|
@@ -1849,7 +1767,13 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1849
1767
|
classParts.push(`(${JSON.stringify(results)}[${masterKeyExpr || '""'}] || ${baseConflictClass ? JSON.stringify(baseConflictClass) : '""'})`);
|
|
1850
1768
|
}
|
|
1851
1769
|
classParts.push(...dynamicClassParts);
|
|
1852
|
-
return {
|
|
1770
|
+
return {
|
|
1771
|
+
classParts,
|
|
1772
|
+
isOptimizable,
|
|
1773
|
+
baseStyle,
|
|
1774
|
+
dynamicVars,
|
|
1775
|
+
propVarSpreads,
|
|
1776
|
+
};
|
|
1853
1777
|
};
|
|
1854
1778
|
(0, utils_1.traverse)(ast, {
|
|
1855
1779
|
JSXOpeningElement({ node }) {
|
|
@@ -2050,14 +1974,40 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2050
1974
|
node.value &&
|
|
2051
1975
|
node.value.type === 'JSXExpressionContainer') {
|
|
2052
1976
|
const expr = node.value.expression;
|
|
1977
|
+
const carrierFor = (subNode) => {
|
|
1978
|
+
const vars = [];
|
|
1979
|
+
let unresolved = false;
|
|
1980
|
+
(0, utils_1.traverse)(subNode, {
|
|
1981
|
+
CallExpression({ node: call }) {
|
|
1982
|
+
if (!isStyleFunctionCall(call))
|
|
1983
|
+
return;
|
|
1984
|
+
const resolved = resolveDynamicCall(call, true);
|
|
1985
|
+
if (!resolved) {
|
|
1986
|
+
unresolved = true;
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1989
|
+
vars.push(...resolved.vars);
|
|
1990
|
+
},
|
|
1991
|
+
});
|
|
1992
|
+
if (unresolved)
|
|
1993
|
+
return null;
|
|
1994
|
+
return `{ ${foldDynamicVars(vars).join(', ')} }`;
|
|
1995
|
+
};
|
|
2053
1996
|
const replaceWithKey = (subNode) => {
|
|
2054
1997
|
const entry = list.find((x) => x.spanStart === subNode.span.start &&
|
|
2055
1998
|
x.filePath === resourcePath);
|
|
2056
1999
|
if (entry) {
|
|
2000
|
+
let content = JSON.stringify(entry.key);
|
|
2001
|
+
if (entry.hasVars) {
|
|
2002
|
+
const carrier = carrierFor(subNode);
|
|
2003
|
+
if (!carrier)
|
|
2004
|
+
return false;
|
|
2005
|
+
content = `{ key: ${content}, vars: ${carrier} }`;
|
|
2006
|
+
}
|
|
2057
2007
|
replacements.push({
|
|
2058
2008
|
start: subNode.span.start - baseByteOffset,
|
|
2059
2009
|
end: subNode.span.end - baseByteOffset,
|
|
2060
|
-
content
|
|
2010
|
+
content,
|
|
2061
2011
|
});
|
|
2062
2012
|
processStyleRecords(entry.styleObj);
|
|
2063
2013
|
return true;
|
|
@@ -2075,6 +2025,11 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2075
2025
|
excludeSubtreeSpans(subNode);
|
|
2076
2026
|
}
|
|
2077
2027
|
},
|
|
2028
|
+
CallExpression({ node: subNode }) {
|
|
2029
|
+
if (replaceWithKey(subNode)) {
|
|
2030
|
+
excludeSubtreeSpans(subNode);
|
|
2031
|
+
}
|
|
2032
|
+
},
|
|
2078
2033
|
});
|
|
2079
2034
|
}
|
|
2080
2035
|
}
|
|
@@ -2150,9 +2105,12 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2150
2105
|
}
|
|
2151
2106
|
}
|
|
2152
2107
|
}
|
|
2153
|
-
const { classParts, isOptimizable, baseStyle, dynamicVars } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
|
|
2154
|
-
const
|
|
2155
|
-
|
|
2108
|
+
const { classParts, isOptimizable, baseStyle, dynamicVars, propVarSpreads, } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
|
|
2109
|
+
const styleParts = [
|
|
2110
|
+
...existingStyleParts,
|
|
2111
|
+
...foldDynamicVars(dynamicVars),
|
|
2112
|
+
...propVarSpreads,
|
|
2113
|
+
];
|
|
2156
2114
|
const styleAttr = styleParts.length > 0 || existingStyleExpr
|
|
2157
2115
|
? ` style={{ ${[existingStyleExpr, ...styleParts].filter(Boolean).join(', ')} }}`
|
|
2158
2116
|
: '';
|
|
@@ -2168,10 +2126,13 @@ const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2168
2126
|
});
|
|
2169
2127
|
}
|
|
2170
2128
|
else {
|
|
2129
|
+
const keptClass = existingClassExpr
|
|
2130
|
+
? `className={${existingClassExpr}}`
|
|
2131
|
+
: '';
|
|
2171
2132
|
replacements.push({
|
|
2172
2133
|
start: node.span.start - baseByteOffset,
|
|
2173
2134
|
end: node.span.end - baseByteOffset,
|
|
2174
|
-
content: styleAttr
|
|
2135
|
+
content: `${keptClass}${styleAttr}`,
|
|
2175
2136
|
});
|
|
2176
2137
|
}
|
|
2177
2138
|
},
|
package/dist/core.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createFilter } from '@rollup/pluginutils';
|
|
2
2
|
import { parseSync } from '@swc/core';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
-
import { applyCssValue, genBase36Hash,
|
|
5
|
-
import { traverse, resolvePropertyPolicy, assertPropertyPolicy, collectReferenceIdentifiers, getStyleRecords, getStateWeights, collectLocalConsts, objectExpressionToObject, t, getRootIdentifier, extractOndemandStyles, deepMerge, scanAll, resolveFileError, resolveImportPath, getLeadingCommentLength, optimizer, themeHashOf, getFileDependencies, resolveExport, resolveComponentKey, resolveThemeSelector, DEFAULT_STYLE_PROP, } from '@plumeria/utils';
|
|
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';
|
|
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) => {
|
|
@@ -29,87 +29,37 @@ const componentFunctionOf = (node) => {
|
|
|
29
29
|
}
|
|
30
30
|
return undefined;
|
|
31
31
|
};
|
|
32
|
+
const unwrapPatternDefault = (pattern) => pattern?.type === 'AssignmentPattern' ? pattern.left : pattern;
|
|
33
|
+
const destructuredPropAliases = (fn) => {
|
|
34
|
+
const aliases = new Map();
|
|
35
|
+
const first = fn.params[0];
|
|
36
|
+
const pattern = unwrapPatternDefault(first?.pat ?? first);
|
|
37
|
+
if (pattern?.type !== 'ObjectPattern')
|
|
38
|
+
return aliases;
|
|
39
|
+
for (const item of pattern.properties ?? []) {
|
|
40
|
+
if (item.type !== 'KeyValuePatternProperty')
|
|
41
|
+
continue;
|
|
42
|
+
const local = unwrapPatternDefault(item.value);
|
|
43
|
+
const key = item.key;
|
|
44
|
+
if (!t.isIdentifier(local))
|
|
45
|
+
continue;
|
|
46
|
+
if (!t.isIdentifier(key) && !t.isStringLiteral(key))
|
|
47
|
+
continue;
|
|
48
|
+
const name = String(key.value);
|
|
49
|
+
if (name !== local.value)
|
|
50
|
+
aliases.set(local.value, name);
|
|
51
|
+
}
|
|
52
|
+
return aliases;
|
|
53
|
+
};
|
|
32
54
|
const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
|
|
33
55
|
node.type === 'NumericLiteral' ||
|
|
34
56
|
node.type === 'BooleanLiteral' ||
|
|
35
57
|
(node.type === 'TemplateLiteral' && node.expressions.length === 0) ||
|
|
36
58
|
t.isIdentifier(node) ||
|
|
37
59
|
t.isMemberExpression(node);
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const first = params[0];
|
|
42
|
-
const pattern = (first?.pat ?? first);
|
|
43
|
-
if (pattern?.type !== 'ObjectPattern')
|
|
44
|
-
return undefined;
|
|
45
|
-
const named = [];
|
|
46
|
-
for (const prop of pattern.properties ?? []) {
|
|
47
|
-
if (prop.type === 'AssignmentPatternProperty' && t.isIdentifier(prop.key)) {
|
|
48
|
-
named.push({ key: prop.key.value, local: prop.key.value });
|
|
49
|
-
if (prop.value)
|
|
50
|
-
defaults[prop.key.value] = prop.value;
|
|
51
|
-
}
|
|
52
|
-
else if (prop.type === 'KeyValuePatternProperty' &&
|
|
53
|
-
t.isIdentifier(prop.key) &&
|
|
54
|
-
t.isIdentifier(prop.value)) {
|
|
55
|
-
named.push({ key: prop.key.value, local: prop.value.value });
|
|
56
|
-
}
|
|
57
|
-
else if (prop.type === 'KeyValuePatternProperty' &&
|
|
58
|
-
t.isIdentifier(prop.key) &&
|
|
59
|
-
prop.value?.type === 'AssignmentPattern' &&
|
|
60
|
-
t.isIdentifier(prop.value.left)) {
|
|
61
|
-
const pattern = prop.value;
|
|
62
|
-
named.push({ key: String(prop.key.value), local: pattern.left.value });
|
|
63
|
-
defaults[pattern.left.value] = pattern.right;
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return named.length > 0 ? named : undefined;
|
|
70
|
-
};
|
|
71
|
-
const styleFunctionsOf = (objExpr) => {
|
|
72
|
-
const styleFunctions = {};
|
|
73
|
-
objExpr.properties.forEach((prop) => {
|
|
74
|
-
if (prop.type !== 'KeyValueProperty' || prop.key.type !== 'Identifier')
|
|
75
|
-
return;
|
|
76
|
-
const func = prop.value;
|
|
77
|
-
if (func.type !== 'ArrowFunctionExpression' &&
|
|
78
|
-
func.type !== 'FunctionExpression')
|
|
79
|
-
return;
|
|
80
|
-
const defaults = {};
|
|
81
|
-
const params = func.params.map((p) => {
|
|
82
|
-
const pattern = typeof p === 'object' && p !== null && 'pat' in p ? p.pat : p;
|
|
83
|
-
if (t.isIdentifier(pattern))
|
|
84
|
-
return pattern.value;
|
|
85
|
-
if (pattern?.type === 'AssignmentPattern' &&
|
|
86
|
-
t.isIdentifier(pattern.left)) {
|
|
87
|
-
defaults[pattern.left.value] = pattern.right;
|
|
88
|
-
return pattern.left.value;
|
|
89
|
-
}
|
|
90
|
-
return 'arg';
|
|
91
|
-
});
|
|
92
|
-
let actualBody = func.body;
|
|
93
|
-
if (actualBody?.type === 'ParenthesisExpression')
|
|
94
|
-
actualBody = actualBody.expression;
|
|
95
|
-
if (actualBody?.type === 'BlockStatement') {
|
|
96
|
-
const first = actualBody.stmts?.[0];
|
|
97
|
-
if (first?.type === 'ReturnStatement')
|
|
98
|
-
actualBody = first.argument;
|
|
99
|
-
if (actualBody?.type === 'ParenthesisExpression')
|
|
100
|
-
actualBody = actualBody.expression;
|
|
101
|
-
}
|
|
102
|
-
if (actualBody && actualBody.type === 'ObjectExpression') {
|
|
103
|
-
styleFunctions[prop.key.value] = {
|
|
104
|
-
params,
|
|
105
|
-
named: namedParamsOf(func.params, defaults),
|
|
106
|
-
defaults,
|
|
107
|
-
body: actualBody,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
return styleFunctions;
|
|
112
|
-
};
|
|
60
|
+
const isNoOpStyle = (node) => t.isNullLiteral(node) ||
|
|
61
|
+
(t.isBooleanLiteral(node) && node.value === false) ||
|
|
62
|
+
(t.isIdentifier(node) && node.value === 'undefined');
|
|
113
63
|
const foldDynamicVars = (vars) => {
|
|
114
64
|
const grouped = new Map();
|
|
115
65
|
[...vars]
|
|
@@ -131,59 +81,6 @@ const foldDynamicVars = (vars) => {
|
|
|
131
81
|
return `"${cssVar}": ${value}`;
|
|
132
82
|
});
|
|
133
83
|
};
|
|
134
|
-
const isUnitlessProp = (prop) => exceptionCamelCase.includes(prop) || prop.startsWith('--');
|
|
135
|
-
const collectVarProps = (style, cssVar, props) => {
|
|
136
|
-
const reference = `var(${cssVar})`;
|
|
137
|
-
for (const [prop, value] of Object.entries(style)) {
|
|
138
|
-
if (typeof value === 'string' && value.includes(reference))
|
|
139
|
-
props.push(prop);
|
|
140
|
-
else if (value !== null && typeof value === 'object')
|
|
141
|
-
collectVarProps(value, cssVar, props);
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
const retargetVar = (style, cssVar, next, unitless) => {
|
|
145
|
-
const reference = `var(${cssVar})`;
|
|
146
|
-
for (const [prop, value] of Object.entries(style)) {
|
|
147
|
-
if (typeof value === 'string' && value.includes(reference)) {
|
|
148
|
-
if (isUnitlessProp(prop) === unitless)
|
|
149
|
-
style[prop] = value
|
|
150
|
-
.split(reference)
|
|
151
|
-
.join(`var(${next})`);
|
|
152
|
-
}
|
|
153
|
-
else if (value !== null && typeof value === 'object') {
|
|
154
|
-
retargetVar(value, cssVar, next, unitless);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
const splitVarByUnit = (style, cssVar) => {
|
|
159
|
-
const props = [];
|
|
160
|
-
collectVarProps(style, cssVar, props);
|
|
161
|
-
if (props.length === 0)
|
|
162
|
-
return [];
|
|
163
|
-
const lead = props[0];
|
|
164
|
-
const split = props.find((prop) => isUnitlessProp(prop) !== isUnitlessProp(lead));
|
|
165
|
-
if (!split)
|
|
166
|
-
return [{ cssVar, prop: lead }];
|
|
167
|
-
const splitVar = `${cssVar}-${camelToKebabCase(split).replace(/^-+/, '')}`;
|
|
168
|
-
retargetVar(style, cssVar, splitVar, isUnitlessProp(split));
|
|
169
|
-
return [
|
|
170
|
-
{ cssVar, prop: lead },
|
|
171
|
-
{ cssVar: splitVar, prop: split },
|
|
172
|
-
];
|
|
173
|
-
};
|
|
174
|
-
const applyVarFallback = (style, cssVar, literal) => {
|
|
175
|
-
const reference = `var(${cssVar})`;
|
|
176
|
-
for (const [prop, value] of Object.entries(style)) {
|
|
177
|
-
if (typeof value === 'string' && value.includes(reference)) {
|
|
178
|
-
style[prop] = value
|
|
179
|
-
.split(reference)
|
|
180
|
-
.join(`var(${cssVar}, ${applyCssValue(literal, camelToKebabCase(prop))})`);
|
|
181
|
-
}
|
|
182
|
-
else if (value !== null && typeof value === 'object') {
|
|
183
|
-
applyVarFallback(value, cssVar, literal);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
84
|
export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
188
85
|
const filter = createFilter(options.include, options.exclude);
|
|
189
86
|
const propertyPolicy = resolvePropertyPolicy(options);
|
|
@@ -339,18 +236,22 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
339
236
|
}
|
|
340
237
|
}
|
|
341
238
|
const components = [];
|
|
239
|
+
const propAliases = new Map();
|
|
240
|
+
const addComponent = (name, fn) => {
|
|
241
|
+
components.push({ name, node: fn });
|
|
242
|
+
const aliases = destructuredPropAliases(fn);
|
|
243
|
+
if (aliases.size > 0)
|
|
244
|
+
propAliases.set(name, aliases);
|
|
245
|
+
};
|
|
342
246
|
for (const node of ast.body) {
|
|
343
247
|
const statement = unwrapExport(node);
|
|
344
248
|
if (isFunctionNode(statement)) {
|
|
345
|
-
|
|
346
|
-
name: statement.identifier?.value ?? 'default',
|
|
347
|
-
node: statement,
|
|
348
|
-
});
|
|
249
|
+
addComponent(statement.identifier?.value ?? 'default', statement);
|
|
349
250
|
}
|
|
350
251
|
else if (statement?.type === 'CallExpression') {
|
|
351
252
|
const fn = componentFunctionOf(statement);
|
|
352
253
|
if (fn)
|
|
353
|
-
|
|
254
|
+
addComponent('default', fn);
|
|
354
255
|
}
|
|
355
256
|
else if (t.isVariableDeclaration(statement)) {
|
|
356
257
|
for (const decl of statement.declarations) {
|
|
@@ -358,7 +259,7 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
358
259
|
continue;
|
|
359
260
|
const fn = componentFunctionOf(decl.init);
|
|
360
261
|
if (fn)
|
|
361
|
-
|
|
262
|
+
addComponent(decl.id.value, fn);
|
|
362
263
|
}
|
|
363
264
|
}
|
|
364
265
|
}
|
|
@@ -558,6 +459,16 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
558
459
|
for (const key of Object.keys(createStaticImportMap)) {
|
|
559
460
|
mergedCreateStaticHashTable[key] = createStaticImportMap[key];
|
|
560
461
|
}
|
|
462
|
+
const dynamicStyleTables = {
|
|
463
|
+
keyframesHashTable: mergedKeyframesTable,
|
|
464
|
+
viewTransitionHashTable: mergedViewTransitionTable,
|
|
465
|
+
createThemeHashTable: mergedCreateThemeHashTable,
|
|
466
|
+
createThemeObjectTable: scannedTables.createThemeObjectTable,
|
|
467
|
+
createHashTable: mergedCreateTable,
|
|
468
|
+
createStaticHashTable: mergedCreateStaticHashTable,
|
|
469
|
+
createStaticObjectTable: scannedTables.createStaticObjectTable,
|
|
470
|
+
variantsHashTable: mergedVariantsTable,
|
|
471
|
+
};
|
|
561
472
|
const localCreateStyles = {};
|
|
562
473
|
const localStyleAliases = {};
|
|
563
474
|
const checkStyleAliasAssignment = (decl) => {
|
|
@@ -959,7 +870,16 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
959
870
|
}
|
|
960
871
|
return null;
|
|
961
872
|
};
|
|
962
|
-
const
|
|
873
|
+
const isStyleFunctionCall = (expr) => {
|
|
874
|
+
if (!t.isCallExpression(expr) || !t.isMemberExpression(expr.callee))
|
|
875
|
+
return false;
|
|
876
|
+
const callee = expr.callee;
|
|
877
|
+
if (!t.isIdentifier(callee.object) || !t.isIdentifier(callee.property))
|
|
878
|
+
return false;
|
|
879
|
+
return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
|
|
880
|
+
createFunctionImportMap[callee.object.value]?.[callee.property.value]);
|
|
881
|
+
};
|
|
882
|
+
const resolveDynamicCall = (expr, forceRuntime = false) => {
|
|
963
883
|
if (!t.isCallExpression(expr) || !t.isMemberExpression(expr.callee))
|
|
964
884
|
return null;
|
|
965
885
|
const callee = expr.callee;
|
|
@@ -1003,7 +923,9 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1003
923
|
throwCompilationError(`Plumeria: ${getSource(expr)} leaves "${key}" unset, and a dynamic style function has no value to fall back on.`, expr);
|
|
1004
924
|
return;
|
|
1005
925
|
}
|
|
1006
|
-
if (
|
|
926
|
+
if (!forceRuntime &&
|
|
927
|
+
isStaticArgValue(source) &&
|
|
928
|
+
argObj[key] !== undefined)
|
|
1007
929
|
tempStaticTable[local] = argObj[key];
|
|
1008
930
|
else
|
|
1009
931
|
runtime.push({ param: local, source });
|
|
@@ -1011,6 +933,8 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1011
933
|
}
|
|
1012
934
|
else if (callArgs.length === 1 &&
|
|
1013
935
|
callArgs[0].expression.type === 'ObjectExpression') {
|
|
936
|
+
if (forceRuntime)
|
|
937
|
+
return null;
|
|
1014
938
|
const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
|
|
1015
939
|
func.params.forEach((p) => {
|
|
1016
940
|
if (argObj[p] !== undefined)
|
|
@@ -1025,39 +949,10 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1025
949
|
runtime.push({ param: p, source: callArg.expression });
|
|
1026
950
|
});
|
|
1027
951
|
}
|
|
1028
|
-
const
|
|
1029
|
-
|
|
1030
|
-
const varParams = Array.from(new Set([
|
|
1031
|
-
...runtime.map(({ param }) => param),
|
|
1032
|
-
...withDefault.map(([param]) => param),
|
|
1033
|
-
]));
|
|
1034
|
-
if (varParams.length > 0) {
|
|
1035
|
-
varParams.forEach((param) => (tempStaticTable[param] = param));
|
|
1036
|
-
const probe = objectExpressionToObject(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
1037
|
-
const hash = genBase36Hash(probe ?? {}, 1, 8);
|
|
1038
|
-
varParams.forEach((param) => {
|
|
1039
|
-
const cssVar = `--${hash}-${param}`;
|
|
1040
|
-
tempStaticTable[param] = `var(${cssVar})`;
|
|
1041
|
-
cssVars[param] = cssVar;
|
|
1042
|
-
});
|
|
1043
|
-
}
|
|
1044
|
-
const style = objectExpressionToObject(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
1045
|
-
if (!style)
|
|
952
|
+
const resolved = resolveDynamicStyle(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables);
|
|
953
|
+
if (!resolved)
|
|
1046
954
|
return null;
|
|
1047
|
-
const varGroups =
|
|
1048
|
-
varParams.forEach((param) => {
|
|
1049
|
-
const cssVar = cssVars[param];
|
|
1050
|
-
if (cssVar)
|
|
1051
|
-
varGroups.set(param, splitVarByUnit(style, cssVar));
|
|
1052
|
-
});
|
|
1053
|
-
withDefault.forEach(([param, expr]) => {
|
|
1054
|
-
const literal = expr.type === 'StringLiteral' || expr.type === 'NumericLiteral'
|
|
1055
|
-
? expr.value
|
|
1056
|
-
: undefined;
|
|
1057
|
-
if (literal === undefined)
|
|
1058
|
-
return;
|
|
1059
|
-
(varGroups.get(param) ?? []).forEach(({ cssVar }) => applyVarFallback(style, cssVar, literal));
|
|
1060
|
-
});
|
|
955
|
+
const { style, varGroups } = resolved;
|
|
1061
956
|
const vars = [];
|
|
1062
957
|
runtime.forEach(({ param, source }) => {
|
|
1063
958
|
const groups = varGroups.get(param);
|
|
@@ -1099,6 +994,7 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1099
994
|
});
|
|
1100
995
|
const conditionals = [];
|
|
1101
996
|
const dynamicVars = [];
|
|
997
|
+
const propVarSpreads = [];
|
|
1102
998
|
let groupIdCounter = 0;
|
|
1103
999
|
let sourceOrder = 0;
|
|
1104
1000
|
const baseChunks = [];
|
|
@@ -1218,6 +1114,8 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1218
1114
|
return buildDecision(node, prefix, off, { n: 0 }, scoped);
|
|
1219
1115
|
};
|
|
1220
1116
|
const collectConditions = (node, currentTestStrings = [], argOrder) => {
|
|
1117
|
+
if (isNoOpStyle(node))
|
|
1118
|
+
return true;
|
|
1221
1119
|
let branchStyle = resolveStyleObject(node);
|
|
1222
1120
|
if (!branchStyle) {
|
|
1223
1121
|
const dynamic = resolveDynamicCall(node);
|
|
@@ -1298,17 +1196,20 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1298
1196
|
? expr.value
|
|
1299
1197
|
: expr.property.value;
|
|
1300
1198
|
const source = t.isIdentifier(expr) ? varName : getSource(expr);
|
|
1301
|
-
markStylePropApplied(varName, expr);
|
|
1302
1199
|
const owner = ownerComponentOf(expr);
|
|
1200
|
+
const propName = (t.isIdentifier(expr) && owner
|
|
1201
|
+
? propAliases.get(owner)?.get(varName)
|
|
1202
|
+
: undefined) ?? varName;
|
|
1203
|
+
markStylePropApplied(propName, expr);
|
|
1303
1204
|
let possibilities = owner
|
|
1304
|
-
? scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[
|
|
1205
|
+
? scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[propName]
|
|
1305
1206
|
: undefined;
|
|
1306
1207
|
if (!possibilities) {
|
|
1307
1208
|
const candidates = [];
|
|
1308
1209
|
for (const key of Object.keys(scannedTables.componentPropsTable || {})) {
|
|
1309
1210
|
if (!key.startsWith(`${resourcePath}-`))
|
|
1310
1211
|
continue;
|
|
1311
|
-
const entries = scannedTables.componentPropsTable?.[key]?.[
|
|
1212
|
+
const entries = scannedTables.componentPropsTable?.[key]?.[propName];
|
|
1312
1213
|
if (entries)
|
|
1313
1214
|
candidates.push(...entries);
|
|
1314
1215
|
}
|
|
@@ -1317,9 +1218,23 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1317
1218
|
}
|
|
1318
1219
|
if (!possibilities || possibilities.length === 0)
|
|
1319
1220
|
return false;
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1221
|
+
const carriesVars = possibilities.some((entry) => entry.hasVars);
|
|
1222
|
+
if (carriesVars && !isStyleProp) {
|
|
1223
|
+
throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
|
|
1224
|
+
`Apply it to ${styleProp} on the element instead.`, expr);
|
|
1225
|
+
}
|
|
1226
|
+
const gate = gates.length ? `(${gates.join(' && ')}) && ` : '';
|
|
1227
|
+
if (carriesVars) {
|
|
1228
|
+
const spread = `...(${gate}${source} && ${source}.vars)`;
|
|
1229
|
+
if (!propVarSpreads.includes(spread))
|
|
1230
|
+
propVarSpreads.push(spread);
|
|
1231
|
+
}
|
|
1232
|
+
const token = carriesVars
|
|
1233
|
+
? `((${source} && ${source}.key) || ${source})`
|
|
1322
1234
|
: source;
|
|
1235
|
+
const testLHS = gates.length
|
|
1236
|
+
? `((${gates.join(' && ')}) ? ${token} : "")`
|
|
1237
|
+
: token;
|
|
1323
1238
|
const currentGroupId = ++groupIdCounter;
|
|
1324
1239
|
const currentOrder = sourceOrder++;
|
|
1325
1240
|
const seen = new Set();
|
|
@@ -1349,6 +1264,8 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1349
1264
|
};
|
|
1350
1265
|
for (const arg of args) {
|
|
1351
1266
|
const expr = arg.expression;
|
|
1267
|
+
if (isNoOpStyle(expr))
|
|
1268
|
+
continue;
|
|
1352
1269
|
if (pushPropPossibilities(expr, []))
|
|
1353
1270
|
continue;
|
|
1354
1271
|
if (t.isCallExpression(expr) && t.isIdentifier(expr.callee)) {
|
|
@@ -1558,6 +1475,7 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1558
1475
|
isOptimizable,
|
|
1559
1476
|
baseStyle,
|
|
1560
1477
|
dynamicVars,
|
|
1478
|
+
propVarSpreads,
|
|
1561
1479
|
};
|
|
1562
1480
|
}
|
|
1563
1481
|
const stateSources = baseChunks.map(({ order, style }) => ({ order, style: style }));
|
|
@@ -1813,7 +1731,13 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
1813
1731
|
classParts.push(`(${JSON.stringify(results)}[${masterKeyExpr || '""'}] || ${baseConflictClass ? JSON.stringify(baseConflictClass) : '""'})`);
|
|
1814
1732
|
}
|
|
1815
1733
|
classParts.push(...dynamicClassParts);
|
|
1816
|
-
return {
|
|
1734
|
+
return {
|
|
1735
|
+
classParts,
|
|
1736
|
+
isOptimizable,
|
|
1737
|
+
baseStyle,
|
|
1738
|
+
dynamicVars,
|
|
1739
|
+
propVarSpreads,
|
|
1740
|
+
};
|
|
1817
1741
|
};
|
|
1818
1742
|
traverse(ast, {
|
|
1819
1743
|
JSXOpeningElement({ node }) {
|
|
@@ -2014,14 +1938,40 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2014
1938
|
node.value &&
|
|
2015
1939
|
node.value.type === 'JSXExpressionContainer') {
|
|
2016
1940
|
const expr = node.value.expression;
|
|
1941
|
+
const carrierFor = (subNode) => {
|
|
1942
|
+
const vars = [];
|
|
1943
|
+
let unresolved = false;
|
|
1944
|
+
traverse(subNode, {
|
|
1945
|
+
CallExpression({ node: call }) {
|
|
1946
|
+
if (!isStyleFunctionCall(call))
|
|
1947
|
+
return;
|
|
1948
|
+
const resolved = resolveDynamicCall(call, true);
|
|
1949
|
+
if (!resolved) {
|
|
1950
|
+
unresolved = true;
|
|
1951
|
+
return;
|
|
1952
|
+
}
|
|
1953
|
+
vars.push(...resolved.vars);
|
|
1954
|
+
},
|
|
1955
|
+
});
|
|
1956
|
+
if (unresolved)
|
|
1957
|
+
return null;
|
|
1958
|
+
return `{ ${foldDynamicVars(vars).join(', ')} }`;
|
|
1959
|
+
};
|
|
2017
1960
|
const replaceWithKey = (subNode) => {
|
|
2018
1961
|
const entry = list.find((x) => x.spanStart === subNode.span.start &&
|
|
2019
1962
|
x.filePath === resourcePath);
|
|
2020
1963
|
if (entry) {
|
|
1964
|
+
let content = JSON.stringify(entry.key);
|
|
1965
|
+
if (entry.hasVars) {
|
|
1966
|
+
const carrier = carrierFor(subNode);
|
|
1967
|
+
if (!carrier)
|
|
1968
|
+
return false;
|
|
1969
|
+
content = `{ key: ${content}, vars: ${carrier} }`;
|
|
1970
|
+
}
|
|
2021
1971
|
replacements.push({
|
|
2022
1972
|
start: subNode.span.start - baseByteOffset,
|
|
2023
1973
|
end: subNode.span.end - baseByteOffset,
|
|
2024
|
-
content
|
|
1974
|
+
content,
|
|
2025
1975
|
});
|
|
2026
1976
|
processStyleRecords(entry.styleObj);
|
|
2027
1977
|
return true;
|
|
@@ -2039,6 +1989,11 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2039
1989
|
excludeSubtreeSpans(subNode);
|
|
2040
1990
|
}
|
|
2041
1991
|
},
|
|
1992
|
+
CallExpression({ node: subNode }) {
|
|
1993
|
+
if (replaceWithKey(subNode)) {
|
|
1994
|
+
excludeSubtreeSpans(subNode);
|
|
1995
|
+
}
|
|
1996
|
+
},
|
|
2042
1997
|
});
|
|
2043
1998
|
}
|
|
2044
1999
|
}
|
|
@@ -2114,9 +2069,12 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2114
2069
|
}
|
|
2115
2070
|
}
|
|
2116
2071
|
}
|
|
2117
|
-
const { classParts, isOptimizable, baseStyle, dynamicVars } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
|
|
2118
|
-
const
|
|
2119
|
-
|
|
2072
|
+
const { classParts, isOptimizable, baseStyle, dynamicVars, propVarSpreads, } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
|
|
2073
|
+
const styleParts = [
|
|
2074
|
+
...existingStyleParts,
|
|
2075
|
+
...foldDynamicVars(dynamicVars),
|
|
2076
|
+
...propVarSpreads,
|
|
2077
|
+
];
|
|
2120
2078
|
const styleAttr = styleParts.length > 0 || existingStyleExpr
|
|
2121
2079
|
? ` style={{ ${[existingStyleExpr, ...styleParts].filter(Boolean).join(', ')} }}`
|
|
2122
2080
|
: '';
|
|
@@ -2132,10 +2090,13 @@ export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
|
2132
2090
|
});
|
|
2133
2091
|
}
|
|
2134
2092
|
else {
|
|
2093
|
+
const keptClass = existingClassExpr
|
|
2094
|
+
? `className={${existingClassExpr}}`
|
|
2095
|
+
: '';
|
|
2135
2096
|
replacements.push({
|
|
2136
2097
|
start: node.span.start - baseByteOffset,
|
|
2137
2098
|
end: node.span.end - baseByteOffset,
|
|
2138
|
-
content: styleAttr
|
|
2099
|
+
content: `${keptClass}${styleAttr}`,
|
|
2139
2100
|
});
|
|
2140
2101
|
}
|
|
2141
2102
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumeria/unplugin",
|
|
3
|
-
"version": "18.4.
|
|
3
|
+
"version": "18.4.2",
|
|
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.4.
|
|
97
|
+
"@plumeria/utils": "^18.4.2"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@swc/core": "1.15.47",
|