1 module.exports = serializeNode
3 var voidElements = ["area","base","br","col","embed","hr","img","input","keygen","link","menuitem","meta","param","source","track","wbr"];
5 function serializeNode(node) {
6 switch (node.nodeType) {
8 return escapeText(node.data)
10 return "<!--" + node.data + "-->"
12 return serializeElement(node)
16 function serializeElement(elem) {
19 var tagname = elem.tagName
21 if (elem.namespaceURI === "http://www.w3.org/1999/xhtml") {
22 tagname = tagname.toLowerCase()
25 strings.push("<" + tagname + properties(elem) + datasetify(elem))
27 if (voidElements.indexOf(tagname) > -1) {
32 if (elem.childNodes.length) {
33 strings.push.apply(strings, elem.childNodes.map(serializeNode))
34 } else if (elem.textContent || elem.innerText) {
35 strings.push(escapeText(elem.textContent || elem.innerText))
36 } else if (elem.innerHTML) {
37 strings.push(elem.innerHTML)
40 strings.push("</" + tagname + ">")
43 return strings.join("")
46 function isProperty(elem, key) {
47 var type = typeof elem[key]
49 if (key === "style" && Object.keys(elem.style).length > 0) {
53 return elem.hasOwnProperty(key) &&
54 (type === "string" || type === "boolean" || type === "number") &&
55 key !== "nodeName" && key !== "className" && key !== "tagName" &&
56 key !== "textContent" && key !== "innerText" && key !== "namespaceURI" && key !== "innerHTML"
59 function stylify(styles) {
60 if (typeof styles === 'string') return styles
62 Object.keys(styles).forEach(function (key) {
63 var value = styles[key]
64 key = key.replace(/[A-Z]/g, function(c) {
65 return "-" + c.toLowerCase();
67 attr += key + ":" + value + ";"
72 function datasetify(elem) {
77 props.push({ name: "data-" + key, value: ds[key] })
80 return props.length ? stringify(props) : ""
83 function stringify(list) {
85 list.forEach(function (tuple) {
87 var value = tuple.value
89 if (name === "style") {
90 value = stylify(value)
93 attributes.push(name + "=" + "\"" + escapeAttributeValue(value) + "\"")
96 return attributes.length ? " " + attributes.join(" ") : ""
99 function properties(elem) {
101 for (var key in elem) {
102 if (isProperty(elem, key)) {
103 props.push({ name: key, value: elem[key] })
107 for (var ns in elem._attributes) {
108 for (var attribute in elem._attributes[ns]) {
109 var prop = elem._attributes[ns][attribute]
110 var name = (prop.prefix ? prop.prefix + ":" : "") + attribute
111 props.push({ name: name, value: prop.value })
115 if (elem.className) {
116 props.push({ name: "class", value: elem.className })
119 return props.length ? stringify(props) : ""
122 function escapeText(s) {
125 if (typeof(s) === 'string') {
132 .replace(/&/g, "&")
133 .replace(/</g, "<")
134 .replace(/>/g, ">")
137 function escapeAttributeValue(str) {
138 return escapeText(str).replace(/"/g, """)