1- import type * as CompilerDOM from '@vue/compiler-dom' ;
1+ import * as CompilerDOM from '@vue/compiler-dom' ;
22import type { Code } from '../../types' ;
33import type { TemplateCodegenContext } from './context' ;
44import type { TemplateCodegenOptions } from './index' ;
5- import { generateTemplateChild } from './templateChild' ;
5+ import { generateTemplateChild , getVIfNode } from './templateChild' ;
66
77export function * generateElementChildren (
88 options : TemplateCodegenOptions ,
@@ -11,8 +11,92 @@ export function* generateElementChildren(
1111 enterNode = true ,
1212) : Generator < Code > {
1313 const endScope = ctx . startScope ( ) ;
14- for ( const childNode of children ) {
15- yield * generateTemplateChild ( options , ctx , childNode , enterNode ) ;
14+ for ( let i = 0 ; i < children . length ; i ++ ) {
15+ let current = children [ i ] ;
16+ [ current , i ] = normalizeIfBranch ( children , i ) ;
17+ yield * generateTemplateChild ( options , ctx , current , enterNode ) ;
1618 }
1719 yield * endScope ( ) ;
1820}
21+
22+ function normalizeIfBranch (
23+ children : ( CompilerDOM . TemplateChildNode | CompilerDOM . SimpleExpressionNode ) [ ] ,
24+ start : number ,
25+ ) : [ node : typeof children [ number ] , end : number ] {
26+ const first = children [ start ] ! ;
27+ if ( first . type !== CompilerDOM . NodeTypes . ELEMENT ) {
28+ return [ first , start ] ;
29+ }
30+
31+ const ifNode = getVIfNode ( first ) ;
32+ if ( ! ifNode ) {
33+ return [ first , start ] ;
34+ }
35+
36+ let end = start ;
37+ let comments : CompilerDOM . CommentNode [ ] = [ ] ;
38+
39+ for ( let i = start + 1 ; i < children . length ; i ++ ) {
40+ const sibling = children [ i ] ! ;
41+ if ( sibling . type === CompilerDOM . NodeTypes . SIMPLE_EXPRESSION ) {
42+ continue ;
43+ }
44+ if ( sibling . type === CompilerDOM . NodeTypes . COMMENT ) {
45+ comments . push ( sibling ) ;
46+ continue ;
47+ }
48+ if ( sibling . type === CompilerDOM . NodeTypes . TEXT && ! sibling . content . trim ( ) ) {
49+ continue ;
50+ }
51+ const elseBranch = getVElseDirective ( sibling ) ;
52+ if ( elseBranch ) {
53+ const branchNode : CompilerDOM . ElementNode = {
54+ ...elseBranch . element ,
55+ props : elseBranch . element . props . filter ( prop => prop !== elseBranch . directive ) ,
56+ } ;
57+
58+ const branch = createIfBranch ( branchNode , elseBranch . directive ) ;
59+ if ( comments . length ) {
60+ branch . children = [ ...comments , ...branch . children ] ;
61+ }
62+
63+ ifNode . branches . push ( branch ) ;
64+ comments = [ ] ;
65+ end = i ;
66+ continue ;
67+ }
68+ break ;
69+ }
70+
71+ return [ ifNode , end ] ;
72+ }
73+
74+ // source: https://github.com/vuejs/core/blob/25ebe3a42cd80ac0256355c2740a0258cdd7419d/packages/compiler-core/src/transforms/vIf.ts#L207
75+ function createIfBranch ( node : CompilerDOM . ElementNode , dir : CompilerDOM . DirectiveNode ) : CompilerDOM . IfBranchNode {
76+ const isTemplateIf = node . tagType === CompilerDOM . ElementTypes . TEMPLATE ;
77+ return {
78+ type : CompilerDOM . NodeTypes . IF_BRANCH ,
79+ loc : node . loc ,
80+ condition : dir . name === 'else' ? undefined : dir . exp ,
81+ children : isTemplateIf && ! CompilerDOM . findDir ( node , 'for' ) ? node . children : [ node ] ,
82+ userKey : CompilerDOM . findProp ( node , 'key' ) ,
83+ isTemplateIf,
84+ } ;
85+ }
86+
87+ function getVElseDirective ( node : CompilerDOM . TemplateChildNode ) {
88+ if ( node . type !== CompilerDOM . NodeTypes . ELEMENT ) {
89+ return ;
90+ }
91+ const directive = node . props . find (
92+ ( prop ) : prop is CompilerDOM . DirectiveNode =>
93+ prop . type === CompilerDOM . NodeTypes . DIRECTIVE
94+ && ( prop . name === 'else-if' || prop . name === 'else' ) ,
95+ ) ;
96+ if ( directive ) {
97+ return {
98+ element : node ,
99+ directive,
100+ } ;
101+ }
102+ }
0 commit comments