@@ -8,6 +8,17 @@ const webTypes = JSON.parse(
8
8
readFileSync ( "./node_modules/vuetify/dist/json/web-types.json" )
9
9
) ;
10
10
11
+ const tags = webTypes . contributions . html . tags ;
12
+
13
+ // https://github.com/vuetifyjs/vuetify/pull/18307
14
+ // Remove it after Vuetify 2.7.2 released
15
+ tags
16
+ . find ( ( component ) => component . name === "VDialog" )
17
+ . slots [ 0 ] [ "vue-properties" ] . push ( {
18
+ name : "attrs" ,
19
+ type : "{ role: string, aria-haspopup: boolean, aria-expanded: string }" ,
20
+ } ) ;
21
+
11
22
const blackList = [ "VFlex" , "VLayout" ] ; // Components not to define in global
12
23
13
24
function convertType ( typeStr ) {
@@ -20,6 +31,8 @@ function convertType(typeStr) {
20
31
return "Date" ;
21
32
case "regexp" :
22
33
return "RegExp" ;
34
+ case "event" :
35
+ return "Event" ;
23
36
default :
24
37
return typeStr ;
25
38
}
@@ -28,7 +41,7 @@ function convertType(typeStr) {
28
41
function getPropType ( attr ) {
29
42
const attrType = attr . value . type ;
30
43
if ( attr . name == "rules" && attr . description ?. includes ( "error message" ) ) {
31
- return "InputValidationRules"
44
+ return "InputValidationRules" ;
32
45
}
33
46
if ( typeof attrType === "string" ) {
34
47
return convertType ( attrType ) ;
@@ -50,7 +63,7 @@ function getSlotPropType(type) {
50
63
. replace ( / \/ \/ .* / , "" )
51
64
. replaceAll ( "):" , ")=>" )
52
65
. replace ( / ( a r i a - [ a - z ] * ) : / g, '"$1":' )
53
- . replace ( / = \w * / g, '' ) // remove default values
66
+ . replace ( / = \w * / g, "" ) // remove default values
54
67
. replaceAll ( "function" , "Function" )
55
68
. replaceAll ( "Function" , "(...args: any[]) => any" )
56
69
. replaceAll ( "object" , "{ [key: keyof any]: any }" )
@@ -62,30 +75,82 @@ function getSlotName(name) {
62
75
return "[name:`header.${string}`]" ;
63
76
} else if ( name === "item.<name>" ) {
64
77
return "[name:`item.${string}`]" ;
65
- } else if ( name . startsWith ( "item.data-table" ) || name . startsWith ( "header.data-table" ) ) {
78
+ } else if (
79
+ name . startsWith ( "item.data-table" ) ||
80
+ name . startsWith ( "header.data-table" )
81
+ ) {
82
+ // Ts doesn't allow overriding template literals with more specific keys/values.
83
+ return `//@ts-expect-error\n '${ name } '` ;
84
+ }
85
+ return `'${ name } '` ;
86
+ }
87
+
88
+ function splitByComma ( str ) {
89
+ const result = [ ] ;
90
+ let current = "" ;
91
+ let level = 0 ;
92
+ for ( let i = 0 ; i < str . length ; i ++ ) {
93
+ const char = str [ i ] ;
94
+ if ( char === "{" ) {
95
+ level ++ ;
96
+ }
97
+ if ( char === "}" ) {
98
+ level -- ;
99
+ }
100
+ if ( char === "," && level === 0 ) {
101
+ result . push ( current ) ;
102
+ current = "" ;
103
+ } else {
104
+ current += char ;
105
+ }
106
+ }
107
+ result . push ( current ) ;
108
+ return result ;
109
+ }
110
+
111
+ function getEventArguments ( args ) {
112
+ const _args = args
113
+ . replaceAll ( ':"' , ":" )
114
+ . replaceAll ( '",' , "," )
115
+ . replaceAll ( '"}' , "}" )
116
+ . replaceAll ( "):" , ")=>" )
117
+ . replace ( / = \w * / g, "" ) // remove default values
118
+ . replaceAll ( "ClickEvent" , "MouseEvent" ) ;
119
+
120
+ // event may have multiple arguments
121
+ const matches = splitByComma ( _args )
122
+ . map ( ( a , i ) => `arg${ i } :${ convertType ( a ) } ` )
123
+ . join ( "," ) ;
124
+ return matches ;
125
+ }
126
+
127
+ function getEventName ( name ) {
128
+ if ( name === "<event>:row" ) {
129
+ return "[name:`${string}:row`]" ;
130
+ } else if ( name . startsWith ( "click:row" ) ) {
66
131
// Ts doesn't allow overriding template literals with more specific keys/values.
67
132
return `//@ts-expect-error\n '${ name } '` ;
68
133
}
69
134
return `'${ name } '` ;
70
135
}
71
136
72
- const types = webTypes . contributions . html . tags
137
+ const types = tags
73
138
. filter ( ( vm ) => ! blackList . includes ( vm . name ) )
74
139
. map (
75
140
( vm ) =>
76
141
vm . name +
77
142
": DefineComponent<{" +
78
-
79
143
// Prop types:
80
144
vm . attributes
81
145
. map (
82
146
( attr ) =>
83
147
getDescription ( attr ) +
84
- `${ attr . name . replace ( / - ./ g, ( x ) => x [ 1 ] . toUpperCase ( ) ) } ?: ${ getPropType ( attr ) } | null`
148
+ `${ attr . name . replace ( / - ./ g, ( x ) =>
149
+ x [ 1 ] . toUpperCase ( )
150
+ ) } ?: ${ getPropType ( attr ) } | null`
85
151
)
86
152
. join ( "\n" ) +
87
153
"}" +
88
-
89
154
// Slot types:
90
155
( vm . slots ?. length
91
156
? ",{$scopedSlots: Readonly<{\n" +
@@ -107,15 +172,29 @@ const types = webTypes.contributions.html.tags
107
172
)
108
173
. join ( "\n" ) +
109
174
"}>}\n"
175
+ : ",{}" ) +
176
+ // Event types:
177
+ ( vm . events ?. length
178
+ ? ",{},{},{},{},{},{\n" +
179
+ vm . events
180
+ . map (
181
+ ( event ) =>
182
+ getDescription ( event ) +
183
+ `${ getEventName ( event . name ) } :(${ getEventArguments (
184
+ event . arguments [ 0 ] . type
185
+ ) } )=>void`
186
+ )
187
+ . join ( "\n" ) +
188
+ "}"
110
189
: "" ) +
111
190
">"
112
191
)
113
192
. join ( "\n\n" ) ;
114
193
115
194
console . log ( ) ;
116
195
117
- console . log (
118
- prettier . format (
196
+ prettier
197
+ . format (
119
198
`
120
199
import type { DataTableHeader, DataOptions, CalendarTimestamp as VTimestamp } from 'vuetify'
121
200
import type VueComponent from "vue"
@@ -147,4 +226,4 @@ export {}`,
147
226
semi : false ,
148
227
}
149
228
)
150
- ) ;
229
+ . then ( ( v ) => console . log ( v ) ) ;
0 commit comments