@pandacss/parser 0.0.0-dev-20230413133612 → 0.0.0-dev-20230413141731
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.ts +15 -5
- package/dist/index.js +145 -324
- package/dist/index.mjs +143 -324
- package/package.json +8 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import * as _pandacss_types from '@pandacss/types';
|
|
2
|
+
import { RecipeConfig } from '@pandacss/types';
|
|
2
3
|
import * as ts_morph from 'ts-morph';
|
|
3
4
|
import { ProjectOptions as ProjectOptions$1 } from 'ts-morph';
|
|
4
5
|
|
|
5
|
-
type
|
|
6
|
+
type ParserPatternNode = {
|
|
6
7
|
name: string;
|
|
7
|
-
type: 'pattern'
|
|
8
|
+
type: 'pattern';
|
|
8
9
|
props?: string[];
|
|
9
10
|
baseName: string;
|
|
10
11
|
};
|
|
12
|
+
type ParserRecipeNode = {
|
|
13
|
+
name: string;
|
|
14
|
+
type: 'recipe';
|
|
15
|
+
props: string[];
|
|
16
|
+
baseName: string;
|
|
17
|
+
jsx: RecipeConfig['jsx'];
|
|
18
|
+
};
|
|
19
|
+
type ParserNodeOptions = ParserPatternNode | ParserRecipeNode;
|
|
11
20
|
type ParserOptions = {
|
|
12
21
|
importMap: Record<'css' | 'recipe' | 'pattern' | 'jsx', string>;
|
|
13
22
|
jsx?: {
|
|
@@ -15,8 +24,9 @@ type ParserOptions = {
|
|
|
15
24
|
nodes: ParserNodeOptions[];
|
|
16
25
|
isStyleProp: (prop: string) => boolean;
|
|
17
26
|
};
|
|
27
|
+
getRecipeName: (tagName: string) => string;
|
|
28
|
+
getRecipeByName: (name: string) => RecipeConfig | undefined;
|
|
18
29
|
};
|
|
19
|
-
type ParserMode = 'box-extractor' | 'internal';
|
|
20
30
|
|
|
21
31
|
type ProjectOptions = Partial<ProjectOptions$1> & {
|
|
22
32
|
readFile: (filePath: string) => string;
|
|
@@ -27,10 +37,10 @@ declare const createProject: ({ getFiles, readFile, parserOptions, ...projectOpt
|
|
|
27
37
|
getSourceFile: (filePath: string) => ts_morph.SourceFile | undefined;
|
|
28
38
|
removeSourceFile: (filePath: string) => void;
|
|
29
39
|
createSourceFile: (filePath: string) => ts_morph.SourceFile;
|
|
30
|
-
parseSourceFile: (filePath: string, properties: string[]
|
|
40
|
+
parseSourceFile: (filePath: string, properties: string[]) => _pandacss_types.ParserResult | undefined;
|
|
31
41
|
reloadSourceFile: (filePath: string) => ts_morph.FileSystemRefreshResult | undefined;
|
|
32
42
|
reloadSourceFiles: () => void;
|
|
33
43
|
};
|
|
34
44
|
type Project = ReturnType<typeof createProject>;
|
|
35
45
|
|
|
36
|
-
export {
|
|
46
|
+
export { Project, ProjectOptions, createProject };
|
package/dist/index.js
CHANGED
|
@@ -26,124 +26,19 @@ module.exports = __toCommonJS(src_exports);
|
|
|
26
26
|
|
|
27
27
|
// src/project.ts
|
|
28
28
|
var import_lil_fp = require("lil-fp");
|
|
29
|
-
var
|
|
29
|
+
var import_ts_morph2 = require("ts-morph");
|
|
30
30
|
|
|
31
31
|
// src/parser.ts
|
|
32
32
|
var import_extractor = require("@pandacss/extractor");
|
|
33
33
|
var import_logger = require("@pandacss/logger");
|
|
34
34
|
var import_shared2 = require("@pandacss/shared");
|
|
35
|
-
var import_ts_morph4 = require("ts-morph");
|
|
36
|
-
var import_ts_pattern3 = require("ts-pattern");
|
|
37
|
-
|
|
38
|
-
// src/call-expression.ts
|
|
39
|
-
var import_ts_morph2 = require("ts-morph");
|
|
40
|
-
|
|
41
|
-
// src/literal.ts
|
|
42
35
|
var import_ts_morph = require("ts-morph");
|
|
43
36
|
var import_ts_pattern = require("ts-pattern");
|
|
44
37
|
|
|
45
|
-
// src/strip-quotes.ts
|
|
46
|
-
function stripQuotes(q) {
|
|
47
|
-
const quoteStart = `'|"|\u2018|\u201C|\u2039|\xAB`;
|
|
48
|
-
const quoteEnd = `'|"|\u2019|\u201D|\u203A|\xBB`;
|
|
49
|
-
if (typeof q !== "string")
|
|
50
|
-
throw new Error(`input was '${typeof q}' and not of type 'string'`);
|
|
51
|
-
if (!q.length)
|
|
52
|
-
throw new Error(`input was empty`);
|
|
53
|
-
let s = q;
|
|
54
|
-
let t = s.length;
|
|
55
|
-
if (s.charAt(0).match(new RegExp(quoteStart))) {
|
|
56
|
-
s = s.substring(1, t--);
|
|
57
|
-
}
|
|
58
|
-
if (s.charAt(--t).match(new RegExp(quoteEnd))) {
|
|
59
|
-
s = s.substring(0, t);
|
|
60
|
-
}
|
|
61
|
-
return s;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// src/literal.ts
|
|
65
|
-
function isPrimitiveLiteral(node) {
|
|
66
|
-
return import_ts_morph.Node.isStringLiteral(node) || import_ts_morph.Node.isNumericLiteral(node) || import_ts_morph.Node.isTrueLiteral(node) || import_ts_morph.Node.isFalseLiteral(node);
|
|
67
|
-
}
|
|
68
|
-
function extractValue(value) {
|
|
69
|
-
return (0, import_ts_pattern.match)(value).when(
|
|
70
|
-
(node) => import_ts_morph.Node.isStringLiteral(node) || import_ts_morph.Node.isNoSubstitutionTemplateLiteral(node),
|
|
71
|
-
(value2) => {
|
|
72
|
-
return value2.getLiteralValue().replaceAll(/[\n\s]+/g, " ");
|
|
73
|
-
}
|
|
74
|
-
).when(isPrimitiveLiteral, (value2) => {
|
|
75
|
-
return value2.getLiteralValue();
|
|
76
|
-
}).when(import_ts_morph.Node.isNullLiteral, () => {
|
|
77
|
-
return null;
|
|
78
|
-
}).when(import_ts_morph.Node.isObjectLiteralExpression, (value2) => {
|
|
79
|
-
return extractObjectLiteral(value2);
|
|
80
|
-
}).when(import_ts_morph.Node.isArrayLiteralExpression, (value2) => {
|
|
81
|
-
return extractArrayLiteral(value2);
|
|
82
|
-
}).otherwise(() => {
|
|
83
|
-
return void 0;
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
function extractObjectLiteral(node) {
|
|
87
|
-
const data = {};
|
|
88
|
-
const properties = node.getProperties();
|
|
89
|
-
for (const property of properties) {
|
|
90
|
-
if (import_ts_morph.Node.isPropertyAssignment(property)) {
|
|
91
|
-
const key = stripQuotes(property.getName());
|
|
92
|
-
const value = property.getInitializer();
|
|
93
|
-
const returnValue = extractValue(value);
|
|
94
|
-
if (returnValue !== void 0) {
|
|
95
|
-
data[key] = returnValue;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return data;
|
|
100
|
-
}
|
|
101
|
-
function extractArrayLiteral(node) {
|
|
102
|
-
const result = [];
|
|
103
|
-
node.forEachChild((child) => {
|
|
104
|
-
(0, import_ts_pattern.match)(child).when(isPrimitiveLiteral, (child2) => {
|
|
105
|
-
result.push(child2.getLiteralValue());
|
|
106
|
-
}).when(import_ts_morph.Node.isUndefinedKeyword, () => {
|
|
107
|
-
result.push(void 0);
|
|
108
|
-
}).when(import_ts_morph.Node.isNullLiteral, () => {
|
|
109
|
-
result.push(null);
|
|
110
|
-
}).when(import_ts_morph.Node.isObjectLiteralExpression, (child2) => {
|
|
111
|
-
result.push(extractObjectLiteral(child2));
|
|
112
|
-
}).when(import_ts_morph.Node.isArrayLiteralExpression, (child2) => {
|
|
113
|
-
result.push(extractArrayLiteral(child2));
|
|
114
|
-
}).otherwise(() => {
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
return result;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// src/call-expression.ts
|
|
121
|
-
function visitCallExpressions(file, options) {
|
|
122
|
-
const { match: match4, fn } = options;
|
|
123
|
-
const callExpressions = file.getDescendantsOfKind(import_ts_morph2.ts.SyntaxKind.CallExpression);
|
|
124
|
-
for (const node of callExpressions) {
|
|
125
|
-
const expr = node.getExpression();
|
|
126
|
-
const name = expr.getText();
|
|
127
|
-
if (!match4(name)) {
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
const args = node.getArguments();
|
|
131
|
-
if (args.length === 0) {
|
|
132
|
-
fn({ name, data: {} });
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
args.forEach((arg) => {
|
|
136
|
-
if (import_ts_morph2.Node.isObjectLiteralExpression(arg)) {
|
|
137
|
-
fn({ name, data: extractObjectLiteral(arg) });
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
38
|
// src/import.ts
|
|
144
39
|
var import_shared = require("@pandacss/shared");
|
|
145
40
|
function getImportDeclarations(file, options) {
|
|
146
|
-
const { match:
|
|
41
|
+
const { match: match2 } = options;
|
|
147
42
|
const result = [];
|
|
148
43
|
file.getImportDeclarations().forEach((node) => {
|
|
149
44
|
const source = node.getModuleSpecifierValue();
|
|
@@ -153,7 +48,7 @@ function getImportDeclarations(file, options) {
|
|
|
153
48
|
specifiers.forEach((specifier) => {
|
|
154
49
|
const name = specifier.getNameNode().getText();
|
|
155
50
|
const alias = specifier.getAliasNode()?.getText() || name;
|
|
156
|
-
if (!
|
|
51
|
+
if (!match2({ id: name, mod: source }))
|
|
157
52
|
return;
|
|
158
53
|
result.push({ name, alias, mod: source });
|
|
159
54
|
});
|
|
@@ -182,49 +77,6 @@ function getImportDeclarations(file, options) {
|
|
|
182
77
|
};
|
|
183
78
|
}
|
|
184
79
|
|
|
185
|
-
// src/jsx-element.ts
|
|
186
|
-
var import_ts_morph3 = require("ts-morph");
|
|
187
|
-
var import_ts_pattern2 = require("ts-pattern");
|
|
188
|
-
function visitJsxElement(file, options) {
|
|
189
|
-
const { match: matchProp, fn } = options;
|
|
190
|
-
const elements = [
|
|
191
|
-
...file.getDescendantsOfKind(import_ts_morph3.ts.SyntaxKind.JsxOpeningElement),
|
|
192
|
-
...file.getDescendantsOfKind(import_ts_morph3.ts.SyntaxKind.JsxSelfClosingElement)
|
|
193
|
-
];
|
|
194
|
-
for (const node of elements) {
|
|
195
|
-
const tag = node.getTagNameNode().getText();
|
|
196
|
-
if (!tag || !matchProp.tag(tag)) {
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
const props = node.getAttributes();
|
|
200
|
-
const data = {};
|
|
201
|
-
for (const prop of props) {
|
|
202
|
-
if (!import_ts_morph3.Node.isJsxAttribute(prop)) {
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
const name = prop.getName();
|
|
206
|
-
const value = prop.getInitializer();
|
|
207
|
-
if (!tag || !matchProp.prop({ tag, name })) {
|
|
208
|
-
continue;
|
|
209
|
-
}
|
|
210
|
-
(0, import_ts_pattern2.match)(value).when(import_ts_morph3.Node.isStringLiteral, (value2) => {
|
|
211
|
-
data[name] = value2.getLiteralValue().replaceAll(/[\n\s]+/g, " ");
|
|
212
|
-
}).when(import_ts_morph3.Node.isJsxExpression, (value2) => {
|
|
213
|
-
const expr = value2.getExpression();
|
|
214
|
-
const returnValue = extractValue(expr);
|
|
215
|
-
if (returnValue !== void 0) {
|
|
216
|
-
data[name] = returnValue;
|
|
217
|
-
}
|
|
218
|
-
}).otherwise(() => {
|
|
219
|
-
if (!value) {
|
|
220
|
-
data[name] = true;
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
fn({ name: tag, data });
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
80
|
// src/parser-result.ts
|
|
229
81
|
var createParserResult = () => ({
|
|
230
82
|
jsx: /* @__PURE__ */ new Set(),
|
|
@@ -252,6 +104,7 @@ var createParserResult = () => ({
|
|
|
252
104
|
});
|
|
253
105
|
|
|
254
106
|
// src/parser.ts
|
|
107
|
+
var isNodeRecipe = (node) => node.type === "recipe";
|
|
255
108
|
function createImportMatcher(mod, values) {
|
|
256
109
|
const regex = values ? new RegExp(`^(${values.join("|")})$`) : /.*/;
|
|
257
110
|
return {
|
|
@@ -266,11 +119,11 @@ var combineResult = (unboxed) => {
|
|
|
266
119
|
return [...unboxed.conditions, unboxed.raw, ...unboxed.spreadConditions];
|
|
267
120
|
};
|
|
268
121
|
function createParser(options) {
|
|
269
|
-
return function parse(sourceFile, confProperties
|
|
122
|
+
return function parse(sourceFile, confProperties) {
|
|
270
123
|
if (!sourceFile)
|
|
271
124
|
return;
|
|
272
125
|
const filePath = sourceFile.getFilePath();
|
|
273
|
-
const { jsx, importMap } = options;
|
|
126
|
+
const { jsx, importMap, getRecipeByName } = options;
|
|
274
127
|
const importRegex = [
|
|
275
128
|
createImportMatcher(importMap.css, ["css", "cva"]),
|
|
276
129
|
createImportMatcher(importMap.recipe),
|
|
@@ -296,195 +149,163 @@ function createParser(options) {
|
|
|
296
149
|
const isValidStyleFn = (name) => name === jsx?.factory;
|
|
297
150
|
const jsxFactoryAlias = jsx ? imports.getAlias(jsx.factory) : "panda";
|
|
298
151
|
const jsxPatternNodes = new RegExp(`(${jsx?.nodes.map((node) => node.type === "pattern" && node.name).join("|")})$`);
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if (isRecipe) {
|
|
306
|
-
recipes.set(alias, true);
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
const functions = /* @__PURE__ */ new Map();
|
|
310
|
-
const components = /* @__PURE__ */ new Map();
|
|
311
|
-
const propertiesMap = new Map(confProperties.map((prop) => [prop, true]));
|
|
312
|
-
const cvaAlias = imports.getAlias("cva");
|
|
313
|
-
const cssAlias = imports.getAlias("css");
|
|
314
|
-
if (options.jsx) {
|
|
315
|
-
options.jsx.nodes.forEach((node) => {
|
|
316
|
-
const properties = node.props ? new Map(propertiesMap) : propertiesMap;
|
|
317
|
-
const alias = imports.getAlias(node.name);
|
|
318
|
-
node.props?.forEach((prop) => properties.set(prop, true));
|
|
319
|
-
functions.set(node.baseName, properties);
|
|
320
|
-
functions.set(alias, properties);
|
|
321
|
-
components.set(alias, properties);
|
|
322
|
-
});
|
|
152
|
+
const recipes = /* @__PURE__ */ new Map();
|
|
153
|
+
imports.value.forEach((importDeclaration) => {
|
|
154
|
+
const { name, alias } = importDeclaration;
|
|
155
|
+
const isRecipe = isValidRecipe(name);
|
|
156
|
+
if (isRecipe) {
|
|
157
|
+
recipes.set(alias, true);
|
|
323
158
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
return Boolean(functions.get(fnName));
|
|
338
|
-
});
|
|
339
|
-
const matchFnProp = (0, import_shared2.memo)((fnName, propName) => {
|
|
340
|
-
if (propertiesMap.size === 0)
|
|
341
|
-
return true;
|
|
342
|
-
if (recipes.has(fnName))
|
|
343
|
-
return true;
|
|
344
|
-
if (fnName === cvaAlias)
|
|
345
|
-
return true;
|
|
346
|
-
if (fnName.startsWith(jsxFactoryAlias))
|
|
347
|
-
return true;
|
|
348
|
-
if (fnName === cssAlias)
|
|
349
|
-
return Boolean(propertiesMap.get(propName) || propName === "selectors");
|
|
350
|
-
return Boolean(functions.get(fnName)?.get(propName));
|
|
351
|
-
});
|
|
352
|
-
const measure2 = import_logger.logger.time.debug(`Tokens extracted from ${filePath}`);
|
|
353
|
-
const extractResultByName = (0, import_extractor.extract)({
|
|
354
|
-
ast: sourceFile,
|
|
355
|
-
components: {
|
|
356
|
-
matchTag: (prop) => matchTag(prop.tagName),
|
|
357
|
-
matchProp: (prop) => matchTagProp(prop.tagName, prop.propName)
|
|
358
|
-
},
|
|
359
|
-
functions: {
|
|
360
|
-
matchFn: (prop) => matchFn(prop.fnName),
|
|
361
|
-
matchProp: (prop) => matchFnProp(prop.fnName, prop.propName),
|
|
362
|
-
matchArg: (prop) => {
|
|
363
|
-
if (prop.fnName === jsxFactoryAlias && prop.index === 1 && import_ts_morph4.Node.isIdentifier(prop.argNode))
|
|
364
|
-
return false;
|
|
365
|
-
return true;
|
|
159
|
+
});
|
|
160
|
+
const functions = /* @__PURE__ */ new Map();
|
|
161
|
+
const components = /* @__PURE__ */ new Map();
|
|
162
|
+
const propertiesMap = new Map(confProperties.map((prop) => [prop, true]));
|
|
163
|
+
const recipePropertiesByName = /* @__PURE__ */ new Map();
|
|
164
|
+
const recipeJsxLists = (jsx?.nodes ?? []).filter(isNodeRecipe).reduce(
|
|
165
|
+
(acc, recipe) => {
|
|
166
|
+
recipePropertiesByName.set(recipe.baseName, new Set(recipe.props ?? []));
|
|
167
|
+
recipe.jsx?.forEach((jsx2) => {
|
|
168
|
+
if (typeof jsx2 === "string") {
|
|
169
|
+
acc.string.add(jsx2);
|
|
170
|
+
} else {
|
|
171
|
+
acc.regex.push(jsx2);
|
|
366
172
|
}
|
|
367
|
-
}
|
|
368
|
-
|
|
173
|
+
});
|
|
174
|
+
return acc;
|
|
175
|
+
},
|
|
176
|
+
{ string: /* @__PURE__ */ new Set(), regex: [] }
|
|
177
|
+
);
|
|
178
|
+
const cvaAlias = imports.getAlias("cva");
|
|
179
|
+
const cssAlias = imports.getAlias("css");
|
|
180
|
+
if (options.jsx) {
|
|
181
|
+
options.jsx.nodes.forEach((node) => {
|
|
182
|
+
const properties = node.props ? new Map(propertiesMap) : propertiesMap;
|
|
183
|
+
const alias = imports.getAlias(node.name);
|
|
184
|
+
node.props?.forEach((prop) => properties.set(prop, true));
|
|
185
|
+
functions.set(alias, properties);
|
|
186
|
+
components.set(alias, properties);
|
|
369
187
|
});
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
188
|
+
}
|
|
189
|
+
const getRecipeName = (0, import_shared2.memo)(options.getRecipeName);
|
|
190
|
+
const isJsxTagRecipe = (0, import_shared2.memo)(
|
|
191
|
+
(tagName) => recipeJsxLists.string.has(tagName) || recipeJsxLists.regex.some((regex) => regex.test(tagName))
|
|
192
|
+
);
|
|
193
|
+
const matchTag = (0, import_shared2.memo)((tagName) => {
|
|
194
|
+
return components.has(tagName) || isUpperCase(tagName) || tagName.startsWith(jsxFactoryAlias) || isJsxTagRecipe(tagName);
|
|
195
|
+
});
|
|
196
|
+
const matchTagProp = (0, import_shared2.memo)((tagName, propName) => {
|
|
197
|
+
if (propertiesMap.size === 0)
|
|
198
|
+
return true;
|
|
199
|
+
if (Boolean(components.get(tagName)?.get(propName)) || propertiesMap.has(propName))
|
|
200
|
+
return true;
|
|
201
|
+
if (isJsxTagRecipe(tagName)) {
|
|
202
|
+
const recipe = getRecipeByName(getRecipeName(tagName));
|
|
203
|
+
if (recipe) {
|
|
204
|
+
return recipePropertiesByName.get(recipe.name)?.has(propName) ?? false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
});
|
|
209
|
+
const matchFn = (0, import_shared2.memo)((fnName) => {
|
|
210
|
+
if (recipes.has(fnName))
|
|
211
|
+
return true;
|
|
212
|
+
if (fnName === cvaAlias || fnName === cssAlias || fnName.startsWith(jsxFactoryAlias))
|
|
213
|
+
return true;
|
|
214
|
+
return Boolean(functions.get(fnName));
|
|
215
|
+
});
|
|
216
|
+
const matchFnProp = (0, import_shared2.memo)((fnName, propName) => {
|
|
217
|
+
if (propertiesMap.size === 0)
|
|
218
|
+
return true;
|
|
219
|
+
if (recipes.has(fnName))
|
|
220
|
+
return true;
|
|
221
|
+
if (fnName === cvaAlias)
|
|
222
|
+
return true;
|
|
223
|
+
if (fnName.startsWith(jsxFactoryAlias))
|
|
224
|
+
return true;
|
|
225
|
+
if (fnName === cssAlias)
|
|
226
|
+
return Boolean(propertiesMap.get(propName) || propName === "selectors");
|
|
227
|
+
return Boolean(functions.get(fnName)?.get(propName));
|
|
228
|
+
});
|
|
229
|
+
const measure = import_logger.logger.time.debug(`Tokens extracted from ${filePath}`);
|
|
230
|
+
const extractResultByName = (0, import_extractor.extract)({
|
|
231
|
+
ast: sourceFile,
|
|
232
|
+
components: {
|
|
233
|
+
matchTag: (prop) => matchTag(prop.tagName),
|
|
234
|
+
matchProp: (prop) => matchTagProp(prop.tagName, prop.propName)
|
|
235
|
+
},
|
|
236
|
+
functions: {
|
|
237
|
+
matchFn: (prop) => matchFn(prop.fnName),
|
|
238
|
+
matchProp: (prop) => matchFnProp(prop.fnName, prop.propName),
|
|
239
|
+
matchArg: (prop) => {
|
|
240
|
+
if (prop.fnName === jsxFactoryAlias && prop.index === 1 && import_ts_morph.Node.isIdentifier(prop.argNode))
|
|
241
|
+
return false;
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
flags: { skipTraverseFiles: true }
|
|
246
|
+
});
|
|
247
|
+
measure();
|
|
248
|
+
extractResultByName.forEach((result, alias) => {
|
|
249
|
+
const name = imports.getName(alias);
|
|
250
|
+
import_logger.logger.debug(`ast:${name}`, { filePath, result, alias });
|
|
251
|
+
if (result.kind === "function") {
|
|
252
|
+
(0, import_ts_pattern.match)(name).when(css.match, (name2) => {
|
|
253
|
+
result.queryList.forEach((query) => {
|
|
254
|
+
collector.set(name2, {
|
|
255
|
+
name: name2,
|
|
256
|
+
box: query.box.value[0],
|
|
257
|
+
data: combineResult((0, import_extractor.unbox)(query.box.value[0]))
|
|
390
258
|
});
|
|
391
|
-
})
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
259
|
+
});
|
|
260
|
+
}).when(isValidPattern, (name2) => {
|
|
261
|
+
result.queryList.forEach((query) => {
|
|
262
|
+
collector.setPattern(name2, {
|
|
263
|
+
name: name2,
|
|
264
|
+
box: query.box.value[0],
|
|
265
|
+
data: combineResult((0, import_extractor.unbox)(query.box.value[0]))
|
|
398
266
|
});
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
267
|
+
});
|
|
268
|
+
}).when(isValidRecipe, (name2) => {
|
|
269
|
+
result.queryList.forEach((query) => {
|
|
270
|
+
collector.setRecipe(name2, {
|
|
271
|
+
name: name2,
|
|
272
|
+
box: query.box.value[0],
|
|
273
|
+
data: combineResult((0, import_extractor.unbox)(query.box.value[0]))
|
|
406
274
|
});
|
|
407
|
-
}).otherwise(() => {
|
|
408
275
|
});
|
|
409
|
-
}
|
|
276
|
+
}).when(isValidStyleFn, () => {
|
|
410
277
|
result.queryList.forEach((query) => {
|
|
411
|
-
|
|
412
|
-
const data = combineResult((0, import_extractor.unbox)(query.box));
|
|
413
|
-
import_logger.logger.debug(`ast:jsx:${name}`, { filePath, result: data });
|
|
414
|
-
if (jsx && name.startsWith(jsxFactoryAlias)) {
|
|
415
|
-
type = "jsx-factory";
|
|
416
|
-
} else if (jsxPatternNodes.test(name)) {
|
|
417
|
-
type = "pattern";
|
|
418
|
-
} else if (jsxRecipeNodes.test(name)) {
|
|
419
|
-
type = "recipe";
|
|
420
|
-
} else {
|
|
421
|
-
type = "jsx";
|
|
422
|
-
}
|
|
423
|
-
collector.jsx.add({
|
|
424
|
-
// from "panda.*" -> "panda.button"
|
|
278
|
+
collector.setCva({
|
|
425
279
|
name,
|
|
426
|
-
box: query.box,
|
|
427
|
-
|
|
428
|
-
data
|
|
280
|
+
box: query.box.value[1],
|
|
281
|
+
data: combineResult((0, import_extractor.unbox)(query.box.value[1]))
|
|
429
282
|
});
|
|
430
283
|
});
|
|
431
|
-
}
|
|
432
|
-
});
|
|
433
|
-
return collector;
|
|
434
|
-
}
|
|
435
|
-
const measure = import_logger.logger.time.debug(`Tokens extracted & collected from ${filePath}`);
|
|
436
|
-
visitCallExpressions(sourceFile, {
|
|
437
|
-
match: (0, import_shared2.memo)((name) => imports.match(name)),
|
|
438
|
-
fn({ name: _name, data }) {
|
|
439
|
-
const name = imports.getName(_name);
|
|
440
|
-
const [css2] = importRegex;
|
|
441
|
-
const result = { name, data };
|
|
442
|
-
import_logger.logger.debug(`ast:${name}`, { filePath, result });
|
|
443
|
-
(0, import_ts_pattern3.match)(name).when(css2.match, (name2) => {
|
|
444
|
-
collector.set(name2, result);
|
|
445
|
-
}).when(isValidPattern, (name2) => {
|
|
446
|
-
collector.setPattern(name2, result);
|
|
447
|
-
}).when(isValidRecipe, (name2) => {
|
|
448
|
-
collector.setRecipe(name2, result);
|
|
449
|
-
}).when(isValidStyleFn, () => {
|
|
450
|
-
collector.setCva(result);
|
|
451
284
|
}).otherwise(() => {
|
|
452
285
|
});
|
|
286
|
+
} else if (result.kind === "component") {
|
|
287
|
+
result.queryList.forEach((query) => {
|
|
288
|
+
const data = combineResult((0, import_extractor.unbox)(query.box));
|
|
289
|
+
import_logger.logger.debug(`ast:jsx:${name}`, { filePath, result: data });
|
|
290
|
+
if (jsx && name.startsWith(jsxFactoryAlias)) {
|
|
291
|
+
collector.jsx.add({ name, box: query.box, type: "jsx-factory", data });
|
|
292
|
+
} else if (jsxPatternNodes.test(name)) {
|
|
293
|
+
collector.setPattern(name, { type: "jsx-pattern", name, box: query.box, data });
|
|
294
|
+
} else if (recipeJsxLists.string.has(name) || recipeJsxLists.regex.some((regex) => regex.test(name))) {
|
|
295
|
+
collector.setRecipe(getRecipeName(name), { type: "jsx-recipe", name, box: query.box, data });
|
|
296
|
+
} else {
|
|
297
|
+
collector.jsx.add({ name, box: query.box, type: "jsx", data });
|
|
298
|
+
}
|
|
299
|
+
});
|
|
453
300
|
}
|
|
454
301
|
});
|
|
455
|
-
visitJsxElement(sourceFile, {
|
|
456
|
-
match: {
|
|
457
|
-
tag: (0, import_shared2.memo)((name) => {
|
|
458
|
-
return name.startsWith(jsxFactoryAlias) || isUpperCase(name);
|
|
459
|
-
}),
|
|
460
|
-
prop: ({ tag, name }) => {
|
|
461
|
-
const node = jsx?.nodes.find((n) => n.name === tag);
|
|
462
|
-
return !!jsx?.isStyleProp(name) || !!node?.props?.includes(name);
|
|
463
|
-
}
|
|
464
|
-
},
|
|
465
|
-
fn({ name, data }) {
|
|
466
|
-
let type;
|
|
467
|
-
import_logger.logger.debug(`ast:jsx:${name}`, { filePath, result: data });
|
|
468
|
-
if (jsx && name.startsWith(jsxFactoryAlias)) {
|
|
469
|
-
type = "jsx-factory";
|
|
470
|
-
} else if (jsxPatternNodes.test(name)) {
|
|
471
|
-
type = "pattern";
|
|
472
|
-
} else if (jsxRecipeNodes.test(name)) {
|
|
473
|
-
type = "recipe";
|
|
474
|
-
} else {
|
|
475
|
-
type = "jsx";
|
|
476
|
-
}
|
|
477
|
-
collector.jsx.add({ type, name, data });
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
measure();
|
|
481
302
|
return collector;
|
|
482
303
|
};
|
|
483
304
|
}
|
|
484
305
|
var isUpperCase = (value) => value[0] === value[0].toUpperCase();
|
|
485
306
|
|
|
486
307
|
// src/project.ts
|
|
487
|
-
var createTsProject = (options) => new
|
|
308
|
+
var createTsProject = (options) => new import_ts_morph2.Project({
|
|
488
309
|
skipAddingFilesFromTsConfig: true,
|
|
489
310
|
skipFileDependencyResolution: true,
|
|
490
311
|
skipLoadingLibFiles: true,
|
|
@@ -510,10 +331,10 @@ var createProject = ({ getFiles, readFile, parserOptions, ...projectOptions }) =
|
|
|
510
331
|
},
|
|
511
332
|
createSourceFile: (filePath) => project.createSourceFile(filePath, readFile(filePath), {
|
|
512
333
|
overwrite: true,
|
|
513
|
-
scriptKind:
|
|
334
|
+
scriptKind: import_ts_morph2.ScriptKind.TSX
|
|
514
335
|
}),
|
|
515
|
-
parseSourceFile: (filePath, properties
|
|
516
|
-
return parser(project.getSourceFile(filePath), properties
|
|
336
|
+
parseSourceFile: (filePath, properties) => {
|
|
337
|
+
return parser(project.getSourceFile(filePath), properties);
|
|
517
338
|
}
|
|
518
339
|
})),
|
|
519
340
|
(0, import_lil_fp.tap)(({ createSourceFile }) => {
|
package/dist/index.mjs
CHANGED
|
@@ -6,120 +6,13 @@ import { Project as TsProject, ScriptKind } from "ts-morph";
|
|
|
6
6
|
import { extract, unbox } from "@pandacss/extractor";
|
|
7
7
|
import { logger } from "@pandacss/logger";
|
|
8
8
|
import { memo as memo2 } from "@pandacss/shared";
|
|
9
|
-
import { Node
|
|
10
|
-
import { match as match3 } from "ts-pattern";
|
|
11
|
-
|
|
12
|
-
// src/call-expression.ts
|
|
13
|
-
import { Node as Node2, ts } from "ts-morph";
|
|
14
|
-
|
|
15
|
-
// src/literal.ts
|
|
16
|
-
import {
|
|
17
|
-
Node
|
|
18
|
-
} from "ts-morph";
|
|
9
|
+
import { Node } from "ts-morph";
|
|
19
10
|
import { match } from "ts-pattern";
|
|
20
11
|
|
|
21
|
-
// src/strip-quotes.ts
|
|
22
|
-
function stripQuotes(q) {
|
|
23
|
-
const quoteStart = `'|"|\u2018|\u201C|\u2039|\xAB`;
|
|
24
|
-
const quoteEnd = `'|"|\u2019|\u201D|\u203A|\xBB`;
|
|
25
|
-
if (typeof q !== "string")
|
|
26
|
-
throw new Error(`input was '${typeof q}' and not of type 'string'`);
|
|
27
|
-
if (!q.length)
|
|
28
|
-
throw new Error(`input was empty`);
|
|
29
|
-
let s = q;
|
|
30
|
-
let t = s.length;
|
|
31
|
-
if (s.charAt(0).match(new RegExp(quoteStart))) {
|
|
32
|
-
s = s.substring(1, t--);
|
|
33
|
-
}
|
|
34
|
-
if (s.charAt(--t).match(new RegExp(quoteEnd))) {
|
|
35
|
-
s = s.substring(0, t);
|
|
36
|
-
}
|
|
37
|
-
return s;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// src/literal.ts
|
|
41
|
-
function isPrimitiveLiteral(node) {
|
|
42
|
-
return Node.isStringLiteral(node) || Node.isNumericLiteral(node) || Node.isTrueLiteral(node) || Node.isFalseLiteral(node);
|
|
43
|
-
}
|
|
44
|
-
function extractValue(value) {
|
|
45
|
-
return match(value).when(
|
|
46
|
-
(node) => Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node),
|
|
47
|
-
(value2) => {
|
|
48
|
-
return value2.getLiteralValue().replaceAll(/[\n\s]+/g, " ");
|
|
49
|
-
}
|
|
50
|
-
).when(isPrimitiveLiteral, (value2) => {
|
|
51
|
-
return value2.getLiteralValue();
|
|
52
|
-
}).when(Node.isNullLiteral, () => {
|
|
53
|
-
return null;
|
|
54
|
-
}).when(Node.isObjectLiteralExpression, (value2) => {
|
|
55
|
-
return extractObjectLiteral(value2);
|
|
56
|
-
}).when(Node.isArrayLiteralExpression, (value2) => {
|
|
57
|
-
return extractArrayLiteral(value2);
|
|
58
|
-
}).otherwise(() => {
|
|
59
|
-
return void 0;
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
function extractObjectLiteral(node) {
|
|
63
|
-
const data = {};
|
|
64
|
-
const properties = node.getProperties();
|
|
65
|
-
for (const property of properties) {
|
|
66
|
-
if (Node.isPropertyAssignment(property)) {
|
|
67
|
-
const key = stripQuotes(property.getName());
|
|
68
|
-
const value = property.getInitializer();
|
|
69
|
-
const returnValue = extractValue(value);
|
|
70
|
-
if (returnValue !== void 0) {
|
|
71
|
-
data[key] = returnValue;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return data;
|
|
76
|
-
}
|
|
77
|
-
function extractArrayLiteral(node) {
|
|
78
|
-
const result = [];
|
|
79
|
-
node.forEachChild((child) => {
|
|
80
|
-
match(child).when(isPrimitiveLiteral, (child2) => {
|
|
81
|
-
result.push(child2.getLiteralValue());
|
|
82
|
-
}).when(Node.isUndefinedKeyword, () => {
|
|
83
|
-
result.push(void 0);
|
|
84
|
-
}).when(Node.isNullLiteral, () => {
|
|
85
|
-
result.push(null);
|
|
86
|
-
}).when(Node.isObjectLiteralExpression, (child2) => {
|
|
87
|
-
result.push(extractObjectLiteral(child2));
|
|
88
|
-
}).when(Node.isArrayLiteralExpression, (child2) => {
|
|
89
|
-
result.push(extractArrayLiteral(child2));
|
|
90
|
-
}).otherwise(() => {
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
return result;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// src/call-expression.ts
|
|
97
|
-
function visitCallExpressions(file, options) {
|
|
98
|
-
const { match: match4, fn } = options;
|
|
99
|
-
const callExpressions = file.getDescendantsOfKind(ts.SyntaxKind.CallExpression);
|
|
100
|
-
for (const node of callExpressions) {
|
|
101
|
-
const expr = node.getExpression();
|
|
102
|
-
const name = expr.getText();
|
|
103
|
-
if (!match4(name)) {
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
const args = node.getArguments();
|
|
107
|
-
if (args.length === 0) {
|
|
108
|
-
fn({ name, data: {} });
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
args.forEach((arg) => {
|
|
112
|
-
if (Node2.isObjectLiteralExpression(arg)) {
|
|
113
|
-
fn({ name, data: extractObjectLiteral(arg) });
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
12
|
// src/import.ts
|
|
120
13
|
import { memo } from "@pandacss/shared";
|
|
121
14
|
function getImportDeclarations(file, options) {
|
|
122
|
-
const { match:
|
|
15
|
+
const { match: match2 } = options;
|
|
123
16
|
const result = [];
|
|
124
17
|
file.getImportDeclarations().forEach((node) => {
|
|
125
18
|
const source = node.getModuleSpecifierValue();
|
|
@@ -129,7 +22,7 @@ function getImportDeclarations(file, options) {
|
|
|
129
22
|
specifiers.forEach((specifier) => {
|
|
130
23
|
const name = specifier.getNameNode().getText();
|
|
131
24
|
const alias = specifier.getAliasNode()?.getText() || name;
|
|
132
|
-
if (!
|
|
25
|
+
if (!match2({ id: name, mod: source }))
|
|
133
26
|
return;
|
|
134
27
|
result.push({ name, alias, mod: source });
|
|
135
28
|
});
|
|
@@ -158,49 +51,6 @@ function getImportDeclarations(file, options) {
|
|
|
158
51
|
};
|
|
159
52
|
}
|
|
160
53
|
|
|
161
|
-
// src/jsx-element.ts
|
|
162
|
-
import { Node as Node3, ts as ts2 } from "ts-morph";
|
|
163
|
-
import { match as match2 } from "ts-pattern";
|
|
164
|
-
function visitJsxElement(file, options) {
|
|
165
|
-
const { match: matchProp, fn } = options;
|
|
166
|
-
const elements = [
|
|
167
|
-
...file.getDescendantsOfKind(ts2.SyntaxKind.JsxOpeningElement),
|
|
168
|
-
...file.getDescendantsOfKind(ts2.SyntaxKind.JsxSelfClosingElement)
|
|
169
|
-
];
|
|
170
|
-
for (const node of elements) {
|
|
171
|
-
const tag = node.getTagNameNode().getText();
|
|
172
|
-
if (!tag || !matchProp.tag(tag)) {
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
const props = node.getAttributes();
|
|
176
|
-
const data = {};
|
|
177
|
-
for (const prop of props) {
|
|
178
|
-
if (!Node3.isJsxAttribute(prop)) {
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
const name = prop.getName();
|
|
182
|
-
const value = prop.getInitializer();
|
|
183
|
-
if (!tag || !matchProp.prop({ tag, name })) {
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
match2(value).when(Node3.isStringLiteral, (value2) => {
|
|
187
|
-
data[name] = value2.getLiteralValue().replaceAll(/[\n\s]+/g, " ");
|
|
188
|
-
}).when(Node3.isJsxExpression, (value2) => {
|
|
189
|
-
const expr = value2.getExpression();
|
|
190
|
-
const returnValue = extractValue(expr);
|
|
191
|
-
if (returnValue !== void 0) {
|
|
192
|
-
data[name] = returnValue;
|
|
193
|
-
}
|
|
194
|
-
}).otherwise(() => {
|
|
195
|
-
if (!value) {
|
|
196
|
-
data[name] = true;
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
fn({ name: tag, data });
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
54
|
// src/parser-result.ts
|
|
205
55
|
var createParserResult = () => ({
|
|
206
56
|
jsx: /* @__PURE__ */ new Set(),
|
|
@@ -228,6 +78,7 @@ var createParserResult = () => ({
|
|
|
228
78
|
});
|
|
229
79
|
|
|
230
80
|
// src/parser.ts
|
|
81
|
+
var isNodeRecipe = (node) => node.type === "recipe";
|
|
231
82
|
function createImportMatcher(mod, values) {
|
|
232
83
|
const regex = values ? new RegExp(`^(${values.join("|")})$`) : /.*/;
|
|
233
84
|
return {
|
|
@@ -242,11 +93,11 @@ var combineResult = (unboxed) => {
|
|
|
242
93
|
return [...unboxed.conditions, unboxed.raw, ...unboxed.spreadConditions];
|
|
243
94
|
};
|
|
244
95
|
function createParser(options) {
|
|
245
|
-
return function parse(sourceFile, confProperties
|
|
96
|
+
return function parse(sourceFile, confProperties) {
|
|
246
97
|
if (!sourceFile)
|
|
247
98
|
return;
|
|
248
99
|
const filePath = sourceFile.getFilePath();
|
|
249
|
-
const { jsx, importMap } = options;
|
|
100
|
+
const { jsx, importMap, getRecipeByName } = options;
|
|
250
101
|
const importRegex = [
|
|
251
102
|
createImportMatcher(importMap.css, ["css", "cva"]),
|
|
252
103
|
createImportMatcher(importMap.recipe),
|
|
@@ -272,188 +123,156 @@ function createParser(options) {
|
|
|
272
123
|
const isValidStyleFn = (name) => name === jsx?.factory;
|
|
273
124
|
const jsxFactoryAlias = jsx ? imports.getAlias(jsx.factory) : "panda";
|
|
274
125
|
const jsxPatternNodes = new RegExp(`(${jsx?.nodes.map((node) => node.type === "pattern" && node.name).join("|")})$`);
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (isRecipe) {
|
|
282
|
-
recipes.set(alias, true);
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
const functions = /* @__PURE__ */ new Map();
|
|
286
|
-
const components = /* @__PURE__ */ new Map();
|
|
287
|
-
const propertiesMap = new Map(confProperties.map((prop) => [prop, true]));
|
|
288
|
-
const cvaAlias = imports.getAlias("cva");
|
|
289
|
-
const cssAlias = imports.getAlias("css");
|
|
290
|
-
if (options.jsx) {
|
|
291
|
-
options.jsx.nodes.forEach((node) => {
|
|
292
|
-
const properties = node.props ? new Map(propertiesMap) : propertiesMap;
|
|
293
|
-
const alias = imports.getAlias(node.name);
|
|
294
|
-
node.props?.forEach((prop) => properties.set(prop, true));
|
|
295
|
-
functions.set(node.baseName, properties);
|
|
296
|
-
functions.set(alias, properties);
|
|
297
|
-
components.set(alias, properties);
|
|
298
|
-
});
|
|
126
|
+
const recipes = /* @__PURE__ */ new Map();
|
|
127
|
+
imports.value.forEach((importDeclaration) => {
|
|
128
|
+
const { name, alias } = importDeclaration;
|
|
129
|
+
const isRecipe = isValidRecipe(name);
|
|
130
|
+
if (isRecipe) {
|
|
131
|
+
recipes.set(alias, true);
|
|
299
132
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
return Boolean(functions.get(fnName));
|
|
314
|
-
});
|
|
315
|
-
const matchFnProp = memo2((fnName, propName) => {
|
|
316
|
-
if (propertiesMap.size === 0)
|
|
317
|
-
return true;
|
|
318
|
-
if (recipes.has(fnName))
|
|
319
|
-
return true;
|
|
320
|
-
if (fnName === cvaAlias)
|
|
321
|
-
return true;
|
|
322
|
-
if (fnName.startsWith(jsxFactoryAlias))
|
|
323
|
-
return true;
|
|
324
|
-
if (fnName === cssAlias)
|
|
325
|
-
return Boolean(propertiesMap.get(propName) || propName === "selectors");
|
|
326
|
-
return Boolean(functions.get(fnName)?.get(propName));
|
|
327
|
-
});
|
|
328
|
-
const measure2 = logger.time.debug(`Tokens extracted from ${filePath}`);
|
|
329
|
-
const extractResultByName = extract({
|
|
330
|
-
ast: sourceFile,
|
|
331
|
-
components: {
|
|
332
|
-
matchTag: (prop) => matchTag(prop.tagName),
|
|
333
|
-
matchProp: (prop) => matchTagProp(prop.tagName, prop.propName)
|
|
334
|
-
},
|
|
335
|
-
functions: {
|
|
336
|
-
matchFn: (prop) => matchFn(prop.fnName),
|
|
337
|
-
matchProp: (prop) => matchFnProp(prop.fnName, prop.propName),
|
|
338
|
-
matchArg: (prop) => {
|
|
339
|
-
if (prop.fnName === jsxFactoryAlias && prop.index === 1 && Node4.isIdentifier(prop.argNode))
|
|
340
|
-
return false;
|
|
341
|
-
return true;
|
|
133
|
+
});
|
|
134
|
+
const functions = /* @__PURE__ */ new Map();
|
|
135
|
+
const components = /* @__PURE__ */ new Map();
|
|
136
|
+
const propertiesMap = new Map(confProperties.map((prop) => [prop, true]));
|
|
137
|
+
const recipePropertiesByName = /* @__PURE__ */ new Map();
|
|
138
|
+
const recipeJsxLists = (jsx?.nodes ?? []).filter(isNodeRecipe).reduce(
|
|
139
|
+
(acc, recipe) => {
|
|
140
|
+
recipePropertiesByName.set(recipe.baseName, new Set(recipe.props ?? []));
|
|
141
|
+
recipe.jsx?.forEach((jsx2) => {
|
|
142
|
+
if (typeof jsx2 === "string") {
|
|
143
|
+
acc.string.add(jsx2);
|
|
144
|
+
} else {
|
|
145
|
+
acc.regex.push(jsx2);
|
|
342
146
|
}
|
|
343
|
-
}
|
|
344
|
-
|
|
147
|
+
});
|
|
148
|
+
return acc;
|
|
149
|
+
},
|
|
150
|
+
{ string: /* @__PURE__ */ new Set(), regex: [] }
|
|
151
|
+
);
|
|
152
|
+
const cvaAlias = imports.getAlias("cva");
|
|
153
|
+
const cssAlias = imports.getAlias("css");
|
|
154
|
+
if (options.jsx) {
|
|
155
|
+
options.jsx.nodes.forEach((node) => {
|
|
156
|
+
const properties = node.props ? new Map(propertiesMap) : propertiesMap;
|
|
157
|
+
const alias = imports.getAlias(node.name);
|
|
158
|
+
node.props?.forEach((prop) => properties.set(prop, true));
|
|
159
|
+
functions.set(alias, properties);
|
|
160
|
+
components.set(alias, properties);
|
|
345
161
|
});
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
162
|
+
}
|
|
163
|
+
const getRecipeName = memo2(options.getRecipeName);
|
|
164
|
+
const isJsxTagRecipe = memo2(
|
|
165
|
+
(tagName) => recipeJsxLists.string.has(tagName) || recipeJsxLists.regex.some((regex) => regex.test(tagName))
|
|
166
|
+
);
|
|
167
|
+
const matchTag = memo2((tagName) => {
|
|
168
|
+
return components.has(tagName) || isUpperCase(tagName) || tagName.startsWith(jsxFactoryAlias) || isJsxTagRecipe(tagName);
|
|
169
|
+
});
|
|
170
|
+
const matchTagProp = memo2((tagName, propName) => {
|
|
171
|
+
if (propertiesMap.size === 0)
|
|
172
|
+
return true;
|
|
173
|
+
if (Boolean(components.get(tagName)?.get(propName)) || propertiesMap.has(propName))
|
|
174
|
+
return true;
|
|
175
|
+
if (isJsxTagRecipe(tagName)) {
|
|
176
|
+
const recipe = getRecipeByName(getRecipeName(tagName));
|
|
177
|
+
if (recipe) {
|
|
178
|
+
return recipePropertiesByName.get(recipe.name)?.has(propName) ?? false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
});
|
|
183
|
+
const matchFn = memo2((fnName) => {
|
|
184
|
+
if (recipes.has(fnName))
|
|
185
|
+
return true;
|
|
186
|
+
if (fnName === cvaAlias || fnName === cssAlias || fnName.startsWith(jsxFactoryAlias))
|
|
187
|
+
return true;
|
|
188
|
+
return Boolean(functions.get(fnName));
|
|
189
|
+
});
|
|
190
|
+
const matchFnProp = memo2((fnName, propName) => {
|
|
191
|
+
if (propertiesMap.size === 0)
|
|
192
|
+
return true;
|
|
193
|
+
if (recipes.has(fnName))
|
|
194
|
+
return true;
|
|
195
|
+
if (fnName === cvaAlias)
|
|
196
|
+
return true;
|
|
197
|
+
if (fnName.startsWith(jsxFactoryAlias))
|
|
198
|
+
return true;
|
|
199
|
+
if (fnName === cssAlias)
|
|
200
|
+
return Boolean(propertiesMap.get(propName) || propName === "selectors");
|
|
201
|
+
return Boolean(functions.get(fnName)?.get(propName));
|
|
202
|
+
});
|
|
203
|
+
const measure = logger.time.debug(`Tokens extracted from ${filePath}`);
|
|
204
|
+
const extractResultByName = extract({
|
|
205
|
+
ast: sourceFile,
|
|
206
|
+
components: {
|
|
207
|
+
matchTag: (prop) => matchTag(prop.tagName),
|
|
208
|
+
matchProp: (prop) => matchTagProp(prop.tagName, prop.propName)
|
|
209
|
+
},
|
|
210
|
+
functions: {
|
|
211
|
+
matchFn: (prop) => matchFn(prop.fnName),
|
|
212
|
+
matchProp: (prop) => matchFnProp(prop.fnName, prop.propName),
|
|
213
|
+
matchArg: (prop) => {
|
|
214
|
+
if (prop.fnName === jsxFactoryAlias && prop.index === 1 && Node.isIdentifier(prop.argNode))
|
|
215
|
+
return false;
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
flags: { skipTraverseFiles: true }
|
|
220
|
+
});
|
|
221
|
+
measure();
|
|
222
|
+
extractResultByName.forEach((result, alias) => {
|
|
223
|
+
const name = imports.getName(alias);
|
|
224
|
+
logger.debug(`ast:${name}`, { filePath, result, alias });
|
|
225
|
+
if (result.kind === "function") {
|
|
226
|
+
match(name).when(css.match, (name2) => {
|
|
227
|
+
result.queryList.forEach((query) => {
|
|
228
|
+
collector.set(name2, {
|
|
229
|
+
name: name2,
|
|
230
|
+
box: query.box.value[0],
|
|
231
|
+
data: combineResult(unbox(query.box.value[0]))
|
|
366
232
|
});
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
233
|
+
});
|
|
234
|
+
}).when(isValidPattern, (name2) => {
|
|
235
|
+
result.queryList.forEach((query) => {
|
|
236
|
+
collector.setPattern(name2, {
|
|
237
|
+
name: name2,
|
|
238
|
+
box: query.box.value[0],
|
|
239
|
+
data: combineResult(unbox(query.box.value[0]))
|
|
374
240
|
});
|
|
375
|
-
})
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
241
|
+
});
|
|
242
|
+
}).when(isValidRecipe, (name2) => {
|
|
243
|
+
result.queryList.forEach((query) => {
|
|
244
|
+
collector.setRecipe(name2, {
|
|
245
|
+
name: name2,
|
|
246
|
+
box: query.box.value[0],
|
|
247
|
+
data: combineResult(unbox(query.box.value[0]))
|
|
382
248
|
});
|
|
383
|
-
}).otherwise(() => {
|
|
384
249
|
});
|
|
385
|
-
}
|
|
250
|
+
}).when(isValidStyleFn, () => {
|
|
386
251
|
result.queryList.forEach((query) => {
|
|
387
|
-
|
|
388
|
-
const data = combineResult(unbox(query.box));
|
|
389
|
-
logger.debug(`ast:jsx:${name}`, { filePath, result: data });
|
|
390
|
-
if (jsx && name.startsWith(jsxFactoryAlias)) {
|
|
391
|
-
type = "jsx-factory";
|
|
392
|
-
} else if (jsxPatternNodes.test(name)) {
|
|
393
|
-
type = "pattern";
|
|
394
|
-
} else if (jsxRecipeNodes.test(name)) {
|
|
395
|
-
type = "recipe";
|
|
396
|
-
} else {
|
|
397
|
-
type = "jsx";
|
|
398
|
-
}
|
|
399
|
-
collector.jsx.add({
|
|
400
|
-
// from "panda.*" -> "panda.button"
|
|
252
|
+
collector.setCva({
|
|
401
253
|
name,
|
|
402
|
-
box: query.box,
|
|
403
|
-
|
|
404
|
-
data
|
|
254
|
+
box: query.box.value[1],
|
|
255
|
+
data: combineResult(unbox(query.box.value[1]))
|
|
405
256
|
});
|
|
406
257
|
});
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
return collector;
|
|
410
|
-
}
|
|
411
|
-
const measure = logger.time.debug(`Tokens extracted & collected from ${filePath}`);
|
|
412
|
-
visitCallExpressions(sourceFile, {
|
|
413
|
-
match: memo2((name) => imports.match(name)),
|
|
414
|
-
fn({ name: _name, data }) {
|
|
415
|
-
const name = imports.getName(_name);
|
|
416
|
-
const [css2] = importRegex;
|
|
417
|
-
const result = { name, data };
|
|
418
|
-
logger.debug(`ast:${name}`, { filePath, result });
|
|
419
|
-
match3(name).when(css2.match, (name2) => {
|
|
420
|
-
collector.set(name2, result);
|
|
421
|
-
}).when(isValidPattern, (name2) => {
|
|
422
|
-
collector.setPattern(name2, result);
|
|
423
|
-
}).when(isValidRecipe, (name2) => {
|
|
424
|
-
collector.setRecipe(name2, result);
|
|
425
|
-
}).when(isValidStyleFn, () => {
|
|
426
|
-
collector.setCva(result);
|
|
427
258
|
}).otherwise(() => {
|
|
428
259
|
});
|
|
260
|
+
} else if (result.kind === "component") {
|
|
261
|
+
result.queryList.forEach((query) => {
|
|
262
|
+
const data = combineResult(unbox(query.box));
|
|
263
|
+
logger.debug(`ast:jsx:${name}`, { filePath, result: data });
|
|
264
|
+
if (jsx && name.startsWith(jsxFactoryAlias)) {
|
|
265
|
+
collector.jsx.add({ name, box: query.box, type: "jsx-factory", data });
|
|
266
|
+
} else if (jsxPatternNodes.test(name)) {
|
|
267
|
+
collector.setPattern(name, { type: "jsx-pattern", name, box: query.box, data });
|
|
268
|
+
} else if (recipeJsxLists.string.has(name) || recipeJsxLists.regex.some((regex) => regex.test(name))) {
|
|
269
|
+
collector.setRecipe(getRecipeName(name), { type: "jsx-recipe", name, box: query.box, data });
|
|
270
|
+
} else {
|
|
271
|
+
collector.jsx.add({ name, box: query.box, type: "jsx", data });
|
|
272
|
+
}
|
|
273
|
+
});
|
|
429
274
|
}
|
|
430
275
|
});
|
|
431
|
-
visitJsxElement(sourceFile, {
|
|
432
|
-
match: {
|
|
433
|
-
tag: memo2((name) => {
|
|
434
|
-
return name.startsWith(jsxFactoryAlias) || isUpperCase(name);
|
|
435
|
-
}),
|
|
436
|
-
prop: ({ tag, name }) => {
|
|
437
|
-
const node = jsx?.nodes.find((n) => n.name === tag);
|
|
438
|
-
return !!jsx?.isStyleProp(name) || !!node?.props?.includes(name);
|
|
439
|
-
}
|
|
440
|
-
},
|
|
441
|
-
fn({ name, data }) {
|
|
442
|
-
let type;
|
|
443
|
-
logger.debug(`ast:jsx:${name}`, { filePath, result: data });
|
|
444
|
-
if (jsx && name.startsWith(jsxFactoryAlias)) {
|
|
445
|
-
type = "jsx-factory";
|
|
446
|
-
} else if (jsxPatternNodes.test(name)) {
|
|
447
|
-
type = "pattern";
|
|
448
|
-
} else if (jsxRecipeNodes.test(name)) {
|
|
449
|
-
type = "recipe";
|
|
450
|
-
} else {
|
|
451
|
-
type = "jsx";
|
|
452
|
-
}
|
|
453
|
-
collector.jsx.add({ type, name, data });
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
measure();
|
|
457
276
|
return collector;
|
|
458
277
|
};
|
|
459
278
|
}
|
|
@@ -488,8 +307,8 @@ var createProject = ({ getFiles, readFile, parserOptions, ...projectOptions }) =
|
|
|
488
307
|
overwrite: true,
|
|
489
308
|
scriptKind: ScriptKind.TSX
|
|
490
309
|
}),
|
|
491
|
-
parseSourceFile: (filePath, properties
|
|
492
|
-
return parser(project.getSourceFile(filePath), properties
|
|
310
|
+
parseSourceFile: (filePath, properties) => {
|
|
311
|
+
return parser(project.getSourceFile(filePath), properties);
|
|
493
312
|
}
|
|
494
313
|
})),
|
|
495
314
|
tap(({ createSourceFile }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pandacss/parser",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20230413141731",
|
|
4
4
|
"description": "The static parser for panda css",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -14,14 +14,15 @@
|
|
|
14
14
|
"lil-fp": "1.4.5",
|
|
15
15
|
"ts-morph": "18.0.0",
|
|
16
16
|
"ts-pattern": "4.2.2",
|
|
17
|
-
"@pandacss/extractor": "0.0.0-dev-
|
|
18
|
-
"@pandacss/is-valid-prop": "0.0.0-dev-
|
|
19
|
-
"@pandacss/logger": "0.0.0-dev-
|
|
20
|
-
"@pandacss/shared": "0.0.0-dev-
|
|
21
|
-
"@pandacss/types": "0.0.0-dev-
|
|
17
|
+
"@pandacss/extractor": "0.0.0-dev-20230413141731",
|
|
18
|
+
"@pandacss/is-valid-prop": "0.0.0-dev-20230413141731",
|
|
19
|
+
"@pandacss/logger": "0.0.0-dev-20230413141731",
|
|
20
|
+
"@pandacss/shared": "0.0.0-dev-20230413141731",
|
|
21
|
+
"@pandacss/types": "0.0.0-dev-20230413141731"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@pandacss/fixture": "0.0.0-dev-
|
|
24
|
+
"@pandacss/fixture": "0.0.0-dev-20230413141731",
|
|
25
|
+
"@pandacss/generator": "0.0.0-dev-20230413141731"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
27
28
|
"dist"
|