import { StructuralDirectiveTransform , NodeTransform , NodeTypes } from '../../shared/svu' ; import { createConditionalExpression , createCallExpression , } from '../ast' ; import { traverseNode } from '../transform' ; function createStructuralDirectiveTransform ( name , fn ) { const matches = ( n ) => name . test ( n ) ; return ( node , context ) => { if ( node . type === NodeTypes . ELEMENT ) { const { props } = node ; const exitFns = [ ] ; for ( let i = 0 ; i < props . length ; i ++ ) { const prop = props [ i ] ; if ( prop . type === NodeTypes . DIRECTIVE && matches ( prop . name ) ) { props . splice ( i , 1 ) ; i -- ; const onExit = fn ( node , prop , context ) ; onExit && exitFns . push ( onExit ) ; } } return exitFns ; } } ; } export const transformIf = createStructuralDirectiveTransform ( /^(if|else|else-if)$/ , ( node , dir , context ) => { return processIf ( node , dir , context , ( ifNode , branch , isRoot ) => { return ( ) => { if ( isRoot ) { ifNode . codegenNode = createCodegenNodeForBranch ( branch , context ) ; } else { const parentCondition = getParentCondition ( ifNode . codegenNode ! ) ; parentCondition . alternate = createCodegenNodeForBranch ( branch , context ) ; } } ; } ) ; } ) ; export function processIf ( node , dir , context , processCodegen ? ) { if ( dir . name === 'if' ) { const branch = createIfBranch ( node , dir ) ; const ifNode = { type : NodeTypes . IF , loc : node . loc , branches : [ branch ] } ; context . replaceNode ( ifNode ) ; if ( processCodegen ) { return processCodegen ( ifNode , branch , true ) ; } } else { const siblings = context . parent ! . children ; let i = siblings . indexOf ( node ) ; while ( i -- >= - 1 ) { const sibling = siblings [ i ] ; if ( sibling && sibling . type === NodeTypes . IF ) { context . removeNode ( ) ; const branch = createIfBranch ( node , dir ) ; sibling . branches . push ( branch ) ; const onExit = processCodegen && processCodegen ( sibling , branch , false ) ; traverseNode ( branch , context ) ; onExit && onExit ( ) ; context . currentNode = null ; } break ; } } } function createIfBranch ( node , dir ) { return { type : NodeTypes . IF_BRANCH , loc : node . loc , condition : dir . name === 'else' ? undefined : dir . exp , children : [ node ] , } ; } function createCodegenNodeForBranch ( branch , context ) { if ( branch . condition ) { return createConditionalExpression ( branch . condition , createChildrenCodegenNode ( branch , context ) , createCallExpression ( context . helper ( 'CREATE_COMMENT' ) , [ '""' , 'true' ] ) ) ; } else { return createChildrenCodegenNode ( branch , context ) ; } } function createChildrenCodegenNode ( branch , context ) { const { helper } = context ; const { children } = branch ; const firstChild = children [ 0 ] ; const vnodeCall = firstChild . codegenNode ; if ( vnodeCall . type === NodeTypes . VNODE_CALL ) { vnodeCall . isBlock = true ; helper ( 'OPEN_BLOCK' ) ; helper ( 'CREATE_BLOCK' ) ; } return vnodeCall ; } function getParentCondition ( node ) { while ( true ) { if ( node . type === NodeTypes . JS_CONDITIONAL_EXPRESSION ) { return node ; } } }