diff --git a/packages/diffhtml/lib/node/create.js b/packages/diffhtml/lib/node/create.js index f9e965fc..dc995bec 100644 --- a/packages/diffhtml/lib/node/create.js +++ b/packages/diffhtml/lib/node/create.js @@ -1,5 +1,5 @@ import { NodeCache, MiddlewareCache } from '../util/caches'; -import { elements, namespace } from '../util/svg'; +import { namespace } from '../util/svg'; import process from '../util/process'; const { CreateNodeHookCache } = MiddlewareCache; @@ -11,9 +11,10 @@ const { CreateNodeHookCache } = MiddlewareCache; * * @param {Object} - A Virtual Tree Element or VTree-like element * @param {Object} - Document to create Nodes in + * @param {Boolean} - Is their a root SVG element? * @return {Object} - A DOM Node matching the vTree */ -export default function createNode(vTree, ownerDocument = document) { +export default function createNode(vTree, ownerDocument = document, isSVG) { if (process.env.NODE_ENV !== 'production') { if (!vTree) { throw new Error('Missing VTree when trying to create DOM Node'); @@ -28,6 +29,7 @@ export default function createNode(vTree, ownerDocument = document) { } const { nodeName, childNodes = [] } = vTree; + isSVG = isSVG || nodeName === 'svg'; // Will vary based on the properties of the VTree. let domNode = null; @@ -50,12 +52,8 @@ export default function createNode(vTree, ownerDocument = document) { else if (nodeName === '#document-fragment') { domNode = ownerDocument.createDocumentFragment(); } - // If the nodeName matches any of the known SVG element names, mark it as - // SVG. The reason for doing this over detecting if nested in an - // element, is that we do not currently have circular dependencies in the - // VTree, by avoiding parentNode, so there is no way to crawl up the - // parents. - else if (elements.indexOf(nodeName) > -1) { + // Support SVG. + else if (isSVG) { domNode = ownerDocument.createElementNS(namespace, nodeName); } // If not a Text or SVG Node, then create with the standard method. @@ -70,7 +68,7 @@ export default function createNode(vTree, ownerDocument = document) { // Append all the children into the domNode, making sure to run them // through this `createNode` function as well. for (let i = 0; i < childNodes.length; i++) { - domNode.appendChild(createNode(childNodes[i], ownerDocument)); + domNode.appendChild(createNode(childNodes[i], ownerDocument, isSVG)); } return domNode; diff --git a/packages/diffhtml/lib/node/patch.js b/packages/diffhtml/lib/node/patch.js index 41bd3677..e8f88289 100644 --- a/packages/diffhtml/lib/node/patch.js +++ b/packages/diffhtml/lib/node/patch.js @@ -15,9 +15,10 @@ const removeAttribute = (domNode, name) => { } }; -export default function patchNode(patches) { +export default function patchNode(patches, state = {}) { const promises = []; const { TREE_OPS, NODE_VALUE, SET_ATTRIBUTE, REMOVE_ATTRIBUTE } = patches; + const { isSVG, ownerDocument } = state; // Set attributes. if (SET_ATTRIBUTE.length) { @@ -26,7 +27,7 @@ export default function patchNode(patches) { const _name = SET_ATTRIBUTE[i + 1]; const value = decodeEntities(SET_ATTRIBUTE[i + 2]); - const domNode = createNode(vTree); + const domNode = createNode(vTree, ownerDocument, isSVG); const attributeChanged = TransitionCache.get('attributeChanged'); const oldValue = domNode.getAttribute(_name); const newPromises = runTransitions( @@ -119,21 +120,21 @@ export default function patchNode(patches) { for (let i = 0; i < INSERT_BEFORE.length; i += 3) { const vTree = INSERT_BEFORE[i]; const newTree = INSERT_BEFORE[i + 1]; - const referenceTree = INSERT_BEFORE[i + 2]; + const refTree = INSERT_BEFORE[i + 2]; const domNode = NodeCache.get(vTree); - const referenceNode = referenceTree && createNode(referenceTree); + const refNode = refTree && createNode(refTree, ownerDocument, isSVG); const attached = TransitionCache.get('attached'); - if (referenceTree) { - protectVTree(referenceTree); + if (refTree) { + protectVTree(refTree); } - const newNode = createNode(newTree); + const newNode = createNode(newTree, ownerDocument, isSVG); protectVTree(newTree); // If refNode is `null` then it will simply append like `appendChild`. - domNode.insertBefore(newNode, referenceNode); + domNode.insertBefore(newNode, refNode); const attachedPromises = runTransitions('attached', newNode); @@ -171,7 +172,7 @@ export default function patchNode(patches) { const oldTree = REPLACE_CHILD[i + 1]; const oldDomNode = NodeCache.get(oldTree); - const newDomNode = createNode(newTree); + const newDomNode = createNode(newTree, ownerDocument, isSVG); const attached = TransitionCache.get('attached'); const detached = TransitionCache.get('detached'); const replaced = TransitionCache.get('replaced'); diff --git a/packages/diffhtml/lib/tasks/patch-node.js b/packages/diffhtml/lib/tasks/patch-node.js index 105f1ecf..3b97d357 100644 --- a/packages/diffhtml/lib/tasks/patch-node.js +++ b/packages/diffhtml/lib/tasks/patch-node.js @@ -10,6 +10,12 @@ export default function patch(transaction) { const { domNode, state, state: { measure }, patches } = transaction; const { promises = [] } = transaction; + // Is the root SVG? + state.isSVG = transaction.oldTree.nodeName === 'svg'; + + // Set the ownerDocument. + state.ownerDocument = domNode.ownerDocument || document; + measure('patch node'); promises.push(...patchNode(patches, state)); measure('patch node'); diff --git a/packages/diffhtml/lib/util/svg.js b/packages/diffhtml/lib/util/svg.js index 8d1770ea..d6b57e7a 100644 --- a/packages/diffhtml/lib/util/svg.js +++ b/packages/diffhtml/lib/util/svg.js @@ -1,82 +1,2 @@ // Namespace. export const namespace = 'http://www.w3.org/2000/svg'; - -// List of SVG elements. -export const elements = [ - 'altGlyph', - 'altGlyphDef', - 'altGlyphItem', - 'animate', - 'animateColor', - 'animateMotion', - 'animateTransform', - 'circle', - 'clipPath', - 'color-profile', - 'cursor', - 'defs', - 'desc', - 'ellipse', - 'feBlend', - 'feColorMatrix', - 'feComponentTransfer', - 'feComposite', - 'feConvolveMatrix', - 'feDiffuseLighting', - 'feDisplacementMap', - 'feDistantLight', - 'feFlood', - 'feFuncA', - 'feFuncB', - 'feFuncG', - 'feFuncR', - 'feGaussianBlur', - 'feImage', - 'feMerge', - 'feMergeNode', - 'feMorphology', - 'feOffset', - 'fePointLight', - 'feSpecularLighting', - 'feSpotLight', - 'feTile', - 'feTurbulence', - 'filter', - 'font', - 'font-face', - 'font-face-format', - 'font-face-name', - 'font-face-src', - 'font-face-uri', - 'foreignObject', - 'g', - 'glyph', - 'glyphRef', - 'hkern', - 'image', - 'line', - 'linearGradient', - 'marker', - 'mask', - 'metadata', - 'missing-glyph', - 'mpath', - 'path', - 'pattern', - 'polygon', - 'polyline', - 'radialGradient', - 'rect', - 'set', - 'stop', - 'svg', - 'switch', - 'symbol', - 'text', - 'textPath', - 'tref', - 'tspan', - 'use', - 'view', - 'vkern', -]; diff --git a/packages/diffhtml/test/integration/svg.js b/packages/diffhtml/test/integration/svg.js index e510b67e..4f7f3d6f 100644 --- a/packages/diffhtml/test/integration/svg.js +++ b/packages/diffhtml/test/integration/svg.js @@ -4,8 +4,7 @@ import validateMemory from '../util/validateMemory'; describe('Integration: SVG', function() { beforeEach(function() { - this.fixture = document.createElement('div'); - this.fixture.innerHTML = ''; + this.fixture = document.createElement('svg'); this.namespace = 'http://www.w3.org/2000/svg'; }); diff --git a/packages/diffhtml/test/util.js b/packages/diffhtml/test/util.js index bbf1a470..90deb40b 100644 --- a/packages/diffhtml/test/util.js +++ b/packages/diffhtml/test/util.js @@ -7,7 +7,7 @@ import decodeEntities from '../lib/util/decode-entities'; import escape from '../lib/util/escape'; import parse from '../lib/util/parse'; import _process from '../lib/util/process'; -import { namespace, elements } from '../lib/util/svg'; +import { namespace } from '../lib/util/svg'; import { protectVTree, unprotectVTree, cleanMemory } from '../lib/util/memory'; import makeMeasure from '../lib/util/make-measure'; import Pool from '../lib/util/pool'; @@ -853,11 +853,6 @@ describe('Util', function() { }); describe('SVG', () => { - it('exports a list of valid SVG elements', () => { - ok(Array.isArray(elements)); - ok(elements.length); - }); - it('exports the SVG namespace', () => { equal(namespace, 'http://www.w3.org/2000/svg'); });