vue-component-meta 3.1.5 → 3.1.7

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 CHANGED
@@ -42,6 +42,29 @@ const meta = checker.getComponentMeta(componentPath);
42
42
 
43
43
  This meta contains really useful stuff like component props, slots, events and more. You can refer to its [type definition](https://github.com/vuejs/language-tools/blob/master/packages/component-meta/lib/types.ts) for more details.
44
44
 
45
+ ### Extracting component name and description
46
+
47
+ The component meta also includes `name` and `description` fields at the root level:
48
+
49
+ - **`name`**: Extracted from the `name` property in the component options (for Options API components)
50
+ - **`description`**: Extracted from JSDoc comments above the component export (for TypeScript/JavaScript files)
51
+
52
+ ```ts
53
+ /**
54
+ * My awesome component description
55
+ */
56
+ export default defineComponent({
57
+ name: 'MyComponent',
58
+ // ... component definition
59
+ })
60
+ ```
61
+
62
+ When you extract the component meta, you'll get:
63
+ ```ts
64
+ meta.name // 'MyComponent'
65
+ meta.description // 'My awesome component description'
66
+ ```
67
+
45
68
  ### Extracting prop meta
46
69
 
47
70
  `vue-component-meta` will automatically extract the prop details like its name, default value, is required or not, etc. Additionally, you can even write prop description in source code via [JSDoc](https://jsdoc.app/) comment for that prop.
package/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export declare function createCheckerByJson(rootPath: string, json: any, checker
8
8
  deleteFile(fileName: string): void;
9
9
  reload(): void;
10
10
  clearCache(): void;
11
+ getProgram(): ts.Program | undefined;
11
12
  __internal__: {
12
13
  tsLs: ts.LanguageService;
13
14
  };
@@ -19,6 +20,7 @@ export declare function createChecker(tsconfig: string, checkerOptions?: MetaChe
19
20
  deleteFile(fileName: string): void;
20
21
  reload(): void;
21
22
  clearCache(): void;
23
+ getProgram(): ts.Program | undefined;
22
24
  __internal__: {
23
25
  tsLs: ts.LanguageService;
24
26
  };
package/lib/base.d.ts CHANGED
@@ -8,6 +8,10 @@ export declare function createCheckerByJsonConfigBase(ts: typeof import('typescr
8
8
  deleteFile(fileName: string): void;
9
9
  reload(): void;
10
10
  clearCache(): void;
11
+ getProgram(): ts.Program | undefined;
12
+ /**
13
+ * @deprecated use `getProgram()` instead
14
+ */
11
15
  __internal__: {
12
16
  tsLs: ts.LanguageService;
13
17
  };
@@ -19,6 +23,10 @@ export declare function createCheckerBase(ts: typeof import('typescript'), tscon
19
23
  deleteFile(fileName: string): void;
20
24
  reload(): void;
21
25
  clearCache(): void;
26
+ getProgram(): ts.Program | undefined;
27
+ /**
28
+ * @deprecated use `getProgram()` instead
29
+ */
22
30
  __internal__: {
23
31
  tsLs: ts.LanguageService;
24
32
  };
package/lib/base.js CHANGED
@@ -21,6 +21,49 @@ const core = require("@vue/language-core");
21
21
  const path_browserify_1 = require("path-browserify");
22
22
  __exportStar(require("./types"), exports);
23
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
+ }
24
67
  function createCheckerByJsonConfigBase(ts, rootDir, json, checkerOptions = {}) {
25
68
  rootDir = rootDir.replace(windowsPathReg, '/');
26
69
  return baseCreate(ts, () => {
@@ -156,6 +199,12 @@ function baseCreate(ts, getConfigAndFiles, checkerOptions, rootPath, globalCompo
156
199
  scriptSnapshots.clear();
157
200
  projectVersion++;
158
201
  },
202
+ getProgram() {
203
+ return tsLs.getProgram();
204
+ },
205
+ /**
206
+ * @deprecated use `getProgram()` instead
207
+ */
159
208
  __internal__: {
160
209
  tsLs,
161
210
  },
@@ -210,7 +259,15 @@ interface ComponentMeta<T> {
210
259
  let _events;
211
260
  let _slots;
212
261
  let _exposed;
262
+ let _name;
263
+ let _description;
213
264
  const meta = {
265
+ get name() {
266
+ return _name ?? (_name = getName());
267
+ },
268
+ get description() {
269
+ return _description ?? (_description = getDescription());
270
+ },
214
271
  get type() {
215
272
  return _type ?? (_type = getType());
216
273
  },
@@ -325,6 +382,34 @@ interface ComponentMeta<T> {
325
382
  }
326
383
  return [];
327
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
+ }
328
413
  }
329
414
  function _getExports(program, typeChecker, componentPath) {
330
415
  const sourceFile = program.getSourceFile(getMetaFileName(componentPath));
@@ -397,13 +482,16 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
397
482
  })),
398
483
  required: !(prop.flags & ts.SymbolFlags.Optional),
399
484
  type: getFullyQualifiedName(subtype),
400
- rawType: rawType ? subtype : undefined,
401
485
  get declarations() {
402
486
  return declarations ??= getDeclarations(prop.declarations ?? []);
403
487
  },
404
488
  get schema() {
405
489
  return schema ??= resolveSchema(subtype);
406
490
  },
491
+ rawType: rawType ? subtype : undefined,
492
+ getTypeObject() {
493
+ return subtype;
494
+ },
407
495
  };
408
496
  }
409
497
  function resolveSlotProperties(prop) {
@@ -416,7 +504,6 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
416
504
  return {
417
505
  name: prop.getName(),
418
506
  type: getFullyQualifiedName(subtype),
419
- rawType: rawType ? subtype : undefined,
420
507
  description: ts.displayPartsToString(prop.getDocumentationComment(typeChecker)),
421
508
  get declarations() {
422
509
  return declarations ??= getDeclarations(prop.declarations ?? []);
@@ -424,6 +511,10 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
424
511
  get schema() {
425
512
  return schema ??= resolveSchema(subtype);
426
513
  },
514
+ rawType: rawType ? subtype : undefined,
515
+ getTypeObject() {
516
+ return subtype;
517
+ },
427
518
  };
428
519
  }
429
520
  function resolveExposedProperties(expose) {
@@ -433,7 +524,6 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
433
524
  return {
434
525
  name: expose.getName(),
435
526
  type: getFullyQualifiedName(subtype),
436
- rawType: rawType ? subtype : undefined,
437
527
  description: ts.displayPartsToString(expose.getDocumentationComment(typeChecker)),
438
528
  get declarations() {
439
529
  return declarations ??= getDeclarations(expose.declarations ?? []);
@@ -441,16 +531,22 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
441
531
  get schema() {
442
532
  return schema ??= resolveSchema(subtype);
443
533
  },
534
+ rawType: rawType ? subtype : undefined,
535
+ getTypeObject() {
536
+ return subtype;
537
+ },
444
538
  };
445
539
  }
446
540
  function resolveEventSignature(call) {
447
541
  let schema;
448
542
  let declarations;
449
- let subtype = undefined;
543
+ let subtype;
544
+ let symbol;
450
545
  let subtypeStr = '[]';
451
546
  let getSchema = () => [];
452
547
  if (call.parameters.length >= 2) {
453
- subtype = typeChecker.getTypeOfSymbolAtLocation(call.parameters[1], symbolNode);
548
+ symbol = call.parameters[1];
549
+ subtype = typeChecker.getTypeOfSymbolAtLocation(symbol, symbolNode);
454
550
  if (call.parameters[1].valueDeclaration?.dotDotDotToken) {
455
551
  subtypeStr = getFullyQualifiedName(subtype);
456
552
  getSchema = () => typeChecker.getTypeArguments(subtype).map(resolveSchema);
@@ -479,7 +575,6 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
479
575
  text: tag.text !== undefined ? ts.displayPartsToString(tag.text) : undefined,
480
576
  })),
481
577
  type: subtypeStr,
482
- rawType: rawType ? subtype : undefined,
483
578
  signature: typeChecker.signatureToString(call),
484
579
  get declarations() {
485
580
  return declarations ??= call.declaration ? getDeclarations([call.declaration]) : [];
@@ -487,6 +582,10 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
487
582
  get schema() {
488
583
  return schema ??= getSchema();
489
584
  },
585
+ rawType: rawType ? subtype : undefined,
586
+ getTypeObject() {
587
+ return subtype;
588
+ },
490
589
  };
491
590
  }
492
591
  function resolveCallbackSchema(signature) {
@@ -680,45 +779,11 @@ function readTsComponentDefaultProps(ast, exportName, printer, ts) {
680
779
  }
681
780
  return {};
682
781
  function getComponentNode() {
683
- let result;
684
- if (exportName === 'default') {
685
- ast.forEachChild(child => {
686
- if (ts.isExportAssignment(child)) {
687
- result = child.expression;
688
- }
689
- });
690
- }
691
- else {
692
- ast.forEachChild(child => {
693
- if (ts.isVariableStatement(child)
694
- && child.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)) {
695
- for (const dec of child.declarationList.declarations) {
696
- if (dec.name.getText(ast) === exportName) {
697
- result = dec.initializer;
698
- }
699
- }
700
- }
701
- });
702
- }
703
- return result;
782
+ return getComponentNodeFromAst(ast, exportName, ts);
704
783
  }
705
784
  function getComponentOptionsNode() {
706
785
  const component = getComponentNode();
707
- if (component) {
708
- // export default { ... }
709
- if (ts.isObjectLiteralExpression(component)) {
710
- return component;
711
- }
712
- // export default defineComponent({ ... })
713
- else if (ts.isCallExpression(component)) {
714
- if (component.arguments.length) {
715
- const arg = component.arguments[0];
716
- if (ts.isObjectLiteralExpression(arg)) {
717
- return arg;
718
- }
719
- }
720
- }
721
- }
786
+ return getComponentOptionsNodeFromComponent(component, ts);
722
787
  }
723
788
  function getPropsNode() {
724
789
  const options = getComponentOptionsNode();
@@ -781,4 +846,61 @@ function resolveDefaultOptionExpression(_default, ts) {
781
846
  }
782
847
  return _default;
783
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
+ }
784
906
  //# sourceMappingURL=base.js.map
package/lib/types.d.ts CHANGED
@@ -5,6 +5,8 @@ export interface Declaration {
5
5
  range: [number, number];
6
6
  }
7
7
  export interface ComponentMeta {
8
+ name?: string;
9
+ description?: string;
8
10
  type: TypeMeta;
9
11
  props: PropertyMeta[];
10
12
  events: EventMeta[];
@@ -23,19 +25,22 @@ export interface PropertyMeta {
23
25
  global: boolean;
24
26
  required: boolean;
25
27
  type: string;
26
- rawType?: ts.Type;
27
28
  tags: {
28
29
  name: string;
29
30
  text?: string;
30
31
  }[];
31
32
  declarations: Declaration[];
32
33
  schema: PropertyMetaSchema;
34
+ /**
35
+ * @deprecated use `getTypeObject()` instead
36
+ */
37
+ rawType?: ts.Type;
38
+ getTypeObject(): ts.Type;
33
39
  }
34
40
  export interface EventMeta {
35
41
  name: string;
36
42
  description: string;
37
43
  type: string;
38
- rawType?: ts.Type;
39
44
  signature: string;
40
45
  tags: {
41
46
  name: string;
@@ -43,22 +48,35 @@ export interface EventMeta {
43
48
  }[];
44
49
  declarations: Declaration[];
45
50
  schema: PropertyMetaSchema[];
51
+ /**
52
+ * @deprecated use `getTypeObject()` instead
53
+ */
54
+ rawType?: ts.Type;
55
+ getTypeObject(): ts.Type | undefined;
46
56
  }
47
57
  export interface SlotMeta {
48
58
  name: string;
49
59
  type: string;
50
- rawType?: ts.Type;
51
60
  description: string;
52
61
  declarations: Declaration[];
53
62
  schema: PropertyMetaSchema;
63
+ /**
64
+ * @deprecated use `getTypeObject()` instead
65
+ */
66
+ rawType?: ts.Type;
67
+ getTypeObject(): ts.Type;
54
68
  }
55
69
  export interface ExposeMeta {
56
70
  name: string;
57
71
  description: string;
58
72
  type: string;
59
- rawType?: ts.Type;
60
73
  declarations: Declaration[];
61
74
  schema: PropertyMetaSchema;
75
+ /**
76
+ * @deprecated use `getTypeObject()` instead
77
+ */
78
+ rawType?: ts.Type;
79
+ getTypeObject(): ts.Type;
62
80
  }
63
81
  export type PropertyMetaSchema = string | {
64
82
  kind: 'enum';
@@ -88,6 +106,9 @@ export interface MetaCheckerOptions {
88
106
  schema?: MetaCheckerSchemaOptions;
89
107
  forceUseTs?: boolean;
90
108
  printer?: ts.PrinterOptions;
91
- rawType?: boolean;
92
109
  noDeclarations?: boolean;
110
+ /**
111
+ * @deprecated No longer needed, use `getTypeObject()` instead
112
+ */
113
+ rawType?: boolean;
93
114
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-component-meta",
3
- "version": "3.1.5",
3
+ "version": "3.1.7",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "**/*.js",
@@ -13,10 +13,10 @@
13
13
  "directory": "packages/component-meta"
14
14
  },
15
15
  "dependencies": {
16
- "@volar/typescript": "2.4.23",
17
- "@vue/language-core": "3.1.5",
16
+ "@volar/typescript": "2.4.26",
17
+ "@vue/language-core": "3.1.7",
18
18
  "path-browserify": "^1.0.1",
19
- "vue-component-type-helpers": "3.1.5"
19
+ "vue-component-type-helpers": "3.1.7"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "typescript": "*"
@@ -25,5 +25,5 @@
25
25
  "@types/node": "^22.10.4",
26
26
  "@types/path-browserify": "^1.0.1"
27
27
  },
28
- "gitHead": "d124a88fbf169e793c39ae4248da2092098de92d"
28
+ "gitHead": "20dcd47c0cb4ce30e2c5e3ef1986ce297c218a06"
29
29
  }
package/lib/helpers.d.ts DELETED
@@ -1 +0,0 @@
1
- export type * from 'vue-component-type-helpers';
package/lib/helpers.js DELETED
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=helpers.js.map