mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
[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
137 lines
4.1 KiB
JavaScript
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;
|