@sudosandwich/limps-headless 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +339 -0
- package/bin/limps-headless +2 -0
- package/dist/analysis/index.d.ts +6 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +6 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/ir/build-ir.d.ts +10 -0
- package/dist/analysis/ir/build-ir.d.ts.map +1 -0
- package/dist/analysis/ir/build-ir.js +102 -0
- package/dist/analysis/ir/build-ir.js.map +1 -0
- package/dist/analysis/ir/types.d.ts +44 -0
- package/dist/analysis/ir/types.d.ts.map +1 -0
- package/dist/analysis/ir/types.js +2 -0
- package/dist/analysis/ir/types.js.map +1 -0
- package/dist/analysis/module-graph.d.ts +20 -0
- package/dist/analysis/module-graph.d.ts.map +1 -0
- package/dist/analysis/module-graph.js +104 -0
- package/dist/analysis/module-graph.js.map +1 -0
- package/dist/analysis/passes/behavior-evidence.d.ts +9 -0
- package/dist/analysis/passes/behavior-evidence.d.ts.map +1 -0
- package/dist/analysis/passes/behavior-evidence.js +80 -0
- package/dist/analysis/passes/behavior-evidence.js.map +1 -0
- package/dist/analysis/passes/import-evidence.d.ts +3 -0
- package/dist/analysis/passes/import-evidence.d.ts.map +1 -0
- package/dist/analysis/passes/import-evidence.js +58 -0
- package/dist/analysis/passes/import-evidence.js.map +1 -0
- package/dist/analysis/passes/index.d.ts +15 -0
- package/dist/analysis/passes/index.d.ts.map +1 -0
- package/dist/analysis/passes/index.js +21 -0
- package/dist/analysis/passes/index.js.map +1 -0
- package/dist/analysis/passes/jsx-evidence.d.ts +8 -0
- package/dist/analysis/passes/jsx-evidence.d.ts.map +1 -0
- package/dist/analysis/passes/jsx-evidence.js +149 -0
- package/dist/analysis/passes/jsx-evidence.js.map +1 -0
- package/dist/analysis/ts-program.d.ts +12 -0
- package/dist/analysis/ts-program.d.ts.map +1 -0
- package/dist/analysis/ts-program.js +59 -0
- package/dist/analysis/ts-program.js.map +1 -0
- package/dist/analyzer/disambiguator.d.ts +20 -0
- package/dist/analyzer/disambiguator.d.ts.map +1 -0
- package/dist/analyzer/disambiguator.js +83 -0
- package/dist/analyzer/disambiguator.js.map +1 -0
- package/dist/analyzer/index.d.ts +26 -0
- package/dist/analyzer/index.d.ts.map +1 -0
- package/dist/analyzer/index.js +68 -0
- package/dist/analyzer/index.js.map +1 -0
- package/dist/analyzer/parser.d.ts +23 -0
- package/dist/analyzer/parser.d.ts.map +1 -0
- package/dist/analyzer/parser.js +58 -0
- package/dist/analyzer/parser.js.map +1 -0
- package/dist/analyzer/patterns.d.ts +42 -0
- package/dist/analyzer/patterns.d.ts.map +1 -0
- package/dist/analyzer/patterns.js +206 -0
- package/dist/analyzer/patterns.js.map +1 -0
- package/dist/analyzer/props.d.ts +16 -0
- package/dist/analyzer/props.d.ts.map +1 -0
- package/dist/analyzer/props.js +235 -0
- package/dist/analyzer/props.js.map +1 -0
- package/dist/analyzer/rules/checkbox-switch-toggle.d.ts +10 -0
- package/dist/analyzer/rules/checkbox-switch-toggle.d.ts.map +1 -0
- package/dist/analyzer/rules/checkbox-switch-toggle.js +26 -0
- package/dist/analyzer/rules/checkbox-switch-toggle.js.map +1 -0
- package/dist/analyzer/rules/dialog-popover.d.ts +10 -0
- package/dist/analyzer/rules/dialog-popover.d.ts.map +1 -0
- package/dist/analyzer/rules/dialog-popover.js +25 -0
- package/dist/analyzer/rules/dialog-popover.js.map +1 -0
- package/dist/analyzer/rules/index.d.ts +24 -0
- package/dist/analyzer/rules/index.d.ts.map +1 -0
- package/dist/analyzer/rules/index.js +51 -0
- package/dist/analyzer/rules/index.js.map +1 -0
- package/dist/analyzer/rules/tooltip-hovercard.d.ts +10 -0
- package/dist/analyzer/rules/tooltip-hovercard.d.ts.map +1 -0
- package/dist/analyzer/rules/tooltip-hovercard.js +21 -0
- package/dist/analyzer/rules/tooltip-hovercard.js.map +1 -0
- package/dist/analyzer/scorer.d.ts +12 -0
- package/dist/analyzer/scorer.d.ts.map +1 -0
- package/dist/analyzer/scorer.js +171 -0
- package/dist/analyzer/scorer.js.map +1 -0
- package/dist/analyzer/weights.d.ts +28 -0
- package/dist/analyzer/weights.d.ts.map +1 -0
- package/dist/analyzer/weights.js +40 -0
- package/dist/analyzer/weights.js.map +1 -0
- package/dist/audit/analyses/migration.d.ts +42 -0
- package/dist/audit/analyses/migration.d.ts.map +1 -0
- package/dist/audit/analyses/migration.js +91 -0
- package/dist/audit/analyses/migration.js.map +1 -0
- package/dist/audit/discover-components.d.ts +7 -0
- package/dist/audit/discover-components.d.ts.map +1 -0
- package/dist/audit/discover-components.js +486 -0
- package/dist/audit/discover-components.js.map +1 -0
- package/dist/audit/generate-report.d.ts +28 -0
- package/dist/audit/generate-report.d.ts.map +1 -0
- package/dist/audit/generate-report.js +333 -0
- package/dist/audit/generate-report.js.map +1 -0
- package/dist/audit/index.d.ts +8 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +8 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/run-audit.d.ts +33 -0
- package/dist/audit/run-audit.d.ts.map +1 -0
- package/dist/audit/run-audit.js +287 -0
- package/dist/audit/run-audit.js.map +1 -0
- package/dist/audit/types.d.ts +135 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +5 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/cache/index.d.ts +110 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +176 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/storage.d.ts +73 -0
- package/dist/cache/storage.d.ts.map +1 -0
- package/dist/cache/storage.js +176 -0
- package/dist/cache/storage.js.map +1 -0
- package/dist/cache/ttl.d.ts +62 -0
- package/dist/cache/ttl.d.ts.map +1 -0
- package/dist/cache/ttl.js +96 -0
- package/dist/cache/ttl.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +6 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +43 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/audit.d.ts +6 -0
- package/dist/cli/commands/audit.d.ts.map +1 -0
- package/dist/cli/commands/audit.js +73 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/cli/commands/check-updates.d.ts +6 -0
- package/dist/cli/commands/check-updates.d.ts.map +1 -0
- package/dist/cli/commands/check-updates.js +34 -0
- package/dist/cli/commands/check-updates.js.map +1 -0
- package/dist/cli/commands/diff.d.ts +7 -0
- package/dist/cli/commands/diff.d.ts.map +1 -0
- package/dist/cli/commands/diff.js +48 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/extract.d.ts +6 -0
- package/dist/cli/commands/extract.d.ts.map +1 -0
- package/dist/cli/commands/extract.js +42 -0
- package/dist/cli/commands/extract.js.map +1 -0
- package/dist/cli/commands/list.d.ts +6 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +33 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/flags.d.ts +9 -0
- package/dist/cli/flags.d.ts.map +1 -0
- package/dist/cli/flags.js +22 -0
- package/dist/cli/flags.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +40 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/differ/hints.d.ts +21 -0
- package/dist/differ/hints.d.ts.map +1 -0
- package/dist/differ/hints.js +105 -0
- package/dist/differ/hints.js.map +1 -0
- package/dist/differ/index.d.ts +25 -0
- package/dist/differ/index.d.ts.map +1 -0
- package/dist/differ/index.js +115 -0
- package/dist/differ/index.js.map +1 -0
- package/dist/differ/props.d.ts +36 -0
- package/dist/differ/props.d.ts.map +1 -0
- package/dist/differ/props.js +210 -0
- package/dist/differ/props.js.map +1 -0
- package/dist/differ/severity.d.ts +31 -0
- package/dist/differ/severity.d.ts.map +1 -0
- package/dist/differ/severity.js +65 -0
- package/dist/differ/severity.js.map +1 -0
- package/dist/differ/types.d.ts +109 -0
- package/dist/differ/types.d.ts.map +1 -0
- package/dist/differ/types.js +5 -0
- package/dist/differ/types.js.map +1 -0
- package/dist/extractor/classifier.d.ts +30 -0
- package/dist/extractor/classifier.d.ts.map +1 -0
- package/dist/extractor/classifier.js +150 -0
- package/dist/extractor/classifier.js.map +1 -0
- package/dist/extractor/forward-ref.d.ts +28 -0
- package/dist/extractor/forward-ref.d.ts.map +1 -0
- package/dist/extractor/forward-ref.js +134 -0
- package/dist/extractor/forward-ref.js.map +1 -0
- package/dist/extractor/index.d.ts +25 -0
- package/dist/extractor/index.d.ts.map +1 -0
- package/dist/extractor/index.js +43 -0
- package/dist/extractor/index.js.map +1 -0
- package/dist/extractor/interface.d.ts +40 -0
- package/dist/extractor/interface.d.ts.map +1 -0
- package/dist/extractor/interface.js +233 -0
- package/dist/extractor/interface.js.map +1 -0
- package/dist/extractor/jsdoc.d.ts +24 -0
- package/dist/extractor/jsdoc.d.ts.map +1 -0
- package/dist/extractor/jsdoc.js +74 -0
- package/dist/extractor/jsdoc.js.map +1 -0
- package/dist/extractor/project.d.ts +17 -0
- package/dist/extractor/project.d.ts.map +1 -0
- package/dist/extractor/project.js +33 -0
- package/dist/extractor/project.js.map +1 -0
- package/dist/extractor/props.d.ts +24 -0
- package/dist/extractor/props.d.ts.map +1 -0
- package/dist/extractor/props.js +78 -0
- package/dist/extractor/props.js.map +1 -0
- package/dist/extractor/type-resolver.d.ts +32 -0
- package/dist/extractor/type-resolver.d.ts.map +1 -0
- package/dist/extractor/type-resolver.js +129 -0
- package/dist/extractor/type-resolver.js.map +1 -0
- package/dist/fetcher/index.d.ts +7 -0
- package/dist/fetcher/index.d.ts.map +1 -0
- package/dist/fetcher/index.js +7 -0
- package/dist/fetcher/index.js.map +1 -0
- package/dist/fetcher/npm-registry.d.ts +45 -0
- package/dist/fetcher/npm-registry.d.ts.map +1 -0
- package/dist/fetcher/npm-registry.js +217 -0
- package/dist/fetcher/npm-registry.js.map +1 -0
- package/dist/fetcher/unified-package.d.ts +27 -0
- package/dist/fetcher/unified-package.d.ts.map +1 -0
- package/dist/fetcher/unified-package.js +99 -0
- package/dist/fetcher/unified-package.js.map +1 -0
- package/dist/fetcher/unpkg.d.ts +20 -0
- package/dist/fetcher/unpkg.d.ts.map +1 -0
- package/dist/fetcher/unpkg.js +58 -0
- package/dist/fetcher/unpkg.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/base.d.ts +10 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +80 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +10 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/interface.d.ts +56 -0
- package/dist/providers/interface.d.ts.map +1 -0
- package/dist/providers/interface.js +5 -0
- package/dist/providers/interface.js.map +1 -0
- package/dist/providers/radix-backend.d.ts +11 -0
- package/dist/providers/radix-backend.d.ts.map +1 -0
- package/dist/providers/radix-backend.js +107 -0
- package/dist/providers/radix-backend.js.map +1 -0
- package/dist/providers/radix.d.ts +6 -0
- package/dist/providers/radix.d.ts.map +1 -0
- package/dist/providers/radix.js +21 -0
- package/dist/providers/radix.js.map +1 -0
- package/dist/providers/registry.d.ts +17 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +55 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/rules/engine.d.ts +4 -0
- package/dist/rules/engine.d.ts.map +1 -0
- package/dist/rules/engine.js +37 -0
- package/dist/rules/engine.js.map +1 -0
- package/dist/rules/index.d.ts +6 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +6 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/predicates.d.ts +10 -0
- package/dist/rules/predicates.d.ts.map +1 -0
- package/dist/rules/predicates.js +93 -0
- package/dist/rules/predicates.js.map +1 -0
- package/dist/rules/rulesets/base-ui.d.ts +3 -0
- package/dist/rules/rulesets/base-ui.d.ts.map +1 -0
- package/dist/rules/rulesets/base-ui.js +65 -0
- package/dist/rules/rulesets/base-ui.js.map +1 -0
- package/dist/rules/rulesets/radix-legacy.d.ts +3 -0
- package/dist/rules/rulesets/radix-legacy.d.ts.map +1 -0
- package/dist/rules/rulesets/radix-legacy.js +38 -0
- package/dist/rules/rulesets/radix-legacy.js.map +1 -0
- package/dist/rules/types.d.ts +57 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +2 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/signatures/disambiguation.d.ts +30 -0
- package/dist/signatures/disambiguation.d.ts.map +1 -0
- package/dist/signatures/disambiguation.js +99 -0
- package/dist/signatures/disambiguation.js.map +1 -0
- package/dist/signatures/distinguishing.d.ts +29 -0
- package/dist/signatures/distinguishing.d.ts.map +1 -0
- package/dist/signatures/distinguishing.js +108 -0
- package/dist/signatures/distinguishing.js.map +1 -0
- package/dist/signatures/generator.d.ts +20 -0
- package/dist/signatures/generator.d.ts.map +1 -0
- package/dist/signatures/generator.js +147 -0
- package/dist/signatures/generator.js.map +1 -0
- package/dist/signatures/index.d.ts +10 -0
- package/dist/signatures/index.d.ts.map +1 -0
- package/dist/signatures/index.js +10 -0
- package/dist/signatures/index.js.map +1 -0
- package/dist/signatures/inference.d.ts +37 -0
- package/dist/signatures/inference.d.ts.map +1 -0
- package/dist/signatures/inference.js +132 -0
- package/dist/signatures/inference.js.map +1 -0
- package/dist/tools/analyze-component.d.ts +41 -0
- package/dist/tools/analyze-component.d.ts.map +1 -0
- package/dist/tools/analyze-component.js +274 -0
- package/dist/tools/analyze-component.js.map +1 -0
- package/dist/tools/check-updates.d.ts +33 -0
- package/dist/tools/check-updates.d.ts.map +1 -0
- package/dist/tools/check-updates.js +81 -0
- package/dist/tools/check-updates.js.map +1 -0
- package/dist/tools/diff-versions.d.ts +39 -0
- package/dist/tools/diff-versions.d.ts.map +1 -0
- package/dist/tools/diff-versions.js +78 -0
- package/dist/tools/diff-versions.js.map +1 -0
- package/dist/tools/extract-primitive.d.ts +50 -0
- package/dist/tools/extract-primitive.d.ts.map +1 -0
- package/dist/tools/extract-primitive.js +145 -0
- package/dist/tools/extract-primitive.js.map +1 -0
- package/dist/tools/generate-report.d.ts +29 -0
- package/dist/tools/generate-report.d.ts.map +1 -0
- package/dist/tools/generate-report.js +36 -0
- package/dist/tools/generate-report.js.map +1 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-primitives.d.ts +41 -0
- package/dist/tools/list-primitives.d.ts.map +1 -0
- package/dist/tools/list-primitives.js +74 -0
- package/dist/tools/list-primitives.js.map +1 -0
- package/dist/tools/run-audit.d.ts +43 -0
- package/dist/tools/run-audit.d.ts.map +1 -0
- package/dist/tools/run-audit.js +60 -0
- package/dist/tools/run-audit.js.map +1 -0
- package/dist/types/index.d.ts +143 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/docs/architecture.md +88 -0
- package/docs/providers.md +47 -0
- package/docs/tools.md +143 -0
- package/package.json +59 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Props extraction from local component files.
|
|
3
|
+
* Handles various prop patterns: interfaces, inline props, FC generics, ForwardRef.
|
|
4
|
+
*/
|
|
5
|
+
import { extractPropsFromInterface } from '../extractor/props.js';
|
|
6
|
+
import { findForwardRefDeclarations, extractPropsFromForwardRef, } from '../extractor/forward-ref.js';
|
|
7
|
+
import { classifyProp } from '../extractor/classifier.js';
|
|
8
|
+
import { filterReactInternals } from '../extractor/type-resolver.js';
|
|
9
|
+
/**
|
|
10
|
+
* Extract props from a component file.
|
|
11
|
+
* Tries multiple patterns:
|
|
12
|
+
* 1. Named Props interface (e.g., ModalProps)
|
|
13
|
+
* 2. Inline props in function parameters
|
|
14
|
+
* 3. FC generic (const Modal: FC<ModalProps>)
|
|
15
|
+
* 4. ForwardRefExoticComponent
|
|
16
|
+
*/
|
|
17
|
+
export function extractProps(sourceFile, componentName) {
|
|
18
|
+
const propsMap = new Map();
|
|
19
|
+
// Try to find named Props interface first
|
|
20
|
+
const propsInterface = findPropsInterface(sourceFile, componentName);
|
|
21
|
+
if (propsInterface) {
|
|
22
|
+
const rawProps = extractPropsFromInterface(propsInterface);
|
|
23
|
+
for (const rawProp of rawProps) {
|
|
24
|
+
const classified = classifyProp(rawProp);
|
|
25
|
+
propsMap.set(classified.name, classified);
|
|
26
|
+
}
|
|
27
|
+
return propsMap;
|
|
28
|
+
}
|
|
29
|
+
// Try ForwardRef declarations
|
|
30
|
+
const forwardRefDecls = findForwardRefDeclarations(sourceFile);
|
|
31
|
+
if (forwardRefDecls.length > 0) {
|
|
32
|
+
for (const decl of forwardRefDecls) {
|
|
33
|
+
if (componentName && decl.name !== componentName)
|
|
34
|
+
continue;
|
|
35
|
+
const rawProps = extractPropsFromForwardRef(sourceFile, decl);
|
|
36
|
+
if (rawProps) {
|
|
37
|
+
const filtered = filterReactInternals(rawProps);
|
|
38
|
+
for (const rawProp of filtered) {
|
|
39
|
+
const classified = classifyProp(rawProp);
|
|
40
|
+
propsMap.set(classified.name, classified);
|
|
41
|
+
}
|
|
42
|
+
return propsMap;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Try function component with inline props
|
|
47
|
+
const funcDecl = findFunctionComponent(sourceFile, componentName);
|
|
48
|
+
if (funcDecl) {
|
|
49
|
+
const rawProps = extractPropsFromFunction(funcDecl);
|
|
50
|
+
for (const rawProp of rawProps) {
|
|
51
|
+
const classified = classifyProp(rawProp);
|
|
52
|
+
propsMap.set(classified.name, classified);
|
|
53
|
+
}
|
|
54
|
+
return propsMap;
|
|
55
|
+
}
|
|
56
|
+
// Try FC generic pattern
|
|
57
|
+
const fcDecl = findFCComponent(sourceFile, componentName);
|
|
58
|
+
if (fcDecl) {
|
|
59
|
+
const rawProps = extractPropsFromFC(fcDecl, sourceFile);
|
|
60
|
+
for (const rawProp of rawProps) {
|
|
61
|
+
const classified = classifyProp(rawProp);
|
|
62
|
+
propsMap.set(classified.name, classified);
|
|
63
|
+
}
|
|
64
|
+
return propsMap;
|
|
65
|
+
}
|
|
66
|
+
return propsMap;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Find a Props interface (e.g., ModalProps, DialogProps).
|
|
70
|
+
*/
|
|
71
|
+
function findPropsInterface(sourceFile, componentName) {
|
|
72
|
+
const interfaces = sourceFile.getInterfaces();
|
|
73
|
+
// If component name provided, look for ComponentNameProps
|
|
74
|
+
if (componentName) {
|
|
75
|
+
const propsName = `${componentName}Props`;
|
|
76
|
+
const iface = sourceFile.getInterface(propsName);
|
|
77
|
+
if (iface)
|
|
78
|
+
return iface;
|
|
79
|
+
}
|
|
80
|
+
// Look for any interface ending in "Props"
|
|
81
|
+
for (const iface of interfaces) {
|
|
82
|
+
if (iface.getName().endsWith('Props')) {
|
|
83
|
+
return iface;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Find a function component declaration.
|
|
90
|
+
*/
|
|
91
|
+
function findFunctionComponent(sourceFile, componentName) {
|
|
92
|
+
const functions = sourceFile.getFunctions();
|
|
93
|
+
if (componentName) {
|
|
94
|
+
const func = sourceFile.getFunction(componentName);
|
|
95
|
+
if (func)
|
|
96
|
+
return func;
|
|
97
|
+
}
|
|
98
|
+
// Look for exported function (common pattern)
|
|
99
|
+
for (const func of functions) {
|
|
100
|
+
if (func.isExported()) {
|
|
101
|
+
return func;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Extract props from a function component with inline props.
|
|
108
|
+
* Handles: function Modal({ open, onOpenChange }: { open: boolean; ... }) { ... }
|
|
109
|
+
*/
|
|
110
|
+
function extractPropsFromFunction(func) {
|
|
111
|
+
const params = func.getParameters();
|
|
112
|
+
if (params.length === 0)
|
|
113
|
+
return [];
|
|
114
|
+
// First parameter is usually the props
|
|
115
|
+
const propsParam = params[0];
|
|
116
|
+
const typeNode = propsParam.getTypeNode();
|
|
117
|
+
if (!typeNode) {
|
|
118
|
+
// Try to infer from type
|
|
119
|
+
const type = propsParam.getType();
|
|
120
|
+
return extractPropsFromType(type);
|
|
121
|
+
}
|
|
122
|
+
// Extract from type node
|
|
123
|
+
return extractPropsFromTypeNode(typeNode);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Extract props from a TypeNode (inline type literal).
|
|
127
|
+
*/
|
|
128
|
+
function extractPropsFromTypeNode(typeNode) {
|
|
129
|
+
const props = [];
|
|
130
|
+
const type = typeNode.getType();
|
|
131
|
+
// Get properties from the type
|
|
132
|
+
for (const prop of type.getProperties()) {
|
|
133
|
+
const name = prop.getName();
|
|
134
|
+
const declarations = prop.getDeclarations();
|
|
135
|
+
const propDecl = declarations[0];
|
|
136
|
+
if (!propDecl)
|
|
137
|
+
continue;
|
|
138
|
+
const propType = prop.getTypeAtLocation(propDecl);
|
|
139
|
+
const typeText = propType.getText();
|
|
140
|
+
// Check if optional
|
|
141
|
+
const isOptional = propDecl.getKindName() === 'PropertySignature'
|
|
142
|
+
? propDecl
|
|
143
|
+
.hasQuestionToken?.() ?? false
|
|
144
|
+
: typeText.includes('undefined');
|
|
145
|
+
props.push({
|
|
146
|
+
name,
|
|
147
|
+
type: simplifyTypeText(typeText),
|
|
148
|
+
required: !isOptional,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return props;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Extract props from a Type (from type checker).
|
|
155
|
+
*/
|
|
156
|
+
function extractPropsFromType(type) {
|
|
157
|
+
const props = [];
|
|
158
|
+
for (const prop of type.getProperties()) {
|
|
159
|
+
const name = prop.getName();
|
|
160
|
+
const declarations = prop.getDeclarations();
|
|
161
|
+
const propDecl = declarations[0];
|
|
162
|
+
if (!propDecl)
|
|
163
|
+
continue;
|
|
164
|
+
const propType = prop.getTypeAtLocation(propDecl);
|
|
165
|
+
const typeText = propType.getText();
|
|
166
|
+
// Check if optional (union with undefined)
|
|
167
|
+
const isOptional = typeText.includes('undefined');
|
|
168
|
+
props.push({
|
|
169
|
+
name,
|
|
170
|
+
type: simplifyTypeText(typeText),
|
|
171
|
+
required: !isOptional,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return props;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Find a React.FC component declaration.
|
|
178
|
+
* Handles: const Modal: FC<ModalProps> = ...
|
|
179
|
+
*/
|
|
180
|
+
function findFCComponent(sourceFile, componentName) {
|
|
181
|
+
for (const statement of sourceFile.getVariableStatements()) {
|
|
182
|
+
for (const decl of statement.getDeclarations()) {
|
|
183
|
+
const name = decl.getName();
|
|
184
|
+
if (componentName && name !== componentName)
|
|
185
|
+
continue;
|
|
186
|
+
const typeNode = decl.getTypeNode();
|
|
187
|
+
if (!typeNode)
|
|
188
|
+
continue;
|
|
189
|
+
const typeText = typeNode.getText();
|
|
190
|
+
if (typeText.includes('FC<') || typeText.includes('React.FC<')) {
|
|
191
|
+
return decl;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Extract props from a React.FC declaration.
|
|
199
|
+
*/
|
|
200
|
+
function extractPropsFromFC(decl, sourceFile) {
|
|
201
|
+
const typeNode = decl.getTypeNode();
|
|
202
|
+
if (!typeNode)
|
|
203
|
+
return [];
|
|
204
|
+
const type = typeNode.getType();
|
|
205
|
+
const typeArgs = type.getTypeArguments();
|
|
206
|
+
if (typeArgs.length === 0)
|
|
207
|
+
return [];
|
|
208
|
+
// First type argument is the props type
|
|
209
|
+
const propsType = typeArgs[0];
|
|
210
|
+
// Try to get the interface name
|
|
211
|
+
const typeText = typeNode.getText();
|
|
212
|
+
const match = typeText.match(/(?:React\.)?FC<(\w+)>/);
|
|
213
|
+
if (match) {
|
|
214
|
+
const propsTypeName = match[1];
|
|
215
|
+
const propsInterface = sourceFile.getInterface(propsTypeName);
|
|
216
|
+
if (propsInterface) {
|
|
217
|
+
return extractPropsFromInterface(propsInterface);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Fallback: extract from type directly
|
|
221
|
+
return extractPropsFromType(propsType);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Simplify complex type text for readability.
|
|
225
|
+
*/
|
|
226
|
+
function simplifyTypeText(text) {
|
|
227
|
+
return text
|
|
228
|
+
.replace(/React\.ReactNode/g, 'ReactNode')
|
|
229
|
+
.replace(/React\.ReactElement/g, 'ReactElement')
|
|
230
|
+
.replace(/React\.CSSProperties/g, 'CSSProperties')
|
|
231
|
+
.replace(/React\.HTMLAttributes<.*?>/g, 'HTMLAttributes')
|
|
232
|
+
.replace(/React\.ComponentPropsWithoutRef<.*?>/g, 'ComponentProps')
|
|
233
|
+
.replace(/import\(".*?"\)\./g, '');
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=props.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"props.js","sourceRoot":"","sources":["../../src/analyzer/props.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rule for Checkbox vs Switch vs Toggle.
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentAnalysis } from '../../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Disambiguate between Checkbox, Switch, and Toggle.
|
|
7
|
+
* Returns the preferred primitive or null if cannot disambiguate.
|
|
8
|
+
*/
|
|
9
|
+
export declare function disambiguateCheckboxSwitchToggle(analysis: ComponentAnalysis): 'Checkbox' | 'Switch' | 'Toggle' | null;
|
|
10
|
+
//# sourceMappingURL=checkbox-switch-toggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-switch-toggle.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/checkbox-switch-toggle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,iBAAiB,GAC1B,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAqBzC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rule for Checkbox vs Switch vs Toggle.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Disambiguate between Checkbox, Switch, and Toggle.
|
|
6
|
+
* Returns the preferred primitive or null if cannot disambiguate.
|
|
7
|
+
*/
|
|
8
|
+
export function disambiguateCheckboxSwitchToggle(analysis) {
|
|
9
|
+
const props = analysis.propsInterface;
|
|
10
|
+
const subComponents = analysis.subComponents;
|
|
11
|
+
// Switch: has Thumb sub-component (distinctive)
|
|
12
|
+
if (subComponents.includes('Thumb')) {
|
|
13
|
+
return 'Switch';
|
|
14
|
+
}
|
|
15
|
+
// Toggle: has pressed state (distinctive)
|
|
16
|
+
if (props.has('pressed') || props.has('defaultPressed')) {
|
|
17
|
+
return 'Toggle';
|
|
18
|
+
}
|
|
19
|
+
// Checkbox: has checked state (but not pressed)
|
|
20
|
+
if (props.has('checked') || props.has('defaultChecked')) {
|
|
21
|
+
return 'Checkbox';
|
|
22
|
+
}
|
|
23
|
+
// Cannot disambiguate
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=checkbox-switch-toggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkbox-switch-toggle.js","sourceRoot":"","sources":["../../../src/analyzer/rules/checkbox-switch-toggle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,UAAU,gCAAgC,CAC9C,QAA2B;IAE3B,MAAM,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC;IACtC,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;IAE7C,gDAAgD;IAChD,IAAI,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0CAA0C;IAC1C,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACxD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,gDAAgD;IAChD,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACxD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,sBAAsB;IACtB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rule for Dialog vs Popover.
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentAnalysis } from '../../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Disambiguate between Dialog and Popover.
|
|
7
|
+
* Returns the preferred primitive or null if cannot disambiguate.
|
|
8
|
+
*/
|
|
9
|
+
export declare function disambiguateDialogPopover(analysis: ComponentAnalysis): 'Dialog' | 'Popover' | null;
|
|
10
|
+
//# sourceMappingURL=dialog-popover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog-popover.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/dialog-popover.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,iBAAiB,GAC1B,QAAQ,GAAG,SAAS,GAAG,IAAI,CAoB7B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rule for Dialog vs Popover.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Disambiguate between Dialog and Popover.
|
|
6
|
+
* Returns the preferred primitive or null if cannot disambiguate.
|
|
7
|
+
*/
|
|
8
|
+
export function disambiguateDialogPopover(analysis) {
|
|
9
|
+
const props = analysis.propsInterface;
|
|
10
|
+
// Dialog: has modal prop
|
|
11
|
+
if (props.has('modal')) {
|
|
12
|
+
return 'Dialog';
|
|
13
|
+
}
|
|
14
|
+
// Dialog: has Overlay sub-component
|
|
15
|
+
if (analysis.subComponents.includes('Overlay')) {
|
|
16
|
+
return 'Dialog';
|
|
17
|
+
}
|
|
18
|
+
// Popover: has side or align props (positioning props)
|
|
19
|
+
if (props.has('side') || props.has('align')) {
|
|
20
|
+
return 'Popover';
|
|
21
|
+
}
|
|
22
|
+
// Cannot disambiguate
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=dialog-popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog-popover.js","sourceRoot":"","sources":["../../../src/analyzer/rules/dialog-popover.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAA2B;IAE3B,MAAM,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC;IAEtC,yBAAyB;IACzB,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,oCAAoC;IACpC,IAAI,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,uDAAuD;IACvD,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,sBAAsB;IACtB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rules registry.
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentAnalysis } from '../../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Disambiguation rule function type.
|
|
7
|
+
*/
|
|
8
|
+
export type DisambiguationRule = (analysis: ComponentAnalysis) => string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Disambiguation rules map.
|
|
11
|
+
* Key: pair of primitives (sorted alphabetically, joined with '-')
|
|
12
|
+
* Value: disambiguation function
|
|
13
|
+
*/
|
|
14
|
+
export declare const DISAMBIGUATION_RULES: Map<string, DisambiguationRule>;
|
|
15
|
+
/**
|
|
16
|
+
* Get disambiguation rule for a pair of primitives.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getDisambiguationRule(primitive1: string, primitive2: string): DisambiguationRule | null;
|
|
19
|
+
/**
|
|
20
|
+
* Get disambiguation rule for multiple primitives.
|
|
21
|
+
* Also checks if the provided primitives are a subset of any registered rule.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDisambiguationRuleForGroup(primitives: string[]): DisambiguationRule | null;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAK9D;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,QAAQ,EAAE,iBAAiB,KACxB,MAAM,GAAG,IAAI,CAAC;AAEnB;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,iCAI/B,CAAC;AAEH;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,kBAAkB,GAAG,IAAI,CAM3B;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAAE,GACnB,kBAAkB,GAAG,IAAI,CAuB3B"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rules registry.
|
|
3
|
+
*/
|
|
4
|
+
import { disambiguateDialogPopover } from './dialog-popover.js';
|
|
5
|
+
import { disambiguateTooltipHoverCard } from './tooltip-hovercard.js';
|
|
6
|
+
import { disambiguateCheckboxSwitchToggle } from './checkbox-switch-toggle.js';
|
|
7
|
+
/**
|
|
8
|
+
* Disambiguation rules map.
|
|
9
|
+
* Key: pair of primitives (sorted alphabetically, joined with '-')
|
|
10
|
+
* Value: disambiguation function
|
|
11
|
+
*/
|
|
12
|
+
export const DISAMBIGUATION_RULES = new Map([
|
|
13
|
+
['Dialog-Popover', disambiguateDialogPopover],
|
|
14
|
+
['HoverCard-Tooltip', disambiguateTooltipHoverCard],
|
|
15
|
+
['Checkbox-Switch-Toggle', disambiguateCheckboxSwitchToggle],
|
|
16
|
+
]);
|
|
17
|
+
/**
|
|
18
|
+
* Get disambiguation rule for a pair of primitives.
|
|
19
|
+
*/
|
|
20
|
+
export function getDisambiguationRule(primitive1, primitive2) {
|
|
21
|
+
// Sort primitives alphabetically for consistent key lookup
|
|
22
|
+
const sorted = [primitive1, primitive2].sort();
|
|
23
|
+
const key = sorted.join('-');
|
|
24
|
+
return DISAMBIGUATION_RULES.get(key) || null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get disambiguation rule for multiple primitives.
|
|
28
|
+
* Also checks if the provided primitives are a subset of any registered rule.
|
|
29
|
+
*/
|
|
30
|
+
export function getDisambiguationRuleForGroup(primitives) {
|
|
31
|
+
// Sort primitives alphabetically for consistent key lookup
|
|
32
|
+
const sorted = [...primitives].sort();
|
|
33
|
+
const key = sorted.join('-');
|
|
34
|
+
// Try exact match first
|
|
35
|
+
const exactMatch = DISAMBIGUATION_RULES.get(key);
|
|
36
|
+
if (exactMatch) {
|
|
37
|
+
return exactMatch;
|
|
38
|
+
}
|
|
39
|
+
// Try to find a rule where the provided primitives are a subset
|
|
40
|
+
// e.g., ['Checkbox', 'Switch'] should match 'Checkbox-Switch-Toggle'
|
|
41
|
+
for (const [ruleKey, rule] of DISAMBIGUATION_RULES.entries()) {
|
|
42
|
+
const rulePrimitives = ruleKey.split('-');
|
|
43
|
+
// Check if all provided primitives are in the rule
|
|
44
|
+
const allMatch = sorted.every((p) => rulePrimitives.includes(p));
|
|
45
|
+
if (allMatch && sorted.length >= 2) {
|
|
46
|
+
return rule;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzer/rules/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAC;AAS/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAA6B;IACtE,CAAC,gBAAgB,EAAE,yBAAyB,CAAC;IAC7C,CAAC,mBAAmB,EAAE,4BAA4B,CAAC;IACnD,CAAC,wBAAwB,EAAE,gCAAgC,CAAC;CAC7D,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAkB,EAClB,UAAkB;IAElB,2DAA2D;IAC3D,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE7B,OAAO,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,UAAoB;IAEpB,2DAA2D;IAC3D,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE7B,wBAAwB;IACxB,MAAM,UAAU,GAAG,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,gEAAgE;IAChE,qEAAqE;IACrE,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,oBAAoB,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7D,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,mDAAmD;QACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rule for Tooltip vs HoverCard.
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentAnalysis } from '../../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Disambiguate between Tooltip and HoverCard.
|
|
7
|
+
* Returns the preferred primitive or null if cannot disambiguate.
|
|
8
|
+
*/
|
|
9
|
+
export declare function disambiguateTooltipHoverCard(analysis: ComponentAnalysis): 'Tooltip' | 'HoverCard' | null;
|
|
10
|
+
//# sourceMappingURL=tooltip-hovercard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip-hovercard.d.ts","sourceRoot":"","sources":["../../../src/analyzer/rules/tooltip-hovercard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,iBAAiB,GAC1B,SAAS,GAAG,WAAW,GAAG,IAAI,CAehC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disambiguation rule for Tooltip vs HoverCard.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Disambiguate between Tooltip and HoverCard.
|
|
6
|
+
* Returns the preferred primitive or null if cannot disambiguate.
|
|
7
|
+
*/
|
|
8
|
+
export function disambiguateTooltipHoverCard(analysis) {
|
|
9
|
+
const props = analysis.propsInterface;
|
|
10
|
+
// Tooltip: has delayDuration prop (common naming)
|
|
11
|
+
if (props.has('delayDuration')) {
|
|
12
|
+
return 'Tooltip';
|
|
13
|
+
}
|
|
14
|
+
// HoverCard: has openDelay prop (common naming)
|
|
15
|
+
if (props.has('openDelay')) {
|
|
16
|
+
return 'HoverCard';
|
|
17
|
+
}
|
|
18
|
+
// Cannot disambiguate
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=tooltip-hovercard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip-hovercard.js","sourceRoot":"","sources":["../../../src/analyzer/rules/tooltip-hovercard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAA2B;IAE3B,MAAM,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC;IAEtC,kDAAkD;IAClD,IAAI,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,gDAAgD;IAChD,IAAI,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,sBAAsB;IACtB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Confidence scoring for component analysis.
|
|
3
|
+
* Scores components against Radix signatures using weighted dimensions.
|
|
4
|
+
*/
|
|
5
|
+
import type { ComponentAnalysis, PrimitiveMatch, BehaviorSignature } from '../types/index.js';
|
|
6
|
+
import { type ScoringWeights } from './weights.js';
|
|
7
|
+
/**
|
|
8
|
+
* Score a component analysis against a Radix signature.
|
|
9
|
+
* Returns a PrimitiveMatch with confidence score and breakdown.
|
|
10
|
+
*/
|
|
11
|
+
export declare function scoreAgainstSignatures(analysis: ComponentAnalysis, signatures: BehaviorSignature[], weights?: Partial<ScoringWeights>): PrimitiveMatch[];
|
|
12
|
+
//# sourceMappingURL=scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../../src/analyzer/scorer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EAElB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,iBAAiB,EAAE,EAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,cAAc,EAAE,CAalB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Confidence scoring for component analysis.
|
|
3
|
+
* Scores components against Radix signatures using weighted dimensions.
|
|
4
|
+
*/
|
|
5
|
+
import { getScoringWeights } from './weights.js';
|
|
6
|
+
/**
|
|
7
|
+
* Score a component analysis against a Radix signature.
|
|
8
|
+
* Returns a PrimitiveMatch with confidence score and breakdown.
|
|
9
|
+
*/
|
|
10
|
+
export function scoreAgainstSignatures(analysis, signatures, weights) {
|
|
11
|
+
const scoringWeights = getScoringWeights(weights);
|
|
12
|
+
const matches = [];
|
|
13
|
+
for (const signature of signatures) {
|
|
14
|
+
const match = scoreComponent(analysis, signature, scoringWeights);
|
|
15
|
+
matches.push(match);
|
|
16
|
+
}
|
|
17
|
+
// Sort by confidence (descending)
|
|
18
|
+
matches.sort((a, b) => b.confidence - a.confidence);
|
|
19
|
+
return matches;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Score a single component against a signature.
|
|
23
|
+
*/
|
|
24
|
+
function scoreComponent(analysis, signature, weights) {
|
|
25
|
+
const breakdown = {
|
|
26
|
+
statePatternScore: scoreStatePattern(analysis.inferredStatePattern, signature.statePattern, weights.statePattern),
|
|
27
|
+
compositionScore: scoreComposition(analysis.inferredCompositionPattern, signature.compositionPattern, weights.composition),
|
|
28
|
+
propsSignatureScore: scorePropsSignature(analysis.propsInterface, signature, weights.propsSignature),
|
|
29
|
+
accessibilityScore: scoreAccessibility(analysis.ariaRoles, analysis.dataAttributes, signature, weights.accessibility),
|
|
30
|
+
renderingScore: scoreRendering(analysis.inferredRenderingPattern, signature.renderingPattern, weights.rendering),
|
|
31
|
+
};
|
|
32
|
+
// Calculate total confidence
|
|
33
|
+
let confidence = breakdown.statePatternScore +
|
|
34
|
+
breakdown.compositionScore +
|
|
35
|
+
breakdown.propsSignatureScore +
|
|
36
|
+
breakdown.accessibilityScore +
|
|
37
|
+
breakdown.renderingScore;
|
|
38
|
+
// Apply anti-pattern penalty
|
|
39
|
+
const antiPatternPenalty = calculateAntiPatternPenalty(analysis.propsInterface, signature.antiPatternProps);
|
|
40
|
+
confidence = Math.max(0, confidence - antiPatternPenalty);
|
|
41
|
+
// Collect signals
|
|
42
|
+
const signals = collectSignals(analysis, signature);
|
|
43
|
+
return {
|
|
44
|
+
primitive: signature.primitive,
|
|
45
|
+
package: signature.package,
|
|
46
|
+
confidence: Math.round(confidence),
|
|
47
|
+
breakdown,
|
|
48
|
+
signals,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Score state pattern match (0 to maxScore).
|
|
53
|
+
*/
|
|
54
|
+
function scoreStatePattern(inferred, expected, maxScore) {
|
|
55
|
+
if (inferred === expected) {
|
|
56
|
+
return maxScore;
|
|
57
|
+
}
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Score composition pattern match (0 to maxScore).
|
|
62
|
+
*/
|
|
63
|
+
function scoreComposition(inferred, expected, maxScore) {
|
|
64
|
+
if (inferred === expected) {
|
|
65
|
+
return maxScore;
|
|
66
|
+
}
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Score props signature match (0 to maxScore).
|
|
71
|
+
* Checks for distinguishing props and gives partial credit.
|
|
72
|
+
*/
|
|
73
|
+
function scorePropsSignature(props, signature, maxScore) {
|
|
74
|
+
const distinguishingProps = signature.distinguishingProps;
|
|
75
|
+
if (distinguishingProps.length === 0) {
|
|
76
|
+
// No distinguishing props to check, return neutral score
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
let matchedCount = 0;
|
|
80
|
+
for (const propName of distinguishingProps) {
|
|
81
|
+
if (props.has(propName)) {
|
|
82
|
+
matchedCount++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Proportional score based on how many distinguishing props match
|
|
86
|
+
return Math.round((matchedCount / distinguishingProps.length) * maxScore);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Score accessibility features (0 to maxScore).
|
|
90
|
+
* Checks for aria roles and data attributes that match expected patterns.
|
|
91
|
+
*/
|
|
92
|
+
function scoreAccessibility(ariaRoles, dataAttributes, _signature, maxScore) {
|
|
93
|
+
// Basic scoring: if component has accessibility features, give partial credit
|
|
94
|
+
// More sophisticated scoring could check for specific roles/attributes
|
|
95
|
+
if (ariaRoles.length > 0 || dataAttributes.length > 0) {
|
|
96
|
+
// Give partial credit for having accessibility features
|
|
97
|
+
return Math.round(maxScore * 0.5);
|
|
98
|
+
}
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Score rendering pattern match (0 to maxScore).
|
|
103
|
+
*/
|
|
104
|
+
function scoreRendering(inferred, expected, maxScore) {
|
|
105
|
+
if (inferred === expected) {
|
|
106
|
+
return maxScore;
|
|
107
|
+
}
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Calculate anti-pattern penalty.
|
|
112
|
+
* Returns penalty points to subtract from total score.
|
|
113
|
+
*/
|
|
114
|
+
function calculateAntiPatternPenalty(props, antiPatternProps) {
|
|
115
|
+
let penalty = 0;
|
|
116
|
+
for (const antiProp of antiPatternProps) {
|
|
117
|
+
if (props.has(antiProp)) {
|
|
118
|
+
// Each anti-pattern prop reduces score by 10 points
|
|
119
|
+
penalty += 10;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return penalty;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Collect signals (matched, missing, anti-patterns) for debugging.
|
|
126
|
+
*/
|
|
127
|
+
function collectSignals(analysis, signature) {
|
|
128
|
+
const matched = [];
|
|
129
|
+
const missing = [];
|
|
130
|
+
const antiPatterns = [];
|
|
131
|
+
// Check distinguishing props
|
|
132
|
+
for (const propName of signature.distinguishingProps) {
|
|
133
|
+
if (analysis.propsInterface.has(propName)) {
|
|
134
|
+
matched.push(`prop:${propName}`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
missing.push(`prop:${propName}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Check patterns
|
|
141
|
+
if (analysis.inferredStatePattern === signature.statePattern) {
|
|
142
|
+
matched.push(`state:${signature.statePattern}`);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
missing.push(`state:${signature.statePattern}`);
|
|
146
|
+
}
|
|
147
|
+
if (analysis.inferredCompositionPattern === signature.compositionPattern) {
|
|
148
|
+
matched.push(`composition:${signature.compositionPattern}`);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
missing.push(`composition:${signature.compositionPattern}`);
|
|
152
|
+
}
|
|
153
|
+
if (analysis.inferredRenderingPattern === signature.renderingPattern) {
|
|
154
|
+
matched.push(`rendering:${signature.renderingPattern}`);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
missing.push(`rendering:${signature.renderingPattern}`);
|
|
158
|
+
}
|
|
159
|
+
// Check anti-patterns
|
|
160
|
+
for (const antiProp of signature.antiPatternProps) {
|
|
161
|
+
if (analysis.propsInterface.has(antiProp)) {
|
|
162
|
+
antiPatterns.push(antiProp);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
matched,
|
|
167
|
+
missing,
|
|
168
|
+
antiPatterns,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=scorer.js.map
|