skatejs-dom-diff
Version:
Library for efficiently diffing and patching DOM fragments.
81 lines (68 loc) • 1.85 kB
JavaScript
import { isElement, isFragment, isString } from './util/is-type';
import fragment from './fragment';
import h from './h';
import nodeMap from './util/node-map';
import root from './util/root';
import text from './text';
import WeakMap from './util/weak-map';
const { NodeFilter } = root;
const { SHOW_DOCUMENT_FRAGMENT, SHOW_ELEMENT, SHOW_TEXT } = NodeFilter;
const vNodeMap = new WeakMap();
function getAttributes (node) {
const temp = {};
const { attributes } = node;
const { length } = attributes;
for (let a = 0; a < length; a++) {
const { name, value } = attributes[a];
temp[name] = value;
}
return temp;
}
function getFragmentFromString (str) {
const div = document.createElement('div');
const fra = document.createDocumentFragment();
div.innerHTML = str;
while (div.hasChildNodes()) {
fra.appendChild(div.firstChild);
}
return fra;
}
function getVNode (node) {
const { nodeType } = node;
if (nodeType === 3) {
return text(node.textContent);
}
const vNode = h(node.localName);
vNode.attributes = getAttributes(node);
nodeMap[vNode.__id] = node;
vNodeMap.set(node, vNode);
return vNode;
}
export default function (dom) {
let vRoot;
if (isElement(dom)) {
vRoot = getVNode(dom);
} else if (isFragment(dom)) {
vRoot = fragment();
} else if (isString(dom)) {
dom = getFragmentFromString(dom);
vRoot = fragment();
}
const walker = document.createTreeWalker(
dom,
SHOW_DOCUMENT_FRAGMENT | SHOW_ELEMENT | SHOW_TEXT,
null,
false
);
while (walker.nextNode()) {
const { currentNode } = walker;
const vNode = getVNode(currentNode);
const vNodeParent = vNodeMap.get(currentNode.parentNode);
if (vNodeParent) {
vNodeParent.childNodes.push(vNode);
} else {
vRoot.childNodes.push(vNode);
}
}
return vRoot;
}