marko/test/util/domToString.js
Patrick Steele-Idem 2be98636ea Fixes #817 - Support dynamic root elements
[Optimizations] Simplified bookkeeping for component tree
A component stack is no longer used

Small API improvements

Improved how component boundaries are managed

Assign keys to all HTML elements and custom tags for better diffing

Checking in progress

Just build the src when calculating size
2017-09-08 12:32:17 -06:00

137 lines
4.1 KiB
JavaScript

function ltrim(s) {
return s ? s.replace(/^\s\s*/,'') : '';
}
function getNodeType(node) {
return node.nodeType || node.___nodeType;
}
function getNodeValue(node) {
return node.___nodeValue || node.nodeValue;
}
function getFirstChild(node) {
return node.___firstChild || node.firstChild;
}
function getNextSibling(node) {
return node.___nextSibling || node.nextSibling;
}
function vdomToHTML(node, options) {
// NOTE: We don't use XMLSerializer because we need to sort the attributes to correctly compare output HTML strings
// BAD: return (new XMLSerializer()).serializeToString(node);
var html = '';
function serializeHelper(node, indent) {
var nodeType = getNodeType(node);
if (nodeType === 1) {
serializeElHelper(node, indent);
} else if (nodeType === 3) {
serializeTextHelper(node, indent);
} else if (nodeType === 8) {
serializeCommentHelper(node, indent);
} else {
console.log('Invalid node:', node);
html += indent + `INVALID NODE TYPE ${nodeType}\n`;
// throw new Error('Unexpected node type');
}
}
function serializeElHelper(el, indent) {
var tagName = el.nodeName || el.___nodeName;
var elNamespaceURI = el.namespaceURI || el.___namespaceURI;
if (elNamespaceURI === 'http://www.w3.org/2000/svg') {
tagName = 'svg:' + tagName;
} else if (elNamespaceURI === 'http://www.w3.org/1998/Math/MathML') {
tagName = 'math:' + tagName;
}
html += indent + '<' + tagName;
var attributes = el.attributes || el.___attributes;
var attributesArray = [];
var attrName;
if (typeof attributes.length === 'number') {
for (var i=0; i<attributes.length; i++) {
var attr = attributes[i];
if (attr.namespaceURI) {
attrName = attr.namespaceURI + ':' + attr.localName;
} else {
attrName = attr.name;
}
if (attrName === 'data-marko-const') {
continue;
}
attributesArray.push(' ' + attrName + '="' + attr.value + '"');
}
} else {
for (attrName in attributes) {
if (attrName === 'data-marko-const') {
continue;
}
var attrValue = attributes[attrName];
if (typeof attrValue !== 'string') {
if (attrValue === true) {
attrValue = '';
} else if (attrValue == null || attrValue === false) {
continue;
}
}
if (attrName === 'xlink:href') {
attrName = 'http://www.w3.org/1999/xlink:href';
}
attributesArray.push(' ' + attrName + '="' + attrValue + '"');
}
}
attributesArray.sort();
html += attributesArray.join('');
html += '>\n';
if (tagName.toUpperCase() === 'TEXTAREA') {
html += indent + ' VALUE: ' + JSON.stringify(ltrim(el.value || el.___value)) + '\n';
} else {
var curChild = getFirstChild(el);
while(curChild) {
serializeHelper(curChild, indent + ' ');
curChild = getNextSibling(curChild);
}
}
}
function serializeTextHelper(node, indent) {
html += indent + JSON.stringify(getNodeValue(node)) + '\n';
}
function serializeCommentHelper(node, indent) {
html += indent + '<!--' + JSON.stringify(getNodeValue(node)) + '-->\n';
}
if (getNodeType(node) === 11 /* DocumentFragment */ || (options && options.childrenOnly)) {
var curChild = getFirstChild(node);
while(curChild) {
serializeHelper(curChild, '');
curChild = getNextSibling(curChild);
}
} else {
serializeHelper(node, '');
}
return html;
}
module.exports = vdomToHTML;