| InterpolationNode
| undefined
// If interpolation, this is dynamic <textarea> content, potentially
- // injected by v-model and takes higher priority than v-bind value
- if (!existingText || existingText.type !== NodeTypes.INTERPOLATION) {
+ // injected by v-model and takes higher priority than v-bind value.
+ // Additionally, directives with content overrides (v-text/v-html)
+ // have higher priority than the merged props.
+ if (
+ !hasContentOverrideDirective(node) &&
+ (!existingText || existingText.type !== NodeTypes.INTERPOLATION)
+ ) {
// <textarea> with dynamic v-bind. We don't know if the final props
// will contain .value, so we will have to do something special:
// assign the merged props to a temp variable, and check whether
]
}
} else if (directives.length && !node.children.length) {
- // v-text directive has higher priority than the merged props
- const vText = findDir(node, 'text')
- if (!vText) {
+ // v-text/v-html have higher priority than the merged props
+ if (!hasContentOverrideDirective(node)) {
const tempId = `_temp${context.temps++}`
propsExp.arguments = [
createAssignmentExpression(
) as DirectiveNode | undefined
}
+function hasContentOverrideDirective(node: PlainElementNode): boolean {
+ return !!findDir(node, 'text') || !!findDir(node, 'html')
+}
+
export function ssrProcessElement(
node: PlainElementNode,
context: SSRTransformContext,
})
})
+ describe('template with v-text / v-html', () => {
+ test('element with v-html', async () => {
+ expect(
+ await renderToString(
+ createApp({
+ data: () => ({ foo: 'hello' }),
+ template: `<span v-html="foo"/>`,
+ }),
+ ),
+ ).toBe(`<span>hello</span>`)
+ })
+
+ test('textarea with v-text', async () => {
+ expect(
+ await renderToString(
+ createApp({
+ data: () => ({ foo: 'hello' }),
+ template: `<textarea v-text="foo"/>`,
+ }),
+ ),
+ ).toBe(`<textarea>hello</textarea>`)
+ })
+
+ test('textarea with v-html', async () => {
+ expect(
+ await renderToString(
+ createApp({
+ data: () => ({ foo: 'hello' }),
+ template: `<textarea v-html="foo"/>`,
+ }),
+ ),
+ ).toBe(`<textarea>hello</textarea>`)
+ })
+ })
+
describe('vnode v-show', () => {
test('basic', async () => {
expect(