]>
Commit | Line | Data |
---|---|---|
51a2f11c TL |
1 | // NOTE: just relays parsing to markedjs parser |
2 | Ext.define('Proxmox.Markdown', { | |
3 | alternateClassName: 'Px.Markdown', // just trying out something, do NOT copy this line | |
4 | singleton: true, | |
5 | ||
6 | // transforms HTML to a DOM tree and recursively descends and prunes every branch with a | |
7 | // "bad" node.type and drops "bad" attributes from the remaining nodes. | |
8 | // "bad" means anything which can do XSS or break the layout of the outer page | |
9 | sanitizeHTML: function(input) { | |
10 | if (!input) { | |
11 | return input; | |
12 | } | |
13 | let _sanitize; | |
14 | _sanitize = (node) => { | |
15 | if (node.nodeType === 3) return; | |
16 | if (node.nodeType !== 1 || /^(script|iframe|object|embed|svg)$/i.test(node.tagName)) { | |
17 | node.remove(); | |
18 | return; | |
19 | } | |
20 | for (let i=node.attributes.length; i--;) { | |
21 | const name = node.attributes[i].name; | |
22 | // TODO: we may want to also disallow class and id attrs | |
a610dd9e | 23 | if (!/^(class|id|name|href|src|alt|align|valign|disabled|checked|start|type)$/i.test(name)) { |
51a2f11c TL |
24 | node.attributes.removeNamedItem(name); |
25 | } | |
26 | } | |
27 | for (let i=node.childNodes.length; i--;) _sanitize(node.childNodes[i]); | |
28 | }; | |
29 | ||
30 | const doc = new DOMParser().parseFromString(`<!DOCTYPE html><html><body>${input}`, 'text/html'); | |
31 | doc.normalize(); | |
32 | ||
33 | _sanitize(doc.body); | |
34 | ||
35 | return doc.body.innerHTML; | |
36 | }, | |
37 | ||
38 | parse: function(markdown) { | |
39 | /*global marked*/ | |
40 | let unsafeHTML = marked(markdown); | |
41 | ||
42 | return `<div class="pmx-md">${this.sanitizeHTML(unsafeHTML)}</div>`; | |
43 | }, | |
44 | ||
45 | }); |