vue-component-meta 1.0.3 → 1.0.4
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 +169 -3
- package/out/index.d.ts +8 -21
- package/out/index.js +56 -54
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,10 +1,176 @@
|
|
|
1
1
|
# vue-component-meta
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`vue-component-meta` allows you to extract the meta-data like props, slots, events, etc from your components via static code analysis. You can even generate description for your props from your source code. This helps document your components via automation. Please refer to the [reference](#reference) section for references.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Guide 📗
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
First of all, you need to create a component meta checker using `createComponentMetaChecker`:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import * as url from 'url'
|
|
11
|
+
import path from 'path'
|
|
12
|
+
|
|
13
|
+
import type { MetaCheckerOptions } from 'vue-component-meta'
|
|
14
|
+
import { createComponentMetaChecker } from 'vue-component-meta'
|
|
15
|
+
|
|
16
|
+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
17
|
+
|
|
18
|
+
const checkerOptions: MetaCheckerOptions = {
|
|
19
|
+
forceUseTs: true,
|
|
20
|
+
schema: { ignore: ['MyIgnoredNestedProps'] },
|
|
21
|
+
printer: { newLine: 1 },
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const tsconfigChecker = createComponentMetaChecker(
|
|
25
|
+
// Write your tsconfig path
|
|
26
|
+
path.join(__dirname, 'path-to-tsconfig')
|
|
27
|
+
checkerOptions,
|
|
28
|
+
)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Now, you can extract the component meta using `getComponentMeta` method of checker:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import * as url from 'url'
|
|
35
|
+
import path from 'path'
|
|
36
|
+
|
|
37
|
+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
38
|
+
|
|
39
|
+
const componentPath = path.join(__dirname, 'path-to-component');
|
|
40
|
+
const meta = checker.getComponentMeta(componentPath);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This meta contains really useful stuff like component props, slots, events and more. You can refer to its [type definition](https://github.com/johnsoncodehk/volar/blob/master/vue-language-tools/vue-component-meta/src/types.ts) for more details.
|
|
44
|
+
|
|
45
|
+
### Extracting prop meta
|
|
46
|
+
|
|
47
|
+
`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.
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
/**
|
|
51
|
+
* Hide/Show alert based on v-model value
|
|
52
|
+
*/
|
|
53
|
+
modelValue: {
|
|
54
|
+
type: Boolean,
|
|
55
|
+
default: null,
|
|
56
|
+
},
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
When you extract the component meta and extract the `description` property of that prop it will be "Hide/Show alert based on v-model value" 😍
|
|
60
|
+
|
|
61
|
+
> **Warning**
|
|
62
|
+
>
|
|
63
|
+
> Do note that `meta.props` will be array of props so you can't access it via `meta.props.<prop-name>`. Moreover, `meta.props` will also contain some global prop which you can identify via `prop.global` property.
|
|
64
|
+
|
|
65
|
+
You can use it to document your component as you build your project without writing additional documentation.
|
|
66
|
+
|
|
67
|
+
## Pitfalls 👀
|
|
68
|
+
|
|
69
|
+
As `vue-component-meta` uses static code analysis, it can't extract the dynamic prop definition.
|
|
70
|
+
|
|
71
|
+
### default value
|
|
72
|
+
|
|
73
|
+
`vue-component-meta` won't be able to extract default value for prop as props can't be analyzed.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
props: {
|
|
77
|
+
// Props definition by function execution
|
|
78
|
+
...useLayerProps({
|
|
79
|
+
color: {
|
|
80
|
+
default: 'primary',
|
|
81
|
+
},
|
|
82
|
+
variant: {
|
|
83
|
+
default: 'light',
|
|
84
|
+
},
|
|
85
|
+
}),
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
In this scenario, to get the correct default value you can let `vue-component-meta` know it by writing them explicitly:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
props: {
|
|
93
|
+
// let vue-component-meta found it
|
|
94
|
+
color: { default: 'primary' },
|
|
95
|
+
variant: { default: 'light' },
|
|
96
|
+
|
|
97
|
+
// Props definition by function execution
|
|
98
|
+
...useLayerProps({
|
|
99
|
+
color: {
|
|
100
|
+
default: 'primary',
|
|
101
|
+
},
|
|
102
|
+
variant: {
|
|
103
|
+
default: 'light',
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### description
|
|
110
|
+
|
|
111
|
+
Same as above scenario you might have issue with description not generating when prop definition is dynamic. In this case writing prop description can be tricky.
|
|
112
|
+
|
|
113
|
+
When it's function execution, write prop description in function definition:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
export const useLayerProp = (...) => {
|
|
117
|
+
const props = {
|
|
118
|
+
/**
|
|
119
|
+
* Layer variant
|
|
120
|
+
*/
|
|
121
|
+
variant: {
|
|
122
|
+
type: String,
|
|
123
|
+
default: 'text',
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export { props }
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### required
|
|
132
|
+
|
|
133
|
+
For generating the correct `required` value for props like below:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
// @/composables/useProps.ts
|
|
137
|
+
export const disabled = {
|
|
138
|
+
type: Boolean,
|
|
139
|
+
default: false,
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { disabled } from '@/composables/useProps'
|
|
145
|
+
|
|
146
|
+
export default defineComponent({
|
|
147
|
+
props: {
|
|
148
|
+
disabled,
|
|
149
|
+
},
|
|
150
|
+
})
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
You need to add `as const` to variable definition:
|
|
154
|
+
|
|
155
|
+
```diff
|
|
156
|
+
export const disabled = {
|
|
157
|
+
type: Boolean,
|
|
158
|
+
default: false,
|
|
159
|
+
- }
|
|
160
|
+
+ } as const
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Used by 🎉
|
|
164
|
+
|
|
165
|
+
- [Anu](https://github.com/jd-solanki/anu) UI library uses `vue-component-meta` to generate components' API via [automation](https://github.com/jd-solanki/anu/blob/main/scripts/gen-component-meta.ts).
|
|
166
|
+
|
|
167
|
+
## Reference 📚
|
|
168
|
+
|
|
169
|
+
- [tests](https://github.com/johnsoncodehk/volar/blob/master/vue-language-tools/vue-component-meta/tests/index.spec.ts)
|
|
170
|
+
- [Anu's components' API automation](https://github.com/jd-solanki/anu/blob/main/scripts/gen-component-meta.ts)
|
|
171
|
+
- [Discord chat for dynamic usage](https://discord.com/channels/793943652350427136/1027819645677350912)
|
|
172
|
+
|
|
173
|
+
## Sponsors ❤️
|
|
8
174
|
|
|
9
175
|
<p align="center">
|
|
10
176
|
<a href="https://cdn.jsdelivr.net/gh/johnsoncodehk/sponsors/company/sponsors.svg">
|
package/out/index.d.ts
CHANGED
|
@@ -1,47 +1,34 @@
|
|
|
1
1
|
import * as vue from '@volar/vue-language-core';
|
|
2
|
-
import * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import type * as ts from 'typescript/lib/tsserverlibrary';
|
|
3
3
|
import type { MetaCheckerOptions, ComponentMeta, EventMeta, ExposeMeta, MetaCheckerSchemaOptions, PropertyMeta, PropertyMetaSchema, SlotMeta } from './types';
|
|
4
4
|
export type { MetaCheckerOptions, ComponentMeta, EventMeta, ExposeMeta, MetaCheckerSchemaOptions, PropertyMeta, PropertyMetaSchema, SlotMeta };
|
|
5
5
|
export type ComponentMetaChecker = ReturnType<typeof baseCreate>;
|
|
6
|
-
export declare function createComponentMetaCheckerByJsonConfig(root: string, json: any, checkerOptions?: MetaCheckerOptions): {
|
|
7
|
-
getExportNames: (componentPath: string) => string[];
|
|
8
|
-
getComponentMeta: (componentPath: string, exportName?: string) => ComponentMeta;
|
|
6
|
+
export declare function createComponentMetaCheckerByJsonConfig(root: string, json: any, checkerOptions?: MetaCheckerOptions, ts?: typeof import('typescript/lib/tsserverlibrary')): {
|
|
9
7
|
updateFile(fileName: string, text: string): void;
|
|
10
8
|
deleteFile(fileName: string): void;
|
|
11
9
|
reload(): void;
|
|
12
10
|
clearCache(): void;
|
|
11
|
+
getExportNames: (componentPath: string) => string[];
|
|
12
|
+
getComponentMeta: (componentPath: string, exportName?: string) => ComponentMeta;
|
|
13
13
|
__internal__: {
|
|
14
|
-
parsedCommandLine: vue.ParsedCommandLine;
|
|
15
|
-
program: ts.Program;
|
|
16
14
|
tsLs: ts.LanguageService;
|
|
17
|
-
typeChecker: ts.TypeChecker;
|
|
18
15
|
};
|
|
19
16
|
};
|
|
20
|
-
export declare function createComponentMetaChecker(tsconfigPath: string, checkerOptions?: MetaCheckerOptions): {
|
|
21
|
-
getExportNames: (componentPath: string) => string[];
|
|
22
|
-
getComponentMeta: (componentPath: string, exportName?: string) => ComponentMeta;
|
|
17
|
+
export declare function createComponentMetaChecker(tsconfigPath: string, checkerOptions?: MetaCheckerOptions, ts?: typeof import('typescript/lib/tsserverlibrary')): {
|
|
23
18
|
updateFile(fileName: string, text: string): void;
|
|
24
19
|
deleteFile(fileName: string): void;
|
|
25
20
|
reload(): void;
|
|
26
21
|
clearCache(): void;
|
|
22
|
+
getExportNames: (componentPath: string) => string[];
|
|
23
|
+
getComponentMeta: (componentPath: string, exportName?: string) => ComponentMeta;
|
|
27
24
|
__internal__: {
|
|
28
|
-
parsedCommandLine: vue.ParsedCommandLine;
|
|
29
|
-
program: ts.Program;
|
|
30
25
|
tsLs: ts.LanguageService;
|
|
31
|
-
typeChecker: ts.TypeChecker;
|
|
32
26
|
};
|
|
33
27
|
};
|
|
34
|
-
declare function baseCreate(
|
|
28
|
+
export declare function baseCreate(_host: vue.LanguageServiceHost, checkerOptions: MetaCheckerOptions, globalComponentName: string, ts: typeof import('typescript/lib/tsserverlibrary')): {
|
|
35
29
|
getExportNames: (componentPath: string) => string[];
|
|
36
30
|
getComponentMeta: (componentPath: string, exportName?: string) => ComponentMeta;
|
|
37
|
-
updateFile(fileName: string, text: string): void;
|
|
38
|
-
deleteFile(fileName: string): void;
|
|
39
|
-
reload(): void;
|
|
40
|
-
clearCache(): void;
|
|
41
31
|
__internal__: {
|
|
42
|
-
parsedCommandLine: vue.ParsedCommandLine;
|
|
43
|
-
program: ts.Program;
|
|
44
32
|
tsLs: ts.LanguageService;
|
|
45
|
-
typeChecker: ts.TypeChecker;
|
|
46
33
|
};
|
|
47
34
|
};
|
package/out/index.js
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
-
exports.createComponentMetaChecker = exports.createComponentMetaCheckerByJsonConfig = void 0;
|
|
2
|
+
exports.baseCreate = exports.createComponentMetaChecker = exports.createComponentMetaCheckerByJsonConfig = void 0;
|
|
3
3
|
const vue = require("@volar/vue-language-core");
|
|
4
4
|
const embedded = require("@volar/language-core");
|
|
5
|
-
const ts = require("typescript/lib/tsserverlibrary");
|
|
6
5
|
const path = require("typesafe-path/posix");
|
|
7
6
|
const extraFileExtensions = [{
|
|
8
7
|
extension: 'vue',
|
|
9
8
|
isMixedContent: true,
|
|
10
|
-
scriptKind: ts.ScriptKind.Deferred
|
|
9
|
+
scriptKind: 7 /* ts.ScriptKind.Deferred */,
|
|
11
10
|
}];
|
|
12
|
-
function createComponentMetaCheckerByJsonConfig(root, json, checkerOptions = {}) {
|
|
13
|
-
return
|
|
11
|
+
function createComponentMetaCheckerByJsonConfig(root, json, checkerOptions = {}, ts = require('typescript')) {
|
|
12
|
+
return createComponentMetaCheckerWorker(() => vue.createParsedCommandLineByJson(ts, ts.sys, root, json, extraFileExtensions), checkerOptions, path.join(root.replace(/\\/g, '/'), 'jsconfig.json.global.vue'), ts);
|
|
14
13
|
}
|
|
15
14
|
exports.createComponentMetaCheckerByJsonConfig = createComponentMetaCheckerByJsonConfig;
|
|
16
|
-
function createComponentMetaChecker(tsconfigPath, checkerOptions = {}) {
|
|
17
|
-
return
|
|
15
|
+
function createComponentMetaChecker(tsconfigPath, checkerOptions = {}, ts = require('typescript')) {
|
|
16
|
+
return createComponentMetaCheckerWorker(() => vue.createParsedCommandLine(ts, ts.sys, tsconfigPath, extraFileExtensions), checkerOptions, tsconfigPath.replace(/\\/g, '/') + '.global.vue', ts);
|
|
18
17
|
}
|
|
19
18
|
exports.createComponentMetaChecker = createComponentMetaChecker;
|
|
20
|
-
function
|
|
19
|
+
function createComponentMetaCheckerWorker(loadParsedCommandLine, checkerOptions, globalComponentName, ts) {
|
|
21
20
|
/**
|
|
22
21
|
* Original Host
|
|
23
22
|
*/
|
|
@@ -35,6 +34,29 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
35
34
|
}
|
|
36
35
|
return scriptSnapshots.get(fileName);
|
|
37
36
|
}, getTypeScriptModule: () => ts, getVueCompilationSettings: () => parsedCommandLine.vueOptions });
|
|
37
|
+
return Object.assign(Object.assign({}, baseCreate(_host, checkerOptions, globalComponentName, ts)), { updateFile(fileName, text) {
|
|
38
|
+
fileName = fileName.replace(/\\/g, '/');
|
|
39
|
+
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(text));
|
|
40
|
+
scriptVersions.set(fileName, scriptVersions.has(fileName) ? scriptVersions.get(fileName) + 1 : 1);
|
|
41
|
+
projectVersion++;
|
|
42
|
+
},
|
|
43
|
+
deleteFile(fileName) {
|
|
44
|
+
fileName = fileName.replace(/\\/g, '/');
|
|
45
|
+
fileNames = fileNames.filter(f => f !== fileName);
|
|
46
|
+
projectVersion++;
|
|
47
|
+
},
|
|
48
|
+
reload() {
|
|
49
|
+
parsedCommandLine = loadParsedCommandLine();
|
|
50
|
+
fileNames = parsedCommandLine.fileNames.map(path => path.replace(/\\/g, '/'));
|
|
51
|
+
this.clearCache();
|
|
52
|
+
},
|
|
53
|
+
clearCache() {
|
|
54
|
+
scriptSnapshots.clear();
|
|
55
|
+
scriptVersions.clear();
|
|
56
|
+
projectVersion++;
|
|
57
|
+
} });
|
|
58
|
+
}
|
|
59
|
+
function baseCreate(_host, checkerOptions, globalComponentName, ts) {
|
|
38
60
|
/**
|
|
39
61
|
* Meta
|
|
40
62
|
*/
|
|
@@ -94,39 +116,13 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
94
116
|
}
|
|
95
117
|
});
|
|
96
118
|
const tsLs = ts.createLanguageService(proxyHost);
|
|
97
|
-
const program = tsLs.getProgram();
|
|
98
|
-
const typeChecker = program.getTypeChecker();
|
|
99
119
|
let globalPropNames = [];
|
|
100
120
|
globalPropNames = getComponentMeta(globalComponentName).props.map(prop => prop.name);
|
|
101
121
|
return {
|
|
102
122
|
getExportNames,
|
|
103
123
|
getComponentMeta,
|
|
104
|
-
updateFile(fileName, text) {
|
|
105
|
-
fileName = fileName.replace(/\\/g, '/');
|
|
106
|
-
scriptSnapshots.set(fileName, ts.ScriptSnapshot.fromString(text));
|
|
107
|
-
scriptVersions.set(fileName, scriptVersions.has(fileName) ? scriptVersions.get(fileName) + 1 : 1);
|
|
108
|
-
projectVersion++;
|
|
109
|
-
},
|
|
110
|
-
deleteFile(fileName) {
|
|
111
|
-
fileName = fileName.replace(/\\/g, '/');
|
|
112
|
-
fileNames = fileNames.filter(f => f !== fileName);
|
|
113
|
-
projectVersion++;
|
|
114
|
-
},
|
|
115
|
-
reload() {
|
|
116
|
-
parsedCommandLine = loadParsedCommandLine();
|
|
117
|
-
fileNames = parsedCommandLine.fileNames.map(path => path.replace(/\\/g, '/'));
|
|
118
|
-
this.clearCache();
|
|
119
|
-
},
|
|
120
|
-
clearCache() {
|
|
121
|
-
scriptSnapshots.clear();
|
|
122
|
-
scriptVersions.clear();
|
|
123
|
-
projectVersion++;
|
|
124
|
-
},
|
|
125
124
|
__internal__: {
|
|
126
|
-
parsedCommandLine,
|
|
127
|
-
program,
|
|
128
125
|
tsLs,
|
|
129
|
-
typeChecker,
|
|
130
126
|
},
|
|
131
127
|
};
|
|
132
128
|
function isMetaFileName(fileName) {
|
|
@@ -142,11 +138,15 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
142
138
|
`;
|
|
143
139
|
}
|
|
144
140
|
function getExportNames(componentPath) {
|
|
145
|
-
|
|
141
|
+
const program = tsLs.getProgram();
|
|
142
|
+
const typeChecker = program.getTypeChecker();
|
|
143
|
+
return _getExports(program, typeChecker, componentPath).exports.map(e => e.getName());
|
|
146
144
|
}
|
|
147
145
|
function getComponentMeta(componentPath, exportName = 'default') {
|
|
148
146
|
var _a;
|
|
149
|
-
const
|
|
147
|
+
const program = tsLs.getProgram();
|
|
148
|
+
const typeChecker = program.getTypeChecker();
|
|
149
|
+
const { symbolNode, exports } = _getExports(program, typeChecker, componentPath);
|
|
150
150
|
const _export = exports.find((property) => property.getName() === exportName);
|
|
151
151
|
if (!_export) {
|
|
152
152
|
throw `Could not find export ${exportName}`;
|
|
@@ -169,7 +169,7 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
169
169
|
const properties = type.getProperties();
|
|
170
170
|
result = properties
|
|
171
171
|
.map((prop) => {
|
|
172
|
-
const { resolveNestedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
|
|
172
|
+
const { resolveNestedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts);
|
|
173
173
|
return resolveNestedProperties(prop);
|
|
174
174
|
})
|
|
175
175
|
.filter((prop) => !prop.name.match(propEventRegex));
|
|
@@ -183,10 +183,10 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
183
183
|
const snapshot = host.getScriptSnapshot(componentPath);
|
|
184
184
|
const vueSourceFile = (_a = core.mapper.get(componentPath)) === null || _a === void 0 ? void 0 : _a[0];
|
|
185
185
|
const vueDefaults = vueSourceFile && exportName === 'default'
|
|
186
|
-
? (vueSourceFile instanceof vue.VueSourceFile ? readVueComponentDefaultProps(vueSourceFile, printer) : {})
|
|
186
|
+
? (vueSourceFile instanceof vue.VueSourceFile ? readVueComponentDefaultProps(vueSourceFile, printer, ts) : {})
|
|
187
187
|
: {};
|
|
188
188
|
const tsDefaults = !vueSourceFile ? readTsComponentDefaultProps(componentPath.substring(componentPath.lastIndexOf('.') + 1), // ts | js | tsx | jsx
|
|
189
|
-
snapshot.getText(0, snapshot.getLength()), exportName, printer) : {};
|
|
189
|
+
snapshot.getText(0, snapshot.getLength()), exportName, printer, ts) : {};
|
|
190
190
|
for (const [propName, defaultExp] of Object.entries(Object.assign(Object.assign({}, vueDefaults), tsDefaults))) {
|
|
191
191
|
const prop = result.find(p => p.name === propName);
|
|
192
192
|
if (prop) {
|
|
@@ -207,7 +207,7 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
207
207
|
const type = typeChecker.getTypeOfSymbolAtLocation($emit, symbolNode);
|
|
208
208
|
const calls = type.getCallSignatures();
|
|
209
209
|
return calls.map((call) => {
|
|
210
|
-
const { resolveEventSignature, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
|
|
210
|
+
const { resolveEventSignature, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts);
|
|
211
211
|
return resolveEventSignature(call);
|
|
212
212
|
}).filter(event => event.name);
|
|
213
213
|
}
|
|
@@ -215,13 +215,14 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
215
215
|
}
|
|
216
216
|
function getSlots() {
|
|
217
217
|
var _a;
|
|
218
|
-
const
|
|
218
|
+
const target = (_a = _host.getVueCompilationSettings().target) !== null && _a !== void 0 ? _a : 3;
|
|
219
|
+
const propertyName = target < 3 ? '$scopedSlots' : '$slots';
|
|
219
220
|
const $slots = symbolProperties.find(prop => prop.escapedName === propertyName);
|
|
220
221
|
if ($slots) {
|
|
221
222
|
const type = typeChecker.getTypeOfSymbolAtLocation($slots, symbolNode);
|
|
222
223
|
const properties = type.getProperties();
|
|
223
224
|
return properties.map((prop) => {
|
|
224
|
-
const { resolveSlotProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
|
|
225
|
+
const { resolveSlotProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts);
|
|
225
226
|
return resolveSlotProperties(prop);
|
|
226
227
|
});
|
|
227
228
|
}
|
|
@@ -233,14 +234,14 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
233
234
|
Boolean(prop.syntheticOrigin));
|
|
234
235
|
if (exposed.length) {
|
|
235
236
|
return exposed.map((prop) => {
|
|
236
|
-
const { resolveExposedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions);
|
|
237
|
+
const { resolveExposedProperties, } = createSchemaResolvers(typeChecker, symbolNode, checkerOptions, ts);
|
|
237
238
|
return resolveExposedProperties(prop);
|
|
238
239
|
});
|
|
239
240
|
}
|
|
240
241
|
return [];
|
|
241
242
|
}
|
|
242
243
|
}
|
|
243
|
-
function _getExports(componentPath) {
|
|
244
|
+
function _getExports(program, typeChecker, componentPath) {
|
|
244
245
|
var _a;
|
|
245
246
|
const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(getMetaFileName(componentPath));
|
|
246
247
|
if (!sourceFile) {
|
|
@@ -269,7 +270,8 @@ function baseCreate(loadParsedCommandLine, checkerOptions, globalComponentName)
|
|
|
269
270
|
};
|
|
270
271
|
}
|
|
271
272
|
}
|
|
272
|
-
|
|
273
|
+
exports.baseCreate = baseCreate;
|
|
274
|
+
function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: options }, ts) {
|
|
273
275
|
var _a;
|
|
274
276
|
const enabled = !!options;
|
|
275
277
|
const ignore = typeof options === 'object' ? [...(_a = options === null || options === void 0 ? void 0 : options.ignore) !== null && _a !== void 0 ? _a : []] : [];
|
|
@@ -403,7 +405,7 @@ function createSchemaResolvers(typeChecker, symbolNode, { rawType, schema: optio
|
|
|
403
405
|
resolveSchema,
|
|
404
406
|
};
|
|
405
407
|
}
|
|
406
|
-
function readVueComponentDefaultProps(vueSourceFile, printer) {
|
|
408
|
+
function readVueComponentDefaultProps(vueSourceFile, printer, ts) {
|
|
407
409
|
let result = {};
|
|
408
410
|
scriptSetupWorker();
|
|
409
411
|
scriptWorker();
|
|
@@ -420,7 +422,7 @@ function readVueComponentDefaultProps(vueSourceFile, printer) {
|
|
|
420
422
|
for (const prop of obj.properties) {
|
|
421
423
|
if (ts.isPropertyAssignment(prop)) {
|
|
422
424
|
const name = prop.name.getText(ast);
|
|
423
|
-
const expNode = resolveDefaultOptionExpression(prop.initializer);
|
|
425
|
+
const expNode = resolveDefaultOptionExpression(prop.initializer, ts);
|
|
424
426
|
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);
|
|
425
427
|
result[name] = {
|
|
426
428
|
default: expText,
|
|
@@ -434,7 +436,7 @@ function readVueComponentDefaultProps(vueSourceFile, printer) {
|
|
|
434
436
|
const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
|
|
435
437
|
const obj = findObjectLiteralExpression(ast);
|
|
436
438
|
if (obj) {
|
|
437
|
-
result = Object.assign(Object.assign({}, result), resolvePropsOption(ast, obj, printer));
|
|
439
|
+
result = Object.assign(Object.assign({}, result), resolvePropsOption(ast, obj, printer, ts));
|
|
438
440
|
}
|
|
439
441
|
}
|
|
440
442
|
function findObjectLiteralExpression(node) {
|
|
@@ -453,18 +455,18 @@ function readVueComponentDefaultProps(vueSourceFile, printer) {
|
|
|
453
455
|
function scriptWorker() {
|
|
454
456
|
const descriptor = vueSourceFile.sfc;
|
|
455
457
|
if (descriptor.script) {
|
|
456
|
-
const scriptResult = readTsComponentDefaultProps(descriptor.script.lang, descriptor.script.content, 'default', printer);
|
|
458
|
+
const scriptResult = readTsComponentDefaultProps(descriptor.script.lang, descriptor.script.content, 'default', printer, ts);
|
|
457
459
|
for (const [key, value] of Object.entries(scriptResult)) {
|
|
458
460
|
result[key] = value;
|
|
459
461
|
}
|
|
460
462
|
}
|
|
461
463
|
}
|
|
462
464
|
}
|
|
463
|
-
function readTsComponentDefaultProps(lang, tsFileText, exportName, printer) {
|
|
465
|
+
function readTsComponentDefaultProps(lang, tsFileText, exportName, printer, ts) {
|
|
464
466
|
const ast = ts.createSourceFile('/tmp.' + lang, tsFileText, ts.ScriptTarget.Latest);
|
|
465
467
|
const props = getPropsNode();
|
|
466
468
|
if (props) {
|
|
467
|
-
return resolvePropsOption(ast, props, printer);
|
|
469
|
+
return resolvePropsOption(ast, props, printer, ts);
|
|
468
470
|
}
|
|
469
471
|
return {};
|
|
470
472
|
function getComponentNode() {
|
|
@@ -520,7 +522,7 @@ function readTsComponentDefaultProps(lang, tsFileText, exportName, printer) {
|
|
|
520
522
|
}
|
|
521
523
|
}
|
|
522
524
|
}
|
|
523
|
-
function resolvePropsOption(ast, props, printer) {
|
|
525
|
+
function resolvePropsOption(ast, props, printer, ts) {
|
|
524
526
|
var _a, _b;
|
|
525
527
|
const result = {};
|
|
526
528
|
for (const prop of props.properties) {
|
|
@@ -535,7 +537,7 @@ function resolvePropsOption(ast, props, printer) {
|
|
|
535
537
|
result[name].required = exp === 'true';
|
|
536
538
|
}
|
|
537
539
|
if (defaultProp) {
|
|
538
|
-
const expNode = resolveDefaultOptionExpression(defaultProp.initializer);
|
|
540
|
+
const expNode = resolveDefaultOptionExpression(defaultProp.initializer, ts);
|
|
539
541
|
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);
|
|
540
542
|
result[name].default = expText;
|
|
541
543
|
}
|
|
@@ -544,7 +546,7 @@ function resolvePropsOption(ast, props, printer) {
|
|
|
544
546
|
}
|
|
545
547
|
return result;
|
|
546
548
|
}
|
|
547
|
-
function resolveDefaultOptionExpression(_default) {
|
|
549
|
+
function resolveDefaultOptionExpression(_default, ts) {
|
|
548
550
|
if (ts.isArrowFunction(_default)) {
|
|
549
551
|
if (ts.isBlock(_default.body)) {
|
|
550
552
|
return _default; // TODO
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-component-meta",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"main": "out/index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"directory": "vue-language-tools/vue-component-meta"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@volar/language-core": "1.0.
|
|
17
|
-
"@volar/vue-language-core": "1.0.
|
|
18
|
-
"typesafe-path": "^0.2.
|
|
16
|
+
"@volar/language-core": "1.0.4",
|
|
17
|
+
"@volar/vue-language-core": "1.0.4",
|
|
18
|
+
"typesafe-path": "^0.2.2"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"typescript": "*"
|
|
22
22
|
},
|
|
23
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "1394533d1822a588136364ab33a02c1bdf89cac9"
|
|
24
24
|
}
|