docs: function applyDOM(dom, vdom, document) {
  	if (!dom || !vdom) return;
  	if (!isArray(vdom)) {
  		// if we have a node
  		if (!isArray(vdom.children)) vdom.children = [vdom.children];
  		if (dom.__hash !== vdom.__hash) {
  			// if the tag name is not the same
  			if (vdom.tagName !== dom.tagName.toLowerCase()) {
  				// replace the node entirely
  				dom.parentNode.replaceChild(createElement(vdom, document), dom);
  			} else {
  				var attributes = Object.keys(vdom.attributes);
  				// check all vdom attributes
  				for (var attr, _index = 0, len = attributes.length; attr = vdom.attributes[attributes[_index]], _index < len; _index += 1) {
  					// if the VDOM attribute is a non-object
  					if (_typeof(attr.value) !== 'object') {
  						// check if it differs
  						if (dom.getAttribute(attr.name) != attr.value) {
  							// if so, apply it
  							dom.setAttribute(attr.name, attr.value);
  						}
  					} else {
  						// the attribute is an object
  						if (dom.getAttribute(attr.name) && dom.getAttribute(attr.name).match(/^--|--$/g)) {
  							// if it has a complex value, use the data resolver to define it on the DOM
  							var id = dataResolver(attr.name, attr.value, dom.getAttribute(attr.name).replace(/^--|--$/g, ''));
  							// only set the ID with markers so that we know it is supposed to be a complex value
  							dom.setAttribute(attr.name, '--' + id + '--');
  						}
  					}
  				}
  				// if we have too many attributes in our DOM
  				var index = 0;
  				while (dom.attributes.length > attributes.length) {
  					var _attr = dom.attributes[index];
  					// if the respective attribute does not exist on the VDOM
  					if (typeof vdom.attributes[_attr.name] === 'undefined') {
  						// remove it
  						dom.removeAttribute(_attr.name);
  						index = 0;
  						continue;
  					}
  					index += 1;
  				}
  			}
  		}
  	}
  
  	// deal with the vdom's children
  	var children = isArray(vdom) ? vdom : vdom.__hash !== dom.__hash ? vdom.children : [];
  	for (var _index2 = 0, node, _len2 = children.length; node = children[_index2], _index2 < _len2; _index2 += 1) {
  		if (isArray(node)) return applyDOM(dom, node, document);
  		var domChild = dom.childNodes[_index2];
  		if (typeof domChild === 'undefined') {
  			// does not exist, so it needs to be appended
  			dom.appendChild(createElement(node, document));
  		} else if (domChild.nodeType === 3) {
  			// is a text node
  			// if the VDOM node is also a text node
  			if (typeof node === 'string' && domChild.nodeValue !== node) {
  				applyText(domChild, dom, node, document);
  			} else if (typeof node !== 'string') {
  				// else replace with a new element
  				dom.replaceChild(createElement(node, document), domChild);
  			}
  		} else if (domChild.nodeType === 1) {
  			// is a normal HTML tag
  			if ((typeof node === 'undefined' ? 'undefined' : _typeof(node)) === 'object') {
  				// the VDOM is also a tag, apply it recursively
  				applyDOM(domChild, node, document);
  			} else {
  				applyText(domChild, dom, node, document);
  			}
  		}
  	}
  	if (dom.__hash !== vdom.__hash && dom.childNodes.length > children.length) {
  		// remove superfluous child nodes
  		for (var _index3 = children.length, _len3 = dom.childNodes.length; _index3 < _len3; _index3 += 1) {
  			dom.removeChild(dom.childNodes[_index3]);
  			_len3 -= 1;
  			_index3 -= 1;
  		}
  	}
  	dom.__hash = vdom.__hash;
  	dom.setAttribute = setAttribute.bind(dom);
  }