Skip to content

Commit

Permalink
feat(vue-component-meta): add prop default values to documentation (#…
Browse files Browse the repository at this point in the history
…1640)

Co-authored-by: johnsoncodehk <[email protected]>
  • Loading branch information
elevatebart and johnsoncodehk authored Jul 28, 2022
1 parent 23c2500 commit ddb2632
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 26 deletions.
60 changes: 58 additions & 2 deletions packages/vue-component-meta/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as ts from 'typescript/lib/tsserverlibrary';

export type PropertyMeta = {
name: string;
default?: string;
description: string;
required: boolean;
type: string;
Expand Down Expand Up @@ -198,16 +199,26 @@ export function createComponentMetaChecker(tsconfigPath: string) {
function getProps() {

const $props = symbolProperties.find(prop => prop.escapedName === '$props');
let result: PropertyMeta[] = [];

if ($props) {
const type = typeChecker.getTypeOfSymbolAtLocation($props, symbolNode!);
const properties = type.getApparentProperties();
const { resolveSymbolSchema } = createSchemaResolvers(typeChecker, symbolNode!);

return properties.map(resolveSymbolSchema);
result = properties.map(resolveSymbolSchema);
}

return [];
// fill defaults
const defaults = findCmponentDefaultProps(componentPath);
for (const propName in defaults) {
const prop = result.find(p => p.name === propName);
if (prop) {
prop.default = defaults[propName];
}
}

return result;
}

function getEvents() {
Expand Down Expand Up @@ -306,3 +317,48 @@ export function createComponentMetaChecker(tsconfigPath: string) {
};
}
}

export function findCmponentDefaultProps(componentPath: string) {

const fileText = ts.sys.readFile(componentPath);
if (fileText === undefined) {
throw new Error(`${componentPath} not found`);
}

const vueSourceFile = vue.createSourceFile(componentPath, fileText, {}, {}, ts);
const descriptor = vueSourceFile.getDescriptor();
const scriptSetupRanges = vueSourceFile.getScriptSetupRanges();
const result: Record<string, string> = {};

if (descriptor.scriptSetup && scriptSetupRanges?.withDefaultsArg) {

const defaultsText = descriptor.scriptSetup.content.substring(scriptSetupRanges.withDefaultsArg.start, scriptSetupRanges.withDefaultsArg.end);
const ast = ts.createSourceFile('/tmp.' + descriptor.scriptSetup.lang, '(' + defaultsText + ')', ts.ScriptTarget.Latest);
const obj = findObjectLiteralExpression(ast);

if (obj) {
for (const prop of obj.properties) {
if (ts.isPropertyAssignment(prop)) {
const name = prop.name.getText(ast);
const exp = prop.initializer.getText(ast);
result[name] = exp;
}
}
}

function findObjectLiteralExpression(node: ts.Node) {
if (ts.isObjectLiteralExpression(node)) {
return node;
}
let result: ts.ObjectLiteralExpression | undefined;
node.forEachChild(child => {
if (!result) {
result = findObjectLiteralExpression(child);
}
});
return result;
}
}

return result;
}
45 changes: 23 additions & 22 deletions packages/vue-component-meta/tests/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe(`vue-component-meta`, () => {
const enumValue = meta.props.find(prop => prop.name === 'enumValue');
const literalFromContext = meta.props.find(prop => prop.name === 'literalFromContext');
const literal = meta.props.find(prop => prop.name === 'literal');
const onEvent = meta.props.find(prop => prop.name === 'onEvent');
// const onEvent = meta.props.find(prop => prop.name === 'onEvent');

expect(foo).toBeDefined();
expect(foo?.required).toBeTruthy();
Expand All @@ -52,6 +52,7 @@ describe(`vue-component-meta`, () => {
]);

expect(bar).toBeDefined();
expect(bar?.default).toEqual('1');
expect(bar?.required).toBeFalsy();
expect(bar?.type).toEqual('number | undefined');
expect(bar?.description).toEqual('optional number bar');
Expand Down Expand Up @@ -267,27 +268,27 @@ describe(`vue-component-meta`, () => {
]
});

expect(onEvent).toBeDefined();
// expect(onEvent?.required).toBeFalsy()
expect(onEvent?.type).toEqual('((...args: any[]) => any) | undefined');
expect(onEvent?.schema).toEqual({
kind: 'enum',
type: '((...args: any[]) => any) | undefined',
schema: [
'undefined',
{
kind: 'event',
type: '(...args: any[]): any',
schema: [
{
kind: 'array',
type: 'any',
schema: [],
}
]
}
]
});
// expect(onEvent).toBeDefined();
// // expect(onEvent?.required).toBeFalsy()
// expect(onEvent?.type).toEqual('((...args: any[]) => any) | undefined');
// expect(onEvent?.schema).toEqual({
// kind: 'enum',
// type: '((...args: any[]) => any) | undefined',
// schema: [
// 'undefined',
// {
// kind: 'event',
// type: '(...args: any[]): any',
// schema: [
// {
// kind: 'array',
// type: 'any',
// schema: [],
// }
// ]
// }
// ]
// });
});

test('reference-type-events', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { MyProps } from './my-props';
defineEmits(['event']);
defineProps<MyProps>();
withDefaults(defineProps<MyProps>(), {
bar: 1,
});
</script>

0 comments on commit ddb2632

Please sign in to comment.