@bamboocss/parser 1.14.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FileSystemRefreshResult, Project as Project$1, ProjectOptions as ProjectOptions$1, SourceFile } from "ts-morph";
2
2
  import { Context, ParserOptions, StyleDecoder, Stylesheet } from "@bamboocss/core";
3
- import { ArtifactId, BambooHooks, ConfigTsOptions, CssArtifactType, JsxFactoryResultTransform, LoadConfigResult, ParserResultConfigureOptions, ParserResultInterface, ResultItem, Runtime, SpecFile, SpecType, SpecTypeMap } from "@bamboocss/types";
3
+ import { ArtifactId, BambooHooks, ConfigTsOptions, CssArtifactType, LoadConfigResult, ParserResultConfigureOptions, ParserResultInterface, ResultItem, Runtime, SpecFile, SpecType, SpecTypeMap } from "@bamboocss/types";
4
4
 
5
5
  //#region ../generator/dist/index.d.cts
6
6
  //#region src/generator.d.ts
@@ -93,6 +93,20 @@ declare class Generator extends Context {
93
93
  */
94
94
  private getAlwaysKeptTokenVars;
95
95
  getParserCss: (decoder: StyleDecoder) => string;
96
+ /**
97
+ * The grouped class names this build emitted a rule for.
98
+ *
99
+ * Derived from the encoder rather than the decoder, so it is available as soon as
100
+ * extraction finishes and before a stylesheet exists. Both sides go through
101
+ * `groupClassName`, which is the same function the browser runtime calls — a registry
102
+ * built any other way would be a third spelling of a name that already has two.
103
+ *
104
+ * Unescaped, unlike `StyleDecoder`'s class names: this is compared against what `css()`
105
+ * returns into a `class` attribute, not against a selector. A grouped class is an opaque
106
+ * hash, so the two only differ in principle, but the principle is the one that matters
107
+ * here — the registry is only useful if it holds exactly what the runtime will ask about.
108
+ */
109
+ getGroupRegistry: () => string[];
96
110
  getCss: (stylesheet?: Stylesheet) => string;
97
111
  /**
98
112
  * Get CSS for a specific layer from the stylesheet
@@ -119,29 +133,94 @@ declare class Generator extends Context {
119
133
  * Get CSS for a specific theme
120
134
  */
121
135
  //#endregion
136
+ //#region src/unresolved-styles.d.ts
137
+ interface UnresolvedStyle {
138
+ /** The property the build could not resolve, or `undefined` when only the count differs. */
139
+ prop?: string;
140
+ filePath: string;
141
+ line: number;
142
+ column: number;
143
+ /**
144
+ * How the build lost the call:
145
+ *
146
+ * - `unresolvable-value` — a value it could not evaluate.
147
+ * - `missing-property` — a key that never arrived in the box tree at all.
148
+ * - `unenumerable-keys` — a spread or computed key, so it cannot say what the call sets.
149
+ * - `ambiguous-merge` — two arguments setting one property, which it cannot tell from a
150
+ * pair of alternatives.
151
+ * - `too-many-combinations` — more ternary branches than it will enumerate.
152
+ */
153
+ reason: 'unresolvable-value' | 'missing-property' | 'unenumerable-keys' | 'ambiguous-merge' | 'too-many-combinations';
154
+ }
155
+ /**
156
+ * Every property of a `css()` call that will not reach the stylesheet.
157
+ *
158
+ * Only meaningful under `cssMode: 'grouped'`, where one class names the whole call: a
159
+ * property the build cannot resolve does not merely go missing, it changes the class, and
160
+ * the element renders with no styles at all. Under `atomic` the same call loses one
161
+ * declaration and keeps the rest, which is why this is not reported there.
162
+ */
163
+ declare const findUnresolvedStyles: (item: ResultItem) => UnresolvedStyle[];
164
+ //#endregion
122
165
  //#region src/parser-result.d.ts
123
166
  declare class ParserResult implements ParserResultInterface {
124
167
  private context;
125
168
  /** Ordered list of all ResultItem */
126
169
  all: ResultItem[];
127
- jsx: Set<ResultItem>;
128
170
  css: Set<ResultItem>;
129
171
  cva: Set<ResultItem>;
130
172
  sva: Set<ResultItem>;
131
173
  token: Set<ResultItem>;
174
+ viewTransition: Set<ResultItem>;
132
175
  recipe: Map<string, Set<ResultItem>>;
133
176
  pattern: Map<string, Set<ResultItem>>;
134
177
  filePath: string | undefined;
135
178
  encoder: ParserOptions['encoder'];
179
+ /**
180
+ * `css()` calls whose styles the build could not fully see.
181
+ *
182
+ * Only collected under `cssMode: 'grouped'`, where one class names the whole call, so a
183
+ * property the build cannot resolve changes the class rather than dropping a declaration
184
+ * from it — and the element renders with no styles at all. Under `atomic` the same call
185
+ * keeps everything the build did resolve, which is not worth interrupting a build over.
186
+ */
187
+ unresolved: UnresolvedStyle[];
136
188
  constructor(context: ParserOptions, encoder?: ParserOptions['encoder']);
189
+ /**
190
+ * Record a call whose styles the build could not fully see, at the call's own position.
191
+ *
192
+ * Used for losses the box tree cannot show — a ternary past the combination cap emits
193
+ * fragments rather than whole objects, and every individual box in it resolved fine.
194
+ */
195
+ private reportUnresolved;
137
196
  append(result: ResultItem): ResultItem;
138
197
  set(name: 'cva' | 'css' | 'sva' | 'token', result: ResultItem): void;
139
198
  setCss(result: ResultItem): void;
199
+ /**
200
+ * How many arguments the call this result came from was written with.
201
+ *
202
+ * Returns 1 for anything that is not a call — a JSX element, or a box that lost its node —
203
+ * since the question only separates operands from branches and neither has operands.
204
+ */
205
+ private callArgumentCount;
140
206
  setCva(result: ResultItem): void;
141
207
  setSva(result: ResultItem): void;
142
208
  setToken(result: ResultItem): void;
143
- setJsx(result: ResultItem): void;
209
+ setViewTransition(result: ResultItem): void;
144
210
  setPattern(name: string, result: ResultItem): void;
211
+ /**
212
+ * Whether the group encoded for this result is the one the runtime will ask for.
213
+ *
214
+ * True only when the build saw the whole thing at once: one style object, with every
215
+ * value in it resolved. Several objects means the runtime merges them into a call this
216
+ * never encoded — `setCss` reconstructs those combinations, and nothing else does — and
217
+ * an unresolved value means the merge would not have matched anyway.
218
+ *
219
+ * Answering "no" costs a call site its atomic rules, which is CSS that duplicates the
220
+ * group. Answering a wrong "yes" costs the element every style it has, so this is
221
+ * deliberately conservative.
222
+ */
223
+ private groupIsExact;
145
224
  setRecipe(recipeName: string, result: ResultItem): void;
146
225
  isEmpty(): boolean;
147
226
  setFilePath(filePath: string): this;
@@ -152,7 +231,7 @@ declare class ParserResult implements ParserResultInterface {
152
231
  cva: ResultItem[];
153
232
  sva: ResultItem[];
154
233
  token: ResultItem[];
155
- jsx: ResultItem[];
234
+ viewTransition: ResultItem[];
156
235
  recipe: {
157
236
  [k: string]: ResultItem[];
158
237
  };
@@ -163,7 +242,7 @@ declare class ParserResult implements ParserResultInterface {
163
242
  }
164
243
  //#endregion
165
244
  //#region src/parser.d.ts
166
- declare function createParser(context: ParserOptions): (sourceFile: SourceFile | undefined, encoder?: Generator["encoder"], options?: ParserResultConfigureOptions & Partial<JsxFactoryResultTransform>) => ParserResult | undefined;
245
+ declare function createParser(context: ParserOptions): (sourceFile: SourceFile | undefined, encoder?: Generator["encoder"], options?: ParserResultConfigureOptions) => ParserResult | undefined;
167
246
  //#endregion
168
247
  //#region src/project.d.ts
169
248
  interface ProjectOptions extends ProjectOptions$1 {
@@ -248,4 +327,4 @@ declare class Project {
248
327
  classify: (fileMap: Map<string, ParserResultInterface>) => import("@bamboocss/types").ClassifyReport;
249
328
  }
250
329
  //#endregion
251
- export { ParserResult, Project, ProjectOptions };
330
+ export { ParserResult, Project, ProjectOptions, type UnresolvedStyle, findUnresolvedStyles };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Node, Project as Project$1, ScriptKind, ts } from "ts-morph";
2
2
  import { box, clearBoxNodeCache, extract, unbox } from "@bamboocss/extractor";
3
- import { BambooError, astish, compact, getOrCreateSet, patternFns } from "@bamboocss/shared";
3
+ import { BambooError, compact, getOrCreateSet, patternFns } from "@bamboocss/shared";
4
4
  import { logger } from "@bamboocss/logger";
5
5
  import { match } from "ts-pattern";
6
6
  import { resolveTsPathPattern } from "@bamboocss/config/ts-path";
@@ -43,7 +43,7 @@ function classifyProject(ctx, resultMap) {
43
43
  const processPattern = (opts) => {
44
44
  const { boxNode, data, item, filepath, localMaps } = opts;
45
45
  const name = item.componentName;
46
- const pattern = ctx.patterns.details.find((p) => p.match.test(name) || p.baseName === name);
46
+ const pattern = ctx.patterns.details.find((p) => p.baseName === name);
47
47
  if (!pattern) return;
48
48
  const cssObj = pattern.config.transform?.(data || {}, patternFns) ?? {};
49
49
  const newItem = {
@@ -75,7 +75,7 @@ function classifyProject(ctx, resultMap) {
75
75
  contains: [],
76
76
  debug: Reflect.has(item, "debug")
77
77
  };
78
- if (item.type === "pattern" || item.type === "jsx-pattern") return processPattern({
78
+ if (item.type === "pattern") return processPattern({
79
79
  boxNode: item.box,
80
80
  data: item.data[0],
81
81
  item: componentReportItem,
@@ -200,14 +200,6 @@ function classifyProject(ctx, resultMap) {
200
200
  resultMap.forEach((parserResult, filepath) => {
201
201
  if (parserResult.isEmpty()) return;
202
202
  const localMaps = createReportMaps();
203
- const componentFn = (item) => {
204
- processResultItemFn({
205
- item,
206
- filepath,
207
- localMaps,
208
- type: "component"
209
- });
210
- };
211
203
  const functionFn = (item) => {
212
204
  processResultItemFn({
213
205
  item,
@@ -216,7 +208,6 @@ function classifyProject(ctx, resultMap) {
216
208
  type: "function"
217
209
  });
218
210
  };
219
- parserResult.jsx.forEach(componentFn);
220
211
  parserResult.css.forEach(functionFn);
221
212
  parserResult.cva.forEach(functionFn);
222
213
  parserResult.pattern.forEach((itemList) => {
@@ -465,6 +456,120 @@ function getImportDeclarations(context, sourceFile) {
465
456
  return importDeclarations;
466
457
  }
467
458
  //#endregion
459
+ //#region src/unresolved-styles.ts
460
+ /**
461
+ * Whether every box under this one carries a value the build can actually see.
462
+ *
463
+ * Mirrors `isStaticBox` in `@bamboocss/vite`, which asks the same question to decide
464
+ * whether a call is safe to fold. Duplicated rather than shared for now because the fold's
465
+ * copy also answers questions about ternaries that a diagnostic does not care about;
466
+ * unifying them is worth doing when the fold's detection moves out of the vite package.
467
+ */
468
+ const findUnresolvable = (node, path, out, seen = /* @__PURE__ */ new Set()) => {
469
+ if (!node || seen.has(node)) return;
470
+ seen.add(node);
471
+ if (box.isUnresolvable(node)) {
472
+ out.push(path.join("."));
473
+ return;
474
+ }
475
+ if (box.isConditional(node)) return;
476
+ if (box.isLiteral(node) && node.value === void 0) {
477
+ if (Node.isTemplateExpression(node.getNode())) out.push(path.join("."));
478
+ return;
479
+ }
480
+ if (box.isMap(node)) {
481
+ for (const [key, child] of node.value) findUnresolvable(child, [...path, key], out, seen);
482
+ return;
483
+ }
484
+ if (box.isArray(node)) node.value.forEach((child, index) => findUnresolvable(child, [...path, String(index)], out, seen));
485
+ };
486
+ /**
487
+ * Property names written at the top level of the call's own object literal.
488
+ *
489
+ * A key whose value the extractor could not evaluate at all is not boxed as
490
+ * `unresolvable` — `maybeBoxNode` returns nothing and the pair is never recorded
491
+ * (`get-object-literal-expression-prop-pairs.ts` has no fallback), so the property
492
+ * disappears with no trace in the box tree. Reading the source back is the only way to
493
+ * notice, and it is why `css({ color: getColor() })` needs this and not just the walk above.
494
+ *
495
+ * Returns `undefined` only when the argument is not a single object literal at all, so the
496
+ * caller reports nothing rather than something wrong.
497
+ */
498
+ const writtenProps = (node) => {
499
+ let literal = node;
500
+ if (literal && Node.isCallExpression(literal)) {
501
+ const args = literal.getArguments();
502
+ if (args.length !== 1) return void 0;
503
+ literal = args[0];
504
+ }
505
+ if (!literal || !Node.isObjectLiteralExpression(literal)) return void 0;
506
+ const names = [];
507
+ let uncertain = false;
508
+ for (const property of literal.getProperties()) {
509
+ if (Node.isPropertyAssignment(property) || Node.isShorthandPropertyAssignment(property)) {
510
+ const name = property.getName();
511
+ if (name.startsWith("[")) {
512
+ uncertain = true;
513
+ continue;
514
+ }
515
+ names.push(name.replace(/^['"]|['"]$/g, ""));
516
+ continue;
517
+ }
518
+ uncertain = true;
519
+ }
520
+ return {
521
+ names,
522
+ uncertain
523
+ };
524
+ };
525
+ /**
526
+ * Every property of a `css()` call that will not reach the stylesheet.
527
+ *
528
+ * Only meaningful under `cssMode: 'grouped'`, where one class names the whole call: a
529
+ * property the build cannot resolve does not merely go missing, it changes the class, and
530
+ * the element renders with no styles at all. Under `atomic` the same call loses one
531
+ * declaration and keeps the rest, which is why this is not reported there.
532
+ */
533
+ const findUnresolvedStyles = (item) => {
534
+ const boxNode = item.box;
535
+ if (!boxNode) return [];
536
+ const node = boxNode.getNode();
537
+ const sourceFile = node?.getSourceFile();
538
+ if (!node || !sourceFile) return [];
539
+ const found = [];
540
+ findUnresolvable(boxNode, [], found);
541
+ const losses = found.map((prop) => ({
542
+ prop: prop || void 0,
543
+ reason: "unresolvable-value"
544
+ }));
545
+ const written = writtenProps(node);
546
+ if (written) {
547
+ const resolved = /* @__PURE__ */ new Set();
548
+ for (const entry of item.data) if (entry && typeof entry === "object") for (const key of Object.keys(entry)) resolved.add(key);
549
+ if (box.isMap(boxNode)) for (const key of boxNode.value.keys()) resolved.add(key);
550
+ for (const prop of written.names) if (!resolved.has(prop)) losses.push({
551
+ prop,
552
+ reason: "missing-property"
553
+ });
554
+ if (written.uncertain && !hasKeyOutside(resolved, written.names)) losses.push({ reason: "unenumerable-keys" });
555
+ }
556
+ if (!losses.length) return [];
557
+ const { line, column } = sourceFile.getLineAndColumnAtPos(node.getStart());
558
+ const at = {
559
+ filePath: sourceFile.getFilePath(),
560
+ line,
561
+ column
562
+ };
563
+ return losses.map((loss) => ({
564
+ ...at,
565
+ ...loss
566
+ }));
567
+ };
568
+ const hasKeyOutside = (resolved, names) => {
569
+ for (const key of resolved) if (!names.includes(key)) return true;
570
+ return false;
571
+ };
572
+ //#endregion
468
573
  //#region src/parser-result.ts
469
574
  function cartesian(arrays) {
470
575
  if (arrays.length === 0) return [[]];
@@ -476,19 +581,46 @@ var ParserResult = class {
476
581
  context;
477
582
  /** Ordered list of all ResultItem */
478
583
  all = [];
479
- jsx = /* @__PURE__ */ new Set();
480
584
  css = /* @__PURE__ */ new Set();
481
585
  cva = /* @__PURE__ */ new Set();
482
586
  sva = /* @__PURE__ */ new Set();
483
587
  token = /* @__PURE__ */ new Set();
588
+ viewTransition = /* @__PURE__ */ new Set();
484
589
  recipe = /* @__PURE__ */ new Map();
485
590
  pattern = /* @__PURE__ */ new Map();
486
591
  filePath;
487
592
  encoder;
593
+ /**
594
+ * `css()` calls whose styles the build could not fully see.
595
+ *
596
+ * Only collected under `cssMode: 'grouped'`, where one class names the whole call, so a
597
+ * property the build cannot resolve changes the class rather than dropping a declaration
598
+ * from it — and the element renders with no styles at all. Under `atomic` the same call
599
+ * keeps everything the build did resolve, which is not worth interrupting a build over.
600
+ */
601
+ unresolved = [];
488
602
  constructor(context, encoder) {
489
603
  this.context = context;
490
604
  this.encoder = encoder ?? context.encoder;
491
605
  }
606
+ /**
607
+ * Record a call whose styles the build could not fully see, at the call's own position.
608
+ *
609
+ * Used for losses the box tree cannot show — a ternary past the combination cap emits
610
+ * fragments rather than whole objects, and every individual box in it resolved fine.
611
+ */
612
+ reportUnresolved(result, reason) {
613
+ const node = result.box?.getNode();
614
+ const sourceFile = node?.getSourceFile();
615
+ if (!node || !sourceFile) return;
616
+ const { line, column } = sourceFile.getLineAndColumnAtPos(node.getStart());
617
+ this.unresolved.push({
618
+ filePath: sourceFile.getFilePath(),
619
+ line,
620
+ column,
621
+ reason
622
+ });
623
+ }
492
624
  append(result) {
493
625
  this.all.push(result);
494
626
  return result;
@@ -514,24 +646,36 @@ var ParserResult = class {
514
646
  this.css.add(this.append(Object.assign({ type: "css" }, result)));
515
647
  const encoder = this.encoder;
516
648
  const grouped = this.context.config.cssMode === "grouped";
517
- if (!grouped || result.data.length <= 1) {
518
- result.data.forEach((obj) => grouped ? encoder.processGrouped(obj) : encoder.processAtomic(obj));
649
+ const data = result.data.some(Array.isArray) ? result.data.flatMap((obj) => Array.isArray(obj) ? obj : [obj]) : result.data;
650
+ if (grouped) {
651
+ const unresolved = findUnresolvedStyles(result);
652
+ if (unresolved.length) {
653
+ this.unresolved.push(...unresolved);
654
+ data.forEach((obj) => encoder.processAtomic(obj));
655
+ }
656
+ }
657
+ if (!grouped || data.length <= 1) {
658
+ data.forEach((obj) => grouped ? encoder.processGrouped(obj) : encoder.processAtomic(obj));
519
659
  return;
520
660
  }
521
661
  const keyCounts = /* @__PURE__ */ new Map();
522
- for (const obj of result.data) for (const key of Object.keys(obj)) keyCounts.set(key, (keyCounts.get(key) || 0) + 1);
662
+ for (const obj of data) for (const key of Object.keys(obj)) keyCounts.set(key, (keyCounts.get(key) || 0) + 1);
523
663
  if (!Array.from(keyCounts.values()).some((c) => c > 1)) {
524
- encoder.processGrouped(Object.assign({}, ...result.data));
664
+ encoder.processGroupedMerge(data);
525
665
  return;
526
666
  }
667
+ if (this.callArgumentCount(result) > 1) {
668
+ this.reportUnresolved(result, "ambiguous-merge");
669
+ data.forEach((obj) => encoder.processAtomic(obj));
670
+ }
527
671
  const overlappingKeys = /* @__PURE__ */ new Set();
528
672
  keyCounts.forEach((count, key) => {
529
673
  if (count > 1) overlappingKeys.add(key);
530
674
  });
531
- const base = {};
675
+ const baseEntries = [];
532
676
  const branchEntries = [];
533
- for (const obj of result.data) if (Object.keys(obj).some((k) => overlappingKeys.has(k))) branchEntries.push(obj);
534
- else Object.assign(base, obj);
677
+ for (const obj of data) if (Object.keys(obj).some((k) => overlappingKeys.has(k))) branchEntries.push(obj);
678
+ else baseEntries.push(obj);
535
679
  const branchGroups = /* @__PURE__ */ new Map();
536
680
  for (const entry of branchEntries) {
537
681
  const keySet = Object.keys(entry).sort().join("\0");
@@ -541,10 +685,24 @@ var ParserResult = class {
541
685
  }
542
686
  const groupArrays = Array.from(branchGroups.values());
543
687
  if (groupArrays.reduce((acc, g) => acc * g.length, 1) > 32) {
544
- result.data.forEach((obj) => encoder.processGrouped(obj));
688
+ this.reportUnresolved(result, "too-many-combinations");
689
+ data.forEach((obj) => {
690
+ encoder.processGrouped(obj);
691
+ encoder.processAtomic(obj);
692
+ });
545
693
  return;
546
694
  }
547
- for (const combo of cartesian(groupArrays)) encoder.processGrouped(Object.assign({}, base, ...combo));
695
+ for (const combo of cartesian(groupArrays)) encoder.processGroupedMerge([...baseEntries, ...combo]);
696
+ }
697
+ /**
698
+ * How many arguments the call this result came from was written with.
699
+ *
700
+ * Returns 1 for anything that is not a call — a JSX element, or a box that lost its node —
701
+ * since the question only separates operands from branches and neither has operands.
702
+ */
703
+ callArgumentCount(result) {
704
+ const node = result.box?.getNode();
705
+ return node && Node.isCallExpression(node) ? node.getArguments().length : 1;
548
706
  }
549
707
  setCva(result) {
550
708
  this.cva.add(this.append(Object.assign({ type: "cva" }, result)));
@@ -559,11 +717,10 @@ var ParserResult = class {
559
717
  setToken(result) {
560
718
  this.token.add(this.append(Object.assign({ type: "token" }, result)));
561
719
  }
562
- setJsx(result) {
563
- this.jsx.add(this.append(Object.assign({ type: "jsx" }, result)));
720
+ setViewTransition(result) {
721
+ this.viewTransition.add(this.append(Object.assign({ type: "viewTransition" }, result)));
564
722
  const encoder = this.encoder;
565
- const grouped = this.context.config.cssMode === "grouped";
566
- result.data.forEach((obj) => encoder.processStyleProps(obj, grouped));
723
+ result.data.forEach((obj) => encoder.processViewTransition(obj));
567
724
  }
568
725
  setPattern(name, result) {
569
726
  getOrCreateSet(this.pattern, name).add(this.append(Object.assign({
@@ -571,7 +728,25 @@ var ParserResult = class {
571
728
  name
572
729
  }, result)));
573
730
  const encoder = this.encoder;
574
- result.data.forEach((obj) => encoder.processPattern(name, obj, result.type ?? "pattern", result.name));
731
+ const grouped = this.context.config.cssMode === "grouped";
732
+ result.data.forEach((obj) => encoder.processPattern(name, obj, grouped));
733
+ if (grouped && !this.groupIsExact(result)) result.data.forEach((obj) => encoder.processPattern(name, obj, false));
734
+ }
735
+ /**
736
+ * Whether the group encoded for this result is the one the runtime will ask for.
737
+ *
738
+ * True only when the build saw the whole thing at once: one style object, with every
739
+ * value in it resolved. Several objects means the runtime merges them into a call this
740
+ * never encoded — `setCss` reconstructs those combinations, and nothing else does — and
741
+ * an unresolved value means the merge would not have matched anyway.
742
+ *
743
+ * Answering "no" costs a call site its atomic rules, which is CSS that duplicates the
744
+ * group. Answering a wrong "yes" costs the element every style it has, so this is
745
+ * deliberately conservative.
746
+ */
747
+ groupIsExact(result) {
748
+ if (result.data.length !== 1) return false;
749
+ return findUnresolvedStyles(result).length === 0;
575
750
  }
576
751
  setRecipe(recipeName, result) {
577
752
  getOrCreateSet(this.recipe, recipeName).add(this.append(Object.assign({ type: "recipe" }, result)));
@@ -600,7 +775,7 @@ var ParserResult = class {
600
775
  result.cva.forEach((item) => this.cva.add(this.append(item)));
601
776
  result.sva.forEach((item) => this.sva.add(this.append(item)));
602
777
  result.token.forEach((item) => this.token.add(this.append(item)));
603
- result.jsx.forEach((item) => this.jsx.add(this.append(item)));
778
+ result.viewTransition.forEach((item) => this.viewTransition.add(this.append(item)));
604
779
  result.recipe.forEach((items, name) => {
605
780
  const set = getOrCreateSet(this.recipe, name);
606
781
  items.forEach((item) => set.add(this.append(item)));
@@ -609,6 +784,7 @@ var ParserResult = class {
609
784
  const set = getOrCreateSet(this.pattern, name);
610
785
  items.forEach((item) => set.add(this.append(item)));
611
786
  });
787
+ if (result.unresolved.length) this.unresolved.push(...result.unresolved);
612
788
  return this;
613
789
  }
614
790
  toArray() {
@@ -620,7 +796,7 @@ var ParserResult = class {
620
796
  cva: Array.from(this.cva),
621
797
  sva: Array.from(this.sva),
622
798
  token: Array.from(this.token),
623
- jsx: Array.from(this.jsx),
799
+ viewTransition: Array.from(this.viewTransition),
624
800
  recipe: Object.fromEntries(Array.from(this.recipe.entries()).map(([key, value]) => [key, Array.from(value)])),
625
801
  pattern: Object.fromEntries(Array.from(this.pattern.entries()).map(([key, value]) => [key, Array.from(value)]))
626
802
  };
@@ -645,8 +821,7 @@ const defaultEnv = { preset: "ECMA" };
645
821
  const fallbackImpl = (...values) => values.some((value) => value === void 0) ? void 0 : `fallback(${values.join(", ")})`;
646
822
  const evaluateOptions = { environment: defaultEnv };
647
823
  function createParser(context) {
648
- const { jsx, imports, recipes, config } = context;
649
- const syntax = config.syntax;
824
+ const { jsx, imports, recipes } = context;
650
825
  return function parse(sourceFile, encoder, options) {
651
826
  if (!sourceFile) return;
652
827
  const importDeclarations = getImportDeclarations(context, sourceFile);
@@ -681,12 +856,8 @@ function createParser(context) {
681
856
  functions: {
682
857
  matchFn: (prop) => file.matchFn(prop.fnName),
683
858
  matchProp: () => true,
684
- matchArg: (prop) => {
685
- if (file.isJsxFactory(prop.fnName) && prop.index === 1 && Node.isIdentifier(prop.argNode)) return false;
686
- return true;
687
- }
859
+ matchArg: () => true
688
860
  },
689
- taggedTemplates: syntax === "template-literal" ? { matchTaggedTemplate: (tag) => file.matchFn(tag.fnName) } : void 0,
690
861
  getEvaluateOptions: (node) => {
691
862
  if (!Node.isCallExpression(node)) return evaluateOptions;
692
863
  const propAccessExpr = node.getExpression();
@@ -720,14 +891,6 @@ function createParser(context) {
720
891
  box: query.box.value[0] ?? box.fallback(query.box),
721
892
  data: combineResult(unbox(query.box.value[0]))
722
893
  });
723
- else if (query.kind === "tagged-template") {
724
- const obj = astish(query.box.value);
725
- parserResult.set(name, {
726
- name,
727
- box: query.box ?? box.fallback(query.box),
728
- data: [obj]
729
- });
730
- }
731
894
  });
732
895
  }).when(imports.matchers.tokens.match, (name) => {
733
896
  result.queryList.forEach((query) => {
@@ -753,116 +916,28 @@ function createParser(context) {
753
916
  data: combineResult(unbox(query.box.value[0]))
754
917
  });
755
918
  });
756
- }).when(jsx.isJsxFactory, () => {
757
- result.queryList.forEach((query) => {
758
- if (query.kind === "call-expression" && query.box.value[1]) {
759
- const map = query.box.value[1];
760
- const boxNode = box.isMap(map) ? map : box.fallback(query.box);
761
- const combined = combineResult(unbox(boxNode));
762
- const result = {
763
- name,
764
- box: boxNode,
765
- data: options?.transform?.({
766
- type: "jsx-factory",
767
- data: combined
768
- }) ?? combined
769
- };
770
- if (box.isRecipe(map)) parserResult.setCva(result);
771
- else parserResult.set("css", result);
772
- const recipeOptions = query.box.value[2];
773
- if (box.isUnresolvable(map) && recipeOptions && box.isMap(recipeOptions) && recipeOptions.value.has("defaultProps")) {
774
- const maybeIdentifier = map.getNode();
775
- if (Node.isIdentifier(maybeIdentifier)) {
776
- const name = maybeIdentifier.getText();
777
- const recipeName = file.getName(name);
778
- parserResult.setRecipe(recipeName, {
779
- type: "jsx-recipe",
780
- name: recipeName,
781
- box: recipeOptions,
782
- data: combineResult(unbox(recipeOptions.value.get("defaultProps")))
783
- });
784
- }
785
- }
786
- } else if (query.kind === "tagged-template") {
787
- const obj = astish(query.box.value);
788
- parserResult.set("css", {
789
- name,
790
- box: query.box ?? box.fallback(query.box),
791
- data: [obj]
792
- });
793
- }
794
- });
795
- }).when(file.isJsxFactory, (name) => {
919
+ }).when(file.isViewTransitionFn, (name) => {
796
920
  result.queryList.forEach((query) => {
797
- if (query.kind === "call-expression") {
798
- const map = query.box.value[0];
799
- const boxNode = box.isMap(map) ? map : box.fallback(query.box);
800
- const combined = combineResult(unbox(boxNode));
801
- const result = {
802
- name,
803
- box: boxNode,
804
- data: options?.transform?.({
805
- type: "jsx-factory",
806
- data: combined
807
- }) ?? combined
808
- };
809
- if (box.isRecipe(map)) parserResult.setCva(result);
810
- else parserResult.set("css", result);
811
- } else if (query.kind === "tagged-template") {
812
- const obj = astish(query.box.value);
813
- parserResult.set("css", {
814
- name,
815
- box: query.box ?? box.fallback(query.box),
816
- data: [obj]
817
- });
818
- }
921
+ if (query.kind === "call-expression") parserResult.setViewTransition({
922
+ name,
923
+ box: query.box.value[0] ?? box.fallback(query.box),
924
+ data: combineResult(unbox(query.box.value[0]))
925
+ });
819
926
  });
820
927
  }).otherwise(() => {});
821
928
  else if (jsx.isEnabled && result.kind === "component") result.queryList.forEach((query) => {
822
929
  const data = combineResult(unbox(query.box));
823
- switch (true) {
824
- case file.isJsxFactory(name) || file.isJsxFactory(alias):
825
- parserResult.setJsx({
826
- type: "jsx-factory",
827
- name,
828
- box: query.box,
829
- data
830
- });
831
- break;
832
- case jsx.isJsxTagPattern(name) || jsx.isJsxTagPattern(alias):
833
- parserResult.setPattern(name, {
834
- type: "jsx-pattern",
835
- name,
930
+ for (const tag of [name, alias]) {
931
+ if (!jsx.isJsxTagRecipe(tag)) continue;
932
+ recipes.filter(tag).forEach((recipe) => {
933
+ parserResult.setRecipe(recipe.baseName, {
934
+ type: "jsx-recipe",
935
+ name: tag,
836
936
  box: query.box,
837
937
  data
838
938
  });
839
- break;
840
- case jsx.isJsxTagRecipe(name):
841
- recipes.filter(name).map((recipe) => {
842
- parserResult.setRecipe(recipe.baseName, {
843
- type: "jsx-recipe",
844
- name,
845
- box: query.box,
846
- data
847
- });
848
- });
849
- break;
850
- case jsx.isJsxTagRecipe(alias):
851
- recipes.filter(alias).map((recipe) => {
852
- parserResult.setRecipe(recipe.baseName, {
853
- type: "jsx-recipe",
854
- name: alias,
855
- box: query.box,
856
- data
857
- });
858
- });
859
- break;
860
- default: parserResult.setJsx({
861
- type: "jsx",
862
- name,
863
- box: query.box,
864
- data
865
939
  });
940
+ break;
866
941
  }
867
942
  });
868
943
  });
@@ -1073,7 +1148,6 @@ var Project = class {
1073
1148
  }
1074
1149
  }) ?? this.transformFile(filePath, original);
1075
1150
  if (original !== transformed) sourceFile.replaceWithText(transformed);
1076
- if (hooks["parser:preprocess"]) options.transform = hooks["parser:preprocess"];
1077
1151
  const result = this.parser(sourceFile, encoder, options)?.setFilePath(filePath);
1078
1152
  hooks["parser:after"]?.({
1079
1153
  filePath,
@@ -1090,4 +1164,4 @@ var Project = class {
1090
1164
  };
1091
1165
  };
1092
1166
  //#endregion
1093
- export { ParserResult, Project };
1167
+ export { ParserResult, Project, findUnresolvedStyles };