vue-component-meta 0.39.2 → 0.39.5

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/out/index.d.ts CHANGED
@@ -1,53 +1,12 @@
1
- export declare type PropertyMeta = {
2
- name: string;
3
- default?: string;
4
- description: string;
5
- required: boolean;
6
- type: string;
7
- tags: {
8
- name: string;
9
- text?: string;
10
- }[];
11
- schema: PropertyMetaSchema;
12
- };
13
- export declare type PropertyMetaSchema = string | {
14
- kind: 'enum';
15
- type: string;
16
- schema: PropertyMetaSchema[];
17
- } | {
18
- kind: 'array';
19
- type: string;
20
- schema: PropertyMetaSchema[];
21
- } | {
22
- kind: 'event';
23
- type: string;
24
- schema: PropertyMetaSchema[];
25
- } | {
26
- kind: 'object';
27
- type: string;
28
- schema: Record<string, PropertyMeta>;
29
- };
30
- export declare function createComponentMetaChecker(tsconfigPath: string): {
31
- getGlobalPropNames: () => string[];
1
+ import * as ts from 'typescript/lib/tsserverlibrary';
2
+ import type { MetaCheckerOptions, ComponentMeta, EventMeta, ExposeMeta, MetaCheckerSchemaOptions, PropertyMeta, PropertyMetaSchema, SlotMeta } from './types';
3
+ export type { MetaCheckerOptions, ComponentMeta, EventMeta, ExposeMeta, MetaCheckerSchemaOptions, PropertyMeta, PropertyMetaSchema, SlotMeta };
4
+ export declare function createComponentMetaChecker(tsconfigPath: string, checkerOptions?: MetaCheckerOptions): {
32
5
  getExportNames: (componentPath: string) => string[];
33
- getComponentMeta: (componentPath: string, exportName?: string) => {
34
- props: PropertyMeta[];
35
- events: {
36
- name: string;
37
- type: string;
38
- signature: string;
39
- schema: PropertyMetaSchema[];
40
- }[];
41
- slots: {
42
- name: string;
43
- type: string;
44
- description: string;
45
- }[];
46
- exposed: {
47
- name: string;
48
- type: string;
49
- description: string;
50
- }[];
6
+ getComponentMeta: (componentPath: string, exportName?: string) => ComponentMeta;
7
+ __internal__: {
8
+ program: ts.Program;
9
+ tsLs: ts.LanguageService;
10
+ typeChecker: ts.TypeChecker;
51
11
  };
52
12
  };
53
- export declare function findCmponentDefaultProps(componentPath: string): Record<string, string>;
package/out/index.js CHANGED
@@ -1,83 +1,8 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findCmponentDefaultProps = exports.createComponentMetaChecker = void 0;
2
+ exports.createComponentMetaChecker = void 0;
4
3
  const vue = require("@volar/vue-language-core");
5
4
  const ts = require("typescript/lib/tsserverlibrary");
6
- function createSchemaResolvers(typeChecker, symbolNode) {
7
- function reducer(acc, cur) {
8
- acc[cur.name] = cur;
9
- return acc;
10
- }
11
- function resolveSymbolSchema(prop) {
12
- var _a, _b, _c;
13
- const subtype = typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode);
14
- typeChecker.getDefaultFromTypeParameter(subtype);
15
- return {
16
- name: prop.getEscapedName().toString(),
17
- description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
18
- tags: prop.getJsDocTags(typeChecker).map(tag => {
19
- var _a;
20
- return ({
21
- name: tag.name,
22
- text: (_a = tag.text) === null || _a === void 0 ? void 0 : _a.map(part => part.text).join(''),
23
- });
24
- }),
25
- required: !Boolean((_c = (_b = (_a = prop.declarations) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.questionToken) !== null && _c !== void 0 ? _c : false),
26
- type: typeChecker.typeToString(subtype),
27
- schema: resolveSchema(subtype),
28
- };
29
- }
30
- function resolveCallbackSchema(signature) {
31
- return {
32
- kind: 'event',
33
- type: typeChecker.signatureToString(signature),
34
- schema: typeChecker.getTypeArguments(typeChecker.getTypeOfSymbolAtLocation(signature.parameters[0], symbolNode)).map(resolveSchema)
35
- };
36
- }
37
- function resolveEventSchema(subtype) {
38
- return (subtype.getCallSignatures().length === 1)
39
- ? resolveCallbackSchema(subtype.getCallSignatures()[0])
40
- : typeChecker.typeToString(subtype);
41
- }
42
- function resolveNestedSchema(subtype) {
43
- // !!(subtype.flags & ts.TypeFlags.Object)
44
- return (subtype.isClassOrInterface() || subtype.isIntersection())
45
- ? {
46
- kind: 'object',
47
- type: typeChecker.typeToString(subtype),
48
- schema: subtype.getProperties().map(resolveSymbolSchema).reduce(reducer, {})
49
- }
50
- : resolveEventSchema(subtype);
51
- }
52
- function resolveArraySchema(subtype) {
53
- // @ts-ignore - typescript internal, isArrayLikeType exists
54
- return typeChecker.isArrayLikeType(subtype)
55
- ? {
56
- kind: 'array',
57
- type: typeChecker.typeToString(subtype),
58
- schema: typeChecker.getTypeArguments(subtype).map(resolveSchema)
59
- }
60
- : resolveNestedSchema(subtype);
61
- }
62
- function resolveSchema(subtype) {
63
- return subtype.isUnion()
64
- ? {
65
- kind: 'enum',
66
- type: typeChecker.typeToString(subtype),
67
- schema: subtype.types.map(resolveArraySchema)
68
- }
69
- : resolveArraySchema(subtype);
70
- }
71
- return {
72
- resolveSymbolSchema,
73
- resolveCallbackSchema,
74
- resolveEventSchema,
75
- resolveNestedSchema,
76
- resolveArraySchema,
77
- resolveSchema,
78
- };
79
- }
80
- function createComponentMetaChecker(tsconfigPath) {
5
+ function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
81
6
  const parsedCommandLine = vue.tsShared.createParsedCommandLine(ts, {
82
7
  useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
83
8
  readDirectory: (path, extensions, exclude, include, depth) => {
@@ -88,7 +13,7 @@ function createComponentMetaChecker(tsconfigPath) {
88
13
  }, tsconfigPath);
89
14
  const scriptSnapshot = {};
90
15
  const globalComponentName = tsconfigPath.replace(/\\/g, '/') + '.global.ts';
91
- const core = vue.createLanguageContext(Object.assign(Object.assign({}, ts.sys), { getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, getCompilationSettings: () => parsedCommandLine.options, getScriptFileNames: () => {
16
+ const host = Object.assign(Object.assign({}, ts.sys), { getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, getCompilationSettings: () => parsedCommandLine.options, getScriptFileNames: () => {
92
17
  return [
93
18
  ...parsedCommandLine.fileNames,
94
19
  ...parsedCommandLine.fileNames.map(getMetaFileName),
@@ -115,39 +40,48 @@ function createComponentMetaChecker(tsconfigPath) {
115
40
  }
116
41
  }
117
42
  return scriptSnapshot[fileName];
118
- }, getTypeScriptModule: () => ts, getVueCompilationSettings: () => parsedCommandLine.vueOptions }));
119
- const tsLs = ts.createLanguageService(core.typescriptLanguageServiceHost);
43
+ }, getTypeScriptModule: () => ts, getVueCompilationSettings: () => parsedCommandLine.vueOptions });
44
+ const core = vue.createLanguageContext(host);
45
+ const proxyApis = checkerOptions.forceUseTs ? {
46
+ getScriptKind: (fileName) => {
47
+ if (fileName.endsWith('.vue.js')) {
48
+ return ts.ScriptKind.TS;
49
+ }
50
+ if (fileName.endsWith('.vue.jsx')) {
51
+ return ts.ScriptKind.TSX;
52
+ }
53
+ return core.typescriptLanguageServiceHost.getScriptKind(fileName);
54
+ },
55
+ } : {};
56
+ const proxyHost = new Proxy(core.typescriptLanguageServiceHost, {
57
+ get(target, propKey) {
58
+ if (propKey in proxyApis) {
59
+ return proxyApis[propKey];
60
+ }
61
+ return target[propKey];
62
+ }
63
+ });
64
+ const tsLs = ts.createLanguageService(proxyHost);
120
65
  const program = tsLs.getProgram();
121
66
  const typeChecker = program.getTypeChecker();
67
+ let globalPropNames = [];
68
+ globalPropNames = getComponentMeta(globalComponentName).props.map(prop => prop.name);
122
69
  return {
123
- getGlobalPropNames,
124
70
  getExportNames,
125
71
  getComponentMeta,
72
+ __internal__: {
73
+ program,
74
+ tsLs,
75
+ typeChecker,
76
+ },
126
77
  };
127
- /**
128
- * Get helper array to map internal properties added by vue to any components
129
- *
130
- * @example
131
- * ```ts
132
- * import { createComponentMetaChecker } from 'vue-component-meta'
133
- *
134
- * const checker = createComponentMetaChecker('path/to/tsconfig.json')
135
- * const meta = checker.getComponentMeta('path/to/component.vue')
136
- * const globalPropNames = checker.getGlobalPropNames();
137
- * const props = meta.props.filter(prop => !globalPropNames.includes(prop.name))
138
- * ```
139
- */
140
- function getGlobalPropNames() {
141
- const meta = getComponentMeta(globalComponentName);
142
- return meta.props.map(prop => prop.name);
143
- }
144
78
  function getMetaFileName(fileName) {
145
79
  return (fileName.endsWith('.vue') ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + '.meta.ts';
146
80
  }
147
81
  function getMetaScriptContent(fileName) {
148
82
  return `
149
83
  import * as Components from '${fileName.substring(0, fileName.length - '.meta.ts'.length)}';
150
- export default {} as { [K in keyof typeof Components]: InstanceType<typeof Components[K]>; };;
84
+ export default {} as { [K in keyof typeof Components]: InstanceType<typeof Components[K]>; };
151
85
  `;
152
86
  }
153
87
  function getExportNames(componentPath) {
@@ -170,20 +104,39 @@ function createComponentMetaChecker(tsconfigPath) {
170
104
  };
171
105
  function getProps() {
172
106
  const $props = symbolProperties.find(prop => prop.escapedName === '$props');
107
+ const propEventRegex = /^(on[A-Z])/;
173
108
  let result = [];
174
109
  if ($props) {
175
110
  const type = typeChecker.getTypeOfSymbolAtLocation($props, symbolNode);
176
- const properties = type.getApparentProperties();
177
- const { resolveSymbolSchema } = createSchemaResolvers(typeChecker, symbolNode);
178
- result = properties.map(resolveSymbolSchema);
111
+ const properties = type.getProperties();
112
+ result = properties
113
+ .map((prop) => {
114
+ const { resolveNestedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
115
+ return resolveNestedProperties(prop);
116
+ })
117
+ .filter((prop) => !prop.name.match(propEventRegex));
118
+ }
119
+ // fill global
120
+ for (const prop of result) {
121
+ prop.global = globalPropNames.includes(prop.name);
179
122
  }
180
123
  // fill defaults
181
- if (componentPath.endsWith('.vue') && exportName === 'default') {
182
- const defaults = findCmponentDefaultProps(componentPath);
183
- for (const propName in defaults) {
184
- const prop = result.find(p => p.name === propName);
185
- if (prop) {
186
- prop.default = defaults[propName];
124
+ const printer = checkerOptions.printer ? ts.createPrinter(checkerOptions.printer) : undefined;
125
+ const snapshot = host.getScriptSnapshot(componentPath);
126
+ const vueDefaults = componentPath.endsWith('.vue') && exportName === 'default'
127
+ ? readVueComponentDefaultProps(snapshot.getText(0, snapshot.getLength()), printer)
128
+ : {};
129
+ const tsDefaults = !componentPath.endsWith('.vue') ? readTsComponentDefaultProps(componentPath.substring(componentPath.lastIndexOf('.') + 1), // ts | js | tsx | jsx
130
+ snapshot.getText(0, snapshot.getLength()), exportName, printer) : {};
131
+ for (const [propName, defaultExp] of Object.entries(Object.assign(Object.assign({}, vueDefaults), tsDefaults))) {
132
+ const prop = result.find(p => p.name === propName);
133
+ if (prop) {
134
+ prop.default = defaultExp.default;
135
+ if (defaultExp.required !== undefined) {
136
+ prop.required = defaultExp.required;
137
+ }
138
+ if (prop.default !== undefined) {
139
+ prop.required = false; // props with default are always optional
187
140
  }
188
141
  }
189
142
  }
@@ -194,13 +147,10 @@ function createComponentMetaChecker(tsconfigPath) {
194
147
  if ($emit) {
195
148
  const type = typeChecker.getTypeOfSymbolAtLocation($emit, symbolNode);
196
149
  const calls = type.getCallSignatures();
197
- const { resolveSchema } = createSchemaResolvers(typeChecker, symbolNode);
198
- return calls.map(call => ({
199
- name: typeChecker.getTypeOfSymbolAtLocation(call.parameters[0], symbolNode).value,
200
- type: typeChecker.typeToString(typeChecker.getTypeOfSymbolAtLocation(call.parameters[1], symbolNode)),
201
- signature: typeChecker.signatureToString(call),
202
- schema: typeChecker.getTypeArguments(typeChecker.getTypeOfSymbolAtLocation(call.parameters[1], symbolNode)).map(resolveSchema),
203
- }));
150
+ return calls.map((call) => {
151
+ const { resolveEventSignature, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
152
+ return resolveEventSignature(call);
153
+ }).filter(event => event.name);
204
154
  }
205
155
  return [];
206
156
  }
@@ -211,11 +161,10 @@ function createComponentMetaChecker(tsconfigPath) {
211
161
  if ($slots) {
212
162
  const type = typeChecker.getTypeOfSymbolAtLocation($slots, symbolNode);
213
163
  const properties = type.getProperties();
214
- return properties.map(prop => ({
215
- name: prop.getName(),
216
- type: typeChecker.typeToString(typeChecker.getTypeOfSymbolAtLocation(typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode).getCallSignatures()[0].parameters[0], symbolNode)),
217
- description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
218
- }));
164
+ return properties.map((prop) => {
165
+ const { resolveSlotProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
166
+ return resolveSlotProperties(prop);
167
+ });
219
168
  }
220
169
  return [];
221
170
  }
@@ -224,11 +173,10 @@ function createComponentMetaChecker(tsconfigPath) {
224
173
  // only exposed props will have a syntheticOrigin
225
174
  Boolean(prop.syntheticOrigin));
226
175
  if (exposed.length) {
227
- return exposed.map(expose => ({
228
- name: expose.getName(),
229
- type: typeChecker.typeToString(typeChecker.getTypeOfSymbolAtLocation(expose, symbolNode)),
230
- description: ts.displayPartsToString(expose.getDocumentationComment(typeChecker)),
231
- }));
176
+ return exposed.map((prop) => {
177
+ const { resolveExposedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
178
+ return resolveExposedProperties(prop);
179
+ });
232
180
  }
233
181
  return [];
234
182
  }
@@ -263,28 +211,175 @@ function createComponentMetaChecker(tsconfigPath) {
263
211
  }
264
212
  }
265
213
  exports.createComponentMetaChecker = createComponentMetaChecker;
266
- function findCmponentDefaultProps(componentPath) {
267
- const fileText = ts.sys.readFile(componentPath);
268
- if (fileText === undefined) {
269
- throw new Error(`${componentPath} not found`);
214
+ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: options }) {
215
+ var _a;
216
+ const enabled = !!options;
217
+ const ignore = typeof options === 'object' ? [...(_a = options === null || options === void 0 ? void 0 : options.ignore) !== null && _a !== void 0 ? _a : []] : [];
218
+ function shouldIgnore(subtype) {
219
+ const type = typeChecker.typeToString(subtype);
220
+ if (type === 'any') {
221
+ return true;
222
+ }
223
+ if (ignore.length === 0) {
224
+ return false;
225
+ }
226
+ return ignore.includes(type);
270
227
  }
271
- const vueSourceFile = vue.createSourceFile(componentPath, fileText, {}, {}, ts);
272
- const descriptor = vueSourceFile.getDescriptor();
273
- const scriptSetupRanges = vueSourceFile.getScriptSetupRanges();
274
- const result = {};
275
- if (descriptor.scriptSetup && (scriptSetupRanges === null || scriptSetupRanges === void 0 ? void 0 : scriptSetupRanges.withDefaultsArg)) {
276
- const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.withDefaultsArg.start, scriptSetupRanges.withDefaultsArg.end);
277
- const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
278
- const obj = findObjectLiteralExpression(ast);
279
- if (obj) {
280
- for (const prop of obj.properties) {
281
- if (ts.isPropertyAssignment(prop)) {
282
- const name = prop.name.getText(ast);
283
- const exp = prop.initializer.getText(ast);
284
- result[name] = exp;
228
+ function setVisited(subtype) {
229
+ const type = typeChecker.typeToString(subtype);
230
+ ignore.push(type);
231
+ }
232
+ function reducer(acc, cur) {
233
+ acc[cur.name] = cur;
234
+ return acc;
235
+ }
236
+ function resolveNestedProperties(prop) {
237
+ var _a, _b, _c;
238
+ const subtype = typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode);
239
+ const schema = enabled ? resolveSchema(subtype) : undefined;
240
+ return {
241
+ name: prop.getEscapedName().toString(),
242
+ global: false,
243
+ description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
244
+ tags: prop.getJsDocTags(typeChecker).map(tag => {
245
+ var _a;
246
+ return ({
247
+ name: tag.name,
248
+ text: (_a = tag.text) === null || _a === void 0 ? void 0 : _a.map(part => part.text).join(''),
249
+ });
250
+ }),
251
+ required: !Boolean((_c = (_b = (_a = prop.declarations) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.questionToken) !== null && _c !== void 0 ? _c : false),
252
+ type: typeChecker.typeToString(subtype),
253
+ rawType: rawType ? subtype : undefined,
254
+ schema,
255
+ };
256
+ }
257
+ function resolveSlotProperties(prop) {
258
+ const subtype = typeChecker.getTypeOfSymbolAtLocation(typeChecker.getTypeOfSymbolAtLocation(prop, symbolNode).getCallSignatures()[0].parameters[0], symbolNode);
259
+ const schema = enabled ? resolveSchema(subtype) : undefined;
260
+ return {
261
+ name: prop.getName(),
262
+ type: typeChecker.typeToString(subtype),
263
+ rawType: rawType ? subtype : undefined,
264
+ description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
265
+ schema,
266
+ };
267
+ }
268
+ function resolveExposedProperties(expose) {
269
+ const subtype = typeChecker.getTypeOfSymbolAtLocation(expose, symbolNode);
270
+ const schema = enabled ? resolveSchema(subtype) : undefined;
271
+ return {
272
+ name: expose.getName(),
273
+ type: typeChecker.typeToString(subtype),
274
+ rawType: rawType ? subtype : undefined,
275
+ description: ts.displayPartsToString(expose.getDocumentationComment(typeChecker)),
276
+ schema,
277
+ };
278
+ }
279
+ function resolveEventSignature(call) {
280
+ const subtype = typeChecker.getTypeOfSymbolAtLocation(call.parameters[1], symbolNode);
281
+ const schema = enabled
282
+ ? typeChecker.getTypeArguments(subtype).map(resolveSchema)
283
+ : undefined;
284
+ return {
285
+ name: typeChecker.getTypeOfSymbolAtLocation(call.parameters[0], symbolNode).value,
286
+ type: typeChecker.typeToString(subtype),
287
+ rawType: rawType ? subtype : undefined,
288
+ signature: typeChecker.signatureToString(call),
289
+ schema,
290
+ };
291
+ }
292
+ function resolveCallbackSchema(signature) {
293
+ const schema = enabled && signature.parameters.length > 0
294
+ ? typeChecker
295
+ .getTypeArguments(typeChecker.getTypeOfSymbolAtLocation(signature.parameters[0], symbolNode))
296
+ .map(resolveSchema)
297
+ : undefined;
298
+ return {
299
+ kind: 'event',
300
+ type: typeChecker.signatureToString(signature),
301
+ schema,
302
+ };
303
+ }
304
+ function resolveSchema(subtype) {
305
+ const type = typeChecker.typeToString(subtype);
306
+ let schema = type;
307
+ if (shouldIgnore(subtype)) {
308
+ return type;
309
+ }
310
+ setVisited(subtype);
311
+ if (subtype.isUnion()) {
312
+ schema = {
313
+ kind: 'enum',
314
+ type,
315
+ schema: subtype.types.map(resolveSchema)
316
+ };
317
+ }
318
+ // @ts-ignore - typescript internal, isArrayLikeType exists
319
+ else if (typeChecker.isArrayLikeType(subtype)) {
320
+ schema = {
321
+ kind: 'array',
322
+ type,
323
+ schema: typeChecker.getTypeArguments(subtype).map(resolveSchema)
324
+ };
325
+ }
326
+ else if (subtype.getCallSignatures().length === 0 &&
327
+ (subtype.isClassOrInterface() || subtype.isIntersection() || subtype.objectFlags & ts.ObjectFlags.Anonymous)) {
328
+ // setVisited(subtype);
329
+ schema = {
330
+ kind: 'object',
331
+ type,
332
+ schema: subtype.getProperties().map(resolveNestedProperties).reduce(reducer, {})
333
+ };
334
+ }
335
+ else if (subtype.getCallSignatures().length === 1) {
336
+ schema = resolveCallbackSchema(subtype.getCallSignatures()[0]);
337
+ }
338
+ return schema;
339
+ }
340
+ return {
341
+ resolveNestedProperties,
342
+ resolveSlotProperties,
343
+ resolveEventSignature,
344
+ resolveExposedProperties,
345
+ resolveSchema,
346
+ };
347
+ }
348
+ function readVueComponentDefaultProps(vueFileText, printer) {
349
+ let result = {};
350
+ scriptSetupWorker();
351
+ scriptWorker();
352
+ return result;
353
+ function scriptSetupWorker() {
354
+ var _a;
355
+ const vueSourceFile = vue.createSourceFile('/tmp.vue', vueFileText, {}, {}, ts);
356
+ const descriptor = vueSourceFile.getDescriptor();
357
+ const scriptSetupRanges = vueSourceFile.getScriptSetupRanges();
358
+ if (descriptor.scriptSetup && (scriptSetupRanges === null || scriptSetupRanges === void 0 ? void 0 : scriptSetupRanges.withDefaultsArg)) {
359
+ const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.withDefaultsArg.start, scriptSetupRanges.withDefaultsArg.end);
360
+ const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
361
+ const obj = findObjectLiteralExpression(ast);
362
+ if (obj) {
363
+ for (const prop of obj.properties) {
364
+ if (ts.isPropertyAssignment(prop)) {
365
+ const name = prop.name.getText(ast);
366
+ const expNode = resolveDefaultOptionExpression(prop.initializer);
367
+ const expText = (_a = printer === null || printer === void 0 ? void 0 : printer.printNode(ts.EmitHint.Expression, expNode, ast)) !== null && _a !== void 0 ? _a : expNode.getText(ast);
368
+ result[name] = {
369
+ default: expText,
370
+ };
371
+ }
285
372
  }
286
373
  }
287
374
  }
375
+ else if (descriptor.scriptSetup && (scriptSetupRanges === null || scriptSetupRanges === void 0 ? void 0 : scriptSetupRanges.propsRuntimeArg)) {
376
+ const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.propsRuntimeArg.start, scriptSetupRanges.propsRuntimeArg.end);
377
+ const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
378
+ const obj = findObjectLiteralExpression(ast);
379
+ if (obj) {
380
+ result = Object.assign(Object.assign({}, result), resolvePropsOption(ast, obj, printer));
381
+ }
382
+ }
288
383
  function findObjectLiteralExpression(node) {
289
384
  if (ts.isObjectLiteralExpression(node)) {
290
385
  return node;
@@ -298,7 +393,113 @@ function findCmponentDefaultProps(componentPath) {
298
393
  return result;
299
394
  }
300
395
  }
396
+ function scriptWorker() {
397
+ const vueSourceFile = vue.createSourceFile('/tmp.vue', vueFileText, {}, {}, ts);
398
+ const descriptor = vueSourceFile.getDescriptor();
399
+ if (descriptor.script) {
400
+ const scriptResult = readTsComponentDefaultProps(descriptor.script.lang, descriptor.script.content, 'default', printer);
401
+ for (const [key, value] of Object.entries(scriptResult)) {
402
+ result[key] = value;
403
+ }
404
+ }
405
+ }
406
+ }
407
+ function readTsComponentDefaultProps(lang, tsFileText, exportName, printer) {
408
+ const ast = ts.createSourceFile('/tmp.' + lang, tsFileText, ts.ScriptTarget.Latest);
409
+ const props = getPropsNode();
410
+ if (props) {
411
+ return resolvePropsOption(ast, props, printer);
412
+ }
413
+ return {};
414
+ function getComponentNode() {
415
+ let result;
416
+ if (exportName === 'default') {
417
+ ast.forEachChild(child => {
418
+ if (ts.isExportAssignment(child)) {
419
+ result = child.expression;
420
+ }
421
+ });
422
+ }
423
+ else {
424
+ ast.forEachChild(child => {
425
+ var _a;
426
+ if (ts.isVariableStatement(child)
427
+ && ((_a = child.modifiers) === null || _a === void 0 ? void 0 : _a.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword))) {
428
+ for (const dec of child.declarationList.declarations) {
429
+ if (dec.name.getText(ast) === exportName) {
430
+ result = dec.initializer;
431
+ }
432
+ }
433
+ }
434
+ });
435
+ }
436
+ return result;
437
+ }
438
+ function getComponentOptionsNode() {
439
+ const component = getComponentNode();
440
+ if (component) {
441
+ // export default { ... }
442
+ if (ts.isObjectLiteralExpression(component)) {
443
+ return component;
444
+ }
445
+ // export default defineComponent({ ... })
446
+ // export default Vue.extend({ ... })
447
+ else if (ts.isCallExpression(component)) {
448
+ if (component.arguments.length) {
449
+ const arg = component.arguments[0];
450
+ if (ts.isObjectLiteralExpression(arg)) {
451
+ return arg;
452
+ }
453
+ }
454
+ }
455
+ }
456
+ }
457
+ function getPropsNode() {
458
+ const options = getComponentOptionsNode();
459
+ const props = options === null || options === void 0 ? void 0 : options.properties.find(prop => { var _a; return ((_a = prop.name) === null || _a === void 0 ? void 0 : _a.getText(ast)) === 'props'; });
460
+ if (props && ts.isPropertyAssignment(props)) {
461
+ if (ts.isObjectLiteralExpression(props.initializer)) {
462
+ return props.initializer;
463
+ }
464
+ }
465
+ }
466
+ }
467
+ function resolvePropsOption(ast, props, printer) {
468
+ var _a, _b;
469
+ const result = {};
470
+ for (const prop of props.properties) {
471
+ if (ts.isPropertyAssignment(prop)) {
472
+ const name = (_a = prop.name) === null || _a === void 0 ? void 0 : _a.getText(ast);
473
+ if (ts.isObjectLiteralExpression(prop.initializer)) {
474
+ const defaultProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'default');
475
+ const requiredProp = prop.initializer.properties.find(p => ts.isPropertyAssignment(p) && p.name.getText(ast) === 'required');
476
+ result[name] = {};
477
+ if (requiredProp) {
478
+ const exp = requiredProp.initializer.getText(ast);
479
+ result[name].required = exp === 'true';
480
+ }
481
+ if (defaultProp) {
482
+ const expNode = resolveDefaultOptionExpression(defaultProp.initializer);
483
+ const expText = (_b = printer === null || printer === void 0 ? void 0 : printer.printNode(ts.EmitHint.Expression, expNode, ast)) !== null && _b !== void 0 ? _b : expNode.getText(ast);
484
+ result[name].default = expText;
485
+ }
486
+ }
487
+ }
488
+ }
301
489
  return result;
302
490
  }
303
- exports.findCmponentDefaultProps = findCmponentDefaultProps;
491
+ function resolveDefaultOptionExpression(_default) {
492
+ if (ts.isArrowFunction(_default)) {
493
+ if (ts.isBlock(_default.body)) {
494
+ return _default; // TODO
495
+ }
496
+ else if (ts.isParenthesizedExpression(_default.body)) {
497
+ return _default.body.expression;
498
+ }
499
+ else {
500
+ return _default.body;
501
+ }
502
+ }
503
+ return _default;
504
+ }
304
505
  //# sourceMappingURL=index.js.map
package/out/types.d.ts ADDED
@@ -0,0 +1,67 @@
1
+ export interface ComponentMeta {
2
+ props: PropertyMeta[];
3
+ events: EventMeta[];
4
+ slots: SlotMeta[];
5
+ exposed: ExposeMeta[];
6
+ }
7
+ export interface PropertyMeta {
8
+ name: string;
9
+ default?: string;
10
+ description: string;
11
+ global: boolean;
12
+ required: boolean;
13
+ type: string;
14
+ rawType?: ts.Type;
15
+ tags: {
16
+ name: string;
17
+ text?: string;
18
+ }[];
19
+ schema?: PropertyMetaSchema;
20
+ }
21
+ export interface EventMeta {
22
+ name: string;
23
+ type: string;
24
+ rawType?: ts.Type;
25
+ signature: string;
26
+ schema?: PropertyMetaSchema[];
27
+ }
28
+ export interface SlotMeta {
29
+ name: string;
30
+ type: string;
31
+ rawType?: ts.Type;
32
+ description: string;
33
+ schema?: PropertyMetaSchema;
34
+ }
35
+ export interface ExposeMeta {
36
+ name: string;
37
+ description: string;
38
+ type: string;
39
+ rawType?: ts.Type;
40
+ schema?: PropertyMetaSchema;
41
+ }
42
+ export declare type PropertyMetaSchema = string | {
43
+ kind: 'enum';
44
+ type: string;
45
+ schema?: PropertyMetaSchema[];
46
+ } | {
47
+ kind: 'array';
48
+ type: string;
49
+ schema?: PropertyMetaSchema[];
50
+ } | {
51
+ kind: 'event';
52
+ type: string;
53
+ schema?: PropertyMetaSchema[];
54
+ } | {
55
+ kind: 'object';
56
+ type: string;
57
+ schema?: Record<string, PropertyMeta>;
58
+ };
59
+ export declare type MetaCheckerSchemaOptions = boolean | {
60
+ ignore?: string[];
61
+ };
62
+ export interface MetaCheckerOptions {
63
+ schema?: MetaCheckerSchemaOptions;
64
+ forceUseTs?: boolean;
65
+ printer?: import('typescript').PrinterOptions;
66
+ rawType?: boolean;
67
+ }
package/out/types.js ADDED
@@ -0,0 +1,3 @@
1
+ Object.defineProperty(exports, "__esModule", { value: true });
2
+ ;
3
+ //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-component-meta",
3
- "version": "0.39.2",
3
+ "version": "0.39.5",
4
4
  "main": "out/index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -13,10 +13,10 @@
13
13
  "directory": "packages/vue-component-meta"
14
14
  },
15
15
  "dependencies": {
16
- "@volar/vue-language-core": "0.39.2"
16
+ "@volar/vue-language-core": "0.39.5"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "typescript": "*"
20
20
  },
21
- "gitHead": "eac2dca4206dfa3f92ad50dd53650f924a9e6f94"
21
+ "gitHead": "b2efb244b43f24b3e351c72e731f31090e51a736"
22
22
  }