@builder.io/sdk
Version:
169 lines (168 loc) • 4.63 kB
JavaScript
import VNode from 'virtual-dom/vnode/vnode';
import VText from 'virtual-dom/vnode/vtext';
// tslint:disable:no-increment-decrement
// CREDIT: adopted from https://raw.githubusercontent.com/marcelklehr/vdom-virtualize/master/index.js
export function createVNode(domNode, deep) {
if (deep === void 0) { deep = false; }
if (domNode.nodeType === 1)
return createFromElement(domNode, deep);
if (domNode.nodeType === 3)
return createFromTextNode(domNode);
return;
}
function createFromTextNode(tNode) {
return new VText(tNode.nodeValue);
}
function createFromElement(el, deep) {
if (deep === void 0) { deep = false; }
var tagName = el.tagName;
var namespace = el.namespaceURI === 'http://www.w3.org/1999/xhtml' ? null : el.namespaceURI;
var properties = getElementProperties(el);
var children = [];
if (deep) {
for (var i = 0; i < el.childNodes.length; i++) {
children.push(createVNode(el.childNodes[i]));
}
}
return new VNode(tagName, properties, children, null, namespace);
}
function getElementProperties(el) {
var obj = {};
for (var i = 0; i < props.length; i++) {
var propName = props[i];
if (!el[propName]) {
continue;
}
if (propName === 'style') {
var css = {};
if ('undefined' !== typeof el.style.length) {
for (var j = 0; j < el.style.length; j++) {
var styleProp = el.style[j];
css[styleProp] = el.style.getPropertyValue(styleProp); // TODO: add support for "!important" via getPropertyPriority()!
}
}
if (Object.keys(css).length) {
obj[propName] = css;
}
continue;
}
// https://msdn.microsoft.com/en-us/library/cc848861%28v=vs.85%29.aspx
// The img element does not support the HREF content attribute.
// In addition, the href property is read-only for the img Document Object Model (DOM) object
if (el.tagName.toLowerCase() === 'img' && propName === 'href') {
continue;
}
if (propName === 'attributes') {
var atts = Array.prototype.slice.call(el[propName]);
var hash = {};
for (var k = 0; k < atts.length; k++) {
var name_1 = atts[k].name;
if (obj[name_1] || obj[attrBlacklist[name_1]]) {
continue;
}
hash[name_1] = el.getAttribute(name_1);
}
obj[propName] = hash;
continue;
}
if (propName === 'tabIndex' && el.tabIndex === -1) {
continue;
}
// Special case: contentEditable
// browser use 'inherit' by default on all nodes, but does not allow setting it to ''
// diffing virtualize dom will trigger error
// ref: https://github.com/Matt-Esch/virtual-dom/issues/176
if (propName === 'contentEditable' && el[propName] === 'inherit') {
continue;
}
if ('object' === typeof el[propName]) {
continue;
}
// default: just copy the property
obj[propName] = el[propName];
}
return obj;
}
/**
* DOMNode property white list
* Taken from https://github.com/Raynos/react/blob/dom-property-config/src/browser/ui/dom/DefaultDOMPropertyConfig.js
*/
export var props = [
'accept',
'accessKey',
'action',
'alt',
'async',
'autoComplete',
'autoPlay',
'cellPadding',
'cellSpacing',
'checked',
'className',
'colSpan',
'content',
'contentEditable',
'controls',
'crossOrigin',
'data',
'defer',
'dir',
'download',
'draggable',
'encType',
'formNoValidate',
'href',
'hrefLang',
'htmlFor',
'httpEquiv',
'icon',
'id',
'label',
'lang',
'list',
'loop',
'max',
'mediaGroup',
'method',
'min',
'multiple',
'muted',
'name',
'noValidate',
'pattern',
'placeholder',
'poster',
'preload',
'radioGroup',
'readOnly',
'rel',
'required',
'rowSpan',
'sandbox',
'scope',
'scrollLeft',
'scrolling',
'scrollTop',
'selected',
'span',
'spellCheck',
'src',
'srcDoc',
'srcSet',
'start',
'step',
'style',
'tabIndex',
'target',
'title',
'type',
'value',
// Non-standard Properties
'autoCapitalize',
'autoCorrect',
'property',
'attributes',
];
export var attrBlacklist = {
class: 'className',
};