@contentful/experience-design-system-cli 2.2.1
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/README.md +532 -0
- package/bin/cli.js +58 -0
- package/dist/package.json +56 -0
- package/dist/src/analyze/command.d.ts +3 -0
- package/dist/src/analyze/command.js +175 -0
- package/dist/src/analyze/extract/astro.d.ts +5 -0
- package/dist/src/analyze/extract/astro.js +280 -0
- package/dist/src/analyze/extract/pipeline.d.ts +6 -0
- package/dist/src/analyze/extract/pipeline.js +298 -0
- package/dist/src/analyze/extract/react.d.ts +2 -0
- package/dist/src/analyze/extract/react.js +1949 -0
- package/dist/src/analyze/extract/slot-detection.d.ts +35 -0
- package/dist/src/analyze/extract/slot-detection.js +101 -0
- package/dist/src/analyze/extract/stencil.d.ts +2 -0
- package/dist/src/analyze/extract/stencil.js +293 -0
- package/dist/src/analyze/extract/tsx-shared.d.ts +8 -0
- package/dist/src/analyze/extract/tsx-shared.js +263 -0
- package/dist/src/analyze/extract/vue-tsx.d.ts +2 -0
- package/dist/src/analyze/extract/vue-tsx.js +498 -0
- package/dist/src/analyze/extract/vue.d.ts +5 -0
- package/dist/src/analyze/extract/vue.js +647 -0
- package/dist/src/analyze/extract/web-components.d.ts +2 -0
- package/dist/src/analyze/extract/web-components.js +866 -0
- package/dist/src/analyze/pre-classify.d.ts +17 -0
- package/dist/src/analyze/pre-classify.js +144 -0
- package/dist/src/analyze/select/command.d.ts +2 -0
- package/dist/src/analyze/select/command.js +256 -0
- package/dist/src/analyze/select/index.d.ts +6 -0
- package/dist/src/analyze/select/index.js +5 -0
- package/dist/src/analyze/select/parser.d.ts +6 -0
- package/dist/src/analyze/select/parser.js +53 -0
- package/dist/src/analyze/select/persistence.d.ts +9 -0
- package/dist/src/analyze/select/persistence.js +42 -0
- package/dist/src/analyze/select/stdout.d.ts +7 -0
- package/dist/src/analyze/select/stdout.js +3 -0
- package/dist/src/analyze/select/tui/App.d.ts +8 -0
- package/dist/src/analyze/select/tui/App.js +491 -0
- package/dist/src/analyze/select/tui/components/ComponentDetail.d.ts +20 -0
- package/dist/src/analyze/select/tui/components/ComponentDetail.js +43 -0
- package/dist/src/analyze/select/tui/components/FieldEditor.d.ts +11 -0
- package/dist/src/analyze/select/tui/components/FieldEditor.js +531 -0
- package/dist/src/analyze/select/tui/components/FinalizeDialog.d.ts +10 -0
- package/dist/src/analyze/select/tui/components/FinalizeDialog.js +15 -0
- package/dist/src/analyze/select/tui/components/HelpOverlay.d.ts +7 -0
- package/dist/src/analyze/select/tui/components/HelpOverlay.js +11 -0
- package/dist/src/analyze/select/tui/components/JsonEditor.d.ts +11 -0
- package/dist/src/analyze/select/tui/components/JsonEditor.js +154 -0
- package/dist/src/analyze/select/tui/components/JsonPanel.d.ts +11 -0
- package/dist/src/analyze/select/tui/components/JsonPanel.js +62 -0
- package/dist/src/analyze/select/tui/components/PreviewSummaryBar.d.ts +8 -0
- package/dist/src/analyze/select/tui/components/PreviewSummaryBar.js +29 -0
- package/dist/src/analyze/select/tui/components/QuitDialog.d.ts +8 -0
- package/dist/src/analyze/select/tui/components/QuitDialog.js +14 -0
- package/dist/src/analyze/select/tui/components/Sidebar.d.ts +15 -0
- package/dist/src/analyze/select/tui/components/Sidebar.js +48 -0
- package/dist/src/analyze/select/tui/components/SourcePanel.d.ts +11 -0
- package/dist/src/analyze/select/tui/components/SourcePanel.js +52 -0
- package/dist/src/analyze/select/tui/components/StatusBar.d.ts +11 -0
- package/dist/src/analyze/select/tui/components/StatusBar.js +6 -0
- package/dist/src/analyze/select/tui/components/TopBar.d.ts +10 -0
- package/dist/src/analyze/select/tui/components/TopBar.js +5 -0
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.d.ts +24 -0
- package/dist/src/analyze/select/tui/hooks/useImmediateInput.js +68 -0
- package/dist/src/analyze/select/tui/hooks/useKeymap.d.ts +24 -0
- package/dist/src/analyze/select/tui/hooks/useKeymap.js +67 -0
- package/dist/src/analyze/select/tui/hooks/useSession.d.ts +19 -0
- package/dist/src/analyze/select/tui/hooks/useSession.js +52 -0
- package/dist/src/analyze/select/tui/hooks/useUndo.d.ts +8 -0
- package/dist/src/analyze/select/tui/hooks/useUndo.js +26 -0
- package/dist/src/analyze/select/types.d.ts +46 -0
- package/dist/src/analyze/select/types.js +20 -0
- package/dist/src/analyze/select-agent/command.d.ts +2 -0
- package/dist/src/analyze/select-agent/command.js +208 -0
- package/dist/src/analyze/tui/AnalyzeView.d.ts +24 -0
- package/dist/src/analyze/tui/AnalyzeView.js +38 -0
- package/dist/src/apply/api-client.d.ts +35 -0
- package/dist/src/apply/api-client.js +143 -0
- package/dist/src/apply/command.d.ts +6 -0
- package/dist/src/apply/command.js +787 -0
- package/dist/src/apply/manifest.d.ts +1 -0
- package/dist/src/apply/manifest.js +1 -0
- package/dist/src/apply/tui/SelectView.d.ts +18 -0
- package/dist/src/apply/tui/SelectView.js +34 -0
- package/dist/src/apply/tui/ServerApplyView.d.ts +32 -0
- package/dist/src/apply/tui/ServerApplyView.js +42 -0
- package/dist/src/apply/tui/ServerPreviewView.d.ts +9 -0
- package/dist/src/apply/tui/ServerPreviewView.js +21 -0
- package/dist/src/credentials-store.d.ts +8 -0
- package/dist/src/credentials-store.js +30 -0
- package/dist/src/generate/agent-runner.d.ts +86 -0
- package/dist/src/generate/agent-runner.js +314 -0
- package/dist/src/generate/command.d.ts +2 -0
- package/dist/src/generate/command.js +545 -0
- package/dist/src/generate/edit/command.d.ts +2 -0
- package/dist/src/generate/edit/command.js +126 -0
- package/dist/src/generate/prompt-builder.d.ts +18 -0
- package/dist/src/generate/prompt-builder.js +202 -0
- package/dist/src/generate/tui/GenerateView.d.ts +12 -0
- package/dist/src/generate/tui/GenerateView.js +10 -0
- package/dist/src/import/command.d.ts +2 -0
- package/dist/src/import/command.js +96 -0
- package/dist/src/import/orchestrator.d.ts +37 -0
- package/dist/src/import/orchestrator.js +374 -0
- package/dist/src/import/path-utils.d.ts +15 -0
- package/dist/src/import/path-utils.js +30 -0
- package/dist/src/import/tui/WizardApp.d.ts +10 -0
- package/dist/src/import/tui/WizardApp.js +906 -0
- package/dist/src/import/tui/steps/CredentialsStep.d.ts +15 -0
- package/dist/src/import/tui/steps/CredentialsStep.js +79 -0
- package/dist/src/import/tui/steps/DoneStep.d.ts +20 -0
- package/dist/src/import/tui/steps/DoneStep.js +17 -0
- package/dist/src/import/tui/steps/ErrorStep.d.ts +8 -0
- package/dist/src/import/tui/steps/ErrorStep.js +11 -0
- package/dist/src/import/tui/steps/GateStep.d.ts +14 -0
- package/dist/src/import/tui/steps/GateStep.js +20 -0
- package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +8 -0
- package/dist/src/import/tui/steps/GenerateReviewStep.js +208 -0
- package/dist/src/import/tui/steps/PathValidationStep.d.ts +10 -0
- package/dist/src/import/tui/steps/PathValidationStep.js +151 -0
- package/dist/src/import/tui/steps/PreviewStep.d.ts +21 -0
- package/dist/src/import/tui/steps/PreviewStep.js +36 -0
- package/dist/src/import/tui/steps/RunningStep.d.ts +10 -0
- package/dist/src/import/tui/steps/RunningStep.js +20 -0
- package/dist/src/import/tui/steps/TokenInputStep.d.ts +8 -0
- package/dist/src/import/tui/steps/TokenInputStep.js +70 -0
- package/dist/src/import/tui/steps/WelcomeStep.d.ts +7 -0
- package/dist/src/import/tui/steps/WelcomeStep.js +33 -0
- package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +15 -0
- package/dist/src/import/tui/steps/WizardPreviewStep.js +121 -0
- package/dist/src/import/tui/steps/preview-diff.d.ts +10 -0
- package/dist/src/import/tui/steps/preview-diff.js +132 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +2 -0
- package/dist/src/output/format.d.ts +23 -0
- package/dist/src/output/format.js +110 -0
- package/dist/src/print/command.d.ts +2 -0
- package/dist/src/print/command.js +199 -0
- package/dist/src/print/validate/tui/ValidateView.d.ts +15 -0
- package/dist/src/print/validate/tui/ValidateView.js +37 -0
- package/dist/src/print/validate/validators/cdf-validator.d.ts +2 -0
- package/dist/src/print/validate/validators/cdf-validator.js +104 -0
- package/dist/src/print/validate/validators/dtcg-validator.d.ts +2 -0
- package/dist/src/print/validate/validators/dtcg-validator.js +110 -0
- package/dist/src/print/validate/validators/format-errors.d.ts +12 -0
- package/dist/src/print/validate/validators/format-errors.js +18 -0
- package/dist/src/program.d.ts +2 -0
- package/dist/src/program.js +25 -0
- package/dist/src/session/command.d.ts +2 -0
- package/dist/src/session/command.js +261 -0
- package/dist/src/session/db.d.ts +111 -0
- package/dist/src/session/db.js +1114 -0
- package/dist/src/session/migration.d.ts +4 -0
- package/dist/src/session/migration.js +117 -0
- package/dist/src/session/session-id.d.ts +1 -0
- package/dist/src/session/session-id.js +212 -0
- package/dist/src/session/stats.d.ts +27 -0
- package/dist/src/session/stats.js +89 -0
- package/dist/src/setup/command.d.ts +2 -0
- package/dist/src/setup/command.js +765 -0
- package/dist/src/types.d.ts +48 -0
- package/dist/src/types.js +1 -0
- package/package.json +55 -0
- package/skills/generate-components.md +361 -0
- package/skills/generate-tokens.md +194 -0
- package/skills/select-components.md +180 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
import { Node, Project, SyntaxKind } from 'ts-morph';
|
|
2
|
+
import { extractAllowedValues, getTypeReferenceName, getTypeTargetDeclarations, getValueTargetDeclarations, } from './tsx-shared.js';
|
|
3
|
+
export async function extractVueTsxComponents(filePaths) {
|
|
4
|
+
const componentFiles = filePaths.filter((f) => f.endsWith('.tsx'));
|
|
5
|
+
if (componentFiles.length === 0) {
|
|
6
|
+
return { components: [], warnings: [] };
|
|
7
|
+
}
|
|
8
|
+
const projectFiles = filePaths.filter((f) => /\.[jt]sx?$/.test(f) && !f.endsWith('.d.ts'));
|
|
9
|
+
const project = new Project({
|
|
10
|
+
compilerOptions: {
|
|
11
|
+
jsx: 1,
|
|
12
|
+
target: 99,
|
|
13
|
+
module: 99,
|
|
14
|
+
moduleResolution: 100,
|
|
15
|
+
skipLibCheck: true,
|
|
16
|
+
allowJs: true,
|
|
17
|
+
},
|
|
18
|
+
skipAddingFilesFromTsConfig: true,
|
|
19
|
+
});
|
|
20
|
+
for (const filePath of projectFiles) {
|
|
21
|
+
project.addSourceFileAtPath(filePath);
|
|
22
|
+
}
|
|
23
|
+
const warnings = [];
|
|
24
|
+
const components = [];
|
|
25
|
+
for (const filePath of componentFiles) {
|
|
26
|
+
try {
|
|
27
|
+
const sourceFile = project.getSourceFile(filePath);
|
|
28
|
+
if (!sourceFile)
|
|
29
|
+
continue;
|
|
30
|
+
components.push(...extractFromSourceFile(sourceFile));
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
warnings.push(`Failed to extract from ${filePath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
components: components.sort((a, b) => a.name.localeCompare(b.name)),
|
|
38
|
+
warnings,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function extractFromSourceFile(sourceFile) {
|
|
42
|
+
const components = [];
|
|
43
|
+
const exported = sourceFile.getExportedDeclarations();
|
|
44
|
+
for (const [exportKey, declarations] of exported) {
|
|
45
|
+
let name = exportKey;
|
|
46
|
+
if (exportKey === 'default') {
|
|
47
|
+
const decl = declarations[0];
|
|
48
|
+
const declName = Node.isFunctionDeclaration(decl) ? decl.getName() : undefined;
|
|
49
|
+
if (!declName || !/^[A-Z]/.test(declName))
|
|
50
|
+
continue;
|
|
51
|
+
if (exported.has(declName))
|
|
52
|
+
continue;
|
|
53
|
+
name = declName;
|
|
54
|
+
}
|
|
55
|
+
if (!/^[A-Z]/.test(name))
|
|
56
|
+
continue;
|
|
57
|
+
if (name.startsWith('use'))
|
|
58
|
+
continue;
|
|
59
|
+
const component = extractVueTsxComponent(declarations, name, sourceFile);
|
|
60
|
+
if (component) {
|
|
61
|
+
components.push(component);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return components;
|
|
65
|
+
}
|
|
66
|
+
function extractVueTsxComponent(declarations, exportName, sourceFile) {
|
|
67
|
+
for (const declaration of declarations) {
|
|
68
|
+
if (!Node.isVariableDeclaration(declaration))
|
|
69
|
+
continue;
|
|
70
|
+
if (declaration.getSourceFile().getFilePath() !== sourceFile.getFilePath())
|
|
71
|
+
continue;
|
|
72
|
+
const resolved = resolveVueComponentOptions(declaration.getInitializer());
|
|
73
|
+
if (!resolved)
|
|
74
|
+
continue;
|
|
75
|
+
const name = extractVueGenericComponentName(resolved.options) ?? exportName;
|
|
76
|
+
const props = extractVueGenericComponentProps(resolved.options);
|
|
77
|
+
const slots = extractVueGenericComponentSlots(resolved.options, resolved.slotsTypeNode);
|
|
78
|
+
return {
|
|
79
|
+
name,
|
|
80
|
+
source: sourceFile.getFilePath(),
|
|
81
|
+
framework: 'vue',
|
|
82
|
+
props,
|
|
83
|
+
slots,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
function resolveVueComponentOptions(node) {
|
|
89
|
+
if (!node || !Node.isCallExpression(node))
|
|
90
|
+
return undefined;
|
|
91
|
+
const directExpressionText = node.getExpression().getText();
|
|
92
|
+
if (/(^|\.)defineComponent$/.test(directExpressionText)) {
|
|
93
|
+
const optionsArg = node.getArguments()[0];
|
|
94
|
+
if (!optionsArg || !Node.isObjectLiteralExpression(optionsArg))
|
|
95
|
+
return undefined;
|
|
96
|
+
return { options: optionsArg };
|
|
97
|
+
}
|
|
98
|
+
if (!Node.isCallExpression(node.getExpression()))
|
|
99
|
+
return undefined;
|
|
100
|
+
const outerArgs = node.getArguments();
|
|
101
|
+
if (outerArgs.length !== 1)
|
|
102
|
+
return undefined;
|
|
103
|
+
const optionsArg = outerArgs[0];
|
|
104
|
+
if (!Node.isObjectLiteralExpression(optionsArg))
|
|
105
|
+
return undefined;
|
|
106
|
+
const innerCall = node.getExpression();
|
|
107
|
+
if (!Node.isCallExpression(innerCall))
|
|
108
|
+
return undefined;
|
|
109
|
+
const innerExpressionText = innerCall.getExpression().getText();
|
|
110
|
+
if (!/(^|\.)genericComponent$/.test(innerExpressionText))
|
|
111
|
+
return undefined;
|
|
112
|
+
return {
|
|
113
|
+
options: optionsArg,
|
|
114
|
+
slotsTypeNode: innerCall.getTypeArguments()[0],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function extractVueGenericComponentName(options) {
|
|
118
|
+
const nameProp = options.getProperty('name');
|
|
119
|
+
if (!nameProp || !Node.isPropertyAssignment(nameProp))
|
|
120
|
+
return undefined;
|
|
121
|
+
const initializer = nameProp.getInitializer();
|
|
122
|
+
if (!initializer || !Node.isStringLiteral(initializer))
|
|
123
|
+
return undefined;
|
|
124
|
+
return initializer.getLiteralText();
|
|
125
|
+
}
|
|
126
|
+
function extractVueGenericComponentProps(options) {
|
|
127
|
+
const propsProp = options.getProperty('props');
|
|
128
|
+
if (!propsProp || !Node.isPropertyAssignment(propsProp))
|
|
129
|
+
return [];
|
|
130
|
+
const initializer = propsProp.getInitializer();
|
|
131
|
+
if (!initializer)
|
|
132
|
+
return [];
|
|
133
|
+
return extractVuePropsFromExpression(initializer, new Set()).sort((a, b) => a.name.localeCompare(b.name));
|
|
134
|
+
}
|
|
135
|
+
function resolveVuePropsObjectLiteral(node) {
|
|
136
|
+
if (Node.isObjectLiteralExpression(node))
|
|
137
|
+
return node;
|
|
138
|
+
if (!Node.isCallExpression(node))
|
|
139
|
+
return undefined;
|
|
140
|
+
const returnedObject = resolveReturnedObjectLiteralFromCallExpression(node, new Set());
|
|
141
|
+
if (returnedObject)
|
|
142
|
+
return returnedObject;
|
|
143
|
+
const expression = node.getExpression();
|
|
144
|
+
if (Node.isIdentifier(expression)) {
|
|
145
|
+
for (const declaration of getValueTargetDeclarations(expression)) {
|
|
146
|
+
if (!Node.isVariableDeclaration(declaration))
|
|
147
|
+
continue;
|
|
148
|
+
const initializer = declaration.getInitializer();
|
|
149
|
+
if (!initializer || !Node.isCallExpression(initializer))
|
|
150
|
+
continue;
|
|
151
|
+
if (!/(^|\.)propsFactory$/.test(initializer.getExpression().getText()))
|
|
152
|
+
continue;
|
|
153
|
+
const propsArg = initializer.getArguments()[0];
|
|
154
|
+
if (propsArg && Node.isObjectLiteralExpression(propsArg)) {
|
|
155
|
+
return propsArg;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
function extractVuePropsFromExpression(node, seen) {
|
|
162
|
+
if (seen.has(node))
|
|
163
|
+
return [];
|
|
164
|
+
seen.add(node);
|
|
165
|
+
if (Node.isObjectLiteralExpression(node)) {
|
|
166
|
+
return extractVuePropsFromObjectLiteral(node, seen);
|
|
167
|
+
}
|
|
168
|
+
if (Node.isCallExpression(node)) {
|
|
169
|
+
const expressionName = getExpressionTerminalName(node.getExpression());
|
|
170
|
+
if (expressionName === 'pick' || expressionName === 'omit') {
|
|
171
|
+
const sourceArg = node.getArguments()[0];
|
|
172
|
+
const keyArg = node.getArguments()[1];
|
|
173
|
+
if (!sourceArg || !keyArg)
|
|
174
|
+
return [];
|
|
175
|
+
const keys = extractStringLiteralArrayValues(keyArg);
|
|
176
|
+
if (!keys)
|
|
177
|
+
return [];
|
|
178
|
+
const sourceProps = extractVuePropsFromExpression(sourceArg, seen);
|
|
179
|
+
const keySet = new Set(keys);
|
|
180
|
+
return sourceProps.filter((prop) => (expressionName === 'pick' ? keySet.has(prop.name) : !keySet.has(prop.name)));
|
|
181
|
+
}
|
|
182
|
+
const propsObject = resolveVuePropsObjectLiteral(node);
|
|
183
|
+
if (propsObject)
|
|
184
|
+
return extractVuePropsFromObjectLiteral(propsObject, seen);
|
|
185
|
+
}
|
|
186
|
+
if (Node.isIdentifier(node)) {
|
|
187
|
+
for (const declaration of getValueTargetDeclarations(node)) {
|
|
188
|
+
const resolved = resolveReturnedObjectLiteral(declaration, seen);
|
|
189
|
+
if (resolved) {
|
|
190
|
+
return extractVuePropsFromObjectLiteral(resolved, seen);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
function extractVuePropsFromObjectLiteral(objectLiteral, seen) {
|
|
197
|
+
const propsByName = new Map();
|
|
198
|
+
for (const property of objectLiteral.getProperties()) {
|
|
199
|
+
if (Node.isPropertyAssignment(property)) {
|
|
200
|
+
const propName = getVueObjectPropertyName(property);
|
|
201
|
+
if (!propName)
|
|
202
|
+
continue;
|
|
203
|
+
const definition = extractVuePropDefinition(propName, property.getInitializer());
|
|
204
|
+
if (definition) {
|
|
205
|
+
propsByName.set(definition.name, definition);
|
|
206
|
+
}
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (Node.isSpreadAssignment(property)) {
|
|
210
|
+
for (const definition of extractVuePropsFromExpression(property.getExpression(), seen)) {
|
|
211
|
+
propsByName.set(definition.name, definition);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return [...propsByName.values()];
|
|
216
|
+
}
|
|
217
|
+
function getVueObjectPropertyName(property) {
|
|
218
|
+
const nameNode = property.getNameNode();
|
|
219
|
+
if (Node.isIdentifier(nameNode) || Node.isPrivateIdentifier(nameNode)) {
|
|
220
|
+
return nameNode.getText();
|
|
221
|
+
}
|
|
222
|
+
if (Node.isStringLiteral(nameNode) || Node.isNoSubstitutionTemplateLiteral(nameNode)) {
|
|
223
|
+
return nameNode.getLiteralText();
|
|
224
|
+
}
|
|
225
|
+
if (Node.isComputedPropertyName(nameNode)) {
|
|
226
|
+
const expression = nameNode.getExpression();
|
|
227
|
+
if (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression)) {
|
|
228
|
+
return expression.getLiteralText();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return property.getName();
|
|
232
|
+
}
|
|
233
|
+
function extractVuePropDefinition(propName, initializer) {
|
|
234
|
+
if (!initializer)
|
|
235
|
+
return undefined;
|
|
236
|
+
if (Node.isObjectLiteralExpression(initializer)) {
|
|
237
|
+
return extractVueObjectPropDefinition(propName, initializer);
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
name: propName,
|
|
241
|
+
type: getVuePropTypeText(initializer),
|
|
242
|
+
required: false,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function extractVueObjectPropDefinition(propName, initializer) {
|
|
246
|
+
let type = 'any';
|
|
247
|
+
let required = false;
|
|
248
|
+
let defaultValue;
|
|
249
|
+
let allowedValues;
|
|
250
|
+
for (const property of initializer.getProperties()) {
|
|
251
|
+
if (!Node.isPropertyAssignment(property))
|
|
252
|
+
continue;
|
|
253
|
+
const name = property.getName();
|
|
254
|
+
const value = property.getInitializer();
|
|
255
|
+
if (!value)
|
|
256
|
+
continue;
|
|
257
|
+
if (name === 'type') {
|
|
258
|
+
type = getVuePropTypeText(value);
|
|
259
|
+
allowedValues = extractAllowedValues(value.getType());
|
|
260
|
+
}
|
|
261
|
+
else if (name === 'required') {
|
|
262
|
+
required = value.getText() === 'true';
|
|
263
|
+
}
|
|
264
|
+
else if (name === 'default') {
|
|
265
|
+
defaultValue = value.getText();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
name: propName,
|
|
270
|
+
type,
|
|
271
|
+
required,
|
|
272
|
+
...(defaultValue !== undefined && { defaultValue }),
|
|
273
|
+
...(allowedValues && { allowedValues }),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function getVuePropTypeText(node) {
|
|
277
|
+
if (Node.isAsExpression(node) || Node.isTypeAssertion(node)) {
|
|
278
|
+
const typeNode = node.getTypeNode();
|
|
279
|
+
const propTypeType = extractPropTypeTypeArgumentText(typeNode);
|
|
280
|
+
if (propTypeType)
|
|
281
|
+
return propTypeType;
|
|
282
|
+
return getVuePropTypeText(node.getExpression());
|
|
283
|
+
}
|
|
284
|
+
if (Node.isParenthesizedExpression(node)) {
|
|
285
|
+
return getVuePropTypeText(node.getExpression());
|
|
286
|
+
}
|
|
287
|
+
if (Node.isArrayLiteralExpression(node)) {
|
|
288
|
+
const memberTypes = node.getElements().flatMap((element) => {
|
|
289
|
+
const memberType = getVuePropTypeText(element);
|
|
290
|
+
return memberType === 'any' ? [] : [memberType];
|
|
291
|
+
});
|
|
292
|
+
return memberTypes.length > 0 ? [...new Set(memberTypes)].sort().join(' | ') : 'any';
|
|
293
|
+
}
|
|
294
|
+
if (Node.isIdentifier(node)) {
|
|
295
|
+
return VUE_PROP_VALUE_TYPE_MAP[node.getText()] ?? node.getText();
|
|
296
|
+
}
|
|
297
|
+
if (Node.isNullLiteral(node))
|
|
298
|
+
return 'any';
|
|
299
|
+
return node.getType().getText(node);
|
|
300
|
+
}
|
|
301
|
+
const VUE_PROP_VALUE_TYPE_MAP = {
|
|
302
|
+
String: 'string',
|
|
303
|
+
Number: 'number',
|
|
304
|
+
Boolean: 'boolean',
|
|
305
|
+
Array: 'any[]',
|
|
306
|
+
Object: 'object',
|
|
307
|
+
Function: 'function',
|
|
308
|
+
};
|
|
309
|
+
function extractPropTypeTypeArgumentText(typeNode) {
|
|
310
|
+
if (!typeNode || !Node.isTypeReference(typeNode))
|
|
311
|
+
return undefined;
|
|
312
|
+
if (getTypeReferenceName(typeNode) !== 'PropType')
|
|
313
|
+
return undefined;
|
|
314
|
+
return typeNode.getTypeArguments()[0]?.getText();
|
|
315
|
+
}
|
|
316
|
+
function extractVueGenericComponentSlots(options, slotsTypeNode) {
|
|
317
|
+
const slotsByName = new Map();
|
|
318
|
+
if (slotsTypeNode) {
|
|
319
|
+
for (const slot of extractVueSlotsFromTypeNode(slotsTypeNode, new Set())) {
|
|
320
|
+
slotsByName.set(slot.name, slot);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
for (const slot of extractVueSlotsFromSetup(options)) {
|
|
324
|
+
if (!slotsByName.has(slot.name)) {
|
|
325
|
+
slotsByName.set(slot.name, slot);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return [...slotsByName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
329
|
+
}
|
|
330
|
+
function resolveReturnedObjectLiteral(node, seen) {
|
|
331
|
+
if (seen.has(node))
|
|
332
|
+
return undefined;
|
|
333
|
+
seen.add(node);
|
|
334
|
+
if (Node.isObjectLiteralExpression(node))
|
|
335
|
+
return node;
|
|
336
|
+
if (Node.isParenthesizedExpression(node)) {
|
|
337
|
+
return resolveReturnedObjectLiteral(node.getExpression(), seen);
|
|
338
|
+
}
|
|
339
|
+
if (Node.isVariableDeclaration(node)) {
|
|
340
|
+
const initializer = node.getInitializer();
|
|
341
|
+
if (!initializer)
|
|
342
|
+
return undefined;
|
|
343
|
+
return resolveReturnedObjectLiteral(initializer, seen);
|
|
344
|
+
}
|
|
345
|
+
if (Node.isArrowFunction(node)) {
|
|
346
|
+
const body = node.getBody();
|
|
347
|
+
if (Node.isObjectLiteralExpression(body))
|
|
348
|
+
return body;
|
|
349
|
+
const block = body.asKind(SyntaxKind.Block);
|
|
350
|
+
if (block)
|
|
351
|
+
return resolveReturnedObjectLiteralFromStatements(block.getStatements(), seen);
|
|
352
|
+
return resolveReturnedObjectLiteral(body, seen);
|
|
353
|
+
}
|
|
354
|
+
if (Node.isFunctionDeclaration(node) || Node.isFunctionExpression(node)) {
|
|
355
|
+
const body = node.getBody();
|
|
356
|
+
if (!body)
|
|
357
|
+
return undefined;
|
|
358
|
+
const block = body.asKind(SyntaxKind.Block);
|
|
359
|
+
if (!block)
|
|
360
|
+
return undefined;
|
|
361
|
+
return resolveReturnedObjectLiteralFromStatements(block.getStatements(), seen);
|
|
362
|
+
}
|
|
363
|
+
if (Node.isCallExpression(node)) {
|
|
364
|
+
return resolveReturnedObjectLiteralFromCallExpression(node, seen);
|
|
365
|
+
}
|
|
366
|
+
if (Node.isIdentifier(node)) {
|
|
367
|
+
for (const declaration of getValueTargetDeclarations(node)) {
|
|
368
|
+
const resolved = resolveReturnedObjectLiteral(declaration, seen);
|
|
369
|
+
if (resolved)
|
|
370
|
+
return resolved;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
function resolveReturnedObjectLiteralFromStatements(statements, seen) {
|
|
376
|
+
for (const statement of statements) {
|
|
377
|
+
if (!Node.isReturnStatement(statement))
|
|
378
|
+
continue;
|
|
379
|
+
const expression = statement.getExpression();
|
|
380
|
+
if (!expression)
|
|
381
|
+
continue;
|
|
382
|
+
const resolved = resolveReturnedObjectLiteral(expression, seen);
|
|
383
|
+
if (resolved)
|
|
384
|
+
return resolved;
|
|
385
|
+
}
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
function resolveReturnedObjectLiteralFromCallExpression(callExpression, seen) {
|
|
389
|
+
const expression = callExpression.getExpression();
|
|
390
|
+
if (!Node.isIdentifier(expression))
|
|
391
|
+
return undefined;
|
|
392
|
+
for (const declaration of getValueTargetDeclarations(expression)) {
|
|
393
|
+
const resolved = resolveReturnedObjectLiteral(declaration, seen);
|
|
394
|
+
if (resolved)
|
|
395
|
+
return resolved;
|
|
396
|
+
}
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
function getExpressionTerminalName(node) {
|
|
400
|
+
if (Node.isIdentifier(node))
|
|
401
|
+
return node.getText();
|
|
402
|
+
if (Node.isPropertyAccessExpression(node))
|
|
403
|
+
return node.getName();
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
function extractStringLiteralArrayValues(node) {
|
|
407
|
+
if (!Node.isArrayLiteralExpression(node))
|
|
408
|
+
return undefined;
|
|
409
|
+
const keys = [];
|
|
410
|
+
for (const element of node.getElements()) {
|
|
411
|
+
if (!Node.isStringLiteral(element) && !Node.isNoSubstitutionTemplateLiteral(element)) {
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
keys.push(element.getLiteralText());
|
|
415
|
+
}
|
|
416
|
+
return keys;
|
|
417
|
+
}
|
|
418
|
+
function extractVueSlotsFromTypeNode(typeNode, seen) {
|
|
419
|
+
if (!typeNode || seen.has(typeNode))
|
|
420
|
+
return [];
|
|
421
|
+
seen.add(typeNode);
|
|
422
|
+
if (Node.isTypeLiteral(typeNode)) {
|
|
423
|
+
return typeNode
|
|
424
|
+
.getMembers()
|
|
425
|
+
.flatMap((member) => {
|
|
426
|
+
if (!Node.isPropertySignature(member))
|
|
427
|
+
return [];
|
|
428
|
+
const slotName = member.getName();
|
|
429
|
+
return [{ name: slotName, isDefault: slotName === 'default' }];
|
|
430
|
+
})
|
|
431
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
432
|
+
}
|
|
433
|
+
if (Node.isTypeReference(typeNode)) {
|
|
434
|
+
for (const declaration of getTypeTargetDeclarations(typeNode.getTypeName(), false)) {
|
|
435
|
+
if (Node.isTypeAliasDeclaration(declaration)) {
|
|
436
|
+
return extractVueSlotsFromTypeNode(declaration.getTypeNode(), seen);
|
|
437
|
+
}
|
|
438
|
+
if (Node.isInterfaceDeclaration(declaration)) {
|
|
439
|
+
return declaration
|
|
440
|
+
.getMembers()
|
|
441
|
+
.flatMap((member) => {
|
|
442
|
+
if (!Node.isPropertySignature(member) && !Node.isMethodSignature(member))
|
|
443
|
+
return [];
|
|
444
|
+
const slotName = member.getName();
|
|
445
|
+
return [{ name: slotName, isDefault: slotName === 'default' }];
|
|
446
|
+
})
|
|
447
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return [];
|
|
452
|
+
}
|
|
453
|
+
function extractVueSlotsFromSetup(options) {
|
|
454
|
+
const setupProp = options.getProperty('setup');
|
|
455
|
+
if (!setupProp)
|
|
456
|
+
return [];
|
|
457
|
+
const setupFunction = Node.isMethodDeclaration(setupProp)
|
|
458
|
+
? setupProp
|
|
459
|
+
: Node.isPropertyAssignment(setupProp)
|
|
460
|
+
? setupProp.getInitializer()
|
|
461
|
+
: undefined;
|
|
462
|
+
if (!setupFunction)
|
|
463
|
+
return [];
|
|
464
|
+
if (!Node.isMethodDeclaration(setupFunction) &&
|
|
465
|
+
!Node.isArrowFunction(setupFunction) &&
|
|
466
|
+
!Node.isFunctionExpression(setupFunction)) {
|
|
467
|
+
return [];
|
|
468
|
+
}
|
|
469
|
+
const params = setupFunction.getParameters();
|
|
470
|
+
if (params.length < 2)
|
|
471
|
+
return [];
|
|
472
|
+
const contextParam = params[1];
|
|
473
|
+
const nameNode = contextParam.getNameNode();
|
|
474
|
+
if (!Node.isObjectBindingPattern(nameNode))
|
|
475
|
+
return [];
|
|
476
|
+
const slotsBinding = nameNode
|
|
477
|
+
.getElements()
|
|
478
|
+
.find((element) => element.getPropertyNameNode()?.getText() === 'slots' || element.getName() === 'slots');
|
|
479
|
+
if (!slotsBinding)
|
|
480
|
+
return [];
|
|
481
|
+
const slotsName = slotsBinding.getName();
|
|
482
|
+
const body = setupFunction.getBody();
|
|
483
|
+
if (!body)
|
|
484
|
+
return [];
|
|
485
|
+
const slotsByName = new Map();
|
|
486
|
+
for (const access of body.getDescendantsOfKind(SyntaxKind.PropertyAccessExpression)) {
|
|
487
|
+
if (access.getExpression().getText() !== slotsName)
|
|
488
|
+
continue;
|
|
489
|
+
const slotName = access.getName();
|
|
490
|
+
if (!slotsByName.has(slotName)) {
|
|
491
|
+
slotsByName.set(slotName, {
|
|
492
|
+
name: slotName,
|
|
493
|
+
isDefault: slotName === 'default',
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return [...slotsByName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
498
|
+
}
|