@idealyst/tooling 1.2.29 → 1.2.31
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/analyzer/index.cjs +522 -85
- package/dist/analyzer/index.cjs.map +1 -1
- package/dist/analyzer/index.d.cts +21 -44
- package/dist/analyzer/index.d.ts +21 -44
- package/dist/analyzer/index.js +526 -84
- package/dist/analyzer/index.js.map +1 -1
- package/dist/index.cjs +528 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +535 -104
- package/dist/index.js.map +1 -1
- package/dist/theme-analyzer-C1lprK5o.d.cts +66 -0
- package/dist/theme-analyzer-vmhko10Q.d.ts +66 -0
- package/dist/{types-CrlxbLFJ.d.cts → types-CnxJMLD8.d.cts} +1 -1
- package/dist/{types-CrlxbLFJ.d.ts → types-CnxJMLD8.d.ts} +1 -1
- package/dist/vite-plugin.cjs +488 -89
- package/dist/vite-plugin.cjs.map +1 -1
- package/dist/vite-plugin.d.cts +1 -1
- package/dist/vite-plugin.d.ts +1 -1
- package/dist/vite-plugin.js +495 -89
- package/dist/vite-plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,29 +1,54 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/analyzer/component-analyzer.ts
|
|
9
|
+
import * as ts3 from "typescript";
|
|
10
|
+
import * as fs3 from "fs";
|
|
11
|
+
import * as path3 from "path";
|
|
12
|
+
|
|
13
|
+
// src/analyzer/theme-analyzer.ts
|
|
2
14
|
import * as ts2 from "typescript";
|
|
3
15
|
import * as fs2 from "fs";
|
|
4
16
|
import * as path2 from "path";
|
|
5
17
|
|
|
6
|
-
// src/analyzer/theme-analyzer.ts
|
|
18
|
+
// src/analyzer/theme-source-analyzer.ts
|
|
7
19
|
import * as ts from "typescript";
|
|
8
20
|
import * as fs from "fs";
|
|
9
21
|
import * as path from "path";
|
|
10
|
-
function
|
|
22
|
+
function analyzeThemeSource(themePath, options = {}) {
|
|
11
23
|
const resolvedPath = path.resolve(themePath);
|
|
24
|
+
const verbose = options.verbose ?? false;
|
|
25
|
+
const aliases = options.aliases ?? {};
|
|
26
|
+
const log = (...args) => {
|
|
27
|
+
if (verbose) console.log("[theme-source-analyzer]", ...args);
|
|
28
|
+
};
|
|
12
29
|
if (!fs.existsSync(resolvedPath)) {
|
|
13
30
|
throw new Error(`Theme file not found: ${resolvedPath}`);
|
|
14
31
|
}
|
|
15
|
-
const log = (...args) => {
|
|
16
|
-
if (verbose) console.log("[theme-analyzer]", ...args);
|
|
17
|
-
};
|
|
18
32
|
log("Analyzing theme file:", resolvedPath);
|
|
19
|
-
const
|
|
33
|
+
const configPath = ts.findConfigFile(path.dirname(resolvedPath), ts.sys.fileExists, "tsconfig.json");
|
|
34
|
+
let compilerOptions = {
|
|
20
35
|
target: ts.ScriptTarget.ES2020,
|
|
21
36
|
module: ts.ModuleKind.ESNext,
|
|
37
|
+
moduleResolution: ts.ModuleResolutionKind.Node10,
|
|
22
38
|
strict: true,
|
|
23
39
|
esModuleInterop: true,
|
|
24
40
|
skipLibCheck: true,
|
|
25
|
-
allowSyntheticDefaultImports: true
|
|
26
|
-
|
|
41
|
+
allowSyntheticDefaultImports: true,
|
|
42
|
+
resolveJsonModule: true
|
|
43
|
+
};
|
|
44
|
+
if (configPath) {
|
|
45
|
+
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
46
|
+
if (!configFile.error) {
|
|
47
|
+
const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath));
|
|
48
|
+
compilerOptions = { ...compilerOptions, ...parsed.options };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const program = ts.createProgram([resolvedPath], compilerOptions);
|
|
27
52
|
const sourceFile = program.getSourceFile(resolvedPath);
|
|
28
53
|
if (!sourceFile) {
|
|
29
54
|
throw new Error(`Failed to parse theme file: ${resolvedPath}`);
|
|
@@ -31,7 +56,9 @@ function analyzeTheme(themePath, verbose = false) {
|
|
|
31
56
|
const ctx = {
|
|
32
57
|
program,
|
|
33
58
|
typeChecker: program.getTypeChecker(),
|
|
34
|
-
verbose
|
|
59
|
+
verbose,
|
|
60
|
+
aliases,
|
|
61
|
+
analyzedFiles: /* @__PURE__ */ new Set([resolvedPath])
|
|
35
62
|
};
|
|
36
63
|
const values = {
|
|
37
64
|
intents: [],
|
|
@@ -54,13 +81,368 @@ function analyzeTheme(themePath, verbose = false) {
|
|
|
54
81
|
const localName = element.name.text;
|
|
55
82
|
const importedName = element.propertyName?.text ?? localName;
|
|
56
83
|
imports.set(localName, { source, imported: importedName });
|
|
84
|
+
log(` Import: ${localName} from '${source}'`);
|
|
57
85
|
}
|
|
58
86
|
}
|
|
59
87
|
}
|
|
60
88
|
});
|
|
89
|
+
function resolveImportPath(source, fromFile) {
|
|
90
|
+
for (const [aliasPrefix, aliasPath] of Object.entries(ctx.aliases)) {
|
|
91
|
+
if (source === aliasPrefix || source.startsWith(aliasPrefix + "/")) {
|
|
92
|
+
const remainder = source.slice(aliasPrefix.length);
|
|
93
|
+
let resolved = aliasPath + remainder;
|
|
94
|
+
if (!path.isAbsolute(resolved)) {
|
|
95
|
+
resolved = path.resolve(path.dirname(fromFile), resolved);
|
|
96
|
+
}
|
|
97
|
+
return resolved;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (source.startsWith(".")) {
|
|
101
|
+
return path.resolve(path.dirname(fromFile), source);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
return __require.resolve(source, { paths: [path.dirname(fromFile)] });
|
|
105
|
+
} catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function findThemeFile(basePath, preferDark) {
|
|
110
|
+
const themeFileName = preferDark ? "darkTheme" : "lightTheme";
|
|
111
|
+
const candidates = [
|
|
112
|
+
basePath,
|
|
113
|
+
`${basePath}.ts`,
|
|
114
|
+
`${basePath}.tsx`,
|
|
115
|
+
path.join(basePath, "src", `${themeFileName}.ts`),
|
|
116
|
+
path.join(basePath, `${themeFileName}.ts`),
|
|
117
|
+
path.join(basePath, "src", "index.ts"),
|
|
118
|
+
path.join(basePath, "index.ts")
|
|
119
|
+
];
|
|
120
|
+
for (const candidate of candidates) {
|
|
121
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
122
|
+
return candidate;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
function analyzeBaseTheme2(varName) {
|
|
128
|
+
const importInfo = imports.get(varName);
|
|
129
|
+
if (!importInfo) {
|
|
130
|
+
log(`Could not find import for base theme: ${varName}`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
log(`Analyzing base theme '${varName}' from '${importInfo.source}'`);
|
|
134
|
+
const resolvedBase = resolveImportPath(importInfo.source, resolvedPath);
|
|
135
|
+
if (!resolvedBase) {
|
|
136
|
+
log(`Could not resolve import path: ${importInfo.source}`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const preferDark = varName.toLowerCase().includes("dark");
|
|
140
|
+
const themeFile = findThemeFile(resolvedBase, preferDark);
|
|
141
|
+
if (!themeFile) {
|
|
142
|
+
log(`Could not find theme file for: ${resolvedBase}`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (ctx.analyzedFiles.has(themeFile)) {
|
|
146
|
+
log(`Already analyzed: ${themeFile}`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
ctx.analyzedFiles.add(themeFile);
|
|
150
|
+
log(`Recursively analyzing: ${themeFile}`);
|
|
151
|
+
const baseValues = analyzeThemeSource(themeFile, { verbose, aliases });
|
|
152
|
+
mergeThemeValues(values, baseValues, false);
|
|
153
|
+
}
|
|
154
|
+
function traceBuilderCalls(node, calls = []) {
|
|
155
|
+
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
156
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
157
|
+
const fnName = node.expression.text;
|
|
158
|
+
if (fnName === "fromTheme" && node.arguments.length > 0) {
|
|
159
|
+
const arg = node.arguments[0];
|
|
160
|
+
if (ts.isIdentifier(arg)) {
|
|
161
|
+
return { calls, baseThemeVar: arg.text };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { calls, baseThemeVar: null };
|
|
166
|
+
}
|
|
167
|
+
const methodName = node.expression.name.text;
|
|
168
|
+
calls.unshift({ method: methodName, args: node.arguments });
|
|
169
|
+
const obj = node.expression.expression;
|
|
170
|
+
if (ts.isCallExpression(obj)) {
|
|
171
|
+
return traceBuilderCalls(obj, calls);
|
|
172
|
+
}
|
|
173
|
+
return { calls, baseThemeVar: null };
|
|
174
|
+
}
|
|
175
|
+
function getStringValue2(node) {
|
|
176
|
+
if (!node) return null;
|
|
177
|
+
if (ts.isStringLiteral(node)) return node.text;
|
|
178
|
+
if (ts.isIdentifier(node)) return node.text;
|
|
179
|
+
if (ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
function getObjectKeys2(node) {
|
|
183
|
+
return node.properties.filter((prop) => ts.isPropertyAssignment(prop)).map((prop) => {
|
|
184
|
+
if (ts.isIdentifier(prop.name)) return prop.name.text;
|
|
185
|
+
if (ts.isStringLiteral(prop.name)) return prop.name.text;
|
|
186
|
+
return null;
|
|
187
|
+
}).filter((k) => k !== null);
|
|
188
|
+
}
|
|
189
|
+
function processCalls(calls) {
|
|
190
|
+
log(`Processing ${calls.length} builder method calls`);
|
|
191
|
+
for (const { method, args } of calls) {
|
|
192
|
+
switch (method) {
|
|
193
|
+
case "addIntent": {
|
|
194
|
+
const name = getStringValue2(args[0]);
|
|
195
|
+
if (name && !values.intents.includes(name)) {
|
|
196
|
+
values.intents.push(name);
|
|
197
|
+
log(` Found intent: ${name}`);
|
|
198
|
+
}
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
case "addRadius": {
|
|
202
|
+
const name = getStringValue2(args[0]);
|
|
203
|
+
if (name && !values.radii.includes(name)) {
|
|
204
|
+
values.radii.push(name);
|
|
205
|
+
log(` Found radius: ${name}`);
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case "addShadow": {
|
|
210
|
+
const name = getStringValue2(args[0]);
|
|
211
|
+
if (name && !values.shadows.includes(name)) {
|
|
212
|
+
values.shadows.push(name);
|
|
213
|
+
log(` Found shadow: ${name}`);
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
case "addBreakpoint": {
|
|
218
|
+
const name = getStringValue2(args[0]);
|
|
219
|
+
if (name && !values.breakpoints.includes(name)) {
|
|
220
|
+
values.breakpoints.push(name);
|
|
221
|
+
log(` Found breakpoint: ${name}`);
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case "setBreakpoints": {
|
|
226
|
+
if (args[0] && ts.isObjectLiteralExpression(args[0])) {
|
|
227
|
+
const keys = getObjectKeys2(args[0]);
|
|
228
|
+
for (const key of keys) {
|
|
229
|
+
if (!values.breakpoints.includes(key)) {
|
|
230
|
+
values.breakpoints.push(key);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
log(` Found breakpoints: ${values.breakpoints.join(", ")}`);
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case "setSizes": {
|
|
238
|
+
if (args[0] && ts.isObjectLiteralExpression(args[0])) {
|
|
239
|
+
for (const prop of args[0].properties) {
|
|
240
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
241
|
+
let componentName = null;
|
|
242
|
+
if (ts.isIdentifier(prop.name)) {
|
|
243
|
+
componentName = prop.name.text;
|
|
244
|
+
} else if (ts.isStringLiteral(prop.name)) {
|
|
245
|
+
componentName = prop.name.text;
|
|
246
|
+
}
|
|
247
|
+
if (componentName && ts.isObjectLiteralExpression(prop.initializer)) {
|
|
248
|
+
const sizeKeys = getObjectKeys2(prop.initializer);
|
|
249
|
+
values.sizes[componentName] = sizeKeys;
|
|
250
|
+
log(` Found sizes for ${componentName}: ${sizeKeys.join(", ")}`);
|
|
251
|
+
if (componentName === "typography") {
|
|
252
|
+
for (const key of sizeKeys) {
|
|
253
|
+
if (!values.typography.includes(key)) {
|
|
254
|
+
values.typography.push(key);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
} else if (args[0] && ts.isPropertyAccessExpression(args[0])) {
|
|
262
|
+
const propAccess = args[0];
|
|
263
|
+
if (ts.isIdentifier(propAccess.expression) && propAccess.name.text === "sizes") {
|
|
264
|
+
const themeVarName = propAccess.expression.text;
|
|
265
|
+
log(` Found sizes reference: ${themeVarName}.sizes`);
|
|
266
|
+
const importInfo = imports.get(themeVarName);
|
|
267
|
+
if (importInfo) {
|
|
268
|
+
log(` Resolving sizes from imported theme: ${importInfo.source}`);
|
|
269
|
+
const resolvedBase = resolveImportPath(importInfo.source, resolvedPath);
|
|
270
|
+
if (resolvedBase) {
|
|
271
|
+
const preferDark = themeVarName.toLowerCase().includes("dark");
|
|
272
|
+
const themeFile = findThemeFile(resolvedBase, preferDark);
|
|
273
|
+
if (themeFile && !ctx.analyzedFiles.has(themeFile)) {
|
|
274
|
+
ctx.analyzedFiles.add(themeFile);
|
|
275
|
+
const baseValues = analyzeThemeSource(themeFile, { verbose, aliases });
|
|
276
|
+
for (const [comp, sizes] of Object.entries(baseValues.sizes)) {
|
|
277
|
+
if (!values.sizes[comp]) {
|
|
278
|
+
values.sizes[comp] = sizes;
|
|
279
|
+
log(` Inherited sizes for ${comp}: ${sizes.join(", ")}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
for (const typo of baseValues.typography) {
|
|
283
|
+
if (!values.typography.includes(typo)) {
|
|
284
|
+
values.typography.push(typo);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
case "setColors": {
|
|
295
|
+
if (args[0] && ts.isObjectLiteralExpression(args[0])) {
|
|
296
|
+
for (const prop of args[0].properties) {
|
|
297
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
298
|
+
let colorType = null;
|
|
299
|
+
if (ts.isIdentifier(prop.name)) {
|
|
300
|
+
colorType = prop.name.text;
|
|
301
|
+
} else if (ts.isStringLiteral(prop.name)) {
|
|
302
|
+
colorType = prop.name.text;
|
|
303
|
+
}
|
|
304
|
+
if (colorType && ts.isObjectLiteralExpression(prop.initializer)) {
|
|
305
|
+
const colorKeys = getObjectKeys2(prop.initializer);
|
|
306
|
+
switch (colorType) {
|
|
307
|
+
case "surface":
|
|
308
|
+
values.surfaceColors = colorKeys;
|
|
309
|
+
log(` Found surface colors: ${colorKeys.join(", ")}`);
|
|
310
|
+
break;
|
|
311
|
+
case "text":
|
|
312
|
+
values.textColors = colorKeys;
|
|
313
|
+
log(` Found text colors: ${colorKeys.join(", ")}`);
|
|
314
|
+
break;
|
|
315
|
+
case "border":
|
|
316
|
+
values.borderColors = colorKeys;
|
|
317
|
+
log(` Found border colors: ${colorKeys.join(", ")}`);
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
case "build":
|
|
327
|
+
break;
|
|
328
|
+
default:
|
|
329
|
+
log(` Skipping unknown method: ${method}`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
61
333
|
function processBuilderChain(node) {
|
|
62
334
|
if (!ts.isCallExpression(node)) return;
|
|
63
|
-
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
335
|
+
if (ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "build") {
|
|
336
|
+
log("Found .build() call, tracing chain...");
|
|
337
|
+
const { calls, baseThemeVar } = traceBuilderCalls(node);
|
|
338
|
+
if (baseThemeVar) {
|
|
339
|
+
log(`Found fromTheme(${baseThemeVar})`);
|
|
340
|
+
analyzeBaseTheme2(baseThemeVar);
|
|
341
|
+
}
|
|
342
|
+
processCalls(calls);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
ts.forEachChild(node, processBuilderChain);
|
|
346
|
+
}
|
|
347
|
+
ts.forEachChild(sourceFile, (node) => {
|
|
348
|
+
if (ts.isVariableStatement(node)) {
|
|
349
|
+
for (const decl of node.declarationList.declarations) {
|
|
350
|
+
if (decl.initializer) {
|
|
351
|
+
processBuilderChain(decl.initializer);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (ts.isExportAssignment(node)) {
|
|
356
|
+
processBuilderChain(node.expression);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
log("Analysis complete:");
|
|
360
|
+
log(` Intents: ${values.intents.join(", ")}`);
|
|
361
|
+
log(` Radii: ${values.radii.join(", ")}`);
|
|
362
|
+
log(` Shadows: ${values.shadows.join(", ")}`);
|
|
363
|
+
log(` Breakpoints: ${values.breakpoints.join(", ")}`);
|
|
364
|
+
log(` Typography: ${values.typography.join(", ")}`);
|
|
365
|
+
log(` Size components: ${Object.keys(values.sizes).join(", ")}`);
|
|
366
|
+
return values;
|
|
367
|
+
}
|
|
368
|
+
function mergeThemeValues(target, source, sourceOverrides) {
|
|
369
|
+
const mergeArrays = (targetArr, sourceArr) => {
|
|
370
|
+
for (const item of sourceArr) {
|
|
371
|
+
if (!targetArr.includes(item)) {
|
|
372
|
+
targetArr.push(item);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
mergeArrays(target.intents, source.intents);
|
|
377
|
+
mergeArrays(target.radii, source.radii);
|
|
378
|
+
mergeArrays(target.shadows, source.shadows);
|
|
379
|
+
mergeArrays(target.breakpoints, source.breakpoints);
|
|
380
|
+
mergeArrays(target.typography, source.typography);
|
|
381
|
+
mergeArrays(target.surfaceColors, source.surfaceColors);
|
|
382
|
+
mergeArrays(target.textColors, source.textColors);
|
|
383
|
+
mergeArrays(target.borderColors, source.borderColors);
|
|
384
|
+
for (const [component, sizes] of Object.entries(source.sizes)) {
|
|
385
|
+
if (sourceOverrides || !target.sizes[component]) {
|
|
386
|
+
target.sizes[component] = sizes;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/analyzer/theme-analyzer.ts
|
|
392
|
+
function analyzeTheme(themePath, verbose = false) {
|
|
393
|
+
const resolvedPath = path2.resolve(themePath);
|
|
394
|
+
if (!fs2.existsSync(resolvedPath)) {
|
|
395
|
+
throw new Error(`Theme file not found: ${resolvedPath}`);
|
|
396
|
+
}
|
|
397
|
+
const log = (...args) => {
|
|
398
|
+
if (verbose) console.log("[theme-analyzer]", ...args);
|
|
399
|
+
};
|
|
400
|
+
log("Analyzing theme file:", resolvedPath);
|
|
401
|
+
const program = ts2.createProgram([resolvedPath], {
|
|
402
|
+
target: ts2.ScriptTarget.ES2020,
|
|
403
|
+
module: ts2.ModuleKind.ESNext,
|
|
404
|
+
strict: true,
|
|
405
|
+
esModuleInterop: true,
|
|
406
|
+
skipLibCheck: true,
|
|
407
|
+
allowSyntheticDefaultImports: true
|
|
408
|
+
});
|
|
409
|
+
const sourceFile = program.getSourceFile(resolvedPath);
|
|
410
|
+
if (!sourceFile) {
|
|
411
|
+
throw new Error(`Failed to parse theme file: ${resolvedPath}`);
|
|
412
|
+
}
|
|
413
|
+
const ctx = {
|
|
414
|
+
program,
|
|
415
|
+
typeChecker: program.getTypeChecker(),
|
|
416
|
+
verbose
|
|
417
|
+
};
|
|
418
|
+
const values = {
|
|
419
|
+
intents: [],
|
|
420
|
+
sizes: {},
|
|
421
|
+
radii: [],
|
|
422
|
+
shadows: [],
|
|
423
|
+
breakpoints: [],
|
|
424
|
+
typography: [],
|
|
425
|
+
surfaceColors: [],
|
|
426
|
+
textColors: [],
|
|
427
|
+
borderColors: []
|
|
428
|
+
};
|
|
429
|
+
const imports = /* @__PURE__ */ new Map();
|
|
430
|
+
ts2.forEachChild(sourceFile, (node) => {
|
|
431
|
+
if (ts2.isImportDeclaration(node)) {
|
|
432
|
+
const source = node.moduleSpecifier.text;
|
|
433
|
+
const clause = node.importClause;
|
|
434
|
+
if (clause?.namedBindings && ts2.isNamedImports(clause.namedBindings)) {
|
|
435
|
+
for (const element of clause.namedBindings.elements) {
|
|
436
|
+
const localName = element.name.text;
|
|
437
|
+
const importedName = element.propertyName?.text ?? localName;
|
|
438
|
+
imports.set(localName, { source, imported: importedName });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
function processBuilderChain(node) {
|
|
444
|
+
if (!ts2.isCallExpression(node)) return;
|
|
445
|
+
if (ts2.isPropertyAccessExpression(node.expression)) {
|
|
64
446
|
const methodName = node.expression.name.text;
|
|
65
447
|
if (methodName === "build") {
|
|
66
448
|
const calls = traceBuilderCalls(node);
|
|
@@ -68,15 +450,15 @@ function analyzeTheme(themePath, verbose = false) {
|
|
|
68
450
|
return;
|
|
69
451
|
}
|
|
70
452
|
}
|
|
71
|
-
|
|
453
|
+
ts2.forEachChild(node, processBuilderChain);
|
|
72
454
|
}
|
|
73
455
|
function traceBuilderCalls(node, calls = []) {
|
|
74
|
-
if (!
|
|
75
|
-
if (
|
|
456
|
+
if (!ts2.isPropertyAccessExpression(node.expression)) {
|
|
457
|
+
if (ts2.isCallExpression(node) && ts2.isIdentifier(node.expression)) {
|
|
76
458
|
const fnName = node.expression.text;
|
|
77
459
|
if (fnName === "fromTheme" && node.arguments.length > 0) {
|
|
78
460
|
const arg = node.arguments[0];
|
|
79
|
-
if (
|
|
461
|
+
if (ts2.isIdentifier(arg)) {
|
|
80
462
|
analyzeBaseTheme(arg.text, imports, values, ctx);
|
|
81
463
|
}
|
|
82
464
|
}
|
|
@@ -86,7 +468,7 @@ function analyzeTheme(themePath, verbose = false) {
|
|
|
86
468
|
const methodName = node.expression.name.text;
|
|
87
469
|
calls.unshift({ method: methodName, args: node.arguments });
|
|
88
470
|
const obj = node.expression.expression;
|
|
89
|
-
if (
|
|
471
|
+
if (ts2.isCallExpression(obj)) {
|
|
90
472
|
return traceBuilderCalls(obj, calls);
|
|
91
473
|
}
|
|
92
474
|
return calls;
|
|
@@ -120,11 +502,11 @@ function analyzeTheme(themePath, verbose = false) {
|
|
|
120
502
|
break;
|
|
121
503
|
}
|
|
122
504
|
case "setSizes": {
|
|
123
|
-
if (args[0] &&
|
|
505
|
+
if (args[0] && ts2.isObjectLiteralExpression(args[0])) {
|
|
124
506
|
for (const prop of args[0].properties) {
|
|
125
|
-
if (
|
|
507
|
+
if (ts2.isPropertyAssignment(prop)) {
|
|
126
508
|
const componentName = getPropertyName(prop.name);
|
|
127
|
-
if (componentName &&
|
|
509
|
+
if (componentName && ts2.isObjectLiteralExpression(prop.initializer)) {
|
|
128
510
|
values.sizes[componentName] = getObjectKeys(prop.initializer);
|
|
129
511
|
log(" Found sizes for", componentName + ":", values.sizes[componentName]);
|
|
130
512
|
}
|
|
@@ -134,18 +516,18 @@ function analyzeTheme(themePath, verbose = false) {
|
|
|
134
516
|
break;
|
|
135
517
|
}
|
|
136
518
|
case "setBreakpoints": {
|
|
137
|
-
if (args[0] &&
|
|
519
|
+
if (args[0] && ts2.isObjectLiteralExpression(args[0])) {
|
|
138
520
|
values.breakpoints = getObjectKeys(args[0]);
|
|
139
521
|
log(" Found breakpoints:", values.breakpoints);
|
|
140
522
|
}
|
|
141
523
|
break;
|
|
142
524
|
}
|
|
143
525
|
case "setColors": {
|
|
144
|
-
if (args[0] &&
|
|
526
|
+
if (args[0] && ts2.isObjectLiteralExpression(args[0])) {
|
|
145
527
|
for (const prop of args[0].properties) {
|
|
146
|
-
if (
|
|
528
|
+
if (ts2.isPropertyAssignment(prop)) {
|
|
147
529
|
const colorType = getPropertyName(prop.name);
|
|
148
|
-
if (
|
|
530
|
+
if (ts2.isObjectLiteralExpression(prop.initializer)) {
|
|
149
531
|
const keys = getObjectKeys(prop.initializer);
|
|
150
532
|
switch (colorType) {
|
|
151
533
|
case "surface":
|
|
@@ -174,15 +556,15 @@ function analyzeTheme(themePath, verbose = false) {
|
|
|
174
556
|
}
|
|
175
557
|
}
|
|
176
558
|
}
|
|
177
|
-
|
|
178
|
-
if (
|
|
559
|
+
ts2.forEachChild(sourceFile, (node) => {
|
|
560
|
+
if (ts2.isVariableStatement(node)) {
|
|
179
561
|
for (const decl of node.declarationList.declarations) {
|
|
180
562
|
if (decl.initializer) {
|
|
181
563
|
processBuilderChain(decl.initializer);
|
|
182
564
|
}
|
|
183
565
|
}
|
|
184
566
|
}
|
|
185
|
-
if (
|
|
567
|
+
if (ts2.isExportAssignment(node)) {
|
|
186
568
|
processBuilderChain(node.expression);
|
|
187
569
|
}
|
|
188
570
|
});
|
|
@@ -203,18 +585,40 @@ function analyzeBaseTheme(varName, imports, values, ctx) {
|
|
|
203
585
|
}
|
|
204
586
|
log("Base theme", varName, "imported from", importInfo.source);
|
|
205
587
|
if (importInfo.source === "@idealyst/theme" || importInfo.source.includes("@idealyst/theme")) {
|
|
206
|
-
const
|
|
207
|
-
|
|
588
|
+
const aliasPath = packageAliases["@idealyst/theme"];
|
|
589
|
+
if (aliasPath) {
|
|
590
|
+
const themeFileName = varName.toLowerCase().includes("dark") ? "darkTheme.ts" : "lightTheme.ts";
|
|
591
|
+
const themePath = path2.join(aliasPath, "src", themeFileName);
|
|
592
|
+
if (fs2.existsSync(themePath)) {
|
|
593
|
+
log(`Analyzing @idealyst/theme from source: ${themePath}`);
|
|
594
|
+
try {
|
|
595
|
+
const sourceValues = analyzeThemeSource(themePath, {
|
|
596
|
+
verbose: ctx.verbose,
|
|
597
|
+
aliases: packageAliases
|
|
598
|
+
});
|
|
599
|
+
mergeThemeValues2(values, sourceValues);
|
|
600
|
+
log("Successfully extracted values from source");
|
|
601
|
+
return;
|
|
602
|
+
} catch (err) {
|
|
603
|
+
log("Failed to analyze source, falling back to defaults:", err.message);
|
|
604
|
+
}
|
|
605
|
+
} else {
|
|
606
|
+
log(`Theme file not found at alias path: ${themePath}`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
208
609
|
log("Using default @idealyst/theme values");
|
|
610
|
+
const defaultValues = getDefaultThemeValues();
|
|
611
|
+
mergeThemeValues2(values, defaultValues);
|
|
209
612
|
return;
|
|
210
613
|
}
|
|
211
614
|
log("Skipping base theme analysis for:", importInfo.source);
|
|
212
615
|
}
|
|
213
616
|
function getDefaultThemeValues() {
|
|
214
617
|
return {
|
|
215
|
-
intents: ["primary", "success", "
|
|
618
|
+
intents: ["primary", "success", "danger", "warning", "neutral", "info"],
|
|
216
619
|
sizes: {
|
|
217
620
|
button: ["xs", "sm", "md", "lg", "xl"],
|
|
621
|
+
iconButton: ["xs", "sm", "md", "lg", "xl"],
|
|
218
622
|
chip: ["xs", "sm", "md", "lg", "xl"],
|
|
219
623
|
badge: ["xs", "sm", "md", "lg", "xl"],
|
|
220
624
|
icon: ["xs", "sm", "md", "lg", "xl"],
|
|
@@ -228,6 +632,7 @@ function getDefaultThemeValues() {
|
|
|
228
632
|
progress: ["xs", "sm", "md", "lg", "xl"],
|
|
229
633
|
accordion: ["xs", "sm", "md", "lg", "xl"],
|
|
230
634
|
activityIndicator: ["xs", "sm", "md", "lg", "xl"],
|
|
635
|
+
alert: ["xs", "sm", "md", "lg", "xl"],
|
|
231
636
|
breadcrumb: ["xs", "sm", "md", "lg", "xl"],
|
|
232
637
|
list: ["xs", "sm", "md", "lg", "xl"],
|
|
233
638
|
menu: ["xs", "sm", "md", "lg", "xl"],
|
|
@@ -248,7 +653,7 @@ function getDefaultThemeValues() {
|
|
|
248
653
|
borderColors: ["primary", "secondary", "tertiary", "disabled"]
|
|
249
654
|
};
|
|
250
655
|
}
|
|
251
|
-
function
|
|
656
|
+
function mergeThemeValues2(target, source) {
|
|
252
657
|
target.intents.push(...source.intents.filter((k) => !target.intents.includes(k)));
|
|
253
658
|
target.radii.push(...source.radii.filter((k) => !target.radii.includes(k)));
|
|
254
659
|
target.shadows.push(...source.shadows.filter((k) => !target.shadows.includes(k)));
|
|
@@ -265,32 +670,58 @@ function mergeThemeValues(target, source) {
|
|
|
265
670
|
}
|
|
266
671
|
function getStringValue(node) {
|
|
267
672
|
if (!node) return null;
|
|
268
|
-
if (
|
|
269
|
-
if (
|
|
673
|
+
if (ts2.isStringLiteral(node)) return node.text;
|
|
674
|
+
if (ts2.isIdentifier(node)) return node.text;
|
|
270
675
|
return null;
|
|
271
676
|
}
|
|
272
677
|
function getPropertyName(node) {
|
|
273
|
-
if (
|
|
274
|
-
if (
|
|
678
|
+
if (ts2.isIdentifier(node)) return node.text;
|
|
679
|
+
if (ts2.isStringLiteral(node)) return node.text;
|
|
275
680
|
return null;
|
|
276
681
|
}
|
|
277
682
|
function getObjectKeys(node) {
|
|
278
|
-
return node.properties.filter(
|
|
683
|
+
return node.properties.filter(ts2.isPropertyAssignment).map((prop) => getPropertyName(prop.name)).filter((k) => k !== null);
|
|
279
684
|
}
|
|
280
685
|
var themeKeysCache = null;
|
|
281
686
|
var themeLoadAttempted = false;
|
|
687
|
+
var packageAliases = {};
|
|
688
|
+
function resolveWithAliases(source, fromDir) {
|
|
689
|
+
for (const [aliasPrefix, aliasPath] of Object.entries(packageAliases)) {
|
|
690
|
+
if (source === aliasPrefix || source.startsWith(aliasPrefix + "/")) {
|
|
691
|
+
const remainder = source.slice(aliasPrefix.length);
|
|
692
|
+
let resolved = aliasPath + remainder;
|
|
693
|
+
if (!path2.isAbsolute(resolved)) {
|
|
694
|
+
resolved = path2.resolve(fromDir, resolved);
|
|
695
|
+
}
|
|
696
|
+
return resolved;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
282
701
|
function loadThemeKeys(opts, rootDir, _babelTypes, verboseMode = false) {
|
|
283
702
|
if (themeLoadAttempted && themeKeysCache) {
|
|
284
703
|
return themeKeysCache;
|
|
285
704
|
}
|
|
286
705
|
themeLoadAttempted = true;
|
|
706
|
+
if (opts.aliases && typeof opts.aliases === "object") {
|
|
707
|
+
packageAliases = opts.aliases;
|
|
708
|
+
if (verboseMode) {
|
|
709
|
+
console.log("[idealyst-plugin] Configured aliases:", packageAliases);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
287
712
|
const themePath = opts.themePath;
|
|
288
713
|
if (!themePath) {
|
|
289
714
|
throw new Error(
|
|
290
715
|
'[idealyst-plugin] themePath is required!\nAdd it to your babel config:\n ["@idealyst/theme/plugin", { themePath: "./src/theme/styles.ts" }]'
|
|
291
716
|
);
|
|
292
717
|
}
|
|
293
|
-
|
|
718
|
+
let resolvedPath;
|
|
719
|
+
const aliasResolved = resolveWithAliases(themePath, rootDir);
|
|
720
|
+
if (aliasResolved && fs2.existsSync(aliasResolved)) {
|
|
721
|
+
resolvedPath = aliasResolved;
|
|
722
|
+
} else {
|
|
723
|
+
resolvedPath = themePath.startsWith(".") ? path2.resolve(rootDir, themePath) : themePath;
|
|
724
|
+
}
|
|
294
725
|
if (verboseMode) {
|
|
295
726
|
console.log("[idealyst-plugin] Analyzing theme file via @idealyst/tooling:", resolvedPath);
|
|
296
727
|
}
|
|
@@ -325,14 +756,14 @@ function analyzeComponents(options) {
|
|
|
325
756
|
const registry = {};
|
|
326
757
|
const themeValues = analyzeTheme(themePath, false);
|
|
327
758
|
for (const componentPath of componentPaths) {
|
|
328
|
-
const resolvedPath =
|
|
329
|
-
if (!
|
|
759
|
+
const resolvedPath = path3.resolve(componentPath);
|
|
760
|
+
if (!fs3.existsSync(resolvedPath)) {
|
|
330
761
|
console.warn(`[component-analyzer] Path not found: ${resolvedPath}`);
|
|
331
762
|
continue;
|
|
332
763
|
}
|
|
333
764
|
const componentDirs = findComponentDirs(resolvedPath);
|
|
334
765
|
for (const dir of componentDirs) {
|
|
335
|
-
const componentName =
|
|
766
|
+
const componentName = path3.basename(dir);
|
|
336
767
|
if (include && !include.includes(componentName)) continue;
|
|
337
768
|
if (exclude && exclude.includes(componentName)) continue;
|
|
338
769
|
if (!includeInternal && componentName.startsWith("_")) continue;
|
|
@@ -346,12 +777,12 @@ function analyzeComponents(options) {
|
|
|
346
777
|
}
|
|
347
778
|
function findComponentDirs(basePath) {
|
|
348
779
|
const dirs = [];
|
|
349
|
-
const entries =
|
|
780
|
+
const entries = fs3.readdirSync(basePath, { withFileTypes: true });
|
|
350
781
|
for (const entry of entries) {
|
|
351
782
|
if (!entry.isDirectory()) continue;
|
|
352
|
-
const dirPath =
|
|
353
|
-
const hasIndex =
|
|
354
|
-
const hasTypes =
|
|
783
|
+
const dirPath = path3.join(basePath, entry.name);
|
|
784
|
+
const hasIndex = fs3.existsSync(path3.join(dirPath, "index.ts"));
|
|
785
|
+
const hasTypes = fs3.existsSync(path3.join(dirPath, "types.ts"));
|
|
355
786
|
if (hasIndex || hasTypes) {
|
|
356
787
|
dirs.push(dirPath);
|
|
357
788
|
}
|
|
@@ -359,14 +790,14 @@ function findComponentDirs(basePath) {
|
|
|
359
790
|
return dirs;
|
|
360
791
|
}
|
|
361
792
|
function analyzeComponentDir(dir, componentName, themeValues) {
|
|
362
|
-
const tsFiles =
|
|
793
|
+
const tsFiles = fs3.readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".tsx")).map((f) => path3.join(dir, f));
|
|
363
794
|
if (tsFiles.length === 0) {
|
|
364
795
|
return null;
|
|
365
796
|
}
|
|
366
|
-
const program =
|
|
367
|
-
target:
|
|
368
|
-
module:
|
|
369
|
-
jsx:
|
|
797
|
+
const program = ts3.createProgram(tsFiles, {
|
|
798
|
+
target: ts3.ScriptTarget.ES2020,
|
|
799
|
+
module: ts3.ModuleKind.ESNext,
|
|
800
|
+
jsx: ts3.JsxEmit.React,
|
|
370
801
|
strict: true,
|
|
371
802
|
esModuleInterop: true,
|
|
372
803
|
skipLibCheck: true
|
|
@@ -379,12 +810,12 @@ function analyzeComponentDir(dir, componentName, themeValues) {
|
|
|
379
810
|
for (const filePath of tsFiles) {
|
|
380
811
|
const sourceFile = program.getSourceFile(filePath);
|
|
381
812
|
if (!sourceFile) continue;
|
|
382
|
-
|
|
383
|
-
if (
|
|
813
|
+
ts3.forEachChild(sourceFile, (node) => {
|
|
814
|
+
if (ts3.isInterfaceDeclaration(node) && node.name.text === propsInterfaceName) {
|
|
384
815
|
propsInterface = node;
|
|
385
816
|
interfaceDescription = getJSDocDescription(node);
|
|
386
817
|
}
|
|
387
|
-
if (
|
|
818
|
+
if (ts3.isTypeAliasDeclaration(node) && node.name.text === propsInterfaceName) {
|
|
388
819
|
propsInterface = node;
|
|
389
820
|
interfaceDescription = getJSDocDescription(node);
|
|
390
821
|
}
|
|
@@ -396,8 +827,8 @@ function analyzeComponentDir(dir, componentName, themeValues) {
|
|
|
396
827
|
for (const filePath of tsFiles) {
|
|
397
828
|
const sourceFile = program.getSourceFile(filePath);
|
|
398
829
|
if (!sourceFile) continue;
|
|
399
|
-
|
|
400
|
-
if ((
|
|
830
|
+
ts3.forEachChild(sourceFile, (node) => {
|
|
831
|
+
if ((ts3.isInterfaceDeclaration(node) || ts3.isTypeAliasDeclaration(node)) && node.name.text === altName) {
|
|
401
832
|
propsInterface = node;
|
|
402
833
|
interfaceDescription = getJSDocDescription(node);
|
|
403
834
|
}
|
|
@@ -429,32 +860,32 @@ function analyzeComponentDir(dir, componentName, themeValues) {
|
|
|
429
860
|
description,
|
|
430
861
|
props,
|
|
431
862
|
category,
|
|
432
|
-
filePath:
|
|
863
|
+
filePath: path3.relative(process.cwd(), dir),
|
|
433
864
|
sampleProps
|
|
434
865
|
};
|
|
435
866
|
}
|
|
436
867
|
function extractSampleProps(dir) {
|
|
437
|
-
const docsPath =
|
|
438
|
-
if (!
|
|
868
|
+
const docsPath = path3.join(dir, "docs.ts");
|
|
869
|
+
if (!fs3.existsSync(docsPath)) {
|
|
439
870
|
return void 0;
|
|
440
871
|
}
|
|
441
872
|
try {
|
|
442
|
-
const content =
|
|
443
|
-
const sourceFile =
|
|
873
|
+
const content = fs3.readFileSync(docsPath, "utf-8");
|
|
874
|
+
const sourceFile = ts3.createSourceFile(
|
|
444
875
|
"docs.ts",
|
|
445
876
|
content,
|
|
446
|
-
|
|
877
|
+
ts3.ScriptTarget.ES2020,
|
|
447
878
|
true,
|
|
448
|
-
|
|
879
|
+
ts3.ScriptKind.TS
|
|
449
880
|
);
|
|
450
881
|
let samplePropsNode = null;
|
|
451
|
-
|
|
452
|
-
if (
|
|
453
|
-
const isExported = node.modifiers?.some((m) => m.kind ===
|
|
882
|
+
ts3.forEachChild(sourceFile, (node) => {
|
|
883
|
+
if (ts3.isVariableStatement(node)) {
|
|
884
|
+
const isExported = node.modifiers?.some((m) => m.kind === ts3.SyntaxKind.ExportKeyword);
|
|
454
885
|
if (isExported) {
|
|
455
886
|
for (const decl of node.declarationList.declarations) {
|
|
456
|
-
if (
|
|
457
|
-
if (
|
|
887
|
+
if (ts3.isIdentifier(decl.name) && decl.name.text === "sampleProps" && decl.initializer) {
|
|
888
|
+
if (ts3.isObjectLiteralExpression(decl.initializer)) {
|
|
458
889
|
samplePropsNode = decl.initializer;
|
|
459
890
|
}
|
|
460
891
|
}
|
|
@@ -468,13 +899,13 @@ function extractSampleProps(dir) {
|
|
|
468
899
|
const result = {};
|
|
469
900
|
const propsNode = samplePropsNode;
|
|
470
901
|
for (const prop of propsNode.properties) {
|
|
471
|
-
if (
|
|
902
|
+
if (ts3.isPropertyAssignment(prop) && ts3.isIdentifier(prop.name)) {
|
|
472
903
|
const propName = prop.name.text;
|
|
473
|
-
if (propName === "props" &&
|
|
904
|
+
if (propName === "props" && ts3.isObjectLiteralExpression(prop.initializer)) {
|
|
474
905
|
result.props = extractObjectLiteral(prop.initializer, content);
|
|
475
906
|
} else if (propName === "children") {
|
|
476
907
|
result.children = prop.initializer.getText(sourceFile);
|
|
477
|
-
} else if (propName === "state" &&
|
|
908
|
+
} else if (propName === "state" && ts3.isObjectLiteralExpression(prop.initializer)) {
|
|
478
909
|
result.state = extractObjectLiteral(prop.initializer, content);
|
|
479
910
|
}
|
|
480
911
|
}
|
|
@@ -488,20 +919,20 @@ function extractSampleProps(dir) {
|
|
|
488
919
|
function extractObjectLiteral(node, sourceContent) {
|
|
489
920
|
const result = {};
|
|
490
921
|
for (const prop of node.properties) {
|
|
491
|
-
if (
|
|
922
|
+
if (ts3.isPropertyAssignment(prop) && ts3.isIdentifier(prop.name)) {
|
|
492
923
|
const key = prop.name.text;
|
|
493
924
|
const init = prop.initializer;
|
|
494
|
-
if (
|
|
925
|
+
if (ts3.isStringLiteral(init)) {
|
|
495
926
|
result[key] = init.text;
|
|
496
|
-
} else if (
|
|
927
|
+
} else if (ts3.isNumericLiteral(init)) {
|
|
497
928
|
result[key] = Number(init.text);
|
|
498
|
-
} else if (init.kind ===
|
|
929
|
+
} else if (init.kind === ts3.SyntaxKind.TrueKeyword) {
|
|
499
930
|
result[key] = true;
|
|
500
|
-
} else if (init.kind ===
|
|
931
|
+
} else if (init.kind === ts3.SyntaxKind.FalseKeyword) {
|
|
501
932
|
result[key] = false;
|
|
502
|
-
} else if (
|
|
933
|
+
} else if (ts3.isArrayLiteralExpression(init)) {
|
|
503
934
|
result[key] = extractArrayLiteral(init, sourceContent);
|
|
504
|
-
} else if (
|
|
935
|
+
} else if (ts3.isObjectLiteralExpression(init)) {
|
|
505
936
|
result[key] = extractObjectLiteral(init, sourceContent);
|
|
506
937
|
} else {
|
|
507
938
|
result[key] = init.getText();
|
|
@@ -513,17 +944,17 @@ function extractObjectLiteral(node, sourceContent) {
|
|
|
513
944
|
function extractArrayLiteral(node, sourceContent) {
|
|
514
945
|
const result = [];
|
|
515
946
|
for (const element of node.elements) {
|
|
516
|
-
if (
|
|
947
|
+
if (ts3.isStringLiteral(element)) {
|
|
517
948
|
result.push(element.text);
|
|
518
|
-
} else if (
|
|
949
|
+
} else if (ts3.isNumericLiteral(element)) {
|
|
519
950
|
result.push(Number(element.text));
|
|
520
|
-
} else if (element.kind ===
|
|
951
|
+
} else if (element.kind === ts3.SyntaxKind.TrueKeyword) {
|
|
521
952
|
result.push(true);
|
|
522
|
-
} else if (element.kind ===
|
|
953
|
+
} else if (element.kind === ts3.SyntaxKind.FalseKeyword) {
|
|
523
954
|
result.push(false);
|
|
524
|
-
} else if (
|
|
955
|
+
} else if (ts3.isObjectLiteralExpression(element)) {
|
|
525
956
|
result.push(extractObjectLiteral(element, sourceContent));
|
|
526
|
-
} else if (
|
|
957
|
+
} else if (ts3.isArrayLiteralExpression(element)) {
|
|
527
958
|
result.push(extractArrayLiteral(element, sourceContent));
|
|
528
959
|
} else {
|
|
529
960
|
result.push(element.getText());
|
|
@@ -538,8 +969,8 @@ function analyzeProperty(symbol, typeChecker, themeValues) {
|
|
|
538
969
|
const declaration = declarations[0];
|
|
539
970
|
const type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration);
|
|
540
971
|
const typeString = typeChecker.typeToString(type);
|
|
541
|
-
const description =
|
|
542
|
-
const required = !(symbol.flags &
|
|
972
|
+
const description = ts3.displayPartsToString(symbol.getDocumentationComment(typeChecker)) || void 0;
|
|
973
|
+
const required = !(symbol.flags & ts3.SymbolFlags.Optional);
|
|
543
974
|
const values = extractPropValues(type, typeString, typeChecker, themeValues);
|
|
544
975
|
const defaultValue = extractDefaultValue(symbol);
|
|
545
976
|
return {
|
|
@@ -580,7 +1011,7 @@ function extractDefaultValue(symbol) {
|
|
|
580
1011
|
const tags = symbol.getJsDocTags();
|
|
581
1012
|
for (const tag of tags) {
|
|
582
1013
|
if (tag.name === "default" && tag.text) {
|
|
583
|
-
const value =
|
|
1014
|
+
const value = ts3.displayPartsToString(tag.text);
|
|
584
1015
|
try {
|
|
585
1016
|
return JSON.parse(value);
|
|
586
1017
|
} catch {
|
|
@@ -683,8 +1114,8 @@ function inferCategory(componentName) {
|
|
|
683
1114
|
}
|
|
684
1115
|
|
|
685
1116
|
// src/vite-plugin.ts
|
|
686
|
-
import * as
|
|
687
|
-
import * as
|
|
1117
|
+
import * as fs4 from "fs";
|
|
1118
|
+
import * as path4 from "path";
|
|
688
1119
|
function idealystDocsPlugin(options) {
|
|
689
1120
|
let registry = null;
|
|
690
1121
|
const { debug = false, output, outputPath } = options;
|
|
@@ -702,11 +1133,11 @@ function idealystDocsPlugin(options) {
|
|
|
702
1133
|
log("Components found:", Object.keys(registry));
|
|
703
1134
|
}
|
|
704
1135
|
if (output === "file" && outputPath) {
|
|
705
|
-
const outputDir =
|
|
706
|
-
if (!
|
|
707
|
-
|
|
1136
|
+
const outputDir = path4.dirname(outputPath);
|
|
1137
|
+
if (!fs4.existsSync(outputDir)) {
|
|
1138
|
+
fs4.mkdirSync(outputDir, { recursive: true });
|
|
708
1139
|
}
|
|
709
|
-
|
|
1140
|
+
fs4.writeFileSync(
|
|
710
1141
|
outputPath,
|
|
711
1142
|
`// Auto-generated by @idealyst/tooling - DO NOT EDIT
|
|
712
1143
|
export const componentRegistry = ${JSON.stringify(registry, null, 2)} as const;
|
|
@@ -777,8 +1208,8 @@ export const componentRegistry = ${JSON.stringify(registry, null, 2)} as const;
|
|
|
777
1208
|
},
|
|
778
1209
|
// Regenerate on component file changes
|
|
779
1210
|
handleHotUpdate({ file, server }) {
|
|
780
|
-
const isComponentFile2 = options.componentPaths.some((p) => file.includes(
|
|
781
|
-
const isThemeFile = file.includes(
|
|
1211
|
+
const isComponentFile2 = options.componentPaths.some((p) => file.includes(path4.resolve(p))) && (file.endsWith(".ts") || file.endsWith(".tsx"));
|
|
1212
|
+
const isThemeFile = file.includes(path4.resolve(options.themePath));
|
|
782
1213
|
if (isComponentFile2 || isThemeFile) {
|
|
783
1214
|
log(`File changed: ${file}, regenerating registry...`);
|
|
784
1215
|
registry = null;
|
|
@@ -800,7 +1231,7 @@ function generateComponentRegistry(options) {
|
|
|
800
1231
|
}
|
|
801
1232
|
|
|
802
1233
|
// src/utils/fileClassifier.ts
|
|
803
|
-
import * as
|
|
1234
|
+
import * as path5 from "path";
|
|
804
1235
|
var EXTENSION_PATTERNS = [
|
|
805
1236
|
// Platform-specific component files
|
|
806
1237
|
{ pattern: /\.web\.(tsx|jsx)$/, type: "web" },
|
|
@@ -824,7 +1255,7 @@ var EXCLUDED_PATTERNS = [
|
|
|
824
1255
|
/index\.(ts|tsx|js|jsx)$/
|
|
825
1256
|
];
|
|
826
1257
|
function classifyFile(filePath) {
|
|
827
|
-
const fileName =
|
|
1258
|
+
const fileName = path5.basename(filePath);
|
|
828
1259
|
for (const pattern of EXCLUDED_PATTERNS) {
|
|
829
1260
|
if (pattern.test(fileName)) {
|
|
830
1261
|
return "other";
|
|
@@ -855,12 +1286,12 @@ function getExpectedPlatform(filePath) {
|
|
|
855
1286
|
return null;
|
|
856
1287
|
}
|
|
857
1288
|
function getBaseName(filePath) {
|
|
858
|
-
const fileName =
|
|
1289
|
+
const fileName = path5.basename(filePath);
|
|
859
1290
|
return fileName.replace(/\.(web|native|ios|android)\.(tsx|jsx|ts|js)$/, "").replace(/\.styles?\.(tsx|jsx|ts|js)$/, "").replace(/\.types?\.(tsx|ts)$/, "").replace(/\.(tsx|jsx|ts|js)$/, "");
|
|
860
1291
|
}
|
|
861
1292
|
|
|
862
1293
|
// src/utils/importParser.ts
|
|
863
|
-
import * as
|
|
1294
|
+
import * as ts4 from "typescript";
|
|
864
1295
|
|
|
865
1296
|
// src/rules/reactNativePrimitives.ts
|
|
866
1297
|
var REACT_NATIVE_SOURCES = [
|
|
@@ -1344,19 +1775,19 @@ function getPlatformForSource(source, options) {
|
|
|
1344
1775
|
}
|
|
1345
1776
|
function parseImports(sourceCode, filePath = "unknown.tsx", options) {
|
|
1346
1777
|
const imports = [];
|
|
1347
|
-
const sourceFile =
|
|
1778
|
+
const sourceFile = ts4.createSourceFile(
|
|
1348
1779
|
filePath,
|
|
1349
1780
|
sourceCode,
|
|
1350
|
-
|
|
1781
|
+
ts4.ScriptTarget.Latest,
|
|
1351
1782
|
true,
|
|
1352
|
-
filePath.endsWith(".tsx") || filePath.endsWith(".jsx") ?
|
|
1783
|
+
filePath.endsWith(".tsx") || filePath.endsWith(".jsx") ? ts4.ScriptKind.TSX : ts4.ScriptKind.TS
|
|
1353
1784
|
);
|
|
1354
1785
|
const visit = (node) => {
|
|
1355
|
-
if (
|
|
1786
|
+
if (ts4.isImportDeclaration(node)) {
|
|
1356
1787
|
const importInfo = parseImportDeclaration(node, sourceFile, options);
|
|
1357
1788
|
imports.push(...importInfo);
|
|
1358
1789
|
}
|
|
1359
|
-
if (
|
|
1790
|
+
if (ts4.isCallExpression(node) && ts4.isIdentifier(node.expression) && node.expression.text === "require" && node.arguments.length === 1 && ts4.isStringLiteral(node.arguments[0])) {
|
|
1360
1791
|
const source = node.arguments[0].text;
|
|
1361
1792
|
const { line, character } = sourceFile.getLineAndCharacterOfPosition(
|
|
1362
1793
|
node.getStart()
|
|
@@ -1372,14 +1803,14 @@ function parseImports(sourceCode, filePath = "unknown.tsx", options) {
|
|
|
1372
1803
|
isTypeOnly: false
|
|
1373
1804
|
});
|
|
1374
1805
|
}
|
|
1375
|
-
|
|
1806
|
+
ts4.forEachChild(node, visit);
|
|
1376
1807
|
};
|
|
1377
1808
|
visit(sourceFile);
|
|
1378
1809
|
return imports;
|
|
1379
1810
|
}
|
|
1380
1811
|
function parseImportDeclaration(node, sourceFile, options) {
|
|
1381
1812
|
const imports = [];
|
|
1382
|
-
if (!
|
|
1813
|
+
if (!ts4.isStringLiteral(node.moduleSpecifier)) {
|
|
1383
1814
|
return imports;
|
|
1384
1815
|
}
|
|
1385
1816
|
const source = node.moduleSpecifier.text;
|
|
@@ -1406,7 +1837,7 @@ function parseImportDeclaration(node, sourceFile, options) {
|
|
|
1406
1837
|
}
|
|
1407
1838
|
const namedBindings = importClause.namedBindings;
|
|
1408
1839
|
if (namedBindings) {
|
|
1409
|
-
if (
|
|
1840
|
+
if (ts4.isNamespaceImport(namedBindings)) {
|
|
1410
1841
|
const { line, character } = sourceFile.getLineAndCharacterOfPosition(
|
|
1411
1842
|
namedBindings.name.getStart()
|
|
1412
1843
|
);
|
|
@@ -1420,7 +1851,7 @@ function parseImportDeclaration(node, sourceFile, options) {
|
|
|
1420
1851
|
isNamespace: true,
|
|
1421
1852
|
isTypeOnly
|
|
1422
1853
|
});
|
|
1423
|
-
} else if (
|
|
1854
|
+
} else if (ts4.isNamedImports(namedBindings)) {
|
|
1424
1855
|
for (const element of namedBindings.elements) {
|
|
1425
1856
|
const { line, character } = sourceFile.getLineAndCharacterOfPosition(
|
|
1426
1857
|
element.name.getStart()
|