Skip to content

Commit

Permalink
Removes the need for SVG elements list
Browse files Browse the repository at this point in the history
  • Loading branch information
tbranyen committed Jun 7, 2017
1 parent 57808d9 commit ec0ae20
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 106 deletions.
16 changes: 7 additions & 9 deletions 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;
Expand All @@ -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');
Expand All @@ -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;
Expand All @@ -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 <svg>
// 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.
Expand All @@ -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;
Expand Down
19 changes: 10 additions & 9 deletions packages/diffhtml/lib/node/patch.js
Expand Up @@ -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) {
Expand All @@ -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(
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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');
Expand Down
6 changes: 6 additions & 0 deletions packages/diffhtml/lib/tasks/patch-node.js
Expand Up @@ -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');
Expand Down
80 changes: 0 additions & 80 deletions 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',
];
3 changes: 1 addition & 2 deletions packages/diffhtml/test/integration/svg.js
Expand Up @@ -4,8 +4,7 @@ import validateMemory from '../util/validateMemory';

describe('Integration: SVG', function() {
beforeEach(function() {
this.fixture = document.createElement('div');
this.fixture.innerHTML = '<svg></svg>';
this.fixture = document.createElement('svg');
this.namespace = 'http://www.w3.org/2000/svg';
});

Expand Down
7 changes: 1 addition & 6 deletions packages/diffhtml/test/util.js
Expand Up @@ -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';
Expand Down Expand Up @@ -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');
});
Expand Down

0 comments on commit ec0ae20

Please sign in to comment.