@zeus-js/component-analyzer 0.1.0-beta.2 → 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* component-analyzer v0.1.0-beta.
|
|
2
|
+
* component-analyzer v0.1.0-beta.3
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -192,6 +192,14 @@ function extractInlineMeta(options) {
|
|
|
192
192
|
}
|
|
193
193
|
//#endregion
|
|
194
194
|
//#region packages/web-c/component-analyzer/src/extractProps.ts
|
|
195
|
+
function extractShadowOption(options) {
|
|
196
|
+
if (!options) return {};
|
|
197
|
+
const shadowNode = getObjectProperty(options, "shadow");
|
|
198
|
+
if (!shadowNode) return {};
|
|
199
|
+
const value = staticValue(shadowNode);
|
|
200
|
+
if (typeof value !== "boolean") return {};
|
|
201
|
+
return { shadow: value };
|
|
202
|
+
}
|
|
195
203
|
function extractRuntimeProps(options) {
|
|
196
204
|
if (!options) return {};
|
|
197
205
|
const propsNode = getObjectProperty(options, "props");
|
|
@@ -205,6 +213,76 @@ function extractRuntimeProps(options) {
|
|
|
205
213
|
}
|
|
206
214
|
return props;
|
|
207
215
|
}
|
|
216
|
+
function validateRuntimePropsDefinition(options, optionsArgument) {
|
|
217
|
+
const messages = [];
|
|
218
|
+
if (optionsArgument && !_babel_types.isObjectExpression(optionsArgument)) {
|
|
219
|
+
messages.push("defineElement() options must be an inline object literal so component metadata can be analyzed.");
|
|
220
|
+
return messages;
|
|
221
|
+
}
|
|
222
|
+
if (!options) return messages;
|
|
223
|
+
for (const member of options.properties) if (!_babel_types.isObjectProperty(member) || member.computed) messages.push("defineElement() options cannot contain spreads, methods, or computed keys in component output builds.");
|
|
224
|
+
const propsNode = getObjectProperty(options, "props");
|
|
225
|
+
if (!propsNode) return messages;
|
|
226
|
+
if (!_babel_types.isObjectExpression(propsNode)) {
|
|
227
|
+
messages.push("defineElement() props must be an inline object literal in component output builds.");
|
|
228
|
+
return messages;
|
|
229
|
+
}
|
|
230
|
+
for (const member of propsNode.properties) {
|
|
231
|
+
if (!_babel_types.isObjectProperty(member) || member.computed) {
|
|
232
|
+
messages.push("defineElement() props cannot contain spreads, methods, or computed keys.");
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const propName = getObjectKey(member.key);
|
|
236
|
+
if (!propName) {
|
|
237
|
+
messages.push("defineElement() contains a prop with an unsupported key.");
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (_babel_types.isIdentifier(member.value)) {
|
|
241
|
+
if (!isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" must use String, Number, Boolean, Object, Array, or an inline prop options object.`);
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (!_babel_types.isObjectExpression(member.value)) {
|
|
245
|
+
messages.push(`Prop "${propName}" must use an inline prop options object.`);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
validatePropOptions(propName, member.value, messages);
|
|
249
|
+
}
|
|
250
|
+
return messages;
|
|
251
|
+
}
|
|
252
|
+
function validatePropOptions(propName, options, messages) {
|
|
253
|
+
for (const member of options.properties) {
|
|
254
|
+
if (!_babel_types.isObjectProperty(member) || member.computed) {
|
|
255
|
+
messages.push(`Prop "${propName}" options cannot contain spreads, methods, or computed keys.`);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const optionName = getObjectKey(member.key);
|
|
259
|
+
if (!optionName) {
|
|
260
|
+
messages.push(`Prop "${propName}" contains an unsupported option key.`);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (optionName === "type") {
|
|
264
|
+
if (!_babel_types.isIdentifier(member.value) || !isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" type must be String, Number, Boolean, Object, or Array.`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (optionName === "attr") {
|
|
268
|
+
const value = staticValue(member.value);
|
|
269
|
+
if (value === void 0 && !isExplicitUndefined(member.value)) {
|
|
270
|
+
messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (value !== void 0 && value !== false && typeof value !== "string") messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
if (optionName === "reflect") {
|
|
277
|
+
const value = staticValue(member.value);
|
|
278
|
+
if (value === void 0 && !isExplicitUndefined(member.value)) {
|
|
279
|
+
messages.push(`Prop "${propName}" reflect must be a static boolean.`);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (value !== void 0 && typeof value !== "boolean") messages.push(`Prop "${propName}" reflect must be a static boolean.`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
208
286
|
function extractRuntimeProp(node) {
|
|
209
287
|
if (_babel_types.isIdentifier(node)) return { type: typeFromConstructorName(node.name) };
|
|
210
288
|
if (_babel_types.isObjectExpression(node)) {
|
|
@@ -228,6 +306,12 @@ function extractRuntimeProp(node) {
|
|
|
228
306
|
}
|
|
229
307
|
return { type: "unknown" };
|
|
230
308
|
}
|
|
309
|
+
function isPropConstructorName(name) {
|
|
310
|
+
return name === "String" || name === "Number" || name === "Boolean" || name === "Object" || name === "Array";
|
|
311
|
+
}
|
|
312
|
+
function isExplicitUndefined(node) {
|
|
313
|
+
return _babel_types.isIdentifier(node) && node.name === "undefined";
|
|
314
|
+
}
|
|
231
315
|
function typeFromConstructorName(name) {
|
|
232
316
|
switch (name) {
|
|
233
317
|
case "String": return "string";
|
|
@@ -413,26 +497,32 @@ function inferType(node) {
|
|
|
413
497
|
//#endregion
|
|
414
498
|
//#region packages/web-c/component-analyzer/src/merge.ts
|
|
415
499
|
function buildComponentRecord(options) {
|
|
416
|
-
const { file, call, runtimeProps, typeProps, setupMeta, inlineMeta } = options;
|
|
500
|
+
const { file, call, runtimeProps, runtimePropsDiagnostics, typeProps, setupMeta, inlineMeta, shadow } = options;
|
|
417
501
|
const props = mergeProps(runtimeProps, typeProps, inlineMeta.props);
|
|
418
502
|
const events = mergeEvents(setupMeta.events, inlineMeta.events);
|
|
419
503
|
const slots = mergeSlots(setupMeta.slots, inlineMeta.slots);
|
|
420
504
|
const cssParts = unique([...setupMeta.cssParts, ...toStringArray(inlineMeta.cssParts)]);
|
|
421
505
|
const cssVars = unique(toStringArray(inlineMeta.cssVars));
|
|
422
506
|
const hostAttributes = unique(setupMeta.hostAttributes);
|
|
507
|
+
const restMeta = stripKnownMetaFields(inlineMeta);
|
|
423
508
|
return {
|
|
424
509
|
tag: call.tag,
|
|
425
510
|
name: call.name,
|
|
426
511
|
exportName: call.exportName,
|
|
427
512
|
source: file,
|
|
428
513
|
props,
|
|
514
|
+
runtimeProps,
|
|
515
|
+
runtimePropsDiagnostics: (runtimePropsDiagnostics === null || runtimePropsDiagnostics === void 0 ? void 0 : runtimePropsDiagnostics.length) ? runtimePropsDiagnostics : void 0,
|
|
429
516
|
events,
|
|
430
517
|
slots,
|
|
431
518
|
hostAttributes,
|
|
432
519
|
cssParts,
|
|
433
520
|
cssVars,
|
|
434
521
|
description: typeof inlineMeta.description === "string" ? inlineMeta.description : void 0,
|
|
435
|
-
meta:
|
|
522
|
+
meta: shadow !== void 0 || restMeta ? {
|
|
523
|
+
...restMeta,
|
|
524
|
+
shadow
|
|
525
|
+
} : void 0
|
|
436
526
|
};
|
|
437
527
|
}
|
|
438
528
|
function mergeProps(runtimeProps, typeProps, metaProps) {
|
|
@@ -485,6 +575,7 @@ function stripKnownMetaFields(meta) {
|
|
|
485
575
|
delete rest.slots;
|
|
486
576
|
delete rest.cssVars;
|
|
487
577
|
delete rest.cssParts;
|
|
578
|
+
delete rest.shadow;
|
|
488
579
|
return Object.keys(rest).length ? rest : void 0;
|
|
489
580
|
}
|
|
490
581
|
//#endregion
|
|
@@ -498,8 +589,15 @@ function analyzeFile(options) {
|
|
|
498
589
|
const calls = extractDefineElementCalls(ast);
|
|
499
590
|
const localPropTypes = collectLocalPropTypes(ast);
|
|
500
591
|
for (const call of calls) {
|
|
501
|
-
var _localPropTypes$get;
|
|
592
|
+
var _localPropTypes$get, _shadowOption$shadow;
|
|
593
|
+
const runtimePropsDiagnostics = validateRuntimePropsDefinition(call.options, call.call.arguments[1]);
|
|
594
|
+
for (const message of runtimePropsDiagnostics) diagnostics.push({
|
|
595
|
+
level: "warning",
|
|
596
|
+
file,
|
|
597
|
+
message: `<${call.tag}> ${message}`
|
|
598
|
+
});
|
|
502
599
|
const runtimeProps = extractRuntimeProps(call.options);
|
|
600
|
+
const shadowOption = extractShadowOption(call.options);
|
|
503
601
|
const typeProps = call.propsTypeName ? (_localPropTypes$get = localPropTypes.get(call.propsTypeName)) !== null && _localPropTypes$get !== void 0 ? _localPropTypes$get : {} : {};
|
|
504
602
|
if (call.propsTypeName && !localPropTypes.has(call.propsTypeName) && !isGlobalUtilityType(call.propsTypeName)) diagnostics.push({
|
|
505
603
|
level: "warning",
|
|
@@ -512,9 +610,11 @@ function analyzeFile(options) {
|
|
|
512
610
|
file,
|
|
513
611
|
call,
|
|
514
612
|
runtimeProps,
|
|
613
|
+
runtimePropsDiagnostics,
|
|
515
614
|
typeProps,
|
|
516
615
|
setupMeta,
|
|
517
|
-
inlineMeta
|
|
616
|
+
inlineMeta,
|
|
617
|
+
shadow: (_shadowOption$shadow = shadowOption.shadow) !== null && _shadowOption$shadow !== void 0 ? _shadowOption$shadow : typeof inlineMeta.shadow === "boolean" ? inlineMeta.shadow : void 0
|
|
518
618
|
}));
|
|
519
619
|
}
|
|
520
620
|
} catch (error) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* component-analyzer v0.1.0-beta.
|
|
2
|
+
* component-analyzer v0.1.0-beta.3
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -192,6 +192,14 @@ function extractInlineMeta(options) {
|
|
|
192
192
|
}
|
|
193
193
|
//#endregion
|
|
194
194
|
//#region packages/web-c/component-analyzer/src/extractProps.ts
|
|
195
|
+
function extractShadowOption(options) {
|
|
196
|
+
if (!options) return {};
|
|
197
|
+
const shadowNode = getObjectProperty(options, "shadow");
|
|
198
|
+
if (!shadowNode) return {};
|
|
199
|
+
const value = staticValue(shadowNode);
|
|
200
|
+
if (typeof value !== "boolean") return {};
|
|
201
|
+
return { shadow: value };
|
|
202
|
+
}
|
|
195
203
|
function extractRuntimeProps(options) {
|
|
196
204
|
if (!options) return {};
|
|
197
205
|
const propsNode = getObjectProperty(options, "props");
|
|
@@ -205,6 +213,76 @@ function extractRuntimeProps(options) {
|
|
|
205
213
|
}
|
|
206
214
|
return props;
|
|
207
215
|
}
|
|
216
|
+
function validateRuntimePropsDefinition(options, optionsArgument) {
|
|
217
|
+
const messages = [];
|
|
218
|
+
if (optionsArgument && !_babel_types.isObjectExpression(optionsArgument)) {
|
|
219
|
+
messages.push("defineElement() options must be an inline object literal so component metadata can be analyzed.");
|
|
220
|
+
return messages;
|
|
221
|
+
}
|
|
222
|
+
if (!options) return messages;
|
|
223
|
+
for (const member of options.properties) if (!_babel_types.isObjectProperty(member) || member.computed) messages.push("defineElement() options cannot contain spreads, methods, or computed keys in component output builds.");
|
|
224
|
+
const propsNode = getObjectProperty(options, "props");
|
|
225
|
+
if (!propsNode) return messages;
|
|
226
|
+
if (!_babel_types.isObjectExpression(propsNode)) {
|
|
227
|
+
messages.push("defineElement() props must be an inline object literal in component output builds.");
|
|
228
|
+
return messages;
|
|
229
|
+
}
|
|
230
|
+
for (const member of propsNode.properties) {
|
|
231
|
+
if (!_babel_types.isObjectProperty(member) || member.computed) {
|
|
232
|
+
messages.push("defineElement() props cannot contain spreads, methods, or computed keys.");
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const propName = getObjectKey(member.key);
|
|
236
|
+
if (!propName) {
|
|
237
|
+
messages.push("defineElement() contains a prop with an unsupported key.");
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (_babel_types.isIdentifier(member.value)) {
|
|
241
|
+
if (!isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" must use String, Number, Boolean, Object, Array, or an inline prop options object.`);
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (!_babel_types.isObjectExpression(member.value)) {
|
|
245
|
+
messages.push(`Prop "${propName}" must use an inline prop options object.`);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
validatePropOptions(propName, member.value, messages);
|
|
249
|
+
}
|
|
250
|
+
return messages;
|
|
251
|
+
}
|
|
252
|
+
function validatePropOptions(propName, options, messages) {
|
|
253
|
+
for (const member of options.properties) {
|
|
254
|
+
if (!_babel_types.isObjectProperty(member) || member.computed) {
|
|
255
|
+
messages.push(`Prop "${propName}" options cannot contain spreads, methods, or computed keys.`);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const optionName = getObjectKey(member.key);
|
|
259
|
+
if (!optionName) {
|
|
260
|
+
messages.push(`Prop "${propName}" contains an unsupported option key.`);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (optionName === "type") {
|
|
264
|
+
if (!_babel_types.isIdentifier(member.value) || !isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" type must be String, Number, Boolean, Object, or Array.`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (optionName === "attr") {
|
|
268
|
+
const value = staticValue(member.value);
|
|
269
|
+
if (value === void 0 && !isExplicitUndefined(member.value)) {
|
|
270
|
+
messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (value !== void 0 && value !== false && typeof value !== "string") messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
if (optionName === "reflect") {
|
|
277
|
+
const value = staticValue(member.value);
|
|
278
|
+
if (value === void 0 && !isExplicitUndefined(member.value)) {
|
|
279
|
+
messages.push(`Prop "${propName}" reflect must be a static boolean.`);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (value !== void 0 && typeof value !== "boolean") messages.push(`Prop "${propName}" reflect must be a static boolean.`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
208
286
|
function extractRuntimeProp(node) {
|
|
209
287
|
if (_babel_types.isIdentifier(node)) return { type: typeFromConstructorName(node.name) };
|
|
210
288
|
if (_babel_types.isObjectExpression(node)) {
|
|
@@ -228,6 +306,12 @@ function extractRuntimeProp(node) {
|
|
|
228
306
|
}
|
|
229
307
|
return { type: "unknown" };
|
|
230
308
|
}
|
|
309
|
+
function isPropConstructorName(name) {
|
|
310
|
+
return name === "String" || name === "Number" || name === "Boolean" || name === "Object" || name === "Array";
|
|
311
|
+
}
|
|
312
|
+
function isExplicitUndefined(node) {
|
|
313
|
+
return _babel_types.isIdentifier(node) && node.name === "undefined";
|
|
314
|
+
}
|
|
231
315
|
function typeFromConstructorName(name) {
|
|
232
316
|
switch (name) {
|
|
233
317
|
case "String": return "string";
|
|
@@ -413,26 +497,32 @@ function inferType(node) {
|
|
|
413
497
|
//#endregion
|
|
414
498
|
//#region packages/web-c/component-analyzer/src/merge.ts
|
|
415
499
|
function buildComponentRecord(options) {
|
|
416
|
-
const { file, call, runtimeProps, typeProps, setupMeta, inlineMeta } = options;
|
|
500
|
+
const { file, call, runtimeProps, runtimePropsDiagnostics, typeProps, setupMeta, inlineMeta, shadow } = options;
|
|
417
501
|
const props = mergeProps(runtimeProps, typeProps, inlineMeta.props);
|
|
418
502
|
const events = mergeEvents(setupMeta.events, inlineMeta.events);
|
|
419
503
|
const slots = mergeSlots(setupMeta.slots, inlineMeta.slots);
|
|
420
504
|
const cssParts = unique([...setupMeta.cssParts, ...toStringArray(inlineMeta.cssParts)]);
|
|
421
505
|
const cssVars = unique(toStringArray(inlineMeta.cssVars));
|
|
422
506
|
const hostAttributes = unique(setupMeta.hostAttributes);
|
|
507
|
+
const restMeta = stripKnownMetaFields(inlineMeta);
|
|
423
508
|
return {
|
|
424
509
|
tag: call.tag,
|
|
425
510
|
name: call.name,
|
|
426
511
|
exportName: call.exportName,
|
|
427
512
|
source: file,
|
|
428
513
|
props,
|
|
514
|
+
runtimeProps,
|
|
515
|
+
runtimePropsDiagnostics: (runtimePropsDiagnostics === null || runtimePropsDiagnostics === void 0 ? void 0 : runtimePropsDiagnostics.length) ? runtimePropsDiagnostics : void 0,
|
|
429
516
|
events,
|
|
430
517
|
slots,
|
|
431
518
|
hostAttributes,
|
|
432
519
|
cssParts,
|
|
433
520
|
cssVars,
|
|
434
521
|
description: typeof inlineMeta.description === "string" ? inlineMeta.description : void 0,
|
|
435
|
-
meta:
|
|
522
|
+
meta: shadow !== void 0 || restMeta ? {
|
|
523
|
+
...restMeta,
|
|
524
|
+
shadow
|
|
525
|
+
} : void 0
|
|
436
526
|
};
|
|
437
527
|
}
|
|
438
528
|
function mergeProps(runtimeProps, typeProps, metaProps) {
|
|
@@ -485,6 +575,7 @@ function stripKnownMetaFields(meta) {
|
|
|
485
575
|
delete rest.slots;
|
|
486
576
|
delete rest.cssVars;
|
|
487
577
|
delete rest.cssParts;
|
|
578
|
+
delete rest.shadow;
|
|
488
579
|
return Object.keys(rest).length ? rest : void 0;
|
|
489
580
|
}
|
|
490
581
|
//#endregion
|
|
@@ -498,8 +589,15 @@ function analyzeFile(options) {
|
|
|
498
589
|
const calls = extractDefineElementCalls(ast);
|
|
499
590
|
const localPropTypes = collectLocalPropTypes(ast);
|
|
500
591
|
for (const call of calls) {
|
|
501
|
-
var _localPropTypes$get;
|
|
592
|
+
var _localPropTypes$get, _shadowOption$shadow;
|
|
593
|
+
const runtimePropsDiagnostics = validateRuntimePropsDefinition(call.options, call.call.arguments[1]);
|
|
594
|
+
for (const message of runtimePropsDiagnostics) diagnostics.push({
|
|
595
|
+
level: "warning",
|
|
596
|
+
file,
|
|
597
|
+
message: `<${call.tag}> ${message}`
|
|
598
|
+
});
|
|
502
599
|
const runtimeProps = extractRuntimeProps(call.options);
|
|
600
|
+
const shadowOption = extractShadowOption(call.options);
|
|
503
601
|
const typeProps = call.propsTypeName ? (_localPropTypes$get = localPropTypes.get(call.propsTypeName)) !== null && _localPropTypes$get !== void 0 ? _localPropTypes$get : {} : {};
|
|
504
602
|
if (call.propsTypeName && !localPropTypes.has(call.propsTypeName) && !isGlobalUtilityType(call.propsTypeName)) diagnostics.push({
|
|
505
603
|
level: "warning",
|
|
@@ -512,9 +610,11 @@ function analyzeFile(options) {
|
|
|
512
610
|
file,
|
|
513
611
|
call,
|
|
514
612
|
runtimeProps,
|
|
613
|
+
runtimePropsDiagnostics,
|
|
515
614
|
typeProps,
|
|
516
615
|
setupMeta,
|
|
517
|
-
inlineMeta
|
|
616
|
+
inlineMeta,
|
|
617
|
+
shadow: (_shadowOption$shadow = shadowOption.shadow) !== null && _shadowOption$shadow !== void 0 ? _shadowOption$shadow : typeof inlineMeta.shadow === "boolean" ? inlineMeta.shadow : void 0
|
|
518
618
|
}));
|
|
519
619
|
}
|
|
520
620
|
} catch (error) {
|
|
@@ -8,14 +8,30 @@ export interface ComponentRecord {
|
|
|
8
8
|
name: string;
|
|
9
9
|
exportName: string;
|
|
10
10
|
source: string;
|
|
11
|
+
/**
|
|
12
|
+
* Public props merged from runtime definitions, TypeScript types and metadata.
|
|
13
|
+
* Used by declarations, documentation and framework wrapper types.
|
|
14
|
+
*/
|
|
11
15
|
props: Record<string, ComponentProp>;
|
|
16
|
+
/**
|
|
17
|
+
* Exact runtime props extracted from defineElement(options.props).
|
|
18
|
+
* Lazy Proxy Elements must only consume this field.
|
|
19
|
+
*/
|
|
20
|
+
runtimeProps?: Record<string, ComponentProp>;
|
|
21
|
+
/**
|
|
22
|
+
* Validation messages explaining why runtime props could not be analyzed.
|
|
23
|
+
*/
|
|
24
|
+
runtimePropsDiagnostics?: string[];
|
|
12
25
|
events: Record<string, ComponentEvent>;
|
|
13
26
|
slots: Record<string, ComponentSlot>;
|
|
14
27
|
hostAttributes: string[];
|
|
15
28
|
cssParts: string[];
|
|
16
29
|
cssVars: string[];
|
|
17
30
|
description?: string;
|
|
18
|
-
meta?:
|
|
31
|
+
meta?: {
|
|
32
|
+
shadow?: boolean;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
};
|
|
19
35
|
}
|
|
20
36
|
export interface ComponentProp {
|
|
21
37
|
type: ComponentPropType;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* component-analyzer v0.1.0-beta.
|
|
2
|
+
* component-analyzer v0.1.0-beta.3
|
|
3
3
|
* (c) 2026 baicie
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
**/
|
|
@@ -162,6 +162,14 @@ function extractInlineMeta(options) {
|
|
|
162
162
|
}
|
|
163
163
|
//#endregion
|
|
164
164
|
//#region packages/web-c/component-analyzer/src/extractProps.ts
|
|
165
|
+
function extractShadowOption(options) {
|
|
166
|
+
if (!options) return {};
|
|
167
|
+
const shadowNode = getObjectProperty(options, "shadow");
|
|
168
|
+
if (!shadowNode) return {};
|
|
169
|
+
const value = staticValue(shadowNode);
|
|
170
|
+
if (typeof value !== "boolean") return {};
|
|
171
|
+
return { shadow: value };
|
|
172
|
+
}
|
|
165
173
|
function extractRuntimeProps(options) {
|
|
166
174
|
if (!options) return {};
|
|
167
175
|
const propsNode = getObjectProperty(options, "props");
|
|
@@ -175,6 +183,76 @@ function extractRuntimeProps(options) {
|
|
|
175
183
|
}
|
|
176
184
|
return props;
|
|
177
185
|
}
|
|
186
|
+
function validateRuntimePropsDefinition(options, optionsArgument) {
|
|
187
|
+
const messages = [];
|
|
188
|
+
if (optionsArgument && !t.isObjectExpression(optionsArgument)) {
|
|
189
|
+
messages.push("defineElement() options must be an inline object literal so component metadata can be analyzed.");
|
|
190
|
+
return messages;
|
|
191
|
+
}
|
|
192
|
+
if (!options) return messages;
|
|
193
|
+
for (const member of options.properties) if (!t.isObjectProperty(member) || member.computed) messages.push("defineElement() options cannot contain spreads, methods, or computed keys in component output builds.");
|
|
194
|
+
const propsNode = getObjectProperty(options, "props");
|
|
195
|
+
if (!propsNode) return messages;
|
|
196
|
+
if (!t.isObjectExpression(propsNode)) {
|
|
197
|
+
messages.push("defineElement() props must be an inline object literal in component output builds.");
|
|
198
|
+
return messages;
|
|
199
|
+
}
|
|
200
|
+
for (const member of propsNode.properties) {
|
|
201
|
+
if (!t.isObjectProperty(member) || member.computed) {
|
|
202
|
+
messages.push("defineElement() props cannot contain spreads, methods, or computed keys.");
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const propName = getObjectKey(member.key);
|
|
206
|
+
if (!propName) {
|
|
207
|
+
messages.push("defineElement() contains a prop with an unsupported key.");
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (t.isIdentifier(member.value)) {
|
|
211
|
+
if (!isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" must use String, Number, Boolean, Object, Array, or an inline prop options object.`);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (!t.isObjectExpression(member.value)) {
|
|
215
|
+
messages.push(`Prop "${propName}" must use an inline prop options object.`);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
validatePropOptions(propName, member.value, messages);
|
|
219
|
+
}
|
|
220
|
+
return messages;
|
|
221
|
+
}
|
|
222
|
+
function validatePropOptions(propName, options, messages) {
|
|
223
|
+
for (const member of options.properties) {
|
|
224
|
+
if (!t.isObjectProperty(member) || member.computed) {
|
|
225
|
+
messages.push(`Prop "${propName}" options cannot contain spreads, methods, or computed keys.`);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const optionName = getObjectKey(member.key);
|
|
229
|
+
if (!optionName) {
|
|
230
|
+
messages.push(`Prop "${propName}" contains an unsupported option key.`);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (optionName === "type") {
|
|
234
|
+
if (!t.isIdentifier(member.value) || !isPropConstructorName(member.value.name)) messages.push(`Prop "${propName}" type must be String, Number, Boolean, Object, or Array.`);
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (optionName === "attr") {
|
|
238
|
+
const value = staticValue(member.value);
|
|
239
|
+
if (value === void 0 && !isExplicitUndefined(member.value)) {
|
|
240
|
+
messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (value !== void 0 && value !== false && typeof value !== "string") messages.push(`Prop "${propName}" attr must be a static string, false, or undefined.`);
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (optionName === "reflect") {
|
|
247
|
+
const value = staticValue(member.value);
|
|
248
|
+
if (value === void 0 && !isExplicitUndefined(member.value)) {
|
|
249
|
+
messages.push(`Prop "${propName}" reflect must be a static boolean.`);
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
if (value !== void 0 && typeof value !== "boolean") messages.push(`Prop "${propName}" reflect must be a static boolean.`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
178
256
|
function extractRuntimeProp(node) {
|
|
179
257
|
if (t.isIdentifier(node)) return { type: typeFromConstructorName(node.name) };
|
|
180
258
|
if (t.isObjectExpression(node)) {
|
|
@@ -198,6 +276,12 @@ function extractRuntimeProp(node) {
|
|
|
198
276
|
}
|
|
199
277
|
return { type: "unknown" };
|
|
200
278
|
}
|
|
279
|
+
function isPropConstructorName(name) {
|
|
280
|
+
return name === "String" || name === "Number" || name === "Boolean" || name === "Object" || name === "Array";
|
|
281
|
+
}
|
|
282
|
+
function isExplicitUndefined(node) {
|
|
283
|
+
return t.isIdentifier(node) && node.name === "undefined";
|
|
284
|
+
}
|
|
201
285
|
function typeFromConstructorName(name) {
|
|
202
286
|
switch (name) {
|
|
203
287
|
case "String": return "string";
|
|
@@ -381,7 +465,7 @@ function inferType(node) {
|
|
|
381
465
|
return { type: "unknown" };
|
|
382
466
|
}
|
|
383
467
|
//#endregion
|
|
384
|
-
//#region \0@oxc-project+runtime@0.
|
|
468
|
+
//#region \0@oxc-project+runtime@0.134.0/helpers/esm/typeof.js
|
|
385
469
|
function _typeof(o) {
|
|
386
470
|
"@babel/helpers - typeof";
|
|
387
471
|
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
@@ -391,7 +475,7 @@ function _typeof(o) {
|
|
|
391
475
|
}, _typeof(o);
|
|
392
476
|
}
|
|
393
477
|
//#endregion
|
|
394
|
-
//#region \0@oxc-project+runtime@0.
|
|
478
|
+
//#region \0@oxc-project+runtime@0.134.0/helpers/esm/toPrimitive.js
|
|
395
479
|
function toPrimitive(t, r) {
|
|
396
480
|
if ("object" != _typeof(t) || !t) return t;
|
|
397
481
|
var e = t[Symbol.toPrimitive];
|
|
@@ -403,13 +487,13 @@ function toPrimitive(t, r) {
|
|
|
403
487
|
return ("string" === r ? String : Number)(t);
|
|
404
488
|
}
|
|
405
489
|
//#endregion
|
|
406
|
-
//#region \0@oxc-project+runtime@0.
|
|
490
|
+
//#region \0@oxc-project+runtime@0.134.0/helpers/esm/toPropertyKey.js
|
|
407
491
|
function toPropertyKey(t) {
|
|
408
492
|
var i = toPrimitive(t, "string");
|
|
409
493
|
return "symbol" == _typeof(i) ? i : i + "";
|
|
410
494
|
}
|
|
411
495
|
//#endregion
|
|
412
|
-
//#region \0@oxc-project+runtime@0.
|
|
496
|
+
//#region \0@oxc-project+runtime@0.134.0/helpers/esm/defineProperty.js
|
|
413
497
|
function _defineProperty(e, r, t) {
|
|
414
498
|
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
415
499
|
value: t,
|
|
@@ -419,7 +503,7 @@ function _defineProperty(e, r, t) {
|
|
|
419
503
|
}) : e[r] = t, e;
|
|
420
504
|
}
|
|
421
505
|
//#endregion
|
|
422
|
-
//#region \0@oxc-project+runtime@0.
|
|
506
|
+
//#region \0@oxc-project+runtime@0.134.0/helpers/esm/objectSpread2.js
|
|
423
507
|
function ownKeys(e, r) {
|
|
424
508
|
var t = Object.keys(e);
|
|
425
509
|
if (Object.getOwnPropertySymbols) {
|
|
@@ -444,26 +528,29 @@ function _objectSpread2(e) {
|
|
|
444
528
|
//#endregion
|
|
445
529
|
//#region packages/web-c/component-analyzer/src/merge.ts
|
|
446
530
|
function buildComponentRecord(options) {
|
|
447
|
-
const { file, call, runtimeProps, typeProps, setupMeta, inlineMeta } = options;
|
|
531
|
+
const { file, call, runtimeProps, runtimePropsDiagnostics, typeProps, setupMeta, inlineMeta, shadow } = options;
|
|
448
532
|
const props = mergeProps(runtimeProps, typeProps, inlineMeta.props);
|
|
449
533
|
const events = mergeEvents(setupMeta.events, inlineMeta.events);
|
|
450
534
|
const slots = mergeSlots(setupMeta.slots, inlineMeta.slots);
|
|
451
535
|
const cssParts = unique([...setupMeta.cssParts, ...toStringArray(inlineMeta.cssParts)]);
|
|
452
536
|
const cssVars = unique(toStringArray(inlineMeta.cssVars));
|
|
453
537
|
const hostAttributes = unique(setupMeta.hostAttributes);
|
|
538
|
+
const restMeta = stripKnownMetaFields(inlineMeta);
|
|
454
539
|
return {
|
|
455
540
|
tag: call.tag,
|
|
456
541
|
name: call.name,
|
|
457
542
|
exportName: call.exportName,
|
|
458
543
|
source: file,
|
|
459
544
|
props,
|
|
545
|
+
runtimeProps,
|
|
546
|
+
runtimePropsDiagnostics: (runtimePropsDiagnostics === null || runtimePropsDiagnostics === void 0 ? void 0 : runtimePropsDiagnostics.length) ? runtimePropsDiagnostics : void 0,
|
|
460
547
|
events,
|
|
461
548
|
slots,
|
|
462
549
|
hostAttributes,
|
|
463
550
|
cssParts,
|
|
464
551
|
cssVars,
|
|
465
552
|
description: typeof inlineMeta.description === "string" ? inlineMeta.description : void 0,
|
|
466
|
-
meta:
|
|
553
|
+
meta: shadow !== void 0 || restMeta ? _objectSpread2(_objectSpread2({}, restMeta), {}, { shadow }) : void 0
|
|
467
554
|
};
|
|
468
555
|
}
|
|
469
556
|
function mergeProps(runtimeProps, typeProps, metaProps) {
|
|
@@ -510,6 +597,7 @@ function stripKnownMetaFields(meta) {
|
|
|
510
597
|
delete rest.slots;
|
|
511
598
|
delete rest.cssVars;
|
|
512
599
|
delete rest.cssParts;
|
|
600
|
+
delete rest.shadow;
|
|
513
601
|
return Object.keys(rest).length ? rest : void 0;
|
|
514
602
|
}
|
|
515
603
|
//#endregion
|
|
@@ -523,8 +611,15 @@ function analyzeFile(options) {
|
|
|
523
611
|
const calls = extractDefineElementCalls(ast);
|
|
524
612
|
const localPropTypes = collectLocalPropTypes(ast);
|
|
525
613
|
for (const call of calls) {
|
|
526
|
-
var _localPropTypes$get;
|
|
614
|
+
var _localPropTypes$get, _shadowOption$shadow;
|
|
615
|
+
const runtimePropsDiagnostics = validateRuntimePropsDefinition(call.options, call.call.arguments[1]);
|
|
616
|
+
for (const message of runtimePropsDiagnostics) diagnostics.push({
|
|
617
|
+
level: "warning",
|
|
618
|
+
file,
|
|
619
|
+
message: `<${call.tag}> ${message}`
|
|
620
|
+
});
|
|
527
621
|
const runtimeProps = extractRuntimeProps(call.options);
|
|
622
|
+
const shadowOption = extractShadowOption(call.options);
|
|
528
623
|
const typeProps = call.propsTypeName ? (_localPropTypes$get = localPropTypes.get(call.propsTypeName)) !== null && _localPropTypes$get !== void 0 ? _localPropTypes$get : {} : {};
|
|
529
624
|
if (call.propsTypeName && !localPropTypes.has(call.propsTypeName) && !isGlobalUtilityType(call.propsTypeName)) diagnostics.push({
|
|
530
625
|
level: "warning",
|
|
@@ -537,9 +632,11 @@ function analyzeFile(options) {
|
|
|
537
632
|
file,
|
|
538
633
|
call,
|
|
539
634
|
runtimeProps,
|
|
635
|
+
runtimePropsDiagnostics,
|
|
540
636
|
typeProps,
|
|
541
637
|
setupMeta,
|
|
542
|
-
inlineMeta
|
|
638
|
+
inlineMeta,
|
|
639
|
+
shadow: (_shadowOption$shadow = shadowOption.shadow) !== null && _shadowOption$shadow !== void 0 ? _shadowOption$shadow : typeof inlineMeta.shadow === "boolean" ? inlineMeta.shadow : void 0
|
|
543
640
|
}));
|
|
544
641
|
}
|
|
545
642
|
} catch (error) {
|
|
@@ -581,7 +678,7 @@ const GLOBAL_UTILITY_TYPES = new Set([
|
|
|
581
678
|
"Uncapitalize"
|
|
582
679
|
]);
|
|
583
680
|
//#endregion
|
|
584
|
-
//#region \0@oxc-project+runtime@0.
|
|
681
|
+
//#region \0@oxc-project+runtime@0.134.0/helpers/esm/asyncToGenerator.js
|
|
585
682
|
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
586
683
|
try {
|
|
587
684
|
var i = n[a](c), u = i.value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeus-js/component-analyzer",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"description": "Zeus component analyzer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
15
|
"types": "./dist/component-analyzer.d.ts",
|
|
16
|
+
"module": "./dist/component-analyzer.esm-bundler.js",
|
|
17
|
+
"import": "./dist/component-analyzer.esm-bundler.js",
|
|
18
|
+
"require": "./index.js",
|
|
16
19
|
"node": {
|
|
17
20
|
"production": "./dist/component-analyzer.cjs.prod.js",
|
|
18
21
|
"development": "./dist/component-analyzer.cjs.js",
|
|
19
22
|
"default": "./index.js"
|
|
20
|
-
}
|
|
21
|
-
"module": "./dist/component-analyzer.esm-bundler.js",
|
|
22
|
-
"import": "./dist/component-analyzer.esm-bundler.js",
|
|
23
|
-
"require": "./index.js"
|
|
23
|
+
}
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"sideEffects": false,
|