Skip to content

Commit

Permalink
Merge pull request #26 from mwiencek/serialization-fixes
Browse files Browse the repository at this point in the history
Handle void elements, HTML escaping in serialization code
  • Loading branch information
Raynos committed Jun 17, 2015
2 parents b085c99 + a216507 commit fc4f96d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 16 deletions.
38 changes: 28 additions & 10 deletions serialize.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
module.exports = serializeNode

var voidElements = /area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr/i;

function serializeNode(node) {
switch (node.nodeType) {
case 3:
return escapeText(node.data)
case 8:
return "<!--" + node.data + "-->"
default:
Expand All @@ -18,18 +22,21 @@ function serializeElement(elem) {
tagname = tagname.toLowerCase()
}

strings.push("<" + tagname +
properties(elem) + datasetify(elem) + ">")
strings.push("<" + tagname + properties(elem) + datasetify(elem))

if (elem.textContent || elem.innerText) {
strings.push(elem.textContent || elem.innerText)
}
if (voidElements.test(tagname)) {
strings.push(" />")
} else {
strings.push(">")

elem.childNodes.forEach(function (node) {
strings.push(serializeNode(node))
})
if (elem.childNodes.length) {
strings.push.apply(strings, elem.childNodes.map(serializeNode))
} else {
strings.push(escapeText(elem.textContent || elem.innerText || ""))
}

strings.push("</" + tagname + ">")
strings.push("</" + tagname + ">")
}

return strings.join("")
}
Expand Down Expand Up @@ -77,7 +84,7 @@ function stringify(list) {
value = stylify(value)
}

attributes.push(name + "=" + "\"" + value + "\"")
attributes.push(name + "=" + "\"" + escapeAttributeValue(value) + "\"")
})

return attributes.length ? " " + attributes.join(" ") : ""
Expand All @@ -104,3 +111,14 @@ function properties(elem) {

return props.length ? stringify(props) : ""
}

function escapeText(str) {
return str
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
}

function escapeAttributeValue(str) {
return escapeText(str).replace(/"/g, "&quot;")
}
7 changes: 3 additions & 4 deletions test/test-document.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,17 @@ function testDocument(document) {

var span = document.createElement("span")
div.appendChild(span)
span.textContent = "Hello!"
span.textContent = "Hello! <&>"

var html = String(div.outerHTML || div)

assert.equal(html, "<div class=\"foo bar\">" +
"<span>Hello!</span></div>")
"<span>Hello! &lt;&amp;&gt;</span></div>")

cleanup()
assert.end()
})


test("can createDocumentFragment", function (assert) {
var frag = document.createDocumentFragment()

Expand Down Expand Up @@ -328,7 +327,7 @@ function testDocument(document) {
test("input has type=text by default", function (assert) {
var elem = document.createElement("input")
assert.equal(elem.type, "text");
assert.equal(elemString(elem), "<input type=\"text\"></input>")
assert.equal(elemString(elem), "<input type=\"text\" />")
assert.end()
})

Expand Down
20 changes: 18 additions & 2 deletions test/test-dom-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ function testDomElement(document) {

test("does not serialize innerText as an attribute", function(assert) {
var div = document.createElement("div")
div.innerText = "Test"
assert.equal(div.toString(), "<div>Test</div>")
div.innerText = "Test <&>"
assert.equal(div.toString(), "<div>Test &lt;&amp;&gt;</div>")
cleanup()
assert.end()
})
Expand Down Expand Up @@ -115,4 +115,20 @@ function testDomElement(document) {
cleanup()
assert.end()
})

test("can serialize text nodes", function(assert) {
var div = document.createElement("div")
div.appendChild(document.createTextNode('<test> "&'))
assert.equal(div.toString(), '<div>&lt;test&gt; "&amp;</div>')
cleanup()
assert.end()
})

test("escapes serialized attribute values", function(assert) {
var div = document.createElement("div")
div.setAttribute("data-foo", '<p>"&')
assert.equal(div.toString(), '<div data-foo="&lt;p&gt;&quot;&amp;"></div>')
cleanup()
assert.end()
})
}

0 comments on commit fc4f96d

Please sign in to comment.