@bamboocss/parser 1.11.1 → 1.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,1025 +1,975 @@
1
- // src/project.ts
2
- import {
3
- ScriptKind,
4
- Project as TsProject,
5
- ts
6
- } from "ts-morph";
7
-
8
- // src/classify.ts
9
- import { box } from "@bamboocss/extractor";
10
- import { compact, patternFns } from "@bamboocss/shared";
1
+ import { Node, Project as Project$1, ScriptKind, ts } from "ts-morph";
2
+ import { box, extract, unbox } from "@bamboocss/extractor";
3
+ import { BambooError, astish, compact, getOrCreateSet, patternFns } from "@bamboocss/shared";
4
+ import { logger } from "@bamboocss/logger";
5
+ import { match } from "ts-pattern";
6
+ import { resolveTsPathPattern } from "@bamboocss/config/ts-path";
7
+ //#region src/classify.ts
11
8
  function addTo(map, key, value) {
12
- const set = map.get(key) ?? /* @__PURE__ */ new Set();
13
- set.add(value);
14
- map.set(key, set);
9
+ const set = map.get(key) ?? /* @__PURE__ */ new Set();
10
+ set.add(value);
11
+ map.set(key, set);
15
12
  }
16
13
  function classifyProject(ctx, resultMap) {
17
- const byId = /* @__PURE__ */ new Map();
18
- const byComponentIndex = /* @__PURE__ */ new Map();
19
- const byFilepath = /* @__PURE__ */ new Map();
20
- const byComponentInFilepath = /* @__PURE__ */ new Map();
21
- const globalMaps = createReportMaps();
22
- const byFilePathMaps = /* @__PURE__ */ new Map();
23
- const conditions = new Map(Object.entries(ctx.conditions.values));
24
- const { groupByProp } = getPropertyGroupMap(ctx);
25
- let id = 0;
26
- let componentIndex = 0;
27
- const isKnownUtility = (reportItem, componentReportItem) => {
28
- const { propName, value, tokenType } = reportItem;
29
- const utility = ctx.utility.config[propName];
30
- if (utility) {
31
- if (ctx.tokens.getByName(`${tokenType}.${value}`)) return true;
32
- if (ctx.tokens.getReferences(String(value)).length > 0) return true;
33
- if (ctx.utility.resolveColorMix(String(value)).color) return true;
34
- return false;
35
- }
36
- if (componentReportItem.reportItemType === "pattern") {
37
- const pattern = ctx.patterns.getConfig(componentReportItem.componentName.toLowerCase());
38
- const patternProp = pattern?.properties?.[propName];
39
- if (!patternProp) return false;
40
- if (patternProp.type === "boolean" || patternProp.type === "number") {
41
- return true;
42
- }
43
- if (patternProp.type === "property" && patternProp.value) {
44
- return Boolean(ctx.utility.config[patternProp.value]);
45
- }
46
- if (patternProp.type === "enum" && patternProp.value) {
47
- return Boolean(patternProp.value.includes(String(value)));
48
- }
49
- if (patternProp.type === "token") {
50
- return Boolean(ctx.tokens.getByName(`${patternProp.value}.${value}`));
51
- }
52
- return false;
53
- }
54
- return false;
55
- };
56
- const processPattern = (opts) => {
57
- const { boxNode, data, item, filepath, localMaps } = opts;
58
- const name = item.componentName;
59
- const pattern = ctx.patterns.details.find((p) => p.match.test(name) || p.baseName === name);
60
- if (!pattern) return;
61
- const cssObj = pattern.config.transform?.(data || {}, patternFns) ?? {};
62
- const newItem = {
63
- name: "css",
64
- type: "css",
65
- box: box.objectToMap(compact(cssObj), boxNode.getNode(), boxNode.getStack()),
66
- data: [cssObj]
67
- };
68
- Object.assign(newItem, { debug: true });
69
- return processResultItem({ item: newItem, kind: "function", localMaps, filepath });
70
- };
71
- const processResultItem = (opts) => {
72
- const { item, kind, filepath, localMaps } = opts;
73
- if (!item.box || box.isUnresolvable(item.box)) {
74
- return;
75
- }
76
- if (!item.data) {
77
- return;
78
- }
79
- const componentReportItem = {
80
- componentIndex: String(componentIndex++),
81
- componentName: item.name,
82
- reportItemType: item.type,
83
- kind,
84
- filepath,
85
- value: item.data,
86
- range: item.box.getRange(),
87
- contains: [],
88
- debug: Reflect.has(item, "debug")
89
- };
90
- if (item.type === "pattern" || item.type === "jsx-pattern") {
91
- return processPattern({ boxNode: item.box, data: item.data[0], item: componentReportItem, filepath, localMaps });
92
- }
93
- if (box.isArray(item.box)) {
94
- addTo(byComponentInFilepath, filepath, componentReportItem.componentIndex);
95
- return componentReportItem;
96
- }
97
- if (box.isMap(item.box)) {
98
- addTo(byComponentInFilepath, filepath, componentReportItem.componentIndex);
99
- processMap({ map: item.box, current: [], componentReportItem, filepath, localMaps });
100
- return componentReportItem;
101
- }
102
- if (item.type === "recipe") {
103
- addTo(byComponentInFilepath, filepath, componentReportItem.componentIndex);
104
- return componentReportItem;
105
- }
106
- };
107
- const processResultItemFn = (opts) => {
108
- const { item, filepath, localMaps, type } = opts;
109
- const componentReportItem = processResultItem({ item, kind: type, filepath, localMaps });
110
- if (!componentReportItem) return;
111
- addTo(globalMaps.byComponentOfKind, type, componentReportItem.componentIndex);
112
- addTo(localMaps.byComponentOfKind, type, componentReportItem.componentIndex);
113
- byComponentIndex.set(componentReportItem.componentIndex, componentReportItem);
114
- };
115
- const processMap = (opts) => {
116
- const { map, current, componentReportItem, filepath, localMaps, skipRange } = opts;
117
- const { reportItemType: type, kind, componentName: name } = componentReportItem;
118
- map.value.forEach((attrNode, attrName) => {
119
- if (box.isLiteral(attrNode) || box.isEmptyInitializer(attrNode)) {
120
- const value = box.isLiteral(attrNode) ? attrNode.value : true;
121
- const propReportItem = {
122
- index: String(id++),
123
- componentIndex: String(componentReportItem.componentIndex),
124
- componentName: name,
125
- tokenType: void 0,
126
- propName: attrName,
127
- reportItemKind: "utility",
128
- reportItemType: type,
129
- kind,
130
- filepath,
131
- path: current.concat(attrName),
132
- value,
133
- isKnownValue: false,
134
- range: skipRange ? null : map.getRange()
135
- };
136
- componentReportItem.contains.push(propReportItem.index);
137
- if (conditions.has(attrName)) {
138
- addTo(globalMaps.byConditionName, attrName, propReportItem.index);
139
- addTo(localMaps.byConditionName, attrName, propReportItem.index);
140
- propReportItem.propName = current[0] ?? attrName;
141
- propReportItem.isKnownValue = isKnownUtility(propReportItem, componentReportItem);
142
- propReportItem.conditionName = attrName;
143
- } else {
144
- if (current.length && conditions.has(current[0])) {
145
- propReportItem.conditionName = current[0];
146
- addTo(globalMaps.byConditionName, current[0], propReportItem.index);
147
- addTo(localMaps.byConditionName, current[0], propReportItem.index);
148
- }
149
- const propName = ctx.utility.resolveShorthand(attrName);
150
- const tokenType = ctx.utility.getTokenType(propName);
151
- if (tokenType) {
152
- propReportItem.reportItemKind = "token";
153
- propReportItem.tokenType = tokenType;
154
- }
155
- propReportItem.propName = propName;
156
- propReportItem.isKnownValue = isKnownUtility(propReportItem, componentReportItem);
157
- addTo(globalMaps.byPropertyName, propName, propReportItem.index);
158
- addTo(localMaps.byPropertyName, propName, propReportItem.index);
159
- if (tokenType) {
160
- addTo(globalMaps.byTokenType, tokenType, propReportItem.index);
161
- addTo(localMaps.byTokenType, tokenType, propReportItem.index);
162
- }
163
- if (propName.toLowerCase().includes("color") || groupByProp.get(propName) === "Color" || tokenType === "colors") {
164
- addTo(globalMaps.colorsUsed, value, propReportItem.index);
165
- addTo(localMaps.colorsUsed, value, propReportItem.index);
166
- }
167
- if (ctx.utility.shorthands.has(attrName)) {
168
- addTo(globalMaps.byShorthand, attrName, propReportItem.index);
169
- addTo(localMaps.byShorthand, attrName, propReportItem.index);
170
- }
171
- }
172
- if (current.length) {
173
- addTo(globalMaps.byPropertyPath, propReportItem.path.join("."), propReportItem.index);
174
- addTo(localMaps.byPropertyPath, propReportItem.path.join("."), propReportItem.index);
175
- }
176
- addTo(globalMaps.byTokenName, String(value), propReportItem.index);
177
- addTo(localMaps.byTokenName, String(value), propReportItem.index);
178
- addTo(globalMaps.byType, type, propReportItem.index);
179
- addTo(localMaps.byType, type, propReportItem.index);
180
- addTo(globalMaps.byComponentName, name, propReportItem.index);
181
- addTo(localMaps.byComponentName, name, propReportItem.index);
182
- addTo(globalMaps.fromKind, kind, propReportItem.index);
183
- addTo(localMaps.fromKind, kind, propReportItem.index);
184
- addTo(byFilepath, filepath, propReportItem.index);
185
- byId.set(propReportItem.index, propReportItem);
186
- return;
187
- }
188
- if (box.isMap(attrNode) && attrNode.value.size) {
189
- return processMap({
190
- map: attrNode,
191
- current: current.concat(attrName),
192
- componentReportItem,
193
- filepath,
194
- localMaps
195
- });
196
- }
197
- });
198
- };
199
- resultMap.forEach((parserResult, filepath) => {
200
- if (parserResult.isEmpty()) return;
201
- const localMaps = createReportMaps();
202
- const componentFn = (item) => {
203
- processResultItemFn({ item, filepath, localMaps, type: "component" });
204
- };
205
- const functionFn = (item) => {
206
- processResultItemFn({ item, filepath, localMaps, type: "function" });
207
- };
208
- parserResult.jsx.forEach(componentFn);
209
- parserResult.css.forEach(functionFn);
210
- parserResult.cva.forEach(functionFn);
211
- parserResult.pattern.forEach((itemList) => {
212
- itemList.forEach(functionFn);
213
- });
214
- parserResult.recipe.forEach((itemList) => {
215
- itemList.forEach(functionFn);
216
- });
217
- byFilePathMaps.set(filepath, localMaps);
218
- });
219
- const pickCount = 10;
220
- const filesWithMostComponent = Object.fromEntries(
221
- Array.from(byComponentInFilepath.entries()).map(([filepath, list]) => [filepath, list.size]).sort((a, b) => b[1] - a[1]).slice(0, pickCount)
222
- );
223
- Object.entries(ctx.recipes.config).forEach(([key, recipe]) => {
224
- const localMaps = createReportMaps();
225
- const functionFn = (styleObject) => {
226
- if (!styleObject) return;
227
- const componentReportItem = {
228
- componentIndex: "0",
229
- componentName: `recipes.${key}.base`,
230
- reportItemType: "css",
231
- kind: "function",
232
- filepath: `theme/recipes/${key}`,
233
- value: styleObject,
234
- range: null,
235
- contains: []
236
- };
237
- processMap({
238
- // @ts-expect-error
239
- map: box.objectToMap(styleObject, null, []),
240
- current: [],
241
- filepath: `@config/theme/recipes/${key}`,
242
- skipRange: true,
243
- localMaps,
244
- componentReportItem
245
- });
246
- };
247
- const isSlotRecipe = (_v) => ctx.recipes.isSlotRecipe(key);
248
- if (isSlotRecipe(recipe)) {
249
- Object.values(recipe.base ?? {}).forEach(functionFn);
250
- Object.values(recipe.variants ?? {}).forEach((variants) => {
251
- Object.values(variants).forEach((v) => {
252
- Object.values(v).forEach(functionFn);
253
- });
254
- });
255
- recipe.compoundVariants?.forEach((v) => {
256
- Object.values(v.css).forEach(functionFn);
257
- });
258
- } else {
259
- functionFn(recipe.base);
260
- Object.values(recipe.variants ?? {}).forEach((variants) => {
261
- Object.values(variants).forEach(functionFn);
262
- });
263
- recipe.compoundVariants?.forEach((v) => functionFn(v.css));
264
- }
265
- });
266
- Object.values(ctx.config.globalCss ?? {}).forEach((styleObject) => {
267
- if (!styleObject) return;
268
- processMap({
269
- // @ts-expect-error
270
- map: box.objectToMap(styleObject, null, []),
271
- current: [],
272
- filepath: "@config/globalCss",
273
- skipRange: true,
274
- localMaps: createReportMaps(),
275
- componentReportItem: {
276
- componentIndex: "0",
277
- componentName: "global",
278
- reportItemType: "css",
279
- kind: "function",
280
- filepath: "global",
281
- value: styleObject,
282
- range: null,
283
- contains: []
284
- }
285
- });
286
- });
287
- return {
288
- propById: byId,
289
- componentById: byComponentIndex,
290
- details: {
291
- counts: {
292
- filesWithTokens: byFilepath.size,
293
- propNameUsed: globalMaps.byPropertyName.size,
294
- tokenUsed: globalMaps.byTokenName.size,
295
- shorthandUsed: globalMaps.byShorthand.size,
296
- propertyPathUsed: globalMaps.byPropertyPath.size,
297
- typeUsed: globalMaps.byType.size,
298
- componentNameUsed: globalMaps.byComponentName.size,
299
- kindUsed: globalMaps.fromKind.size,
300
- componentOfKindUsed: globalMaps.byComponentOfKind.size,
301
- colorsUsed: globalMaps.colorsUsed.size
302
- },
303
- stats: {
304
- filesWithMostComponent,
305
- mostUseds: getXMostUseds(globalMaps, 10)
306
- }
307
- },
308
- derived: {
309
- byFilepath,
310
- byComponentInFilepath,
311
- globalMaps,
312
- byFilePathMaps
313
- }
314
- };
14
+ const byId = /* @__PURE__ */ new Map();
15
+ const byComponentIndex = /* @__PURE__ */ new Map();
16
+ const byFilepath = /* @__PURE__ */ new Map();
17
+ const byComponentInFilepath = /* @__PURE__ */ new Map();
18
+ const globalMaps = createReportMaps();
19
+ const byFilePathMaps = /* @__PURE__ */ new Map();
20
+ const conditions = new Map(Object.entries(ctx.conditions.values));
21
+ const { groupByProp } = getPropertyGroupMap(ctx);
22
+ let id = 0;
23
+ let componentIndex = 0;
24
+ const isKnownUtility = (reportItem, componentReportItem) => {
25
+ const { propName, value, tokenType } = reportItem;
26
+ if (ctx.utility.config[propName]) {
27
+ if (ctx.tokens.getByName(`${tokenType}.${value}`)) return true;
28
+ if (ctx.tokens.getReferences(String(value)).length > 0) return true;
29
+ if (ctx.utility.resolveColorMix(String(value)).color) return true;
30
+ return false;
31
+ }
32
+ if (componentReportItem.reportItemType === "pattern") {
33
+ const patternProp = ctx.patterns.getConfig(componentReportItem.componentName.toLowerCase())?.properties?.[propName];
34
+ if (!patternProp) return false;
35
+ if (patternProp.type === "boolean" || patternProp.type === "number") return true;
36
+ if (patternProp.type === "property" && patternProp.value) return Boolean(ctx.utility.config[patternProp.value]);
37
+ if (patternProp.type === "enum" && patternProp.value) return Boolean(patternProp.value.includes(String(value)));
38
+ if (patternProp.type === "token") return Boolean(ctx.tokens.getByName(`${patternProp.value}.${value}`));
39
+ return false;
40
+ }
41
+ return false;
42
+ };
43
+ const processPattern = (opts) => {
44
+ const { boxNode, data, item, filepath, localMaps } = opts;
45
+ const name = item.componentName;
46
+ const pattern = ctx.patterns.details.find((p) => p.match.test(name) || p.baseName === name);
47
+ if (!pattern) return;
48
+ const cssObj = pattern.config.transform?.(data || {}, patternFns) ?? {};
49
+ const newItem = {
50
+ name: "css",
51
+ type: "css",
52
+ box: box.objectToMap(compact(cssObj), boxNode.getNode(), boxNode.getStack()),
53
+ data: [cssObj]
54
+ };
55
+ Object.assign(newItem, { debug: true });
56
+ return processResultItem({
57
+ item: newItem,
58
+ kind: "function",
59
+ localMaps,
60
+ filepath
61
+ });
62
+ };
63
+ const processResultItem = (opts) => {
64
+ const { item, kind, filepath, localMaps } = opts;
65
+ if (!item.box || box.isUnresolvable(item.box)) return;
66
+ if (!item.data) return;
67
+ const componentReportItem = {
68
+ componentIndex: String(componentIndex++),
69
+ componentName: item.name,
70
+ reportItemType: item.type,
71
+ kind,
72
+ filepath,
73
+ value: item.data,
74
+ range: item.box.getRange(),
75
+ contains: [],
76
+ debug: Reflect.has(item, "debug")
77
+ };
78
+ if (item.type === "pattern" || item.type === "jsx-pattern") return processPattern({
79
+ boxNode: item.box,
80
+ data: item.data[0],
81
+ item: componentReportItem,
82
+ filepath,
83
+ localMaps
84
+ });
85
+ if (box.isArray(item.box)) {
86
+ addTo(byComponentInFilepath, filepath, componentReportItem.componentIndex);
87
+ return componentReportItem;
88
+ }
89
+ if (box.isMap(item.box)) {
90
+ addTo(byComponentInFilepath, filepath, componentReportItem.componentIndex);
91
+ processMap({
92
+ map: item.box,
93
+ current: [],
94
+ componentReportItem,
95
+ filepath,
96
+ localMaps
97
+ });
98
+ return componentReportItem;
99
+ }
100
+ if (item.type === "recipe") {
101
+ addTo(byComponentInFilepath, filepath, componentReportItem.componentIndex);
102
+ return componentReportItem;
103
+ }
104
+ };
105
+ const processResultItemFn = (opts) => {
106
+ const { item, filepath, localMaps, type } = opts;
107
+ const componentReportItem = processResultItem({
108
+ item,
109
+ kind: type,
110
+ filepath,
111
+ localMaps
112
+ });
113
+ if (!componentReportItem) return;
114
+ addTo(globalMaps.byComponentOfKind, type, componentReportItem.componentIndex);
115
+ addTo(localMaps.byComponentOfKind, type, componentReportItem.componentIndex);
116
+ byComponentIndex.set(componentReportItem.componentIndex, componentReportItem);
117
+ };
118
+ const processMap = (opts) => {
119
+ const { map, current, componentReportItem, filepath, localMaps, skipRange } = opts;
120
+ const { reportItemType: type, kind, componentName: name } = componentReportItem;
121
+ map.value.forEach((attrNode, attrName) => {
122
+ if (box.isLiteral(attrNode) || box.isEmptyInitializer(attrNode)) {
123
+ const value = box.isLiteral(attrNode) ? attrNode.value : true;
124
+ const propReportItem = {
125
+ index: String(id++),
126
+ componentIndex: String(componentReportItem.componentIndex),
127
+ componentName: name,
128
+ tokenType: void 0,
129
+ propName: attrName,
130
+ reportItemKind: "utility",
131
+ reportItemType: type,
132
+ kind,
133
+ filepath,
134
+ path: current.concat(attrName),
135
+ value,
136
+ isKnownValue: false,
137
+ range: skipRange ? null : map.getRange()
138
+ };
139
+ componentReportItem.contains.push(propReportItem.index);
140
+ if (conditions.has(attrName)) {
141
+ addTo(globalMaps.byConditionName, attrName, propReportItem.index);
142
+ addTo(localMaps.byConditionName, attrName, propReportItem.index);
143
+ propReportItem.propName = current[0] ?? attrName;
144
+ propReportItem.isKnownValue = isKnownUtility(propReportItem, componentReportItem);
145
+ propReportItem.conditionName = attrName;
146
+ } else {
147
+ if (current.length && conditions.has(current[0])) {
148
+ propReportItem.conditionName = current[0];
149
+ addTo(globalMaps.byConditionName, current[0], propReportItem.index);
150
+ addTo(localMaps.byConditionName, current[0], propReportItem.index);
151
+ }
152
+ const propName = ctx.utility.resolveShorthand(attrName);
153
+ const tokenType = ctx.utility.getTokenType(propName);
154
+ if (tokenType) {
155
+ propReportItem.reportItemKind = "token";
156
+ propReportItem.tokenType = tokenType;
157
+ }
158
+ propReportItem.propName = propName;
159
+ propReportItem.isKnownValue = isKnownUtility(propReportItem, componentReportItem);
160
+ addTo(globalMaps.byPropertyName, propName, propReportItem.index);
161
+ addTo(localMaps.byPropertyName, propName, propReportItem.index);
162
+ if (tokenType) {
163
+ addTo(globalMaps.byTokenType, tokenType, propReportItem.index);
164
+ addTo(localMaps.byTokenType, tokenType, propReportItem.index);
165
+ }
166
+ if (propName.toLowerCase().includes("color") || groupByProp.get(propName) === "Color" || tokenType === "colors") {
167
+ addTo(globalMaps.colorsUsed, value, propReportItem.index);
168
+ addTo(localMaps.colorsUsed, value, propReportItem.index);
169
+ }
170
+ if (ctx.utility.shorthands.has(attrName)) {
171
+ addTo(globalMaps.byShorthand, attrName, propReportItem.index);
172
+ addTo(localMaps.byShorthand, attrName, propReportItem.index);
173
+ }
174
+ }
175
+ if (current.length) {
176
+ addTo(globalMaps.byPropertyPath, propReportItem.path.join("."), propReportItem.index);
177
+ addTo(localMaps.byPropertyPath, propReportItem.path.join("."), propReportItem.index);
178
+ }
179
+ addTo(globalMaps.byTokenName, String(value), propReportItem.index);
180
+ addTo(localMaps.byTokenName, String(value), propReportItem.index);
181
+ addTo(globalMaps.byType, type, propReportItem.index);
182
+ addTo(localMaps.byType, type, propReportItem.index);
183
+ addTo(globalMaps.byComponentName, name, propReportItem.index);
184
+ addTo(localMaps.byComponentName, name, propReportItem.index);
185
+ addTo(globalMaps.fromKind, kind, propReportItem.index);
186
+ addTo(localMaps.fromKind, kind, propReportItem.index);
187
+ addTo(byFilepath, filepath, propReportItem.index);
188
+ byId.set(propReportItem.index, propReportItem);
189
+ return;
190
+ }
191
+ if (box.isMap(attrNode) && attrNode.value.size) return processMap({
192
+ map: attrNode,
193
+ current: current.concat(attrName),
194
+ componentReportItem,
195
+ filepath,
196
+ localMaps
197
+ });
198
+ });
199
+ };
200
+ resultMap.forEach((parserResult, filepath) => {
201
+ if (parserResult.isEmpty()) return;
202
+ const localMaps = createReportMaps();
203
+ const componentFn = (item) => {
204
+ processResultItemFn({
205
+ item,
206
+ filepath,
207
+ localMaps,
208
+ type: "component"
209
+ });
210
+ };
211
+ const functionFn = (item) => {
212
+ processResultItemFn({
213
+ item,
214
+ filepath,
215
+ localMaps,
216
+ type: "function"
217
+ });
218
+ };
219
+ parserResult.jsx.forEach(componentFn);
220
+ parserResult.css.forEach(functionFn);
221
+ parserResult.cva.forEach(functionFn);
222
+ parserResult.pattern.forEach((itemList) => {
223
+ itemList.forEach(functionFn);
224
+ });
225
+ parserResult.recipe.forEach((itemList) => {
226
+ itemList.forEach(functionFn);
227
+ });
228
+ byFilePathMaps.set(filepath, localMaps);
229
+ });
230
+ const filesWithMostComponent = Object.fromEntries(Array.from(byComponentInFilepath.entries()).map(([filepath, list]) => [filepath, list.size]).sort((a, b) => b[1] - a[1]).slice(0, 10));
231
+ Object.entries(ctx.recipes.config).forEach(([key, recipe]) => {
232
+ const localMaps = createReportMaps();
233
+ const functionFn = (styleObject) => {
234
+ if (!styleObject) return;
235
+ const componentReportItem = {
236
+ componentIndex: "0",
237
+ componentName: `recipes.${key}.base`,
238
+ reportItemType: "css",
239
+ kind: "function",
240
+ filepath: `theme/recipes/${key}`,
241
+ value: styleObject,
242
+ range: null,
243
+ contains: []
244
+ };
245
+ processMap({
246
+ map: box.objectToMap(styleObject, null, []),
247
+ current: [],
248
+ filepath: `@config/theme/recipes/${key}`,
249
+ skipRange: true,
250
+ localMaps,
251
+ componentReportItem
252
+ });
253
+ };
254
+ const isSlotRecipe = (_v) => ctx.recipes.isSlotRecipe(key);
255
+ if (isSlotRecipe(recipe)) {
256
+ Object.values(recipe.base ?? {}).forEach(functionFn);
257
+ Object.values(recipe.variants ?? {}).forEach((variants) => {
258
+ Object.values(variants).forEach((v) => {
259
+ Object.values(v).forEach(functionFn);
260
+ });
261
+ });
262
+ recipe.compoundVariants?.forEach((v) => {
263
+ Object.values(v.css).forEach(functionFn);
264
+ });
265
+ } else {
266
+ functionFn(recipe.base);
267
+ Object.values(recipe.variants ?? {}).forEach((variants) => {
268
+ Object.values(variants).forEach(functionFn);
269
+ });
270
+ recipe.compoundVariants?.forEach((v) => functionFn(v.css));
271
+ }
272
+ });
273
+ Object.values(ctx.config.globalCss ?? {}).forEach((styleObject) => {
274
+ if (!styleObject) return;
275
+ processMap({
276
+ map: box.objectToMap(styleObject, null, []),
277
+ current: [],
278
+ filepath: "@config/globalCss",
279
+ skipRange: true,
280
+ localMaps: createReportMaps(),
281
+ componentReportItem: {
282
+ componentIndex: "0",
283
+ componentName: "global",
284
+ reportItemType: "css",
285
+ kind: "function",
286
+ filepath: "global",
287
+ value: styleObject,
288
+ range: null,
289
+ contains: []
290
+ }
291
+ });
292
+ });
293
+ return {
294
+ propById: byId,
295
+ componentById: byComponentIndex,
296
+ details: {
297
+ counts: {
298
+ filesWithTokens: byFilepath.size,
299
+ propNameUsed: globalMaps.byPropertyName.size,
300
+ tokenUsed: globalMaps.byTokenName.size,
301
+ shorthandUsed: globalMaps.byShorthand.size,
302
+ propertyPathUsed: globalMaps.byPropertyPath.size,
303
+ typeUsed: globalMaps.byType.size,
304
+ componentNameUsed: globalMaps.byComponentName.size,
305
+ kindUsed: globalMaps.fromKind.size,
306
+ componentOfKindUsed: globalMaps.byComponentOfKind.size,
307
+ colorsUsed: globalMaps.colorsUsed.size
308
+ },
309
+ stats: {
310
+ filesWithMostComponent,
311
+ mostUseds: getXMostUseds(globalMaps, 10)
312
+ }
313
+ },
314
+ derived: {
315
+ byFilepath,
316
+ byComponentInFilepath,
317
+ globalMaps,
318
+ byFilePathMaps
319
+ }
320
+ };
315
321
  }
316
- var getXMostUseds = (globalMaps, pickCount) => {
317
- return {
318
- propNames: getMostUsedInMap(globalMaps.byPropertyName, pickCount),
319
- tokens: getMostUsedInMap(globalMaps.byTokenName, pickCount),
320
- shorthands: getMostUsedInMap(globalMaps.byShorthand, pickCount),
321
- conditions: getMostUsedInMap(globalMaps.byConditionName, pickCount),
322
- propertyPaths: getMostUsedInMap(globalMaps.byPropertyPath, pickCount),
323
- categories: getMostUsedInMap(globalMaps.byTokenType, pickCount),
324
- types: getMostUsedInMap(globalMaps.byType, pickCount),
325
- componentNames: getMostUsedInMap(globalMaps.byComponentName, pickCount),
326
- fromKinds: getMostUsedInMap(globalMaps.fromKind, pickCount),
327
- componentOfKinds: getMostUsedInMap(globalMaps.byComponentOfKind, pickCount),
328
- colors: getMostUsedInMap(globalMaps.colorsUsed, pickCount)
329
- };
322
+ const getXMostUseds = (globalMaps, pickCount) => {
323
+ return {
324
+ propNames: getMostUsedInMap(globalMaps.byPropertyName, pickCount),
325
+ tokens: getMostUsedInMap(globalMaps.byTokenName, pickCount),
326
+ shorthands: getMostUsedInMap(globalMaps.byShorthand, pickCount),
327
+ conditions: getMostUsedInMap(globalMaps.byConditionName, pickCount),
328
+ propertyPaths: getMostUsedInMap(globalMaps.byPropertyPath, pickCount),
329
+ categories: getMostUsedInMap(globalMaps.byTokenType, pickCount),
330
+ types: getMostUsedInMap(globalMaps.byType, pickCount),
331
+ componentNames: getMostUsedInMap(globalMaps.byComponentName, pickCount),
332
+ fromKinds: getMostUsedInMap(globalMaps.fromKind, pickCount),
333
+ componentOfKinds: getMostUsedInMap(globalMaps.byComponentOfKind, pickCount),
334
+ colors: getMostUsedInMap(globalMaps.colorsUsed, pickCount)
335
+ };
330
336
  };
331
- var getMostUsedInMap = (map, pickCount) => {
332
- return Array.from(map.entries()).map(([key, list]) => [key, list.size]).sort((a, b) => b[1] - a[1]).slice(0, pickCount).map(([key, count]) => ({ key, count }));
337
+ const getMostUsedInMap = (map, pickCount) => {
338
+ return Array.from(map.entries()).map(([key, list]) => [key, list.size]).sort((a, b) => b[1] - a[1]).slice(0, pickCount).map(([key, count]) => ({
339
+ key,
340
+ count
341
+ }));
333
342
  };
334
- var defaultGroupNames = [
335
- "System",
336
- "Container",
337
- "Display",
338
- "Visibility",
339
- "Position",
340
- "Transform",
341
- "Flex Layout",
342
- "Grid Layout",
343
- "Layout",
344
- "Border",
345
- "Border Radius",
346
- "Width",
347
- "Height",
348
- "Margin",
349
- "Padding",
350
- "Color",
351
- "Typography",
352
- "Background",
353
- "Shadow",
354
- "Table",
355
- "List",
356
- "Scroll",
357
- "Interactivity",
358
- "Transition",
359
- "Effect",
360
- "Other",
361
- "Focus Ring"
343
+ const defaultGroupNames = [
344
+ "System",
345
+ "Container",
346
+ "Display",
347
+ "Visibility",
348
+ "Position",
349
+ "Transform",
350
+ "Flex Layout",
351
+ "Grid Layout",
352
+ "Layout",
353
+ "Border",
354
+ "Border Radius",
355
+ "Width",
356
+ "Height",
357
+ "Margin",
358
+ "Padding",
359
+ "Color",
360
+ "Typography",
361
+ "Background",
362
+ "Shadow",
363
+ "Table",
364
+ "List",
365
+ "Scroll",
366
+ "Interactivity",
367
+ "Transition",
368
+ "Effect",
369
+ "Other",
370
+ "Focus Ring"
362
371
  ];
363
372
  function getPropertyGroupMap(ctx) {
364
- const groups = new Map(defaultGroupNames.map((name) => [name, /* @__PURE__ */ new Set()]));
365
- const groupByProp = /* @__PURE__ */ new Map();
366
- const systemGroup = groups.get("System");
367
- systemGroup.add("base");
368
- systemGroup.add("colorPalette");
369
- const otherStyleProps = groups.get("Other");
370
- Object.entries(ctx.utility.config).map(([key, value]) => {
371
- const group = value?.group;
372
- if (!group) {
373
- otherStyleProps.add(key);
374
- return;
375
- }
376
- if (!groups.has(group)) {
377
- groups.set(group, /* @__PURE__ */ new Set());
378
- }
379
- const set = groups.get(group);
380
- if (value.shorthand) {
381
- if (Array.isArray(value.shorthand)) {
382
- value.shorthand.forEach((shorthand) => {
383
- set.add(shorthand);
384
- groupByProp.set(shorthand, group);
385
- });
386
- } else {
387
- set.add(value.shorthand);
388
- groupByProp.set(value.shorthand, group);
389
- }
390
- }
391
- set.add(key);
392
- groupByProp.set(key, group);
393
- });
394
- return { groups, groupByProp };
373
+ const groups = new Map(defaultGroupNames.map((name) => [name, /* @__PURE__ */ new Set()]));
374
+ const groupByProp = /* @__PURE__ */ new Map();
375
+ const systemGroup = groups.get("System");
376
+ systemGroup.add("base");
377
+ systemGroup.add("colorPalette");
378
+ const otherStyleProps = groups.get("Other");
379
+ Object.entries(ctx.utility.config).map(([key, value]) => {
380
+ const group = value?.group;
381
+ if (!group) {
382
+ otherStyleProps.add(key);
383
+ return;
384
+ }
385
+ if (!groups.has(group)) groups.set(group, /* @__PURE__ */ new Set());
386
+ const set = groups.get(group);
387
+ if (value.shorthand) if (Array.isArray(value.shorthand)) value.shorthand.forEach((shorthand) => {
388
+ set.add(shorthand);
389
+ groupByProp.set(shorthand, group);
390
+ });
391
+ else {
392
+ set.add(value.shorthand);
393
+ groupByProp.set(value.shorthand, group);
394
+ }
395
+ set.add(key);
396
+ groupByProp.set(key, group);
397
+ });
398
+ return {
399
+ groups,
400
+ groupByProp
401
+ };
395
402
  }
396
403
  function createReportMaps() {
397
- return {
398
- byComponentOfKind: /* @__PURE__ */ new Map(),
399
- byPropertyName: /* @__PURE__ */ new Map(),
400
- byTokenType: /* @__PURE__ */ new Map(),
401
- byConditionName: /* @__PURE__ */ new Map(),
402
- byShorthand: /* @__PURE__ */ new Map(),
403
- byTokenName: /* @__PURE__ */ new Map(),
404
- byPropertyPath: /* @__PURE__ */ new Map(),
405
- fromKind: /* @__PURE__ */ new Map(),
406
- byType: /* @__PURE__ */ new Map(),
407
- byComponentName: /* @__PURE__ */ new Map(),
408
- colorsUsed: /* @__PURE__ */ new Map()
409
- };
404
+ return {
405
+ byComponentOfKind: /* @__PURE__ */ new Map(),
406
+ byPropertyName: /* @__PURE__ */ new Map(),
407
+ byTokenType: /* @__PURE__ */ new Map(),
408
+ byConditionName: /* @__PURE__ */ new Map(),
409
+ byShorthand: /* @__PURE__ */ new Map(),
410
+ byTokenName: /* @__PURE__ */ new Map(),
411
+ byPropertyPath: /* @__PURE__ */ new Map(),
412
+ fromKind: /* @__PURE__ */ new Map(),
413
+ byType: /* @__PURE__ */ new Map(),
414
+ byComponentName: /* @__PURE__ */ new Map(),
415
+ colorsUsed: /* @__PURE__ */ new Map()
416
+ };
410
417
  }
411
-
412
- // src/parser.ts
413
- import { box as box2, extract, unbox } from "@bamboocss/extractor";
414
- import { logger } from "@bamboocss/logger";
415
- import { astish } from "@bamboocss/shared";
416
- import { Node } from "ts-morph";
417
- import { match } from "ts-pattern";
418
-
419
- // src/get-import-declarations.ts
420
- import { resolveTsPathPattern } from "@bamboocss/config/ts-path";
421
-
422
- // src/get-module-specifier-value.ts
423
- var getModuleSpecifierValue = (node) => {
424
- try {
425
- return node.getModuleSpecifierValue();
426
- } catch {
427
- return;
428
- }
418
+ //#endregion
419
+ //#region src/get-module-specifier-value.ts
420
+ const getModuleSpecifierValue = (node) => {
421
+ try {
422
+ return node.getModuleSpecifierValue();
423
+ } catch {
424
+ return;
425
+ }
429
426
  };
430
-
431
- // src/get-import-declarations.ts
427
+ //#endregion
428
+ //#region src/get-import-declarations.ts
432
429
  function getImportDeclarations(context, sourceFile) {
433
- const { imports, tsOptions } = context;
434
- const importDeclarations = [];
435
- sourceFile.getImportDeclarations().forEach((node) => {
436
- const mod = getModuleSpecifierValue(node);
437
- if (!mod) return;
438
- node.getNamedImports().forEach((specifier) => {
439
- const name = specifier.getNameNode().getText();
440
- const alias = specifier.getAliasNode()?.getText() || name;
441
- const result = { name, alias, mod, kind: "named" };
442
- const found = imports.match(result, (mod2) => {
443
- if (!tsOptions?.pathMappings) return;
444
- return resolveTsPathPattern(tsOptions.pathMappings, mod2);
445
- });
446
- if (!found) return;
447
- importDeclarations.push(result);
448
- });
449
- const namespace = node.getNamespaceImport();
450
- if (namespace) {
451
- const name = namespace.getText();
452
- const result = { name, alias: name, mod, kind: "namespace" };
453
- const found = imports.match(result, (mod2) => {
454
- if (!tsOptions?.pathMappings) return;
455
- return resolveTsPathPattern(tsOptions.pathMappings, mod2);
456
- });
457
- if (!found) return;
458
- importDeclarations.push(result);
459
- }
460
- });
461
- return importDeclarations;
430
+ const { imports, tsOptions } = context;
431
+ const importDeclarations = [];
432
+ sourceFile.getImportDeclarations().forEach((node) => {
433
+ const mod = getModuleSpecifierValue(node);
434
+ if (!mod) return;
435
+ node.getNamedImports().forEach((specifier) => {
436
+ const name = specifier.getNameNode().getText();
437
+ const result = {
438
+ name,
439
+ alias: specifier.getAliasNode()?.getText() || name,
440
+ mod,
441
+ kind: "named"
442
+ };
443
+ if (!imports.match(result, (mod) => {
444
+ if (!tsOptions?.pathMappings) return;
445
+ return resolveTsPathPattern(tsOptions.pathMappings, mod);
446
+ })) return;
447
+ importDeclarations.push(result);
448
+ });
449
+ const namespace = node.getNamespaceImport();
450
+ if (namespace) {
451
+ const name = namespace.getText();
452
+ const result = {
453
+ name,
454
+ alias: name,
455
+ mod,
456
+ kind: "namespace"
457
+ };
458
+ if (!imports.match(result, (mod) => {
459
+ if (!tsOptions?.pathMappings) return;
460
+ return resolveTsPathPattern(tsOptions.pathMappings, mod);
461
+ })) return;
462
+ importDeclarations.push(result);
463
+ }
464
+ });
465
+ return importDeclarations;
462
466
  }
463
-
464
- // src/parser-result.ts
465
- import { BambooError, getOrCreateSet } from "@bamboocss/shared";
467
+ //#endregion
468
+ //#region src/parser-result.ts
466
469
  function cartesian(arrays) {
467
- if (arrays.length === 0) return [[]];
468
- const [first, ...rest] = arrays;
469
- const restProduct = cartesian(rest);
470
- return first.flatMap((item) => restProduct.map((combo) => [item, ...combo]));
470
+ if (arrays.length === 0) return [[]];
471
+ const [first, ...rest] = arrays;
472
+ const restProduct = cartesian(rest);
473
+ return first.flatMap((item) => restProduct.map((combo) => [item, ...combo]));
471
474
  }
472
475
  var ParserResult = class {
473
- constructor(context, encoder) {
474
- this.context = context;
475
- this.encoder = encoder ?? context.encoder;
476
- }
477
- /** Ordered list of all ResultItem */
478
- all = [];
479
- jsx = /* @__PURE__ */ new Set();
480
- css = /* @__PURE__ */ new Set();
481
- cva = /* @__PURE__ */ new Set();
482
- sva = /* @__PURE__ */ new Set();
483
- token = /* @__PURE__ */ new Set();
484
- recipe = /* @__PURE__ */ new Map();
485
- pattern = /* @__PURE__ */ new Map();
486
- filePath;
487
- encoder;
488
- append(result) {
489
- this.all.push(result);
490
- return result;
491
- }
492
- set(name, result) {
493
- switch (name) {
494
- case "css":
495
- this.setCss(result);
496
- break;
497
- case "cva":
498
- this.setCva(result);
499
- break;
500
- case "sva":
501
- this.setSva(result);
502
- break;
503
- case "token":
504
- this.setToken(result);
505
- break;
506
- default:
507
- throw new BambooError(
508
- "UNKNOWN_RESULT_TYPE",
509
- `Unknown parser result type: "${name}". Expected one of: css, cva, sva, token`
510
- );
511
- }
512
- }
513
- setCss(result) {
514
- this.css.add(this.append(Object.assign({ type: "css" }, result)));
515
- const encoder = this.encoder;
516
- 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));
519
- return;
520
- }
521
- const keyCounts = /* @__PURE__ */ new Map();
522
- for (const obj of result.data) {
523
- for (const key of Object.keys(obj)) {
524
- keyCounts.set(key, (keyCounts.get(key) || 0) + 1);
525
- }
526
- }
527
- const hasOverlap = Array.from(keyCounts.values()).some((c) => c > 1);
528
- if (!hasOverlap) {
529
- encoder.processGrouped(Object.assign({}, ...result.data));
530
- return;
531
- }
532
- const overlappingKeys = /* @__PURE__ */ new Set();
533
- keyCounts.forEach((count, key) => {
534
- if (count > 1) overlappingKeys.add(key);
535
- });
536
- const base = {};
537
- const branchEntries = [];
538
- for (const obj of result.data) {
539
- if (Object.keys(obj).some((k) => overlappingKeys.has(k))) {
540
- branchEntries.push(obj);
541
- } else {
542
- Object.assign(base, obj);
543
- }
544
- }
545
- const branchGroups = /* @__PURE__ */ new Map();
546
- for (const entry of branchEntries) {
547
- const keySet = Object.keys(entry).sort().join("\0");
548
- const group = branchGroups.get(keySet) || [];
549
- group.push(entry);
550
- branchGroups.set(keySet, group);
551
- }
552
- const groupArrays = Array.from(branchGroups.values());
553
- const totalCombinations = groupArrays.reduce((acc, g) => acc * g.length, 1);
554
- if (totalCombinations > 32) {
555
- result.data.forEach((obj) => encoder.processGrouped(obj));
556
- return;
557
- }
558
- for (const combo of cartesian(groupArrays)) {
559
- encoder.processGrouped(Object.assign({}, base, ...combo));
560
- }
561
- }
562
- setCva(result) {
563
- this.cva.add(this.append(Object.assign({ type: "cva" }, result)));
564
- const encoder = this.encoder;
565
- result.data.forEach((data) => encoder.processAtomicRecipe(data));
566
- }
567
- setSva(result) {
568
- this.sva.add(this.append(Object.assign({ type: "sva" }, result)));
569
- const encoder = this.encoder;
570
- result.data.forEach((data) => encoder.processAtomicSlotRecipe(data));
571
- }
572
- setToken(result) {
573
- this.token.add(this.append(Object.assign({ type: "token" }, result)));
574
- }
575
- setJsx(result) {
576
- this.jsx.add(this.append(Object.assign({ type: "jsx" }, result)));
577
- const encoder = this.encoder;
578
- const grouped = this.context.config.cssMode === "grouped";
579
- result.data.forEach((obj) => encoder.processStyleProps(obj, grouped));
580
- }
581
- setPattern(name, result) {
582
- const set = getOrCreateSet(this.pattern, name);
583
- set.add(this.append(Object.assign({ type: "pattern", name }, result)));
584
- const encoder = this.encoder;
585
- result.data.forEach(
586
- (obj) => encoder.processPattern(name, obj, result.type ?? "pattern", result.name)
587
- );
588
- }
589
- setRecipe(recipeName, result) {
590
- const set = getOrCreateSet(this.recipe, recipeName);
591
- set.add(this.append(Object.assign({ type: "recipe" }, result)));
592
- const encoder = this.encoder;
593
- const recipes = this.context.recipes;
594
- const recipeConfig = recipes.getConfig(recipeName);
595
- if (!recipeConfig) return;
596
- const recipe = result;
597
- if (result.type) {
598
- recipe.data.forEach((data) => {
599
- const [recipeProps, styleProps] = recipes.splitProps(recipeName, data);
600
- encoder.processStyleProps(styleProps);
601
- encoder.processRecipe(recipeName, recipeProps);
602
- });
603
- } else {
604
- recipe.data.forEach((data) => {
605
- encoder.processRecipe(recipeName, data);
606
- });
607
- }
608
- }
609
- isEmpty() {
610
- return this.all.length === 0;
611
- }
612
- setFilePath(filePath) {
613
- this.filePath = filePath;
614
- return this;
615
- }
616
- merge(result) {
617
- result.css.forEach((item) => this.css.add(this.append(item)));
618
- result.cva.forEach((item) => this.cva.add(this.append(item)));
619
- result.sva.forEach((item) => this.sva.add(this.append(item)));
620
- result.token.forEach((item) => this.token.add(this.append(item)));
621
- result.jsx.forEach((item) => this.jsx.add(this.append(item)));
622
- result.recipe.forEach((items, name) => {
623
- const set = getOrCreateSet(this.recipe, name);
624
- items.forEach((item) => set.add(this.append(item)));
625
- });
626
- result.pattern.forEach((items, name) => {
627
- const set = getOrCreateSet(this.pattern, name);
628
- items.forEach((item) => set.add(this.append(item)));
629
- });
630
- return this;
631
- }
632
- toArray() {
633
- return this.all;
634
- }
635
- toJSON() {
636
- return {
637
- css: Array.from(this.css),
638
- cva: Array.from(this.cva),
639
- sva: Array.from(this.sva),
640
- token: Array.from(this.token),
641
- jsx: Array.from(this.jsx),
642
- recipe: Object.fromEntries(Array.from(this.recipe.entries()).map(([key, value]) => [key, Array.from(value)])),
643
- pattern: Object.fromEntries(Array.from(this.pattern.entries()).map(([key, value]) => [key, Array.from(value)]))
644
- };
645
- }
646
- };
647
-
648
- // src/parser.ts
649
- var combineResult = (unboxed) => {
650
- return [...unboxed.conditions, unboxed.raw, ...unboxed.spreadConditions];
476
+ context;
477
+ /** Ordered list of all ResultItem */
478
+ all = [];
479
+ jsx = /* @__PURE__ */ new Set();
480
+ css = /* @__PURE__ */ new Set();
481
+ cva = /* @__PURE__ */ new Set();
482
+ sva = /* @__PURE__ */ new Set();
483
+ token = /* @__PURE__ */ new Set();
484
+ recipe = /* @__PURE__ */ new Map();
485
+ pattern = /* @__PURE__ */ new Map();
486
+ filePath;
487
+ encoder;
488
+ constructor(context, encoder) {
489
+ this.context = context;
490
+ this.encoder = encoder ?? context.encoder;
491
+ }
492
+ append(result) {
493
+ this.all.push(result);
494
+ return result;
495
+ }
496
+ set(name, result) {
497
+ switch (name) {
498
+ case "css":
499
+ this.setCss(result);
500
+ break;
501
+ case "cva":
502
+ this.setCva(result);
503
+ break;
504
+ case "sva":
505
+ this.setSva(result);
506
+ break;
507
+ case "token":
508
+ this.setToken(result);
509
+ break;
510
+ default: throw new BambooError("UNKNOWN_RESULT_TYPE", `Unknown parser result type: "${name}". Expected one of: css, cva, sva, token`);
511
+ }
512
+ }
513
+ setCss(result) {
514
+ this.css.add(this.append(Object.assign({ type: "css" }, result)));
515
+ const encoder = this.encoder;
516
+ 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));
519
+ return;
520
+ }
521
+ 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);
523
+ if (!Array.from(keyCounts.values()).some((c) => c > 1)) {
524
+ encoder.processGrouped(Object.assign({}, ...result.data));
525
+ return;
526
+ }
527
+ const overlappingKeys = /* @__PURE__ */ new Set();
528
+ keyCounts.forEach((count, key) => {
529
+ if (count > 1) overlappingKeys.add(key);
530
+ });
531
+ const base = {};
532
+ 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);
535
+ const branchGroups = /* @__PURE__ */ new Map();
536
+ for (const entry of branchEntries) {
537
+ const keySet = Object.keys(entry).sort().join("\0");
538
+ const group = branchGroups.get(keySet) || [];
539
+ group.push(entry);
540
+ branchGroups.set(keySet, group);
541
+ }
542
+ const groupArrays = Array.from(branchGroups.values());
543
+ if (groupArrays.reduce((acc, g) => acc * g.length, 1) > 32) {
544
+ result.data.forEach((obj) => encoder.processGrouped(obj));
545
+ return;
546
+ }
547
+ for (const combo of cartesian(groupArrays)) encoder.processGrouped(Object.assign({}, base, ...combo));
548
+ }
549
+ setCva(result) {
550
+ this.cva.add(this.append(Object.assign({ type: "cva" }, result)));
551
+ const encoder = this.encoder;
552
+ result.data.forEach((data) => encoder.processAtomicRecipe(data));
553
+ }
554
+ setSva(result) {
555
+ this.sva.add(this.append(Object.assign({ type: "sva" }, result)));
556
+ const encoder = this.encoder;
557
+ result.data.forEach((data) => encoder.processAtomicSlotRecipe(data));
558
+ }
559
+ setToken(result) {
560
+ this.token.add(this.append(Object.assign({ type: "token" }, result)));
561
+ }
562
+ setJsx(result) {
563
+ this.jsx.add(this.append(Object.assign({ type: "jsx" }, result)));
564
+ const encoder = this.encoder;
565
+ const grouped = this.context.config.cssMode === "grouped";
566
+ result.data.forEach((obj) => encoder.processStyleProps(obj, grouped));
567
+ }
568
+ setPattern(name, result) {
569
+ getOrCreateSet(this.pattern, name).add(this.append(Object.assign({
570
+ type: "pattern",
571
+ name
572
+ }, result)));
573
+ const encoder = this.encoder;
574
+ result.data.forEach((obj) => encoder.processPattern(name, obj, result.type ?? "pattern", result.name));
575
+ }
576
+ setRecipe(recipeName, result) {
577
+ getOrCreateSet(this.recipe, recipeName).add(this.append(Object.assign({ type: "recipe" }, result)));
578
+ const encoder = this.encoder;
579
+ const recipes = this.context.recipes;
580
+ if (!recipes.getConfig(recipeName)) return;
581
+ const recipe = result;
582
+ if (result.type) recipe.data.forEach((data) => {
583
+ const [recipeProps, styleProps] = recipes.splitProps(recipeName, data);
584
+ encoder.processStyleProps(styleProps);
585
+ encoder.processRecipe(recipeName, recipeProps);
586
+ });
587
+ else recipe.data.forEach((data) => {
588
+ encoder.processRecipe(recipeName, data);
589
+ });
590
+ }
591
+ isEmpty() {
592
+ return this.all.length === 0;
593
+ }
594
+ setFilePath(filePath) {
595
+ this.filePath = filePath;
596
+ return this;
597
+ }
598
+ merge(result) {
599
+ result.css.forEach((item) => this.css.add(this.append(item)));
600
+ result.cva.forEach((item) => this.cva.add(this.append(item)));
601
+ result.sva.forEach((item) => this.sva.add(this.append(item)));
602
+ result.token.forEach((item) => this.token.add(this.append(item)));
603
+ result.jsx.forEach((item) => this.jsx.add(this.append(item)));
604
+ result.recipe.forEach((items, name) => {
605
+ const set = getOrCreateSet(this.recipe, name);
606
+ items.forEach((item) => set.add(this.append(item)));
607
+ });
608
+ result.pattern.forEach((items, name) => {
609
+ const set = getOrCreateSet(this.pattern, name);
610
+ items.forEach((item) => set.add(this.append(item)));
611
+ });
612
+ return this;
613
+ }
614
+ toArray() {
615
+ return this.all;
616
+ }
617
+ toJSON() {
618
+ return {
619
+ css: Array.from(this.css),
620
+ cva: Array.from(this.cva),
621
+ sva: Array.from(this.sva),
622
+ token: Array.from(this.token),
623
+ jsx: Array.from(this.jsx),
624
+ recipe: Object.fromEntries(Array.from(this.recipe.entries()).map(([key, value]) => [key, Array.from(value)])),
625
+ pattern: Object.fromEntries(Array.from(this.pattern.entries()).map(([key, value]) => [key, Array.from(value)]))
626
+ };
627
+ }
651
628
  };
652
- var defaultEnv = {
653
- preset: "ECMA"
654
- };
655
- var evaluateOptions = {
656
- environment: defaultEnv
629
+ //#endregion
630
+ //#region src/parser.ts
631
+ const combineResult = (unboxed) => {
632
+ return [
633
+ ...unboxed.conditions,
634
+ unboxed.raw,
635
+ ...unboxed.spreadConditions
636
+ ];
657
637
  };
638
+ const defaultEnv = { preset: "ECMA" };
639
+ const evaluateOptions = { environment: defaultEnv };
658
640
  function createParser(context) {
659
- const { jsx, imports, recipes, config } = context;
660
- const syntax = config.syntax;
661
- return function parse(sourceFile, encoder, options) {
662
- if (!sourceFile) return;
663
- const importDeclarations = getImportDeclarations(context, sourceFile);
664
- const file = imports.file(importDeclarations);
665
- const filePath = sourceFile.getFilePath();
666
- logger.debug(
667
- "ast:import",
668
- !file.isEmpty() ? `Found import { ${file.toString()} } in ${filePath}` : `No import found in ${filePath}`
669
- );
670
- const parserResult = new ParserResult(context, encoder);
671
- if (file.isEmpty() && !jsx.isEnabled) {
672
- return parserResult;
673
- }
674
- const extractResultByName = extract({
675
- ast: sourceFile,
676
- tokens: context.tokens ? {
677
- view: context.tokens.view,
678
- isTokenFn: (fnName) => file.isTokenAlias(fnName)
679
- } : void 0,
680
- components: jsx.isEnabled ? {
681
- matchTag: (prop) => {
682
- if (options?.matchTag) {
683
- const isBambooComponent = file.isBambooComponent(prop.tagName);
684
- const matchTagMode = options.matchTagMode ?? "extend";
685
- const isCustomMatch = options.matchTag(prop.tagName, isBambooComponent);
686
- if (matchTagMode === "override") {
687
- return isCustomMatch;
688
- }
689
- return isBambooComponent || isCustomMatch;
690
- }
691
- return !!file.matchTag(prop.tagName);
692
- },
693
- matchProp: (prop) => {
694
- const isBambooProp = file.matchTagProp(prop.tagName, prop.propName);
695
- if (options?.matchTagProp) {
696
- return isBambooProp && options.matchTagProp(prop.tagName, prop.propName);
697
- }
698
- return isBambooProp;
699
- }
700
- } : void 0,
701
- functions: {
702
- matchFn: (prop) => file.matchFn(prop.fnName),
703
- matchProp: () => true,
704
- matchArg: (prop) => {
705
- if (file.isJsxFactory(prop.fnName) && prop.index === 1 && Node.isIdentifier(prop.argNode)) return false;
706
- return true;
707
- }
708
- },
709
- taggedTemplates: syntax === "template-literal" ? {
710
- matchTaggedTemplate: (tag) => file.matchFn(tag.fnName)
711
- } : void 0,
712
- getEvaluateOptions: (node) => {
713
- if (!Node.isCallExpression(node)) return evaluateOptions;
714
- const propAccessExpr = node.getExpression();
715
- if (!Node.isPropertyAccessExpression(propAccessExpr)) return evaluateOptions;
716
- let name = propAccessExpr.getText();
717
- if (!file.isRawFn(name)) {
718
- return evaluateOptions;
719
- }
720
- name = name.replace(".raw", "");
721
- return {
722
- environment: Object.assign({}, defaultEnv, {
723
- extra: {
724
- [name]: { raw: (v) => v }
725
- }
726
- })
727
- };
728
- },
729
- flags: { skipTraverseFiles: true }
730
- });
731
- extractResultByName.forEach((result, alias) => {
732
- const name = file.getName(file.normalizeFnName(alias));
733
- logger.debug(`ast:${name}`, name !== alias ? { kind: result.kind, alias } : { kind: result.kind });
734
- if (result.kind === "function") {
735
- match(name).when(imports.matchers.css.match, (name2) => {
736
- result.queryList.forEach((query) => {
737
- if (query.kind === "call-expression") {
738
- if (query.box.value.length > 1) {
739
- parserResult.set(name2, {
740
- name: name2,
741
- box: query.box,
742
- data: query.box.value.reduce(
743
- (acc, value) => [...acc, ...combineResult(unbox(value))],
744
- []
745
- )
746
- });
747
- } else {
748
- parserResult.set(name2, {
749
- name: name2,
750
- box: query.box.value[0] ?? box2.fallback(query.box),
751
- data: combineResult(unbox(query.box.value[0]))
752
- });
753
- }
754
- } else if (query.kind === "tagged-template") {
755
- const obj = astish(query.box.value);
756
- parserResult.set(name2, {
757
- name: name2,
758
- box: query.box ?? box2.fallback(query.box),
759
- data: [obj]
760
- });
761
- }
762
- });
763
- }).when(imports.matchers.tokens.match, (name2) => {
764
- result.queryList.forEach((query) => {
765
- if (query.kind === "call-expression") {
766
- parserResult.setToken({
767
- name: name2,
768
- box: query.box.value[0] ?? box2.fallback(query.box),
769
- data: combineResult(unbox(query.box.value[0]))
770
- });
771
- }
772
- });
773
- }).when(file.isValidPattern, (name2) => {
774
- result.queryList.forEach((query) => {
775
- if (query.kind === "call-expression") {
776
- parserResult.setPattern(name2, {
777
- name: name2,
778
- box: query.box.value[0] ?? box2.fallback(query.box),
779
- data: combineResult(unbox(query.box.value[0]))
780
- });
781
- }
782
- });
783
- }).when(file.isValidRecipe, (name2) => {
784
- result.queryList.forEach((query) => {
785
- if (query.kind === "call-expression") {
786
- parserResult.setRecipe(name2, {
787
- name: name2,
788
- box: query.box.value[0] ?? box2.fallback(query.box),
789
- data: combineResult(unbox(query.box.value[0]))
790
- });
791
- }
792
- });
793
- }).when(jsx.isJsxFactory, () => {
794
- result.queryList.forEach((query) => {
795
- if (query.kind === "call-expression" && query.box.value[1]) {
796
- const map = query.box.value[1];
797
- const boxNode = box2.isMap(map) ? map : box2.fallback(query.box);
798
- const combined = combineResult(unbox(boxNode));
799
- const transformed = options?.transform?.({ type: "jsx-factory", data: combined });
800
- const result2 = { name, box: boxNode, data: transformed ?? combined };
801
- if (box2.isRecipe(map)) {
802
- parserResult.setCva(result2);
803
- } else {
804
- parserResult.set("css", result2);
805
- }
806
- const recipeOptions = query.box.value[2];
807
- if (box2.isUnresolvable(map) && recipeOptions && box2.isMap(recipeOptions) && recipeOptions.value.has("defaultProps")) {
808
- const maybeIdentifier = map.getNode();
809
- if (Node.isIdentifier(maybeIdentifier)) {
810
- const name2 = maybeIdentifier.getText();
811
- const recipeName = file.getName(name2);
812
- parserResult.setRecipe(recipeName, {
813
- type: "jsx-recipe",
814
- name: recipeName,
815
- box: recipeOptions,
816
- data: combineResult(unbox(recipeOptions.value.get("defaultProps")))
817
- });
818
- }
819
- }
820
- } else if (query.kind === "tagged-template") {
821
- const obj = astish(query.box.value);
822
- parserResult.set("css", {
823
- name,
824
- box: query.box ?? box2.fallback(query.box),
825
- data: [obj]
826
- });
827
- }
828
- });
829
- }).when(file.isJsxFactory, (name2) => {
830
- result.queryList.forEach((query) => {
831
- if (query.kind === "call-expression") {
832
- const map = query.box.value[0];
833
- const boxNode = box2.isMap(map) ? map : box2.fallback(query.box);
834
- const combined = combineResult(unbox(boxNode));
835
- const transformed = options?.transform?.({ type: "jsx-factory", data: combined });
836
- const result2 = { name: name2, box: boxNode, data: transformed ?? combined };
837
- if (box2.isRecipe(map)) {
838
- parserResult.setCva(result2);
839
- } else {
840
- parserResult.set("css", result2);
841
- }
842
- } else if (query.kind === "tagged-template") {
843
- const obj = astish(query.box.value);
844
- parserResult.set("css", {
845
- name: name2,
846
- box: query.box ?? box2.fallback(query.box),
847
- data: [obj]
848
- });
849
- }
850
- });
851
- }).otherwise(() => {
852
- });
853
- } else if (jsx.isEnabled && result.kind === "component") {
854
- result.queryList.forEach((query) => {
855
- const data = combineResult(unbox(query.box));
856
- switch (true) {
857
- case (file.isJsxFactory(name) || file.isJsxFactory(alias)): {
858
- parserResult.setJsx({ type: "jsx-factory", name, box: query.box, data });
859
- break;
860
- }
861
- case (jsx.isJsxTagPattern(name) || jsx.isJsxTagPattern(alias)): {
862
- parserResult.setPattern(name, { type: "jsx-pattern", name, box: query.box, data });
863
- break;
864
- }
865
- // name: Trigger
866
- case jsx.isJsxTagRecipe(name): {
867
- const matchingRecipes = recipes.filter(name);
868
- matchingRecipes.map((recipe) => {
869
- parserResult.setRecipe(recipe.baseName, { type: "jsx-recipe", name, box: query.box, data });
870
- });
871
- break;
872
- }
873
- // alias: Tabs.Trigger
874
- case jsx.isJsxTagRecipe(alias): {
875
- const matchingRecipes = recipes.filter(alias);
876
- matchingRecipes.map((recipe) => {
877
- parserResult.setRecipe(recipe.baseName, { type: "jsx-recipe", name: alias, box: query.box, data });
878
- });
879
- break;
880
- }
881
- default: {
882
- parserResult.setJsx({ type: "jsx", name, box: query.box, data });
883
- }
884
- }
885
- });
886
- }
887
- });
888
- return parserResult;
889
- };
641
+ const { jsx, imports, recipes, config } = context;
642
+ const syntax = config.syntax;
643
+ return function parse(sourceFile, encoder, options) {
644
+ if (!sourceFile) return;
645
+ const importDeclarations = getImportDeclarations(context, sourceFile);
646
+ const file = imports.file(importDeclarations);
647
+ const filePath = sourceFile.getFilePath();
648
+ logger.debug("ast:import", !file.isEmpty() ? `Found import { ${file.toString()} } in ${filePath}` : `No import found in ${filePath}`);
649
+ const parserResult = new ParserResult(context, encoder);
650
+ if (file.isEmpty() && !jsx.isEnabled) return parserResult;
651
+ extract({
652
+ ast: sourceFile,
653
+ tokens: context.tokens ? {
654
+ view: context.tokens.view,
655
+ isTokenFn: (fnName) => file.isTokenAlias(fnName)
656
+ } : void 0,
657
+ components: jsx.isEnabled ? {
658
+ matchTag: (prop) => {
659
+ if (options?.matchTag) {
660
+ const isBambooComponent = file.isBambooComponent(prop.tagName);
661
+ const matchTagMode = options.matchTagMode ?? "extend";
662
+ const isCustomMatch = options.matchTag(prop.tagName, isBambooComponent);
663
+ if (matchTagMode === "override") return isCustomMatch;
664
+ return isBambooComponent || isCustomMatch;
665
+ }
666
+ return !!file.matchTag(prop.tagName);
667
+ },
668
+ matchProp: (prop) => {
669
+ const isBambooProp = file.matchTagProp(prop.tagName, prop.propName);
670
+ if (options?.matchTagProp) return isBambooProp && options.matchTagProp(prop.tagName, prop.propName);
671
+ return isBambooProp;
672
+ }
673
+ } : void 0,
674
+ functions: {
675
+ matchFn: (prop) => file.matchFn(prop.fnName),
676
+ matchProp: () => true,
677
+ matchArg: (prop) => {
678
+ if (file.isJsxFactory(prop.fnName) && prop.index === 1 && Node.isIdentifier(prop.argNode)) return false;
679
+ return true;
680
+ }
681
+ },
682
+ taggedTemplates: syntax === "template-literal" ? { matchTaggedTemplate: (tag) => file.matchFn(tag.fnName) } : void 0,
683
+ getEvaluateOptions: (node) => {
684
+ if (!Node.isCallExpression(node)) return evaluateOptions;
685
+ const propAccessExpr = node.getExpression();
686
+ if (!Node.isPropertyAccessExpression(propAccessExpr)) return evaluateOptions;
687
+ let name = propAccessExpr.getText();
688
+ if (!file.isRawFn(name)) return evaluateOptions;
689
+ name = name.replace(".raw", "");
690
+ return { environment: Object.assign({}, defaultEnv, { extra: { [name]: { raw: (v) => v } } }) };
691
+ },
692
+ flags: { skipTraverseFiles: true }
693
+ }).forEach((result, alias) => {
694
+ const name = file.getName(file.normalizeFnName(alias));
695
+ logger.debug(`ast:${name}`, name !== alias ? {
696
+ kind: result.kind,
697
+ alias
698
+ } : { kind: result.kind });
699
+ if (result.kind === "function") match(name).when(imports.matchers.css.match, (name) => {
700
+ result.queryList.forEach((query) => {
701
+ if (query.kind === "call-expression") if (query.box.value.length > 1) parserResult.set(name, {
702
+ name,
703
+ box: query.box,
704
+ data: query.box.value.reduce((acc, value) => [...acc, ...combineResult(unbox(value))], [])
705
+ });
706
+ else parserResult.set(name, {
707
+ name,
708
+ box: query.box.value[0] ?? box.fallback(query.box),
709
+ data: combineResult(unbox(query.box.value[0]))
710
+ });
711
+ else if (query.kind === "tagged-template") {
712
+ const obj = astish(query.box.value);
713
+ parserResult.set(name, {
714
+ name,
715
+ box: query.box ?? box.fallback(query.box),
716
+ data: [obj]
717
+ });
718
+ }
719
+ });
720
+ }).when(imports.matchers.tokens.match, (name) => {
721
+ result.queryList.forEach((query) => {
722
+ if (query.kind === "call-expression") parserResult.setToken({
723
+ name,
724
+ box: query.box.value[0] ?? box.fallback(query.box),
725
+ data: combineResult(unbox(query.box.value[0]))
726
+ });
727
+ });
728
+ }).when(file.isValidPattern, (name) => {
729
+ result.queryList.forEach((query) => {
730
+ if (query.kind === "call-expression") parserResult.setPattern(name, {
731
+ name,
732
+ box: query.box.value[0] ?? box.fallback(query.box),
733
+ data: combineResult(unbox(query.box.value[0]))
734
+ });
735
+ });
736
+ }).when(file.isValidRecipe, (name) => {
737
+ result.queryList.forEach((query) => {
738
+ if (query.kind === "call-expression") parserResult.setRecipe(name, {
739
+ name,
740
+ box: query.box.value[0] ?? box.fallback(query.box),
741
+ data: combineResult(unbox(query.box.value[0]))
742
+ });
743
+ });
744
+ }).when(jsx.isJsxFactory, () => {
745
+ result.queryList.forEach((query) => {
746
+ if (query.kind === "call-expression" && query.box.value[1]) {
747
+ const map = query.box.value[1];
748
+ const boxNode = box.isMap(map) ? map : box.fallback(query.box);
749
+ const combined = combineResult(unbox(boxNode));
750
+ const result = {
751
+ name,
752
+ box: boxNode,
753
+ data: options?.transform?.({
754
+ type: "jsx-factory",
755
+ data: combined
756
+ }) ?? combined
757
+ };
758
+ if (box.isRecipe(map)) parserResult.setCva(result);
759
+ else parserResult.set("css", result);
760
+ const recipeOptions = query.box.value[2];
761
+ if (box.isUnresolvable(map) && recipeOptions && box.isMap(recipeOptions) && recipeOptions.value.has("defaultProps")) {
762
+ const maybeIdentifier = map.getNode();
763
+ if (Node.isIdentifier(maybeIdentifier)) {
764
+ const name = maybeIdentifier.getText();
765
+ const recipeName = file.getName(name);
766
+ parserResult.setRecipe(recipeName, {
767
+ type: "jsx-recipe",
768
+ name: recipeName,
769
+ box: recipeOptions,
770
+ data: combineResult(unbox(recipeOptions.value.get("defaultProps")))
771
+ });
772
+ }
773
+ }
774
+ } else if (query.kind === "tagged-template") {
775
+ const obj = astish(query.box.value);
776
+ parserResult.set("css", {
777
+ name,
778
+ box: query.box ?? box.fallback(query.box),
779
+ data: [obj]
780
+ });
781
+ }
782
+ });
783
+ }).when(file.isJsxFactory, (name) => {
784
+ result.queryList.forEach((query) => {
785
+ if (query.kind === "call-expression") {
786
+ const map = query.box.value[0];
787
+ const boxNode = box.isMap(map) ? map : box.fallback(query.box);
788
+ const combined = combineResult(unbox(boxNode));
789
+ const result = {
790
+ name,
791
+ box: boxNode,
792
+ data: options?.transform?.({
793
+ type: "jsx-factory",
794
+ data: combined
795
+ }) ?? combined
796
+ };
797
+ if (box.isRecipe(map)) parserResult.setCva(result);
798
+ else parserResult.set("css", result);
799
+ } else if (query.kind === "tagged-template") {
800
+ const obj = astish(query.box.value);
801
+ parserResult.set("css", {
802
+ name,
803
+ box: query.box ?? box.fallback(query.box),
804
+ data: [obj]
805
+ });
806
+ }
807
+ });
808
+ }).otherwise(() => {});
809
+ else if (jsx.isEnabled && result.kind === "component") result.queryList.forEach((query) => {
810
+ const data = combineResult(unbox(query.box));
811
+ switch (true) {
812
+ case file.isJsxFactory(name) || file.isJsxFactory(alias):
813
+ parserResult.setJsx({
814
+ type: "jsx-factory",
815
+ name,
816
+ box: query.box,
817
+ data
818
+ });
819
+ break;
820
+ case jsx.isJsxTagPattern(name) || jsx.isJsxTagPattern(alias):
821
+ parserResult.setPattern(name, {
822
+ type: "jsx-pattern",
823
+ name,
824
+ box: query.box,
825
+ data
826
+ });
827
+ break;
828
+ case jsx.isJsxTagRecipe(name):
829
+ recipes.filter(name).map((recipe) => {
830
+ parserResult.setRecipe(recipe.baseName, {
831
+ type: "jsx-recipe",
832
+ name,
833
+ box: query.box,
834
+ data
835
+ });
836
+ });
837
+ break;
838
+ case jsx.isJsxTagRecipe(alias):
839
+ recipes.filter(alias).map((recipe) => {
840
+ parserResult.setRecipe(recipe.baseName, {
841
+ type: "jsx-recipe",
842
+ name: alias,
843
+ box: query.box,
844
+ data
845
+ });
846
+ });
847
+ break;
848
+ default: parserResult.setJsx({
849
+ type: "jsx",
850
+ name,
851
+ box: query.box,
852
+ data
853
+ });
854
+ }
855
+ });
856
+ });
857
+ return parserResult;
858
+ };
890
859
  }
891
-
892
- // src/project.ts
893
- var normalizeCompilerOptions = (raw) => {
894
- if (!raw) return {};
895
- const { options } = ts.convertCompilerOptionsFromJson(raw, process.cwd());
896
- return options;
860
+ //#endregion
861
+ //#region src/project.ts
862
+ const normalizeCompilerOptions = (raw) => {
863
+ if (!raw) return {};
864
+ const { options } = ts.convertCompilerOptionsFromJson(raw, process.cwd());
865
+ return options;
897
866
  };
898
- var createTsProject = (options) => new TsProject({
899
- skipAddingFilesFromTsConfig: true,
900
- skipFileDependencyResolution: true,
901
- skipLoadingLibFiles: true,
902
- ...options,
903
- compilerOptions: {
904
- allowJs: true,
905
- strictNullChecks: false,
906
- skipLibCheck: true,
907
- ...normalizeCompilerOptions(options.compilerOptions)
908
- }
867
+ const createTsProject = (options) => new Project$1({
868
+ skipAddingFilesFromTsConfig: true,
869
+ skipFileDependencyResolution: true,
870
+ skipLoadingLibFiles: true,
871
+ ...options,
872
+ compilerOptions: {
873
+ allowJs: true,
874
+ strictNullChecks: false,
875
+ skipLibCheck: true,
876
+ ...normalizeCompilerOptions(options.compilerOptions)
877
+ }
909
878
  });
910
879
  var Project = class {
911
- constructor(options) {
912
- this.options = options;
913
- const { parserOptions } = options;
914
- this.project = createTsProject(options);
915
- this.parser = createParser(parserOptions);
916
- this.createSourceFiles();
917
- }
918
- project;
919
- parser;
920
- get parserOptions() {
921
- return this.options.parserOptions;
922
- }
923
- get files() {
924
- return this.options.getFiles();
925
- }
926
- getSourceFile = (filePath) => {
927
- return this.project.getSourceFile(filePath);
928
- };
929
- createSourceFile = (filePath) => {
930
- const { readFile } = this.options;
931
- return this.project.createSourceFile(filePath, readFile(filePath), {
932
- overwrite: true,
933
- scriptKind: ScriptKind.TSX
934
- });
935
- };
936
- createSourceFiles = () => {
937
- const files = this.getFiles();
938
- for (const file of files) {
939
- this.createSourceFile(file);
940
- }
941
- };
942
- addSourceFile = (filePath, content) => {
943
- return this.project.createSourceFile(filePath, content, {
944
- overwrite: true,
945
- scriptKind: ScriptKind.TSX
946
- });
947
- };
948
- removeSourceFile = (filePath) => {
949
- const sourceFile = this.project.getSourceFile(filePath);
950
- if (sourceFile) {
951
- return this.project.removeSourceFile(sourceFile);
952
- }
953
- return false;
954
- };
955
- reloadSourceFile = (filePath) => {
956
- return this.getSourceFile(filePath)?.refreshFromFileSystemSync();
957
- };
958
- reloadSourceFiles = () => {
959
- const files = this.getFiles();
960
- for (const file of files) {
961
- const source = this.getSourceFile(file);
962
- source?.refreshFromFileSystemSync() ?? this.project.addSourceFileAtPath(file);
963
- }
964
- };
965
- get readFile() {
966
- return this.options.readFile;
967
- }
968
- get getFiles() {
969
- return this.options.getFiles;
970
- }
971
- parseJson = (filePath) => {
972
- const { readFile, parserOptions } = this.options;
973
- const content = readFile(filePath);
974
- parserOptions.encoder.fromJSON(JSON.parse(content));
975
- const result = new ParserResult(parserOptions);
976
- return result.setFilePath(filePath);
977
- };
978
- parseSourceFile = (filePath, encoder) => {
979
- const { hooks } = this.options;
980
- if (filePath.endsWith(".json")) {
981
- return this.parseJson(filePath);
982
- }
983
- const sourceFile = this.project.getSourceFile(filePath);
984
- if (!sourceFile) return;
985
- const original = sourceFile.getText();
986
- const options = {};
987
- const custom = hooks["parser:before"]?.({
988
- filePath,
989
- content: original,
990
- configure(opts) {
991
- const { matchTag, matchTagMode, matchTagProp } = opts;
992
- if (matchTag) {
993
- options.matchTag = matchTag;
994
- }
995
- if (matchTagMode) {
996
- options.matchTagMode = matchTagMode;
997
- }
998
- if (matchTagProp) {
999
- options.matchTagProp = matchTagProp;
1000
- }
1001
- }
1002
- });
1003
- const transformed = custom ?? this.transformFile(filePath, original);
1004
- if (original !== transformed) {
1005
- sourceFile.replaceWithText(transformed);
1006
- }
1007
- if (hooks["parser:preprocess"]) {
1008
- options.transform = hooks["parser:preprocess"];
1009
- }
1010
- const result = this.parser(sourceFile, encoder, options)?.setFilePath(filePath);
1011
- hooks["parser:after"]?.({ filePath, result });
1012
- return result;
1013
- };
1014
- transformFile = (_filePath, content) => {
1015
- return content;
1016
- };
1017
- classify = (fileMap) => {
1018
- const { parserOptions } = this.options;
1019
- return classifyProject(parserOptions, fileMap);
1020
- };
1021
- };
1022
- export {
1023
- ParserResult,
1024
- Project
880
+ options;
881
+ project;
882
+ parser;
883
+ get parserOptions() {
884
+ return this.options.parserOptions;
885
+ }
886
+ constructor(options) {
887
+ this.options = options;
888
+ const { parserOptions } = options;
889
+ this.project = createTsProject(options);
890
+ this.parser = createParser(parserOptions);
891
+ this.createSourceFiles();
892
+ }
893
+ get files() {
894
+ return this.options.getFiles();
895
+ }
896
+ getSourceFile = (filePath) => {
897
+ return this.project.getSourceFile(filePath);
898
+ };
899
+ createSourceFile = (filePath) => {
900
+ const { readFile } = this.options;
901
+ return this.project.createSourceFile(filePath, readFile(filePath), {
902
+ overwrite: true,
903
+ scriptKind: ScriptKind.TSX
904
+ });
905
+ };
906
+ createSourceFiles = () => {
907
+ const files = this.getFiles();
908
+ for (const file of files) this.createSourceFile(file);
909
+ };
910
+ addSourceFile = (filePath, content) => {
911
+ return this.project.createSourceFile(filePath, content, {
912
+ overwrite: true,
913
+ scriptKind: ScriptKind.TSX
914
+ });
915
+ };
916
+ removeSourceFile = (filePath) => {
917
+ const sourceFile = this.project.getSourceFile(filePath);
918
+ if (sourceFile) return this.project.removeSourceFile(sourceFile);
919
+ return false;
920
+ };
921
+ reloadSourceFile = (filePath) => {
922
+ return this.getSourceFile(filePath)?.refreshFromFileSystemSync();
923
+ };
924
+ reloadSourceFiles = () => {
925
+ const files = this.getFiles();
926
+ for (const file of files) this.getSourceFile(file)?.refreshFromFileSystemSync() ?? this.project.addSourceFileAtPath(file);
927
+ };
928
+ get readFile() {
929
+ return this.options.readFile;
930
+ }
931
+ get getFiles() {
932
+ return this.options.getFiles;
933
+ }
934
+ parseJson = (filePath) => {
935
+ const { readFile, parserOptions } = this.options;
936
+ const content = readFile(filePath);
937
+ parserOptions.encoder.fromJSON(JSON.parse(content));
938
+ return new ParserResult(parserOptions).setFilePath(filePath);
939
+ };
940
+ parseSourceFile = (filePath, encoder) => {
941
+ const { hooks } = this.options;
942
+ if (filePath.endsWith(".json")) return this.parseJson(filePath);
943
+ const sourceFile = this.project.getSourceFile(filePath);
944
+ if (!sourceFile) return;
945
+ const original = sourceFile.getText();
946
+ const options = {};
947
+ const transformed = hooks["parser:before"]?.({
948
+ filePath,
949
+ content: original,
950
+ configure(opts) {
951
+ const { matchTag, matchTagMode, matchTagProp } = opts;
952
+ if (matchTag) options.matchTag = matchTag;
953
+ if (matchTagMode) options.matchTagMode = matchTagMode;
954
+ if (matchTagProp) options.matchTagProp = matchTagProp;
955
+ }
956
+ }) ?? this.transformFile(filePath, original);
957
+ if (original !== transformed) sourceFile.replaceWithText(transformed);
958
+ if (hooks["parser:preprocess"]) options.transform = hooks["parser:preprocess"];
959
+ const result = this.parser(sourceFile, encoder, options)?.setFilePath(filePath);
960
+ hooks["parser:after"]?.({
961
+ filePath,
962
+ result
963
+ });
964
+ return result;
965
+ };
966
+ transformFile = (_filePath, content) => {
967
+ return content;
968
+ };
969
+ classify = (fileMap) => {
970
+ const { parserOptions } = this.options;
971
+ return classifyProject(parserOptions, fileMap);
972
+ };
1025
973
  };
974
+ //#endregion
975
+ export { ParserResult, Project };