mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
142 lines
3.8 KiB
JavaScript
142 lines
3.8 KiB
JavaScript
'use strict';
|
|
|
|
var runtimeHtmlHelpers = require('../../runtime/html/helpers');
|
|
var escapeXml = runtimeHtmlHelpers.x;
|
|
var escapeXmlAttr = runtimeHtmlHelpers.xa;
|
|
|
|
var openTagOnly = {};
|
|
|
|
[
|
|
'base',
|
|
'br',
|
|
'col',
|
|
'hr',
|
|
'embed',
|
|
'img',
|
|
'input',
|
|
'keygen',
|
|
'link',
|
|
'meta',
|
|
'param',
|
|
'source',
|
|
'track',
|
|
'wbr'
|
|
].forEach(function(tagName) {
|
|
openTagOnly[tagName] = true;
|
|
});
|
|
|
|
|
|
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) {
|
|
if (node.nodeType === 1) {
|
|
serializeElHelper(node);
|
|
} else if (node.nodeType === 3) {
|
|
serializeTextHelper(node);
|
|
} else if (node.nodeType === 8) {
|
|
serializeCommentHelper(node);
|
|
} else {
|
|
console.log('Invalid node:', node);
|
|
html += `INVALID NODE TYPE ${node.nodeType}\n`;
|
|
}
|
|
}
|
|
|
|
function serializeElHelper(el) {
|
|
var tagName = el.nodeName;
|
|
|
|
html += '<' + tagName;
|
|
|
|
var attributes = el.attributes;
|
|
var attributesArray = [];
|
|
var attrName;
|
|
|
|
if (typeof attributes.length === 'number') {
|
|
for (var i=0; i<attributes.length; i++) {
|
|
var attr = attributes[i];
|
|
attrName = attr.name;
|
|
|
|
if (attrName === 'data-marko-const') {
|
|
continue;
|
|
}
|
|
attributesArray.push(' ' + attrName + '="' + escapeXmlAttr(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) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (attrName === 'xlink:href') {
|
|
attrName = 'http://www.w3.org/1999/xlink:href';
|
|
}
|
|
attributesArray.push(' ' + attrName + '="' + escapeXmlAttr(attrValue) + '"');
|
|
}
|
|
}
|
|
|
|
attributesArray.sort();
|
|
|
|
html += attributesArray.join('');
|
|
|
|
html += '>';
|
|
|
|
var hasEndTag = true;
|
|
if (tagName.toUpperCase() === 'TEXTAREA') {
|
|
html += el.value;
|
|
} else {
|
|
var curChild = el.firstChild;
|
|
if (curChild) {
|
|
while(curChild) {
|
|
if (curChild.nodeType === 3) {
|
|
let escapeText = tagName.toUpperCase() !== 'SCRIPT';
|
|
serializeTextHelper(curChild, escapeText);
|
|
} else {
|
|
serializeHelper(curChild);
|
|
}
|
|
|
|
curChild = curChild.nextSibling;
|
|
}
|
|
} else if (openTagOnly[tagName.toLowerCase()]) {
|
|
hasEndTag = false;
|
|
}
|
|
}
|
|
|
|
if (hasEndTag) {
|
|
html += '</' + tagName + '>';
|
|
}
|
|
}
|
|
|
|
function serializeTextHelper(node, escape) {
|
|
html += escape !== false ? escapeXml(node.nodeValue) : node.nodeValue;
|
|
}
|
|
|
|
function serializeCommentHelper(node) {
|
|
html += '<!--' + node.nodeValue + '-->';
|
|
}
|
|
|
|
if (node.nodeType === 11 /* DocumentFragment */ || (options && options.childrenOnly)) {
|
|
var curChild = node.firstChild;
|
|
while(curChild) {
|
|
serializeHelper(curChild);
|
|
curChild = curChild.nextSibling;
|
|
}
|
|
} else {
|
|
serializeHelper(node);
|
|
}
|
|
|
|
return html;
|
|
}
|
|
|
|
module.exports = vdomToHTML; |