diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index 8e8e265a..5052d557 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -29,7 +29,7 @@ function genElement (el) { // if the element is potentially a component, // wrap its children as a thunk. const children = genChildren(el, !isReservedTag(el.tag) /* asThunk */) - const code = `__h__('${el.tag}', ${genData(el)}, ${children}, ${el.svg})` + const code = `__h__('${el.tag}', ${genData(el)}, ${children}, '${el.namespace || ''}')` if (el.staticRoot) { // hoist static sub-trees out staticRenderFns.push(`with(this){return ${code}}`) diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js index 92c74980..6df89aec 100644 --- a/src/compiler/parser/index.js +++ b/src/compiler/parser/index.js @@ -26,8 +26,8 @@ const decodeHTMLCached = cached(decodeHTML) // attributes that should be using props for binding const mustUseProp = makeMap('value,selected,checked,muted') -// this map covers SVG elements that can appear as template root nodes -const isSVG = makeMap('svg,g,defs,symbol,use,image,text,circle,ellipse,line,path,polygon,polyline,rect', true) +// this map covers namespace elements that can appear as template root nodes +const tagNamespace = makeMap('svg,g,defs,symbol,use,image,text,circle,ellipse,line,path,polygon,polyline,rect', true, 'svg') // make warning customizable depending on environment. let warn @@ -47,8 +47,9 @@ export function parse (template, options) { const stack = [] let root let currentParent - let inSvg = false - let svgIndex = -1 + let inNamespace = false + let namespaceIndex = -1 + let currentNamespace = '' let inPre = false let warned = false parseHTML(template, { @@ -73,13 +74,15 @@ export function parse (template, options) { children: [] } - // check svg - if (inSvg) { - element.svg = true - } else if (isSVG(tag)) { - element.svg = true - inSvg = true - svgIndex = stack.length + // check namespace + const namespace = tagNamespace(tag) + if (inNamespace) { + element.namespace = currentNamespace + } else if (namespace) { + element.namespace = namespace + inNamespace = true + currentNamespace = namespace + namespaceIndex = stack.length } if (!inPre) { @@ -136,10 +139,11 @@ export function parse (template, options) { // pop stack stack.length -= 1 currentParent = stack[stack.length - 1] - // check svg state - if (inSvg && stack.length <= svgIndex) { - inSvg = false - svgIndex = -1 + // check namespace state + if (inNamespace && stack.length <= namespaceIndex) { + inNamespace = false + currentNamespace = '' + namespaceIndex = -1 } // check pre state if (element.pre) { diff --git a/src/runtime/dom/class-util.js b/src/runtime/dom/class-util.js index e43b7fc5..16f233c6 100644 --- a/src/runtime/dom/class-util.js +++ b/src/runtime/dom/class-util.js @@ -1,5 +1,7 @@ import { isIE9 } from '../util/index' -import { svgNS } from './node-ops' +import { namespaceMap } from './node-ops' + +const svgNS = namespaceMap.svg /** * In IE9, setAttribute('class') will result in empty class diff --git a/src/runtime/dom/node-ops.js b/src/runtime/dom/node-ops.js index 4fd6fbfa..3933e688 100644 --- a/src/runtime/dom/node-ops.js +++ b/src/runtime/dom/node-ops.js @@ -1,11 +1,13 @@ -export const svgNS = 'http://www.w3.org/2000/svg' +export const namespaceMap = { + svg: 'http://www.w3.org/2000/svg' +} export function createElement (tagName) { return document.createElement(tagName) } -export function createSVGElement (tagName) { - return document.createElementNS(svgNS, tagName) +export function createElementNS (namespace, tagName) { + return document.createElementNS(namespaceMap[namespace], tagName) } export function createTextNode (text) { diff --git a/src/runtime/vdom/create-element.js b/src/runtime/vdom/create-element.js index eb93a034..223d95ed 100644 --- a/src/runtime/vdom/create-element.js +++ b/src/runtime/vdom/create-element.js @@ -4,18 +4,18 @@ import { flatten } from './helpers' import { renderState } from '../instance/render' import { warn, isReservedTag, isUnknownElement, resolveAsset } from '../util/index' -export default function createElement (tag, data, children, svg) { +export default function createElement (tag, data, children, namespace) { const context = this const parent = renderState.activeInstance if (typeof tag === 'string') { let Ctor if (isReservedTag(tag)) { - return VNode(tag, data, flatten(children), undefined, undefined, svg) + return VNode(tag, data, flatten(children), undefined, undefined, namespace) } else if ((Ctor = resolveAsset(context.$options, 'components', tag))) { return createComponent(Ctor, data, parent, children) } else { if (process.env.NODE_ENV !== 'production') { - if (!svg && isUnknownElement(tag)) { + if (!namespace && isUnknownElement(tag)) { warn( 'Unknown custom element: <' + tag + '> - did you ' + 'register the component correctly? For recursive components, ' + @@ -23,7 +23,7 @@ export default function createElement (tag, data, children, svg) { ) } } - return VNode(tag, data, flatten(children && children()), undefined, undefined, svg) + return VNode(tag, data, flatten(children && children()), undefined, undefined, namespace) } } else { return createComponent(tag, data, parent, children) diff --git a/src/runtime/vdom/patch.js b/src/runtime/vdom/patch.js index 92ff9253..fbcbdd6b 100644 --- a/src/runtime/vdom/patch.js +++ b/src/runtime/vdom/patch.js @@ -81,8 +81,8 @@ export default function createPatchFunction (backend) { const children = vnode.children const tag = vnode.tag if (isDef(tag)) { - elm = vnode.elm = vnode.svg - ? nodeOps.createSVGElement(tag) + elm = vnode.elm = vnode.namespace + ? nodeOps.createElementNS(vnode.namespace, tag) : nodeOps.createElement(tag) if (Array.isArray(children)) { for (i = 0; i < children.length; ++i) { diff --git a/src/runtime/vdom/vnode.js b/src/runtime/vdom/vnode.js index 1f9d5cee..9ad21a6d 100644 --- a/src/runtime/vdom/vnode.js +++ b/src/runtime/vdom/vnode.js @@ -1,11 +1,11 @@ -export default function VNode (tag, data, children, text, elm, svg) { +export default function VNode (tag, data, children, text, elm, namespace) { return { tag, data, children, text, elm, - svg, + namespace, key: data && data.key } } diff --git a/src/shared/util.js b/src/shared/util.js index 66d0bc6a..04a5528b 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -7,10 +7,10 @@ * @return {Function} */ -export function makeMap (str, expectsLowerCase) { +export function makeMap (str, expectsLowerCase, defaultValue = true) { const map = Object.create(null) str.split(',').forEach(key => { - map[key] = true + map[key] = defaultValue }) return expectsLowerCase ? val => map[val.toLowerCase()]