2023-07-24 11:13:08 +08:00
'use strict' ;
Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
var compilerDom = require ( '@vue/compiler-dom' ) ;
var shared = require ( '@vue/shared' ) ;
const SSR _INTERPOLATE = Symbol ( ` ssrInterpolate ` ) ;
const SSR _RENDER _VNODE = Symbol ( ` ssrRenderVNode ` ) ;
const SSR _RENDER _COMPONENT = Symbol ( ` ssrRenderComponent ` ) ;
const SSR _RENDER _SLOT = Symbol ( ` ssrRenderSlot ` ) ;
const SSR _RENDER _SLOT _INNER = Symbol ( ` ssrRenderSlotInner ` ) ;
const SSR _RENDER _CLASS = Symbol ( ` ssrRenderClass ` ) ;
const SSR _RENDER _STYLE = Symbol ( ` ssrRenderStyle ` ) ;
const SSR _RENDER _ATTRS = Symbol ( ` ssrRenderAttrs ` ) ;
const SSR _RENDER _ATTR = Symbol ( ` ssrRenderAttr ` ) ;
const SSR _RENDER _DYNAMIC _ATTR = Symbol ( ` ssrRenderDynamicAttr ` ) ;
const SSR _RENDER _LIST = Symbol ( ` ssrRenderList ` ) ;
const SSR _INCLUDE _BOOLEAN _ATTR = Symbol ( ` ssrIncludeBooleanAttr ` ) ;
const SSR _LOOSE _EQUAL = Symbol ( ` ssrLooseEqual ` ) ;
const SSR _LOOSE _CONTAIN = Symbol ( ` ssrLooseContain ` ) ;
const SSR _RENDER _DYNAMIC _MODEL = Symbol ( ` ssrRenderDynamicModel ` ) ;
const SSR _GET _DYNAMIC _MODEL _PROPS = Symbol ( ` ssrGetDynamicModelProps ` ) ;
const SSR _RENDER _TELEPORT = Symbol ( ` ssrRenderTeleport ` ) ;
const SSR _RENDER _SUSPENSE = Symbol ( ` ssrRenderSuspense ` ) ;
const SSR _GET _DIRECTIVE _PROPS = Symbol ( ` ssrGetDirectiveProps ` ) ;
const ssrHelpers = {
2023-09-06 09:51:55 +08:00
[ SSR _INTERPOLATE ] : ` ssrInterpolate ` ,
[ SSR _RENDER _VNODE ] : ` ssrRenderVNode ` ,
[ SSR _RENDER _COMPONENT ] : ` ssrRenderComponent ` ,
[ SSR _RENDER _SLOT ] : ` ssrRenderSlot ` ,
[ SSR _RENDER _SLOT _INNER ] : ` ssrRenderSlotInner ` ,
[ SSR _RENDER _CLASS ] : ` ssrRenderClass ` ,
[ SSR _RENDER _STYLE ] : ` ssrRenderStyle ` ,
[ SSR _RENDER _ATTRS ] : ` ssrRenderAttrs ` ,
[ SSR _RENDER _ATTR ] : ` ssrRenderAttr ` ,
[ SSR _RENDER _DYNAMIC _ATTR ] : ` ssrRenderDynamicAttr ` ,
[ SSR _RENDER _LIST ] : ` ssrRenderList ` ,
[ SSR _INCLUDE _BOOLEAN _ATTR ] : ` ssrIncludeBooleanAttr ` ,
[ SSR _LOOSE _EQUAL ] : ` ssrLooseEqual ` ,
[ SSR _LOOSE _CONTAIN ] : ` ssrLooseContain ` ,
[ SSR _RENDER _DYNAMIC _MODEL ] : ` ssrRenderDynamicModel ` ,
[ SSR _GET _DYNAMIC _MODEL _PROPS ] : ` ssrGetDynamicModelProps ` ,
[ SSR _RENDER _TELEPORT ] : ` ssrRenderTeleport ` ,
[ SSR _RENDER _SUSPENSE ] : ` ssrRenderSuspense ` ,
[ SSR _GET _DIRECTIVE _PROPS ] : ` ssrGetDirectiveProps `
2023-07-24 11:13:08 +08:00
} ;
compilerDom . registerRuntimeHelpers ( ssrHelpers ) ;
2023-09-06 09:51:55 +08:00
const ssrTransformIf = compilerDom . createStructuralDirectiveTransform (
/^(if|else|else-if)$/ ,
compilerDom . processIf
) ;
2023-07-24 11:13:08 +08:00
function ssrProcessIf ( node , context , disableNestedFragments = false ) {
2023-09-06 09:51:55 +08:00
const [ rootBranch ] = node . branches ;
const ifStatement = compilerDom . createIfStatement (
rootBranch . condition ,
processIfBranch ( rootBranch , context , disableNestedFragments )
) ;
context . pushStatement ( ifStatement ) ;
let currentIf = ifStatement ;
for ( let i = 1 ; i < node . branches . length ; i ++ ) {
const branch = node . branches [ i ] ;
const branchBlockStatement = processIfBranch (
branch ,
context ,
disableNestedFragments
) ;
if ( branch . condition ) {
currentIf = currentIf . alternate = compilerDom . createIfStatement (
branch . condition ,
branchBlockStatement
) ;
} else {
currentIf . alternate = branchBlockStatement ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
if ( ! currentIf . alternate ) {
currentIf . alternate = compilerDom . createBlockStatement ( [
compilerDom . createCallExpression ( ` _push ` , [ "`<!---->`" ] )
] ) ;
}
2023-07-24 11:13:08 +08:00
}
function processIfBranch ( branch , context , disableNestedFragments = false ) {
2023-09-06 09:51:55 +08:00
const { children } = branch ;
const needFragmentWrapper = ! disableNestedFragments && ( children . length !== 1 || children [ 0 ] . type !== 1 ) && // optimize away nested fragments when the only child is a ForNode
! ( children . length === 1 && children [ 0 ] . type === 11 ) ;
return processChildrenAsStatement ( branch , context , needFragmentWrapper ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
const ssrTransformFor = compilerDom . createStructuralDirectiveTransform (
"for" ,
compilerDom . processFor
) ;
2023-07-24 11:13:08 +08:00
function ssrProcessFor ( node , context , disableNestedFragments = false ) {
2023-09-06 09:51:55 +08:00
const needFragmentWrapper = ! disableNestedFragments && ( node . children . length !== 1 || node . children [ 0 ] . type !== 1 ) ;
const renderLoop = compilerDom . createFunctionExpression (
compilerDom . createForLoopParams ( node . parseResult )
) ;
renderLoop . body = processChildrenAsStatement (
node ,
context ,
needFragmentWrapper
) ;
if ( ! disableNestedFragments ) {
context . pushStringPart ( ` <!--[--> ` ) ;
}
context . pushStatement (
compilerDom . createCallExpression ( context . helper ( SSR _RENDER _LIST ) , [
node . source ,
renderLoop
] )
) ;
if ( ! disableNestedFragments ) {
context . pushStringPart ( ` <!--]--> ` ) ;
}
2023-07-24 11:13:08 +08:00
}
const ssrTransformSlotOutlet = ( node , context ) => {
2023-09-06 09:51:55 +08:00
if ( compilerDom . isSlotOutlet ( node ) ) {
const { slotName , slotProps } = compilerDom . processSlotOutlet ( node , context ) ;
const args = [
` _ctx. $ slots ` ,
slotName ,
slotProps || ` {} ` ,
// fallback content placeholder. will be replaced in the process phase
` null ` ,
` _push ` ,
` _parent `
] ;
if ( context . scopeId && context . slotted !== false ) {
args . push ( ` " ${ context . scopeId } -s" ` ) ;
}
let method = SSR _RENDER _SLOT ;
const parent = context . parent ;
if ( parent && parent . type === 1 && parent . tagType === 1 && compilerDom . resolveComponentType ( parent , context , true ) === compilerDom . TRANSITION && parent . children . filter ( ( c ) => c . type === 1 ) . length === 1 ) {
method = SSR _RENDER _SLOT _INNER ;
if ( ! ( context . scopeId && context . slotted !== false ) ) {
args . push ( "null" ) ;
}
args . push ( "true" ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
node . ssrCodegenNode = compilerDom . createCallExpression ( context . helper ( method ) , args ) ;
}
2023-07-24 11:13:08 +08:00
} ;
function ssrProcessSlotOutlet ( node , context ) {
2023-09-06 09:51:55 +08:00
const renderCall = node . ssrCodegenNode ;
if ( node . children . length ) {
const fallbackRenderFn = compilerDom . createFunctionExpression ( [ ] ) ;
fallbackRenderFn . body = processChildrenAsStatement ( node , context ) ;
renderCall . arguments [ 3 ] = fallbackRenderFn ;
}
if ( context . withSlotScopeId ) {
const slotScopeId = renderCall . arguments [ 6 ] ;
renderCall . arguments [ 6 ] = slotScopeId ? ` ${ slotScopeId } + _scopeId ` : ` _scopeId ` ;
}
context . pushStatement ( node . ssrCodegenNode ) ;
2023-07-24 11:13:08 +08:00
}
function createSSRCompilerError ( code , loc ) {
2023-09-06 09:51:55 +08:00
return compilerDom . createCompilerError ( code , loc , SSRErrorMessages ) ;
2023-07-24 11:13:08 +08:00
}
const SSRErrorMessages = {
2023-09-06 09:51:55 +08:00
[ 65 ] : ` Unsafe attribute name for SSR. ` ,
[ 66 ] : ` Missing the 'to' prop on teleport element. ` ,
[ 67 ] : ` Invalid AST node during SSR transform. `
2023-07-24 11:13:08 +08:00
} ;
function ssrProcessTeleport ( node , context ) {
2023-09-06 09:51:55 +08:00
const targetProp = compilerDom . findProp ( node , "to" ) ;
if ( ! targetProp ) {
context . onError (
createSSRCompilerError ( 66 , node . loc )
) ;
return ;
}
let target ;
if ( targetProp . type === 6 ) {
target = targetProp . value && compilerDom . createSimpleExpression ( targetProp . value . content , true ) ;
} else {
target = targetProp . exp ;
}
if ( ! target ) {
context . onError (
createSSRCompilerError (
66 ,
targetProp . loc
)
) ;
return ;
}
const disabledProp = compilerDom . findProp (
node ,
"disabled" ,
false ,
true
/* allow empty */
) ;
const disabled = disabledProp ? disabledProp . type === 6 ? ` true ` : disabledProp . exp || ` false ` : ` false ` ;
const contentRenderFn = compilerDom . createFunctionExpression (
[ ` _push ` ] ,
void 0 ,
// Body is added later
true ,
// newline
false ,
// isSlot
node . loc
) ;
contentRenderFn . body = processChildrenAsStatement ( node , context ) ;
context . pushStatement (
compilerDom . createCallExpression ( context . helper ( SSR _RENDER _TELEPORT ) , [
` _push ` ,
contentRenderFn ,
target ,
disabled ,
` _parent `
] )
) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
const wipMap$2 = /* @__PURE__ */ new WeakMap ( ) ;
2023-07-24 11:13:08 +08:00
function ssrTransformSuspense ( node , context ) {
2023-09-06 09:51:55 +08:00
return ( ) => {
if ( node . children . length ) {
const wipEntry = {
slotsExp : null ,
// to be immediately set
wipSlots : [ ]
} ;
wipMap$2 . set ( node , wipEntry ) ;
wipEntry . slotsExp = compilerDom . buildSlots ( node , context , ( _props , children , loc ) => {
const fn = compilerDom . createFunctionExpression (
[ ] ,
void 0 ,
// no return, assign body later
true ,
// newline
false ,
// suspense slots are not treated as normal slots
loc
) ;
wipEntry . wipSlots . push ( {
fn ,
children
} ) ;
return fn ;
} ) . slots ;
}
} ;
2023-07-24 11:13:08 +08:00
}
function ssrProcessSuspense ( node , context ) {
2023-09-06 09:51:55 +08:00
const wipEntry = wipMap$2 . get ( node ) ;
if ( ! wipEntry ) {
return ;
}
const { slotsExp , wipSlots } = wipEntry ;
for ( let i = 0 ; i < wipSlots . length ; i ++ ) {
const slot = wipSlots [ i ] ;
slot . fn . body = processChildrenAsStatement ( slot , context ) ;
}
context . pushStatement (
compilerDom . createCallExpression ( context . helper ( SSR _RENDER _SUSPENSE ) , [
` _push ` ,
slotsExp
] )
) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
const rawChildrenMap = /* @__PURE__ */ new WeakMap ( ) ;
2023-07-24 11:13:08 +08:00
const ssrTransformElement = ( node , context ) => {
2023-09-06 09:51:55 +08:00
if ( node . type !== 1 || node . tagType !== 0 ) {
return ;
}
return function ssrPostTransformElement ( ) {
const openTag = [ ` < ${ node . tag } ` ] ;
const needTagForRuntime = node . tag === "textarea" || node . tag . indexOf ( "-" ) > 0 ;
const hasDynamicVBind = compilerDom . hasDynamicKeyVBind ( node ) ;
const hasCustomDir = node . props . some (
( p ) => p . type === 7 && ! shared . isBuiltInDirective ( p . name )
) ;
const needMergeProps = hasDynamicVBind || hasCustomDir ;
if ( needMergeProps ) {
const { props , directives } = compilerDom . buildProps (
node ,
context ,
node . props ,
false ,
false ,
true
/* ssr */
) ;
if ( props || directives . length ) {
const mergedProps = buildSSRProps ( props , directives , context ) ;
const propsExp = compilerDom . createCallExpression (
context . helper ( SSR _RENDER _ATTRS ) ,
[ mergedProps ]
) ;
if ( node . tag === "textarea" ) {
const existingText = node . children [ 0 ] ;
if ( ! existingText || existingText . type !== 5 ) {
const tempId = ` _temp ${ context . temps ++ } ` ;
propsExp . arguments = [
compilerDom . createAssignmentExpression (
compilerDom . createSimpleExpression ( tempId , false ) ,
mergedProps
)
] ;
rawChildrenMap . set (
node ,
compilerDom . createCallExpression ( context . helper ( SSR _INTERPOLATE ) , [
compilerDom . createConditionalExpression (
compilerDom . createSimpleExpression ( ` "value" in ${ tempId } ` , false ) ,
compilerDom . createSimpleExpression ( ` ${ tempId } .value ` , false ) ,
compilerDom . createSimpleExpression (
existingText ? existingText . content : ` ` ,
true
) ,
false
)
] )
) ;
}
} else if ( node . tag === "input" ) {
const vModel = findVModel ( node ) ;
if ( vModel ) {
const tempId = ` _temp ${ context . temps ++ } ` ;
const tempExp = compilerDom . createSimpleExpression ( tempId , false ) ;
propsExp . arguments = [
compilerDom . createSequenceExpression ( [
compilerDom . createAssignmentExpression ( tempExp , mergedProps ) ,
compilerDom . createCallExpression ( context . helper ( compilerDom . MERGE _PROPS ) , [
tempExp ,
compilerDom . createCallExpression (
context . helper ( SSR _GET _DYNAMIC _MODEL _PROPS ) ,
[
tempExp ,
// existing props
vModel . exp
// model
]
)
] )
] )
] ;
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
if ( needTagForRuntime ) {
propsExp . arguments . push ( ` " ${ node . tag } " ` ) ;
}
openTag . push ( propsExp ) ;
}
}
let dynamicClassBinding = void 0 ;
let staticClassBinding = void 0 ;
let dynamicStyleBinding = void 0 ;
for ( let i = 0 ; i < node . props . length ; i ++ ) {
const prop = node . props [ i ] ;
if ( node . tag === "input" && isTrueFalseValue ( prop ) ) {
continue ;
}
if ( prop . type === 7 ) {
if ( prop . name === "html" && prop . exp ) {
rawChildrenMap . set ( node , prop . exp ) ;
} else if ( prop . name === "text" && prop . exp ) {
node . children = [ compilerDom . createInterpolation ( prop . exp , prop . loc ) ] ;
} else if ( prop . name === "slot" ) {
context . onError (
compilerDom . createCompilerError ( 40 , prop . loc )
) ;
} else if ( isTextareaWithValue ( node , prop ) && prop . exp ) {
if ( ! needMergeProps ) {
node . children = [ compilerDom . createInterpolation ( prop . exp , prop . loc ) ] ;
}
} else if ( ! needMergeProps && prop . name !== "on" ) {
const directiveTransform = context . directiveTransforms [ prop . name ] ;
if ( directiveTransform ) {
const { props , ssrTagParts } = directiveTransform (
prop ,
node ,
context
) ;
if ( ssrTagParts ) {
openTag . push ( ... ssrTagParts ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
for ( let j = 0 ; j < props . length ; j ++ ) {
const { key , value } = props [ j ] ;
if ( compilerDom . isStaticExp ( key ) ) {
let attrName = key . content ;
if ( attrName === "key" || attrName === "ref" ) {
continue ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
if ( attrName === "class" ) {
openTag . push (
` class=" ` ,
dynamicClassBinding = compilerDom . createCallExpression (
context . helper ( SSR _RENDER _CLASS ) ,
[ value ]
) ,
` " `
) ;
} else if ( attrName === "style" ) {
if ( dynamicStyleBinding ) {
mergeCall ( dynamicStyleBinding , value ) ;
} else {
openTag . push (
` style=" ` ,
dynamicStyleBinding = compilerDom . createCallExpression (
context . helper ( SSR _RENDER _STYLE ) ,
[ value ]
) ,
` " `
) ;
}
} else {
attrName = node . tag . indexOf ( "-" ) > 0 ? attrName : shared . propsToAttrMap [ attrName ] || attrName . toLowerCase ( ) ;
if ( shared . isBooleanAttr ( attrName ) ) {
openTag . push (
compilerDom . createConditionalExpression (
compilerDom . createCallExpression (
context . helper ( SSR _INCLUDE _BOOLEAN _ATTR ) ,
[ value ]
) ,
compilerDom . createSimpleExpression ( " " + attrName , true ) ,
compilerDom . createSimpleExpression ( "" , true ) ,
false
/* no newline */
)
) ;
} else if ( shared . isSSRSafeAttrName ( attrName ) ) {
openTag . push (
compilerDom . createCallExpression ( context . helper ( SSR _RENDER _ATTR ) , [
key ,
value
] )
) ;
} else {
context . onError (
createSSRCompilerError (
65 ,
key . loc
)
) ;
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
} else {
const args = [ key , value ] ;
if ( needTagForRuntime ) {
args . push ( ` " ${ node . tag } " ` ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
openTag . push (
compilerDom . createCallExpression (
context . helper ( SSR _RENDER _DYNAMIC _ATTR ) ,
args
)
) ;
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
} else {
if ( node . tag === "textarea" && prop . name === "value" && prop . value ) {
rawChildrenMap . set ( node , shared . escapeHtml ( prop . value . content ) ) ;
} else if ( ! needMergeProps ) {
if ( prop . name === "key" || prop . name === "ref" ) {
continue ;
}
if ( prop . name === "class" && prop . value ) {
staticClassBinding = JSON . stringify ( prop . value . content ) ;
}
openTag . push (
` ${ prop . name } ` + ( prop . value ? ` =" ${ shared . escapeHtml ( prop . value . content ) } " ` : ` ` )
) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
}
if ( dynamicClassBinding && staticClassBinding ) {
mergeCall ( dynamicClassBinding , staticClassBinding ) ;
removeStaticBinding ( openTag , "class" ) ;
}
if ( context . scopeId ) {
openTag . push ( ` ${ context . scopeId } ` ) ;
}
node . ssrCodegenNode = compilerDom . createTemplateLiteral ( openTag ) ;
} ;
2023-07-24 11:13:08 +08:00
} ;
function buildSSRProps ( props , directives , context ) {
2023-09-06 09:51:55 +08:00
let mergePropsArgs = [ ] ;
if ( props ) {
if ( props . type === 14 ) {
mergePropsArgs = props . arguments ;
} else {
mergePropsArgs . push ( props ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
if ( directives . length ) {
for ( const dir of directives ) {
mergePropsArgs . push (
compilerDom . createCallExpression ( context . helper ( SSR _GET _DIRECTIVE _PROPS ) , [
` _ctx ` ,
... compilerDom . buildDirectiveArgs ( dir , context ) . elements
] )
) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
return mergePropsArgs . length > 1 ? compilerDom . createCallExpression ( context . helper ( compilerDom . MERGE _PROPS ) , mergePropsArgs ) : mergePropsArgs [ 0 ] ;
2023-07-24 11:13:08 +08:00
}
function isTrueFalseValue ( prop ) {
2023-09-06 09:51:55 +08:00
if ( prop . type === 7 ) {
return prop . name === "bind" && prop . arg && compilerDom . isStaticExp ( prop . arg ) && ( prop . arg . content === "true-value" || prop . arg . content === "false-value" ) ;
} else {
return prop . name === "true-value" || prop . name === "false-value" ;
}
2023-07-24 11:13:08 +08:00
}
function isTextareaWithValue ( node , prop ) {
2023-09-06 09:51:55 +08:00
return ! ! ( node . tag === "textarea" && prop . name === "bind" && compilerDom . isStaticArgOf ( prop . arg , "value" ) ) ;
2023-07-24 11:13:08 +08:00
}
function mergeCall ( call , arg ) {
2023-09-06 09:51:55 +08:00
const existing = call . arguments [ 0 ] ;
if ( existing . type === 17 ) {
existing . elements . push ( arg ) ;
} else {
call . arguments [ 0 ] = compilerDom . createArrayExpression ( [ existing , arg ] ) ;
}
2023-07-24 11:13:08 +08:00
}
function removeStaticBinding ( tag , binding ) {
2023-09-06 09:51:55 +08:00
const regExp = new RegExp ( ` ^ ${ binding } =".+" $ ` ) ;
const i = tag . findIndex ( ( e ) => typeof e === "string" && regExp . test ( e ) ) ;
if ( i > - 1 ) {
tag . splice ( i , 1 ) ;
}
2023-07-24 11:13:08 +08:00
}
function findVModel ( node ) {
2023-09-06 09:51:55 +08:00
return node . props . find (
( p ) => p . type === 7 && p . name === "model" && p . exp
) ;
2023-07-24 11:13:08 +08:00
}
function ssrProcessElement ( node , context ) {
2023-09-06 09:51:55 +08:00
const isVoidTag = context . options . isVoidTag || shared . NO ;
const elementsToAdd = node . ssrCodegenNode . elements ;
for ( let j = 0 ; j < elementsToAdd . length ; j ++ ) {
context . pushStringPart ( elementsToAdd [ j ] ) ;
}
if ( context . withSlotScopeId ) {
context . pushStringPart ( compilerDom . createSimpleExpression ( ` _scopeId ` , false ) ) ;
}
context . pushStringPart ( ` > ` ) ;
const rawChildren = rawChildrenMap . get ( node ) ;
if ( rawChildren ) {
context . pushStringPart ( rawChildren ) ;
} else if ( node . children . length ) {
processChildren ( node , context ) ;
}
if ( ! isVoidTag ( node . tag ) ) {
context . pushStringPart ( ` </ ${ node . tag } > ` ) ;
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
const wipMap$1 = /* @__PURE__ */ new WeakMap ( ) ;
2023-07-24 11:13:08 +08:00
function ssrTransformTransitionGroup ( node , context ) {
2023-09-06 09:51:55 +08:00
return ( ) => {
const tag = compilerDom . findProp ( node , "tag" ) ;
if ( tag ) {
const otherProps = node . props . filter ( ( p ) => p !== tag ) ;
const { props , directives } = compilerDom . buildProps (
node ,
context ,
otherProps ,
true ,
false ,
true
/* ssr (skip event listeners) */
) ;
let propsExp = null ;
if ( props || directives . length ) {
propsExp = compilerDom . createCallExpression ( context . helper ( SSR _RENDER _ATTRS ) , [
buildSSRProps ( props , directives , context )
] ) ;
}
wipMap$1 . set ( node , {
tag ,
propsExp
} ) ;
}
} ;
2023-07-24 11:13:08 +08:00
}
function ssrProcessTransitionGroup ( node , context ) {
2023-09-06 09:51:55 +08:00
const entry = wipMap$1 . get ( node ) ;
if ( entry ) {
const { tag , propsExp } = entry ;
if ( tag . type === 7 ) {
context . pushStringPart ( ` < ` ) ;
context . pushStringPart ( tag . exp ) ;
if ( propsExp ) {
context . pushStringPart ( propsExp ) ;
}
context . pushStringPart ( ` > ` ) ;
processChildren (
node ,
context ,
false ,
/ * *
* TransitionGroup has the special runtime behavior of flattening and
* concatenating all children into a single fragment ( in order for them to
* be patched using the same key map ) so we need to account for that here
* by disabling nested fragment wrappers from being generated .
* /
true
) ;
context . pushStringPart ( ` </ ` ) ;
context . pushStringPart ( tag . exp ) ;
context . pushStringPart ( ` > ` ) ;
} else {
context . pushStringPart ( ` < ${ tag . value . content } ` ) ;
if ( propsExp ) {
context . pushStringPart ( propsExp ) ;
}
context . pushStringPart ( ` > ` ) ;
processChildren ( node , context , false , true ) ;
context . pushStringPart ( ` </ ${ tag . value . content } > ` ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
} else {
processChildren ( node , context , true , true ) ;
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
const wipMap = /* @__PURE__ */ new WeakMap ( ) ;
2023-07-24 11:13:08 +08:00
const WIP _SLOT = Symbol ( ) ;
2023-09-06 09:51:55 +08:00
const componentTypeMap = /* @__PURE__ */ new WeakMap ( ) ;
2023-07-24 11:13:08 +08:00
const ssrTransformComponent = ( node , context ) => {
2023-09-06 09:51:55 +08:00
if ( node . type !== 1 || node . tagType !== 1 ) {
return ;
}
const component = compilerDom . resolveComponentType (
node ,
context ,
true
/* ssr */
) ;
const isDynamicComponent = shared . isObject ( component ) && component . callee === compilerDom . RESOLVE _DYNAMIC _COMPONENT ;
componentTypeMap . set ( node , component ) ;
if ( shared . isSymbol ( component ) ) {
if ( component === compilerDom . SUSPENSE ) {
return ssrTransformSuspense ( node , context ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
if ( component === compilerDom . TRANSITION _GROUP ) {
return ssrTransformTransitionGroup ( node , context ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
return ;
}
const vnodeBranches = [ ] ;
const clonedNode = clone ( node ) ;
return function ssrPostTransformComponent ( ) {
if ( clonedNode . children . length ) {
compilerDom . buildSlots ( clonedNode , context , ( props , children ) => {
vnodeBranches . push ( createVNodeSlotBranch ( props , children , context ) ) ;
return compilerDom . createFunctionExpression ( void 0 ) ;
} ) ;
}
let propsExp = ` null ` ;
if ( node . props . length ) {
const { props , directives } = compilerDom . buildProps (
node ,
context ,
void 0 ,
true ,
isDynamicComponent
) ;
if ( props || directives . length ) {
propsExp = buildSSRProps ( props , directives , context ) ;
}
}
const wipEntries = [ ] ;
wipMap . set ( node , wipEntries ) ;
const buildSSRSlotFn = ( props , children , loc ) => {
const param0 = props && compilerDom . stringifyExpression ( props ) || ` _ ` ;
const fn = compilerDom . createFunctionExpression (
[ param0 , ` _push ` , ` _parent ` , ` _scopeId ` ] ,
void 0 ,
// no return, assign body later
true ,
// newline
true ,
// isSlot
loc
) ;
wipEntries . push ( {
type : WIP _SLOT ,
fn ,
children ,
// also collect the corresponding vnode branch built earlier
vnodeBranch : vnodeBranches [ wipEntries . length ]
} ) ;
return fn ;
2023-07-24 11:13:08 +08:00
} ;
2023-09-06 09:51:55 +08:00
const slots = node . children . length ? compilerDom . buildSlots ( node , context , buildSSRSlotFn ) . slots : ` null ` ;
if ( typeof component !== "string" ) {
node . ssrCodegenNode = compilerDom . createCallExpression (
context . helper ( SSR _RENDER _VNODE ) ,
[
` _push ` ,
compilerDom . createCallExpression ( context . helper ( compilerDom . CREATE _VNODE ) , [
component ,
propsExp ,
slots
] ) ,
` _parent `
]
) ;
} else {
node . ssrCodegenNode = compilerDom . createCallExpression (
context . helper ( SSR _RENDER _COMPONENT ) ,
[ component , propsExp , slots , ` _parent ` ]
) ;
}
} ;
2023-07-24 11:13:08 +08:00
} ;
function ssrProcessComponent ( node , context , parent ) {
2023-09-06 09:51:55 +08:00
const component = componentTypeMap . get ( node ) ;
if ( ! node . ssrCodegenNode ) {
if ( component === compilerDom . TELEPORT ) {
return ssrProcessTeleport ( node , context ) ;
} else if ( component === compilerDom . SUSPENSE ) {
return ssrProcessSuspense ( node , context ) ;
} else if ( component === compilerDom . TRANSITION _GROUP ) {
return ssrProcessTransitionGroup ( node , context ) ;
} else {
if ( parent . type === WIP _SLOT ) {
context . pushStringPart ( ` ` ) ;
}
if ( component === compilerDom . TRANSITION ) {
node . children = node . children . filter ( ( c ) => c . type !== 3 ) ;
}
processChildren ( node , context ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
} else {
const wipEntries = wipMap . get ( node ) || [ ] ;
for ( let i = 0 ; i < wipEntries . length ; i ++ ) {
const { fn , vnodeBranch } = wipEntries [ i ] ;
fn . body = compilerDom . createIfStatement (
compilerDom . createSimpleExpression ( ` _push ` , false ) ,
processChildrenAsStatement (
wipEntries [ i ] ,
context ,
false ,
true
/* withSlotScopeId */
) ,
vnodeBranch
) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
if ( context . withSlotScopeId ) {
node . ssrCodegenNode . arguments . push ( ` _scopeId ` ) ;
}
if ( typeof component === "string" ) {
context . pushStatement (
compilerDom . createCallExpression ( ` _push ` , [ node . ssrCodegenNode ] )
) ;
} else {
context . pushStatement ( node . ssrCodegenNode ) ;
}
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
const rawOptionsMap = /* @__PURE__ */ new WeakMap ( ) ;
2023-07-24 11:13:08 +08:00
const [ baseNodeTransforms , baseDirectiveTransforms ] = compilerDom . getBaseTransformPreset ( true ) ;
const vnodeNodeTransforms = [ ... baseNodeTransforms , ... compilerDom . DOMNodeTransforms ] ;
const vnodeDirectiveTransforms = {
2023-09-06 09:51:55 +08:00
... baseDirectiveTransforms ,
... compilerDom . DOMDirectiveTransforms
2023-07-24 11:13:08 +08:00
} ;
function createVNodeSlotBranch ( props , children , parentContext ) {
2023-09-06 09:51:55 +08:00
const rawOptions = rawOptionsMap . get ( parentContext . root ) ;
const subOptions = {
... rawOptions ,
// overwrite with vnode-based transforms
nodeTransforms : [
... vnodeNodeTransforms ,
... rawOptions . nodeTransforms || [ ]
] ,
directiveTransforms : {
... vnodeDirectiveTransforms ,
... rawOptions . directiveTransforms || { }
}
} ;
const wrapperNode = {
type : 1 ,
ns : 0 ,
tag : "template" ,
tagType : 3 ,
isSelfClosing : false ,
// important: provide v-slot="props" on the wrapper for proper
// scope analysis
props : [
{
type : 7 ,
name : "slot" ,
exp : props ,
arg : void 0 ,
modifiers : [ ] ,
loc : compilerDom . locStub
}
] ,
children ,
loc : compilerDom . locStub ,
codegenNode : void 0
} ;
subTransform ( wrapperNode , subOptions , parentContext ) ;
return compilerDom . createReturnStatement ( children ) ;
2023-07-24 11:13:08 +08:00
}
function subTransform ( node , options , parentContext ) {
2023-09-06 09:51:55 +08:00
const childRoot = compilerDom . createRoot ( [ node ] ) ;
const childContext = compilerDom . createTransformContext ( childRoot , options ) ;
childContext . ssr = false ;
childContext . scopes = { ... parentContext . scopes } ;
childContext . identifiers = { ... parentContext . identifiers } ;
childContext . imports = parentContext . imports ;
compilerDom . traverseNode ( childRoot , childContext ) ;
[ "helpers" , "components" , "directives" ] . forEach ( ( key ) => {
childContext [ key ] . forEach ( ( value , helperKey ) => {
if ( key === "helpers" ) {
const parentCount = parentContext . helpers . get ( helperKey ) ;
if ( parentCount === void 0 ) {
parentContext . helpers . set ( helperKey , value ) ;
} else {
parentContext . helpers . set ( helperKey , value + parentCount ) ;
}
} else {
parentContext [ key ] . add ( value ) ;
}
2023-07-24 11:13:08 +08:00
} ) ;
2023-09-06 09:51:55 +08:00
} ) ;
2023-07-24 11:13:08 +08:00
}
function clone ( v ) {
2023-09-06 09:51:55 +08:00
if ( shared . isArray ( v ) ) {
return v . map ( clone ) ;
} else if ( shared . isObject ( v ) ) {
const res = { } ;
for ( const key in v ) {
res [ key ] = clone ( v [ key ] ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
return res ;
} else {
return v ;
}
2023-07-24 11:13:08 +08:00
}
function ssrCodegenTransform ( ast , options ) {
2023-09-06 09:51:55 +08:00
const context = createSSRTransformContext ( ast , options ) ;
if ( options . ssrCssVars ) {
const cssContext = compilerDom . createTransformContext ( compilerDom . createRoot ( [ ] ) , options ) ;
const varsExp = compilerDom . processExpression (
compilerDom . createSimpleExpression ( options . ssrCssVars , false ) ,
cssContext
) ;
context . body . push (
compilerDom . createCompoundExpression ( [ ` const _cssVars = { style: ` , varsExp , ` } ` ] )
) ;
Array . from ( cssContext . helpers . keys ( ) ) . forEach ( ( helper ) => {
ast . helpers . add ( helper ) ;
} ) ;
}
const isFragment = ast . children . length > 1 && ast . children . some ( ( c ) => ! compilerDom . isText ( c ) ) ;
processChildren ( ast , context , isFragment ) ;
ast . codegenNode = compilerDom . createBlockStatement ( context . body ) ;
ast . ssrHelpers = Array . from (
/* @__PURE__ */ new Set ( [
... Array . from ( ast . helpers ) . filter ( ( h ) => h in ssrHelpers ) ,
... context . helpers
] )
) ;
ast . helpers = new Set ( Array . from ( ast . helpers ) . filter ( ( h ) => ! ( h in ssrHelpers ) ) ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
function createSSRTransformContext ( root , options , helpers = /* @__PURE__ */ new Set ( ) , withSlotScopeId = false ) {
const body = [ ] ;
let currentString = null ;
return {
root ,
options ,
body ,
helpers ,
withSlotScopeId ,
onError : options . onError || ( ( e ) => {
throw e ;
} ) ,
helper ( name ) {
helpers . add ( name ) ;
return name ;
} ,
pushStringPart ( part ) {
if ( ! currentString ) {
const currentCall = compilerDom . createCallExpression ( ` _push ` ) ;
body . push ( currentCall ) ;
currentString = compilerDom . createTemplateLiteral ( [ ] ) ;
currentCall . arguments . push ( currentString ) ;
}
const bufferedElements = currentString . elements ;
const lastItem = bufferedElements [ bufferedElements . length - 1 ] ;
if ( shared . isString ( part ) && shared . isString ( lastItem ) ) {
bufferedElements [ bufferedElements . length - 1 ] += part ;
} else {
bufferedElements . push ( part ) ;
}
} ,
pushStatement ( statement ) {
currentString = null ;
body . push ( statement ) ;
}
} ;
2023-07-24 11:13:08 +08:00
}
function createChildContext ( parent , withSlotScopeId = parent . withSlotScopeId ) {
2023-09-06 09:51:55 +08:00
return createSSRTransformContext (
parent . root ,
parent . options ,
parent . helpers ,
withSlotScopeId
) ;
2023-07-24 11:13:08 +08:00
}
function processChildren ( parent , context , asFragment = false , disableNestedFragments = false ) {
2023-09-06 09:51:55 +08:00
if ( asFragment ) {
context . pushStringPart ( ` <!--[--> ` ) ;
}
const { children } = parent ;
for ( let i = 0 ; i < children . length ; i ++ ) {
const child = children [ i ] ;
switch ( child . type ) {
case 1 :
switch ( child . tagType ) {
case 0 :
ssrProcessElement ( child , context ) ;
break ;
case 1 :
ssrProcessComponent ( child , context , parent ) ;
break ;
case 2 :
ssrProcessSlotOutlet ( child , context ) ;
break ;
case 3 :
break ;
default :
context . onError (
createSSRCompilerError (
67 ,
child . loc
)
) ;
const exhaustiveCheck2 = child ;
return exhaustiveCheck2 ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
break ;
case 2 :
context . pushStringPart ( shared . escapeHtml ( child . content ) ) ;
break ;
case 3 :
context . pushStringPart ( ` <!-- ${ child . content } --> ` ) ;
break ;
case 5 :
context . pushStringPart (
compilerDom . createCallExpression ( context . helper ( SSR _INTERPOLATE ) , [ child . content ] )
) ;
break ;
case 9 :
ssrProcessIf ( child , context , disableNestedFragments ) ;
break ;
case 11 :
ssrProcessFor ( child , context , disableNestedFragments ) ;
break ;
case 10 :
break ;
case 12 :
case 8 :
break ;
default :
context . onError (
createSSRCompilerError (
67 ,
child . loc
)
) ;
const exhaustiveCheck = child ;
return exhaustiveCheck ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
if ( asFragment ) {
context . pushStringPart ( ` <!--]--> ` ) ;
}
2023-07-24 11:13:08 +08:00
}
function processChildrenAsStatement ( parent , parentContext , asFragment = false , withSlotScopeId = parentContext . withSlotScopeId ) {
2023-09-06 09:51:55 +08:00
const childContext = createChildContext ( parentContext , withSlotScopeId ) ;
processChildren ( parent , childContext , asFragment ) ;
return compilerDom . createBlockStatement ( childContext . body ) ;
2023-07-24 11:13:08 +08:00
}
const ssrTransformModel = ( dir , node , context ) => {
2023-09-06 09:51:55 +08:00
const model = dir . exp ;
function checkDuplicatedValue ( ) {
const value = compilerDom . findProp ( node , "value" ) ;
if ( value ) {
context . onError (
compilerDom . createDOMCompilerError (
60 ,
value . loc
)
) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
if ( node . tagType === 0 ) {
const res = { props : [ ] } ;
const defaultProps = [
// default value binding for text type inputs
compilerDom . createObjectProperty ( ` value ` , model )
] ;
if ( node . tag === "input" ) {
const type = compilerDom . findProp ( node , "type" ) ;
if ( type ) {
const value = findValueBinding ( node ) ;
if ( type . type === 7 ) {
res . ssrTagParts = [
compilerDom . createCallExpression ( context . helper ( SSR _RENDER _DYNAMIC _MODEL ) , [
type . exp ,
model ,
value
] )
] ;
} else if ( type . value ) {
switch ( type . value . content ) {
case "radio" :
res . props = [
compilerDom . createObjectProperty (
` checked ` ,
compilerDom . createCallExpression ( context . helper ( SSR _LOOSE _EQUAL ) , [
model ,
value
] )
)
] ;
break ;
case "checkbox" :
const trueValueBinding = compilerDom . findProp ( node , "true-value" ) ;
if ( trueValueBinding ) {
const trueValue = trueValueBinding . type === 6 ? JSON . stringify ( trueValueBinding . value . content ) : trueValueBinding . exp ;
res . props = [
compilerDom . createObjectProperty (
` checked ` ,
compilerDom . createCallExpression ( context . helper ( SSR _LOOSE _EQUAL ) , [
model ,
trueValue
] )
)
] ;
} else {
res . props = [
compilerDom . createObjectProperty (
` checked ` ,
compilerDom . createConditionalExpression (
compilerDom . createCallExpression ( ` Array.isArray ` , [ model ] ) ,
compilerDom . createCallExpression ( context . helper ( SSR _LOOSE _CONTAIN ) , [
model ,
value
] ) ,
model
)
)
] ;
}
break ;
case "file" :
context . onError (
compilerDom . createDOMCompilerError (
59 ,
dir . loc
)
) ;
break ;
default :
checkDuplicatedValue ( ) ;
res . props = defaultProps ;
break ;
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
} else if ( compilerDom . hasDynamicKeyVBind ( node ) ) ; else {
checkDuplicatedValue ( ) ;
res . props = defaultProps ;
}
} else if ( node . tag === "textarea" ) {
checkDuplicatedValue ( ) ;
node . children = [ compilerDom . createInterpolation ( model , model . loc ) ] ;
} else if ( node . tag === "select" ) ; else {
context . onError (
compilerDom . createDOMCompilerError (
57 ,
dir . loc
)
) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
return res ;
} else {
return compilerDom . transformModel ( dir , node , context ) ;
}
2023-07-24 11:13:08 +08:00
} ;
function findValueBinding ( node ) {
2023-09-06 09:51:55 +08:00
const valueBinding = compilerDom . findProp ( node , "value" ) ;
return valueBinding ? valueBinding . type === 7 ? valueBinding . exp : compilerDom . createSimpleExpression ( valueBinding . value . content , true ) : compilerDom . createSimpleExpression ( ` null ` , false ) ;
2023-07-24 11:13:08 +08:00
}
const ssrTransformShow = ( dir , node , context ) => {
2023-09-06 09:51:55 +08:00
if ( ! dir . exp ) {
context . onError (
compilerDom . createDOMCompilerError ( 61 )
) ;
}
return {
props : [
compilerDom . createObjectProperty (
` style ` ,
compilerDom . createConditionalExpression (
dir . exp ,
compilerDom . createSimpleExpression ( ` null ` , false ) ,
compilerDom . createObjectExpression ( [
compilerDom . createObjectProperty (
` display ` ,
compilerDom . createSimpleExpression ( ` none ` , true )
)
] ) ,
false
/* no newline */
)
)
]
} ;
2023-07-24 11:13:08 +08:00
} ;
2023-09-06 09:51:55 +08:00
const filterChild = ( node ) => node . children . filter ( ( n ) => n . type !== 3 ) ;
2023-07-24 11:13:08 +08:00
const hasSingleChild = ( node ) => filterChild ( node ) . length === 1 ;
const ssrInjectFallthroughAttrs = ( node , context ) => {
2023-09-06 09:51:55 +08:00
if ( node . type === 0 ) {
context . identifiers . _attrs = 1 ;
}
if ( node . type === 1 && node . tagType === 1 && ( compilerDom . isBuiltInType ( node . tag , "Transition" ) || compilerDom . isBuiltInType ( node . tag , "KeepAlive" ) ) ) {
const rootChildren = filterChild ( context . root ) ;
if ( rootChildren . length === 1 && rootChildren [ 0 ] === node ) {
if ( hasSingleChild ( node ) ) {
2023-07-24 11:13:08 +08:00
injectFallthroughAttrs ( node . children [ 0 ] ) ;
2023-09-06 09:51:55 +08:00
}
return ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
const parent = context . parent ;
if ( ! parent || parent . type !== 0 ) {
return ;
}
if ( node . type === 10 && hasSingleChild ( node ) ) {
let hasEncounteredIf = false ;
for ( const c of filterChild ( parent ) ) {
if ( c . type === 9 || c . type === 1 && compilerDom . findDir ( c , "if" ) ) {
if ( hasEncounteredIf )
return ;
hasEncounteredIf = true ;
} else if (
// node before v-if
! hasEncounteredIf || // non else nodes
! ( c . type === 1 && compilerDom . findDir ( c , /else/ , true ) )
) {
return ;
}
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
injectFallthroughAttrs ( node . children [ 0 ] ) ;
} else if ( hasSingleChild ( parent ) ) {
injectFallthroughAttrs ( node ) ;
}
2023-07-24 11:13:08 +08:00
} ;
function injectFallthroughAttrs ( node ) {
2023-09-06 09:51:55 +08:00
if ( node . type === 1 && ( node . tagType === 0 || node . tagType === 1 ) && ! compilerDom . findDir ( node , "for" ) ) {
node . props . push ( {
type : 7 ,
name : "bind" ,
arg : void 0 ,
exp : compilerDom . createSimpleExpression ( ` _attrs ` , false ) ,
modifiers : [ ] ,
loc : compilerDom . locStub
} ) ;
}
2023-07-24 11:13:08 +08:00
}
const ssrInjectCssVars = ( node , context ) => {
2023-09-06 09:51:55 +08:00
if ( ! context . ssrCssVars ) {
return ;
}
if ( node . type === 0 ) {
context . identifiers . _cssVars = 1 ;
}
const parent = context . parent ;
if ( ! parent || parent . type !== 0 ) {
return ;
}
if ( node . type === 10 ) {
for ( const child of node . children ) {
injectCssVars ( child ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
} else {
injectCssVars ( node ) ;
}
2023-07-24 11:13:08 +08:00
} ;
function injectCssVars ( node ) {
2023-09-06 09:51:55 +08:00
if ( node . type === 1 && ( node . tagType === 0 || node . tagType === 1 ) && ! compilerDom . findDir ( node , "for" ) ) {
if ( compilerDom . isBuiltInType ( node . tag , "Suspense" ) ) {
for ( const child of node . children ) {
if ( child . type === 1 && child . tagType === 3 ) {
child . children . forEach ( injectCssVars ) ;
} else {
injectCssVars ( child ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
} else {
node . props . push ( {
type : 7 ,
name : "bind" ,
arg : void 0 ,
exp : compilerDom . createSimpleExpression ( ` _cssVars ` , false ) ,
modifiers : [ ] ,
loc : compilerDom . locStub
} ) ;
2023-07-24 11:13:08 +08:00
}
2023-09-06 09:51:55 +08:00
}
2023-07-24 11:13:08 +08:00
}
function compile ( template , options = { } ) {
2023-09-06 09:51:55 +08:00
options = {
... options ,
// apply DOM-specific parsing options
... compilerDom . parserOptions ,
ssr : true ,
inSSR : true ,
scopeId : options . mode === "function" ? null : options . scopeId ,
// always prefix since compiler-ssr doesn't have size concern
prefixIdentifiers : true ,
// disable optimizations that are unnecessary for ssr
cacheHandlers : false ,
hoistStatic : false
} ;
const ast = compilerDom . baseParse ( template , options ) ;
rawOptionsMap . set ( ast , options ) ;
compilerDom . transform ( ast , {
... options ,
hoistStatic : false ,
nodeTransforms : [
ssrTransformIf ,
ssrTransformFor ,
compilerDom . trackVForSlotScopes ,
compilerDom . transformExpression ,
ssrTransformSlotOutlet ,
ssrInjectFallthroughAttrs ,
ssrInjectCssVars ,
ssrTransformElement ,
ssrTransformComponent ,
compilerDom . trackSlotScopes ,
compilerDom . transformStyle ,
... options . nodeTransforms || [ ]
// user transforms
] ,
directiveTransforms : {
// reusing core v-bind
bind : compilerDom . transformBind ,
on : compilerDom . transformOn ,
// model and show has dedicated SSR handling
model : ssrTransformModel ,
show : ssrTransformShow ,
// the following are ignored during SSR
// on: noopDirectiveTransform,
cloak : compilerDom . noopDirectiveTransform ,
once : compilerDom . noopDirectiveTransform ,
memo : compilerDom . noopDirectiveTransform ,
... options . directiveTransforms || { }
// user transforms
}
} ) ;
ssrCodegenTransform ( ast , options ) ;
return compilerDom . generate ( ast , options ) ;
2023-07-24 11:13:08 +08:00
}
exports . compile = compile ;