diff --git a/Sources/Html/Render.swift b/Sources/Html/Render.swift
index f5b3e64..fcae634 100644
--- a/Sources/Html/Render.swift
+++ b/Sources/Html/Render.swift
@@ -11,9 +11,9 @@ public func render(_ nodes: [Node]) -> String {
public func render(_ node: Node) -> String {
switch node {
case let .comment(string):
- return "", with: "-->")) -->"
+ return ""
case let .doctype(string):
- return "", with: ">"))>"
+ return ""
case let .element(tag, attribs, children):
let renderedAttribs = render(attribs)
guard !children.isEmpty else {
@@ -21,7 +21,7 @@ public func render(_ node: Node) -> String {
}
return "<" + tag + renderedAttribs + ">" + render(children) + "" + tag + ">"
case let .text(string):
- return escape(html: string)
+ return escapeTextNode(text: string)
case let .raw(string):
return string
}
@@ -39,20 +39,32 @@ private func render(_ attribs: [(String, String?)]) -> String {
return attribs
.compactMap { key, value in
value.map {
- " " + key + ($0.isEmpty ? "" : "=\"\($0.replacingOccurrences(of: "\"", with: """))\"")
+ " " + key + ($0.isEmpty ? "" : "=\"\(escapeAttributeValue($0))\"")
}
}
.joined()
}
-private func escape(html: String) -> String {
- return html
+public func escapeAttributeValue(_ value: String) -> String {
+ return value.replacingOccurrences(of: "\"", with: """)
+}
+
+public func escapeTextNode(text: String) -> String {
+ return text
.replacingOccurrences(of: "&", with: "&")
.replacingOccurrences(of: "<", with: "<")
}
+public func escapeDoctype(_ doctype: String) -> String {
+ return doctype.replacingOccurrences(of: ">", with: ">")
+}
+
+public func escapeHtmlComment(_ comment: String) -> String {
+ return comment.replacingOccurrences(of: "-->", with: "-->")
+}
+
/// A set of self-closing "void" elements that should not contain child nodes.
-private let voidElements: Set = [
+public let voidElements: Set = [
"area",
"base",
"br",