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'
23
34// copy from `@vue/compiler-dom`
45enum NodeTypes {
@@ -37,14 +38,8 @@ enum NodeTypes {
3738 JS_RETURN_STATEMENT ,
3839}
3940
40- interface ExpressionTrack {
41- type : NodeTypes
42- name ?: string
43- forParseResult ?: ForParseResult
44- }
45-
4641interface Expression {
47- track : ExpressionTrack [ ]
42+ track : VueTemplateNode [ ]
4843 loc : SourceLocation
4944 src : string
5045 replacement ?: string
@@ -60,7 +55,7 @@ type VueTemplateNode =
6055function handleNode (
6156 node : VueTemplateNode | undefined ,
6257 addExpression : ( ...expressions : Expression [ ] ) => void ,
63- track : ExpressionTrack [ ] ,
58+ track : VueTemplateNode [ ] ,
6459) {
6560 if ( ! node ) {
6661 return
@@ -264,6 +259,43 @@ const defaultSnippetHandler: SnippetHandler = {
264259 standalone : false ,
265260}
266261
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+
267299const destructureSnippetHandler : SnippetHandler = {
268300 key : ( node ) => {
269301 const key = `destructure$:${ node . src } `
@@ -299,7 +331,7 @@ const destructureSnippetHandler: SnippetHandler = {
299331 standalone : true ,
300332}
301333
302- const snippetHandlers = [ destructureSnippetHandler , defaultSnippetHandler ]
334+ const snippetHandlers = [ destructureSnippetHandler , multipleStatementsSnippetHandler , defaultSnippetHandler ]
303335function getKey ( expression : Expression ) {
304336 for ( const handler of snippetHandlers ) {
305337 const key = handler . key ( expression )
0 commit comments