@plumeria/turbopack-loader 19.0.0 → 19.1.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 +10 -2379
  2. package/package.json +3 -4
package/dist/index.js CHANGED
@@ -34,10 +34,8 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.default = loader;
37
- const core_1 = require("@swc/core");
38
37
  const fs = __importStar(require("fs"));
39
38
  const path = __importStar(require("path"));
40
- const zss_engine_1 = require("zss-engine");
41
39
  const utils_1 = require("@plumeria/utils");
42
40
  const compiler_1 = require("@plumeria/compiler");
43
41
  const split_css_rules_1 = require("./split-css-rules");
@@ -84,104 +82,6 @@ const ensureProductionCss = (virtualFilePath, options) => {
84
82
  }
85
83
  return productionCss;
86
84
  };
87
- const unwrapExport = (node) => {
88
- if (node?.type === 'ExportDeclaration')
89
- return node.declaration;
90
- if (node?.type === 'ExportDefaultDeclaration')
91
- return node.decl;
92
- if (node?.type === 'ExportDefaultExpression')
93
- return node.expression;
94
- return node;
95
- };
96
- const isFunctionNode = (node) => node?.type === 'FunctionDeclaration' ||
97
- node?.type === 'FunctionExpression' ||
98
- node?.type === 'ArrowFunctionExpression';
99
- const componentFunctionOf = (node) => {
100
- if (isFunctionNode(node))
101
- return node;
102
- if (node?.type === 'CallExpression') {
103
- for (const arg of node.arguments ?? []) {
104
- const fn = componentFunctionOf(arg.expression);
105
- if (fn)
106
- return fn;
107
- }
108
- }
109
- return undefined;
110
- };
111
- const unwrapPatternDefault = (pattern) => pattern?.type === 'AssignmentPattern' ? pattern.left : pattern;
112
- const destructuredPropAliases = (fn) => {
113
- const aliases = new Map();
114
- const first = fn.params[0];
115
- const pattern = unwrapPatternDefault(first?.pat ?? first);
116
- if (pattern?.type !== 'ObjectPattern')
117
- return aliases;
118
- for (const item of pattern.properties ?? []) {
119
- if (item.type !== 'KeyValuePatternProperty')
120
- continue;
121
- const local = unwrapPatternDefault(item.value);
122
- const key = item.key;
123
- if (!utils_1.t.isIdentifier(local))
124
- continue;
125
- if (!utils_1.t.isIdentifier(key) && !utils_1.t.isStringLiteral(key))
126
- continue;
127
- const name = String(key.value);
128
- if (name !== local.value)
129
- aliases.set(local.value, name);
130
- }
131
- return aliases;
132
- };
133
- const propDefaultMessage = (source) => `Plumeria: A style prop default must be a defined style: "${source}". ` +
134
- `Apply a conditional or dynamic style where the element is styled.`;
135
- const spreadStyleMessage = (source) => `Plumeria: Spread elements in a style array are not supported: "...${source}". ` +
136
- `List each style explicitly.`;
137
- const resolveLocalStyleAlias = (aliases, expression) => {
138
- let current = expression;
139
- const seen = new Set();
140
- while (utils_1.t.isIdentifier(current)) {
141
- const name = current.value;
142
- if (seen.has(name))
143
- break;
144
- seen.add(name);
145
- const candidates = aliases[name];
146
- if (!candidates || candidates.length === 0)
147
- break;
148
- const candidate = candidates.find((candidate) => candidate.context === current.ctxt);
149
- if (!candidate)
150
- break;
151
- current = candidate.expression;
152
- }
153
- return current;
154
- };
155
- const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
156
- node.type === 'NumericLiteral' ||
157
- node.type === 'BooleanLiteral' ||
158
- (node.type === 'TemplateLiteral' && node.expressions.length === 0) ||
159
- utils_1.t.isIdentifier(node) ||
160
- utils_1.t.isMemberExpression(node);
161
- const isNoOpStyle = (node) => utils_1.t.isNullLiteral(node) ||
162
- (utils_1.t.isBooleanLiteral(node) && node.value === false) ||
163
- (utils_1.t.isIdentifier(node) && node.value === 'undefined');
164
- const foldDynamicVars = (vars) => {
165
- const grouped = new Map();
166
- [...vars]
167
- .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
168
- .forEach((entry) => {
169
- const list = grouped.get(entry.cssVar);
170
- if (list)
171
- list.push(entry);
172
- else
173
- grouped.set(entry.cssVar, [entry]);
174
- });
175
- return [...grouped].map(([cssVar, entries]) => {
176
- let value = 'undefined';
177
- entries.forEach((entry) => {
178
- value = entry.test
179
- ? `((${entry.test}) ? ${entry.valueExpr} : ${value})`
180
- : entry.valueExpr;
181
- });
182
- return `"${cssVar}": ${value}`;
183
- });
184
- };
185
85
  async function loader(source) {
186
86
  const callback = this.async();
187
87
  const loaderOptions = this.getOptions?.() ??
@@ -199,2286 +99,17 @@ async function loader(source) {
199
99
  try {
200
100
  this.clearDependencies();
201
101
  this.addDependency(resourcePath);
202
- const ast = (0, core_1.parseSync)(source, {
203
- syntax: 'typescript',
204
- tsx: true,
205
- target: 'es2022',
206
- });
207
- (0, utils_1.assertPropertyPolicy)(ast, propertyPolicy, resourcePath);
208
- const leadingLen = (0, utils_1.getLeadingCommentLength)(source);
209
- const sourceBuffer = Buffer.from(source, 'utf-8');
210
- const leadingBytes = Buffer.byteLength(source.slice(0, leadingLen), 'utf-8');
211
- const baseByteOffset = ast.span.start - leadingBytes;
212
- const throwCompilationError = (message, node) => {
213
- let suffix = '';
214
- if (node) {
215
- const offset = node.span.start - baseByteOffset;
216
- let line = 1;
217
- let colStart = 0;
218
- for (let i = 0; i < offset && i < sourceBuffer.length; i++) {
219
- if (sourceBuffer[i] === 10) {
220
- line++;
221
- colStart = i + 1;
222
- }
223
- }
224
- const col = offset - colStart + 1;
225
- suffix = ` (${path.basename(resourcePath)}:${line}:${col})`;
226
- }
227
- const err = new Error(`${message}${suffix}`);
228
- err.stack = err.message;
229
- throw err;
230
- };
231
- const assertResolvable = (node) => {
232
- if (utils_1.t.isIdentifier(node) && node.value === 'undefined')
233
- return;
234
- if (utils_1.t.isMemberExpression(node) ||
235
- utils_1.t.isIdentifier(node) ||
236
- utils_1.t.isCallExpression(node) ||
237
- utils_1.t.isArrowFunctionExpression(node) ||
238
- utils_1.t.isFunctionExpression(node)) {
239
- const rootId = (0, utils_1.getRootIdentifier)(node);
240
- const isPlumeriaStyle = rootId &&
241
- isVisibleReference(node) &&
242
- ((localCreateStyles[rootId] !== undefined &&
243
- localCreateStyles[rootId].type !== 'constant') ||
244
- mergedCreateTable[rootId] !== undefined);
245
- if (!isPlumeriaStyle) {
246
- const origin = rootId ? localImports[rootId] : undefined;
247
- const failure = origin
248
- ? (0, utils_1.resolveFileError)(origin.actualPath, origin.importedName)
249
- : undefined;
250
- if (failure) {
251
- throwCompilationError(`Plumeria: ${failure.message} (${path.basename(failure.filePath)})`);
252
- }
253
- throwCompilationError(`Plumeria: Dynamic or unresolvable style object "${getSource(node)}" is not supported.`, node);
254
- }
255
- }
256
- };
257
- const scannedTables = (0, utils_1.scanAll)();
258
- const ownFailure = (0, utils_1.resolveFileError)(resourcePath, '');
259
- if (ownFailure)
260
- throwCompilationError(`Plumeria: ${ownFailure.message}`);
261
- for (const node of ast.body) {
262
- if (node.type === 'ImportDeclaration') {
263
- const sourcePath = node.source.value;
264
- const actualPath = (0, utils_1.resolveImportPath)(sourcePath, resourcePath);
265
- if (actualPath) {
266
- this.addDependency(actualPath);
267
- const transDeps = (0, utils_1.getFileDependencies)(actualPath);
268
- for (const dep of transDeps) {
269
- this.addDependency(dep);
270
- }
271
- }
272
- }
273
- }
274
- if (scannedTables.componentPropsTable) {
275
- const parentFiles = new Set();
276
- for (const compKey of Object.keys(scannedTables.componentPropsTable)) {
277
- if (!compKey.startsWith(`${resourcePath}-`))
278
- continue;
279
- const props = scannedTables.componentPropsTable[compKey];
280
- for (const propName of Object.keys(props)) {
281
- for (const entry of props[propName]) {
282
- if (entry.filePath !== resourcePath) {
283
- parentFiles.add(entry.filePath);
284
- }
285
- }
286
- }
287
- }
288
- for (const parentFile of parentFiles) {
289
- this.addDependency(parentFile);
290
- }
291
- }
292
- const components = [];
293
- const propAliases = new Map();
294
- const propDefaults = new Map();
295
- const declaredProps = new Map();
296
- const addComponent = (name, fn) => {
297
- components.push({ name, node: fn });
298
- const first = fn.params[0];
299
- const pattern = unwrapPatternDefault(first?.pat ?? first);
300
- const defaults = new Map();
301
- for (const item of pattern?.properties ?? []) {
302
- if (item.type === 'AssignmentPatternProperty' && item.value)
303
- defaults.set(item.key.value, item.value);
304
- if (item.type === 'KeyValuePatternProperty' &&
305
- item.value?.type === 'AssignmentPattern')
306
- defaults.set(item.key.value, item.value.right);
307
- }
308
- propDefaults.set(name, defaults);
309
- const aliases = destructuredPropAliases(fn);
310
- if (aliases.size > 0)
311
- propAliases.set(name, aliases);
312
- const declared = new Set();
313
- for (const item of pattern?.properties ?? []) {
314
- const key = item.key;
315
- if (utils_1.t.isIdentifier(key) || utils_1.t.isStringLiteral(key))
316
- declared.add(String(key.value));
317
- }
318
- if (declared.size > 0)
319
- declaredProps.set(name, declared);
320
- };
321
- for (const node of ast.body) {
322
- const statement = unwrapExport(node);
323
- if (isFunctionNode(statement)) {
324
- addComponent(statement.identifier?.value ?? 'default', statement);
325
- }
326
- else if (statement?.type === 'CallExpression') {
327
- const fn = componentFunctionOf(statement);
328
- if (fn)
329
- addComponent('default', fn);
330
- }
331
- else if (utils_1.t.isVariableDeclaration(statement)) {
332
- for (const decl of statement.declarations) {
333
- if (!utils_1.t.isIdentifier(decl.id))
334
- continue;
335
- const fn = componentFunctionOf(decl.init);
336
- if (fn)
337
- addComponent(decl.id.value, fn);
338
- }
339
- }
340
- }
341
- const appliedStyleProps = new Set();
342
- const ownerComponentOf = (at) => components.find((c) => at.span.start >= c.node.span.start &&
343
- at.span.start <= c.node.span.end)?.name;
344
- const markStylePropApplied = (name, at) => {
345
- const owner = ownerComponentOf(at);
346
- if (owner) {
347
- appliedStyleProps.add(`${owner}:${name}`);
348
- }
349
- };
350
- const extractedSheets = [];
351
- const addSheet = (sheet) => {
352
- if (!extractedSheets.includes(sheet)) {
353
- extractedSheets.push(sheet);
354
- }
355
- };
356
- const processStyleRecords = (style, weights) => {
357
- const records = (0, utils_1.getStyleRecords)(style, weights);
358
- if (!isProduction) {
359
- (0, utils_1.extractOndemandStyles)(style, extractedSheets, scannedTables);
360
- records.forEach((r) => {
361
- addSheet(r.sheet);
362
- });
363
- }
364
- return records;
365
- };
366
- const localConsts = (0, utils_1.collectLocalConsts)(ast);
367
- const importMap = {};
368
- const keyframesImportMap = {};
369
- const viewTransitionImportMap = {};
370
- const createImportMap = {};
371
- const createFunctionImportMap = {};
372
- const createThemeImportMap = {};
373
- const createStaticImportMap = {};
374
- const plumeriaAliases = {};
375
- const localImports = {};
376
- (0, utils_1.traverse)(ast, {
377
- ImportDeclaration({ node }) {
378
- const sourcePath = node.source.value;
379
- if (sourcePath === '@plumeria/core') {
380
- node.specifiers.forEach((specifier) => {
381
- if (specifier.type === 'ImportNamespaceSpecifier') {
382
- plumeriaAliases[specifier.local.value] = 'NAMESPACE';
383
- }
384
- else if (specifier.type === 'ImportDefaultSpecifier') {
385
- plumeriaAliases[specifier.local.value] = 'NAMESPACE';
386
- }
387
- else if (specifier.type === 'ImportSpecifier') {
388
- const importedName = specifier.imported
389
- ? specifier.imported.value
390
- : specifier.local.value;
391
- plumeriaAliases[specifier.local.value] = importedName;
392
- }
393
- });
394
- }
395
- const actualPath = (0, utils_1.resolveImportPath)(sourcePath, resourcePath);
396
- if (actualPath) {
397
- node.specifiers.forEach((specifier) => {
398
- if (specifier.type === 'ImportNamespaceSpecifier') {
399
- localImports[specifier.local.value] = {
400
- actualPath,
401
- importedName: '*',
402
- };
403
- return;
404
- }
405
- if (specifier.type === 'ImportSpecifier' ||
406
- specifier.type === 'ImportDefaultSpecifier') {
407
- const importedName = specifier.type === 'ImportDefaultSpecifier'
408
- ? 'default'
409
- : specifier.imported
410
- ? specifier.imported.value
411
- : specifier.local.value;
412
- const localName = specifier.local.value;
413
- let resolvedKey = `${actualPath}-${importedName}`;
414
- const resolved = (0, utils_1.resolveExport)(actualPath, importedName);
415
- if (resolved) {
416
- resolvedKey = `${resolved.filePath}-${resolved.localName}`;
417
- }
418
- const uniqueKey = resolvedKey;
419
- localImports[localName] = { actualPath, importedName };
420
- if (scannedTables.staticTable[uniqueKey]) {
421
- importMap[localName] = scannedTables.staticTable[uniqueKey];
422
- }
423
- if (scannedTables.keyframesHashTable[uniqueKey]) {
424
- keyframesImportMap[localName] =
425
- scannedTables.keyframesHashTable[uniqueKey];
426
- }
427
- if (scannedTables.viewTransitionHashTable[uniqueKey]) {
428
- viewTransitionImportMap[localName] =
429
- scannedTables.viewTransitionHashTable[uniqueKey];
430
- }
431
- if (scannedTables.createHashTable[uniqueKey]) {
432
- createImportMap[localName] =
433
- scannedTables.createHashTable[uniqueKey];
434
- }
435
- if (scannedTables.createFunctionTable[uniqueKey]) {
436
- createFunctionImportMap[localName] = (0, utils_1.styleFunctionsOf)(scannedTables.createFunctionTable[uniqueKey]);
437
- }
438
- if (scannedTables.createThemeHashTable[uniqueKey]) {
439
- createThemeImportMap[localName] =
440
- scannedTables.createThemeHashTable[uniqueKey];
441
- }
442
- if (scannedTables.createStaticHashTable[uniqueKey]) {
443
- createStaticImportMap[localName] =
444
- scannedTables.createStaticHashTable[uniqueKey];
445
- }
446
- }
447
- });
448
- }
449
- },
450
- });
451
- const mergedStaticTable = {};
452
- for (const key of Object.keys(scannedTables.staticTable)) {
453
- mergedStaticTable[key] = scannedTables.staticTable[key];
454
- }
455
- for (const key of Object.keys(localConsts)) {
456
- mergedStaticTable[key] = localConsts[key];
457
- }
458
- for (const key of Object.keys(importMap)) {
459
- mergedStaticTable[key] = importMap[key];
460
- }
461
- const mergedKeyframesTable = {};
462
- for (const key of Object.keys(scannedTables.keyframesHashTable)) {
463
- mergedKeyframesTable[key] = scannedTables.keyframesHashTable[key];
464
- if (key.startsWith(`${resourcePath}-`)) {
465
- const varName = key.slice(resourcePath.length + 1);
466
- mergedKeyframesTable[varName] = scannedTables.keyframesHashTable[key];
467
- }
468
- }
469
- for (const key of Object.keys(keyframesImportMap)) {
470
- mergedKeyframesTable[key] = keyframesImportMap[key];
471
- }
472
- const mergedViewTransitionTable = {};
473
- for (const key of Object.keys(scannedTables.viewTransitionHashTable)) {
474
- mergedViewTransitionTable[key] =
475
- scannedTables.viewTransitionHashTable[key];
476
- if (key.startsWith(`${resourcePath}-`)) {
477
- const varName = key.slice(resourcePath.length + 1);
478
- mergedViewTransitionTable[varName] =
479
- scannedTables.viewTransitionHashTable[key];
480
- }
481
- }
482
- for (const key of Object.keys(viewTransitionImportMap)) {
483
- mergedViewTransitionTable[key] = viewTransitionImportMap[key];
484
- }
485
- const mergedCreateTable = {};
486
- for (const key of Object.keys(scannedTables.createHashTable)) {
487
- mergedCreateTable[key] = scannedTables.createHashTable[key];
488
- if (key.startsWith(`${resourcePath}-`)) {
489
- const varName = key.slice(resourcePath.length + 1);
490
- mergedCreateTable[varName] = scannedTables.createHashTable[key];
491
- }
492
- }
493
- for (const key of Object.keys(createImportMap)) {
494
- mergedCreateTable[key] = createImportMap[key];
495
- }
496
- const mergedCreateThemeHashTable = {};
497
- for (const key of Object.keys(scannedTables.createThemeHashTable)) {
498
- mergedCreateThemeHashTable[key] = scannedTables.createThemeHashTable[key];
499
- if (key.startsWith(`${resourcePath}-`)) {
500
- const varName = key.slice(resourcePath.length + 1);
501
- mergedCreateThemeHashTable[varName] =
502
- scannedTables.createThemeHashTable[key];
503
- }
504
- }
505
- for (const key of Object.keys(createThemeImportMap)) {
506
- mergedCreateThemeHashTable[key] = createThemeImportMap[key];
507
- }
508
- const mergedCreateStaticHashTable = {};
509
- for (const key of Object.keys(scannedTables.createStaticHashTable)) {
510
- mergedCreateStaticHashTable[key] =
511
- scannedTables.createStaticHashTable[key];
512
- if (key.startsWith(`${resourcePath}-`)) {
513
- const varName = key.slice(resourcePath.length + 1);
514
- mergedCreateStaticHashTable[varName] =
515
- scannedTables.createStaticHashTable[key];
516
- }
517
- }
518
- for (const key of Object.keys(createStaticImportMap)) {
519
- mergedCreateStaticHashTable[key] = createStaticImportMap[key];
520
- }
521
- const dynamicStyleTables = {
522
- keyframesHashTable: mergedKeyframesTable,
523
- viewTransitionHashTable: mergedViewTransitionTable,
524
- createThemeHashTable: mergedCreateThemeHashTable,
525
- createThemeObjectTable: scannedTables.createThemeObjectTable,
526
- createHashTable: mergedCreateTable,
527
- createStaticHashTable: mergedCreateStaticHashTable,
528
- createStaticObjectTable: scannedTables.createStaticObjectTable,
529
- };
530
- const localCreateStyles = {};
531
- const localStyleAliases = {};
532
- const checkStyleAliasAssignment = (decl) => {
533
- if (!utils_1.t.isIdentifier(decl.id) || !decl.init)
534
- return;
535
- const init = (0, utils_1.unwrapExpression)(decl.init);
536
- if (utils_1.t.isMemberExpression(init) && utils_1.t.isIdentifier(init.object)) {
537
- const objName = init.object.value;
538
- if (localCreateStyles[objName] !== undefined ||
539
- mergedCreateTable[objName] !== undefined) {
540
- (localStyleAliases[decl.id.value] ??= []).push({
541
- expression: init,
542
- context: decl.id.ctxt,
543
- });
544
- }
545
- }
546
- };
547
- const replacements = [];
548
- const deferredSources = [];
549
- const deferRange = (start, end) => {
550
- const token = `__plumeria_preserved_${deferredSources.length}__`;
551
- deferredSources.push({ token, start, end });
552
- return token;
553
- };
554
- const deferSource = (node) => deferRange(node.span.start - baseByteOffset, node.span.end - baseByteOffset);
555
- const deferProperty = (property) => {
556
- const node = property;
557
- const range = node.spread && node.arguments
558
- ? { start: node.spread.start, end: node.arguments.span.end }
559
- : node.span
560
- ? { start: node.span.start, end: node.span.end }
561
- : node.key && node.value
562
- ? { start: node.key.span.start, end: node.value.span.end }
563
- : null;
564
- return range
565
- ? deferRange(range.start - baseByteOffset, range.end - baseByteOffset)
566
- : null;
567
- };
568
- const dynamicFnCalls = [];
569
- const processedDecls = new Set();
570
- const separatelyExported = new Set();
571
- for (const statement of ast.body) {
572
- if (statement.type !== 'ExportNamedDeclaration' || statement.source)
573
- continue;
574
- for (const specifier of statement.specifiers) {
575
- if (specifier.type === 'ExportSpecifier' &&
576
- utils_1.t.isIdentifier(specifier.orig)) {
577
- separatelyExported.add(specifier.orig.value);
578
- }
579
- }
580
- }
581
- const idSpans = new Set();
582
- const excludedSpans = new Set();
583
- const referenceIdents = (0, utils_1.collectReferenceIdentifiers)(ast);
584
- const topLevelDeclarators = new Set();
585
- for (const statement of ast.body) {
586
- const declaration = unwrapExport(statement);
587
- if (utils_1.t.isVariableDeclaration(declaration)) {
588
- declaration.declarations.forEach((decl) => topLevelDeclarators.add(decl));
589
- }
590
- }
591
- const unwrapStyleExpression = (node) => {
592
- while (node &&
593
- [
594
- 'ParenthesisExpression',
595
- 'TsAsExpression',
596
- 'TsSatisfiesExpression',
597
- 'TsNonNullExpression',
598
- 'TsConstAssertion',
599
- 'TsTypeAssertion',
600
- ].includes(node.type))
601
- node = node.expression;
602
- return node;
603
- };
604
- const literalObjectArgument = (node, seen = new Set()) => {
605
- node = unwrapStyleExpression(node);
606
- if (utils_1.t.isObjectExpression(node))
607
- return node;
608
- if (!utils_1.t.isIdentifier(node) || seen.has(node.value))
609
- return null;
610
- seen.add(node.value);
611
- const declaration = [...topLevelDeclarators].find((decl) => utils_1.t.isIdentifier(decl.id) &&
612
- decl.id.value === node.value);
613
- return declaration?.init
614
- ? literalObjectArgument(declaration.init, seen)
615
- : null;
616
- };
617
- const registeredStyleCalls = new Set();
618
- const registerStyle = (node, declSpan, isExported) => {
619
- let propName;
620
- const init = unwrapStyleExpression(node.init);
621
- if (utils_1.t.isIdentifier(node.id) &&
622
- init &&
623
- utils_1.t.isCallExpression(init) &&
624
- init.arguments.length >= 1) {
625
- const callee = init.callee;
626
- if (utils_1.t.isMemberExpression(callee) &&
627
- utils_1.t.isIdentifier(callee.object) &&
628
- utils_1.t.isIdentifier(callee.property)) {
629
- const objectName = callee.object.value;
630
- const propertyName = callee.property.value;
631
- const alias = plumeriaAliases[objectName];
632
- if (alias === 'NAMESPACE') {
633
- propName = propertyName;
634
- }
635
- }
636
- else if (utils_1.t.isIdentifier(callee)) {
637
- const calleeName = callee.value;
638
- const originalName = plumeriaAliases[calleeName];
639
- if (originalName) {
640
- propName = originalName;
641
- }
642
- }
643
- }
644
- if (propName && init && utils_1.t.isCallExpression(init)) {
645
- if (['create', 'createTheme', 'createStatic'].includes(propName) &&
646
- !topLevelDeclarators.has(node)) {
647
- throwCompilationError(`Plumeria: css.${propName} must be assigned to a top-level variable so its styles can be resolved across files. Move this declaration outside the function or block.`, node);
648
- }
649
- if (['create', 'createTheme', 'createStatic'].includes(propName)) {
650
- const argumentIndex = propName === 'createTheme' ? 1 : 0;
651
- const argument = init.arguments[argumentIndex];
652
- const object = argument && literalObjectArgument(argument.expression);
653
- if (!object)
654
- throwCompilationError(`Plumeria: css.${propName} needs a style object it can read at build time. Pass an object literal or a top-level constant containing one.`, init);
655
- argument.expression = object;
656
- registeredStyleCalls.add(init.span.start);
657
- }
658
- if (propName === 'create' &&
659
- utils_1.t.isObjectExpression(init.arguments[0].expression)) {
660
- const obj = (0, utils_1.objectExpressionToObject)(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
661
- if (obj) {
662
- const hashMap = {};
663
- Object.entries(obj).forEach(([key, style]) => {
664
- if (typeof style !== 'object' || style === null)
665
- return;
666
- const records = (0, utils_1.getStyleRecords)(style);
667
- const atomMap = {};
668
- records.forEach((r) => (atomMap[r.key] = r.hash));
669
- hashMap[key] = atomMap;
670
- });
671
- const styleFunctions = (0, utils_1.styleFunctionsOf)(init.arguments[0].expression);
672
- if (utils_1.t.isIdentifier(node.id)) {
673
- idSpans.add(node.id.span.start);
674
- }
675
- if (utils_1.t.isIdentifier(node.id)) {
676
- localCreateStyles[node.id.value] = {
677
- name: node.id.value,
678
- type: 'create',
679
- obj,
680
- hashMap,
681
- isExported,
682
- initSpan: {
683
- start: init.span.start - baseByteOffset,
684
- end: init.span.end - baseByteOffset,
685
- },
686
- declSpan: {
687
- start: declSpan.start - baseByteOffset,
688
- end: declSpan.end - baseByteOffset,
689
- },
690
- functions: styleFunctions,
691
- };
692
- }
693
- }
694
- }
695
- else if (propName === 'createTheme' &&
696
- init.arguments.length >= 2 &&
697
- utils_1.t.isObjectExpression(init.arguments[1].expression)) {
698
- if (utils_1.t.isIdentifier(node.id)) {
699
- idSpans.add(node.id.span.start);
700
- }
701
- const selectorExpr = init.arguments[0].expression;
702
- const selector = (0, utils_1.resolveThemeSelector)(selectorExpr, mergedStaticTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
703
- if (!selector) {
704
- throwCompilationError(`Plumeria: createTheme needs a selector it can read at build time. ` +
705
- `Pass a string literal such as ".dark", or a name this file declares as one.`, selectorExpr);
706
- }
707
- if (selector.startsWith('@') && !(0, zss_engine_1.isAtRule)(selector)) {
708
- throwCompilationError(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`, selectorExpr);
709
- }
710
- const obj = (0, utils_1.objectExpressionToObject)(init.arguments[1].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
711
- const hash = (0, utils_1.themeHashOf)(selector, obj);
712
- if (utils_1.t.isIdentifier(node.id)) {
713
- const uniqueKey = `${resourcePath}-${node.id.value}`;
714
- scannedTables.createThemeHashTable[uniqueKey] = hash;
715
- scannedTables.createThemeObjectTable[hash] = obj;
716
- if (scannedTables.createThemeSelectorTable) {
717
- scannedTables.createThemeSelectorTable[hash] = selector;
718
- }
719
- mergedCreateThemeHashTable[node.id.value] = hash;
720
- const themeHashMap = {};
721
- for (const [key, value] of Object.entries(obj)) {
722
- const cssVarName = (0, zss_engine_1.camelToKebabCase)(key);
723
- const atomicHash = (0, zss_engine_1.genBase36Hash)({ _theme: hash, [key]: value }, 1, 8);
724
- themeHashMap[key] = `var(--${atomicHash}-${cssVarName})`;
725
- }
726
- localCreateStyles[node.id.value] = {
727
- name: node.id.value,
728
- type: 'constant',
729
- obj,
730
- hashMap: themeHashMap,
731
- isExported,
732
- initSpan: {
733
- start: init.span.start - baseByteOffset,
734
- end: init.span.end - baseByteOffset,
735
- },
736
- declSpan: {
737
- start: declSpan.start - baseByteOffset,
738
- end: declSpan.end - baseByteOffset,
739
- },
740
- };
741
- }
742
- }
743
- else if (propName === 'createStatic' &&
744
- utils_1.t.isObjectExpression(init.arguments[0].expression)) {
745
- if (utils_1.t.isIdentifier(node.id)) {
746
- idSpans.add(node.id.span.start);
747
- }
748
- const obj = (0, utils_1.objectExpressionToObject)(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
749
- const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
750
- if (utils_1.t.isIdentifier(node.id)) {
751
- const uniqueKey = `${resourcePath}-${node.id.value}`;
752
- scannedTables.createStaticHashTable[uniqueKey] = hash;
753
- scannedTables.createStaticObjectTable[hash] = obj;
754
- mergedCreateStaticHashTable[node.id.value] = hash;
755
- localCreateStyles[node.id.value] = {
756
- name: node.id.value,
757
- type: 'constant',
758
- obj,
759
- hashMap: obj,
760
- isExported,
761
- initSpan: {
762
- start: init.span.start - baseByteOffset,
763
- end: init.span.end - baseByteOffset,
764
- },
765
- declSpan: {
766
- start: declSpan.start - baseByteOffset,
767
- end: declSpan.end - baseByteOffset,
768
- },
769
- };
770
- }
771
- }
772
- }
773
- };
774
- (0, utils_1.traverse)(ast, {
775
- ImportDeclaration({ node }) {
776
- if (node.source.value === '@plumeria/core') {
777
- if (node.typeOnly)
778
- return;
779
- const typeOnlySpecs = node.specifiers.filter((s) => s.type === 'ImportSpecifier' && s.isTypeOnly);
780
- if (typeOnlySpecs.length > 0) {
781
- const names = typeOnlySpecs
782
- .map((s) => {
783
- if (s.type !== 'ImportSpecifier')
784
- return;
785
- const imported = s.imported ? s.imported.value : s.local.value;
786
- const local = s.local.value;
787
- return imported === local
788
- ? imported
789
- : `${imported} as ${local}`;
790
- })
791
- .join(', ');
792
- replacements.push({
793
- start: node.span.start - baseByteOffset,
794
- end: node.span.end - baseByteOffset,
795
- content: `import type { ${names} } from '@plumeria/core'`,
796
- });
797
- }
798
- else {
799
- replacements.push({
800
- start: node.span.start - baseByteOffset,
801
- end: node.span.end - baseByteOffset,
802
- content: '',
803
- });
804
- }
805
- }
806
- node.specifiers.forEach((specifier) => {
807
- if (specifier.local) {
808
- excludedSpans.add(specifier.local.span.start);
809
- }
810
- if (specifier.type === 'ImportSpecifier' && specifier.imported) {
811
- excludedSpans.add(specifier.imported.span.start);
812
- }
813
- });
814
- },
815
- ExportDeclaration({ node }) {
816
- if (utils_1.t.isVariableDeclaration(node.declaration)) {
817
- processedDecls.add(node.declaration);
818
- node.declaration.declarations.forEach((decl) => {
819
- registerStyle(decl, node.span, true);
820
- checkStyleAliasAssignment(decl);
821
- });
822
- }
823
- },
824
- VariableDeclaration({ node }) {
825
- if (processedDecls.has(node))
826
- return;
827
- node.declarations.forEach((decl) => {
828
- registerStyle(decl, node.span, node.declarations.length > 1 ||
829
- (utils_1.t.isIdentifier(decl.id) &&
830
- separatelyExported.has(decl.id.value)));
831
- checkStyleAliasAssignment(decl);
832
- });
833
- },
834
- CallExpression({ node }) {
835
- const callee = node.callee;
836
- let propName;
837
- if (utils_1.t.isMemberExpression(callee) &&
838
- utils_1.t.isIdentifier(callee.object) &&
839
- utils_1.t.isIdentifier(callee.property)) {
840
- const objectName = callee.object.value;
841
- const propertyName = callee.property.value;
842
- const alias = plumeriaAliases[objectName];
843
- if (alias === 'NAMESPACE') {
844
- propName = propertyName;
845
- }
846
- }
847
- else if (utils_1.t.isIdentifier(callee)) {
848
- const calleeName = callee.value;
849
- const originalName = plumeriaAliases[calleeName];
850
- if (originalName) {
851
- propName = originalName;
852
- }
853
- }
854
- if (propName) {
855
- if (['create', 'createTheme', 'createStatic'].includes(propName) &&
856
- !registeredStyleCalls.has(node.span.start)) {
857
- throwCompilationError(`Plumeria: css.${propName} must be assigned to a named top-level variable. Destructuring, assignment statements, and default-exported calls cannot be compiled.`, node);
858
- }
859
- const args = node.arguments;
860
- if (propName === 'keyframes' && args.length > 0) {
861
- const expr = args[0].expression;
862
- if (utils_1.t.isObjectExpression(expr)) {
863
- const obj = (0, utils_1.objectExpressionToObject)(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
864
- const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
865
- scannedTables.keyframesObjectTable[hash] = obj;
866
- replacements.push({
867
- start: node.span.start - baseByteOffset,
868
- end: node.span.end - baseByteOffset,
869
- content: JSON.stringify(`kf-${hash}`),
870
- });
871
- }
872
- }
873
- else if (propName === 'viewTransition' &&
874
- args.length > 0 &&
875
- utils_1.t.isObjectExpression(args[0].expression)) {
876
- const obj = (0, utils_1.objectExpressionToObject)(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
877
- const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
878
- scannedTables.viewTransitionObjectTable[hash] = obj;
879
- replacements.push({
880
- start: node.span.start - baseByteOffset,
881
- end: node.span.end - baseByteOffset,
882
- content: JSON.stringify(`vt-${hash}`),
883
- });
884
- }
885
- else if (propName === 'createTheme' &&
886
- args.length >= 2 &&
887
- utils_1.t.isObjectExpression(args[1].expression)) {
888
- const selectorExpr = args[0].expression;
889
- const selector = (0, utils_1.resolveThemeSelector)(selectorExpr, mergedStaticTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
890
- if (!selector) {
891
- throwCompilationError(`Plumeria: createTheme needs a selector it can read at build time. ` +
892
- `Pass a string literal such as ".dark", or a name this file declares as one.`, selectorExpr);
893
- }
894
- if (selector.startsWith('@') && !(0, zss_engine_1.isAtRule)(selector)) {
895
- throwCompilationError(`Plumeria: Unsupported at-rule: "${selector}". createTheme only supports nesting at-rules such as @media, @container, @supports, @layer, and @scope.`, selectorExpr);
896
- }
897
- const obj = (0, utils_1.objectExpressionToObject)(args[1].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
898
- const hash = (0, utils_1.themeHashOf)(selector, obj);
899
- scannedTables.createThemeObjectTable[hash] = obj;
900
- if (scannedTables.createThemeSelectorTable) {
901
- scannedTables.createThemeSelectorTable[hash] = selector;
902
- }
903
- }
904
- else if (propName === 'createStatic' &&
905
- args.length > 0 &&
906
- utils_1.t.isObjectExpression(args[0].expression)) {
907
- const obj = (0, utils_1.objectExpressionToObject)(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
908
- const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
909
- scannedTables.createStaticObjectTable[hash] = obj;
910
- }
911
- else if (propName === 'create' &&
912
- args.length > 0 &&
913
- utils_1.t.isObjectExpression(args[0].expression)) {
914
- const obj = (0, utils_1.objectExpressionToObject)(args[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
915
- const hash = (0, zss_engine_1.genBase36Hash)(obj, 1, 8);
916
- scannedTables.createObjectTable[hash] = obj;
917
- }
918
- }
919
- },
920
- });
921
- const jsxOpeningElementMap = new Map();
922
- const componentParamNames = new Set();
923
- const addFirstParamName = (fn) => {
924
- const first = fn.params[0];
925
- const p = unwrapPatternDefault(first?.pat ?? first);
926
- if (utils_1.t.isIdentifier(p)) {
927
- componentParamNames.add(p.value);
928
- }
929
- else if (p?.type === 'ObjectPattern') {
930
- for (const item of p.properties) {
931
- if (item.type === 'RestElement' && utils_1.t.isIdentifier(item.argument)) {
932
- componentParamNames.add(item.argument.value);
933
- }
934
- }
935
- }
936
- };
937
- for (const node of ast.body) {
938
- const statement = unwrapExport(node);
939
- if (isFunctionNode(statement)) {
940
- addFirstParamName(statement);
941
- }
942
- else if (statement?.type === 'CallExpression') {
943
- const fn = componentFunctionOf(statement);
944
- if (fn)
945
- addFirstParamName(fn);
946
- }
947
- else if (utils_1.t.isVariableDeclaration(statement)) {
948
- for (const decl of statement.declarations) {
949
- if (!utils_1.t.isIdentifier(decl.id) || !decl.init)
950
- continue;
951
- const fn = componentFunctionOf(decl.init);
952
- if (fn)
953
- addFirstParamName(fn);
954
- }
955
- }
956
- }
957
- const excludeSubtreeSpans = (n) => {
958
- if (!n || typeof n !== 'object')
959
- return;
960
- if (n.span) {
961
- excludedSpans.add(n.span.start);
962
- }
963
- Object.values(n).forEach((val) => excludeSubtreeSpans(val));
964
- };
965
- const getSource = (node) => {
966
- const start = node.span.start - baseByteOffset;
967
- const end = node.span.end - baseByteOffset;
968
- return sourceBuffer.subarray(start, end).toString('utf-8');
969
- };
970
- const isVisibleReference = (expr) => {
971
- if (utils_1.t.isIdentifier(expr))
972
- return referenceIdents.references.has(expr.span.start);
973
- if (utils_1.t.isMemberExpression(expr))
974
- return isVisibleReference(expr.object);
975
- if (utils_1.t.isCallExpression(expr) &&
976
- expr.callee.type !== 'Super' &&
977
- expr.callee.type !== 'Import')
978
- return isVisibleReference(expr.callee);
979
- return true;
980
- };
981
- const resolveStyleObject = (expr) => {
982
- expr = (0, utils_1.unwrapExpression)(expr);
983
- expr = resolveLocalStyleAlias(localStyleAliases, expr);
984
- if (!isVisibleReference(expr))
985
- return null;
986
- if (expr.type === 'ArrayExpression') {
987
- let merged = {};
988
- for (const element of expr.elements ?? []) {
989
- if (!element)
990
- continue;
991
- if (element.spread)
992
- throwCompilationError(spreadStyleMessage(getSource(element.expression)), element.expression);
993
- const style = resolveStyleObject(element.expression);
994
- if (!style)
995
- return null;
996
- merged = (0, utils_1.deepMerge)(merged, style);
997
- }
998
- return merged;
999
- }
1000
- if (utils_1.t.isObjectExpression(expr)) {
1001
- return (0, utils_1.objectExpressionToObject)(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
1002
- }
1003
- else if (utils_1.t.isMemberExpression(expr) &&
1004
- utils_1.t.isIdentifier(expr.object) &&
1005
- (utils_1.t.isIdentifier(expr.property) || expr.property.type === 'Computed')) {
1006
- const varName = expr.object.value;
1007
- let propName;
1008
- if (expr.property.type === 'Computed') {
1009
- const keyExpr = expr.property.expression;
1010
- if (!utils_1.t.isStringLiteral(keyExpr))
1011
- return null;
1012
- propName = keyExpr.value;
1013
- }
1014
- else {
1015
- propName = expr.property.value;
1016
- }
1017
- const styleInfo = localCreateStyles[varName];
1018
- if (styleInfo?.obj[propName]) {
1019
- const style = styleInfo.obj[propName];
1020
- if (typeof style === 'object' && style !== null)
1021
- return style;
1022
- }
1023
- const hash = mergedCreateTable[varName];
1024
- if (hash) {
1025
- const obj = scannedTables.createObjectTable[hash];
1026
- if (obj?.[propName] && typeof obj[propName] === 'object')
1027
- return obj[propName];
1028
- }
1029
- }
1030
- else if (utils_1.t.isIdentifier(expr)) {
1031
- const varName = expr.value;
1032
- const uniqueKey = `${resourcePath}-${varName}`;
1033
- let hash = scannedTables.createHashTable[uniqueKey];
1034
- if (!hash)
1035
- hash = mergedCreateTable[varName];
1036
- if (hash) {
1037
- const obj = scannedTables.createObjectTable[hash];
1038
- if (obj && typeof obj === 'object')
1039
- return obj;
1040
- }
1041
- const styleInfo = localCreateStyles[varName];
1042
- if (styleInfo?.obj)
1043
- return styleInfo.obj;
1044
- }
1045
- return null;
1046
- };
1047
- const isStyleFunctionCall = (expr) => {
1048
- if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
1049
- return false;
1050
- const callee = expr.callee;
1051
- if (!utils_1.t.isIdentifier(callee.object) || !utils_1.t.isIdentifier(callee.property))
1052
- return false;
1053
- return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
1054
- createFunctionImportMap[callee.object.value]?.[callee.property.value]);
1055
- };
1056
- const carriesStyleReference = (expression) => {
1057
- const node = (0, utils_1.unwrapExpression)(expression);
1058
- if (node.type === 'ArrayExpression')
1059
- return node.elements.some((element) => !!element && carriesStyleReference(element.expression));
1060
- if (isStyleFunctionCall(node))
1061
- return true;
1062
- if (utils_1.t.isObjectExpression(node))
1063
- return false;
1064
- return resolveStyleObject(node) !== null;
1065
- };
1066
- const assertNoStyleArraySpread = (expression) => {
1067
- const node = (0, utils_1.unwrapExpression)(expression);
1068
- if (node.type !== 'ArrayExpression')
1069
- return;
1070
- const spread = node.elements.find((element) => element?.spread);
1071
- if (!spread)
1072
- return;
1073
- if (carriesStyleReference(node))
1074
- throwCompilationError(spreadStyleMessage(getSource(spread.expression)), spread.expression);
1075
- };
1076
- const resolveDynamicCall = (expr, forceRuntime = false) => {
1077
- if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
1078
- return null;
1079
- const callee = expr.callee;
1080
- if (!utils_1.t.isIdentifier(callee.object) || !utils_1.t.isIdentifier(callee.property))
1081
- return null;
1082
- if (!isVisibleReference(callee.object))
1083
- return null;
1084
- const styleInfo = localCreateStyles[callee.object.value];
1085
- const func = styleInfo?.functions?.[callee.property.value] ??
1086
- createFunctionImportMap[callee.object.value]?.[callee.property.value];
1087
- if (!func)
1088
- return null;
1089
- const callArgs = expr.arguments;
1090
- if (callArgs.some((a) => a.spread))
1091
- return null;
1092
- const tempStaticTable = { ...mergedStaticTable };
1093
- const providedParams = new Set();
1094
- const runtime = [];
1095
- const resolveObjectArg = (argExpr) => (0, utils_1.objectExpressionToObject)({
1096
- ...argExpr,
1097
- properties: argExpr.properties.filter((prop) => prop.type === 'Identifier' ||
1098
- (prop.type === 'KeyValueProperty' &&
1099
- isStaticArgValue(prop.value))),
1100
- }, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable);
1101
- if (func.named) {
1102
- const argExpr = callArgs[0]?.expression;
1103
- if (callArgs.length > 1 ||
1104
- (argExpr && argExpr.type !== 'ObjectExpression')) {
1105
- throwCompilationError(`Plumeria: ${getSource(expr)} takes one object argument, because ${callee.property.value} destructures its parameter.`, expr);
1106
- }
1107
- const given = new Map();
1108
- (argExpr?.properties ?? []).forEach((prop) => {
1109
- if (prop.type === 'Identifier') {
1110
- given.set(prop.value, prop);
1111
- }
1112
- else if (prop.type === 'KeyValueProperty' &&
1113
- (utils_1.t.isIdentifier(prop.key) || utils_1.t.isStringLiteral(prop.key))) {
1114
- given.set(String(prop.key.value), prop.value);
1115
- }
1116
- });
1117
- const argObj = argExpr
1118
- ? (resolveObjectArg(argExpr) ?? {})
1119
- : {};
1120
- func.named.forEach(({ key, local }) => {
1121
- const source = given.get(key);
1122
- if (!source) {
1123
- if (func.defaults?.[local])
1124
- return;
1125
- throwCompilationError(`Plumeria: ${getSource(expr)} leaves "${key}" unset, and a dynamic style function has no value to fall back on.`, expr);
1126
- return;
1127
- }
1128
- if (!forceRuntime &&
1129
- isStaticArgValue(source) &&
1130
- argObj[key] !== undefined) {
1131
- tempStaticTable[local] = argObj[key];
1132
- providedParams.add(local);
1133
- }
1134
- else
1135
- runtime.push({ param: local, source });
1136
- });
1137
- }
1138
- else if (callArgs.length === 1 &&
1139
- callArgs[0].expression.type === 'ObjectExpression') {
1140
- if (forceRuntime)
1141
- return null;
1142
- const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
1143
- func.params.forEach((p) => {
1144
- if (argObj[p] !== undefined) {
1145
- tempStaticTable[p] = argObj[p];
1146
- providedParams.add(p);
1147
- }
1148
- });
1149
- }
1150
- else {
1151
- callArgs.forEach((callArg, i) => {
1152
- const p = func.params[i];
1153
- if (!p)
1154
- return;
1155
- runtime.push({ param: p, source: callArg.expression });
1156
- });
1157
- }
1158
- const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables, providedParams);
1159
- if (!resolved)
1160
- return null;
1161
- const { style, varGroups } = resolved;
1162
- const vars = [];
1163
- runtime.forEach(({ param, source }) => {
1164
- const groups = varGroups.get(param);
1165
- if (!groups?.length)
1166
- return;
1167
- const argStart = source.span.start - baseByteOffset;
1168
- const argEnd = source.span.end - baseByteOffset;
1169
- const argSource = sourceBuffer
1170
- .subarray(argStart, argEnd)
1171
- .toString('utf-8');
1172
- const maybeNumber = Number(argSource);
1173
- groups.forEach(({ cssVar, prop }) => {
1174
- let valueExpr;
1175
- const kebabProp = (0, zss_engine_1.camelToKebabCase)(prop);
1176
- if (!isNaN(maybeNumber) && argSource.trim() === String(maybeNumber)) {
1177
- valueExpr = JSON.stringify((0, zss_engine_1.applyCssValue)(maybeNumber, kebabProp));
1178
- }
1179
- else if ((argSource.startsWith('"') && argSource.endsWith('"')) ||
1180
- (argSource.startsWith("'") && argSource.endsWith("'"))) {
1181
- valueExpr = JSON.stringify((0, zss_engine_1.applyCssValue)(argSource.slice(1, -1), kebabProp));
1182
- }
1183
- else {
1184
- valueExpr = (0, utils_1.isUnitlessProp)(prop)
1185
- ? argSource
1186
- : `(typeof (${argSource}) === 'number' ? (${argSource}) + 'px' : (${argSource}))`;
1187
- }
1188
- vars.push({ cssVar, valueExpr });
1189
- });
1190
- });
1191
- return { style, vars };
1192
- };
1193
- const buildClassParts = (args, dynamicClassParts = [], existingClass = '', isStyleProp = false) => {
1194
- args.forEach((arg) => {
1195
- arg.expression = resolveLocalStyleAlias(localStyleAliases, arg.expression);
1196
- });
1197
- const conditionals = [];
1198
- const dynamicVars = [];
1199
- const propVarSpreads = [];
1200
- let groupIdCounter = 0;
1201
- let sourceOrder = 0;
1202
- const baseChunks = [];
1203
- let baseStyle = {};
1204
- let isOptimizable = true;
1205
- const resolveCreateObject = (varName) => {
1206
- const localStyle = localCreateStyles[varName];
1207
- if (localStyle?.type === 'create')
1208
- return localStyle.obj;
1209
- let hash = scannedTables.createHashTable[`${resourcePath}-${varName}`];
1210
- if (!hash)
1211
- hash = mergedCreateTable[varName];
1212
- if (hash && scannedTables.createObjectTable[hash])
1213
- return scannedTables.createObjectTable[hash];
1214
- return null;
1215
- };
1216
- const resolveBracketGroup = (node) => {
1217
- if (!utils_1.t.isMemberExpression(node) ||
1218
- !utils_1.t.isIdentifier(node.object) ||
1219
- node.property.type !== 'Computed' ||
1220
- utils_1.t.isStringLiteral(node.property.expression)) {
1221
- return null;
1222
- }
1223
- if (!isVisibleReference(node.object))
1224
- return null;
1225
- const varName = node.object.value;
1226
- const obj = resolveCreateObject(varName);
1227
- return obj ? { varName, keyExpr: node.property.expression, obj } : null;
1228
- };
1229
- const buildDecision = (node, prefix, off, counter, scoped) => {
1230
- if (node.type === 'ParenthesisExpression') {
1231
- return buildDecision(node.expression, prefix, off, counter, scoped);
1232
- }
1233
- if (node.type === 'ConditionalExpression') {
1234
- const a = buildDecision(node.consequent, prefix, off, counter, scoped);
1235
- if (!a)
1236
- return null;
1237
- const b = buildDecision(node.alternate, prefix, off, counter, scoped);
1238
- if (!b)
1239
- return null;
1240
- return {
1241
- keyExpr: `((${getSource(node.test)}) ? ${a.keyExpr} : ${b.keyExpr})`,
1242
- options: [...a.options, ...b.options],
1243
- leaves: a.leaves + b.leaves,
1244
- hasGroup: a.hasGroup || b.hasGroup,
1245
- };
1246
- }
1247
- if (node.type === 'BinaryExpression' && node.operator === '&&') {
1248
- const right = buildDecision(node.right, prefix, off, counter, scoped);
1249
- if (!right)
1250
- return null;
1251
- return {
1252
- keyExpr: `((${getSource(node.left)}) ? ${right.keyExpr} : ${JSON.stringify(off)})`,
1253
- options: right.options,
1254
- leaves: right.leaves,
1255
- hasGroup: right.hasGroup,
1256
- };
1257
- }
1258
- const group = resolveBracketGroup(node);
1259
- if (group) {
1260
- const tag = scoped ? `${counter.n++}:` : '';
1261
- const keySource = getSource(group.keyExpr);
1262
- return {
1263
- keyExpr: tag
1264
- ? `(${JSON.stringify(tag)} + ${keySource})`
1265
- : keySource,
1266
- options: Object.entries(group.obj).map(([value, style]) => ({
1267
- value: `${tag}${value}`,
1268
- style: style,
1269
- })),
1270
- leaves: 1,
1271
- hasGroup: true,
1272
- };
1273
- }
1274
- const style = resolveStyleObject(node);
1275
- if (!style)
1276
- return null;
1277
- const value = `${prefix}${counter.n++}`;
1278
- return {
1279
- keyExpr: JSON.stringify(value),
1280
- options: [{ value, style }],
1281
- leaves: 1,
1282
- hasGroup: false,
1283
- };
1284
- };
1285
- const collectGroupKeys = (node, acc) => {
1286
- if (node.type === 'ParenthesisExpression') {
1287
- collectGroupKeys(node.expression, acc);
1288
- }
1289
- else if (node.type === 'ConditionalExpression') {
1290
- collectGroupKeys(node.consequent, acc);
1291
- collectGroupKeys(node.alternate, acc);
1292
- }
1293
- else if (node.type === 'BinaryExpression' && node.operator === '&&') {
1294
- collectGroupKeys(node.right, acc);
1295
- }
1296
- else {
1297
- const group = resolveBracketGroup(node);
1298
- if (group)
1299
- Object.entries(group.obj).forEach(([key, style]) => {
1300
- let styles = acc.get(key);
1301
- if (!styles)
1302
- acc.set(key, (styles = new Set()));
1303
- styles.add(style);
1304
- });
1305
- }
1306
- };
1307
- const resolveDecision = (node) => {
1308
- const groupKeys = new Map();
1309
- collectGroupKeys(node, groupKeys);
1310
- let prefix = '#';
1311
- while ([...groupKeys.keys()].some((k) => k.startsWith(prefix)))
1312
- prefix += '#';
1313
- const scoped = [...groupKeys.values()].some((styles) => styles.size > 1);
1314
- const off = !scoped && groupKeys.has('') ? `${prefix}off` : '';
1315
- return buildDecision(node, prefix, off, { n: 0 }, scoped);
1316
- };
1317
- const collectConditions = (node, currentTestStrings = [], argOrder) => {
1318
- node = (0, utils_1.unwrapExpression)(node);
1319
- node = resolveLocalStyleAlias(localStyleAliases, node);
1320
- if (isNoOpStyle(node))
1321
- return true;
1322
- if (node.type === 'ArrayExpression') {
1323
- return node.elements.every((element) => {
1324
- if (!element)
1325
- return true;
1326
- if (element.spread)
1327
- throwCompilationError(spreadStyleMessage(getSource(element.expression)), element.expression);
1328
- return collectConditions(element.expression, currentTestStrings, argOrder);
1329
- });
1330
- }
1331
- let branchStyle = resolveStyleObject(node);
1332
- if (!branchStyle) {
1333
- const dynamic = resolveDynamicCall(node);
1334
- if (dynamic) {
1335
- if (!isStyleProp) {
1336
- throwCompilationError(`Plumeria: css.use(${getSource(node)}) does not support dynamic function keys.`, node);
1337
- }
1338
- branchStyle = dynamic.style;
1339
- dynamic.vars.forEach((v) => dynamicVars.push({
1340
- ...v,
1341
- test: currentTestStrings.length
1342
- ? currentTestStrings.join(' && ')
1343
- : undefined,
1344
- order: argOrder,
1345
- }));
1346
- }
1347
- }
1348
- if (branchStyle) {
1349
- const staticStyle = branchStyle;
1350
- if (currentTestStrings.length === 0) {
1351
- baseStyle = (0, utils_1.deepMerge)(baseStyle, staticStyle);
1352
- baseChunks.push({ order: sourceOrder++, style: staticStyle });
1353
- }
1354
- else {
1355
- conditionals.push({
1356
- test: node,
1357
- testString: currentTestStrings.join(' && '),
1358
- truthy: staticStyle,
1359
- falsy: {},
1360
- varName: undefined,
1361
- order: sourceOrder++,
1362
- });
1363
- }
1364
- return true;
1365
- }
1366
- if (node.type === 'ConditionalExpression') {
1367
- const testSource = getSource(node.test);
1368
- if (currentTestStrings.length === 0) {
1369
- const trueStyle = resolveStyleObject(node.consequent);
1370
- const falseStyle = resolveStyleObject(node.alternate);
1371
- if (trueStyle && falseStyle) {
1372
- conditionals.push({
1373
- test: node,
1374
- testString: testSource,
1375
- truthy: trueStyle,
1376
- falsy: falseStyle,
1377
- varName: undefined,
1378
- order: sourceOrder++,
1379
- });
1380
- return true;
1381
- }
1382
- }
1383
- const consequentHandled = collectConditions(node.consequent, [...currentTestStrings, `(${testSource})`], argOrder);
1384
- const alternateHandled = collectConditions(node.alternate, [...currentTestStrings, `!(${testSource})`], argOrder);
1385
- return consequentHandled && alternateHandled;
1386
- }
1387
- else if (node.type === 'BinaryExpression' && node.operator === '&&') {
1388
- return collectConditions(node.right, [...currentTestStrings, `(${getSource(node.left)})`], argOrder);
1389
- }
1390
- else if (node.type === 'ParenthesisExpression') {
1391
- return collectConditions(node.expression, currentTestStrings, argOrder);
1392
- }
1393
- if (pushPropPossibilities(node, currentTestStrings))
1394
- return true;
1395
- assertResolvable(node);
1396
- return false;
1397
- };
1398
- const pushPropPossibilities = (expr, gates) => {
1399
- const isParamMember = utils_1.t.isMemberExpression(expr) &&
1400
- utils_1.t.isIdentifier(expr.object) &&
1401
- componentParamNames.has(expr.object.value) &&
1402
- utils_1.t.isIdentifier(expr.property);
1403
- if (!utils_1.t.isIdentifier(expr) && !isParamMember)
1404
- return false;
1405
- const paramObject = isParamMember
1406
- ? expr.object.value
1407
- : undefined;
1408
- const isPropsMember = Boolean(paramObject &&
1409
- localCreateStyles[paramObject] === undefined &&
1410
- mergedCreateTable[paramObject] === undefined);
1411
- const varName = utils_1.t.isIdentifier(expr)
1412
- ? expr.value
1413
- : expr.property.value;
1414
- const source = utils_1.t.isIdentifier(expr) ? varName : getSource(expr);
1415
- const owner = ownerComponentOf(expr);
1416
- const propName = (utils_1.t.isIdentifier(expr) && owner
1417
- ? propAliases.get(owner)?.get(varName)
1418
- : undefined) ?? varName;
1419
- markStylePropApplied(propName, expr);
1420
- let possibilities = owner
1421
- ? scannedTables.componentPropsTable?.[`${resourcePath}-${owner}`]?.[propName]
1422
- : undefined;
1423
- if (!possibilities) {
1424
- const candidates = [];
1425
- for (const key of Object.keys(scannedTables.componentPropsTable || {})) {
1426
- if (!key.startsWith(`${resourcePath}-`))
1427
- continue;
1428
- const entries = scannedTables.componentPropsTable?.[key]?.[propName];
1429
- if (entries)
1430
- candidates.push(...entries);
1431
- }
1432
- if (candidates.length > 0)
1433
- possibilities = candidates;
1434
- }
1435
- const fallback = owner && propDefaults.get(owner)?.get(propName);
1436
- if (fallback && !isNoOpStyle((0, utils_1.unwrapExpression)(fallback))) {
1437
- const style = resolveStyleObject(fallback);
1438
- if (!style)
1439
- throwCompilationError(propDefaultMessage(getSource(fallback)), fallback);
1440
- const atoms = {};
1441
- (0, utils_1.getStyleRecords)(style).forEach((record) => {
1442
- atoms[record.key] = record.hash;
1443
- });
1444
- const key = (0, zss_engine_1.genBase36Hash)(Object.values(atoms).join(' '), 1, 8);
1445
- possibilities = [...(possibilities ?? []), { key, styleObj: style }];
1446
- const span = fallback.span;
1447
- for (let index = replacements.length - 1; index >= 0; index--) {
1448
- const replacement = replacements[index];
1449
- if (replacement.start >= span.start - baseByteOffset &&
1450
- replacement.end <= span.end - baseByteOffset)
1451
- replacements.splice(index, 1);
1452
- }
1453
- excludeSubtreeSpans(fallback);
1454
- replacements.push({
1455
- start: span.start - baseByteOffset,
1456
- end: span.end - baseByteOffset,
1457
- content: JSON.stringify(key),
1458
- });
1459
- }
1460
- if (!possibilities || possibilities.length === 0) {
1461
- return Boolean(isPropsMember || (owner && declaredProps.get(owner)?.has(propName)));
1462
- }
1463
- const carriesVars = possibilities.some((entry) => entry.hasVars);
1464
- if (carriesVars && !isStyleProp) {
1465
- throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
1466
- `Apply it to ${styleProp} on the element instead.`, expr);
1467
- }
1468
- const gate = gates.length ? `(${gates.join(' && ')}) && ` : '';
1469
- if (carriesVars) {
1470
- const spread = `...(${gate}${source} && ${source}.vars)`;
1471
- if (!propVarSpreads.includes(spread))
1472
- propVarSpreads.push(spread);
1473
- }
1474
- const token = carriesVars
1475
- ? `((${source} && ${source}.key) || ${source})`
1476
- : source;
1477
- const testLHS = gates.length
1478
- ? `((${gates.join(' && ')}) ? ${token} : "")`
1479
- : token;
1480
- const currentGroupId = ++groupIdCounter;
1481
- const currentOrder = sourceOrder++;
1482
- const seen = new Set();
1483
- const pushOption = (valueName, style) => {
1484
- conditionals.push({
1485
- test: expr,
1486
- testLHS,
1487
- testString: `${testLHS} === ${JSON.stringify(valueName)}`,
1488
- truthy: style,
1489
- falsy: {},
1490
- groupId: currentGroupId,
1491
- order: currentOrder,
1492
- groupName: undefined,
1493
- valueName,
1494
- varName,
1495
- });
1496
- };
1497
- possibilities.forEach((entry) => {
1498
- if (seen.has(entry.key))
1499
- return;
1500
- seen.add(entry.key);
1501
- pushOption(entry.key, entry.styleObj);
1502
- });
1503
- if (gates.length)
1504
- pushOption('', {});
1505
- return true;
1506
- };
1507
- for (const arg of args) {
1508
- const expr = arg.expression;
1509
- if (isNoOpStyle(expr))
1510
- continue;
1511
- if (pushPropPossibilities(expr, []))
1512
- continue;
1513
- if (utils_1.t.isCallExpression(expr) && utils_1.t.isIdentifier(expr.callee)) {
1514
- const varName = expr.callee.value;
1515
- let variantObj;
1516
- if (isVisibleReference(expr) && localCreateStyles[varName]?.obj)
1517
- variantObj = localCreateStyles[varName].obj;
1518
- if (variantObj) {
1519
- const callArgs = expr.arguments;
1520
- const hasSpread = callArgs.some((a) => {
1521
- if (a.spread)
1522
- return true;
1523
- if (a.expression.type === 'ObjectExpression') {
1524
- return a.expression.properties.some((p) => p.type === 'SpreadElement');
1525
- }
1526
- return false;
1527
- });
1528
- if (hasSpread) {
1529
- throwCompilationError(`Plumeria: Spread operator in ${getSource(expr)} is not supported. ` +
1530
- `Please pass specific variant options directly.`, expr);
1531
- }
1532
- if (callArgs.length !== 1) {
1533
- throwCompilationError(`Plumeria: Variant function "${varName}" expects exactly 1 argument, found ${callArgs.length}.`, expr);
1534
- }
1535
- if (callArgs.length === 1 && !callArgs[0].spread) {
1536
- const arg = callArgs[0].expression;
1537
- if (arg.type === 'ObjectExpression') {
1538
- for (const prop of arg.properties) {
1539
- let groupName;
1540
- let valExpr;
1541
- if (prop.type === 'KeyValueProperty' &&
1542
- prop.key.type === 'Identifier') {
1543
- groupName = prop.key.value;
1544
- valExpr = prop.value;
1545
- }
1546
- else if (prop.type === 'Identifier') {
1547
- groupName = prop.value;
1548
- valExpr = prop;
1549
- }
1550
- if (groupName && valExpr) {
1551
- const groupVariants = variantObj[groupName];
1552
- if (!groupVariants)
1553
- continue;
1554
- const currentGroupId = ++groupIdCounter;
1555
- const currentOrder = sourceOrder++;
1556
- const valSource = getSource(valExpr);
1557
- if (valExpr.type === 'StringLiteral') {
1558
- const groupVariantsAsObj = groupVariants;
1559
- const picked = groupVariantsAsObj[valExpr.value];
1560
- if (picked) {
1561
- baseStyle = (0, utils_1.deepMerge)(baseStyle, picked);
1562
- baseChunks.push({
1563
- order: sourceOrder++,
1564
- style: picked,
1565
- });
1566
- }
1567
- continue;
1568
- }
1569
- Object.entries(groupVariants).forEach(([optionName, style]) => {
1570
- conditionals.push({
1571
- test: valExpr,
1572
- testLHS: valSource,
1573
- testString: `${valSource} === '${optionName}'`,
1574
- truthy: style,
1575
- falsy: {},
1576
- groupId: currentGroupId,
1577
- order: currentOrder,
1578
- groupName,
1579
- valueName: optionName,
1580
- varName,
1581
- });
1582
- });
1583
- }
1584
- }
1585
- continue;
1586
- }
1587
- const argSource = getSource(arg);
1588
- if (utils_1.t.isStringLiteral(arg)) {
1589
- const picked = variantObj[arg.value];
1590
- if (picked) {
1591
- baseStyle = (0, utils_1.deepMerge)(baseStyle, picked);
1592
- baseChunks.push({ order: sourceOrder++, style: picked });
1593
- }
1594
- continue;
1595
- }
1596
- const currentGroupId = ++groupIdCounter;
1597
- const currentOrder = sourceOrder++;
1598
- Object.entries(variantObj).forEach(([key, style]) => {
1599
- conditionals.push({
1600
- test: arg,
1601
- testLHS: argSource,
1602
- testString: `${argSource} === '${key}'`,
1603
- truthy: style,
1604
- falsy: {},
1605
- groupId: currentGroupId,
1606
- order: currentOrder,
1607
- groupName: undefined,
1608
- valueName: key,
1609
- varName,
1610
- });
1611
- });
1612
- continue;
1613
- }
1614
- isOptimizable = false;
1615
- break;
1616
- }
1617
- }
1618
- else if (utils_1.t.isIdentifier(expr)) {
1619
- const varName = expr.value;
1620
- let variantObj;
1621
- if (isVisibleReference(expr) && localCreateStyles[varName]?.obj)
1622
- variantObj = localCreateStyles[varName].obj;
1623
- if (variantObj) {
1624
- Object.entries(variantObj).forEach(([groupName, groupVariants]) => {
1625
- if (!groupVariants)
1626
- return;
1627
- const currentGroupId = ++groupIdCounter;
1628
- const currentOrder = sourceOrder++;
1629
- Object.entries(groupVariants).forEach(([optionName, style]) => {
1630
- conditionals.push({
1631
- test: expr,
1632
- testLHS: `props["${groupName}"]`,
1633
- testString: `props["${groupName}"] === '${optionName}'`,
1634
- truthy: style,
1635
- falsy: {},
1636
- groupId: currentGroupId,
1637
- order: currentOrder,
1638
- groupName,
1639
- valueName: optionName,
1640
- varName,
1641
- });
1642
- });
1643
- });
1644
- continue;
1645
- }
1646
- }
1647
- if (utils_1.t.isMemberExpression(expr) &&
1648
- utils_1.t.isIdentifier(expr.object) &&
1649
- expr.property.type === 'Computed') {
1650
- const varName = expr.object.value;
1651
- const styleObj = isVisibleReference(expr)
1652
- ? resolveCreateObject(varName)
1653
- : null;
1654
- if (styleObj) {
1655
- const dynExpr = expr.property.expression;
1656
- const dynSource = getSource(dynExpr);
1657
- const currentGroupId = ++groupIdCounter;
1658
- const currentOrder = sourceOrder++;
1659
- Object.entries(styleObj).forEach(([optionName, style]) => {
1660
- conditionals.push({
1661
- test: dynExpr,
1662
- testLHS: dynSource,
1663
- testString: `${dynSource} === '${optionName}'`,
1664
- truthy: style,
1665
- falsy: {},
1666
- groupId: currentGroupId,
1667
- order: currentOrder,
1668
- groupName: undefined,
1669
- valueName: optionName,
1670
- varName,
1671
- ownKeys: true,
1672
- });
1673
- });
1674
- continue;
1675
- }
1676
- }
1677
- const decision = resolveDecision(expr);
1678
- if (decision && (decision.hasGroup || decision.leaves > 2)) {
1679
- const groupId = ++groupIdCounter;
1680
- const currentOrder = sourceOrder++;
1681
- decision.options.forEach(({ value, style }) => conditionals.push({
1682
- test: expr,
1683
- testLHS: decision.keyExpr,
1684
- testString: `${decision.keyExpr} === '${value}'`,
1685
- truthy: style,
1686
- falsy: {},
1687
- groupId,
1688
- order: currentOrder,
1689
- groupName: undefined,
1690
- valueName: value,
1691
- varName: undefined,
1692
- ownKeys: true,
1693
- }));
1694
- continue;
1695
- }
1696
- const handled = collectConditions(expr, [], arg.order);
1697
- if (handled)
1698
- continue;
1699
- assertResolvable(expr);
1700
- isOptimizable = false;
1701
- break;
1702
- }
1703
- if (!isOptimizable ||
1704
- (args.length === 0 && Object.keys(baseStyle).length === 0)) {
1705
- return {
1706
- classParts: [...dynamicClassParts],
1707
- isOptimizable,
1708
- baseStyle,
1709
- dynamicVars,
1710
- propVarSpreads,
1711
- };
1712
- }
1713
- const stateSources = baseChunks.map(({ order, style }) => ({ order, style: style }));
1714
- conditionals.forEach((c) => {
1715
- const order = c.order ?? 0;
1716
- stateSources.push({ order, style: c.truthy });
1717
- stateSources.push({ order, style: c.falsy });
1718
- });
1719
- const stateWeights = (0, utils_1.getStateWeights)(stateSources);
1720
- const participation = {};
1721
- const registerParticipation = (style, sourceId) => {
1722
- Object.keys(style).forEach((key) => {
1723
- if (!participation[key])
1724
- participation[key] = new Set();
1725
- participation[key].add(sourceId);
1726
- });
1727
- };
1728
- registerParticipation(baseStyle, 'base');
1729
- conditionals
1730
- .filter((c) => c.groupId === undefined)
1731
- .forEach((c, idx) => {
1732
- registerParticipation(c.truthy, `std_${idx}`);
1733
- registerParticipation(c.falsy, `std_${idx}`);
1734
- });
1735
- const variantGroups = {};
1736
- conditionals.forEach((c) => {
1737
- if (c.groupId !== undefined) {
1738
- if (!variantGroups[c.groupId])
1739
- variantGroups[c.groupId] = [];
1740
- variantGroups[c.groupId].push(c);
1741
- }
1742
- });
1743
- Object.entries(variantGroups).forEach(([groupId, opts]) => {
1744
- opts.forEach((opt) => registerParticipation(opt.truthy, `var_${groupId}`));
1745
- });
1746
- const conflictingKeys = new Set();
1747
- Object.entries(participation).forEach(([key, sources]) => {
1748
- if (sources.size > 1)
1749
- conflictingKeys.add(key);
1750
- });
1751
- const baseIndependent = {};
1752
- const baseConflict = {};
1753
- Object.entries(baseStyle).forEach(([key, val]) => {
1754
- if (conflictingKeys.has(key))
1755
- baseConflict[key] = val;
1756
- else
1757
- baseIndependent[key] = val;
1758
- });
1759
- const indepConditionals = [];
1760
- const conflictConditionals = [];
1761
- conditionals.forEach((c) => {
1762
- const truthyIndep = {};
1763
- const truthyConf = {};
1764
- const falsyIndep = {};
1765
- const falsyConf = {};
1766
- let hasIndep = false;
1767
- let hasConf = false;
1768
- Object.entries(c.truthy).forEach(([k, v]) => {
1769
- if (conflictingKeys.has(k)) {
1770
- truthyConf[k] = v;
1771
- hasConf = true;
1772
- }
1773
- else {
1774
- truthyIndep[k] = v;
1775
- hasIndep = true;
1776
- }
1777
- });
1778
- Object.entries(c.falsy).forEach(([k, v]) => {
1779
- if (conflictingKeys.has(k)) {
1780
- falsyConf[k] = v;
1781
- hasConf = true;
1782
- }
1783
- else {
1784
- falsyIndep[k] = v;
1785
- hasIndep = true;
1786
- }
1787
- });
1788
- if (hasIndep)
1789
- indepConditionals.push({
1790
- ...c,
1791
- truthy: truthyIndep,
1792
- falsy: falsyIndep,
1793
- });
1794
- if (hasConf)
1795
- conflictConditionals.push({
1796
- ...c,
1797
- truthy: truthyConf,
1798
- falsy: falsyConf,
1799
- });
1800
- });
1801
- const classParts = [];
1802
- if (existingClass)
1803
- classParts.push(existingClass);
1804
- if (Object.keys(baseIndependent).length > 0) {
1805
- const className = processStyleRecords(baseIndependent, stateWeights)
1806
- .map((r) => r.hash)
1807
- .join(' ');
1808
- if (className)
1809
- classParts.push(JSON.stringify(className));
1810
- }
1811
- indepConditionals
1812
- .filter((c) => c.groupId === undefined)
1813
- .forEach((c) => {
1814
- const processBranch = (style) => {
1815
- if (Object.keys(style).length === 0)
1816
- return '""';
1817
- return JSON.stringify(processStyleRecords(style, stateWeights)
1818
- .map((r) => r.hash)
1819
- .join(' '));
1820
- };
1821
- const testStr = c.testString ?? getSource(c.test);
1822
- classParts.push(`(${testStr} ? ${processBranch(c.truthy)} : ${processBranch(c.falsy)})`);
1823
- });
1824
- const indepVarGroups = {};
1825
- indepConditionals.forEach((c) => {
1826
- if (c.groupId !== undefined) {
1827
- if (!indepVarGroups[c.groupId])
1828
- indepVarGroups[c.groupId] = [];
1829
- indepVarGroups[c.groupId].push(c);
1830
- }
1831
- });
1832
- Object.values(indepVarGroups).forEach((options) => {
1833
- const commonTestExpr = options[0].testLHS ??
1834
- options[0].testString ??
1835
- getSource(options[0].test);
1836
- const lookupMap = {};
1837
- options.forEach((opt) => {
1838
- if (opt.valueName !== undefined && opt.truthy) {
1839
- const className = processStyleRecords(opt.truthy, stateWeights)
1840
- .map((r) => r.hash)
1841
- .join(' ');
1842
- if (className)
1843
- lookupMap[opt.valueName] = className;
1844
- }
1845
- });
1846
- if (Object.keys(lookupMap).length > 0) {
1847
- const entries = Object.entries(lookupMap)
1848
- .map(([k, v]) => `${JSON.stringify(k)}:${JSON.stringify(v)}`)
1849
- .join(',');
1850
- classParts.push(`({${entries}}[${commonTestExpr}] || "")`);
1851
- }
1852
- });
1853
- if (Object.keys(baseConflict).length > 0 ||
1854
- conflictConditionals.length > 0) {
1855
- const ordered = [];
1856
- baseChunks.forEach(({ order, style }) => {
1857
- const conflicting = {};
1858
- Object.entries(style).forEach(([key, value]) => {
1859
- if (conflictingKeys.has(key))
1860
- conflicting[key] = value;
1861
- });
1862
- if (Object.keys(conflicting).length === 0)
1863
- return;
1864
- ordered.push({
1865
- order,
1866
- dimension: {
1867
- type: 'const',
1868
- options: [
1869
- { value: undefined, style: conflicting, label: 'base' },
1870
- ],
1871
- },
1872
- });
1873
- });
1874
- conflictConditionals
1875
- .filter((c) => c.groupId === undefined)
1876
- .forEach((c) => {
1877
- ordered.push({
1878
- order: c.order ?? 0,
1879
- dimension: {
1880
- type: 'std',
1881
- testExpr: c.testString ?? getSource(c.test),
1882
- options: [
1883
- { value: 0, style: c.falsy, label: 'false' },
1884
- { value: 1, style: c.truthy, label: 'true' },
1885
- ],
1886
- },
1887
- });
1888
- });
1889
- const conflictVarGroups = {};
1890
- conflictConditionals.forEach((c) => {
1891
- if (c.groupId !== undefined) {
1892
- if (!conflictVarGroups[c.groupId])
1893
- conflictVarGroups[c.groupId] = [];
1894
- conflictVarGroups[c.groupId].push(c);
1895
- }
1896
- });
1897
- Object.keys(conflictVarGroups).forEach((id) => {
1898
- const groupId = Number(id);
1899
- const opts = conflictVarGroups[groupId];
1900
- if (opts.some((c) => c.valueName === ''))
1901
- return;
1902
- const off = conditionals.find((c) => c.groupId === groupId && c.valueName === '');
1903
- if (off)
1904
- opts.push({ ...off, truthy: {}, falsy: {} });
1905
- });
1906
- Object.entries(conflictVarGroups).forEach(([, opts]) => {
1907
- ordered.push({
1908
- order: opts[0].order ?? 0,
1909
- dimension: {
1910
- type: 'var',
1911
- testExpr: opts[0].testLHS ??
1912
- opts[0].testString ??
1913
- getSource(opts[0].test),
1914
- options: opts.map((opt) => ({
1915
- value: opt.valueName,
1916
- style: opt.truthy,
1917
- label: opt.valueName || 'default',
1918
- })),
1919
- ownKeys: opts[0].ownKeys,
1920
- },
1921
- });
1922
- });
1923
- ordered.sort((a, b) => a.order - b.order);
1924
- const dimensions = ordered.map((o) => o.dimension);
1925
- const joined = dimensions.filter((dim) => dim.type !== 'const').length > 1;
1926
- dimensions.forEach((dim) => {
1927
- if (!joined || dim.type !== 'var' || !dim.ownKeys)
1928
- return;
1929
- const numbers = {};
1930
- dim.options.forEach((opt, index) => {
1931
- numbers[String(opt.value)] = String(index);
1932
- opt.value = String(index);
1933
- });
1934
- dim.testExpr = `(${JSON.stringify(numbers)}[${dim.testExpr}] || "")`;
1935
- });
1936
- const results = {};
1937
- const recurse = (dimIndex, currentStyle, keyParts) => {
1938
- if (dimIndex >= dimensions.length) {
1939
- const className = processStyleRecords(currentStyle, stateWeights)
1940
- .map((r) => r.hash)
1941
- .join(' ');
1942
- if (className)
1943
- results[keyParts.join('__')] = className;
1944
- return;
1945
- }
1946
- const dimension = dimensions[dimIndex];
1947
- dimension.options.forEach((opt) => recurse(dimIndex + 1, (0, utils_1.deepMerge)(currentStyle, opt.style), dimension.type === 'const'
1948
- ? keyParts
1949
- : [...keyParts, String(opt.value)]));
1950
- };
1951
- recurse(0, {}, []);
1952
- const baseConflictClass = Object.keys(baseConflict).length > 0
1953
- ? processStyleRecords(baseConflict, stateWeights)
1954
- .map((r) => r.hash)
1955
- .join(' ')
1956
- : '';
1957
- const masterKeyExpr = dimensions
1958
- .filter((dim) => dim.type !== 'const')
1959
- .map((dim) => dim.type === 'std'
1960
- ? `(${dim.testExpr} ? "1" : "0")`
1961
- : dim.testExpr || '""')
1962
- .join(' + "__" + ');
1963
- classParts.push(`(${JSON.stringify(results)}[${masterKeyExpr || '""'}] || ${baseConflictClass ? JSON.stringify(baseConflictClass) : '""'})`);
1964
- }
1965
- classParts.push(...dynamicClassParts);
1966
- return {
1967
- classParts,
1968
- isOptimizable,
1969
- baseStyle,
1970
- dynamicVars,
1971
- propVarSpreads,
1972
- };
1973
- };
1974
- (0, utils_1.traverse)(ast, {
1975
- JSXOpeningElement({ node }) {
1976
- jsxOpeningElementMap.set(node.span.start, {
1977
- compKey: (0, utils_1.resolveComponentKey)(node.name, resourcePath, localImports),
1978
- attributes: node.attributes,
1979
- });
1980
- },
1981
- MemberExpression({ node }) {
1982
- if (!isVisibleReference(node))
1983
- return;
1984
- if (utils_1.t.isIdentifier(node.object) &&
1985
- (utils_1.t.isIdentifier(node.property) || node.property.type === 'Computed')) {
1986
- const varName = node.object.value;
1987
- const uniqueKey = `${resourcePath}-${varName}`;
1988
- if (node.property.type === 'Computed') {
1989
- const dynExpr = node.property.expression;
1990
- const dynSource = getSource(dynExpr);
1991
- const localStyle = localCreateStyles[varName];
1992
- let hashMap;
1993
- if (localStyle) {
1994
- hashMap = localStyle.hashMap;
1995
- }
1996
- else {
1997
- let hash = scannedTables.createHashTable[uniqueKey];
1998
- if (!hash) {
1999
- hash = mergedCreateTable[varName];
2000
- }
2001
- if (hash) {
2002
- const obj = scannedTables.createObjectTable[hash];
2003
- const atomicMap = scannedTables.createAtomicMapTable[hash];
2004
- if (obj && atomicMap) {
2005
- hashMap = {};
2006
- Object.keys(obj).forEach((key) => {
2007
- if (atomicMap[key]) {
2008
- hashMap[key] = atomicMap[key];
2009
- }
2010
- });
2011
- }
2012
- }
2013
- }
2014
- if (hashMap) {
2015
- replacements.push({
2016
- start: node.span.start - baseByteOffset,
2017
- end: node.span.end - baseByteOffset,
2018
- content: `((${JSON.stringify(hashMap)})[${dynSource}] || {})`,
2019
- });
2020
- }
2021
- return;
2022
- }
2023
- const propName = node.property.value;
2024
- const localStyle = localCreateStyles[varName];
2025
- if (localStyle && localStyle.type === 'create') {
2026
- const atomMap = localStyle.hashMap[propName];
2027
- if (atomMap) {
2028
- replacements.push({
2029
- start: node.span.start - baseByteOffset,
2030
- end: node.span.end - baseByteOffset,
2031
- content: `(${JSON.stringify(atomMap)})`,
2032
- });
2033
- return;
2034
- }
2035
- }
2036
- let hash = scannedTables.createHashTable[uniqueKey];
2037
- if (!hash) {
2038
- hash = mergedCreateTable[varName];
2039
- }
2040
- if (hash) {
2041
- let atomMap;
2042
- if (scannedTables.createAtomicMapTable[hash]) {
2043
- atomMap = scannedTables.createAtomicMapTable[hash][propName];
2044
- }
2045
- if (atomMap) {
2046
- replacements.push({
2047
- start: node.span.start - baseByteOffset,
2048
- end: node.span.end - baseByteOffset,
2049
- content: `(${JSON.stringify(atomMap)})`,
2050
- });
2051
- }
2052
- }
2053
- let themeHash = mergedCreateThemeHashTable[varName];
2054
- if (!themeHash) {
2055
- themeHash = scannedTables.createThemeHashTable[uniqueKey];
2056
- }
2057
- if (themeHash) {
2058
- const atomicMap = scannedTables.createAtomicMapTable[themeHash];
2059
- if (atomicMap && atomicMap[propName]) {
2060
- replacements.push({
2061
- start: node.span.start - baseByteOffset,
2062
- end: node.span.end - baseByteOffset,
2063
- content: `(${JSON.stringify(atomicMap[propName])})`,
2064
- });
2065
- }
2066
- else {
2067
- const cssVarName = (0, zss_engine_1.camelToKebabCase)(propName);
2068
- replacements.push({
2069
- start: node.span.start - baseByteOffset,
2070
- end: node.span.end - baseByteOffset,
2071
- content: `(${JSON.stringify(`var(--${themeHash}-${cssVarName})`)})`,
2072
- });
2073
- }
2074
- }
2075
- let staticHash = mergedCreateStaticHashTable[varName];
2076
- if (!staticHash) {
2077
- staticHash = scannedTables.createStaticHashTable[uniqueKey];
2078
- }
2079
- if (staticHash) {
2080
- const staticObj = scannedTables.createStaticObjectTable[staticHash];
2081
- if (staticObj && staticObj[propName] !== undefined) {
2082
- replacements.push({
2083
- start: node.span.start - baseByteOffset,
2084
- end: node.span.end - baseByteOffset,
2085
- content: `(${JSON.stringify(staticObj[propName])})`,
2086
- });
2087
- }
2088
- }
2089
- }
2090
- },
2091
- Identifier({ node }) {
2092
- if (excludedSpans.has(node.span.start))
2093
- return;
2094
- if (idSpans.has(node.span.start))
2095
- return;
2096
- if (!referenceIdents.references.has(node.span.start))
2097
- return;
2098
- const prefix = referenceIdents.shorthands.has(node.span.start)
2099
- ? `${node.value}: `
2100
- : '';
2101
- const pushReplacement = (content) => {
2102
- replacements.push({
2103
- start: node.span.start - baseByteOffset,
2104
- end: node.span.end - baseByteOffset,
2105
- content: `${prefix}${content}`,
2106
- });
2107
- };
2108
- const styleInfo = localCreateStyles[node.value];
2109
- if (styleInfo) {
2110
- pushReplacement(`(${JSON.stringify(styleInfo.hashMap)})`);
2111
- return;
2112
- }
2113
- const varName = node.value;
2114
- const uniqueKey = `${resourcePath}-${varName}`;
2115
- let hash = mergedCreateTable[varName];
2116
- if (!hash) {
2117
- hash = scannedTables.createHashTable[uniqueKey];
2118
- }
2119
- if (hash) {
2120
- const obj = scannedTables.createObjectTable[hash];
2121
- const atomicMap = scannedTables.createAtomicMapTable[hash];
2122
- if (obj && atomicMap) {
2123
- const hashMap = {};
2124
- Object.keys(obj).forEach((key) => {
2125
- if (atomicMap[key]) {
2126
- hashMap[key] = atomicMap[key];
2127
- }
2128
- });
2129
- pushReplacement(`(${JSON.stringify(hashMap)})`);
2130
- }
2131
- }
2132
- let themeHash = mergedCreateThemeHashTable[varName];
2133
- if (!themeHash) {
2134
- themeHash = scannedTables.createThemeHashTable[uniqueKey];
2135
- }
2136
- if (themeHash) {
2137
- const atomicMap = scannedTables.createAtomicMapTable[themeHash];
2138
- if (atomicMap) {
2139
- pushReplacement(`(${JSON.stringify(atomicMap)})`);
2140
- return;
2141
- }
2142
- }
2143
- let staticHash = mergedCreateStaticHashTable[varName];
2144
- if (!staticHash) {
2145
- staticHash = scannedTables.createStaticHashTable[uniqueKey];
2146
- }
2147
- if (staticHash) {
2148
- const staticObj = scannedTables.createStaticObjectTable[staticHash];
2149
- if (staticObj) {
2150
- pushReplacement(`(${JSON.stringify(staticObj)})`);
2151
- }
2152
- }
2153
- },
2154
- JSXAttribute({ node }) {
2155
- if (node.name.type !== 'Identifier')
2156
- return;
2157
- const attrName = node.name.value;
2158
- if (attrName !== styleProp) {
2159
- let compKey = null;
2160
- for (const [, val] of jsxOpeningElementMap) {
2161
- const found = val.attributes
2162
- .filter((a) => a.type === 'JSXAttribute')
2163
- .find((a) => a.span.start === node.span.start);
2164
- if (found) {
2165
- compKey = val.compKey;
2166
- break;
2167
- }
2168
- }
2169
- if (compKey) {
2170
- if (node.value?.type === 'JSXExpressionContainer')
2171
- assertNoStyleArraySpread(node.value.expression);
2172
- const list = scannedTables.componentPropsTable?.[compKey]?.[attrName];
2173
- if (list &&
2174
- node.value &&
2175
- node.value.type === 'JSXExpressionContainer') {
2176
- const expr = node.value.expression;
2177
- const carrierFor = (subNode, calls) => {
2178
- const vars = [];
2179
- let unresolved = false;
2180
- for (const expression of calls ?? [subNode])
2181
- (0, utils_1.traverse)(expression, {
2182
- CallExpression({ node: call }) {
2183
- if (!isStyleFunctionCall(call))
2184
- return;
2185
- const resolved = resolveDynamicCall(call, true);
2186
- if (!resolved) {
2187
- unresolved = true;
2188
- return;
2189
- }
2190
- vars.push(...resolved.vars);
2191
- },
2192
- });
2193
- if (unresolved)
2194
- return null;
2195
- return `{ ${foldDynamicVars(vars).join(', ')} }`;
2196
- };
2197
- const replaceWithKey = (subNode) => {
2198
- const entries = list.filter((entry) => entry.spanStart === subNode.span.start &&
2199
- entry.filePath === resourcePath);
2200
- if (!entries.length)
2201
- return false;
2202
- let content = '""';
2203
- for (const entry of [...entries].reverse()) {
2204
- let value = JSON.stringify(entry.key);
2205
- if (entry.hasVars) {
2206
- const carrier = carrierFor(subNode, entry.dynamicCalls);
2207
- if (!carrier)
2208
- return false;
2209
- value = `{ key: ${value}, vars: ${carrier} }`;
2210
- }
2211
- const condition = entry.conditions
2212
- ?.map(({ test, truthy }) => `${truthy ? '' : '!'}(${getSource(test)})`)
2213
- .join(' && ');
2214
- content = condition
2215
- ? `((${condition}) ? ${value} : ${content})`
2216
- : value;
2217
- processStyleRecords(entry.styleObj);
2218
- }
2219
- replacements.push({
2220
- start: subNode.span.start - baseByteOffset,
2221
- end: subNode.span.end - baseByteOffset,
2222
- content,
2223
- });
2224
- return true;
2225
- };
2226
- (0, utils_1.traverse)(expr, {
2227
- MemberExpression({ node: subNode }) {
2228
- if (replaceWithKey(subNode)) {
2229
- excludeSubtreeSpans(subNode);
2230
- }
2231
- },
2232
- ArrayExpression({ node: subNode }) {
2233
- if (replaceWithKey(subNode)) {
2234
- excludeSubtreeSpans(subNode);
2235
- }
2236
- },
2237
- CallExpression({ node: subNode }) {
2238
- if (replaceWithKey(subNode)) {
2239
- excludeSubtreeSpans(subNode);
2240
- }
2241
- },
2242
- });
2243
- }
2244
- }
2245
- return;
2246
- }
2247
- if (!node.value || node.value.type !== 'JSXExpressionContainer')
2248
- return;
2249
- const expr = node.value.expression;
2250
- const args = expr.type === 'ArrayExpression'
2251
- ? expr.elements
2252
- .filter((el) => el != null)
2253
- .map((el) => {
2254
- if (el.spread)
2255
- throwCompilationError(spreadStyleMessage(getSource(el.expression)), el.expression);
2256
- return { expression: el.expression };
2257
- })
2258
- : [{ expression: expr }];
2259
- const dynamicClassParts = [];
2260
- const existingStyleParts = [];
2261
- let attributes = [];
2262
- for (const [, val] of jsxOpeningElementMap) {
2263
- const found = val.attributes
2264
- .filter((a) => a.type === 'JSXAttribute')
2265
- .find((a) => a.span.start === node.span.start);
2266
- if (found) {
2267
- attributes = val.attributes;
2268
- break;
2269
- }
2270
- }
2271
- const classNameAttr = attributes.find((attr) => attr.type === 'JSXAttribute' &&
2272
- attr.name.type === 'Identifier' &&
2273
- attr.name.value === 'className');
2274
- let existingClassExpr = '';
2275
- if (classNameAttr) {
2276
- replacements.push({
2277
- start: classNameAttr.span.start - baseByteOffset,
2278
- end: classNameAttr.span.end - baseByteOffset,
2279
- content: '',
2280
- });
2281
- if (classNameAttr.value?.type === 'StringLiteral') {
2282
- existingClassExpr = JSON.stringify(classNameAttr.value.value);
2283
- }
2284
- else if (classNameAttr.value?.type === 'JSXExpressionContainer') {
2285
- existingClassExpr = `(${deferSource(classNameAttr.value.expression)})`;
2286
- }
2287
- }
2288
- const styleAttrExisting = attributes.find((attr) => attr.type === 'JSXAttribute' &&
2289
- attr.name.type === 'Identifier' &&
2290
- attr.name.value === 'style');
2291
- let existingStyleExpr = '';
2292
- if (styleAttrExisting) {
2293
- replacements.push({
2294
- start: styleAttrExisting.span.start - baseByteOffset,
2295
- end: styleAttrExisting.span.end - baseByteOffset,
2296
- content: '',
2297
- });
2298
- if (styleAttrExisting.value?.type === 'JSXExpressionContainer') {
2299
- const innerExpr = styleAttrExisting.value?.expression;
2300
- if (innerExpr.type === 'ObjectExpression') {
2301
- for (const property of innerExpr.properties) {
2302
- const token = deferProperty(property);
2303
- if (token)
2304
- existingStyleParts.push(token);
2305
- }
2306
- }
2307
- else {
2308
- existingStyleExpr = `...(${deferSource(innerExpr)})`;
2309
- }
2310
- }
2311
- }
2312
- const { classParts, isOptimizable, baseStyle, dynamicVars, propVarSpreads, } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
2313
- if (!isOptimizable) {
2314
- throwCompilationError(`Plumeria: Dynamic or unresolvable style object "${getSource(expr)}" is not supported.`, expr);
2315
- }
2316
- const styleParts = [
2317
- ...existingStyleParts,
2318
- ...foldDynamicVars(dynamicVars),
2319
- ...propVarSpreads,
2320
- ];
2321
- const styleAttr = styleParts.length > 0 || existingStyleExpr
2322
- ? ` style={{ ${[existingStyleExpr, ...styleParts].filter(Boolean).join(', ')} }}`
2323
- : '';
2324
- if (isOptimizable &&
2325
- (args.length > 0 ||
2326
- Object.keys(baseStyle).length > 0 ||
2327
- dynamicClassParts.length > 0)) {
2328
- const replacement = classParts.length > 0 ? classParts.join(' + " " + ') : '""';
2329
- replacements.push({
2330
- start: node.span.start - baseByteOffset,
2331
- end: node.span.end - baseByteOffset,
2332
- content: `className={${replacement}}${styleAttr}`,
2333
- });
2334
- }
2335
- else {
2336
- const keptClass = existingClassExpr
2337
- ? `className={${existingClassExpr}}`
2338
- : '';
2339
- replacements.push({
2340
- start: node.span.start - baseByteOffset,
2341
- end: node.span.end - baseByteOffset,
2342
- content: `${keptClass}${styleAttr}`,
2343
- });
2344
- }
2345
- },
2346
- CallExpression({ node }) {
2347
- const callee = node.callee;
2348
- let isUseCall = false;
2349
- if (utils_1.t.isMemberExpression(callee) &&
2350
- utils_1.t.isIdentifier(callee.object) &&
2351
- utils_1.t.isIdentifier(callee.property)) {
2352
- const objectName = callee.object.value;
2353
- const propertyName = callee.property.value;
2354
- if (localCreateStyles[objectName]?.functions?.[propertyName] ||
2355
- createFunctionImportMap[objectName]?.[propertyName]) {
2356
- dynamicFnCalls.push(node);
2357
- }
2358
- const alias = plumeriaAliases[objectName];
2359
- if (alias === 'NAMESPACE' && propertyName === 'use') {
2360
- isUseCall = true;
2361
- }
2362
- }
2363
- else if (utils_1.t.isIdentifier(callee)) {
2364
- const calleeName = callee.value;
2365
- const originalName = plumeriaAliases[calleeName];
2366
- if (originalName === 'use') {
2367
- isUseCall = true;
2368
- }
2369
- }
2370
- if (!isUseCall)
2371
- return;
2372
- const args = node.arguments;
2373
- for (const arg of args) {
2374
- const expr = arg.expression;
2375
- if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
2376
- continue;
2377
- const callee = expr.callee;
2378
- if (!utils_1.t.isIdentifier(callee.object) ||
2379
- !utils_1.t.isIdentifier(callee.property))
2380
- continue;
2381
- const varName = callee.object.value;
2382
- const propKey = callee.property.value;
2383
- const styleInfo = localCreateStyles[varName];
2384
- if (styleInfo?.functions?.[propKey]) {
2385
- throwCompilationError(`Plumeria: css.use(${getSource(expr)}) does not support dynamic function keys.`, expr);
2386
- }
2387
- }
2388
- const { classParts, isOptimizable } = buildClassParts(args);
2389
- if (isOptimizable) {
2390
- const replacement = classParts.length > 0 ? classParts.join(' + " " + ') : '""';
2391
- replacements.push({
2392
- start: node.span.start - baseByteOffset,
2393
- end: node.span.end - baseByteOffset,
2394
- content: replacement,
2395
- });
2396
- }
2397
- else {
2398
- throwCompilationError(`Plumeria: Dynamic or unresolvable style object "${getSource(node)}" is not supported.`, node);
2399
- }
2400
- },
2401
- });
2402
- for (const { name, node } of components) {
2403
- const props = scannedTables.componentPropsTable?.[`${resourcePath}-${name}`];
2404
- for (const propName of Object.keys(props ?? {})) {
2405
- if (appliedStyleProps.has(`${name}:${propName}`)) {
2406
- continue;
2407
- }
2408
- throwCompilationError(`Plumeria: "${propName}" is a style received through a prop but is never applied ` +
2409
- `to ${styleProp} or css.use() here. Apply it on an element this component renders; ` +
2410
- `a style prop cannot be passed on to another component.`, node);
2411
- }
2412
- }
2413
- const buildExportedInit = (info) => {
2414
- const keys = Object.keys(info.obj);
2415
- if (isProduction || keys.length === 0) {
2416
- return JSON.stringify('');
2417
- }
2418
- const head = JSON.stringify(`Plumeria: "${info.name}.`);
2419
- const tail = JSON.stringify(`" was read at runtime. The file that read it was not compiled ` +
2420
- `because it does not reference "@plumeria/core" — add ` +
2421
- `import '@plumeria/core'; to it (see the stack below). Defined in ` +
2422
- `${path.relative(process.cwd(), resourcePath)}.`);
2423
- return (`(()=>{const k=new Set(${JSON.stringify(keys)});` +
2424
- `return new Proxy({},{get(t,p){` +
2425
- `if(typeof p==="string"&&k.has(p))throw new Error(${head}+p+${tail});` +
2426
- `return t[p];}});})()`);
2427
- };
2428
- Object.values(localCreateStyles).forEach((info) => {
2429
- if (info.isExported) {
2430
- replacements.push({
2431
- start: info.initSpan.start,
2432
- end: info.initSpan.end,
2433
- content: buildExportedInit(info),
2434
- });
2435
- }
2436
- else {
2437
- replacements.push({
2438
- start: info.declSpan.start,
2439
- end: info.declSpan.end,
2440
- content: '',
2441
- });
2442
- }
2443
- });
2444
- dynamicFnCalls.forEach((call) => {
2445
- const start = call.span.start - baseByteOffset;
2446
- const end = call.span.end - baseByteOffset;
2447
- const isResolved = replacements.some((r) => r.start <= start && r.end >= end);
2448
- if (!isResolved) {
2449
- throwCompilationError(`Plumeria: ${getSource(call)} is only supported in the ${styleProp} prop. ` +
2450
- `A dynamic style function resolves to a class name and a CSS variable on the element itself, ` +
2451
- `so it cannot be passed through another prop or read as a value.`, call);
2452
- }
2453
- });
2454
- for (const deferred of deferredSources) {
2455
- let cursor = deferred.start;
2456
- const pieces = [];
2457
- for (const replacement of [...replacements].sort((a, b) => a.start - b.start || b.end - a.end)) {
2458
- if (replacement.start < cursor || replacement.end > deferred.end)
2459
- continue;
2460
- pieces.push(sourceBuffer.subarray(cursor, replacement.start).toString('utf-8'), replacement.content);
2461
- cursor = replacement.end;
2462
- }
2463
- pieces.push(sourceBuffer.subarray(cursor, deferred.end).toString('utf-8'));
2464
- const content = pieces.join('');
2465
- for (const replacement of replacements)
2466
- replacement.content = replacement.content.replaceAll(deferred.token, content);
2467
- }
2468
- const buffer = Buffer.from(source);
2469
- let offset = 0;
2470
- const parts = [];
2471
- replacements
2472
- .sort((a, b) => a.start - b.start || b.end - a.end)
2473
- .forEach((r) => {
2474
- if (r.start < offset)
2475
- return;
2476
- parts.push(buffer.subarray(offset, r.start));
2477
- parts.push(Buffer.from(r.content));
2478
- offset = r.end;
102
+ const { code: transformedSource, sheets: extractedSheets } = await (0, utils_1.transformSource)({
103
+ source,
104
+ moduleId: resourcePath,
105
+ filePath: resourcePath,
106
+ root: process.cwd(),
107
+ styleProp,
108
+ propertyPolicy,
109
+ isDev: !isProduction,
110
+ collectOndemandSheets: !isProduction,
111
+ addDependency: (depPath) => this.addDependency(depPath),
2479
112
  });
2480
- parts.push(buffer.subarray(offset));
2481
- const transformedSource = Buffer.concat(parts).toString();
2482
113
  const optInCSS = await (0, utils_1.optimizer)(extractedSheets.join(''));
2483
114
  let relativeImportPath = path.relative(path.dirname(resourcePath), VIRTUAL_FILE_PATH);
2484
115
  relativeImportPath = relativeImportPath.replace(/\\/g, '/');