diff options
Diffstat (limited to 'node_modules/min-document/serialize.js')
-rw-r--r-- | node_modules/min-document/serialize.js | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/node_modules/min-document/serialize.js b/node_modules/min-document/serialize.js new file mode 100644 index 000000000..4411d3c37 --- /dev/null +++ b/node_modules/min-document/serialize.js @@ -0,0 +1,139 @@ +module.exports = serializeNode + +var voidElements = ["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"]; + +function serializeNode(node) { + switch (node.nodeType) { + case 3: + return escapeText(node.data) + case 8: + return "<!--" + node.data + "-->" + default: + return serializeElement(node) + } +} + +function serializeElement(elem) { + var strings = [] + + var tagname = elem.tagName + + if (elem.namespaceURI === "http://www.w3.org/1999/xhtml") { + tagname = tagname.toLowerCase() + } + + strings.push("<" + tagname + properties(elem) + datasetify(elem)) + + if (voidElements.indexOf(tagname) > -1) { + strings.push(" />") + } else { + strings.push(">") + + if (elem.childNodes.length) { + strings.push.apply(strings, elem.childNodes.map(serializeNode)) + } else if (elem.textContent || elem.innerText) { + strings.push(escapeText(elem.textContent || elem.innerText)) + } else if (elem.innerHTML) { + strings.push(elem.innerHTML) + } + + strings.push("</" + tagname + ">") + } + + return strings.join("") +} + +function isProperty(elem, key) { + var type = typeof elem[key] + + if (key === "style" && Object.keys(elem.style).length > 0) { + return true + } + + return elem.hasOwnProperty(key) && + (type === "string" || type === "boolean" || type === "number") && + key !== "nodeName" && key !== "className" && key !== "tagName" && + key !== "textContent" && key !== "innerText" && key !== "namespaceURI" && key !== "innerHTML" +} + +function stylify(styles) { + if (typeof styles === 'string') return styles + var attr = "" + Object.keys(styles).forEach(function (key) { + var value = styles[key] + key = key.replace(/[A-Z]/g, function(c) { + return "-" + c.toLowerCase(); + }) + attr += key + ":" + value + ";" + }) + return attr +} + +function datasetify(elem) { + var ds = elem.dataset + var props = [] + + for (var key in ds) { + props.push({ name: "data-" + key, value: ds[key] }) + } + + return props.length ? stringify(props) : "" +} + +function stringify(list) { + var attributes = [] + list.forEach(function (tuple) { + var name = tuple.name + var value = tuple.value + + if (name === "style") { + value = stylify(value) + } + + attributes.push(name + "=" + "\"" + escapeAttributeValue(value) + "\"") + }) + + return attributes.length ? " " + attributes.join(" ") : "" +} + +function properties(elem) { + var props = [] + for (var key in elem) { + if (isProperty(elem, key)) { + props.push({ name: key, value: elem[key] }) + } + } + + for (var ns in elem._attributes) { + for (var attribute in elem._attributes[ns]) { + var prop = elem._attributes[ns][attribute] + var name = (prop.prefix ? prop.prefix + ":" : "") + attribute + props.push({ name: name, value: prop.value }) + } + } + + if (elem.className) { + props.push({ name: "class", value: elem.className }) + } + + return props.length ? stringify(props) : "" +} + +function escapeText(s) { + var str = ''; + + if (typeof(s) === 'string') { + str = s; + } else if (s) { + str = s.toString(); + } + + return str + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") +} + +function escapeAttributeValue(str) { + return escapeText(str).replace(/"/g, """) +} |