Selaa lähdekoodia

fix(compiler-vapor): do not escape quotes in root-level text nodes (#14310)

close #14309
edison 3 kuukautta sitten
vanhempi
commit
3fc8e4af5d

+ 36 - 1
packages/compiler-vapor/__tests__/transforms/transformText.spec.ts

@@ -5,13 +5,19 @@ import {
   transformElement,
   transformText,
   transformVBind,
+  transformVIf,
   transformVOn,
 } from '../../src'
 
 import { makeCompile } from './_utils'
 
 const compileWithTextTransform = makeCompile({
-  nodeTransforms: [transformElement, transformChildren, transformText],
+  nodeTransforms: [
+    transformVIf,
+    transformElement,
+    transformChildren,
+    transformText,
+  ],
   directiveTransforms: {
     bind: transformVBind,
     on: transformVOn,
@@ -54,6 +60,35 @@ describe('compiler: text transform', () => {
     expect([...ir.template.keys()]).not.toContain('<code><script>')
   })
 
+  it('should not escape quotes in root-level text nodes', () => {
+    // Root-level text goes through createTextNode() which doesn't need escaping
+    const { ir } = compileWithTextTransform(`Howdy y'all`)
+    expect([...ir.template.keys()]).toContain(`Howdy y'all`)
+    expect([...ir.template.keys()]).not.toContain(`Howdy y&#39;all`)
+  })
+
+  it('should not escape double quotes in root-level text nodes', () => {
+    const { ir } = compileWithTextTransform(`Say "hello"`)
+    expect([...ir.template.keys()]).toContain(`Say "hello"`)
+    expect([...ir.template.keys()]).not.toContain(`Say &quot;hello&quot;`)
+  })
+
+  it('should not escape quotes in template v-if text', () => {
+    // Text inside <template> tag also goes through createTextNode()
+    const { code } = compileWithTextTransform(
+      `<template v-if="ok">Howdy y'all</template>`,
+    )
+    expect(code).toContain(`Howdy y'all`)
+    expect(code).not.toContain(`Howdy y&#39;all`)
+  })
+
+  it('should not escape quotes in component slot text', () => {
+    // Text inside component (slot content) also goes through createTextNode()
+    const { ir } = compileWithTextTransform(`<Comp>Howdy y'all</Comp>`)
+    expect([...ir.template.keys()]).toContain(`Howdy y'all`)
+    expect([...ir.template.keys()]).not.toContain(`Howdy y&#39;all`)
+  })
+
   test('constant text', () => {
     const { code } = compileWithTextTransform(
       `

+ 12 - 1
packages/compiler-vapor/src/transforms/transformText.ts

@@ -79,7 +79,18 @@ export const transformText: NodeTransform = (node, context) => {
   } else if (node.type === NodeTypes.INTERPOLATION) {
     processInterpolation(context as TransformContext<InterpolationNode>)
   } else if (node.type === NodeTypes.TEXT) {
-    context.template += escapeHtml(node.content)
+    // Check if this is a root-level text node (parent is ROOT or fragment)
+    // Root-level text nodes go through createTextNode() which doesn't need escaping
+    // Element children go through innerHTML which needs escaping
+    const parent = context.parent?.node
+    const isRootText =
+      !parent ||
+      parent.type === NodeTypes.ROOT ||
+      (parent.type === NodeTypes.ELEMENT &&
+        (parent.tagType === ElementTypes.TEMPLATE ||
+          parent.tagType === ElementTypes.COMPONENT))
+
+    context.template += isRootText ? node.content : escapeHtml(node.content)
   }
 }