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, isBindKey, createSequenceExpression, InterpolationNode } from '@vue/compiler-dom' import { escapeHtml, isBooleanAttr, 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 } 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" or v-bind:[key] 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) if (hasDynamicVBind) { const { props } = buildProps(node, context, node.props, true /* ssr */) if (props) { const propsExp = createCallExpression( context.helper(SSR_RENDER_ATTRS), [props] ) if (node.tag === 'textarea') { const existingText = node.children[0] as | TextNode | InterpolationNode | undefined // If interpolation, this is dynamic