11import * as bt from '@babel/types'
22import recast from 'recast'
3- import { ASTElement , ASTExpression } from 'vue-template-compiler'
3+ import { ASTElement , ASTExpression , ASTNode } from 'vue-template-compiler'
44import buildParser from '../babel-parser'
5- import { Documentation } from '../Documentation'
5+ import { Documentation , ParamTag } from '../Documentation'
66import { TemplateParserOptions } from '../parse-template'
7+ import extractLeadingComment from '../utils/extractLeadingComment'
8+ import getDoclets from '../utils/getDoclets'
9+
10+ const parser = buildParser ( { plugins : [ 'typescript' ] } )
711
812const allowRE = / ^ ( v - b i n d | : ) /
913export default function propTemplateHandler (
@@ -12,35 +16,50 @@ export default function propTemplateHandler(
1216 options : TemplateParserOptions ,
1317) {
1418 if ( options . functional ) {
15- propsInAttributes ( templateAst , documentation )
16- propsInInterpolation ( templateAst , documentation )
19+ propsInAttributes ( templateAst , documentation , options )
20+ propsInInterpolation ( templateAst , documentation , options )
1721 }
1822}
1923
20- function propsInAttributes ( templateAst : ASTElement , documentation : Documentation ) {
24+ function propsInAttributes (
25+ templateAst : ASTElement ,
26+ documentation : Documentation ,
27+ options : TemplateParserOptions ,
28+ ) {
2129 const bindings = templateAst . attrsMap
2230 const keys = Object . keys ( bindings )
2331 for ( const key of keys ) {
2432 // only look at expressions
2533 if ( allowRE . test ( key ) ) {
2634 const expression = bindings [ key ]
27- getPropsFromExpression ( expression , documentation )
35+ getPropsFromExpression ( templateAst . parent , templateAst , expression , documentation , options )
2836 }
2937 }
3038}
3139
32- function propsInInterpolation ( templateAst : ASTElement , documentation : Documentation ) {
40+ function propsInInterpolation (
41+ templateAst : ASTElement ,
42+ documentation : Documentation ,
43+ options : TemplateParserOptions ,
44+ ) {
3345 if ( templateAst . children ) {
3446 templateAst . children
3547 . filter ( c => c . type === 2 )
3648 . forEach ( ( expr : ASTExpression ) => {
37- getPropsFromExpression ( expr . expression , documentation )
49+ getPropsFromExpression ( templateAst , expr , expr . expression , documentation , options )
3850 } )
3951 }
4052}
4153
42- function getPropsFromExpression ( expression : string , documentation : Documentation ) {
43- const ast = buildParser ( { plugins : [ 'typescript' ] } ) . parse ( expression )
54+ function getPropsFromExpression (
55+ parentAst : ASTElement | undefined ,
56+ item : ASTNode ,
57+ expression : string ,
58+ documentation : Documentation ,
59+ options : TemplateParserOptions ,
60+ ) {
61+ const ast = parser . parse ( expression )
62+ const propsFound : string [ ] = [ ]
4463 recast . visit ( ast . program , {
4564 visitMemberExpression ( path ) {
4665 const obj = path . node ? path . node . object : undefined
@@ -54,9 +73,27 @@ function getPropsFromExpression(expression: string, documentation: Documentation
5473 ) {
5574 const pName = propName . name
5675 const p = documentation . getPropDescriptor ( pName )
76+ propsFound . push ( pName )
5777 p . type = { name : 'undefined' }
5878 }
5979 return false
6080 } ,
6181 } )
82+ if ( propsFound . length ) {
83+ const comment = extractLeadingComment ( parentAst , item , options . rootLeadingComment )
84+ const doclets = getDoclets ( comment )
85+ const propTags = doclets . tags && ( doclets . tags . filter ( d => d . title === 'prop' ) as ParamTag [ ] )
86+ if ( propTags && propTags . length ) {
87+ propsFound . forEach ( pName => {
88+ const propTag = propTags . filter ( pt => pt . name === pName )
89+ if ( propTag . length ) {
90+ const p = documentation . getPropDescriptor ( pName )
91+ p . type = propTag [ 0 ] . type
92+ if ( typeof propTag [ 0 ] . description === 'string' ) {
93+ p . description = propTag [ 0 ] . description
94+ }
95+ }
96+ } )
97+ }
98+ }
6299}
0 commit comments