import { NodeTransform, NodeTypes, ElementTypes, TemplateLiteral, createTemplateLiteral, createInterpolation, createCallExpression, createConditionalExpression, createSimpleExpression, buildProps, DirectiveNode, PlainElementNode, createCompilerError, ErrorCodes, CallExpression, createArrayExpression, ExpressionNode, JSChildNode, ArrayExpression, createAssignmentExpression, TextNode, hasDynamicKeyVBind, MERGE_PROPS, isStaticArgOf, createSequenceExpression, InterpolationNode, isStaticExp, AttributeNode, buildDirectiveArgs, TransformContext, PropsExpression } from '@vue/compiler-dom' import { escapeHtml, isBooleanAttr, isBuiltInDirective, isSSRSafeAttrName, NO, propsToAttrMap } from '@vue/shared' import { createSSRCompilerError, SSRErrorCodes } from '../errors' import { SSR_RENDER_ATTR, SSR_RENDER_CLASS, SSR_RENDER_STYLE, SSR_RENDER_DYNAMIC_ATTR, SSR_RENDER_ATTRS, SSR_INTERPOLATE, SSR_GET_DYNAMIC_MODEL_PROPS, SSR_INCLUDE_BOOLEAN_ATTR, SSR_GET_DIRECTIVE_PROPS } from '../runtimeHelpers' import { SSRTransformContext, processChildren } from '../ssrCodegenTransform' // for directives with children overwrite (e.g. v-html & v-text), we need to // store the raw children so that they can be added in the 2nd pass. const rawChildrenMap = new WeakMap< PlainElementNode, TemplateLiteral['elements'][0] >() export const ssrTransformElement: NodeTransform = (node, context) => { if ( node.type !== NodeTypes.ELEMENT || node.tagType !== ElementTypes.ELEMENT ) { return } return function ssrPostTransformElement() { // element // generate the template literal representing the open tag. const openTag: TemplateLiteral['elements'] = [`<${node.tag}`] // some tags need to be passed to runtime for special checks const needTagForRuntime = node.tag === 'textarea' || node.tag.indexOf('-') > 0 // v-bind="obj", v-bind:[key] and custom directives can potentially // overwrite other static attrs and can affect final rendering result, // so when they are present we need to bail out to full `renderAttrs` const hasDynamicVBind = hasDynamicKeyVBind(node) const hasCustomDir = node.props.some( p => p.type === NodeTypes.DIRECTIVE && !isBuiltInDirective(p.name) ) const needMergeProps = hasDynamicVBind || hasCustomDir if (needMergeProps) { const { props, directives } = buildProps( node, context, node.props, false /* isComponent */, false /* isDynamicComponent */, true /* ssr */ ) if (props || directives.length) { const mergedProps = buildSSRProps(props, directives, context) const propsExp = createCallExpression( context.helper(SSR_RENDER_ATTRS), [mergedProps] ) if (node.tag === 'textarea') { const existingText = node.children[0] as | TextNode | InterpolationNode | undefined // If interpolation, this is dynamic