@zeus-js/component-analyzer 0.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* component-analyzer v0.1.0-beta.0
|
|
3
|
+
* (c) 2026 baicie
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
**/
|
|
6
|
+
import { parse } from "@babel/parser";
|
|
7
|
+
import * as t from "@babel/types";
|
|
8
|
+
import fs from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import fg from "fast-glob";
|
|
11
|
+
//#region packages/web-c/component-analyzer/src/ast.ts
|
|
12
|
+
function parseSource(code, file) {
|
|
13
|
+
return parse(code, {
|
|
14
|
+
sourceType: "module",
|
|
15
|
+
sourceFilename: file,
|
|
16
|
+
plugins: [
|
|
17
|
+
"typescript",
|
|
18
|
+
"jsx",
|
|
19
|
+
"decorators-legacy",
|
|
20
|
+
"classProperties",
|
|
21
|
+
"objectRestSpread"
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function walk(node, visitor, parent = null) {
|
|
26
|
+
var _t$VISITOR_KEYS$node$;
|
|
27
|
+
if (!node) return;
|
|
28
|
+
visitor(node, parent);
|
|
29
|
+
const keys = (_t$VISITOR_KEYS$node$ = t.VISITOR_KEYS[node.type]) !== null && _t$VISITOR_KEYS$node$ !== void 0 ? _t$VISITOR_KEYS$node$ : [];
|
|
30
|
+
for (const key of keys) {
|
|
31
|
+
const value = node[key];
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
for (const child of value) if (child && typeof child === "object" && "type" in child) walk(child, visitor, node);
|
|
34
|
+
} else if (value && typeof value === "object" && "type" in value) walk(value, visitor, node);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
//#region packages/web-c/component-analyzer/src/extractDefineElement.ts
|
|
39
|
+
function extractDefineElementCalls(ast) {
|
|
40
|
+
const defineElementLocalNames = collectDefineElementLocalNames(ast);
|
|
41
|
+
const exportedNames = collectExportedNames(ast);
|
|
42
|
+
const records = [];
|
|
43
|
+
walk(ast.program, (node) => {
|
|
44
|
+
if (!t.isVariableDeclarator(node)) return;
|
|
45
|
+
if (!t.isIdentifier(node.id)) return;
|
|
46
|
+
if (!t.isCallExpression(node.init)) return;
|
|
47
|
+
const call = node.init;
|
|
48
|
+
if (!isDefineElementCall(call, defineElementLocalNames)) return;
|
|
49
|
+
const tag = extractTag(call);
|
|
50
|
+
if (!tag) return;
|
|
51
|
+
const name = node.id.name;
|
|
52
|
+
const options = extractOptions(call);
|
|
53
|
+
const setup = call.arguments[2];
|
|
54
|
+
const propsTypeName = extractPropsTypeName(call);
|
|
55
|
+
if (!exportedNames.has(name)) return;
|
|
56
|
+
records.push({
|
|
57
|
+
name,
|
|
58
|
+
exportName: name,
|
|
59
|
+
tag,
|
|
60
|
+
propsTypeName,
|
|
61
|
+
options,
|
|
62
|
+
setup,
|
|
63
|
+
call
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
return records;
|
|
67
|
+
}
|
|
68
|
+
function collectDefineElementLocalNames(ast) {
|
|
69
|
+
const names = /* @__PURE__ */ new Set();
|
|
70
|
+
for (const node of ast.program.body) {
|
|
71
|
+
if (!t.isImportDeclaration(node)) continue;
|
|
72
|
+
const source = node.source.value;
|
|
73
|
+
if (source !== "@zeus-js/zeus" && source !== "@zeus-js/runtime-dom") continue;
|
|
74
|
+
for (const spec of node.specifiers) {
|
|
75
|
+
if (!t.isImportSpecifier(spec)) continue;
|
|
76
|
+
const imported = spec.imported;
|
|
77
|
+
if (t.isIdentifier(imported) && imported.name === "defineElement" || t.isStringLiteral(imported) && imported.value === "defineElement") names.add(spec.local.name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return names;
|
|
81
|
+
}
|
|
82
|
+
function collectExportedNames(ast) {
|
|
83
|
+
const names = /* @__PURE__ */ new Set();
|
|
84
|
+
for (const node of ast.program.body) if (t.isExportNamedDeclaration(node)) {
|
|
85
|
+
if (t.isVariableDeclaration(node.declaration)) {
|
|
86
|
+
for (const declarator of node.declaration.declarations) if (t.isIdentifier(declarator.id)) names.add(declarator.id.name);
|
|
87
|
+
}
|
|
88
|
+
for (const spec of node.specifiers) if (t.isExportSpecifier(spec) && t.isIdentifier(spec.local)) names.add(spec.local.name);
|
|
89
|
+
}
|
|
90
|
+
return names;
|
|
91
|
+
}
|
|
92
|
+
function isDefineElementCall(call, localNames) {
|
|
93
|
+
return t.isIdentifier(call.callee) && localNames.has(call.callee.name);
|
|
94
|
+
}
|
|
95
|
+
function extractTag(call) {
|
|
96
|
+
const first = call.arguments[0];
|
|
97
|
+
if (t.isStringLiteral(first)) return first.value;
|
|
98
|
+
}
|
|
99
|
+
function extractOptions(call) {
|
|
100
|
+
const second = call.arguments[1];
|
|
101
|
+
if (t.isObjectExpression(second)) return second;
|
|
102
|
+
}
|
|
103
|
+
function extractPropsTypeName(call) {
|
|
104
|
+
var _call$typeParameters;
|
|
105
|
+
const first = (_call$typeParameters = call.typeParameters) === null || _call$typeParameters === void 0 ? void 0 : _call$typeParameters.params[0];
|
|
106
|
+
if (!first) return void 0;
|
|
107
|
+
if (t.isTSTypeReference(first) && t.isIdentifier(first.typeName)) return first.typeName.name;
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region packages/web-c/component-analyzer/src/utils.ts
|
|
111
|
+
function getObjectKey(key) {
|
|
112
|
+
if (t.isIdentifier(key)) return key.name;
|
|
113
|
+
if (t.isStringLiteral(key)) return key.value;
|
|
114
|
+
if (t.isNumericLiteral(key)) return String(key.value);
|
|
115
|
+
}
|
|
116
|
+
function getObjectProperty(object, name) {
|
|
117
|
+
for (const prop of object.properties) {
|
|
118
|
+
if (!t.isObjectProperty(prop)) continue;
|
|
119
|
+
if (getObjectKey(prop.key) === name) return prop.value;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function staticValue(node) {
|
|
123
|
+
if (!node) return void 0;
|
|
124
|
+
if (t.isStringLiteral(node)) return node.value;
|
|
125
|
+
if (t.isNumericLiteral(node)) return node.value;
|
|
126
|
+
if (t.isBooleanLiteral(node)) return node.value;
|
|
127
|
+
if (t.isNullLiteral(node)) return null;
|
|
128
|
+
if (t.isIdentifier(node) && node.name === "undefined") return void 0;
|
|
129
|
+
if (t.isArrayExpression(node)) return node.elements.map((element) => {
|
|
130
|
+
if (!element) return null;
|
|
131
|
+
if (t.isSpreadElement(element)) return void 0;
|
|
132
|
+
return staticValue(element);
|
|
133
|
+
});
|
|
134
|
+
if (t.isObjectExpression(node)) {
|
|
135
|
+
const result = {};
|
|
136
|
+
for (const prop of node.properties) {
|
|
137
|
+
if (!t.isObjectProperty(prop)) continue;
|
|
138
|
+
const key = getObjectKey(prop.key);
|
|
139
|
+
if (!key) continue;
|
|
140
|
+
result[key] = staticValue(prop.value);
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function getLeadingDescription(node) {
|
|
146
|
+
const comments = node.leadingComments;
|
|
147
|
+
if (!(comments === null || comments === void 0 ? void 0 : comments.length)) return void 0;
|
|
148
|
+
return comments.map((comment) => comment.value).join("\n").replace(/\*/g, "").split("\n").map((line) => line.trim()).filter(Boolean).join("\n") || void 0;
|
|
149
|
+
}
|
|
150
|
+
function uniqueSorted(values) {
|
|
151
|
+
return Array.from(new Set(values)).sort();
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region packages/web-c/component-analyzer/src/extractMeta.ts
|
|
155
|
+
function extractInlineMeta(options) {
|
|
156
|
+
if (!options) return {};
|
|
157
|
+
const metaNode = getObjectProperty(options, "meta");
|
|
158
|
+
if (!t.isObjectExpression(metaNode)) return {};
|
|
159
|
+
const value = staticValue(metaNode);
|
|
160
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
161
|
+
return value;
|
|
162
|
+
}
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region packages/web-c/component-analyzer/src/extractProps.ts
|
|
165
|
+
function extractRuntimeProps(options) {
|
|
166
|
+
if (!options) return {};
|
|
167
|
+
const propsNode = getObjectProperty(options, "props");
|
|
168
|
+
if (!t.isObjectExpression(propsNode)) return {};
|
|
169
|
+
const props = {};
|
|
170
|
+
for (const prop of propsNode.properties) {
|
|
171
|
+
if (!t.isObjectProperty(prop)) continue;
|
|
172
|
+
const key = getObjectKey(prop.key);
|
|
173
|
+
if (!key) continue;
|
|
174
|
+
props[key] = extractRuntimeProp(prop.value);
|
|
175
|
+
}
|
|
176
|
+
return props;
|
|
177
|
+
}
|
|
178
|
+
function extractRuntimeProp(node) {
|
|
179
|
+
if (t.isIdentifier(node)) return { type: typeFromConstructorName(node.name) };
|
|
180
|
+
if (t.isObjectExpression(node)) {
|
|
181
|
+
const typeNode = getObjectProperty(node, "type");
|
|
182
|
+
const attrNode = getObjectProperty(node, "attr");
|
|
183
|
+
const reflectNode = getObjectProperty(node, "reflect");
|
|
184
|
+
const defaultNode = getObjectProperty(node, "default");
|
|
185
|
+
const prop = { type: t.isIdentifier(typeNode) ? typeFromConstructorName(typeNode.name) : "unknown" };
|
|
186
|
+
if (attrNode) {
|
|
187
|
+
const attr = staticValue(attrNode);
|
|
188
|
+
if (attr === false || typeof attr === "string") prop.attr = attr;
|
|
189
|
+
}
|
|
190
|
+
if (reflectNode) {
|
|
191
|
+
const reflect = staticValue(reflectNode);
|
|
192
|
+
if (typeof reflect === "boolean") prop.reflect = reflect;
|
|
193
|
+
}
|
|
194
|
+
if (defaultNode) {
|
|
195
|
+
if (!t.isFunctionExpression(defaultNode) && !t.isArrowFunctionExpression(defaultNode)) prop.default = staticValue(defaultNode);
|
|
196
|
+
}
|
|
197
|
+
return prop;
|
|
198
|
+
}
|
|
199
|
+
return { type: "unknown" };
|
|
200
|
+
}
|
|
201
|
+
function typeFromConstructorName(name) {
|
|
202
|
+
switch (name) {
|
|
203
|
+
case "String": return "string";
|
|
204
|
+
case "Number": return "number";
|
|
205
|
+
case "Boolean": return "boolean";
|
|
206
|
+
case "Object": return "object";
|
|
207
|
+
case "Array": return "array";
|
|
208
|
+
default: return "unknown";
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//#endregion
|
|
212
|
+
//#region packages/web-c/component-analyzer/src/extractSetup.ts
|
|
213
|
+
function extractSetupMeta(setup) {
|
|
214
|
+
const events = {};
|
|
215
|
+
const slots = {};
|
|
216
|
+
const hostAttributes = [];
|
|
217
|
+
const cssParts = [];
|
|
218
|
+
if (!setup || t.isSpreadElement(setup) || t.isArgumentPlaceholder(setup)) return {
|
|
219
|
+
events,
|
|
220
|
+
slots,
|
|
221
|
+
hostAttributes,
|
|
222
|
+
cssParts
|
|
223
|
+
};
|
|
224
|
+
walk(setup, (node) => {
|
|
225
|
+
extractEmit(node, events);
|
|
226
|
+
extractSlot(node, slots);
|
|
227
|
+
extractHostAttributes(node, hostAttributes);
|
|
228
|
+
extractCssParts(node, cssParts);
|
|
229
|
+
});
|
|
230
|
+
return {
|
|
231
|
+
events,
|
|
232
|
+
slots,
|
|
233
|
+
hostAttributes: uniqueSorted(hostAttributes),
|
|
234
|
+
cssParts: uniqueSorted(cssParts)
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function extractEmit(node, events) {
|
|
238
|
+
if (!t.isCallExpression(node)) return;
|
|
239
|
+
if (!t.isIdentifier(node.callee, { name: "emit" })) return;
|
|
240
|
+
const first = node.arguments[0];
|
|
241
|
+
if (!t.isStringLiteral(first)) return;
|
|
242
|
+
const eventName = first.value;
|
|
243
|
+
events[eventName] || (events[eventName] = {});
|
|
244
|
+
const detailNode = node.arguments[1];
|
|
245
|
+
if (t.isObjectExpression(detailNode)) events[eventName].detail = inferDetail(detailNode);
|
|
246
|
+
}
|
|
247
|
+
function inferDetail(node) {
|
|
248
|
+
const result = {};
|
|
249
|
+
for (const prop of node.properties) {
|
|
250
|
+
if (!t.isObjectProperty(prop)) continue;
|
|
251
|
+
const key = getObjectKey(prop.key);
|
|
252
|
+
if (!key) continue;
|
|
253
|
+
result[key] = inferExpressionType(prop.value);
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
function inferExpressionType(node) {
|
|
258
|
+
if (t.isStringLiteral(node)) return "string";
|
|
259
|
+
if (t.isNumericLiteral(node)) return "number";
|
|
260
|
+
if (t.isBooleanLiteral(node)) return "boolean";
|
|
261
|
+
if (t.isObjectExpression(node)) return "object";
|
|
262
|
+
if (t.isArrayExpression(node)) return "array";
|
|
263
|
+
if (t.isIdentifier(node)) return "unknown";
|
|
264
|
+
return "unknown";
|
|
265
|
+
}
|
|
266
|
+
function extractSlot(node, slots) {
|
|
267
|
+
var _getJSXStringAttribut;
|
|
268
|
+
if (!t.isJSXElement(node)) return;
|
|
269
|
+
const name = node.openingElement.name;
|
|
270
|
+
if (!t.isJSXIdentifier(name, { name: "Slot" })) return;
|
|
271
|
+
const slotName = (_getJSXStringAttribut = getJSXStringAttribute(node, "name")) !== null && _getJSXStringAttribut !== void 0 ? _getJSXStringAttribut : "default";
|
|
272
|
+
slots[slotName] || (slots[slotName] = {});
|
|
273
|
+
}
|
|
274
|
+
function extractHostAttributes(node, hostAttributes) {
|
|
275
|
+
if (!t.isJSXElement(node)) return;
|
|
276
|
+
const name = node.openingElement.name;
|
|
277
|
+
if (!t.isJSXIdentifier(name, { name: "Host" })) return;
|
|
278
|
+
for (const attr of node.openingElement.attributes) {
|
|
279
|
+
if (!t.isJSXAttribute(attr)) continue;
|
|
280
|
+
if (!t.isJSXIdentifier(attr.name)) continue;
|
|
281
|
+
const attrName = normalizeJsxAttrName(attr.name.name);
|
|
282
|
+
if (attrName.startsWith("data-") || attrName.startsWith("aria-") || attrName === "role" || attrName === "part" || attrName === "class" || attrName === "style" || attrName === "id" || attrName === "tabindex") hostAttributes.push(attrName);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function extractCssParts(node, cssParts) {
|
|
286
|
+
if (!t.isJSXElement(node)) return;
|
|
287
|
+
const value = getJSXStringAttribute(node, "part");
|
|
288
|
+
if (!value) return;
|
|
289
|
+
for (const part of value.split(/\s+/)) if (part) cssParts.push(part);
|
|
290
|
+
}
|
|
291
|
+
function getJSXStringAttribute(node, attrName) {
|
|
292
|
+
for (const attr of node.openingElement.attributes) {
|
|
293
|
+
if (!t.isJSXAttribute(attr)) continue;
|
|
294
|
+
if (!t.isJSXIdentifier(attr.name, { name: attrName })) continue;
|
|
295
|
+
if (!attr.value) return "";
|
|
296
|
+
if (t.isStringLiteral(attr.value)) return attr.value.value;
|
|
297
|
+
if (t.isJSXExpressionContainer(attr.value) && t.isExpression(attr.value.expression)) {
|
|
298
|
+
const value = staticValue(attr.value.expression);
|
|
299
|
+
if (typeof value === "string") return value;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function normalizeJsxAttrName(name) {
|
|
304
|
+
switch (name) {
|
|
305
|
+
case "className": return "class";
|
|
306
|
+
case "tabIndex": return "tabindex";
|
|
307
|
+
default: return name;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
//#endregion
|
|
311
|
+
//#region packages/web-c/component-analyzer/src/extractTypeProps.ts
|
|
312
|
+
function collectLocalPropTypes(ast) {
|
|
313
|
+
const map = /* @__PURE__ */ new Map();
|
|
314
|
+
for (const node of ast.program.body) {
|
|
315
|
+
if (t.isExportNamedDeclaration(node)) {
|
|
316
|
+
const declaration = node.declaration;
|
|
317
|
+
if (t.isTSInterfaceDeclaration(declaration)) map.set(declaration.id.name, extractInterfaceProps(declaration));
|
|
318
|
+
if (t.isTSTypeAliasDeclaration(declaration)) {
|
|
319
|
+
const props = extractTypeAliasProps(declaration);
|
|
320
|
+
if (props) map.set(declaration.id.name, props);
|
|
321
|
+
}
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
if (t.isTSInterfaceDeclaration(node)) map.set(node.id.name, extractInterfaceProps(node));
|
|
325
|
+
if (t.isTSTypeAliasDeclaration(node)) {
|
|
326
|
+
const props = extractTypeAliasProps(node);
|
|
327
|
+
if (props) map.set(node.id.name, props);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return map;
|
|
331
|
+
}
|
|
332
|
+
function extractInterfaceProps(node) {
|
|
333
|
+
const result = {};
|
|
334
|
+
for (const member of node.body.body) {
|
|
335
|
+
if (!t.isTSPropertySignature(member)) continue;
|
|
336
|
+
const key = getObjectKey(member.key);
|
|
337
|
+
if (!key) continue;
|
|
338
|
+
result[key] = extractTsProperty(member);
|
|
339
|
+
}
|
|
340
|
+
return result;
|
|
341
|
+
}
|
|
342
|
+
function extractTypeAliasProps(node) {
|
|
343
|
+
if (!t.isTSTypeLiteral(node.typeAnnotation)) return void 0;
|
|
344
|
+
const result = {};
|
|
345
|
+
for (const member of node.typeAnnotation.members) {
|
|
346
|
+
if (!t.isTSPropertySignature(member)) continue;
|
|
347
|
+
const key = getObjectKey(member.key);
|
|
348
|
+
if (!key) continue;
|
|
349
|
+
result[key] = extractTsProperty(member);
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
function extractTsProperty(node) {
|
|
354
|
+
var _node$typeAnnotation;
|
|
355
|
+
const prop = { required: !node.optional };
|
|
356
|
+
const annotation = (_node$typeAnnotation = node.typeAnnotation) === null || _node$typeAnnotation === void 0 ? void 0 : _node$typeAnnotation.typeAnnotation;
|
|
357
|
+
if (annotation) {
|
|
358
|
+
const inferred = inferType(annotation);
|
|
359
|
+
Object.assign(prop, inferred);
|
|
360
|
+
}
|
|
361
|
+
const description = getLeadingDescription(node);
|
|
362
|
+
if (description) prop.description = description;
|
|
363
|
+
return prop;
|
|
364
|
+
}
|
|
365
|
+
function inferType(node) {
|
|
366
|
+
if (t.isTSStringKeyword(node)) return { type: "string" };
|
|
367
|
+
if (t.isTSNumberKeyword(node)) return { type: "number" };
|
|
368
|
+
if (t.isTSBooleanKeyword(node)) return { type: "boolean" };
|
|
369
|
+
if (t.isTSArrayType(node)) return { type: "array" };
|
|
370
|
+
if (t.isTSTypeLiteral(node)) return { type: "object" };
|
|
371
|
+
if (t.isTSUnionType(node)) {
|
|
372
|
+
const values = [];
|
|
373
|
+
let allStringLiteral = true;
|
|
374
|
+
for (const type of node.types) if (t.isTSLiteralType(type) && t.isStringLiteral(type.literal)) values.push(type.literal.value);
|
|
375
|
+
else allStringLiteral = false;
|
|
376
|
+
if (allStringLiteral && values.length > 0) return {
|
|
377
|
+
type: "string",
|
|
378
|
+
values
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
return { type: "unknown" };
|
|
382
|
+
}
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/typeof.js
|
|
385
|
+
function _typeof(o) {
|
|
386
|
+
"@babel/helpers - typeof";
|
|
387
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
388
|
+
return typeof o;
|
|
389
|
+
} : function(o) {
|
|
390
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
391
|
+
}, _typeof(o);
|
|
392
|
+
}
|
|
393
|
+
//#endregion
|
|
394
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPrimitive.js
|
|
395
|
+
function toPrimitive(t, r) {
|
|
396
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
397
|
+
var e = t[Symbol.toPrimitive];
|
|
398
|
+
if (void 0 !== e) {
|
|
399
|
+
var i = e.call(t, r || "default");
|
|
400
|
+
if ("object" != _typeof(i)) return i;
|
|
401
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
402
|
+
}
|
|
403
|
+
return ("string" === r ? String : Number)(t);
|
|
404
|
+
}
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPropertyKey.js
|
|
407
|
+
function toPropertyKey(t) {
|
|
408
|
+
var i = toPrimitive(t, "string");
|
|
409
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
410
|
+
}
|
|
411
|
+
//#endregion
|
|
412
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/defineProperty.js
|
|
413
|
+
function _defineProperty(e, r, t) {
|
|
414
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
415
|
+
value: t,
|
|
416
|
+
enumerable: !0,
|
|
417
|
+
configurable: !0,
|
|
418
|
+
writable: !0
|
|
419
|
+
}) : e[r] = t, e;
|
|
420
|
+
}
|
|
421
|
+
//#endregion
|
|
422
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/objectSpread2.js
|
|
423
|
+
function ownKeys(e, r) {
|
|
424
|
+
var t = Object.keys(e);
|
|
425
|
+
if (Object.getOwnPropertySymbols) {
|
|
426
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
427
|
+
r && (o = o.filter(function(r) {
|
|
428
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
429
|
+
})), t.push.apply(t, o);
|
|
430
|
+
}
|
|
431
|
+
return t;
|
|
432
|
+
}
|
|
433
|
+
function _objectSpread2(e) {
|
|
434
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
435
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
436
|
+
r % 2 ? ownKeys(Object(t), !0).forEach(function(r) {
|
|
437
|
+
_defineProperty(e, r, t[r]);
|
|
438
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) {
|
|
439
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
return e;
|
|
443
|
+
}
|
|
444
|
+
//#endregion
|
|
445
|
+
//#region packages/web-c/component-analyzer/src/merge.ts
|
|
446
|
+
function buildComponentRecord(options) {
|
|
447
|
+
const { file, call, runtimeProps, typeProps, setupMeta, inlineMeta } = options;
|
|
448
|
+
const props = mergeProps(runtimeProps, typeProps, inlineMeta.props);
|
|
449
|
+
const events = mergeEvents(setupMeta.events, inlineMeta.events);
|
|
450
|
+
const slots = mergeSlots(setupMeta.slots, inlineMeta.slots);
|
|
451
|
+
const cssParts = unique([...setupMeta.cssParts, ...toStringArray(inlineMeta.cssParts)]);
|
|
452
|
+
const cssVars = unique(toStringArray(inlineMeta.cssVars));
|
|
453
|
+
const hostAttributes = unique(setupMeta.hostAttributes);
|
|
454
|
+
return {
|
|
455
|
+
tag: call.tag,
|
|
456
|
+
name: call.name,
|
|
457
|
+
exportName: call.exportName,
|
|
458
|
+
source: file,
|
|
459
|
+
props,
|
|
460
|
+
events,
|
|
461
|
+
slots,
|
|
462
|
+
hostAttributes,
|
|
463
|
+
cssParts,
|
|
464
|
+
cssVars,
|
|
465
|
+
description: typeof inlineMeta.description === "string" ? inlineMeta.description : void 0,
|
|
466
|
+
meta: stripKnownMetaFields(inlineMeta)
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
function mergeProps(runtimeProps, typeProps, metaProps) {
|
|
470
|
+
const names = unique([
|
|
471
|
+
...Object.keys(runtimeProps),
|
|
472
|
+
...Object.keys(typeProps),
|
|
473
|
+
...Object.keys(metaProps !== null && metaProps !== void 0 ? metaProps : {})
|
|
474
|
+
]);
|
|
475
|
+
const result = {};
|
|
476
|
+
for (const name of names) {
|
|
477
|
+
var _typeProps$name, _runtimeProps$name, _metaProps$name, _ref, _rp$type, _tp$description, _rp$default, _rp$reflect, _rp$attr;
|
|
478
|
+
const tp = (_typeProps$name = typeProps[name]) !== null && _typeProps$name !== void 0 ? _typeProps$name : {};
|
|
479
|
+
const rp = (_runtimeProps$name = runtimeProps[name]) !== null && _runtimeProps$name !== void 0 ? _runtimeProps$name : {};
|
|
480
|
+
const mp = (_metaProps$name = metaProps === null || metaProps === void 0 ? void 0 : metaProps[name]) !== null && _metaProps$name !== void 0 ? _metaProps$name : {};
|
|
481
|
+
result[name] = {
|
|
482
|
+
type: (_ref = (_rp$type = rp.type) !== null && _rp$type !== void 0 ? _rp$type : tp.type) !== null && _ref !== void 0 ? _ref : "unknown",
|
|
483
|
+
required: tp.required,
|
|
484
|
+
values: tp.values,
|
|
485
|
+
description: (_tp$description = tp.description) !== null && _tp$description !== void 0 ? _tp$description : mp.description,
|
|
486
|
+
default: (_rp$default = rp.default) !== null && _rp$default !== void 0 ? _rp$default : mp.default,
|
|
487
|
+
reflect: (_rp$reflect = rp.reflect) !== null && _rp$reflect !== void 0 ? _rp$reflect : mp.reflect,
|
|
488
|
+
attr: (_rp$attr = rp.attr) !== null && _rp$attr !== void 0 ? _rp$attr : mp.attr
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
return result;
|
|
492
|
+
}
|
|
493
|
+
function mergeEvents(inferred, explicit) {
|
|
494
|
+
return _objectSpread2(_objectSpread2({}, inferred), explicit !== null && explicit !== void 0 ? explicit : {});
|
|
495
|
+
}
|
|
496
|
+
function mergeSlots(inferred, explicit) {
|
|
497
|
+
return _objectSpread2(_objectSpread2({}, inferred), explicit !== null && explicit !== void 0 ? explicit : {});
|
|
498
|
+
}
|
|
499
|
+
function toStringArray(value) {
|
|
500
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
501
|
+
}
|
|
502
|
+
function unique(values) {
|
|
503
|
+
return Array.from(new Set(values)).sort();
|
|
504
|
+
}
|
|
505
|
+
function stripKnownMetaFields(meta) {
|
|
506
|
+
const rest = _objectSpread2({}, meta);
|
|
507
|
+
delete rest.description;
|
|
508
|
+
delete rest.props;
|
|
509
|
+
delete rest.events;
|
|
510
|
+
delete rest.slots;
|
|
511
|
+
delete rest.cssVars;
|
|
512
|
+
delete rest.cssParts;
|
|
513
|
+
return Object.keys(rest).length ? rest : void 0;
|
|
514
|
+
}
|
|
515
|
+
//#endregion
|
|
516
|
+
//#region packages/web-c/component-analyzer/src/analyzeFile.ts
|
|
517
|
+
function analyzeFile(options) {
|
|
518
|
+
const { file, code } = options;
|
|
519
|
+
const diagnostics = [];
|
|
520
|
+
const components = [];
|
|
521
|
+
try {
|
|
522
|
+
const ast = parseSource(code, file);
|
|
523
|
+
const calls = extractDefineElementCalls(ast);
|
|
524
|
+
const localPropTypes = collectLocalPropTypes(ast);
|
|
525
|
+
for (const call of calls) {
|
|
526
|
+
var _localPropTypes$get;
|
|
527
|
+
const runtimeProps = extractRuntimeProps(call.options);
|
|
528
|
+
const typeProps = call.propsTypeName ? (_localPropTypes$get = localPropTypes.get(call.propsTypeName)) !== null && _localPropTypes$get !== void 0 ? _localPropTypes$get : {} : {};
|
|
529
|
+
if (call.propsTypeName && !localPropTypes.has(call.propsTypeName) && !isGlobalUtilityType(call.propsTypeName)) diagnostics.push({
|
|
530
|
+
level: "warning",
|
|
531
|
+
file,
|
|
532
|
+
message: `Cannot resolve local props type "${call.propsTypeName}".`
|
|
533
|
+
});
|
|
534
|
+
const setupMeta = extractSetupMeta(call.setup);
|
|
535
|
+
const inlineMeta = extractInlineMeta(call.options);
|
|
536
|
+
components.push(buildComponentRecord({
|
|
537
|
+
file,
|
|
538
|
+
call,
|
|
539
|
+
runtimeProps,
|
|
540
|
+
typeProps,
|
|
541
|
+
setupMeta,
|
|
542
|
+
inlineMeta
|
|
543
|
+
}));
|
|
544
|
+
}
|
|
545
|
+
} catch (error) {
|
|
546
|
+
diagnostics.push({
|
|
547
|
+
level: "error",
|
|
548
|
+
file,
|
|
549
|
+
message: error instanceof Error ? error.message : String(error)
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
return {
|
|
553
|
+
file,
|
|
554
|
+
components,
|
|
555
|
+
diagnostics
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
function isGlobalUtilityType(name) {
|
|
559
|
+
return GLOBAL_UTILITY_TYPES.has(name);
|
|
560
|
+
}
|
|
561
|
+
const GLOBAL_UTILITY_TYPES = new Set([
|
|
562
|
+
"Awaited",
|
|
563
|
+
"ConstructorParameters",
|
|
564
|
+
"Exclude",
|
|
565
|
+
"Extract",
|
|
566
|
+
"InstanceType",
|
|
567
|
+
"NonNullable",
|
|
568
|
+
"Omit",
|
|
569
|
+
"Parameters",
|
|
570
|
+
"Partial",
|
|
571
|
+
"Pick",
|
|
572
|
+
"Readonly",
|
|
573
|
+
"Record",
|
|
574
|
+
"Required",
|
|
575
|
+
"ReturnType",
|
|
576
|
+
"ThisParameterType",
|
|
577
|
+
"ThisType",
|
|
578
|
+
"Uppercase",
|
|
579
|
+
"Lowercase",
|
|
580
|
+
"Capitalize",
|
|
581
|
+
"Uncapitalize"
|
|
582
|
+
]);
|
|
583
|
+
//#endregion
|
|
584
|
+
//#region \0@oxc-project+runtime@0.133.0/helpers/esm/asyncToGenerator.js
|
|
585
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
586
|
+
try {
|
|
587
|
+
var i = n[a](c), u = i.value;
|
|
588
|
+
} catch (n) {
|
|
589
|
+
e(n);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
i.done ? t(u) : Promise.resolve(u).then(r, o);
|
|
593
|
+
}
|
|
594
|
+
function _asyncToGenerator(n) {
|
|
595
|
+
return function() {
|
|
596
|
+
var t = this, e = arguments;
|
|
597
|
+
return new Promise(function(r, o) {
|
|
598
|
+
var a = n.apply(t, e);
|
|
599
|
+
function _next(n) {
|
|
600
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
|
|
601
|
+
}
|
|
602
|
+
function _throw(n) {
|
|
603
|
+
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
|
|
604
|
+
}
|
|
605
|
+
_next(void 0);
|
|
606
|
+
});
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
//#endregion
|
|
610
|
+
//#region packages/web-c/component-analyzer/src/analyzeComponents.ts
|
|
611
|
+
function analyzeComponents(_x) {
|
|
612
|
+
return _analyzeComponents.apply(this, arguments);
|
|
613
|
+
}
|
|
614
|
+
function _analyzeComponents() {
|
|
615
|
+
_analyzeComponents = _asyncToGenerator(function* (options) {
|
|
616
|
+
var _options$root, _options$exclude;
|
|
617
|
+
const root = (_options$root = options.root) !== null && _options$root !== void 0 ? _options$root : process.cwd();
|
|
618
|
+
const files = yield fg(options.include, {
|
|
619
|
+
cwd: root,
|
|
620
|
+
absolute: true,
|
|
621
|
+
ignore: (_options$exclude = options.exclude) !== null && _options$exclude !== void 0 ? _options$exclude : ["node_modules/**", "**/dist/**"]
|
|
622
|
+
});
|
|
623
|
+
const components = [];
|
|
624
|
+
const diagnostics = [];
|
|
625
|
+
for (const file of files) {
|
|
626
|
+
const code = yield fs.readFile(file, "utf-8");
|
|
627
|
+
const result = analyzeFile({
|
|
628
|
+
file: normalizePath(path.relative(root, file)),
|
|
629
|
+
code
|
|
630
|
+
});
|
|
631
|
+
components.push(...result.components);
|
|
632
|
+
diagnostics.push(...result.diagnostics);
|
|
633
|
+
}
|
|
634
|
+
return {
|
|
635
|
+
manifest: {
|
|
636
|
+
version: 1,
|
|
637
|
+
components
|
|
638
|
+
},
|
|
639
|
+
diagnostics
|
|
640
|
+
};
|
|
641
|
+
});
|
|
642
|
+
return _analyzeComponents.apply(this, arguments);
|
|
643
|
+
}
|
|
644
|
+
function normalizePath(value) {
|
|
645
|
+
return value.split(path.sep).join("/");
|
|
646
|
+
}
|
|
647
|
+
//#endregion
|
|
648
|
+
export { analyzeComponents, analyzeFile };
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zeus-js/component-analyzer",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "Zeus component analyzer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"module": "dist/component-analyzer.esm-bundler.js",
|
|
8
|
+
"types": "dist/component-analyzer.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"index.js",
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/component-analyzer.d.ts",
|
|
16
|
+
"node": {
|
|
17
|
+
"production": "./dist/component-analyzer.cjs.prod.js",
|
|
18
|
+
"development": "./dist/component-analyzer.cjs.js",
|
|
19
|
+
"default": "./index.js"
|
|
20
|
+
},
|
|
21
|
+
"module": "./dist/component-analyzer.esm-bundler.js",
|
|
22
|
+
"import": "./dist/component-analyzer.esm-bundler.js",
|
|
23
|
+
"require": "./index.js"
|
|
24
|
+
},
|
|
25
|
+
"./*": "./*"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/baicie/zeus"
|
|
31
|
+
},
|
|
32
|
+
"buildOptions": {
|
|
33
|
+
"name": "ZeusComponentAnalyzer",
|
|
34
|
+
"formats": [
|
|
35
|
+
"esm-bundler",
|
|
36
|
+
"cjs"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@babel/parser": "^7.29.0",
|
|
41
|
+
"@babel/types": "^7.29.0",
|
|
42
|
+
"fast-glob": "^3.3.3"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"zeus",
|
|
46
|
+
"web-components",
|
|
47
|
+
"component-analyzer"
|
|
48
|
+
],
|
|
49
|
+
"author": "Baicie",
|
|
50
|
+
"license": "MIT"
|
|
51
|
+
}
|