vue-component-meta 3.1.7 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +3 -9
- package/index.js +49 -5
- package/lib/checker.d.ts +16 -0
- package/lib/checker.js +176 -0
- package/lib/componentMeta.d.ts +7 -0
- package/lib/componentMeta.js +192 -0
- package/lib/helpers.d.ts +6 -0
- package/lib/helpers.js +119 -0
- package/lib/schemaResolvers.d.ts +13 -0
- package/lib/schemaResolvers.js +344 -0
- package/lib/scriptSetup.d.ts +4 -0
- package/lib/scriptSetup.js +133 -0
- package/lib/types.d.ts +39 -9
- package/package.json +13 -9
- package/lib/base.d.ts +0 -33
- package/lib/base.js +0 -906
package/lib/base.js
DELETED
|
@@ -1,906 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.createCheckerByJsonConfigBase = createCheckerByJsonConfigBase;
|
|
18
|
-
exports.createCheckerBase = createCheckerBase;
|
|
19
|
-
const typescript_1 = require("@volar/typescript");
|
|
20
|
-
const core = require("@vue/language-core");
|
|
21
|
-
const path_browserify_1 = require("path-browserify");
|
|
22
|
-
__exportStar(require("./types"), exports);
|
|
23
|
-
const windowsPathReg = /\\/g;
|
|
24
|
-
// Utility function to get the component node from an AST
|
|
25
|
-
function getComponentNodeFromAst(ast, exportName, ts) {
|
|
26
|
-
let result;
|
|
27
|
-
if (exportName === 'default') {
|
|
28
|
-
ast.forEachChild(child => {
|
|
29
|
-
if (ts.isExportAssignment(child)) {
|
|
30
|
-
result = child.expression;
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
ast.forEachChild(child => {
|
|
36
|
-
if (ts.isVariableStatement(child)
|
|
37
|
-
&& child.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
38
|
-
for (const dec of child.declarationList.declarations) {
|
|
39
|
-
if (dec.name.getText(ast) === exportName) {
|
|
40
|
-
result = dec.initializer;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
// Utility function to get the component options node from a component node
|
|
49
|
-
function getComponentOptionsNodeFromComponent(component, ts) {
|
|
50
|
-
if (component) {
|
|
51
|
-
// export default { ... }
|
|
52
|
-
if (ts.isObjectLiteralExpression(component)) {
|
|
53
|
-
return component;
|
|
54
|
-
}
|
|
55
|
-
// export default defineComponent({ ... })
|
|
56
|
-
else if (ts.isCallExpression(component)) {
|
|
57
|
-
if (component.arguments.length) {
|
|
58
|
-
const arg = component.arguments[0];
|
|
59
|
-
if (ts.isObjectLiteralExpression(arg)) {
|
|
60
|
-
return arg;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
function createCheckerByJsonConfigBase(ts, rootDir, json, checkerOptions = {}) {
|
|
68
|
-
rootDir = rootDir.replace(windowsPathReg, '/');
|
|
69
|
-
return baseCreate(ts, () => {
|
|
70
|
-
const commandLine = core.createParsedCommandLineByJson(ts, ts.sys, rootDir, json);
|
|
71
|
-
const { fileNames } = ts.parseJsonConfigFileContent(json, ts.sys, rootDir, {}, undefined, undefined, core.getAllExtensions(commandLine.vueOptions)
|
|
72
|
-
.map(extension => ({
|
|
73
|
-
extension: extension.slice(1),
|
|
74
|
-
isMixedContent: true,
|
|
75
|
-
scriptKind: ts.ScriptKind.Deferred,
|
|
76
|
-
})));
|
|
77
|
-
return [commandLine, fileNames];
|
|
78
|
-
}, checkerOptions, rootDir, path_browserify_1.posix.join(rootDir, 'jsconfig.json.global.vue'));
|
|
79
|
-
}
|
|
80
|
-
function createCheckerBase(ts, tsconfig, checkerOptions = {}) {
|
|
81
|
-
tsconfig = tsconfig.replace(windowsPathReg, '/');
|
|
82
|
-
return baseCreate(ts, () => {
|
|
83
|
-
const commandLine = core.createParsedCommandLine(ts, ts.sys, tsconfig);
|
|
84
|
-
const { fileNames } = ts.parseJsonSourceFileConfigFileContent(ts.readJsonConfigFile(tsconfig, ts.sys.readFile), ts.sys, path_browserify_1.posix.dirname(tsconfig), {}, tsconfig, undefined, core.getAllExtensions(commandLine.vueOptions)
|
|
85
|
-
.map(extension => ({
|
|
86
|
-
extension: extension.slice(1),
|
|
87
|
-
isMixedContent: true,
|
|
88
|
-
scriptKind: ts.ScriptKind.Deferred,
|
|
89
|
-
})));
|
|
90
|
-
return [commandLine, fileNames];
|
|
91
|
-
}, checkerOptions, path_browserify_1.posix.dirname(tsconfig), tsconfig + '.global.vue');
|
|
92
|
-
}
|
|
93
|
-
function baseCreate(ts, getConfigAndFiles, checkerOptions, rootPath, globalComponentName) {
|
|
94
|
-
let [{ vueOptions, options, projectReferences }, fileNames] = getConfigAndFiles();
|
|
95
|
-
/**
|
|
96
|
-
* Used to lookup if a file is referenced.
|
|
97
|
-
*/
|
|
98
|
-
let fileNamesSet = new Set(fileNames.map(path => path.replace(windowsPathReg, '/')));
|
|
99
|
-
let projectVersion = 0;
|
|
100
|
-
vueOptions.globalTypesPath = core.createGlobalTypesWriter(vueOptions, ts.sys.writeFile);
|
|
101
|
-
const projectHost = {
|
|
102
|
-
getCurrentDirectory: () => rootPath,
|
|
103
|
-
getProjectVersion: () => projectVersion.toString(),
|
|
104
|
-
getCompilationSettings: () => options,
|
|
105
|
-
getScriptFileNames: () => [...fileNamesSet],
|
|
106
|
-
getProjectReferences: () => projectReferences,
|
|
107
|
-
};
|
|
108
|
-
const globalComponentSnapshot = ts.ScriptSnapshot.fromString('<script setup lang="ts"></script>');
|
|
109
|
-
const scriptSnapshots = new Map();
|
|
110
|
-
const metaSnapshots = new Map();
|
|
111
|
-
const getScriptFileNames = projectHost.getScriptFileNames;
|
|
112
|
-
projectHost.getScriptFileNames = () => {
|
|
113
|
-
const names = getScriptFileNames();
|
|
114
|
-
return [
|
|
115
|
-
...names,
|
|
116
|
-
...names.map(getMetaFileName),
|
|
117
|
-
globalComponentName,
|
|
118
|
-
getMetaFileName(globalComponentName),
|
|
119
|
-
];
|
|
120
|
-
};
|
|
121
|
-
const vueLanguagePlugin = core.createVueLanguagePlugin(ts, projectHost.getCompilationSettings(), vueOptions, id => id);
|
|
122
|
-
const language = core.createLanguage([
|
|
123
|
-
vueLanguagePlugin,
|
|
124
|
-
{
|
|
125
|
-
getLanguageId(fileName) {
|
|
126
|
-
return (0, typescript_1.resolveFileLanguageId)(fileName);
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
], new core.FileMap(ts.sys.useCaseSensitiveFileNames), fileName => {
|
|
130
|
-
let snapshot = scriptSnapshots.get(fileName);
|
|
131
|
-
if (fileName === globalComponentName) {
|
|
132
|
-
snapshot = globalComponentSnapshot;
|
|
133
|
-
}
|
|
134
|
-
else if (isMetaFileName(fileName)) {
|
|
135
|
-
if (!metaSnapshots.has(fileName)) {
|
|
136
|
-
metaSnapshots.set(fileName, ts.ScriptSnapshot.fromString(getMetaScriptContent(fileName)));
|
|
137
|
-
}
|
|
138
|
-
snapshot = metaSnapshots.get(fileName);
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
if (!scriptSnapshots.has(fileName)) {
|
|
142
|
-
const fileText = ts.sys.readFile(fileName);
|
|
143
|
-
if (fileText !== undefined) {
|
|
144
|
-
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(fileText));
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
scriptSnapshots.set(fileName, undefined);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
snapshot = scriptSnapshots.get(fileName);
|
|
151
|
-
}
|
|
152
|
-
if (snapshot) {
|
|
153
|
-
language.scripts.set(fileName, snapshot);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
language.scripts.delete(fileName);
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
const { languageServiceHost } = (0, typescript_1.createLanguageServiceHost)(ts, ts.sys, language, s => s, projectHost);
|
|
160
|
-
const tsLs = ts.createLanguageService(languageServiceHost);
|
|
161
|
-
if (checkerOptions.forceUseTs) {
|
|
162
|
-
const getScriptKind = languageServiceHost.getScriptKind?.bind(languageServiceHost);
|
|
163
|
-
languageServiceHost.getScriptKind = fileName => {
|
|
164
|
-
const scriptKind = getScriptKind(fileName);
|
|
165
|
-
if (vueOptions.extensions.some(ext => fileName.endsWith(ext))) {
|
|
166
|
-
if (scriptKind === ts.ScriptKind.JS) {
|
|
167
|
-
return ts.ScriptKind.TS;
|
|
168
|
-
}
|
|
169
|
-
if (scriptKind === ts.ScriptKind.JSX) {
|
|
170
|
-
return ts.ScriptKind.TSX;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return scriptKind;
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
let globalPropNames;
|
|
177
|
-
return {
|
|
178
|
-
getExportNames,
|
|
179
|
-
getComponentMeta,
|
|
180
|
-
updateFile(fileName, text) {
|
|
181
|
-
fileName = fileName.replace(windowsPathReg, '/');
|
|
182
|
-
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(text));
|
|
183
|
-
// Ensure the file is referenced
|
|
184
|
-
fileNamesSet.add(fileName);
|
|
185
|
-
projectVersion++;
|
|
186
|
-
},
|
|
187
|
-
deleteFile(fileName) {
|
|
188
|
-
fileName = fileName.replace(windowsPathReg, '/');
|
|
189
|
-
fileNamesSet.delete(fileName);
|
|
190
|
-
projectVersion++;
|
|
191
|
-
},
|
|
192
|
-
reload() {
|
|
193
|
-
[{ vueOptions, options, projectReferences }, fileNames] = getConfigAndFiles();
|
|
194
|
-
vueOptions.globalTypesPath = core.createGlobalTypesWriter(vueOptions, ts.sys.writeFile);
|
|
195
|
-
fileNamesSet = new Set(fileNames.map(path => path.replace(windowsPathReg, '/')));
|
|
196
|
-
this.clearCache();
|
|
197
|
-
},
|
|
198
|
-
clearCache() {
|
|
199
|
-
scriptSnapshots.clear();
|
|
200
|
-
projectVersion++;
|
|
201
|
-
},
|
|
202
|
-
getProgram() {
|
|
203
|
-
return tsLs.getProgram();
|
|
204
|
-
},
|
|
205
|
-
/**
|
|
206
|
-
* @deprecated use `getProgram()` instead
|
|
207
|
-
*/
|
|
208
|
-
__internal__: {
|
|
209
|
-
tsLs,
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
|
-
function isMetaFileName(fileName) {
|
|
213
|
-
return fileName.endsWith('.meta.ts');
|
|
214
|
-
}
|
|
215
|
-
function getMetaFileName(fileName) {
|
|
216
|
-
return (vueOptions.extensions.some(ext => fileName.endsWith(ext))
|
|
217
|
-
? fileName
|
|
218
|
-
: fileName.slice(0, fileName.lastIndexOf('.'))) + '.meta.ts';
|
|
219
|
-
}
|
|
220
|
-
function getMetaScriptContent(fileName) {
|
|
221
|
-
const helpersPath = require.resolve('vue-component-type-helpers').replace(windowsPathReg, '/');
|
|
222
|
-
let helpersRelativePath = path_browserify_1.posix.relative(path_browserify_1.posix.dirname(fileName), helpersPath);
|
|
223
|
-
if (!helpersRelativePath.startsWith('./') && !helpersRelativePath.startsWith('../')) {
|
|
224
|
-
helpersRelativePath = './' + helpersRelativePath;
|
|
225
|
-
}
|
|
226
|
-
let code = `
|
|
227
|
-
import type { ComponentType, ComponentProps, ComponentEmit, ComponentSlots, ComponentExposed } from '${helpersRelativePath}';
|
|
228
|
-
import type * as Components from '${fileName.slice(0, -'.meta.ts'.length)}';
|
|
229
|
-
|
|
230
|
-
export default {} as { [K in keyof typeof Components]: ComponentMeta<typeof Components[K]>; };
|
|
231
|
-
|
|
232
|
-
interface ComponentMeta<T> {
|
|
233
|
-
type: ComponentType<T>;
|
|
234
|
-
props: ComponentProps<T>;
|
|
235
|
-
emit: ComponentEmit<T>;
|
|
236
|
-
slots: ComponentSlots<T>;
|
|
237
|
-
exposed: ComponentExposed<T>;
|
|
238
|
-
}
|
|
239
|
-
`.trim();
|
|
240
|
-
return code;
|
|
241
|
-
}
|
|
242
|
-
function getExportNames(componentPath) {
|
|
243
|
-
const program = tsLs.getProgram();
|
|
244
|
-
const typeChecker = program.getTypeChecker();
|
|
245
|
-
return _getExports(program, typeChecker, componentPath).exports.map(e => e.getName());
|
|
246
|
-
}
|
|
247
|
-
function getComponentMeta(componentPath, exportName = 'default') {
|
|
248
|
-
const program = tsLs.getProgram();
|
|
249
|
-
const typeChecker = program.getTypeChecker();
|
|
250
|
-
const { symbolNode, exports } = _getExports(program, typeChecker, componentPath);
|
|
251
|
-
const _export = exports.find(property => property.getName() === exportName);
|
|
252
|
-
if (!_export) {
|
|
253
|
-
throw `Could not find export ${exportName}`;
|
|
254
|
-
}
|
|
255
|
-
const componentType = typeChecker.getTypeOfSymbolAtLocation(_export, symbolNode);
|
|
256
|
-
const symbolProperties = componentType.getProperties();
|
|
257
|
-
let _type;
|
|
258
|
-
let _props;
|
|
259
|
-
let _events;
|
|
260
|
-
let _slots;
|
|
261
|
-
let _exposed;
|
|
262
|
-
let _name;
|
|
263
|
-
let _description;
|
|
264
|
-
const meta = {
|
|
265
|
-
get name() {
|
|
266
|
-
return _name ?? (_name = getName());
|
|
267
|
-
},
|
|
268
|
-
get description() {
|
|
269
|
-
return _description ?? (_description = getDescription());
|
|
270
|
-
},
|
|
271
|
-
get type() {
|
|
272
|
-
return _type ?? (_type = getType());
|
|
273
|
-
},
|
|
274
|
-
get props() {
|
|
275
|
-
return _props ?? (_props = getProps());
|
|
276
|
-
},
|
|
277
|
-
get events() {
|
|
278
|
-
return _events ?? (_events = getEvents());
|
|
279
|
-
},
|
|
280
|
-
get slots() {
|
|
281
|
-
return _slots ?? (_slots = getSlots());
|
|
282
|
-
},
|
|
283
|
-
get exposed() {
|
|
284
|
-
return _exposed ?? (_exposed = getExposed());
|
|
285
|
-
},
|
|
286
|
-
};
|
|
287
|
-
return meta;
|
|
288
|
-
function getType() {
|
|
289
|
-
const $type = symbolProperties.find(prop => prop.escapedName === 'type');
|
|
290
|
-
if ($type) {
|
|
291
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($type, symbolNode);
|
|
292
|
-
return Number(typeChecker.typeToString(type));
|
|
293
|
-
}
|
|
294
|
-
return 0;
|
|
295
|
-
}
|
|
296
|
-
function getProps() {
|
|
297
|
-
const $props = symbolProperties.find(prop => prop.escapedName === 'props');
|
|
298
|
-
const vnodeEventRegex = /^onVnode[A-Z]/;
|
|
299
|
-
let result = [];
|
|
300
|
-
if ($props) {
|
|
301
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($props, symbolNode);
|
|
302
|
-
const properties = type.getProperties();
|
|
303
|
-
const eventProps = new Set(meta.events.map(event => `on${event.name.charAt(0).toUpperCase()}${event.name.slice(1)}`));
|
|
304
|
-
result = properties
|
|
305
|
-
.map(prop => {
|
|
306
|
-
const { resolveNestedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, language);
|
|
307
|
-
return resolveNestedProperties(prop);
|
|
308
|
-
})
|
|
309
|
-
.filter(prop => !vnodeEventRegex.test(prop.name) && !eventProps.has(prop.name));
|
|
310
|
-
}
|
|
311
|
-
// fill global
|
|
312
|
-
if (componentPath !== globalComponentName) {
|
|
313
|
-
globalPropNames ??= getComponentMeta(globalComponentName).props.map(prop => prop.name);
|
|
314
|
-
for (const prop of result) {
|
|
315
|
-
prop.global = globalPropNames.includes(prop.name);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
// fill defaults
|
|
319
|
-
const printer = ts.createPrinter(checkerOptions.printer);
|
|
320
|
-
const sourceScript = language.scripts.get(componentPath);
|
|
321
|
-
const { snapshot } = sourceScript;
|
|
322
|
-
const vueFile = sourceScript.generated?.root;
|
|
323
|
-
const vueDefaults = vueFile && exportName === 'default'
|
|
324
|
-
? (vueFile instanceof core.VueVirtualCode ? readVueComponentDefaultProps(vueFile, printer, ts) : {})
|
|
325
|
-
: {};
|
|
326
|
-
const tsDefaults = !vueFile
|
|
327
|
-
? readTsComponentDefaultProps(ts.createSourceFile('/tmp.' + componentPath.slice(componentPath.lastIndexOf('.') + 1), // ts | js | tsx | jsx
|
|
328
|
-
snapshot.getText(0, snapshot.getLength()), ts.ScriptTarget.Latest), exportName, printer, ts)
|
|
329
|
-
: {};
|
|
330
|
-
for (const [propName, defaultExp] of Object.entries({
|
|
331
|
-
...vueDefaults,
|
|
332
|
-
...tsDefaults,
|
|
333
|
-
})) {
|
|
334
|
-
const prop = result.find(p => p.name === propName);
|
|
335
|
-
if (prop) {
|
|
336
|
-
prop.default = defaultExp.default;
|
|
337
|
-
if (defaultExp.required !== undefined) {
|
|
338
|
-
prop.required = defaultExp.required;
|
|
339
|
-
}
|
|
340
|
-
if (prop.default !== undefined) {
|
|
341
|
-
prop.required = false; // props with default are always optional
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
return result;
|
|
346
|
-
}
|
|
347
|
-
function getEvents() {
|
|
348
|
-
const $emit = symbolProperties.find(prop => prop.escapedName === 'emit');
|
|
349
|
-
if ($emit) {
|
|
350
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($emit, symbolNode);
|
|
351
|
-
const calls = type.getCallSignatures();
|
|
352
|
-
return calls.map(call => {
|
|
353
|
-
const { resolveEventSignature, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, language);
|
|
354
|
-
return resolveEventSignature(call);
|
|
355
|
-
}).filter(event => event.name);
|
|
356
|
-
}
|
|
357
|
-
return [];
|
|
358
|
-
}
|
|
359
|
-
function getSlots() {
|
|
360
|
-
const $slots = symbolProperties.find(prop => prop.escapedName === 'slots');
|
|
361
|
-
if ($slots) {
|
|
362
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($slots, symbolNode);
|
|
363
|
-
const properties = type.getProperties();
|
|
364
|
-
return properties.map(prop => {
|
|
365
|
-
const { resolveSlotProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, language);
|
|
366
|
-
return resolveSlotProperties(prop);
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
return [];
|
|
370
|
-
}
|
|
371
|
-
function getExposed() {
|
|
372
|
-
const $exposed = symbolProperties.find(prop => prop.escapedName === 'exposed');
|
|
373
|
-
if ($exposed) {
|
|
374
|
-
const type = typeChecker.getTypeOfSymbolAtLocation($exposed, symbolNode);
|
|
375
|
-
const properties = type.getProperties().filter(prop =>
|
|
376
|
-
// only exposed props will not have a valueDeclaration
|
|
377
|
-
!prop.valueDeclaration);
|
|
378
|
-
return properties.map(prop => {
|
|
379
|
-
const { resolveExposedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts, language);
|
|
380
|
-
return resolveExposedProperties(prop);
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
return [];
|
|
384
|
-
}
|
|
385
|
-
function getName() {
|
|
386
|
-
// Try to get name from component options
|
|
387
|
-
const sourceScript = language.scripts.get(componentPath);
|
|
388
|
-
const { snapshot } = sourceScript;
|
|
389
|
-
const vueFile = sourceScript.generated?.root;
|
|
390
|
-
if (vueFile && exportName === 'default' && vueFile instanceof core.VueVirtualCode) {
|
|
391
|
-
// For Vue SFC, check the script section
|
|
392
|
-
const { sfc } = vueFile;
|
|
393
|
-
if (sfc.script) {
|
|
394
|
-
const name = readComponentName(sfc.script.ast, exportName, ts);
|
|
395
|
-
if (name) {
|
|
396
|
-
return name;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
else if (!vueFile) {
|
|
401
|
-
// For TS/JS files
|
|
402
|
-
const ast = ts.createSourceFile('/tmp.' + componentPath.slice(componentPath.lastIndexOf('.') + 1), snapshot.getText(0, snapshot.getLength()), ts.ScriptTarget.Latest);
|
|
403
|
-
return readComponentName(ast, exportName, ts);
|
|
404
|
-
}
|
|
405
|
-
return undefined;
|
|
406
|
-
}
|
|
407
|
-
function getDescription() {
|
|
408
|
-
const sourceFile = program.getSourceFile(componentPath);
|
|
409
|
-
if (sourceFile) {
|
|
410
|
-
return readComponentDescription(sourceFile, exportName, ts, typeChecker);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
function _getExports(program, typeChecker, componentPath) {
|
|
415
|
-
const sourceFile = program.getSourceFile(getMetaFileName(componentPath));
|
|
416
|
-
if (!sourceFile) {
|
|
417
|
-
throw 'Could not find main source file';
|
|
418
|
-
}
|
|
419
|
-
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
420
|
-
if (!moduleSymbol) {
|
|
421
|
-
throw 'Could not find module symbol';
|
|
422
|
-
}
|
|
423
|
-
const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol);
|
|
424
|
-
let symbolNode;
|
|
425
|
-
for (const symbol of exportedSymbols) {
|
|
426
|
-
const [declaration] = symbol.getDeclarations() ?? [];
|
|
427
|
-
if (declaration && ts.isExportAssignment(declaration)) {
|
|
428
|
-
symbolNode = declaration.expression;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (!symbolNode) {
|
|
432
|
-
throw 'Could not find symbol node';
|
|
433
|
-
}
|
|
434
|
-
const exportDefaultType = typeChecker.getTypeAtLocation(symbolNode);
|
|
435
|
-
const exports = exportDefaultType.getProperties();
|
|
436
|
-
return {
|
|
437
|
-
symbolNode,
|
|
438
|
-
exports,
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: options, noDeclarations }, ts, language) {
|
|
443
|
-
const visited = new Set();
|
|
444
|
-
function shouldIgnore(subtype) {
|
|
445
|
-
const name = getFullyQualifiedName(subtype);
|
|
446
|
-
if (name === 'any') {
|
|
447
|
-
return true;
|
|
448
|
-
}
|
|
449
|
-
if (visited.has(subtype)) {
|
|
450
|
-
return true;
|
|
451
|
-
}
|
|
452
|
-
if (typeof options === 'object') {
|
|
453
|
-
for (const item of options.ignore ?? []) {
|
|
454
|
-
if (typeof item === 'function') {
|
|
455
|
-
const result = item(name, subtype, typeChecker);
|
|
456
|
-
if (typeof result === 'boolean') {
|
|
457
|
-
return result;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
else if (name === item) {
|
|
461
|
-
return true;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
return false;
|
|
466
|
-
}
|
|
467
|
-
function reducer(acc, cur) {
|
|
468
|
-
acc[cur.name] = cur;
|
|
469
|
-
return acc;
|
|
470
|
-
}
|
|
471
|
-
function resolveNestedProperties(prop) {
|
|
472
|
-
const subtype = typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode);
|
|
473
|
-
let schema;
|
|
474
|
-
let declarations;
|
|
475
|
-
return {
|
|
476
|
-
name: prop.getEscapedName().toString(),
|
|
477
|
-
global: false,
|
|
478
|
-
description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
|
|
479
|
-
tags: prop.getJsDocTags(typeChecker).map(tag => ({
|
|
480
|
-
name: tag.name,
|
|
481
|
-
text: tag.text !== undefined ? ts.displayPartsToString(tag.text) : undefined,
|
|
482
|
-
})),
|
|
483
|
-
required: !(prop.flags & ts.SymbolFlags.Optional),
|
|
484
|
-
type: getFullyQualifiedName(subtype),
|
|
485
|
-
get declarations() {
|
|
486
|
-
return declarations ??= getDeclarations(prop.declarations ?? []);
|
|
487
|
-
},
|
|
488
|
-
get schema() {
|
|
489
|
-
return schema ??= resolveSchema(subtype);
|
|
490
|
-
},
|
|
491
|
-
rawType: rawType ? subtype : undefined,
|
|
492
|
-
getTypeObject() {
|
|
493
|
-
return subtype;
|
|
494
|
-
},
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
function resolveSlotProperties(prop) {
|
|
498
|
-
const propType = typeChecker.getNonNullableType(typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode));
|
|
499
|
-
const signatures = propType.getCallSignatures();
|
|
500
|
-
const paramType = signatures[0]?.parameters[0];
|
|
501
|
-
const subtype = paramType ? typeChecker.getTypeOfSymbolAtLocation(paramType, symbolNode) : typeChecker.getAnyType();
|
|
502
|
-
let schema;
|
|
503
|
-
let declarations;
|
|
504
|
-
return {
|
|
505
|
-
name: prop.getName(),
|
|
506
|
-
type: getFullyQualifiedName(subtype),
|
|
507
|
-
description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
|
|
508
|
-
get declarations() {
|
|
509
|
-
return declarations ??= getDeclarations(prop.declarations ?? []);
|
|
510
|
-
},
|
|
511
|
-
get schema() {
|
|
512
|
-
return schema ??= resolveSchema(subtype);
|
|
513
|
-
},
|
|
514
|
-
rawType: rawType ? subtype : undefined,
|
|
515
|
-
getTypeObject() {
|
|
516
|
-
return subtype;
|
|
517
|
-
},
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
|
-
function resolveExposedProperties(expose) {
|
|
521
|
-
const subtype = typeChecker.getTypeOfSymbolAtLocation(expose, symbolNode);
|
|
522
|
-
let schema;
|
|
523
|
-
let declarations;
|
|
524
|
-
return {
|
|
525
|
-
name: expose.getName(),
|
|
526
|
-
type: getFullyQualifiedName(subtype),
|
|
527
|
-
description: ts.displayPartsToString(expose.getDocumentationComment(typeChecker)),
|
|
528
|
-
get declarations() {
|
|
529
|
-
return declarations ??= getDeclarations(expose.declarations ?? []);
|
|
530
|
-
},
|
|
531
|
-
get schema() {
|
|
532
|
-
return schema ??= resolveSchema(subtype);
|
|
533
|
-
},
|
|
534
|
-
rawType: rawType ? subtype : undefined,
|
|
535
|
-
getTypeObject() {
|
|
536
|
-
return subtype;
|
|
537
|
-
},
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
function resolveEventSignature(call) {
|
|
541
|
-
let schema;
|
|
542
|
-
let declarations;
|
|
543
|
-
let subtype;
|
|
544
|
-
let symbol;
|
|
545
|
-
let subtypeStr = '[]';
|
|
546
|
-
let getSchema = () => [];
|
|
547
|
-
if (call.parameters.length >= 2) {
|
|
548
|
-
symbol = call.parameters[1];
|
|
549
|
-
subtype = typeChecker.getTypeOfSymbolAtLocation(symbol, symbolNode);
|
|
550
|
-
if (call.parameters[1].valueDeclaration?.dotDotDotToken) {
|
|
551
|
-
subtypeStr = getFullyQualifiedName(subtype);
|
|
552
|
-
getSchema = () => typeChecker.getTypeArguments(subtype).map(resolveSchema);
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
subtypeStr = '[';
|
|
556
|
-
for (let i = 1; i < call.parameters.length; i++) {
|
|
557
|
-
subtypeStr += getFullyQualifiedName(typeChecker.getTypeOfSymbolAtLocation(call.parameters[i], symbolNode))
|
|
558
|
-
+ ', ';
|
|
559
|
-
}
|
|
560
|
-
subtypeStr = subtypeStr.slice(0, -2) + ']';
|
|
561
|
-
getSchema = () => {
|
|
562
|
-
const result = [];
|
|
563
|
-
for (let i = 1; i < call.parameters.length; i++) {
|
|
564
|
-
result.push(resolveSchema(typeChecker.getTypeOfSymbolAtLocation(call.parameters[i], symbolNode)));
|
|
565
|
-
}
|
|
566
|
-
return result;
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
return {
|
|
571
|
-
name: typeChecker.getTypeOfSymbolAtLocation(call.parameters[0], symbolNode).value,
|
|
572
|
-
description: ts.displayPartsToString(call.getDocumentationComment(typeChecker)),
|
|
573
|
-
tags: call.getJsDocTags().map(tag => ({
|
|
574
|
-
name: tag.name,
|
|
575
|
-
text: tag.text !== undefined ? ts.displayPartsToString(tag.text) : undefined,
|
|
576
|
-
})),
|
|
577
|
-
type: subtypeStr,
|
|
578
|
-
signature: typeChecker.signatureToString(call),
|
|
579
|
-
get declarations() {
|
|
580
|
-
return declarations ??= call.declaration ? getDeclarations([call.declaration]) : [];
|
|
581
|
-
},
|
|
582
|
-
get schema() {
|
|
583
|
-
return schema ??= getSchema();
|
|
584
|
-
},
|
|
585
|
-
rawType: rawType ? subtype : undefined,
|
|
586
|
-
getTypeObject() {
|
|
587
|
-
return subtype;
|
|
588
|
-
},
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
function resolveCallbackSchema(signature) {
|
|
592
|
-
let schema;
|
|
593
|
-
return {
|
|
594
|
-
kind: 'event',
|
|
595
|
-
type: typeChecker.signatureToString(signature),
|
|
596
|
-
get schema() {
|
|
597
|
-
return schema ??= signature.parameters.length
|
|
598
|
-
? typeChecker
|
|
599
|
-
.getTypeArguments(typeChecker.getTypeOfSymbolAtLocation(signature.parameters[0], symbolNode))
|
|
600
|
-
.map(resolveSchema)
|
|
601
|
-
: undefined;
|
|
602
|
-
},
|
|
603
|
-
};
|
|
604
|
-
}
|
|
605
|
-
function resolveSchema(subtype) {
|
|
606
|
-
const type = getFullyQualifiedName(subtype);
|
|
607
|
-
if (shouldIgnore(subtype)) {
|
|
608
|
-
return type;
|
|
609
|
-
}
|
|
610
|
-
visited.add(subtype);
|
|
611
|
-
if (subtype.isUnion()) {
|
|
612
|
-
let schema;
|
|
613
|
-
return {
|
|
614
|
-
kind: 'enum',
|
|
615
|
-
type,
|
|
616
|
-
get schema() {
|
|
617
|
-
return schema ??= subtype.types.map(resolveSchema);
|
|
618
|
-
},
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
else if (typeChecker.isArrayLikeType(subtype)) {
|
|
622
|
-
let schema;
|
|
623
|
-
return {
|
|
624
|
-
kind: 'array',
|
|
625
|
-
type,
|
|
626
|
-
get schema() {
|
|
627
|
-
return schema ??= typeChecker.getTypeArguments(subtype).map(resolveSchema);
|
|
628
|
-
},
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
else if (subtype.getCallSignatures().length === 0
|
|
632
|
-
&& (subtype.isClassOrInterface() || subtype.isIntersection()
|
|
633
|
-
|| subtype.objectFlags & ts.ObjectFlags.Anonymous)) {
|
|
634
|
-
let schema;
|
|
635
|
-
return {
|
|
636
|
-
kind: 'object',
|
|
637
|
-
type,
|
|
638
|
-
get schema() {
|
|
639
|
-
return schema ??= subtype.getProperties().map(resolveNestedProperties).reduce(reducer, {});
|
|
640
|
-
},
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
else if (subtype.getCallSignatures().length === 1) {
|
|
644
|
-
return resolveCallbackSchema(subtype.getCallSignatures()[0]);
|
|
645
|
-
}
|
|
646
|
-
return type;
|
|
647
|
-
}
|
|
648
|
-
function getFullyQualifiedName(type) {
|
|
649
|
-
const str = typeChecker.typeToString(type, undefined, ts.TypeFormatFlags.UseFullyQualifiedType | ts.TypeFormatFlags.NoTruncation);
|
|
650
|
-
if (str.includes('import(')) {
|
|
651
|
-
return str.replace(/import\(.*?\)\./g, '');
|
|
652
|
-
}
|
|
653
|
-
return str;
|
|
654
|
-
}
|
|
655
|
-
function getDeclarations(declaration) {
|
|
656
|
-
if (noDeclarations) {
|
|
657
|
-
return [];
|
|
658
|
-
}
|
|
659
|
-
return declaration.map(getDeclaration).filter(d => !!d);
|
|
660
|
-
}
|
|
661
|
-
function getDeclaration(declaration) {
|
|
662
|
-
const fileName = declaration.getSourceFile().fileName;
|
|
663
|
-
const sourceScript = language.scripts.get(fileName);
|
|
664
|
-
if (sourceScript?.generated) {
|
|
665
|
-
const script = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
666
|
-
if (script) {
|
|
667
|
-
for (const [sourceScript, map] of language.maps.forEach(script.code)) {
|
|
668
|
-
for (const [start] of map.toSourceLocation(declaration.getStart())) {
|
|
669
|
-
for (const [end] of map.toSourceLocation(declaration.getEnd())) {
|
|
670
|
-
return {
|
|
671
|
-
file: sourceScript.id,
|
|
672
|
-
range: [start, end],
|
|
673
|
-
};
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
return undefined;
|
|
679
|
-
}
|
|
680
|
-
return {
|
|
681
|
-
file: declaration.getSourceFile().fileName,
|
|
682
|
-
range: [declaration.getStart(), declaration.getEnd()],
|
|
683
|
-
};
|
|
684
|
-
}
|
|
685
|
-
return {
|
|
686
|
-
resolveNestedProperties,
|
|
687
|
-
resolveSlotProperties,
|
|
688
|
-
resolveEventSignature,
|
|
689
|
-
resolveExposedProperties,
|
|
690
|
-
resolveSchema,
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
function readVueComponentDefaultProps(root, printer, ts) {
|
|
694
|
-
let result = {};
|
|
695
|
-
const { sfc } = root;
|
|
696
|
-
scriptSetupWorker();
|
|
697
|
-
scriptWorker();
|
|
698
|
-
return result;
|
|
699
|
-
function scriptSetupWorker() {
|
|
700
|
-
if (!sfc.scriptSetup) {
|
|
701
|
-
return;
|
|
702
|
-
}
|
|
703
|
-
const { ast } = sfc.scriptSetup;
|
|
704
|
-
const codegen = core.tsCodegen.get(sfc);
|
|
705
|
-
const scriptSetupRanges = codegen?.getScriptSetupRanges();
|
|
706
|
-
if (scriptSetupRanges?.withDefaults?.argNode) {
|
|
707
|
-
const obj = findObjectLiteralExpression(scriptSetupRanges.withDefaults.argNode);
|
|
708
|
-
if (obj) {
|
|
709
|
-
for (const prop of obj.properties) {
|
|
710
|
-
if (ts.isPropertyAssignment(prop)) {
|
|
711
|
-
const name = prop.name.getText(ast);
|
|
712
|
-
const expNode = resolveDefaultOptionExpression(prop.initializer, ts);
|
|
713
|
-
const expText = printer?.printNode(ts.EmitHint.Expression, expNode, ast) ?? expNode.getText(ast);
|
|
714
|
-
result[name] = {
|
|
715
|
-
default: expText,
|
|
716
|
-
};
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
else if (scriptSetupRanges?.defineProps?.argNode) {
|
|
722
|
-
const obj = findObjectLiteralExpression(scriptSetupRanges.defineProps.argNode);
|
|
723
|
-
if (obj) {
|
|
724
|
-
result = {
|
|
725
|
-
...result,
|
|
726
|
-
...resolvePropsOption(ast, obj, printer, ts),
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
else if (scriptSetupRanges?.defineProps?.destructured) {
|
|
731
|
-
for (const [name, initializer] of scriptSetupRanges.defineProps.destructured) {
|
|
732
|
-
if (initializer) {
|
|
733
|
-
const expText = printer?.printNode(ts.EmitHint.Expression, initializer, ast) ?? initializer.getText(ast);
|
|
734
|
-
result[name] = {
|
|
735
|
-
default: expText,
|
|
736
|
-
};
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
if (scriptSetupRanges?.defineModel) {
|
|
741
|
-
for (const defineModel of scriptSetupRanges.defineModel) {
|
|
742
|
-
const obj = defineModel.argNode ? findObjectLiteralExpression(defineModel.argNode) : undefined;
|
|
743
|
-
if (obj) {
|
|
744
|
-
const name = defineModel.name
|
|
745
|
-
? sfc.scriptSetup.content.slice(defineModel.name.start, defineModel.name.end).slice(1, -1)
|
|
746
|
-
: 'modelValue';
|
|
747
|
-
result[name] = resolveModelOption(ast, obj, printer, ts);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
function findObjectLiteralExpression(node) {
|
|
752
|
-
if (ts.isObjectLiteralExpression(node)) {
|
|
753
|
-
return node;
|
|
754
|
-
}
|
|
755
|
-
let result;
|
|
756
|
-
node.forEachChild(child => {
|
|
757
|
-
if (!result) {
|
|
758
|
-
result = findObjectLiteralExpression(child);
|
|
759
|
-
}
|
|
760
|
-
});
|
|
761
|
-
return result;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
function scriptWorker() {
|
|
765
|
-
if (!sfc.script) {
|
|
766
|
-
return;
|
|
767
|
-
}
|
|
768
|
-
const { ast } = sfc.script;
|
|
769
|
-
const scriptResult = readTsComponentDefaultProps(ast, 'default', printer, ts);
|
|
770
|
-
for (const [key, value] of Object.entries(scriptResult)) {
|
|
771
|
-
result[key] = value;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
function readTsComponentDefaultProps(ast, exportName, printer, ts) {
|
|
776
|
-
const props = getPropsNode();
|
|
777
|
-
if (props) {
|
|
778
|
-
return resolvePropsOption(ast, props, printer, ts);
|
|
779
|
-
}
|
|
780
|
-
return {};
|
|
781
|
-
function getComponentNode() {
|
|
782
|
-
return getComponentNodeFromAst(ast, exportName, ts);
|
|
783
|
-
}
|
|
784
|
-
function getComponentOptionsNode() {
|
|
785
|
-
const component = getComponentNode();
|
|
786
|
-
return getComponentOptionsNodeFromComponent(component, ts);
|
|
787
|
-
}
|
|
788
|
-
function getPropsNode() {
|
|
789
|
-
const options = getComponentOptionsNode();
|
|
790
|
-
const props = options?.properties.find(prop => prop.name?.getText(ast) === 'props');
|
|
791
|
-
if (props && ts.isPropertyAssignment(props)) {
|
|
792
|
-
if (ts.isObjectLiteralExpression(props.initializer)) {
|
|
793
|
-
return props.initializer;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
function resolvePropsOption(ast, props, printer, ts) {
|
|
799
|
-
const result = {};
|
|
800
|
-
for (const prop of props.properties) {
|
|
801
|
-
if (ts.isPropertyAssignment(prop)) {
|
|
802
|
-
const name = prop.name.getText(ast);
|
|
803
|
-
if (ts.isObjectLiteralExpression(prop.initializer)) {
|
|
804
|
-
const defaultProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'default');
|
|
805
|
-
const requiredProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'required');
|
|
806
|
-
result[name] = {};
|
|
807
|
-
if (requiredProp) {
|
|
808
|
-
const exp = requiredProp.initializer.getText(ast);
|
|
809
|
-
result[name].required = exp === 'true';
|
|
810
|
-
}
|
|
811
|
-
if (defaultProp) {
|
|
812
|
-
const expNode = resolveDefaultOptionExpression(defaultProp.initializer, ts);
|
|
813
|
-
const expText = printer?.printNode(ts.EmitHint.Expression, expNode, ast) ?? expNode.getText(ast);
|
|
814
|
-
result[name].default = expText;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
return result;
|
|
820
|
-
}
|
|
821
|
-
function resolveModelOption(ast, options, printer, ts) {
|
|
822
|
-
const result = {};
|
|
823
|
-
for (const prop of options.properties) {
|
|
824
|
-
if (ts.isPropertyAssignment(prop)) {
|
|
825
|
-
const name = prop.name.getText(ast);
|
|
826
|
-
if (name === 'default') {
|
|
827
|
-
const expNode = resolveDefaultOptionExpression(prop.initializer, ts);
|
|
828
|
-
const expText = printer?.printNode(ts.EmitHint.Expression, expNode, ast) ?? expNode.getText(ast);
|
|
829
|
-
result.default = expText;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
return result;
|
|
834
|
-
}
|
|
835
|
-
function resolveDefaultOptionExpression(_default, ts) {
|
|
836
|
-
if (ts.isArrowFunction(_default)) {
|
|
837
|
-
if (ts.isBlock(_default.body)) {
|
|
838
|
-
return _default; // TODO
|
|
839
|
-
}
|
|
840
|
-
else if (ts.isParenthesizedExpression(_default.body)) {
|
|
841
|
-
return _default.body.expression;
|
|
842
|
-
}
|
|
843
|
-
else {
|
|
844
|
-
return _default.body;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
return _default;
|
|
848
|
-
}
|
|
849
|
-
function readComponentName(ast, exportName, ts) {
|
|
850
|
-
const componentNode = getComponentNodeFromAst(ast, exportName, ts);
|
|
851
|
-
const optionsNode = getComponentOptionsNodeFromComponent(componentNode, ts);
|
|
852
|
-
if (optionsNode) {
|
|
853
|
-
const nameProp = optionsNode.properties.find(prop => ts.isPropertyAssignment(prop) && prop.name?.getText(ast) === 'name');
|
|
854
|
-
if (nameProp && ts.isPropertyAssignment(nameProp) && ts.isStringLiteral(nameProp.initializer)) {
|
|
855
|
-
return nameProp.initializer.text;
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
return undefined;
|
|
859
|
-
}
|
|
860
|
-
function readComponentDescription(ast, exportName, ts, typeChecker) {
|
|
861
|
-
const exportNode = getExportNode();
|
|
862
|
-
if (exportNode) {
|
|
863
|
-
// Try to get JSDoc comments from the node using TypeScript API
|
|
864
|
-
const jsDocComments = ts.getJSDocCommentsAndTags(exportNode);
|
|
865
|
-
for (const jsDoc of jsDocComments) {
|
|
866
|
-
if (ts.isJSDoc(jsDoc) && jsDoc.comment) {
|
|
867
|
-
// Handle both string and array of comment parts
|
|
868
|
-
if (typeof jsDoc.comment === 'string') {
|
|
869
|
-
return jsDoc.comment;
|
|
870
|
-
}
|
|
871
|
-
else if (Array.isArray(jsDoc.comment)) {
|
|
872
|
-
return jsDoc.comment.map(part => part.text || '').join('');
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
// Fallback to symbol documentation
|
|
877
|
-
const symbol = typeChecker.getSymbolAtLocation(exportNode);
|
|
878
|
-
if (symbol) {
|
|
879
|
-
const description = ts.displayPartsToString(symbol.getDocumentationComment(typeChecker));
|
|
880
|
-
return description || undefined;
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
return undefined;
|
|
884
|
-
function getExportNode() {
|
|
885
|
-
let result;
|
|
886
|
-
if (exportName === 'default') {
|
|
887
|
-
ast.forEachChild(child => {
|
|
888
|
-
if (ts.isExportAssignment(child)) {
|
|
889
|
-
// Return the export assignment itself, not the expression
|
|
890
|
-
result = child;
|
|
891
|
-
}
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
else {
|
|
895
|
-
ast.forEachChild(child => {
|
|
896
|
-
if (ts.isVariableStatement(child)
|
|
897
|
-
&& child.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)) {
|
|
898
|
-
// Return the variable statement itself
|
|
899
|
-
result = child;
|
|
900
|
-
}
|
|
901
|
-
});
|
|
902
|
-
}
|
|
903
|
-
return result;
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
//# sourceMappingURL=base.js.map
|