@plumeria/vite-plugin 5.0.1 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +415 -223
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import { createFilter } from 'vite';
2
2
  import { parseSync } from '@swc/core';
3
3
  import path from 'path';
4
- import fs from 'fs';
5
4
  import { genBase36Hash } from 'zss-engine';
6
- import { tables, traverse, getStyleRecords, collectLocalConsts, objectExpressionToObject, t, extractOndemandStyles, deepMerge, scanAll, resolveImportPath, } from '@plumeria/utils';
5
+ import { traverse, getStyleRecords, collectLocalConsts, objectExpressionToObject, t, extractOndemandStyles, deepMerge, scanAll, resolveImportPath, } from '@plumeria/utils';
7
6
  const TARGET_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx'];
8
7
  const EXTENSION_PATTERN = /\.(ts|tsx|js|jsx)$/;
9
8
  export function plumeria(options = {}) {
@@ -64,13 +63,12 @@ export function plumeria(options = {}) {
64
63
  return null;
65
64
  if (!filter(id))
66
65
  return null;
67
- const isTSFile = id.endsWith('.ts') && !id.endsWith('.tsx');
68
66
  const dependencies = [];
69
67
  const addDependency = (depPath) => {
70
68
  dependencies.push(depPath);
71
69
  this.addWatchFile(depPath);
72
70
  };
73
- scanAll(addDependency);
71
+ const scannedTables = scanAll();
74
72
  const ast = parseSync(source, {
75
73
  syntax: 'typescript',
76
74
  tsx: true,
@@ -83,59 +81,106 @@ export function plumeria(options = {}) {
83
81
  ImportDeclaration({ node }) {
84
82
  const sourcePath = node.source.value;
85
83
  const actualPath = resolveImportPath(sourcePath, resourcePath);
86
- if (actualPath && fs.existsSync(actualPath)) {
87
- if (fs.existsSync(actualPath)) {
88
- node.specifiers.forEach((specifier) => {
89
- if (specifier.type === 'ImportSpecifier') {
90
- const importedName = specifier.imported
91
- ? specifier.imported.value
92
- : specifier.local.value;
93
- const localName = specifier.local.value;
94
- const uniqueKey = `${actualPath}-${importedName}`;
95
- if (tables.staticTable[uniqueKey]) {
96
- importMap[localName] = tables.staticTable[uniqueKey];
97
- }
98
- if (tables.keyframesHashTable[uniqueKey]) {
99
- importMap[localName] = tables.keyframesHashTable[uniqueKey];
100
- }
101
- if (tables.viewTransitionHashTable[uniqueKey]) {
102
- importMap[localName] =
103
- tables.viewTransitionHashTable[uniqueKey];
104
- }
105
- if (tables.themeTable[uniqueKey]) {
106
- importMap[localName] = tables.themeTable[uniqueKey];
107
- }
84
+ if (actualPath) {
85
+ addDependency(actualPath);
86
+ node.specifiers.forEach((specifier) => {
87
+ if (specifier.type === 'ImportSpecifier') {
88
+ const importedName = specifier.imported
89
+ ? specifier.imported.value
90
+ : specifier.local.value;
91
+ const localName = specifier.local.value;
92
+ const uniqueKey = `${actualPath}-${importedName}`;
93
+ if (scannedTables.staticTable[uniqueKey]) {
94
+ importMap[localName] = scannedTables.staticTable[uniqueKey];
108
95
  }
109
- });
110
- }
96
+ if (scannedTables.keyframesHashTable[uniqueKey]) {
97
+ importMap[localName] =
98
+ scannedTables.keyframesHashTable[uniqueKey];
99
+ }
100
+ if (scannedTables.viewTransitionHashTable[uniqueKey]) {
101
+ importMap[localName] =
102
+ scannedTables.viewTransitionHashTable[uniqueKey];
103
+ }
104
+ if (scannedTables.themeTable[uniqueKey]) {
105
+ importMap[localName] = scannedTables.themeTable[uniqueKey];
106
+ }
107
+ if (scannedTables.createHashTable[uniqueKey]) {
108
+ importMap[localName] =
109
+ scannedTables.createHashTable[uniqueKey];
110
+ }
111
+ if (scannedTables.variantsHashTable[uniqueKey]) {
112
+ importMap[localName] =
113
+ scannedTables.variantsHashTable[uniqueKey];
114
+ }
115
+ }
116
+ });
111
117
  }
112
118
  },
113
119
  });
114
- const mergedStaticTable = { ...tables.staticTable };
120
+ const mergedStaticTable = {};
121
+ for (const key of Object.keys(scannedTables.staticTable)) {
122
+ mergedStaticTable[key] = scannedTables.staticTable[key];
123
+ }
115
124
  for (const key of Object.keys(localConsts)) {
116
125
  mergedStaticTable[key] = localConsts[key];
117
126
  }
118
127
  for (const key of Object.keys(importMap)) {
119
128
  mergedStaticTable[key] = importMap[key];
120
129
  }
121
- const mergedKeyframesTable = { ...tables.keyframesHashTable };
130
+ const mergedKeyframesTable = {};
131
+ for (const key of Object.keys(scannedTables.keyframesHashTable)) {
132
+ mergedKeyframesTable[key] = scannedTables.keyframesHashTable[key];
133
+ }
122
134
  for (const key of Object.keys(importMap)) {
123
135
  mergedKeyframesTable[key] = importMap[key];
124
136
  }
125
- const mergedViewTransitionTable = { ...tables.viewTransitionHashTable };
137
+ const mergedViewTransitionTable = {};
138
+ for (const key of Object.keys(scannedTables.viewTransitionHashTable)) {
139
+ mergedViewTransitionTable[key] =
140
+ scannedTables.viewTransitionHashTable[key];
141
+ }
126
142
  for (const key of Object.keys(importMap)) {
127
143
  mergedViewTransitionTable[key] = importMap[key];
128
144
  }
129
- const mergedThemeTable = { ...tables.themeTable };
145
+ const mergedThemeTable = {};
146
+ for (const key of Object.keys(scannedTables.themeTable)) {
147
+ mergedThemeTable[key] = scannedTables.themeTable[key];
148
+ }
130
149
  for (const key of Object.keys(importMap)) {
131
150
  mergedThemeTable[key] = importMap[key];
132
151
  }
152
+ const mergedCreateTable = {};
153
+ for (const key of Object.keys(scannedTables.createHashTable)) {
154
+ mergedCreateTable[key] = scannedTables.createHashTable[key];
155
+ }
156
+ for (const key of Object.keys(importMap)) {
157
+ mergedCreateTable[key] = importMap[key];
158
+ }
159
+ const mergedVariantsTable = {};
160
+ for (const key of Object.keys(scannedTables.variantsHashTable)) {
161
+ mergedVariantsTable[key] = scannedTables.variantsHashTable[key];
162
+ }
163
+ for (const key of Object.keys(importMap)) {
164
+ mergedVariantsTable[key] = importMap[key];
165
+ }
133
166
  const localCreateStyles = {};
134
167
  const replacements = [];
135
168
  const extractedSheets = [];
136
169
  const processedDecls = new Set();
137
- const excludedSpans = new Set();
138
170
  const idSpans = new Set();
171
+ const excludedSpans = new Set();
172
+ const checkVariantAssignment = (decl) => {
173
+ if (decl.init &&
174
+ t.isCallExpression(decl.init) &&
175
+ t.isIdentifier(decl.init.callee)) {
176
+ const varName = decl.init.callee.value;
177
+ if ((localCreateStyles[varName] &&
178
+ localCreateStyles[varName].type === 'variant') ||
179
+ mergedVariantsTable[varName]) {
180
+ throw new Error(`Plumeria: Assigning the return value of "css.variants" to a variable is not supported.\nPlease pass the variant function directly to "css.props". Found assignment to: ${t.isIdentifier(decl.id) ? decl.id.value : 'unknown'}`);
181
+ }
182
+ }
183
+ };
139
184
  const registerStyle = (node, declSpan, isExported) => {
140
185
  if (t.isIdentifier(node.id) &&
141
186
  node.init &&
@@ -147,12 +192,12 @@ export function plumeria(options = {}) {
147
192
  const propName = node.init.callee.property.value;
148
193
  if (propName === 'create' &&
149
194
  t.isObjectExpression(node.init.arguments[0].expression)) {
150
- const obj = objectExpressionToObject(node.init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable);
195
+ const obj = objectExpressionToObject(node.init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable, mergedCreateTable, mergedVariantsTable);
151
196
  if (obj) {
152
197
  const hashMap = {};
153
198
  Object.entries(obj).forEach(([key, style]) => {
154
199
  const records = getStyleRecords(key, style, 2);
155
- extractOndemandStyles(style, extractedSheets);
200
+ extractOndemandStyles(style, extractedSheets, scannedTables);
156
201
  records.forEach((r) => {
157
202
  extractedSheets.push(r.sheet);
158
203
  });
@@ -168,7 +213,6 @@ export function plumeria(options = {}) {
168
213
  type: 'create',
169
214
  obj,
170
215
  hashMap,
171
- hasDynamicAccess: false,
172
216
  isExported,
173
217
  initSpan: {
174
218
  start: node.init.span.start - ast.span.start,
@@ -189,7 +233,36 @@ export function plumeria(options = {}) {
189
233
  type: 'constant',
190
234
  obj: {},
191
235
  hashMap: {},
192
- hasDynamicAccess: false,
236
+ isExported,
237
+ initSpan: {
238
+ start: node.init.span.start - ast.span.start,
239
+ end: node.init.span.end - ast.span.start,
240
+ },
241
+ declSpan: {
242
+ start: declSpan.start - ast.span.start,
243
+ end: declSpan.end - ast.span.start,
244
+ },
245
+ };
246
+ }
247
+ else if (propName === 'variants' &&
248
+ t.isObjectExpression(node.init.arguments[0].expression)) {
249
+ const obj = objectExpressionToObject(node.init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable, mergedCreateTable, mergedVariantsTable, (name) => {
250
+ if (localCreateStyles[name]) {
251
+ return localCreateStyles[name].obj;
252
+ }
253
+ if (mergedCreateTable[name]) {
254
+ const hash = mergedCreateTable[name];
255
+ if (scannedTables.createObjectTable[hash]) {
256
+ return scannedTables.createObjectTable[hash];
257
+ }
258
+ }
259
+ return undefined;
260
+ });
261
+ localCreateStyles[node.id.value] = {
262
+ name: node.id.value,
263
+ type: 'variant',
264
+ obj,
265
+ hashMap: {},
193
266
  isExported,
194
267
  initSpan: {
195
268
  start: node.init.span.start - ast.span.start,
@@ -204,10 +277,23 @@ export function plumeria(options = {}) {
204
277
  }
205
278
  };
206
279
  traverse(ast, {
280
+ ImportDeclaration({ node }) {
281
+ if (node.specifiers) {
282
+ node.specifiers.forEach((specifier) => {
283
+ if (specifier.local) {
284
+ excludedSpans.add(specifier.local.span.start);
285
+ }
286
+ if (specifier.imported) {
287
+ excludedSpans.add(specifier.imported.span.start);
288
+ }
289
+ });
290
+ }
291
+ },
207
292
  ExportDeclaration({ node }) {
208
293
  if (t.isVariableDeclaration(node.declaration)) {
209
294
  processedDecls.add(node.declaration);
210
295
  node.declaration.declarations.forEach((decl) => {
296
+ checkVariantAssignment(decl);
211
297
  registerStyle(decl, node.span, true);
212
298
  });
213
299
  }
@@ -216,25 +302,10 @@ export function plumeria(options = {}) {
216
302
  if (processedDecls.has(node))
217
303
  return;
218
304
  node.declarations.forEach((decl) => {
305
+ checkVariantAssignment(decl);
219
306
  registerStyle(decl, node.span, false);
220
307
  });
221
308
  },
222
- MemberExpression({ node }) {
223
- if (t.isIdentifier(node.object)) {
224
- const styleInfo = localCreateStyles[node.object.value];
225
- if (styleInfo) {
226
- if (t.isIdentifier(node.property)) {
227
- const hash = styleInfo.hashMap[node.property.value];
228
- if (!hash && styleInfo.type !== 'constant') {
229
- styleInfo.hasDynamicAccess = true;
230
- }
231
- }
232
- else {
233
- styleInfo.hasDynamicAccess = true;
234
- }
235
- }
236
- }
237
- },
238
309
  CallExpression({ node }) {
239
310
  const callee = node.callee;
240
311
  if (t.isMemberExpression(callee) &&
@@ -245,9 +316,9 @@ export function plumeria(options = {}) {
245
316
  if (propName === 'keyframes' &&
246
317
  args.length > 0 &&
247
318
  t.isObjectExpression(args[0].expression)) {
248
- const obj = objectExpressionToObject(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable);
319
+ const obj = objectExpressionToObject(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable, mergedCreateTable, mergedVariantsTable);
249
320
  const hash = genBase36Hash(obj, 1, 8);
250
- tables.keyframesObjectTable[hash] = obj;
321
+ scannedTables.keyframesObjectTable[hash] = obj;
251
322
  replacements.push({
252
323
  start: node.span.start - ast.span.start,
253
324
  end: node.span.end - ast.span.start,
@@ -257,11 +328,11 @@ export function plumeria(options = {}) {
257
328
  else if (propName === 'viewTransition' &&
258
329
  args.length > 0 &&
259
330
  t.isObjectExpression(args[0].expression)) {
260
- const obj = objectExpressionToObject(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable);
331
+ const obj = objectExpressionToObject(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable, mergedCreateTable, mergedVariantsTable);
261
332
  const hash = genBase36Hash(obj, 1, 8);
262
- tables.viewTransitionObjectTable[hash] = obj;
263
- extractOndemandStyles(obj, extractedSheets);
264
- extractOndemandStyles({ vt: `vt-${hash}` }, extractedSheets);
333
+ scannedTables.viewTransitionObjectTable[hash] = obj;
334
+ extractOndemandStyles(obj, extractedSheets, scannedTables);
335
+ extractOndemandStyles({ vt: `vt-${hash}` }, extractedSheets, scannedTables);
265
336
  replacements.push({
266
337
  start: node.span.start - ast.span.start,
267
338
  end: node.span.end - ast.span.start,
@@ -271,43 +342,65 @@ export function plumeria(options = {}) {
271
342
  else if (propName === 'createTheme' &&
272
343
  args.length > 0 &&
273
344
  t.isObjectExpression(args[0].expression)) {
274
- const obj = objectExpressionToObject(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable);
345
+ const obj = objectExpressionToObject(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable, mergedCreateTable, mergedVariantsTable);
346
+ const hash = genBase36Hash(obj, 1, 8);
347
+ scannedTables.createThemeObjectTable[hash] = obj;
348
+ }
349
+ else if (propName === 'create' &&
350
+ args.length > 0 &&
351
+ t.isObjectExpression(args[0].expression)) {
352
+ const obj = objectExpressionToObject(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable, mergedCreateTable, mergedVariantsTable);
275
353
  const hash = genBase36Hash(obj, 1, 8);
276
- tables.createThemeObjectTable[hash] = obj;
354
+ scannedTables.createObjectTable[hash] = obj;
355
+ Object.entries(obj).forEach(([key, style]) => {
356
+ if (typeof style === 'object' && style !== null) {
357
+ const records = getStyleRecords(key, style, 2);
358
+ extractOndemandStyles(style, extractedSheets, scannedTables);
359
+ records.forEach((r) => extractedSheets.push(r.sheet));
360
+ }
361
+ });
277
362
  }
278
363
  }
279
364
  },
280
365
  });
281
366
  traverse(ast, {
282
367
  MemberExpression({ node }) {
283
- if (excludedSpans.has(node.span.start))
284
- return;
285
368
  if (t.isIdentifier(node.object) && t.isIdentifier(node.property)) {
286
- const styleInfo = localCreateStyles[node.object.value];
287
- if (styleInfo && !styleInfo.hasDynamicAccess) {
288
- const atomMap = styleInfo.hashMap[node.property.value];
369
+ const varName = node.object.value;
370
+ const propName = node.property.value;
371
+ const styleInfo = localCreateStyles[varName];
372
+ if (styleInfo) {
373
+ const atomMap = styleInfo.hashMap[propName];
289
374
  if (atomMap) {
290
375
  replacements.push({
291
376
  start: node.span.start - ast.span.start,
292
377
  end: node.span.end - ast.span.start,
293
378
  content: JSON.stringify(atomMap),
294
379
  });
380
+ return;
381
+ }
382
+ }
383
+ const hash = mergedCreateTable[varName];
384
+ if (hash) {
385
+ const obj = scannedTables.createObjectTable[hash];
386
+ if (obj && obj[propName]) {
387
+ const style = obj[propName];
388
+ if (typeof style === 'object' && style !== null) {
389
+ const records = getStyleRecords(propName, style, 2);
390
+ extractOndemandStyles(style, extractedSheets, scannedTables);
391
+ records.forEach((r) => extractedSheets.push(r.sheet));
392
+ const atomMap = {};
393
+ records.forEach((r) => (atomMap[r.key] = r.hash));
394
+ if (Object.keys(atomMap).length > 0) {
395
+ replacements.push({
396
+ start: node.span.start - ast.span.start,
397
+ end: node.span.end - ast.span.start,
398
+ content: JSON.stringify(atomMap),
399
+ });
400
+ }
401
+ }
295
402
  }
296
403
  }
297
- }
298
- },
299
- Identifier({ node }) {
300
- if (excludedSpans.has(node.span.start))
301
- return;
302
- if (idSpans.has(node.span.start))
303
- return;
304
- const styleInfo = localCreateStyles[node.value];
305
- if (styleInfo && !styleInfo.hasDynamicAccess) {
306
- replacements.push({
307
- start: node.span.start - ast.span.start,
308
- end: node.span.end - ast.span.start,
309
- content: JSON.stringify(styleInfo.hashMap),
310
- });
311
404
  }
312
405
  },
313
406
  CallExpression({ node }) {
@@ -316,182 +409,281 @@ export function plumeria(options = {}) {
316
409
  t.isIdentifier(callee.object, { name: 'css' }) &&
317
410
  t.isIdentifier(callee.property, { name: 'props' })) {
318
411
  const args = node.arguments;
319
- const checkStatic = (expr) => {
320
- if (t.isObjectExpression(expr) ||
321
- t.isStringLiteral(expr) ||
322
- t.isNumericLiteral(expr) ||
323
- t.isBooleanLiteral(expr) ||
324
- t.isNullLiteral(expr))
325
- return true;
326
- if (t.isMemberExpression(expr) &&
412
+ const resolveStyleObject = (expr) => {
413
+ if (t.isObjectExpression(expr)) {
414
+ return objectExpressionToObject(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable, mergedCreateTable, mergedVariantsTable);
415
+ }
416
+ else if (t.isMemberExpression(expr) &&
327
417
  t.isIdentifier(expr.object) &&
328
- t.isIdentifier(expr.property)) {
329
- const styleInfo = localCreateStyles[expr.object.value];
330
- return !!(styleInfo &&
331
- !styleInfo.hasDynamicAccess &&
332
- styleInfo.hashMap[expr.property.value]);
418
+ (t.isIdentifier(expr.property) ||
419
+ expr.property.type === 'Computed')) {
420
+ if (expr.property.type === 'Computed') {
421
+ return {};
422
+ }
423
+ const varName = expr.object.value;
424
+ const propName = expr.property.value;
425
+ const styleInfo = localCreateStyles[varName];
426
+ if (styleInfo && styleInfo.obj[propName]) {
427
+ const style = styleInfo.obj[propName];
428
+ if (typeof style === 'object' && style !== null) {
429
+ return style;
430
+ }
431
+ }
432
+ const hash = mergedCreateTable[varName];
433
+ if (hash) {
434
+ const obj = scannedTables.createObjectTable[hash];
435
+ if (obj && obj[propName]) {
436
+ const style = obj[propName];
437
+ if (typeof style === 'object' && style !== null) {
438
+ return style;
439
+ }
440
+ }
441
+ }
333
442
  }
334
- if (t.isIdentifier(expr)) {
335
- const styleInfo = localCreateStyles[expr.value];
336
- return !!(styleInfo && !styleInfo.hasDynamicAccess);
443
+ else if (t.isIdentifier(expr)) {
444
+ const varName = expr.value;
445
+ const styleInfo = localCreateStyles[varName];
446
+ if (styleInfo && styleInfo.obj) {
447
+ return styleInfo.obj;
448
+ }
449
+ const hash = mergedCreateTable[varName];
450
+ if (hash) {
451
+ const obj = scannedTables.createObjectTable[hash];
452
+ if (obj && typeof obj === 'object') {
453
+ return obj;
454
+ }
455
+ }
456
+ if (localCreateStyles[varName]) {
457
+ return localCreateStyles[varName].obj;
458
+ }
459
+ const vHash = mergedVariantsTable[varName];
460
+ if (vHash) {
461
+ return scannedTables.variantsObjectTable[vHash];
462
+ }
337
463
  }
338
- return false;
464
+ return null;
339
465
  };
340
- const hasDynamicAccess = (expr) => {
341
- if (t.isMemberExpression(expr) && t.isIdentifier(expr.object)) {
342
- const info = localCreateStyles[expr.object.value];
343
- if (info && info.hasDynamicAccess)
344
- return true;
345
- }
346
- if (t.isIdentifier(expr)) {
347
- const info = localCreateStyles[expr.value];
348
- if (info && info.hasDynamicAccess)
349
- return true;
350
- }
351
- if (t.isConditionalExpression(expr)) {
352
- return (hasDynamicAccess(expr.consequent) ||
353
- hasDynamicAccess(expr.alternate));
466
+ const conditionals = [];
467
+ let groupIdCounter = 0;
468
+ let baseStyle = {};
469
+ let isOptimizable = true;
470
+ for (const arg of args) {
471
+ const expr = arg.expression;
472
+ if (t.isCallExpression(expr) && t.isIdentifier(expr.callee)) {
473
+ const varName = expr.callee.value;
474
+ let variantObj;
475
+ if (localCreateStyles[varName] &&
476
+ localCreateStyles[varName].obj) {
477
+ variantObj = localCreateStyles[varName].obj;
478
+ }
479
+ else if (mergedVariantsTable[varName]) {
480
+ const hash = mergedVariantsTable[varName];
481
+ if (scannedTables.variantsObjectTable[hash]) {
482
+ variantObj = scannedTables.variantsObjectTable[hash];
483
+ }
484
+ }
485
+ if (variantObj) {
486
+ const callArgs = expr.arguments;
487
+ if (callArgs.length === 1 && !callArgs[0].spread) {
488
+ const arg = callArgs[0].expression;
489
+ if (arg.type === 'ObjectExpression') {
490
+ for (const prop of arg.properties) {
491
+ let groupName;
492
+ let valExpr;
493
+ if (prop.type === 'KeyValueProperty' &&
494
+ prop.key.type === 'Identifier') {
495
+ groupName = prop.key.value;
496
+ valExpr = prop.value;
497
+ }
498
+ else if (prop.type === 'Identifier') {
499
+ groupName = prop.value;
500
+ valExpr = prop;
501
+ }
502
+ if (groupName && valExpr) {
503
+ const groupVariants = variantObj[groupName];
504
+ if (!groupVariants)
505
+ continue;
506
+ const currentGroupId = ++groupIdCounter;
507
+ const valStart = valExpr.span.start - ast.span.start;
508
+ const valEnd = valExpr.span.end - ast.span.start;
509
+ const valSource = source.substring(valStart, valEnd);
510
+ if (valExpr.type === 'StringLiteral') {
511
+ if (groupVariants[valExpr.value]) {
512
+ baseStyle = deepMerge(baseStyle, groupVariants[valExpr.value]);
513
+ }
514
+ continue;
515
+ }
516
+ Object.entries(groupVariants).forEach(([optionName, style]) => {
517
+ conditionals.push({
518
+ test: valExpr,
519
+ testString: `${valSource} === '${optionName}'`,
520
+ truthy: style,
521
+ falsy: {},
522
+ groupId: currentGroupId,
523
+ });
524
+ });
525
+ }
526
+ }
527
+ continue;
528
+ }
529
+ const argStart = arg.span.start - ast.span.start;
530
+ const argEnd = arg.span.end - ast.span.start;
531
+ const argSource = source.substring(argStart, argEnd);
532
+ if (t.isStringLiteral(arg)) {
533
+ if (variantObj[arg.value]) {
534
+ baseStyle = deepMerge(baseStyle, variantObj[arg.value]);
535
+ }
536
+ continue;
537
+ }
538
+ const currentGroupId = ++groupIdCounter;
539
+ Object.entries(variantObj).forEach(([key, style]) => {
540
+ conditionals.push({
541
+ test: arg,
542
+ testString: `${argSource} === '${key}'`,
543
+ truthy: style,
544
+ falsy: {},
545
+ groupId: currentGroupId,
546
+ });
547
+ });
548
+ continue;
549
+ }
550
+ isOptimizable = false;
551
+ break;
552
+ }
354
553
  }
355
- if (t.isBinaryExpression(expr) &&
356
- (expr.operator === '&&' ||
357
- expr.operator === '||' ||
358
- expr.operator === '??')) {
359
- return (hasDynamicAccess(expr.left) || hasDynamicAccess(expr.right));
554
+ const staticStyle = resolveStyleObject(expr);
555
+ if (staticStyle) {
556
+ baseStyle = deepMerge(baseStyle, staticStyle);
557
+ continue;
360
558
  }
361
- return false;
362
- };
363
- const allStatic = args.every((arg) => checkStatic(arg.expression));
364
- const anyDynamic = args.some((arg) => hasDynamicAccess(arg.expression));
365
- if (allStatic && args.length > 0) {
366
- const merged = args.reduce((acc, arg) => {
367
- const expr = arg.expression;
368
- if (t.isObjectExpression(expr)) {
369
- const obj = objectExpressionToObject(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedThemeTable);
370
- return obj ? deepMerge(acc, obj) : acc;
559
+ else if (expr.type === 'ConditionalExpression') {
560
+ const truthyStyle = resolveStyleObject(expr.consequent);
561
+ const falsyStyle = resolveStyleObject(expr.alternate);
562
+ if (truthyStyle !== null && falsyStyle !== null) {
563
+ conditionals.push({
564
+ test: expr.test,
565
+ truthy: truthyStyle,
566
+ falsy: falsyStyle,
567
+ });
568
+ continue;
371
569
  }
372
- else if (t.isMemberExpression(expr) &&
373
- t.isIdentifier(expr.object) &&
374
- t.isIdentifier(expr.property)) {
375
- const styleInfo = localCreateStyles[expr.object.value];
376
- return styleInfo
377
- ? deepMerge(acc, styleInfo.obj[expr.property.value])
378
- : acc;
570
+ }
571
+ else if (expr.type === 'BinaryExpression' &&
572
+ expr.operator === '&&') {
573
+ const truthyStyle = resolveStyleObject(expr.right);
574
+ if (truthyStyle !== null) {
575
+ conditionals.push({
576
+ test: expr.left,
577
+ truthy: truthyStyle,
578
+ falsy: {},
579
+ });
580
+ continue;
379
581
  }
380
- else if (t.isIdentifier(expr)) {
381
- const styleInfo = localCreateStyles[expr.value];
382
- return styleInfo ? deepMerge(acc, styleInfo.obj) : acc;
582
+ }
583
+ else if (expr.type === 'ParenthesisExpression') {
584
+ const inner = expr.expression;
585
+ const innerStatic = resolveStyleObject(inner);
586
+ if (innerStatic) {
587
+ baseStyle = deepMerge(baseStyle, innerStatic);
588
+ continue;
383
589
  }
384
- return acc;
385
- }, {});
386
- if (Object.keys(merged).length > 0) {
387
- extractOndemandStyles(merged, extractedSheets);
388
- const hash = genBase36Hash(merged, 1, 8);
389
- const records = getStyleRecords(hash, merged, 2);
590
+ }
591
+ isOptimizable = false;
592
+ break;
593
+ }
594
+ if (isOptimizable &&
595
+ (args.length > 0 || Object.keys(baseStyle).length > 0)) {
596
+ if (conditionals.length === 0) {
597
+ extractOndemandStyles(baseStyle, extractedSheets, scannedTables);
598
+ const hash = genBase36Hash(baseStyle, 1, 8);
599
+ const records = getStyleRecords(hash, baseStyle, 2);
390
600
  records.forEach((r) => extractedSheets.push(r.sheet));
391
- const resultHash = records
601
+ const className = records
392
602
  .map((r) => r.hash)
393
603
  .join(' ');
394
604
  replacements.push({
395
605
  start: node.span.start - ast.span.start,
396
606
  end: node.span.end - ast.span.start,
397
- content: JSON.stringify(resultHash),
607
+ content: JSON.stringify(className),
398
608
  });
399
609
  }
400
- }
401
- else if (anyDynamic) {
402
- const processExpr = (expr) => {
403
- if (t.isIdentifier(expr)) {
404
- const info = localCreateStyles[expr.value];
405
- if (info && info.hasDynamicAccess) {
406
- excludedSpans.add(expr.span.start);
407
- }
408
- }
409
- else if (t.isConditionalExpression(expr)) {
410
- processExpr(expr.consequent);
411
- processExpr(expr.alternate);
412
- }
413
- else if (t.isBinaryExpression(expr) &&
414
- (expr.operator === '&&' ||
415
- expr.operator === '||' ||
416
- expr.operator === '??')) {
417
- processExpr(expr.left);
418
- processExpr(expr.right);
419
- }
420
- };
421
- args.forEach((arg) => processExpr(arg.expression));
422
- }
423
- else {
424
- const processExpr = (expr) => {
425
- if (t.isMemberExpression(expr) &&
426
- t.isIdentifier(expr.object) &&
427
- t.isIdentifier(expr.property)) {
428
- const info = localCreateStyles[expr.object.value];
429
- if (info) {
430
- const atomMap = info.hashMap[expr.property.value];
431
- if (atomMap) {
432
- excludedSpans.add(expr.span.start);
433
- replacements.push({
434
- start: expr.span.start - ast.span.start,
435
- end: expr.span.end - ast.span.start,
436
- content: JSON.stringify(atomMap),
437
- });
610
+ else {
611
+ const table = {};
612
+ const combinations = 1 << conditionals.length;
613
+ for (let i = 0; i < combinations; i++) {
614
+ let currentStyle = { ...baseStyle };
615
+ const seenGroups = new Set();
616
+ let impossible = false;
617
+ for (let j = 0; j < conditionals.length; j++) {
618
+ if ((i >> j) & 1) {
619
+ if (conditionals[j].groupId !== undefined) {
620
+ if (seenGroups.has(conditionals[j].groupId)) {
621
+ impossible = true;
622
+ break;
623
+ }
624
+ seenGroups.add(conditionals[j].groupId);
625
+ }
626
+ currentStyle = deepMerge(currentStyle, conditionals[j].truthy);
627
+ }
628
+ else {
629
+ currentStyle = deepMerge(currentStyle, conditionals[j].falsy);
438
630
  }
439
631
  }
440
- }
441
- else if (t.isIdentifier(expr)) {
442
- const info = localCreateStyles[expr.value];
443
- if (info) {
444
- excludedSpans.add(expr.span.start);
445
- replacements.push({
446
- start: expr.span.start - ast.span.start,
447
- end: expr.span.end - ast.span.start,
448
- content: JSON.stringify(info.hashMap),
449
- });
632
+ if (impossible) {
633
+ table[i] = '';
634
+ continue;
450
635
  }
636
+ extractOndemandStyles(currentStyle, extractedSheets, scannedTables);
637
+ const hash = genBase36Hash(currentStyle, 1, 8);
638
+ const records = getStyleRecords(hash, currentStyle, 2);
639
+ records.forEach((r) => extractedSheets.push(r.sheet));
640
+ const className = records
641
+ .map((r) => r.hash)
642
+ .join(' ');
643
+ table[i] = className;
451
644
  }
452
- else if (t.isConditionalExpression(expr)) {
453
- processExpr(expr.consequent);
454
- processExpr(expr.alternate);
645
+ let indexExpr = '';
646
+ if (conditionals.length === 0) {
647
+ indexExpr = '0';
455
648
  }
456
- else if (t.isBinaryExpression(expr) &&
457
- (expr.operator === '&&' ||
458
- expr.operator === '||' ||
459
- expr.operator === '??')) {
460
- processExpr(expr.left);
461
- processExpr(expr.right);
649
+ else {
650
+ const parts = conditionals.map((c, idx) => {
651
+ if (c.testString) {
652
+ return `(!!(${c.testString}) << ${idx})`;
653
+ }
654
+ const start = c.test.span.start - ast.span.start;
655
+ const end = c.test.span.end - ast.span.start;
656
+ const testStr = source.substring(start, end);
657
+ return `(!!(${testStr}) << ${idx})`;
658
+ });
659
+ indexExpr = parts.join(' | ');
462
660
  }
463
- };
464
- args.forEach((arg) => processExpr(arg.expression));
661
+ const tableStr = JSON.stringify(table);
662
+ const replacement = `${tableStr}[${indexExpr}]`;
663
+ replacements.push({
664
+ start: node.span.start - ast.span.start,
665
+ end: node.span.end - ast.span.start,
666
+ content: replacement,
667
+ });
668
+ }
465
669
  }
466
670
  }
467
671
  },
468
672
  });
469
673
  Object.values(localCreateStyles).forEach((info) => {
470
674
  if (info.isExported) {
471
- const content = isTSFile || info.hasDynamicAccess
472
- ? JSON.stringify(info.hashMap)
473
- : JSON.stringify('');
474
675
  replacements.push({
475
- start: info.initSpan.start,
476
- end: info.initSpan.end,
477
- content,
676
+ start: info.declSpan.start,
677
+ end: info.declSpan.end,
678
+ content: JSON.stringify(''),
478
679
  });
479
680
  }
480
681
  else {
481
- if (info.hasDynamicAccess) {
482
- replacements.push({
483
- start: info.initSpan.start,
484
- end: info.initSpan.end,
485
- content: JSON.stringify(info.hashMap),
486
- });
487
- }
488
- else {
489
- replacements.push({
490
- start: info.declSpan.start,
491
- end: info.declSpan.end,
492
- content: '',
493
- });
494
- }
682
+ replacements.push({
683
+ start: info.declSpan.start,
684
+ end: info.declSpan.end,
685
+ content: '',
686
+ });
495
687
  }
496
688
  });
497
689
  const buffer = Buffer.from(source);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/vite-plugin",
3
- "version": "5.0.1",
3
+ "version": "6.0.1",
4
4
  "type": "module",
5
5
  "description": "Plumeria Vite plugin",
6
6
  "author": "Refirst 11",
@@ -22,7 +22,7 @@
22
22
  "dist/"
23
23
  ],
24
24
  "dependencies": {
25
- "@plumeria/utils": "^5.0.1"
25
+ "@plumeria/utils": "^6.0.1"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@swc/core": "1.15.8",