Skip to content

Commit 40b1e1e

Browse files
committed
feat(runtime-vapor): support svg and MathML
1 parent f70f9d1 commit 40b1e1e

File tree

5 files changed

+37
-12
lines changed

5 files changed

+37
-12
lines changed

packages/compiler-vapor/src/generators/template.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ import { type CodeFragment, NEWLINE, buildCodeFragment, genCall } from './utils'
77
export function genTemplates(
88
templates: string[],
99
rootIndex: number | undefined,
10-
{ helper }: CodegenContext,
10+
{ helper, ir: { templateNS } }: CodegenContext,
1111
): string {
1212
return templates
13-
.map(
14-
(template, i) =>
15-
`const t${i} = ${helper('template')}(${JSON.stringify(
16-
template,
17-
)}${i === rootIndex ? ', true' : ''})\n`,
18-
)
13+
.map((template, i) => {
14+
const ns = templateNS.get(template)
15+
return `const t${i} = ${helper('template')}(${JSON.stringify(
16+
template,
17+
)}${i === rootIndex ? ', true' : ns ? ', false' : ''}${ns ? `, ${ns}` : ''})\n`
18+
})
1919
.join('')
2020
}
2121

packages/compiler-vapor/src/ir/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export interface RootIRNode {
6060
node: RootNode
6161
source: string
6262
template: string[]
63+
templateNS: Map<string, number>
6364
rootTemplateIndex?: number
6465
component: Set<string>
6566
directive: Set<string>

packages/compiler-vapor/src/transform.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
type ElementNode,
77
ElementTypes,
88
NodeTypes,
9+
type PlainElementNode,
910
type RootNode,
1011
type SimpleExpressionNode,
1112
type TemplateChildNode,
@@ -73,6 +74,7 @@ export class TransformContext<T extends AllNode = AllNode> {
7374
>
7475

7576
template: string = ''
77+
templateNS: Map<string, number> = new Map<string, number>()
7678
childrenTemplate: (string | null)[] = []
7779
dynamic: IRDynamicInfo = this.ir.block.dynamic
7880

@@ -98,10 +100,12 @@ export class TransformContext<T extends AllNode = AllNode> {
98100
}
99101

100102
enterBlock(ir: BlockIRNode, isVFor: boolean = false): () => void {
101-
const { block, template, dynamic, childrenTemplate, slots } = this
103+
const { block, template, templateNS, dynamic, childrenTemplate, slots } =
104+
this
102105
this.block = ir
103106
this.dynamic = ir.dynamic
104107
this.template = ''
108+
this.templateNS = new Map<string, number>()
105109
this.childrenTemplate = []
106110
this.slots = []
107111
isVFor && this.inVFor++
@@ -110,6 +114,7 @@ export class TransformContext<T extends AllNode = AllNode> {
110114
this.registerTemplate()
111115
this.block = block
112116
this.template = template
117+
this.templateNS = templateNS
113118
this.dynamic = dynamic
114119
this.childrenTemplate = childrenTemplate
115120
this.slots = slots
@@ -130,6 +135,7 @@ export class TransformContext<T extends AllNode = AllNode> {
130135
)
131136
if (existing !== -1) return existing
132137
this.ir.template.push(content)
138+
this.ir.templateNS.set(content, (this.node as PlainElementNode).ns)
133139
return this.ir.template.length - 1
134140
}
135141
registerTemplate(): number {
@@ -215,6 +221,7 @@ export function transform(
215221
node,
216222
source: node.source,
217223
template: [],
224+
templateNS: new Map<string, number>(),
218225
component: new Set(),
219226
directive: new Set(),
220227
block: newBlock(node),

packages/runtime-dom/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,7 @@ export {
348348
vModelSelectInit,
349349
vModelSetSelected,
350350
} from './directives/vModel'
351+
/**
352+
* @internal
353+
*/
354+
export { svgNS, mathmlNS } from './nodeOps'

packages/runtime-vapor/src/dom/template.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import { mathmlNS, svgNS } from '@vue/runtime-dom'
12
import { adoptTemplate, currentHydrationNode, isHydrating } from './hydration'
23
import { child, createTextNode } from './node'
34

45
let t: HTMLTemplateElement
6+
let st: HTMLTemplateElement
7+
let mt: HTMLTemplateElement
58

69
/*! #__NO_SIDE_EFFECTS__ */
7-
export function template(html: string, root?: boolean) {
10+
export function template(html: string, root?: boolean, ns?: number) {
811
let node: Node
912
return (): Node & { $root?: true } => {
1013
if (isHydrating) {
@@ -19,9 +22,19 @@ export function template(html: string, root?: boolean) {
1922
return createTextNode(html)
2023
}
2124
if (!node) {
22-
t = t || document.createElement('template')
23-
t.innerHTML = html
24-
node = child(t.content)
25+
if (!ns) {
26+
t = t || document.createElement('template')
27+
t.innerHTML = html
28+
node = child(t.content)
29+
} else if (ns === 1) {
30+
st = st || document.createElementNS(svgNS, 'template')
31+
st.innerHTML = html
32+
node = child(st)
33+
} else {
34+
mt = mt || document.createElementNS(mathmlNS, 'template')
35+
mt.innerHTML = html
36+
node = child(mt)
37+
}
2538
}
2639
const ret = node.cloneNode(true)
2740
if (root) (ret as any).$root = true

0 commit comments

Comments
 (0)