diff --git a/docs/change-log.md b/docs/change-log.md
index 87343422..19b701a9 100644
--- a/docs/change-log.md
+++ b/docs/change-log.md
@@ -29,7 +29,8 @@
- API: Event handlers may also be objects with `handleEvent` methods ([#1939](https://github.com/MithrilJS/mithril.js/issues/1939)).
- API: `m.route.link` accepts an optional `options` object ([#1930](https://github.com/MithrilJS/mithril.js/pull/1930))
- API: `m.request` supports `timeout` as attr - ([#1966](https://github.com/MithrilJS/mithril.js/pull/1966))
-- Mocks: add limited support for the DOMParser API
+- Mocks: add limited support for the DOMParser API ([#2097](https://github.com/MithrilJS/mithril.js/pull/2097))
+- API: add support for raw SVG in `m.trust()` string ([#2097](https://github.com/MithrilJS/mithril.js/pull/2097))
#### Bug fixes
diff --git a/docs/trust.md b/docs/trust.md
index d960e743..34e6ace8 100644
--- a/docs/trust.md
+++ b/docs/trust.md
@@ -11,7 +11,7 @@
### Description
-Turns an HTML string into unescaped HTML. **Do not use `m.trust` on unsanitized user input.**
+Turns an HTML or SVG string into unescaped HTML or SVG. **Do not use `m.trust` on unsanitized user input.**
Always try to use an [alternative method](#avoid-trusting-html) first, before considering using `m.trust`.
@@ -23,7 +23,7 @@ Always try to use an [alternative method](#avoid-trusting-html) first, before co
Argument | Type | Required | Description
----------- | -------------------- | -------- | ---
-`html` | `String` | Yes | A string containing HTML text
+`html` | `String` | Yes | A string containing HTML or SVG text
**returns** | `Vnode` | | A trusted HTML [vnode](vnodes.md) that represents the input string
[How to read signatures](signatures.md)
diff --git a/render/render.js b/render/render.js
index 9efbde96..98e0f4d1 100644
--- a/render/render.js
+++ b/render/render.js
@@ -52,7 +52,7 @@ module.exports = function($window) {
if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
switch (tag) {
case "#": return createText(parent, vnode, nextSibling)
- case "<": return createHTML(parent, vnode, nextSibling)
+ case "<": return createHTML(parent, vnode, ns, nextSibling)
case "[": return createFragment(parent, vnode, hooks, ns, nextSibling)
default: return createElement(parent, vnode, hooks, ns, nextSibling)
}
@@ -64,12 +64,16 @@ module.exports = function($window) {
insertNode(parent, vnode.dom, nextSibling)
return vnode.dom
}
- function createHTML(parent, vnode, nextSibling) {
+ var possibleParents = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}
+ function createHTML(parent, vnode, ns, nextSibling) {
var match = vnode.children.match(/^\s*?<(\w+)/im) || []
- var parent1 = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}[match[1]] || "div"
- var temp = $doc.createElement(parent1)
-
- temp.innerHTML = vnode.children
+ var temp = $doc.createElement(possibleParents[match[1]] || "div")
+ if (ns === "http://www.w3.org/2000/svg") {
+ temp.innerHTML = ""
+ temp = temp.firstChild
+ } else {
+ temp.innerHTML = vnode.children
+ }
vnode.dom = temp.firstChild
vnode.domSize = temp.childNodes.length
var fragment = $doc.createDocumentFragment()
@@ -404,7 +408,7 @@ module.exports = function($window) {
}
switch (oldTag) {
case "#": updateText(old, vnode); break
- case "<": updateHTML(parent, old, vnode, nextSibling); break
+ case "<": updateHTML(parent, old, vnode, ns, nextSibling); break
case "[": updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns); break
default: updateElement(old, vnode, recycling, hooks, ns)
}
@@ -422,10 +426,10 @@ module.exports = function($window) {
}
vnode.dom = old.dom
}
- function updateHTML(parent, old, vnode, nextSibling) {
+ function updateHTML(parent, old, vnode, ns, nextSibling) {
if (old.children !== vnode.children) {
toFragment(old)
- createHTML(parent, vnode, nextSibling)
+ createHTML(parent, vnode, ns, nextSibling)
}
else vnode.dom = old.dom, vnode.domSize = old.domSize
}
diff --git a/render/tests/test-createHTML.js b/render/tests/test-createHTML.js
index bb0d508c..a337213b 100644
--- a/render/tests/test-createHTML.js
+++ b/render/tests/test-createHTML.js
@@ -31,7 +31,7 @@ o.spec("createHTML", function() {
o(vnode.dom).equals(null)
o(vnode.domSize).equals(0)
})
- o("handles multiple children", function() {
+ o("handles multiple children in HTML", function() {
var vnode = {tag: "<", children: ""}
render(root, [vnode])
@@ -51,4 +51,34 @@ o.spec("createHTML", function() {
o(vnode.dom.nodeName).equals(tag.toUpperCase())
})
})
+ o("creates SVG", function() {
+ var vnode = {tag: "<", children: ""}
+ render(root, [{tag:"svg", children: [vnode]}])
+
+ o(vnode.dom.nodeName).equals("g")
+ o(vnode.dom.namespaceURI).equals("http://www.w3.org/2000/svg")
+ })
+ o("creates text SVG", function() {
+ var vnode = {tag: "<", children: "a"}
+ render(root, [{tag:"svg", children: [vnode]}])
+
+ o(vnode.dom.nodeValue).equals("a")
+ })
+ o("handles empty SVG", function() {
+ var vnode = {tag: "<", children: ""}
+ render(root, [{tag:"svg", children: [vnode]}])
+
+ o(vnode.dom).equals(null)
+ o(vnode.domSize).equals(0)
+ })
+ o("handles multiple children in SVG", function() {
+ var vnode = {tag: "<", children: ""}
+ render(root, [{tag:"svg", children: [vnode]}])
+
+ o(vnode.domSize).equals(2)
+ o(vnode.dom.nodeName).equals("g")
+ o(vnode.dom.namespaceURI).equals("http://www.w3.org/2000/svg")
+ o(vnode.dom.nextSibling.nodeName).equals("text")
+ o(vnode.dom.nextSibling.namespaceURI).equals("http://www.w3.org/2000/svg")
+ })
})