Skip to content

Commit f5014e2

Browse files
committed
feat: MathML support
1 parent 98f1934 commit f5014e2

File tree

20 files changed

+357
-155
lines changed

20 files changed

+357
-155
lines changed

packages/compiler-dom/src/parserOptions.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import {
55
NodeTypes,
66
isBuiltInType
77
} from '@vue/compiler-core'
8-
import { makeMap, isVoidTag, isHTMLTag, isSVGTag } from '@vue/shared'
8+
import {
9+
makeMap,
10+
isVoidTag,
11+
isHTMLTag,
12+
isSVGTag,
13+
isMathMLTag
14+
} from '@vue/shared'
915
import { TRANSITION, TRANSITION_GROUP } from './runtimeHelpers'
1016
import { decodeHtml } from './decodeHtml'
1117
import { decodeHtmlBrowser } from './decodeHtmlBrowser'
@@ -23,7 +29,7 @@ export const enum DOMNamespaces {
2329

2430
export const parserOptions: ParserOptions = {
2531
isVoidTag,
26-
isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag),
32+
isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag) || isMathMLTag(tag),
2733
isPreTag: tag => tag === 'pre',
2834
decodeEntities: __BROWSER__ ? decodeHtmlBrowser : decodeHtml,
2935

packages/runtime-core/src/apiCreateApp.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export interface App<HostElement = any> {
4646
mount(
4747
rootContainer: HostElement | string,
4848
isHydrate?: boolean,
49-
isSVG?: boolean
49+
namespace?: 'svg' | 'mathml'
5050
): ComponentPublicInstance
5151
unmount(): void
5252
provide<T>(key: InjectionKey<T> | string, value: T): this
@@ -294,7 +294,7 @@ export function createAppAPI<HostElement>(
294294
mount(
295295
rootContainer: HostElement,
296296
isHydrate?: boolean,
297-
isSVG?: boolean
297+
namespace?: 'svg' | 'mathml'
298298
): any {
299299
if (!isMounted) {
300300
// #5571
@@ -316,14 +316,14 @@ export function createAppAPI<HostElement>(
316316
// HMR root reload
317317
if (__DEV__) {
318318
context.reload = () => {
319-
render(cloneVNode(vnode), rootContainer, isSVG)
319+
render(cloneVNode(vnode), rootContainer, namespace)
320320
}
321321
}
322322

323323
if (isHydrate && hydrate) {
324324
hydrate(vnode as VNode<Node, Element>, rootContainer as any)
325325
} else {
326-
render(vnode, rootContainer, isSVG)
326+
render(vnode, rootContainer, namespace)
327327
}
328328
isMounted = true
329329
app._container = rootContainer

packages/runtime-core/src/compat/global.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -503,15 +503,17 @@ function installCompatMount(
503503
container = selectorOrEl || document.createElement('div')
504504
}
505505

506-
const isSVG = container instanceof SVGElement
506+
let namespace: 'svg' | 'mathml' | undefined
507+
if (container instanceof SVGElement) namespace = 'svg'
508+
if (container instanceof MathMLElement) namespace = 'mathml'
507509

508510
// HMR root reload
509511
if (__DEV__) {
510512
context.reload = () => {
511513
const cloned = cloneVNode(vnode)
512514
// compat mode will use instance if not reset to null
513515
cloned.component = null
514-
render(cloned, container, isSVG)
516+
render(cloned, container, namespace)
515517
}
516518
}
517519

@@ -538,7 +540,7 @@ function installCompatMount(
538540
container.innerHTML = ''
539541

540542
// TODO hydration
541-
render(vnode, container, isSVG)
543+
render(vnode, container, namespace)
542544

543545
if (container instanceof Element) {
544546
container.removeAttribute('v-cloak')

packages/runtime-core/src/components/KeepAlive.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export interface KeepAliveContext extends ComponentRenderContext {
6464
vnode: VNode,
6565
container: RendererElement,
6666
anchor: RendererNode | null,
67-
isSVG: boolean,
67+
namespace: 'svg' | 'mathml' | undefined,
6868
optimized: boolean
6969
) => void
7070
deactivate: (vnode: VNode) => void
@@ -125,7 +125,13 @@ const KeepAliveImpl: ComponentOptions = {
125125
} = sharedContext
126126
const storageContainer = createElement('div')
127127

128-
sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {
128+
sharedContext.activate = (
129+
vnode,
130+
container,
131+
anchor,
132+
namespace,
133+
optimized
134+
) => {
129135
const instance = vnode.component!
130136
move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
131137
// in case props have changed
@@ -136,7 +142,7 @@ const KeepAliveImpl: ComponentOptions = {
136142
anchor,
137143
instance,
138144
parentSuspense,
139-
isSVG,
145+
namespace,
140146
vnode.slotScopeIds,
141147
optimized
142148
)

packages/runtime-core/src/components/Suspense.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export const SuspenseImpl = {
5656
anchor: RendererNode | null,
5757
parentComponent: ComponentInternalInstance | null,
5858
parentSuspense: SuspenseBoundary | null,
59-
isSVG: boolean,
59+
namespace: 'svg' | 'mathml' | undefined,
6060
slotScopeIds: string[] | null,
6161
optimized: boolean,
6262
// platform-specific impl passed from renderer
@@ -69,7 +69,7 @@ export const SuspenseImpl = {
6969
anchor,
7070
parentComponent,
7171
parentSuspense,
72-
isSVG,
72+
namespace,
7373
slotScopeIds,
7474
optimized,
7575
rendererInternals
@@ -81,7 +81,7 @@ export const SuspenseImpl = {
8181
container,
8282
anchor,
8383
parentComponent,
84-
isSVG,
84+
namespace,
8585
slotScopeIds,
8686
optimized,
8787
rendererInternals
@@ -117,7 +117,7 @@ function mountSuspense(
117117
anchor: RendererNode | null,
118118
parentComponent: ComponentInternalInstance | null,
119119
parentSuspense: SuspenseBoundary | null,
120-
isSVG: boolean,
120+
namespace: 'svg' | 'mathml' | undefined,
121121
slotScopeIds: string[] | null,
122122
optimized: boolean,
123123
rendererInternals: RendererInternals
@@ -134,7 +134,7 @@ function mountSuspense(
134134
container,
135135
hiddenContainer,
136136
anchor,
137-
isSVG,
137+
namespace,
138138
slotScopeIds,
139139
optimized,
140140
rendererInternals
@@ -148,7 +148,7 @@ function mountSuspense(
148148
null,
149149
parentComponent,
150150
suspense,
151-
isSVG,
151+
namespace,
152152
slotScopeIds
153153
)
154154
// now check if we have encountered any async deps
@@ -166,7 +166,7 @@ function mountSuspense(
166166
anchor,
167167
parentComponent,
168168
null, // fallback tree will not have suspense context
169-
isSVG,
169+
namespace,
170170
slotScopeIds
171171
)
172172
setActiveBranch(suspense, vnode.ssFallback!)
@@ -182,7 +182,7 @@ function patchSuspense(
182182
container: RendererElement,
183183
anchor: RendererNode | null,
184184
parentComponent: ComponentInternalInstance | null,
185-
isSVG: boolean,
185+
namespace: 'svg' | 'mathml' | undefined,
186186
slotScopeIds: string[] | null,
187187
optimized: boolean,
188188
{ p: patch, um: unmount, o: { createElement } }: RendererInternals
@@ -205,7 +205,7 @@ function patchSuspense(
205205
null,
206206
parentComponent,
207207
suspense,
208-
isSVG,
208+
namespace,
209209
slotScopeIds,
210210
optimized
211211
)
@@ -219,7 +219,7 @@ function patchSuspense(
219219
anchor,
220220
parentComponent,
221221
null, // fallback tree will not have suspense context
222-
isSVG,
222+
namespace,
223223
slotScopeIds,
224224
optimized
225225
)
@@ -254,7 +254,7 @@ function patchSuspense(
254254
null,
255255
parentComponent,
256256
suspense,
257-
isSVG,
257+
namespace,
258258
slotScopeIds,
259259
optimized
260260
)
@@ -268,7 +268,7 @@ function patchSuspense(
268268
anchor,
269269
parentComponent,
270270
null, // fallback tree will not have suspense context
271-
isSVG,
271+
namespace,
272272
slotScopeIds,
273273
optimized
274274
)
@@ -283,7 +283,7 @@ function patchSuspense(
283283
anchor,
284284
parentComponent,
285285
suspense,
286-
isSVG,
286+
namespace,
287287
slotScopeIds,
288288
optimized
289289
)
@@ -298,7 +298,7 @@ function patchSuspense(
298298
null,
299299
parentComponent,
300300
suspense,
301-
isSVG,
301+
namespace,
302302
slotScopeIds,
303303
optimized
304304
)
@@ -317,7 +317,7 @@ function patchSuspense(
317317
anchor,
318318
parentComponent,
319319
suspense,
320-
isSVG,
320+
namespace,
321321
slotScopeIds,
322322
optimized
323323
)
@@ -336,7 +336,7 @@ function patchSuspense(
336336
null,
337337
parentComponent,
338338
suspense,
339-
isSVG,
339+
namespace,
340340
slotScopeIds,
341341
optimized
342342
)
@@ -363,7 +363,7 @@ export interface SuspenseBoundary {
363363
vnode: VNode<RendererNode, RendererElement, SuspenseProps>
364364
parent: SuspenseBoundary | null
365365
parentComponent: ComponentInternalInstance | null
366-
isSVG: boolean
366+
namespace: 'svg' | 'mathml' | undefined
367367
container: RendererElement
368368
hiddenContainer: RendererElement
369369
anchor: RendererNode | null
@@ -400,7 +400,7 @@ function createSuspenseBoundary(
400400
container: RendererElement,
401401
hiddenContainer: RendererElement,
402402
anchor: RendererNode | null,
403-
isSVG: boolean,
403+
namespace: 'svg' | 'mathml' | undefined,
404404
slotScopeIds: string[] | null,
405405
optimized: boolean,
406406
rendererInternals: RendererInternals,
@@ -432,7 +432,7 @@ function createSuspenseBoundary(
432432
vnode,
433433
parent,
434434
parentComponent,
435-
isSVG,
435+
namespace,
436436
container,
437437
hiddenContainer,
438438
anchor,
@@ -531,7 +531,7 @@ function createSuspenseBoundary(
531531
return
532532
}
533533

534-
const { vnode, activeBranch, parentComponent, container, isSVG } =
534+
const { vnode, activeBranch, parentComponent, container, namespace } =
535535
suspense
536536

537537
// invoke @fallback event
@@ -550,7 +550,7 @@ function createSuspenseBoundary(
550550
anchor,
551551
parentComponent,
552552
null, // fallback tree will not have suspense context
553-
isSVG,
553+
namespace,
554554
slotScopeIds,
555555
optimized
556556
)
@@ -631,7 +631,7 @@ function createSuspenseBoundary(
631631
// consider the comment placeholder case.
632632
hydratedEl ? null : next(instance.subTree),
633633
suspense,
634-
isSVG,
634+
namespace,
635635
optimized
636636
)
637637
if (placeholder) {
@@ -677,7 +677,7 @@ function hydrateSuspense(
677677
vnode: VNode,
678678
parentComponent: ComponentInternalInstance | null,
679679
parentSuspense: SuspenseBoundary | null,
680-
isSVG: boolean,
680+
namespace: 'svg' | 'mathml' | undefined,
681681
slotScopeIds: string[] | null,
682682
optimized: boolean,
683683
rendererInternals: RendererInternals,
@@ -698,7 +698,7 @@ function hydrateSuspense(
698698
node.parentNode!,
699699
document.createElement('div'),
700700
null,
701-
isSVG,
701+
namespace,
702702
slotScopeIds,
703703
optimized,
704704
rendererInternals,

0 commit comments

Comments
 (0)