-
Notifications
You must be signed in to change notification settings - Fork 2
/
Sanitize.js
112 lines (100 loc) · 3.56 KB
/
Sanitize.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
"use strict";
/** Intented to strip XHTML down to minimum set of elements
* (i.e. Clean up the dirty HTML sometimes encountered)
*/
class Sanitize {
constructor() {
this.attributesForTag = new Map();
for(let t of Sanitize.TAG_LIST) {
let attributes = ["id", "class", "style"];
let extra = Sanitize.ATTRIBUTES[t];
if (extra !== undefined) {
for(let a of extra) {
attributes.push(a);
}
}
this.attributesForTag.set(t, attributes);
}
}
clean(element) {
let e2 = this.cloneTag(element);
return this.cloneChildren(e2, element);
}
cloneTag(element) {
let tag = element.tagName.toLowerCase();
let validAttributes = this.attributesForTag.get(tag);
if (validAttributes === undefined) {
tag = "div";
validAttributes = this.attributesForTag.get(tag);
}
let e2 = this.isSvgElement(tag)
? this.makeSvgElement(tag)
: document.createElement(tag)
return this.copyAttributes(e2, element, validAttributes);
}
isSvgElement(tag) {
return (tag === "svg") || (tag === "image") || (tag === "desc");
}
makeSvgElement(tag) {
return document.createElementNS("http://www.w3.org/2000/svg", tag);
}
copyAttributes(e2, element, validAttributes) {
for(let attribName of validAttributes) {
let val = element.getAttribute(attribName);
if (val !== null) {
e2.setAttribute(attribName, val);
}
}
return e2;
}
cloneChildren(e2, element) {
for(let child of element.childNodes) {
let clone = this.cloneChildNode(child);
if (clone !== null) {
e2.appendChild(clone);
}
}
return e2;
}
cloneChildNode(childNode) {
switch(childNode.nodeType) {
case 1:
// Element
return this.clean(childNode);
case 3:
// Text
return this.cleanTextNode(childNode);
case 8:
// comment
return childNode.cloneNode();
default:
return null;
}
}
cleanTextNode(textNode) {
// ToDo: fully implement
let text = textNode.nodeValue;
return document.createTextNode(text);
}
}
Sanitize.TAG_LIST = ["a", "abbr", "access", "action",
"address", "blockcode", "blockquote", "body", "br", "caption", "cite", "code",
"col", "colgroup", "dd", "delete", "desc", "dfn", "di", "dispatch", "div", "dl",
"dt", "em", "ev:listener", "group", "h",
"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8",
"handler", "head", "heading",
"html", "img", "image", "input", "insert", "kbd", "l", "label", "li", "link",
"load", "message", "meta", "model", "nl", "object", "ol", "output",
"p", "param", "pre", "quote", "range", "rebuild", "recalculate",
"refresh", "repeat", "reset", "revalidate", "ruby", "samp", "secret",
"section", "select1", "select", "send", "separator", "setfocus",
"setindex", "setvalue", "span", "standby", "strong", "style", "sub",
"submit", "summary", "sup", "svg", "switch", "table", "tbody", "td",
"textarea", "tfoot", "th", "thead", "title", "tr", "trigger",
"ul", "upload", "var"];
Sanitize.ATTRIBUTES = {
"a": ["href"],
"img": ["src"],
"image": ["xlink:href", "width", "height"],
"svg": ["xmlns", "xmlns:xlink", "height", "width", "version", "preserveAspectRatio", "viewBox"]
};