1
- import type { AttributeNode , DirectiveNode , ExpressionNode , ForParseResult , ParentNode , RootNode , SourceLocation , TemplateChildNode , TextNode } from '@vue/compiler-dom'
1
+ import type { AttributeNode , DirectiveNode , ExpressionNode , ParentNode , RootNode , SourceLocation , TemplateChildNode , TextNode } from '@vue/compiler-dom'
2
+ import { isFnExpressionBrowser as isFnExpression , isMemberExpressionBrowser as isMemberExpression } from '@vue/compiler-core'
2
3
3
4
// copy from `@vue/compiler-dom`
4
5
enum NodeTypes {
@@ -37,14 +38,8 @@ enum NodeTypes {
37
38
JS_RETURN_STATEMENT ,
38
39
}
39
40
40
- interface ExpressionTrack {
41
- type : NodeTypes
42
- name ?: string
43
- forParseResult ?: ForParseResult
44
- }
45
-
46
41
interface Expression {
47
- track : ExpressionTrack [ ]
42
+ track : VueTemplateNode [ ]
48
43
loc : SourceLocation
49
44
src : string
50
45
replacement ?: string
@@ -60,7 +55,7 @@ type VueTemplateNode =
60
55
function handleNode (
61
56
node : VueTemplateNode | undefined ,
62
57
addExpression : ( ...expressions : Expression [ ] ) => void ,
63
- track : ExpressionTrack [ ] ,
58
+ track : VueTemplateNode [ ] ,
64
59
) {
65
60
if ( ! node ) {
66
61
return
@@ -264,6 +259,43 @@ const defaultSnippetHandler: SnippetHandler = {
264
259
standalone : false ,
265
260
}
266
261
262
+ const multipleStatementsSnippetHandler : SnippetHandler = {
263
+ key : ( node ) => {
264
+ const key = `multipleStatements$:${ node . src } `
265
+ const secondLastTrack = node . track . at ( - 2 )
266
+ const lastTrack = node . track . at ( - 1 )
267
+
268
+ if (
269
+ lastTrack ?. type === NodeTypes . SIMPLE_EXPRESSION
270
+ && secondLastTrack ?. type === NodeTypes . DIRECTIVE
271
+ && secondLastTrack . name === 'on'
272
+ ) {
273
+ const isMemberExp = isMemberExpression ( lastTrack )
274
+ const isInlineStatement = ! ( isMemberExp || isFnExpression ( lastTrack ) )
275
+
276
+ const hasMultipleStatements = node . src . includes ( ';' )
277
+
278
+ if ( ( isInlineStatement || isMemberExp ) && hasMultipleStatements ) {
279
+ return key
280
+ }
281
+ }
282
+
283
+ return null
284
+ } ,
285
+ prepare : ( node , id ) => `wrapper_${ id } (() => {${ node . src } });` ,
286
+ parse : ( code ) => {
287
+ const wrapperRegex = / ^ ( w r a p p e r _ \d + ) \( \( \) = > \{ ( [ \s \S ] * ?) \} \) ; $ /
288
+
289
+ const [ _ , wrapperName , res ] = code . trim ( ) . match ( wrapperRegex ) ?? [ ]
290
+ if ( ! wrapperName || ! res ) {
291
+ return undefined
292
+ }
293
+
294
+ return res . trim ( ) . replace ( / ; $ / , '' )
295
+ } ,
296
+ standalone : false ,
297
+ }
298
+
267
299
const destructureSnippetHandler : SnippetHandler = {
268
300
key : ( node ) => {
269
301
const key = `destructure$:${ node . src } `
@@ -299,7 +331,7 @@ const destructureSnippetHandler: SnippetHandler = {
299
331
standalone : true ,
300
332
}
301
333
302
- const snippetHandlers = [ destructureSnippetHandler , defaultSnippetHandler ]
334
+ const snippetHandlers = [ destructureSnippetHandler , multipleStatementsSnippetHandler , defaultSnippetHandler ]
303
335
function getKey ( expression : Expression ) {
304
336
for ( const handler of snippetHandlers ) {
305
337
const key = handler . key ( expression )
0 commit comments