@plumeria/unplugin 10.5.3
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/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/bun.d.ts +3 -0
- package/dist/bun.js +5 -0
- package/dist/bun.mjs +3 -0
- package/dist/core.d.ts +9 -0
- package/dist/core.js +1298 -0
- package/dist/core.mjs +1261 -0
- package/dist/disk-css.d.ts +4 -0
- package/dist/disk-css.js +104 -0
- package/dist/disk-css.mjs +65 -0
- package/dist/esbuild.d.ts +3 -0
- package/dist/esbuild.js +5 -0
- package/dist/esbuild.mjs +3 -0
- package/dist/farm.d.ts +3 -0
- package/dist/farm.js +111 -0
- package/dist/farm.mjs +76 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +38 -0
- package/dist/index.mjs +24 -0
- package/dist/rolldown.d.ts +3 -0
- package/dist/rolldown.js +5 -0
- package/dist/rolldown.mjs +3 -0
- package/dist/rollup.d.ts +3 -0
- package/dist/rollup.js +5 -0
- package/dist/rollup.mjs +3 -0
- package/dist/rspack.d.ts +3 -0
- package/dist/rspack.js +8 -0
- package/dist/rspack.mjs +6 -0
- package/dist/unloader.d.ts +3 -0
- package/dist/unloader.js +5 -0
- package/dist/unloader.mjs +3 -0
- package/dist/vite.d.ts +7 -0
- package/dist/vite.js +143 -0
- package/dist/vite.mjs +108 -0
- package/dist/webpack.d.ts +4 -0
- package/dist/webpack.js +167 -0
- package/dist/webpack.mjs +131 -0
- package/package.json +105 -0
- package/zero-virtual.css +1 -0
package/dist/core.mjs
ADDED
|
@@ -0,0 +1,1261 @@
|
|
|
1
|
+
import { createFilter } from '@rollup/pluginutils';
|
|
2
|
+
import { parseSync } from '@swc/core';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { applyCssValue, genBase36Hash, exceptionCamelCase } from 'zss-engine';
|
|
5
|
+
import { traverse, getStyleRecords, collectLocalConsts, objectExpressionToObject, t, extractOndemandStyles, deepMerge, scanAll, resolveImportPath, processVariants, getLeadingCommentLength, optimizer, } from '@plumeria/utils';
|
|
6
|
+
export const TARGET_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx'];
|
|
7
|
+
export const EXTENSION_PATTERN = /\.(ts|tsx|js|jsx)$/;
|
|
8
|
+
export const unpluginFactory = (options = {}, unpluginMeta) => {
|
|
9
|
+
const filter = createFilter(options.include, options.exclude);
|
|
10
|
+
const cssLookup = new Map();
|
|
11
|
+
const cssFileLookup = new Map();
|
|
12
|
+
const targets = [];
|
|
13
|
+
const devCssSheets = new Map();
|
|
14
|
+
let isDev = false;
|
|
15
|
+
let viteRoot = process.cwd();
|
|
16
|
+
return {
|
|
17
|
+
name: '@plumeria/unplugin',
|
|
18
|
+
enforce: 'pre',
|
|
19
|
+
__plumeriaInternal: {
|
|
20
|
+
cssLookup,
|
|
21
|
+
cssFileLookup,
|
|
22
|
+
targets,
|
|
23
|
+
devCssSheets,
|
|
24
|
+
unpluginMeta,
|
|
25
|
+
setDev(value) {
|
|
26
|
+
isDev = value;
|
|
27
|
+
},
|
|
28
|
+
setRoot(root) {
|
|
29
|
+
viteRoot = root;
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
resolveId(id, importer) {
|
|
33
|
+
const [pathId, query] = id.split('?');
|
|
34
|
+
if (pathId.endsWith('.zero.css')) {
|
|
35
|
+
if (pathId.startsWith('/')) {
|
|
36
|
+
let absolutePath = cssFileLookup.get(pathId);
|
|
37
|
+
if (!absolutePath) {
|
|
38
|
+
absolutePath = path.join(viteRoot, pathId);
|
|
39
|
+
}
|
|
40
|
+
return query ? `${absolutePath}?${query}` : absolutePath;
|
|
41
|
+
}
|
|
42
|
+
if (importer && !path.isAbsolute(pathId)) {
|
|
43
|
+
const resolved = path.resolve(path.dirname(importer), pathId);
|
|
44
|
+
return query ? `${resolved}?${query}` : resolved;
|
|
45
|
+
}
|
|
46
|
+
return query ? `${pathId}?${query}` : pathId;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
},
|
|
50
|
+
loadInclude(id) {
|
|
51
|
+
const [pathId] = id.split('?');
|
|
52
|
+
return pathId.endsWith('.zero.css');
|
|
53
|
+
},
|
|
54
|
+
load(id) {
|
|
55
|
+
const [pathId] = id.split('?', 1);
|
|
56
|
+
return cssLookup.get(pathId) || '';
|
|
57
|
+
},
|
|
58
|
+
transformInclude(id) {
|
|
59
|
+
return filter(id);
|
|
60
|
+
},
|
|
61
|
+
async transform(source, id) {
|
|
62
|
+
if (id.includes('node_modules'))
|
|
63
|
+
return null;
|
|
64
|
+
if (!source.includes('@plumeria/core'))
|
|
65
|
+
return null;
|
|
66
|
+
const [baseId] = id.split('?');
|
|
67
|
+
if (!filter(baseId))
|
|
68
|
+
return null;
|
|
69
|
+
const dependencies = [];
|
|
70
|
+
const addDependency = (depPath) => {
|
|
71
|
+
dependencies.push(depPath);
|
|
72
|
+
if (this.addWatchFile) {
|
|
73
|
+
this.addWatchFile(depPath);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const ast = parseSync(source, {
|
|
77
|
+
syntax: 'typescript',
|
|
78
|
+
tsx: true,
|
|
79
|
+
target: 'es2022',
|
|
80
|
+
});
|
|
81
|
+
const leadingLen = getLeadingCommentLength(source);
|
|
82
|
+
const sourceBuffer = Buffer.from(source, 'utf-8');
|
|
83
|
+
const leadingBytes = Buffer.byteLength(source.slice(0, leadingLen), 'utf-8');
|
|
84
|
+
const baseByteOffset = ast.span.start - leadingBytes;
|
|
85
|
+
for (const node of ast.body) {
|
|
86
|
+
if (node.type === 'ImportDeclaration') {
|
|
87
|
+
const sourcePath = node.source.value;
|
|
88
|
+
const actualPath = resolveImportPath(sourcePath, id);
|
|
89
|
+
if (actualPath) {
|
|
90
|
+
addDependency(actualPath);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const scannedTables = scanAll();
|
|
95
|
+
const extractedSheets = [];
|
|
96
|
+
const addSheet = (sheet) => {
|
|
97
|
+
if (!extractedSheets.includes(sheet)) {
|
|
98
|
+
extractedSheets.push(sheet);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const processStyleRecords = (style) => {
|
|
102
|
+
const records = getStyleRecords(style);
|
|
103
|
+
extractOndemandStyles(style, extractedSheets, scannedTables);
|
|
104
|
+
records.forEach((r) => {
|
|
105
|
+
addSheet(r.sheet);
|
|
106
|
+
});
|
|
107
|
+
return records;
|
|
108
|
+
};
|
|
109
|
+
const localConsts = collectLocalConsts(ast);
|
|
110
|
+
const resourcePath = id;
|
|
111
|
+
const importMap = {};
|
|
112
|
+
const createThemeImportMap = {};
|
|
113
|
+
const createStaticImportMap = {};
|
|
114
|
+
const plumeriaAliases = {};
|
|
115
|
+
traverse(ast, {
|
|
116
|
+
ImportDeclaration({ node }) {
|
|
117
|
+
const sourcePath = node.source.value;
|
|
118
|
+
if (sourcePath === '@plumeria/core') {
|
|
119
|
+
node.specifiers.forEach((specifier) => {
|
|
120
|
+
if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
121
|
+
plumeriaAliases[specifier.local.value] = 'NAMESPACE';
|
|
122
|
+
}
|
|
123
|
+
else if (specifier.type === 'ImportDefaultSpecifier') {
|
|
124
|
+
plumeriaAliases[specifier.local.value] = 'NAMESPACE';
|
|
125
|
+
}
|
|
126
|
+
else if (specifier.type === 'ImportSpecifier') {
|
|
127
|
+
const importedName = specifier.imported
|
|
128
|
+
? specifier.imported.value
|
|
129
|
+
: specifier.local.value;
|
|
130
|
+
plumeriaAliases[specifier.local.value] = importedName;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const actualPath = resolveImportPath(sourcePath, resourcePath);
|
|
135
|
+
if (actualPath) {
|
|
136
|
+
node.specifiers.forEach((specifier) => {
|
|
137
|
+
if (specifier.type === 'ImportSpecifier') {
|
|
138
|
+
const importedName = specifier.imported
|
|
139
|
+
? specifier.imported.value
|
|
140
|
+
: specifier.local.value;
|
|
141
|
+
const localName = specifier.local.value;
|
|
142
|
+
const uniqueKey = `${actualPath}-${importedName}`;
|
|
143
|
+
if (scannedTables.staticTable[uniqueKey]) {
|
|
144
|
+
importMap[localName] = scannedTables.staticTable[uniqueKey];
|
|
145
|
+
}
|
|
146
|
+
if (scannedTables.keyframesHashTable[uniqueKey]) {
|
|
147
|
+
importMap[localName] =
|
|
148
|
+
scannedTables.keyframesHashTable[uniqueKey];
|
|
149
|
+
}
|
|
150
|
+
if (scannedTables.viewTransitionHashTable[uniqueKey]) {
|
|
151
|
+
importMap[localName] =
|
|
152
|
+
scannedTables.viewTransitionHashTable[uniqueKey];
|
|
153
|
+
}
|
|
154
|
+
if (scannedTables.createHashTable[uniqueKey]) {
|
|
155
|
+
importMap[localName] =
|
|
156
|
+
scannedTables.createHashTable[uniqueKey];
|
|
157
|
+
}
|
|
158
|
+
if (scannedTables.variantsHashTable[uniqueKey]) {
|
|
159
|
+
importMap[localName] =
|
|
160
|
+
scannedTables.variantsHashTable[uniqueKey];
|
|
161
|
+
}
|
|
162
|
+
if (scannedTables.createThemeHashTable[uniqueKey]) {
|
|
163
|
+
createThemeImportMap[localName] =
|
|
164
|
+
scannedTables.createThemeHashTable[uniqueKey];
|
|
165
|
+
}
|
|
166
|
+
if (scannedTables.createStaticHashTable[uniqueKey]) {
|
|
167
|
+
createStaticImportMap[localName] =
|
|
168
|
+
scannedTables.createStaticHashTable[uniqueKey];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
const mergedStaticTable = {};
|
|
176
|
+
for (const key of Object.keys(scannedTables.staticTable)) {
|
|
177
|
+
mergedStaticTable[key] = scannedTables.staticTable[key];
|
|
178
|
+
}
|
|
179
|
+
for (const key of Object.keys(localConsts)) {
|
|
180
|
+
mergedStaticTable[key] = localConsts[key];
|
|
181
|
+
}
|
|
182
|
+
for (const key of Object.keys(importMap)) {
|
|
183
|
+
mergedStaticTable[key] = importMap[key];
|
|
184
|
+
}
|
|
185
|
+
const mergedKeyframesTable = {};
|
|
186
|
+
for (const key of Object.keys(scannedTables.keyframesHashTable)) {
|
|
187
|
+
mergedKeyframesTable[key] = scannedTables.keyframesHashTable[key];
|
|
188
|
+
}
|
|
189
|
+
for (const key of Object.keys(importMap)) {
|
|
190
|
+
const val = importMap[key];
|
|
191
|
+
if (typeof val === 'string') {
|
|
192
|
+
mergedKeyframesTable[key] = val;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const mergedViewTransitionTable = {};
|
|
196
|
+
for (const key of Object.keys(scannedTables.viewTransitionHashTable)) {
|
|
197
|
+
mergedViewTransitionTable[key] =
|
|
198
|
+
scannedTables.viewTransitionHashTable[key];
|
|
199
|
+
}
|
|
200
|
+
for (const key of Object.keys(importMap)) {
|
|
201
|
+
const val = importMap[key];
|
|
202
|
+
if (typeof val === 'string') {
|
|
203
|
+
mergedViewTransitionTable[key] = val;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const mergedCreateTable = {};
|
|
207
|
+
for (const key of Object.keys(scannedTables.createHashTable)) {
|
|
208
|
+
mergedCreateTable[key] = scannedTables.createHashTable[key];
|
|
209
|
+
}
|
|
210
|
+
for (const key of Object.keys(importMap)) {
|
|
211
|
+
const val = importMap[key];
|
|
212
|
+
if (typeof val === 'string') {
|
|
213
|
+
mergedCreateTable[key] = val;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const mergedVariantsTable = {};
|
|
217
|
+
for (const key of Object.keys(scannedTables.variantsHashTable)) {
|
|
218
|
+
mergedVariantsTable[key] = scannedTables.variantsHashTable[key];
|
|
219
|
+
}
|
|
220
|
+
for (const key of Object.keys(importMap)) {
|
|
221
|
+
const val = importMap[key];
|
|
222
|
+
if (typeof val === 'string') {
|
|
223
|
+
mergedVariantsTable[key] = val;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const mergedCreateThemeHashTable = {};
|
|
227
|
+
for (const key of Object.keys(scannedTables.createThemeHashTable)) {
|
|
228
|
+
mergedCreateThemeHashTable[key] =
|
|
229
|
+
scannedTables.createThemeHashTable[key];
|
|
230
|
+
if (key.startsWith(`${resourcePath}-`)) {
|
|
231
|
+
const varName = key.slice(resourcePath.length + 1);
|
|
232
|
+
mergedCreateThemeHashTable[varName] =
|
|
233
|
+
scannedTables.createThemeHashTable[key];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
for (const key of Object.keys(createThemeImportMap)) {
|
|
237
|
+
mergedCreateThemeHashTable[key] = createThemeImportMap[key];
|
|
238
|
+
}
|
|
239
|
+
const mergedCreateStaticHashTable = {};
|
|
240
|
+
for (const key of Object.keys(scannedTables.createStaticHashTable)) {
|
|
241
|
+
mergedCreateStaticHashTable[key] =
|
|
242
|
+
scannedTables.createStaticHashTable[key];
|
|
243
|
+
if (key.startsWith(`${resourcePath}-`)) {
|
|
244
|
+
const varName = key.slice(resourcePath.length + 1);
|
|
245
|
+
mergedCreateStaticHashTable[varName] =
|
|
246
|
+
scannedTables.createStaticHashTable[key];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
for (const key of Object.keys(createStaticImportMap)) {
|
|
250
|
+
mergedCreateStaticHashTable[key] = createStaticImportMap[key];
|
|
251
|
+
}
|
|
252
|
+
const localCreateStyles = {};
|
|
253
|
+
const replacements = [];
|
|
254
|
+
const processedDecls = new Set();
|
|
255
|
+
const idSpans = new Set();
|
|
256
|
+
const excludedSpans = new Set();
|
|
257
|
+
const getSource = (node) => {
|
|
258
|
+
const start = node.span.start - baseByteOffset;
|
|
259
|
+
const end = node.span.end - baseByteOffset;
|
|
260
|
+
return sourceBuffer.subarray(start, end).toString('utf-8');
|
|
261
|
+
};
|
|
262
|
+
const resolveStyleObject = (expr) => {
|
|
263
|
+
if (t.isObjectExpression(expr)) {
|
|
264
|
+
return objectExpressionToObject(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
265
|
+
}
|
|
266
|
+
else if (t.isMemberExpression(expr) &&
|
|
267
|
+
t.isIdentifier(expr.object) &&
|
|
268
|
+
(t.isIdentifier(expr.property) || expr.property.type === 'Computed')) {
|
|
269
|
+
if (expr.property.type === 'Computed')
|
|
270
|
+
return {};
|
|
271
|
+
const varName = expr.object.value;
|
|
272
|
+
const propName = expr.property.value;
|
|
273
|
+
const styleInfo = localCreateStyles[varName];
|
|
274
|
+
if (styleInfo?.obj[propName]) {
|
|
275
|
+
const style = styleInfo.obj[propName];
|
|
276
|
+
if (typeof style === 'object' && style !== null)
|
|
277
|
+
return style;
|
|
278
|
+
}
|
|
279
|
+
const hash = mergedCreateTable[varName];
|
|
280
|
+
if (hash) {
|
|
281
|
+
const obj = scannedTables.createObjectTable[hash];
|
|
282
|
+
if (obj?.[propName] && typeof obj[propName] === 'object')
|
|
283
|
+
return obj[propName];
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
else if (t.isIdentifier(expr)) {
|
|
287
|
+
const varName = expr.value;
|
|
288
|
+
const uniqueKey = `${resourcePath}-${varName}`;
|
|
289
|
+
let hash = scannedTables.createHashTable[uniqueKey];
|
|
290
|
+
if (!hash)
|
|
291
|
+
hash = mergedCreateTable[varName];
|
|
292
|
+
if (hash) {
|
|
293
|
+
const obj = scannedTables.createObjectTable[hash];
|
|
294
|
+
if (obj && typeof obj === 'object')
|
|
295
|
+
return obj;
|
|
296
|
+
}
|
|
297
|
+
const styleInfo = localCreateStyles[varName];
|
|
298
|
+
if (styleInfo?.obj)
|
|
299
|
+
return styleInfo.obj;
|
|
300
|
+
const vHash = mergedVariantsTable[varName];
|
|
301
|
+
if (vHash)
|
|
302
|
+
return scannedTables.variantsObjectTable[vHash];
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
};
|
|
306
|
+
const buildClassParts = (args, dynamicClassParts = [], existingClass = '') => {
|
|
307
|
+
const conditionals = [];
|
|
308
|
+
let groupIdCounter = 0;
|
|
309
|
+
let baseStyle = {};
|
|
310
|
+
let isOptimizable = true;
|
|
311
|
+
const collectConditions = (node, currentTestStrings = []) => {
|
|
312
|
+
const staticStyle = resolveStyleObject(node);
|
|
313
|
+
if (staticStyle) {
|
|
314
|
+
if (currentTestStrings.length === 0) {
|
|
315
|
+
baseStyle = deepMerge(baseStyle, staticStyle);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
conditionals.push({
|
|
319
|
+
test: node,
|
|
320
|
+
testString: currentTestStrings.join(' && '),
|
|
321
|
+
truthy: staticStyle,
|
|
322
|
+
falsy: {},
|
|
323
|
+
varName: undefined,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
if (node.type === 'ConditionalExpression') {
|
|
329
|
+
const testSource = getSource(node.test);
|
|
330
|
+
if (currentTestStrings.length === 0) {
|
|
331
|
+
const trueStyle = resolveStyleObject(node.consequent);
|
|
332
|
+
const falseStyle = resolveStyleObject(node.alternate);
|
|
333
|
+
if (trueStyle && falseStyle) {
|
|
334
|
+
conditionals.push({
|
|
335
|
+
test: node,
|
|
336
|
+
testString: testSource,
|
|
337
|
+
truthy: trueStyle,
|
|
338
|
+
falsy: falseStyle,
|
|
339
|
+
varName: undefined,
|
|
340
|
+
});
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
collectConditions(node.consequent, [
|
|
345
|
+
...currentTestStrings,
|
|
346
|
+
`(${testSource})`,
|
|
347
|
+
]);
|
|
348
|
+
collectConditions(node.alternate, [
|
|
349
|
+
...currentTestStrings,
|
|
350
|
+
`!(${testSource})`,
|
|
351
|
+
]);
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
else if (node.type === 'BinaryExpression' &&
|
|
355
|
+
node.operator === '&&') {
|
|
356
|
+
collectConditions(node.right, [
|
|
357
|
+
...currentTestStrings,
|
|
358
|
+
`(${getSource(node.left)})`,
|
|
359
|
+
]);
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
else if (node.type === 'ParenthesisExpression') {
|
|
363
|
+
return collectConditions(node.expression, currentTestStrings);
|
|
364
|
+
}
|
|
365
|
+
return false;
|
|
366
|
+
};
|
|
367
|
+
for (const arg of args) {
|
|
368
|
+
const expr = arg.expression;
|
|
369
|
+
if (t.isCallExpression(expr) && t.isIdentifier(expr.callee)) {
|
|
370
|
+
const varName = expr.callee.value;
|
|
371
|
+
const uniqueKey = `${resourcePath}-${varName}`;
|
|
372
|
+
let variantObj;
|
|
373
|
+
let hash = scannedTables.variantsHashTable[uniqueKey];
|
|
374
|
+
if (!hash)
|
|
375
|
+
hash = mergedVariantsTable[varName];
|
|
376
|
+
if (hash && scannedTables.variantsObjectTable[hash])
|
|
377
|
+
variantObj = scannedTables.variantsObjectTable[hash];
|
|
378
|
+
if (!variantObj && localCreateStyles[varName]?.obj)
|
|
379
|
+
variantObj = localCreateStyles[varName].obj;
|
|
380
|
+
if (variantObj) {
|
|
381
|
+
const callArgs = expr.arguments;
|
|
382
|
+
if (callArgs.length === 1 && !callArgs[0].spread) {
|
|
383
|
+
const innerArg = callArgs[0].expression;
|
|
384
|
+
if (innerArg.type === 'ObjectExpression') {
|
|
385
|
+
for (const prop of innerArg.properties) {
|
|
386
|
+
let groupName;
|
|
387
|
+
let valExpr;
|
|
388
|
+
if (prop.type === 'KeyValueProperty' &&
|
|
389
|
+
prop.key.type === 'Identifier') {
|
|
390
|
+
groupName = prop.key.value;
|
|
391
|
+
valExpr = prop.value;
|
|
392
|
+
}
|
|
393
|
+
else if (prop.type === 'Identifier') {
|
|
394
|
+
groupName = prop.value;
|
|
395
|
+
valExpr = prop;
|
|
396
|
+
}
|
|
397
|
+
if (groupName && valExpr) {
|
|
398
|
+
const groupVariants = variantObj[groupName];
|
|
399
|
+
if (!groupVariants)
|
|
400
|
+
continue;
|
|
401
|
+
const currentGroupId = ++groupIdCounter;
|
|
402
|
+
const valSource = getSource(valExpr);
|
|
403
|
+
if (valExpr.type === 'StringLiteral') {
|
|
404
|
+
const groupVariantsAsObj = groupVariants;
|
|
405
|
+
if (groupVariantsAsObj[valExpr.value])
|
|
406
|
+
baseStyle = deepMerge(baseStyle, groupVariantsAsObj[valExpr.value]);
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
Object.entries(groupVariants).forEach(([optionName, style]) => {
|
|
410
|
+
conditionals.push({
|
|
411
|
+
test: valExpr,
|
|
412
|
+
testLHS: valSource,
|
|
413
|
+
testString: `${valSource} === '${optionName}'`,
|
|
414
|
+
truthy: style,
|
|
415
|
+
falsy: {},
|
|
416
|
+
groupId: currentGroupId,
|
|
417
|
+
groupName,
|
|
418
|
+
valueName: optionName,
|
|
419
|
+
varName,
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
const argSource = getSource(innerArg);
|
|
427
|
+
if (t.isStringLiteral(innerArg)) {
|
|
428
|
+
if (variantObj[innerArg.value])
|
|
429
|
+
baseStyle = deepMerge(baseStyle, variantObj[innerArg.value]);
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
const currentGroupId = ++groupIdCounter;
|
|
433
|
+
Object.entries(variantObj).forEach(([key, style]) => {
|
|
434
|
+
conditionals.push({
|
|
435
|
+
test: innerArg,
|
|
436
|
+
testLHS: argSource,
|
|
437
|
+
testString: `${argSource} === '${key}'`,
|
|
438
|
+
truthy: style,
|
|
439
|
+
falsy: {},
|
|
440
|
+
groupId: currentGroupId,
|
|
441
|
+
groupName: undefined,
|
|
442
|
+
valueName: key,
|
|
443
|
+
varName,
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
isOptimizable = false;
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
else if (t.isIdentifier(expr)) {
|
|
453
|
+
const varName = expr.value;
|
|
454
|
+
const uniqueKey = `${resourcePath}-${varName}`;
|
|
455
|
+
let variantObj;
|
|
456
|
+
let hash = scannedTables.variantsHashTable[uniqueKey];
|
|
457
|
+
if (!hash)
|
|
458
|
+
hash = mergedVariantsTable[varName];
|
|
459
|
+
if (hash && scannedTables.variantsObjectTable[hash])
|
|
460
|
+
variantObj = scannedTables.variantsObjectTable[hash];
|
|
461
|
+
if (!variantObj && localCreateStyles[varName]?.obj)
|
|
462
|
+
variantObj = localCreateStyles[varName].obj;
|
|
463
|
+
if (variantObj) {
|
|
464
|
+
Object.entries(variantObj).forEach(([groupName, groupVariants]) => {
|
|
465
|
+
if (!groupVariants)
|
|
466
|
+
return;
|
|
467
|
+
const currentGroupId = ++groupIdCounter;
|
|
468
|
+
Object.entries(groupVariants).forEach(([optionName, style]) => {
|
|
469
|
+
conditionals.push({
|
|
470
|
+
test: expr,
|
|
471
|
+
testLHS: `props["${groupName}"]`,
|
|
472
|
+
testString: `props["${groupName}"] === '${optionName}'`,
|
|
473
|
+
truthy: style,
|
|
474
|
+
falsy: {},
|
|
475
|
+
groupId: currentGroupId,
|
|
476
|
+
groupName,
|
|
477
|
+
valueName: optionName,
|
|
478
|
+
varName,
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
const handled = collectConditions(expr);
|
|
486
|
+
if (handled)
|
|
487
|
+
continue;
|
|
488
|
+
isOptimizable = false;
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
if (!isOptimizable ||
|
|
492
|
+
(args.length === 0 && Object.keys(baseStyle).length === 0)) {
|
|
493
|
+
return {
|
|
494
|
+
classParts: [...dynamicClassParts],
|
|
495
|
+
isOptimizable,
|
|
496
|
+
baseStyle,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
const participation = {};
|
|
500
|
+
const registerParticipation = (style, sourceId) => {
|
|
501
|
+
Object.keys(style).forEach((key) => {
|
|
502
|
+
if (!participation[key])
|
|
503
|
+
participation[key] = new Set();
|
|
504
|
+
participation[key].add(sourceId);
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
registerParticipation(baseStyle, 'base');
|
|
508
|
+
conditionals
|
|
509
|
+
.filter((c) => c.groupId === undefined)
|
|
510
|
+
.forEach((c, idx) => {
|
|
511
|
+
registerParticipation(c.truthy, `std_${idx}`);
|
|
512
|
+
registerParticipation(c.falsy, `std_${idx}`);
|
|
513
|
+
});
|
|
514
|
+
const variantGroups = {};
|
|
515
|
+
conditionals.forEach((c) => {
|
|
516
|
+
if (c.groupId !== undefined) {
|
|
517
|
+
if (!variantGroups[c.groupId])
|
|
518
|
+
variantGroups[c.groupId] = [];
|
|
519
|
+
variantGroups[c.groupId].push(c);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
Object.entries(variantGroups).forEach(([groupId, opts]) => {
|
|
523
|
+
opts.forEach((opt) => registerParticipation(opt.truthy, `var_${groupId}`));
|
|
524
|
+
});
|
|
525
|
+
const conflictingKeys = new Set();
|
|
526
|
+
Object.entries(participation).forEach(([key, sources]) => {
|
|
527
|
+
if (sources.size > 1)
|
|
528
|
+
conflictingKeys.add(key);
|
|
529
|
+
});
|
|
530
|
+
const baseIndependent = {};
|
|
531
|
+
const baseConflict = {};
|
|
532
|
+
Object.entries(baseStyle).forEach(([key, val]) => {
|
|
533
|
+
if (conflictingKeys.has(key))
|
|
534
|
+
baseConflict[key] = val;
|
|
535
|
+
else
|
|
536
|
+
baseIndependent[key] = val;
|
|
537
|
+
});
|
|
538
|
+
const indepConditionals = [];
|
|
539
|
+
const conflictConditionals = [];
|
|
540
|
+
conditionals.forEach((c) => {
|
|
541
|
+
const truthyIndep = {};
|
|
542
|
+
const truthyConf = {};
|
|
543
|
+
const falsyIndep = {};
|
|
544
|
+
const falsyConf = {};
|
|
545
|
+
let hasIndep = false;
|
|
546
|
+
let hasConf = false;
|
|
547
|
+
Object.entries(c.truthy).forEach(([k, v]) => {
|
|
548
|
+
if (conflictingKeys.has(k)) {
|
|
549
|
+
truthyConf[k] = v;
|
|
550
|
+
hasConf = true;
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
truthyIndep[k] = v;
|
|
554
|
+
hasIndep = true;
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
Object.entries(c.falsy).forEach(([k, v]) => {
|
|
558
|
+
if (conflictingKeys.has(k)) {
|
|
559
|
+
falsyConf[k] = v;
|
|
560
|
+
hasConf = true;
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
falsyIndep[k] = v;
|
|
564
|
+
hasIndep = true;
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
if (hasIndep)
|
|
568
|
+
indepConditionals.push({
|
|
569
|
+
...c,
|
|
570
|
+
truthy: truthyIndep,
|
|
571
|
+
falsy: falsyIndep,
|
|
572
|
+
});
|
|
573
|
+
if (hasConf)
|
|
574
|
+
conflictConditionals.push({
|
|
575
|
+
...c,
|
|
576
|
+
truthy: truthyConf,
|
|
577
|
+
falsy: falsyConf,
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
const classParts = [];
|
|
581
|
+
if (existingClass)
|
|
582
|
+
classParts.push(JSON.stringify(existingClass));
|
|
583
|
+
if (Object.keys(baseIndependent).length > 0) {
|
|
584
|
+
const className = processStyleRecords(baseIndependent)
|
|
585
|
+
.map((r) => r.hash)
|
|
586
|
+
.join(' ');
|
|
587
|
+
if (className)
|
|
588
|
+
classParts.push(JSON.stringify(className));
|
|
589
|
+
}
|
|
590
|
+
indepConditionals
|
|
591
|
+
.filter((c) => c.groupId === undefined)
|
|
592
|
+
.forEach((c) => {
|
|
593
|
+
const processBranch = (style) => {
|
|
594
|
+
if (Object.keys(style).length === 0)
|
|
595
|
+
return '""';
|
|
596
|
+
return JSON.stringify(processStyleRecords(style)
|
|
597
|
+
.map((r) => r.hash)
|
|
598
|
+
.join(' '));
|
|
599
|
+
};
|
|
600
|
+
const testStr = c.testString ?? getSource(c.test);
|
|
601
|
+
classParts.push(`(${testStr} ? ${processBranch(c.truthy)} : ${processBranch(c.falsy)})`);
|
|
602
|
+
});
|
|
603
|
+
const indepVarGroups = {};
|
|
604
|
+
indepConditionals.forEach((c) => {
|
|
605
|
+
if (c.groupId !== undefined) {
|
|
606
|
+
if (!indepVarGroups[c.groupId])
|
|
607
|
+
indepVarGroups[c.groupId] = [];
|
|
608
|
+
indepVarGroups[c.groupId].push(c);
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
Object.values(indepVarGroups).forEach((opts) => {
|
|
612
|
+
const commonTestExpr = opts[0].testLHS ?? opts[0].testString ?? getSource(opts[0].test);
|
|
613
|
+
const lookupMap = {};
|
|
614
|
+
opts.forEach((opt) => {
|
|
615
|
+
if (opt.valueName && opt.truthy) {
|
|
616
|
+
const className = processStyleRecords(opt.truthy)
|
|
617
|
+
.map((r) => r.hash)
|
|
618
|
+
.join(' ');
|
|
619
|
+
if (className)
|
|
620
|
+
lookupMap[opt.valueName] = className;
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
if (Object.keys(lookupMap).length > 0) {
|
|
624
|
+
const entries = Object.entries(lookupMap)
|
|
625
|
+
.map(([k, v]) => `"${k}":"${v}"`)
|
|
626
|
+
.join(',');
|
|
627
|
+
classParts.push(`({${entries}}[${commonTestExpr}] || "")`);
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
if (Object.keys(baseConflict).length > 0 ||
|
|
631
|
+
conflictConditionals.length > 0) {
|
|
632
|
+
const dimensions = [];
|
|
633
|
+
conflictConditionals
|
|
634
|
+
.filter((c) => c.groupId === undefined)
|
|
635
|
+
.forEach((c) => {
|
|
636
|
+
dimensions.push({
|
|
637
|
+
type: 'std',
|
|
638
|
+
testExpr: c.testString ?? getSource(c.test),
|
|
639
|
+
options: [
|
|
640
|
+
{ value: 0, style: c.falsy, label: 'false' },
|
|
641
|
+
{ value: 1, style: c.truthy, label: 'true' },
|
|
642
|
+
],
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
const conflictVarGroups = {};
|
|
646
|
+
conflictConditionals.forEach((c) => {
|
|
647
|
+
if (c.groupId !== undefined) {
|
|
648
|
+
if (!conflictVarGroups[c.groupId])
|
|
649
|
+
conflictVarGroups[c.groupId] = [];
|
|
650
|
+
conflictVarGroups[c.groupId].push(c);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
Object.entries(conflictVarGroups).forEach(([, opts]) => {
|
|
654
|
+
dimensions.push({
|
|
655
|
+
type: 'var',
|
|
656
|
+
testExpr: opts[0].testLHS ??
|
|
657
|
+
opts[0].testString ??
|
|
658
|
+
getSource(opts[0].test),
|
|
659
|
+
options: opts.map((opt) => ({
|
|
660
|
+
value: opt.valueName,
|
|
661
|
+
style: opt.truthy,
|
|
662
|
+
label: opt.valueName || 'default',
|
|
663
|
+
})),
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
const results = {};
|
|
667
|
+
const recurse = (dimIndex, currentStyle, keyParts) => {
|
|
668
|
+
if (dimIndex >= dimensions.length) {
|
|
669
|
+
const className = processStyleRecords(currentStyle)
|
|
670
|
+
.map((r) => r.hash)
|
|
671
|
+
.join(' ');
|
|
672
|
+
if (className)
|
|
673
|
+
results[keyParts.join('__')] = className;
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
dimensions[dimIndex].options.forEach((opt) => recurse(dimIndex + 1, deepMerge(currentStyle, opt.style), [
|
|
677
|
+
...keyParts,
|
|
678
|
+
String(opt.value),
|
|
679
|
+
]));
|
|
680
|
+
};
|
|
681
|
+
recurse(0, baseConflict, []);
|
|
682
|
+
const baseConflictClass = Object.keys(baseConflict).length > 0
|
|
683
|
+
? processStyleRecords(baseConflict)
|
|
684
|
+
.map((r) => r.hash)
|
|
685
|
+
.join(' ')
|
|
686
|
+
: '';
|
|
687
|
+
const masterKeyExpr = dimensions
|
|
688
|
+
.map((dim) => dim.type === 'std'
|
|
689
|
+
? `(${dim.testExpr} ? "1" : "0")`
|
|
690
|
+
: dim.testExpr || '""')
|
|
691
|
+
.join(' + "__" + ');
|
|
692
|
+
classParts.push(`(${JSON.stringify(results)}[${masterKeyExpr || '""'}] || ${baseConflictClass ? JSON.stringify(baseConflictClass) : '""'})`);
|
|
693
|
+
}
|
|
694
|
+
classParts.push(...dynamicClassParts);
|
|
695
|
+
return { classParts, isOptimizable, baseStyle };
|
|
696
|
+
};
|
|
697
|
+
const registerStyle = (node, declSpan, isExported) => {
|
|
698
|
+
let propName;
|
|
699
|
+
const init = node.init;
|
|
700
|
+
if (t.isIdentifier(node.id) &&
|
|
701
|
+
init &&
|
|
702
|
+
t.isCallExpression(init) &&
|
|
703
|
+
init.arguments.length >= 1) {
|
|
704
|
+
const callee = init.callee;
|
|
705
|
+
if (t.isMemberExpression(callee) &&
|
|
706
|
+
t.isIdentifier(callee.object) &&
|
|
707
|
+
t.isIdentifier(callee.property)) {
|
|
708
|
+
const objectName = callee.object.value;
|
|
709
|
+
const propertyName = callee.property.value;
|
|
710
|
+
const alias = plumeriaAliases[objectName];
|
|
711
|
+
if (alias === 'NAMESPACE')
|
|
712
|
+
propName = propertyName;
|
|
713
|
+
}
|
|
714
|
+
else if (t.isIdentifier(callee)) {
|
|
715
|
+
const calleeName = callee.value;
|
|
716
|
+
const originalName = plumeriaAliases[calleeName];
|
|
717
|
+
if (originalName)
|
|
718
|
+
propName = originalName;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (propName && init && t.isCallExpression(init)) {
|
|
722
|
+
if (propName === 'create' &&
|
|
723
|
+
t.isObjectExpression(init.arguments[0].expression)) {
|
|
724
|
+
const obj = objectExpressionToObject(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
725
|
+
if (obj) {
|
|
726
|
+
const hashMap = {};
|
|
727
|
+
Object.entries(obj).forEach(([key, style]) => {
|
|
728
|
+
if (typeof style !== 'object' || style === null)
|
|
729
|
+
return;
|
|
730
|
+
const records = getStyleRecords(style);
|
|
731
|
+
const atomMap = {};
|
|
732
|
+
records.forEach((r) => (atomMap[r.key] = r.hash));
|
|
733
|
+
hashMap[key] = atomMap;
|
|
734
|
+
});
|
|
735
|
+
const styleFunctions = {};
|
|
736
|
+
const objExpr = init.arguments[0].expression;
|
|
737
|
+
objExpr.properties.forEach((prop) => {
|
|
738
|
+
if (prop.type !== 'KeyValueProperty' ||
|
|
739
|
+
prop.key.type !== 'Identifier')
|
|
740
|
+
return;
|
|
741
|
+
const func = prop.value;
|
|
742
|
+
if (func.type !== 'ArrowFunctionExpression' &&
|
|
743
|
+
func.type !== 'FunctionExpression')
|
|
744
|
+
return;
|
|
745
|
+
const params = func.params.map((p) => {
|
|
746
|
+
if (t.isIdentifier(p))
|
|
747
|
+
return p.value;
|
|
748
|
+
if (typeof p === 'object' &&
|
|
749
|
+
p !== null &&
|
|
750
|
+
'pat' in p &&
|
|
751
|
+
t.isIdentifier(p.pat))
|
|
752
|
+
return p.pat.value;
|
|
753
|
+
return 'arg';
|
|
754
|
+
});
|
|
755
|
+
let actualBody = func.body;
|
|
756
|
+
if (actualBody?.type === 'ParenthesisExpression')
|
|
757
|
+
actualBody = actualBody.expression;
|
|
758
|
+
if (actualBody?.type === 'BlockStatement') {
|
|
759
|
+
const first = actualBody.stmts?.[0];
|
|
760
|
+
if (first?.type === 'ReturnStatement')
|
|
761
|
+
actualBody = first.argument;
|
|
762
|
+
if (actualBody?.type === 'ParenthesisExpression')
|
|
763
|
+
actualBody = actualBody.expression;
|
|
764
|
+
}
|
|
765
|
+
if (actualBody && actualBody.type === 'ObjectExpression') {
|
|
766
|
+
styleFunctions[prop.key.value] = {
|
|
767
|
+
params,
|
|
768
|
+
body: actualBody,
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
if (t.isIdentifier(node.id)) {
|
|
773
|
+
idSpans.add(node.id.span.start);
|
|
774
|
+
localCreateStyles[node.id.value] = {
|
|
775
|
+
name: node.id.value,
|
|
776
|
+
type: 'create',
|
|
777
|
+
obj,
|
|
778
|
+
hashMap,
|
|
779
|
+
isExported,
|
|
780
|
+
initSpan: {
|
|
781
|
+
start: init.span.start - baseByteOffset,
|
|
782
|
+
end: init.span.end - baseByteOffset,
|
|
783
|
+
},
|
|
784
|
+
declSpan: {
|
|
785
|
+
start: declSpan.start - baseByteOffset,
|
|
786
|
+
end: declSpan.end - baseByteOffset,
|
|
787
|
+
},
|
|
788
|
+
functions: styleFunctions,
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
else if (propName === 'variants' &&
|
|
794
|
+
t.isObjectExpression(init.arguments[0].expression)) {
|
|
795
|
+
if (t.isIdentifier(node.id))
|
|
796
|
+
idSpans.add(node.id.span.start);
|
|
797
|
+
const obj = objectExpressionToObject(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable, (name) => {
|
|
798
|
+
if (localCreateStyles[name])
|
|
799
|
+
return localCreateStyles[name].obj;
|
|
800
|
+
if (mergedCreateTable[name]) {
|
|
801
|
+
const hash = mergedCreateTable[name];
|
|
802
|
+
if (scannedTables.createObjectTable[hash])
|
|
803
|
+
return scannedTables.createObjectTable[hash];
|
|
804
|
+
}
|
|
805
|
+
return undefined;
|
|
806
|
+
});
|
|
807
|
+
const { hashMap } = processVariants(obj);
|
|
808
|
+
if (t.isIdentifier(node.id)) {
|
|
809
|
+
localCreateStyles[node.id.value] = {
|
|
810
|
+
name: node.id.value,
|
|
811
|
+
type: 'variant',
|
|
812
|
+
obj,
|
|
813
|
+
hashMap,
|
|
814
|
+
isExported,
|
|
815
|
+
initSpan: {
|
|
816
|
+
start: init.span.start - baseByteOffset,
|
|
817
|
+
end: init.span.end - baseByteOffset,
|
|
818
|
+
},
|
|
819
|
+
declSpan: {
|
|
820
|
+
start: declSpan.start - baseByteOffset,
|
|
821
|
+
end: declSpan.end - baseByteOffset,
|
|
822
|
+
},
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
else if (propName === 'createTheme' &&
|
|
827
|
+
t.isObjectExpression(init.arguments[0].expression)) {
|
|
828
|
+
if (t.isIdentifier(node.id))
|
|
829
|
+
idSpans.add(node.id.span.start);
|
|
830
|
+
const obj = objectExpressionToObject(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
831
|
+
const hash = genBase36Hash(obj, 1, 8);
|
|
832
|
+
if (t.isIdentifier(node.id)) {
|
|
833
|
+
const uniqueKey = `${resourcePath}-${node.id.value}`;
|
|
834
|
+
scannedTables.createThemeHashTable[uniqueKey] = hash;
|
|
835
|
+
scannedTables.createThemeObjectTable[hash] = obj;
|
|
836
|
+
localCreateStyles[node.id.value] = {
|
|
837
|
+
name: node.id.value,
|
|
838
|
+
type: 'constant',
|
|
839
|
+
obj,
|
|
840
|
+
hashMap: scannedTables.createAtomicMapTable[hash],
|
|
841
|
+
isExported,
|
|
842
|
+
initSpan: {
|
|
843
|
+
start: init.span.start - baseByteOffset,
|
|
844
|
+
end: init.span.end - baseByteOffset,
|
|
845
|
+
},
|
|
846
|
+
declSpan: {
|
|
847
|
+
start: declSpan.start - baseByteOffset,
|
|
848
|
+
end: declSpan.end - baseByteOffset,
|
|
849
|
+
},
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
const jsxOpeningElementMap = new Map();
|
|
856
|
+
traverse(ast, {
|
|
857
|
+
ImportDeclaration({ node }) {
|
|
858
|
+
if (node.specifiers) {
|
|
859
|
+
node.specifiers.forEach((specifier) => {
|
|
860
|
+
if (specifier.local)
|
|
861
|
+
excludedSpans.add(specifier.local.span.start);
|
|
862
|
+
if (specifier.type === 'ImportSpecifier' && specifier.imported)
|
|
863
|
+
excludedSpans.add(specifier.imported.span.start);
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
},
|
|
867
|
+
ExportDeclaration({ node }) {
|
|
868
|
+
if (t.isVariableDeclaration(node.declaration)) {
|
|
869
|
+
processedDecls.add(node.declaration);
|
|
870
|
+
node.declaration.declarations.forEach((decl) => registerStyle(decl, node.span, true));
|
|
871
|
+
}
|
|
872
|
+
},
|
|
873
|
+
VariableDeclaration({ node }) {
|
|
874
|
+
if (processedDecls.has(node))
|
|
875
|
+
return;
|
|
876
|
+
node.declarations.forEach((decl) => registerStyle(decl, node.span, false));
|
|
877
|
+
},
|
|
878
|
+
JSXOpeningElement({ node }) {
|
|
879
|
+
jsxOpeningElementMap.set(node.span.start, node.attributes);
|
|
880
|
+
},
|
|
881
|
+
MemberExpression({ node }) {
|
|
882
|
+
if (t.isIdentifier(node.object) && t.isIdentifier(node.property)) {
|
|
883
|
+
const varName = node.object.value;
|
|
884
|
+
const propName = node.property.value;
|
|
885
|
+
const uniqueKey = `${resourcePath}-${varName}`;
|
|
886
|
+
let hash = scannedTables.createHashTable[uniqueKey];
|
|
887
|
+
if (!hash)
|
|
888
|
+
hash = mergedCreateTable[varName];
|
|
889
|
+
if (hash) {
|
|
890
|
+
let atomMap;
|
|
891
|
+
if (scannedTables.createAtomicMapTable[hash])
|
|
892
|
+
atomMap = scannedTables.createAtomicMapTable[hash][propName];
|
|
893
|
+
if (atomMap)
|
|
894
|
+
replacements.push({
|
|
895
|
+
start: node.span.start - baseByteOffset,
|
|
896
|
+
end: node.span.end - baseByteOffset,
|
|
897
|
+
content: `(${JSON.stringify(atomMap)})`,
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
let themeHash = scannedTables.createThemeHashTable[uniqueKey];
|
|
901
|
+
if (!themeHash)
|
|
902
|
+
themeHash = mergedCreateThemeHashTable[varName];
|
|
903
|
+
if (themeHash) {
|
|
904
|
+
const atomicMap = scannedTables.createAtomicMapTable[themeHash];
|
|
905
|
+
if (atomicMap && atomicMap[propName])
|
|
906
|
+
replacements.push({
|
|
907
|
+
start: node.span.start - baseByteOffset,
|
|
908
|
+
end: node.span.end - baseByteOffset,
|
|
909
|
+
content: `(${JSON.stringify(atomicMap[propName])})`,
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
let staticHash = scannedTables.createStaticHashTable[uniqueKey];
|
|
913
|
+
if (!staticHash)
|
|
914
|
+
staticHash = mergedCreateStaticHashTable[varName];
|
|
915
|
+
if (staticHash) {
|
|
916
|
+
const staticObj = scannedTables.createStaticObjectTable[staticHash];
|
|
917
|
+
if (staticObj && staticObj[propName] !== undefined)
|
|
918
|
+
replacements.push({
|
|
919
|
+
start: node.span.start - baseByteOffset,
|
|
920
|
+
end: node.span.end - baseByteOffset,
|
|
921
|
+
content: `(${JSON.stringify(staticObj[propName])})`,
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
},
|
|
926
|
+
Identifier({ node }) {
|
|
927
|
+
if (excludedSpans.has(node.span.start))
|
|
928
|
+
return;
|
|
929
|
+
if (idSpans.has(node.span.start))
|
|
930
|
+
return;
|
|
931
|
+
const styleInfo = localCreateStyles[node.value];
|
|
932
|
+
if (styleInfo) {
|
|
933
|
+
replacements.push({
|
|
934
|
+
start: node.span.start - baseByteOffset,
|
|
935
|
+
end: node.span.end - baseByteOffset,
|
|
936
|
+
content: `(${JSON.stringify(styleInfo.hashMap)})`,
|
|
937
|
+
});
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const varName = node.value;
|
|
941
|
+
const uniqueKey = `${resourcePath}-${varName}`;
|
|
942
|
+
let hash = scannedTables.createHashTable[uniqueKey];
|
|
943
|
+
if (!hash)
|
|
944
|
+
hash = mergedCreateTable[varName];
|
|
945
|
+
if (hash) {
|
|
946
|
+
const obj = scannedTables.createObjectTable[hash];
|
|
947
|
+
const atomicMap = scannedTables.createAtomicMapTable[hash];
|
|
948
|
+
if (obj && atomicMap) {
|
|
949
|
+
const hashMap = {};
|
|
950
|
+
Object.keys(obj).forEach((key) => {
|
|
951
|
+
if (atomicMap[key])
|
|
952
|
+
hashMap[key] = atomicMap[key];
|
|
953
|
+
});
|
|
954
|
+
replacements.push({
|
|
955
|
+
start: node.span.start - baseByteOffset,
|
|
956
|
+
end: node.span.end - baseByteOffset,
|
|
957
|
+
content: `(${JSON.stringify(hashMap)})`,
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
let themeHash = scannedTables.createThemeHashTable[uniqueKey];
|
|
962
|
+
if (!themeHash)
|
|
963
|
+
themeHash = mergedCreateThemeHashTable[varName];
|
|
964
|
+
if (themeHash) {
|
|
965
|
+
const atomicMap = scannedTables.createAtomicMapTable[themeHash];
|
|
966
|
+
if (atomicMap)
|
|
967
|
+
replacements.push({
|
|
968
|
+
start: node.span.start - baseByteOffset,
|
|
969
|
+
end: node.span.end - baseByteOffset,
|
|
970
|
+
content: `(${JSON.stringify(atomicMap)})`,
|
|
971
|
+
});
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
let staticHash = scannedTables.createStaticHashTable[uniqueKey];
|
|
975
|
+
if (!staticHash)
|
|
976
|
+
staticHash = mergedCreateStaticHashTable[varName];
|
|
977
|
+
if (staticHash) {
|
|
978
|
+
const staticObj = scannedTables.createStaticObjectTable[staticHash];
|
|
979
|
+
if (staticObj)
|
|
980
|
+
replacements.push({
|
|
981
|
+
start: node.span.start - baseByteOffset,
|
|
982
|
+
end: node.span.end - baseByteOffset,
|
|
983
|
+
content: `(${JSON.stringify(staticObj)})`,
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
},
|
|
987
|
+
JSXAttribute({ node }) {
|
|
988
|
+
if (node.name.type !== 'Identifier' ||
|
|
989
|
+
node.name.value !== 'styleName')
|
|
990
|
+
return;
|
|
991
|
+
if (!node.value || node.value.type !== 'JSXExpressionContainer')
|
|
992
|
+
return;
|
|
993
|
+
const expr = node.value.expression;
|
|
994
|
+
let args = expr.type === 'ArrayExpression'
|
|
995
|
+
? expr.elements
|
|
996
|
+
.filter((el) => el !== undefined)
|
|
997
|
+
.map((el) => ({ expression: el.expression }))
|
|
998
|
+
: [{ expression: expr }];
|
|
999
|
+
const dynamicClassParts = [];
|
|
1000
|
+
const dynamicStyleParts = [];
|
|
1001
|
+
let attributes = [];
|
|
1002
|
+
for (const [, attrs] of jsxOpeningElementMap) {
|
|
1003
|
+
const found = attrs
|
|
1004
|
+
.filter((a) => a.type === 'JSXAttribute')
|
|
1005
|
+
.find((a) => a.span.start === node.span.start);
|
|
1006
|
+
if (found) {
|
|
1007
|
+
attributes = attrs;
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
const classNameAttr = attributes.find((attr) => attr.type === 'JSXAttribute' &&
|
|
1012
|
+
attr.name.type === 'Identifier' &&
|
|
1013
|
+
attr.name.value === 'className');
|
|
1014
|
+
let existingClass = '';
|
|
1015
|
+
if (classNameAttr?.value?.type === 'StringLiteral') {
|
|
1016
|
+
existingClass = classNameAttr.value.value;
|
|
1017
|
+
replacements.push({
|
|
1018
|
+
start: classNameAttr.span.start - baseByteOffset,
|
|
1019
|
+
end: classNameAttr.span.end - baseByteOffset,
|
|
1020
|
+
content: '',
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
const styleAttrExisting = attributes.find((attr) => attr.type === 'JSXAttribute' &&
|
|
1024
|
+
attr.name.type === 'Identifier' &&
|
|
1025
|
+
attr.name.value === 'style');
|
|
1026
|
+
if (styleAttrExisting) {
|
|
1027
|
+
replacements.push({
|
|
1028
|
+
start: styleAttrExisting.span.start - baseByteOffset,
|
|
1029
|
+
end: styleAttrExisting.span.end - baseByteOffset,
|
|
1030
|
+
content: '',
|
|
1031
|
+
});
|
|
1032
|
+
if (styleAttrExisting.value?.type === 'JSXExpressionContainer') {
|
|
1033
|
+
const innerExpr = styleAttrExisting.value?.expression;
|
|
1034
|
+
if (innerExpr?.type === 'ObjectExpression') {
|
|
1035
|
+
const start = innerExpr.span.start - baseByteOffset;
|
|
1036
|
+
const end = innerExpr.span.end - baseByteOffset;
|
|
1037
|
+
const innerSource = sourceBuffer
|
|
1038
|
+
.subarray(start, end)
|
|
1039
|
+
.toString('utf-8');
|
|
1040
|
+
const stripped = innerSource.slice(1, -1).trim();
|
|
1041
|
+
if (stripped)
|
|
1042
|
+
dynamicStyleParts.push(stripped);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
args = args.filter((arg) => {
|
|
1047
|
+
const innerExpr = arg.expression;
|
|
1048
|
+
if (!t.isCallExpression(innerExpr) ||
|
|
1049
|
+
!t.isMemberExpression(innerExpr.callee))
|
|
1050
|
+
return true;
|
|
1051
|
+
const callee = innerExpr.callee;
|
|
1052
|
+
if (!t.isIdentifier(callee.object) ||
|
|
1053
|
+
!t.isIdentifier(callee.property))
|
|
1054
|
+
return true;
|
|
1055
|
+
const varName = callee.object.value;
|
|
1056
|
+
const propKey = callee.property.value;
|
|
1057
|
+
const styleInfo = localCreateStyles[varName];
|
|
1058
|
+
if (styleInfo?.functions?.[propKey]) {
|
|
1059
|
+
const func = styleInfo.functions[propKey];
|
|
1060
|
+
const callArgs = innerExpr.arguments;
|
|
1061
|
+
const tempStaticTable = { ...mergedStaticTable };
|
|
1062
|
+
if (callArgs.length === 1 && !callArgs[0].spread) {
|
|
1063
|
+
const argExpr = callArgs[0].expression;
|
|
1064
|
+
const cssVarInfo = {};
|
|
1065
|
+
if (argExpr.type === 'ObjectExpression') {
|
|
1066
|
+
const argObj = objectExpressionToObject(argExpr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
1067
|
+
func.params.forEach((p) => {
|
|
1068
|
+
if (argObj[p] !== undefined)
|
|
1069
|
+
tempStaticTable[p] = argObj[p];
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
func.params.forEach((p) => {
|
|
1074
|
+
const cssVar = `--${propKey}-${p}`;
|
|
1075
|
+
tempStaticTable[p] = `var(${cssVar})`;
|
|
1076
|
+
cssVarInfo[p] = { cssVar, propKey: '' };
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
const substituted = objectExpressionToObject(func.body, tempStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
|
|
1080
|
+
if (substituted) {
|
|
1081
|
+
const records = processStyleRecords(substituted);
|
|
1082
|
+
const hashes = records.map((r) => r.hash).join(' ');
|
|
1083
|
+
if (hashes)
|
|
1084
|
+
dynamicClassParts.push(JSON.stringify(hashes));
|
|
1085
|
+
if (Object.keys(cssVarInfo).length > 0) {
|
|
1086
|
+
Object.entries(cssVarInfo).forEach(([_, info]) => {
|
|
1087
|
+
const targetProp = Object.keys(substituted).find((k) => typeof substituted[k] === 'string' &&
|
|
1088
|
+
substituted[k].includes(info.cssVar));
|
|
1089
|
+
if (targetProp) {
|
|
1090
|
+
const argStart = argExpr.span.start - baseByteOffset;
|
|
1091
|
+
const argEnd = argExpr.span.end - baseByteOffset;
|
|
1092
|
+
const argSource = sourceBuffer
|
|
1093
|
+
.subarray(argStart, argEnd)
|
|
1094
|
+
.toString('utf-8');
|
|
1095
|
+
let valueExpr;
|
|
1096
|
+
const maybeNumber = Number(argSource);
|
|
1097
|
+
if (!isNaN(maybeNumber) &&
|
|
1098
|
+
argSource.trim() === String(maybeNumber)) {
|
|
1099
|
+
valueExpr = JSON.stringify(applyCssValue(maybeNumber, targetProp));
|
|
1100
|
+
}
|
|
1101
|
+
else if ((argSource.startsWith('"') &&
|
|
1102
|
+
argSource.endsWith('"')) ||
|
|
1103
|
+
(argSource.startsWith("'") && argSource.endsWith("'"))) {
|
|
1104
|
+
valueExpr = JSON.stringify(applyCssValue(argSource.slice(1, -1), targetProp));
|
|
1105
|
+
}
|
|
1106
|
+
else {
|
|
1107
|
+
valueExpr = exceptionCamelCase.includes(targetProp)
|
|
1108
|
+
? argSource
|
|
1109
|
+
: `(typeof ${argSource} === 'number' ? ${argSource} + 'px' : ${argSource})`;
|
|
1110
|
+
}
|
|
1111
|
+
dynamicStyleParts.push(`"${info.cssVar}": ${valueExpr}`);
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
return false;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
return true;
|
|
1120
|
+
});
|
|
1121
|
+
const styleAttr = dynamicStyleParts.length > 0
|
|
1122
|
+
? ` style={{${dynamicStyleParts.join(', ')}}}`
|
|
1123
|
+
: '';
|
|
1124
|
+
const { classParts, isOptimizable, baseStyle } = buildClassParts(args, dynamicClassParts, existingClass);
|
|
1125
|
+
if (isOptimizable &&
|
|
1126
|
+
(args.length > 0 ||
|
|
1127
|
+
Object.keys(baseStyle).length > 0 ||
|
|
1128
|
+
dynamicClassParts.length > 0)) {
|
|
1129
|
+
const replacement = classParts.length > 0 ? classParts.join(' + " " + ') : '""';
|
|
1130
|
+
replacements.push({
|
|
1131
|
+
start: node.span.start - baseByteOffset,
|
|
1132
|
+
end: node.span.end - baseByteOffset,
|
|
1133
|
+
content: `className={${replacement}}${styleAttr}`,
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
else {
|
|
1137
|
+
replacements.push({
|
|
1138
|
+
start: node.span.start - baseByteOffset,
|
|
1139
|
+
end: node.span.end - baseByteOffset,
|
|
1140
|
+
content: styleAttr || '',
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
},
|
|
1144
|
+
CallExpression({ node }) {
|
|
1145
|
+
const callee = node.callee;
|
|
1146
|
+
let isUseCall = false;
|
|
1147
|
+
if (t.isMemberExpression(callee) &&
|
|
1148
|
+
t.isIdentifier(callee.object) &&
|
|
1149
|
+
t.isIdentifier(callee.property)) {
|
|
1150
|
+
const objectName = callee.object.value;
|
|
1151
|
+
const propertyName = callee.property.value;
|
|
1152
|
+
const alias = plumeriaAliases[objectName];
|
|
1153
|
+
if (alias === 'NAMESPACE' && propertyName === 'use')
|
|
1154
|
+
isUseCall = true;
|
|
1155
|
+
}
|
|
1156
|
+
else if (t.isIdentifier(callee)) {
|
|
1157
|
+
const calleeName = callee.value;
|
|
1158
|
+
const originalName = plumeriaAliases[calleeName];
|
|
1159
|
+
if (originalName === 'use')
|
|
1160
|
+
isUseCall = true;
|
|
1161
|
+
}
|
|
1162
|
+
if (!isUseCall)
|
|
1163
|
+
return;
|
|
1164
|
+
const args = node.arguments;
|
|
1165
|
+
for (const arg of args) {
|
|
1166
|
+
const innerExpr = arg.expression;
|
|
1167
|
+
if (!t.isCallExpression(innerExpr) ||
|
|
1168
|
+
!t.isMemberExpression(innerExpr.callee))
|
|
1169
|
+
continue;
|
|
1170
|
+
const innerCallee = innerExpr.callee;
|
|
1171
|
+
if (!t.isIdentifier(innerCallee.object) ||
|
|
1172
|
+
!t.isIdentifier(innerCallee.property))
|
|
1173
|
+
continue;
|
|
1174
|
+
const varName = innerCallee.object.value;
|
|
1175
|
+
const propKey = innerCallee.property.value;
|
|
1176
|
+
const styleInfo = localCreateStyles[varName];
|
|
1177
|
+
if (styleInfo?.functions?.[propKey]) {
|
|
1178
|
+
throw new Error(`Plumeria: css.use(${getSource(innerExpr)}) does not support dynamic function keys.\n`);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
const { classParts, isOptimizable, baseStyle } = buildClassParts(args);
|
|
1182
|
+
if (isOptimizable &&
|
|
1183
|
+
(args.length > 0 || Object.keys(baseStyle).length > 0)) {
|
|
1184
|
+
const replacement = classParts.length > 0 ? classParts.join(' + " " + ') : '""';
|
|
1185
|
+
replacements.push({
|
|
1186
|
+
start: node.span.start - baseByteOffset,
|
|
1187
|
+
end: node.span.end - baseByteOffset,
|
|
1188
|
+
content: replacement,
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
},
|
|
1192
|
+
});
|
|
1193
|
+
Object.values(localCreateStyles).forEach((info) => {
|
|
1194
|
+
if (info.type === 'constant')
|
|
1195
|
+
return;
|
|
1196
|
+
if (info.isExported) {
|
|
1197
|
+
replacements.push({
|
|
1198
|
+
start: info.declSpan.start,
|
|
1199
|
+
end: info.declSpan.end,
|
|
1200
|
+
content: JSON.stringify(''),
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
else {
|
|
1204
|
+
replacements.push({
|
|
1205
|
+
start: info.declSpan.start,
|
|
1206
|
+
end: info.declSpan.end,
|
|
1207
|
+
content: '',
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1211
|
+
const optInCSS = await optimizer(extractedSheets.join(''));
|
|
1212
|
+
const buffer = Buffer.from(source);
|
|
1213
|
+
let offset = 0;
|
|
1214
|
+
const parts = [];
|
|
1215
|
+
replacements
|
|
1216
|
+
.sort((a, b) => a.start - b.start || b.end - a.end)
|
|
1217
|
+
.forEach((r) => {
|
|
1218
|
+
if (r.start < offset)
|
|
1219
|
+
return;
|
|
1220
|
+
parts.push(buffer.subarray(offset, r.start));
|
|
1221
|
+
parts.push(Buffer.from(r.content));
|
|
1222
|
+
offset = r.end;
|
|
1223
|
+
});
|
|
1224
|
+
parts.push(buffer.subarray(offset));
|
|
1225
|
+
const transformedSource = Buffer.concat(parts).toString();
|
|
1226
|
+
if (extractedSheets.length > 0) {
|
|
1227
|
+
const baseId = id.replace(EXTENSION_PATTERN, '');
|
|
1228
|
+
const cssFilename = `${baseId}.zero.css`;
|
|
1229
|
+
const cssId = `/${path.relative(viteRoot, cssFilename).replace(/\\/g, '/')}`;
|
|
1230
|
+
if (isDev) {
|
|
1231
|
+
if (!devCssSheets.has(cssFilename)) {
|
|
1232
|
+
devCssSheets.set(cssFilename, new Set());
|
|
1233
|
+
}
|
|
1234
|
+
const acc = devCssSheets.get(cssFilename);
|
|
1235
|
+
extractedSheets.forEach((sheet) => acc.add(sheet));
|
|
1236
|
+
const accCSS = await optimizer(Array.from(acc).join(''));
|
|
1237
|
+
cssLookup.set(cssFilename, accCSS);
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
cssLookup.set(cssFilename, optInCSS);
|
|
1241
|
+
}
|
|
1242
|
+
cssFileLookup.set(cssId, cssFilename);
|
|
1243
|
+
const targetIndex = targets.findIndex((t) => t.id === id);
|
|
1244
|
+
if (targetIndex !== -1) {
|
|
1245
|
+
targets[targetIndex].dependencies = dependencies;
|
|
1246
|
+
}
|
|
1247
|
+
else {
|
|
1248
|
+
targets.push({ id, dependencies });
|
|
1249
|
+
}
|
|
1250
|
+
return {
|
|
1251
|
+
code: transformedSource + `\nimport ${JSON.stringify(cssId)};`,
|
|
1252
|
+
map: null,
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
return {
|
|
1256
|
+
code: transformedSource,
|
|
1257
|
+
map: null,
|
|
1258
|
+
};
|
|
1259
|
+
},
|
|
1260
|
+
};
|
|
1261
|
+
};
|