dompurify 2.3.6 → 2.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/purify.cjs.js +425 -266
- package/dist/purify.cjs.js.map +1 -1
- package/dist/purify.es.js +426 -267
- package/dist/purify.es.js.map +1 -1
- package/dist/purify.js +427 -268
- package/dist/purify.js.map +1 -1
- package/dist/purify.min.js +2 -2
- package/dist/purify.min.js.map +1 -1
- package/package.json +14 -19
package/dist/purify.es.js
CHANGED
|
@@ -1,6 +1,86 @@
|
|
|
1
|
-
/*! @license DOMPurify 2.3.
|
|
1
|
+
/*! @license DOMPurify 2.3.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.7/LICENSE */
|
|
2
2
|
|
|
3
|
-
function
|
|
3
|
+
function _typeof(obj) {
|
|
4
|
+
"@babel/helpers - typeof";
|
|
5
|
+
|
|
6
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
|
|
7
|
+
return typeof obj;
|
|
8
|
+
} : function (obj) {
|
|
9
|
+
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
|
10
|
+
}, _typeof(obj);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function _setPrototypeOf(o, p) {
|
|
14
|
+
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
|
15
|
+
o.__proto__ = p;
|
|
16
|
+
return o;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return _setPrototypeOf(o, p);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function _isNativeReflectConstruct() {
|
|
23
|
+
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
24
|
+
if (Reflect.construct.sham) return false;
|
|
25
|
+
if (typeof Proxy === "function") return true;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
|
29
|
+
return true;
|
|
30
|
+
} catch (e) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function _construct(Parent, args, Class) {
|
|
36
|
+
if (_isNativeReflectConstruct()) {
|
|
37
|
+
_construct = Reflect.construct;
|
|
38
|
+
} else {
|
|
39
|
+
_construct = function _construct(Parent, args, Class) {
|
|
40
|
+
var a = [null];
|
|
41
|
+
a.push.apply(a, args);
|
|
42
|
+
var Constructor = Function.bind.apply(Parent, a);
|
|
43
|
+
var instance = new Constructor();
|
|
44
|
+
if (Class) _setPrototypeOf(instance, Class.prototype);
|
|
45
|
+
return instance;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return _construct.apply(null, arguments);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function _toConsumableArray(arr) {
|
|
53
|
+
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function _arrayWithoutHoles(arr) {
|
|
57
|
+
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function _iterableToArray(iter) {
|
|
61
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function _unsupportedIterableToArray(o, minLen) {
|
|
65
|
+
if (!o) return;
|
|
66
|
+
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
67
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
68
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
69
|
+
if (n === "Map" || n === "Set") return Array.from(o);
|
|
70
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function _arrayLikeToArray(arr, len) {
|
|
74
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
75
|
+
|
|
76
|
+
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
77
|
+
|
|
78
|
+
return arr2;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function _nonIterableSpread() {
|
|
82
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
83
|
+
}
|
|
4
84
|
|
|
5
85
|
var hasOwnProperty = Object.hasOwnProperty,
|
|
6
86
|
setPrototypeOf = Object.setPrototypeOf,
|
|
@@ -35,45 +115,40 @@ if (!seal) {
|
|
|
35
115
|
|
|
36
116
|
if (!construct) {
|
|
37
117
|
construct = function construct(Func, args) {
|
|
38
|
-
return
|
|
118
|
+
return _construct(Func, _toConsumableArray(args));
|
|
39
119
|
};
|
|
40
120
|
}
|
|
41
121
|
|
|
42
122
|
var arrayForEach = unapply(Array.prototype.forEach);
|
|
43
123
|
var arrayPop = unapply(Array.prototype.pop);
|
|
44
124
|
var arrayPush = unapply(Array.prototype.push);
|
|
45
|
-
|
|
46
125
|
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
47
126
|
var stringMatch = unapply(String.prototype.match);
|
|
48
127
|
var stringReplace = unapply(String.prototype.replace);
|
|
49
128
|
var stringIndexOf = unapply(String.prototype.indexOf);
|
|
50
129
|
var stringTrim = unapply(String.prototype.trim);
|
|
51
|
-
|
|
52
130
|
var regExpTest = unapply(RegExp.prototype.test);
|
|
53
|
-
|
|
54
131
|
var typeErrorCreate = unconstruct(TypeError);
|
|
55
|
-
|
|
56
132
|
function unapply(func) {
|
|
57
133
|
return function (thisArg) {
|
|
58
|
-
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
134
|
+
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
59
135
|
args[_key - 1] = arguments[_key];
|
|
60
136
|
}
|
|
61
137
|
|
|
62
138
|
return apply(func, thisArg, args);
|
|
63
139
|
};
|
|
64
140
|
}
|
|
65
|
-
|
|
66
141
|
function unconstruct(func) {
|
|
67
142
|
return function () {
|
|
68
|
-
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
143
|
+
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
69
144
|
args[_key2] = arguments[_key2];
|
|
70
145
|
}
|
|
71
146
|
|
|
72
147
|
return construct(func, args);
|
|
73
148
|
};
|
|
74
149
|
}
|
|
75
|
-
|
|
76
150
|
/* Add properties to a lookup table */
|
|
151
|
+
|
|
77
152
|
function addToSet(set, array) {
|
|
78
153
|
if (setPrototypeOf) {
|
|
79
154
|
// Make 'in' and truthy checks like Boolean(set.constructor)
|
|
@@ -83,10 +158,13 @@ function addToSet(set, array) {
|
|
|
83
158
|
}
|
|
84
159
|
|
|
85
160
|
var l = array.length;
|
|
161
|
+
|
|
86
162
|
while (l--) {
|
|
87
163
|
var element = array[l];
|
|
164
|
+
|
|
88
165
|
if (typeof element === 'string') {
|
|
89
166
|
var lcElement = stringToLowerCase(element);
|
|
167
|
+
|
|
90
168
|
if (lcElement !== element) {
|
|
91
169
|
// Config presets (e.g. tags.js, attrs.js) are immutable.
|
|
92
170
|
if (!isFrozen(array)) {
|
|
@@ -102,12 +180,12 @@ function addToSet(set, array) {
|
|
|
102
180
|
|
|
103
181
|
return set;
|
|
104
182
|
}
|
|
105
|
-
|
|
106
183
|
/* Shallow clone an object */
|
|
184
|
+
|
|
107
185
|
function clone(object) {
|
|
108
186
|
var newObject = create(null);
|
|
187
|
+
var property;
|
|
109
188
|
|
|
110
|
-
var property = void 0;
|
|
111
189
|
for (property in object) {
|
|
112
190
|
if (apply(hasOwnProperty, object, [property])) {
|
|
113
191
|
newObject[property] = object[property];
|
|
@@ -116,14 +194,15 @@ function clone(object) {
|
|
|
116
194
|
|
|
117
195
|
return newObject;
|
|
118
196
|
}
|
|
119
|
-
|
|
120
197
|
/* IE10 doesn't support __lookupGetter__ so lets'
|
|
121
198
|
* simulate it. It also automatically checks
|
|
122
199
|
* if the prop is function or getter and behaves
|
|
123
200
|
* accordingly. */
|
|
201
|
+
|
|
124
202
|
function lookupGetter(object, prop) {
|
|
125
203
|
while (object !== null) {
|
|
126
204
|
var desc = getOwnPropertyDescriptor(object, prop);
|
|
205
|
+
|
|
127
206
|
if (desc) {
|
|
128
207
|
if (desc.get) {
|
|
129
208
|
return unapply(desc.get);
|
|
@@ -145,40 +224,33 @@ function lookupGetter(object, prop) {
|
|
|
145
224
|
return fallbackValue;
|
|
146
225
|
}
|
|
147
226
|
|
|
148
|
-
var html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
|
|
149
|
-
|
|
150
|
-
// SVG
|
|
151
|
-
var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
|
|
152
|
-
|
|
153
|
-
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
227
|
+
var html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']); // SVG
|
|
154
228
|
|
|
155
|
-
|
|
229
|
+
var svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
|
|
230
|
+
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']); // List of SVG elements that are disallowed by default.
|
|
156
231
|
// We still need to know them so that we can do namespace
|
|
157
232
|
// checks properly in case one wants to add them to
|
|
158
233
|
// allow-list.
|
|
159
|
-
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
|
|
160
|
-
|
|
161
|
-
var mathMl = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
|
|
162
234
|
|
|
163
|
-
|
|
235
|
+
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
|
|
236
|
+
var mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']); // Similarly to SVG, we want to know all MathML elements,
|
|
164
237
|
// even those that we disallow by default.
|
|
165
|
-
var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
166
238
|
|
|
239
|
+
var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
167
240
|
var text = freeze(['#text']);
|
|
168
241
|
|
|
169
|
-
var html
|
|
170
|
-
|
|
171
|
-
var
|
|
172
|
-
|
|
173
|
-
var mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
174
|
-
|
|
242
|
+
var html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns', 'slot']);
|
|
243
|
+
var svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
244
|
+
var mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
175
245
|
var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
176
246
|
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
var ERB_EXPR = seal(/<%[\
|
|
247
|
+
var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
248
|
+
|
|
249
|
+
var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
|
|
180
250
|
var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
|
|
251
|
+
|
|
181
252
|
var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
253
|
+
|
|
182
254
|
var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
|
|
183
255
|
);
|
|
184
256
|
var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
@@ -186,14 +258,9 @@ var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\
|
|
|
186
258
|
);
|
|
187
259
|
var DOCTYPE_NAME = seal(/^html$/i);
|
|
188
260
|
|
|
189
|
-
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
190
|
-
|
|
191
|
-
function _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
192
|
-
|
|
193
261
|
var getGlobal = function getGlobal() {
|
|
194
262
|
return typeof window === 'undefined' ? null : window;
|
|
195
263
|
};
|
|
196
|
-
|
|
197
264
|
/**
|
|
198
265
|
* Creates a no-op policy for internal use only.
|
|
199
266
|
* Don't export this function outside this module!
|
|
@@ -202,16 +269,19 @@ var getGlobal = function getGlobal() {
|
|
|
202
269
|
* @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
|
|
203
270
|
* are not supported).
|
|
204
271
|
*/
|
|
272
|
+
|
|
273
|
+
|
|
205
274
|
var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
|
|
206
|
-
if (
|
|
275
|
+
if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
|
|
207
276
|
return null;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Allow the callers to control the unique policy name
|
|
277
|
+
} // Allow the callers to control the unique policy name
|
|
211
278
|
// by adding a data-tt-policy-suffix to the script element with the DOMPurify.
|
|
212
279
|
// Policy creation with duplicate names throws in Trusted Types.
|
|
280
|
+
|
|
281
|
+
|
|
213
282
|
var suffix = null;
|
|
214
283
|
var ATTR_NAME = 'data-tt-policy-suffix';
|
|
284
|
+
|
|
215
285
|
if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
|
|
216
286
|
suffix = document.currentScript.getAttribute(ATTR_NAME);
|
|
217
287
|
}
|
|
@@ -220,8 +290,8 @@ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes,
|
|
|
220
290
|
|
|
221
291
|
try {
|
|
222
292
|
return trustedTypes.createPolicy(policyName, {
|
|
223
|
-
createHTML: function createHTML(html
|
|
224
|
-
return html
|
|
293
|
+
createHTML: function createHTML(html) {
|
|
294
|
+
return html;
|
|
225
295
|
}
|
|
226
296
|
});
|
|
227
297
|
} catch (_) {
|
|
@@ -239,29 +309,28 @@ function createDOMPurify() {
|
|
|
239
309
|
var DOMPurify = function DOMPurify(root) {
|
|
240
310
|
return createDOMPurify(root);
|
|
241
311
|
};
|
|
242
|
-
|
|
243
312
|
/**
|
|
244
313
|
* Version label, exposed for easier checks
|
|
245
314
|
* if DOMPurify is up to date or not
|
|
246
315
|
*/
|
|
247
|
-
DOMPurify.version = '2.3.6';
|
|
248
316
|
|
|
317
|
+
|
|
318
|
+
DOMPurify.version = '2.3.7';
|
|
249
319
|
/**
|
|
250
320
|
* Array of elements that DOMPurify removed during sanitation.
|
|
251
321
|
* Empty if nothing was removed.
|
|
252
322
|
*/
|
|
323
|
+
|
|
253
324
|
DOMPurify.removed = [];
|
|
254
325
|
|
|
255
326
|
if (!window || !window.document || window.document.nodeType !== 9) {
|
|
256
327
|
// Not running in a browser, provide a factory function
|
|
257
328
|
// so that you can pass your own Window
|
|
258
329
|
DOMPurify.isSupported = false;
|
|
259
|
-
|
|
260
330
|
return DOMPurify;
|
|
261
331
|
}
|
|
262
332
|
|
|
263
333
|
var originalDocument = window.document;
|
|
264
|
-
|
|
265
334
|
var document = window.document;
|
|
266
335
|
var DocumentFragment = window.DocumentFragment,
|
|
267
336
|
HTMLTemplateElement = window.HTMLTemplateElement,
|
|
@@ -269,63 +338,57 @@ function createDOMPurify() {
|
|
|
269
338
|
Element = window.Element,
|
|
270
339
|
NodeFilter = window.NodeFilter,
|
|
271
340
|
_window$NamedNodeMap = window.NamedNodeMap,
|
|
272
|
-
NamedNodeMap = _window$NamedNodeMap ===
|
|
341
|
+
NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
273
342
|
HTMLFormElement = window.HTMLFormElement,
|
|
274
343
|
DOMParser = window.DOMParser,
|
|
275
344
|
trustedTypes = window.trustedTypes;
|
|
276
|
-
|
|
277
|
-
|
|
278
345
|
var ElementPrototype = Element.prototype;
|
|
279
|
-
|
|
280
346
|
var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
281
347
|
var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
282
348
|
var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
283
|
-
var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
284
|
-
|
|
285
|
-
// As per issue #47, the web-components registry is inherited by a
|
|
349
|
+
var getParentNode = lookupGetter(ElementPrototype, 'parentNode'); // As per issue #47, the web-components registry is inherited by a
|
|
286
350
|
// new document created via createHTMLDocument. As per the spec
|
|
287
351
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
288
352
|
// a new empty registry is used when creating a template contents owner
|
|
289
353
|
// document, so we use that as our parent document to ensure nothing
|
|
290
354
|
// is inherited.
|
|
355
|
+
|
|
291
356
|
if (typeof HTMLTemplateElement === 'function') {
|
|
292
357
|
var template = document.createElement('template');
|
|
358
|
+
|
|
293
359
|
if (template.content && template.content.ownerDocument) {
|
|
294
360
|
document = template.content.ownerDocument;
|
|
295
361
|
}
|
|
296
362
|
}
|
|
297
363
|
|
|
298
364
|
var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
|
|
299
|
-
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
300
365
|
|
|
366
|
+
var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
|
|
301
367
|
var _document = document,
|
|
302
368
|
implementation = _document.implementation,
|
|
303
369
|
createNodeIterator = _document.createNodeIterator,
|
|
304
370
|
createDocumentFragment = _document.createDocumentFragment,
|
|
305
371
|
getElementsByTagName = _document.getElementsByTagName;
|
|
306
372
|
var importNode = originalDocument.importNode;
|
|
307
|
-
|
|
308
|
-
|
|
309
373
|
var documentMode = {};
|
|
374
|
+
|
|
310
375
|
try {
|
|
311
376
|
documentMode = clone(document).documentMode ? document.documentMode : {};
|
|
312
377
|
} catch (_) {}
|
|
313
378
|
|
|
314
379
|
var hooks = {};
|
|
315
|
-
|
|
316
380
|
/**
|
|
317
381
|
* Expose whether this browser supports running the full DOMPurify.
|
|
318
382
|
*/
|
|
319
|
-
DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
320
|
-
|
|
321
|
-
var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
|
|
322
|
-
ERB_EXPR$$1 = ERB_EXPR,
|
|
323
|
-
DATA_ATTR$$1 = DATA_ATTR,
|
|
324
|
-
ARIA_ATTR$$1 = ARIA_ATTR,
|
|
325
|
-
IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,
|
|
326
|
-
ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;
|
|
327
|
-
var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;
|
|
328
383
|
|
|
384
|
+
DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
385
|
+
var MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
|
|
386
|
+
ERB_EXPR$1 = ERB_EXPR,
|
|
387
|
+
DATA_ATTR$1 = DATA_ATTR,
|
|
388
|
+
ARIA_ATTR$1 = ARIA_ATTR,
|
|
389
|
+
IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
|
|
390
|
+
ATTR_WHITESPACE$1 = ATTR_WHITESPACE;
|
|
391
|
+
var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
|
|
329
392
|
/**
|
|
330
393
|
* We consider the elements and attributes below to be safe. Ideally
|
|
331
394
|
* don't add any new ones but feel free to remove unwanted ones.
|
|
@@ -334,18 +397,18 @@ function createDOMPurify() {
|
|
|
334
397
|
/* allowed element names */
|
|
335
398
|
|
|
336
399
|
var ALLOWED_TAGS = null;
|
|
337
|
-
var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1
|
|
338
|
-
|
|
400
|
+
var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
|
|
339
401
|
/* Allowed attribute names */
|
|
340
|
-
var ALLOWED_ATTR = null;
|
|
341
|
-
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));
|
|
342
402
|
|
|
403
|
+
var ALLOWED_ATTR = null;
|
|
404
|
+
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
|
|
343
405
|
/*
|
|
344
406
|
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
345
407
|
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
346
408
|
* @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
|
|
347
409
|
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
348
410
|
*/
|
|
411
|
+
|
|
349
412
|
var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
350
413
|
tagNameCheck: {
|
|
351
414
|
writable: true,
|
|
@@ -366,93 +429,93 @@ function createDOMPurify() {
|
|
|
366
429
|
value: false
|
|
367
430
|
}
|
|
368
431
|
}));
|
|
369
|
-
|
|
370
432
|
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
371
|
-
var FORBID_TAGS = null;
|
|
372
433
|
|
|
434
|
+
var FORBID_TAGS = null;
|
|
373
435
|
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
374
|
-
var FORBID_ATTR = null;
|
|
375
436
|
|
|
437
|
+
var FORBID_ATTR = null;
|
|
376
438
|
/* Decide if ARIA attributes are okay */
|
|
377
|
-
var ALLOW_ARIA_ATTR = true;
|
|
378
439
|
|
|
440
|
+
var ALLOW_ARIA_ATTR = true;
|
|
379
441
|
/* Decide if custom data attributes are okay */
|
|
380
|
-
var ALLOW_DATA_ATTR = true;
|
|
381
442
|
|
|
443
|
+
var ALLOW_DATA_ATTR = true;
|
|
382
444
|
/* Decide if unknown protocols are okay */
|
|
383
|
-
var ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
384
445
|
|
|
446
|
+
var ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
385
447
|
/* Output should be safe for common template engines.
|
|
386
448
|
* This means, DOMPurify removes data attributes, mustaches and ERB
|
|
387
449
|
*/
|
|
388
|
-
var SAFE_FOR_TEMPLATES = false;
|
|
389
450
|
|
|
451
|
+
var SAFE_FOR_TEMPLATES = false;
|
|
390
452
|
/* Decide if document with <html>... should be returned */
|
|
391
|
-
var WHOLE_DOCUMENT = false;
|
|
392
453
|
|
|
454
|
+
var WHOLE_DOCUMENT = false;
|
|
393
455
|
/* Track whether config is already set on this instance of DOMPurify. */
|
|
394
|
-
var SET_CONFIG = false;
|
|
395
456
|
|
|
457
|
+
var SET_CONFIG = false;
|
|
396
458
|
/* Decide if all elements (e.g. style, script) must be children of
|
|
397
459
|
* document.body. By default, browsers might move them to document.head */
|
|
398
|
-
var FORCE_BODY = false;
|
|
399
460
|
|
|
461
|
+
var FORCE_BODY = false;
|
|
400
462
|
/* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
|
|
401
463
|
* string (or a TrustedHTML object if Trusted Types are supported).
|
|
402
464
|
* If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
|
|
403
465
|
*/
|
|
404
|
-
var RETURN_DOM = false;
|
|
405
466
|
|
|
467
|
+
var RETURN_DOM = false;
|
|
406
468
|
/* Decide if a DOM `DocumentFragment` should be returned, instead of a html
|
|
407
469
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
408
|
-
var RETURN_DOM_FRAGMENT = false;
|
|
409
470
|
|
|
471
|
+
var RETURN_DOM_FRAGMENT = false;
|
|
410
472
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
411
473
|
* case Trusted Types are not supported */
|
|
412
|
-
var RETURN_TRUSTED_TYPE = false;
|
|
413
474
|
|
|
475
|
+
var RETURN_TRUSTED_TYPE = false;
|
|
414
476
|
/* Output should be free from DOM clobbering attacks? */
|
|
415
|
-
var SANITIZE_DOM = true;
|
|
416
477
|
|
|
478
|
+
var SANITIZE_DOM = true;
|
|
417
479
|
/* Keep element content when removing element? */
|
|
418
|
-
var KEEP_CONTENT = true;
|
|
419
480
|
|
|
481
|
+
var KEEP_CONTENT = true;
|
|
420
482
|
/* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
|
|
421
483
|
* of importing it into a new Document and returning a sanitized copy */
|
|
422
|
-
var IN_PLACE = false;
|
|
423
484
|
|
|
485
|
+
var IN_PLACE = false;
|
|
424
486
|
/* Allow usage of profiles like html, svg and mathMl */
|
|
425
|
-
var USE_PROFILES = {};
|
|
426
487
|
|
|
488
|
+
var USE_PROFILES = {};
|
|
427
489
|
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
490
|
+
|
|
428
491
|
var FORBID_CONTENTS = null;
|
|
429
492
|
var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
430
|
-
|
|
431
493
|
/* Tags that are safe for data: URIs */
|
|
494
|
+
|
|
432
495
|
var DATA_URI_TAGS = null;
|
|
433
496
|
var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
|
|
434
|
-
|
|
435
497
|
/* Attributes safe for values like "javascript:" */
|
|
498
|
+
|
|
436
499
|
var URI_SAFE_ATTRIBUTES = null;
|
|
437
500
|
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
438
|
-
|
|
439
501
|
var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
440
502
|
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
441
503
|
var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
442
504
|
/* Document namespace */
|
|
505
|
+
|
|
443
506
|
var NAMESPACE = HTML_NAMESPACE;
|
|
444
507
|
var IS_EMPTY_INPUT = false;
|
|
445
|
-
|
|
446
508
|
/* Parsing of strict XHTML documents */
|
|
447
|
-
|
|
509
|
+
|
|
510
|
+
var PARSER_MEDIA_TYPE;
|
|
448
511
|
var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
449
512
|
var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
450
|
-
var transformCaseFunc
|
|
451
|
-
|
|
513
|
+
var transformCaseFunc;
|
|
452
514
|
/* Keep a reference to config to pass to hooks */
|
|
453
|
-
var CONFIG = null;
|
|
454
515
|
|
|
516
|
+
var CONFIG = null;
|
|
455
517
|
/* Ideally, do not touch anything below this line */
|
|
518
|
+
|
|
456
519
|
/* ______________________________________________ */
|
|
457
520
|
|
|
458
521
|
var formElement = document.createElement('form');
|
|
@@ -460,27 +523,30 @@ function createDOMPurify() {
|
|
|
460
523
|
var isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
461
524
|
return testValue instanceof RegExp || testValue instanceof Function;
|
|
462
525
|
};
|
|
463
|
-
|
|
464
526
|
/**
|
|
465
527
|
* _parseConfig
|
|
466
528
|
*
|
|
467
529
|
* @param {Object} cfg optional config literal
|
|
468
530
|
*/
|
|
469
531
|
// eslint-disable-next-line complexity
|
|
532
|
+
|
|
533
|
+
|
|
470
534
|
var _parseConfig = function _parseConfig(cfg) {
|
|
471
535
|
if (CONFIG && CONFIG === cfg) {
|
|
472
536
|
return;
|
|
473
537
|
}
|
|
474
|
-
|
|
475
538
|
/* Shield configuration object from tampering */
|
|
476
|
-
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
if (!cfg || _typeof(cfg) !== 'object') {
|
|
477
542
|
cfg = {};
|
|
478
543
|
}
|
|
479
|
-
|
|
480
544
|
/* Shield configuration object from prototype pollution */
|
|
481
|
-
cfg = clone(cfg);
|
|
482
545
|
|
|
546
|
+
|
|
547
|
+
cfg = clone(cfg);
|
|
483
548
|
/* Set configuration parameters */
|
|
549
|
+
|
|
484
550
|
ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
|
|
485
551
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
|
|
486
552
|
URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
@@ -490,19 +556,32 @@ function createDOMPurify() {
|
|
|
490
556
|
FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
|
|
491
557
|
USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
|
|
492
558
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
559
|
+
|
|
493
560
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
561
|
+
|
|
494
562
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
563
|
+
|
|
495
564
|
SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
|
|
565
|
+
|
|
496
566
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
567
|
+
|
|
497
568
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
569
|
+
|
|
498
570
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
571
|
+
|
|
499
572
|
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
|
|
573
|
+
|
|
500
574
|
FORCE_BODY = cfg.FORCE_BODY || false; // Default false
|
|
575
|
+
|
|
501
576
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
577
|
+
|
|
502
578
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
579
|
+
|
|
503
580
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
504
|
-
|
|
581
|
+
|
|
582
|
+
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
|
|
505
583
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
584
|
+
|
|
506
585
|
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
507
586
|
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
508
587
|
}
|
|
@@ -515,11 +594,9 @@ function createDOMPurify() {
|
|
|
515
594
|
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
|
|
516
595
|
}
|
|
517
596
|
|
|
518
|
-
PARSER_MEDIA_TYPE =
|
|
519
|
-
//
|
|
520
|
-
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
597
|
+
PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
|
|
598
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE; // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
521
599
|
|
|
522
|
-
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
523
600
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
|
|
524
601
|
return x;
|
|
525
602
|
} : stringToLowerCase;
|
|
@@ -531,36 +608,39 @@ function createDOMPurify() {
|
|
|
531
608
|
if (RETURN_DOM_FRAGMENT) {
|
|
532
609
|
RETURN_DOM = true;
|
|
533
610
|
}
|
|
534
|
-
|
|
535
611
|
/* Parse profile info */
|
|
612
|
+
|
|
613
|
+
|
|
536
614
|
if (USE_PROFILES) {
|
|
537
|
-
ALLOWED_TAGS = addToSet({},
|
|
615
|
+
ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
|
|
538
616
|
ALLOWED_ATTR = [];
|
|
617
|
+
|
|
539
618
|
if (USE_PROFILES.html === true) {
|
|
540
|
-
addToSet(ALLOWED_TAGS, html);
|
|
541
|
-
addToSet(ALLOWED_ATTR, html
|
|
619
|
+
addToSet(ALLOWED_TAGS, html$1);
|
|
620
|
+
addToSet(ALLOWED_ATTR, html);
|
|
542
621
|
}
|
|
543
622
|
|
|
544
623
|
if (USE_PROFILES.svg === true) {
|
|
545
|
-
addToSet(ALLOWED_TAGS, svg);
|
|
546
|
-
addToSet(ALLOWED_ATTR, svg
|
|
624
|
+
addToSet(ALLOWED_TAGS, svg$1);
|
|
625
|
+
addToSet(ALLOWED_ATTR, svg);
|
|
547
626
|
addToSet(ALLOWED_ATTR, xml);
|
|
548
627
|
}
|
|
549
628
|
|
|
550
629
|
if (USE_PROFILES.svgFilters === true) {
|
|
551
630
|
addToSet(ALLOWED_TAGS, svgFilters);
|
|
552
|
-
addToSet(ALLOWED_ATTR, svg
|
|
631
|
+
addToSet(ALLOWED_ATTR, svg);
|
|
553
632
|
addToSet(ALLOWED_ATTR, xml);
|
|
554
633
|
}
|
|
555
634
|
|
|
556
635
|
if (USE_PROFILES.mathMl === true) {
|
|
557
|
-
addToSet(ALLOWED_TAGS, mathMl);
|
|
558
|
-
addToSet(ALLOWED_ATTR, mathMl
|
|
636
|
+
addToSet(ALLOWED_TAGS, mathMl$1);
|
|
637
|
+
addToSet(ALLOWED_ATTR, mathMl);
|
|
559
638
|
addToSet(ALLOWED_ATTR, xml);
|
|
560
639
|
}
|
|
561
640
|
}
|
|
562
|
-
|
|
563
641
|
/* Merge configuration parameters */
|
|
642
|
+
|
|
643
|
+
|
|
564
644
|
if (cfg.ADD_TAGS) {
|
|
565
645
|
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
566
646
|
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
@@ -588,25 +668,28 @@ function createDOMPurify() {
|
|
|
588
668
|
|
|
589
669
|
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
|
|
590
670
|
}
|
|
591
|
-
|
|
592
671
|
/* Add #text in case KEEP_CONTENT is set to true */
|
|
672
|
+
|
|
673
|
+
|
|
593
674
|
if (KEEP_CONTENT) {
|
|
594
675
|
ALLOWED_TAGS['#text'] = true;
|
|
595
676
|
}
|
|
596
|
-
|
|
597
677
|
/* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
|
|
678
|
+
|
|
679
|
+
|
|
598
680
|
if (WHOLE_DOCUMENT) {
|
|
599
681
|
addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
|
|
600
682
|
}
|
|
601
|
-
|
|
602
683
|
/* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
|
|
684
|
+
|
|
685
|
+
|
|
603
686
|
if (ALLOWED_TAGS.table) {
|
|
604
687
|
addToSet(ALLOWED_TAGS, ['tbody']);
|
|
605
688
|
delete FORBID_TAGS.tbody;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// Prevent further manipulation of configuration.
|
|
689
|
+
} // Prevent further manipulation of configuration.
|
|
609
690
|
// Not available in IE8, Safari 5, etc.
|
|
691
|
+
|
|
692
|
+
|
|
610
693
|
if (freeze) {
|
|
611
694
|
freeze(cfg);
|
|
612
695
|
}
|
|
@@ -615,19 +698,21 @@ function createDOMPurify() {
|
|
|
615
698
|
};
|
|
616
699
|
|
|
617
700
|
var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
701
|
+
var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']); // Certain elements are allowed in both SVG and HTML
|
|
702
|
+
// namespace. We need to specify them explicitly
|
|
703
|
+
// so that they don't get erroneously deleted from
|
|
704
|
+
// HTML namespace.
|
|
618
705
|
|
|
619
|
-
var
|
|
620
|
-
|
|
706
|
+
var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
621
707
|
/* Keep track of all possible SVG and MathML tags
|
|
622
708
|
* so that we can perform the namespace checks
|
|
623
709
|
* correctly. */
|
|
624
|
-
|
|
710
|
+
|
|
711
|
+
var ALL_SVG_TAGS = addToSet({}, svg$1);
|
|
625
712
|
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
626
713
|
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
627
|
-
|
|
628
|
-
var ALL_MATHML_TAGS = addToSet({}, mathMl);
|
|
714
|
+
var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
|
|
629
715
|
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
630
|
-
|
|
631
716
|
/**
|
|
632
717
|
*
|
|
633
718
|
*
|
|
@@ -636,11 +721,11 @@ function createDOMPurify() {
|
|
|
636
721
|
* namespace that a spec-compliant parser would never
|
|
637
722
|
* return. Return true otherwise.
|
|
638
723
|
*/
|
|
639
|
-
var _checkValidNamespace = function _checkValidNamespace(element) {
|
|
640
|
-
var parent = getParentNode(element);
|
|
641
724
|
|
|
642
|
-
|
|
725
|
+
var _checkValidNamespace = function _checkValidNamespace(element) {
|
|
726
|
+
var parent = getParentNode(element); // In JSDOM, if we're inside shadow DOM, then parentNode
|
|
643
727
|
// can be null. We just simulate parent in this case.
|
|
728
|
+
|
|
644
729
|
if (!parent || !parent.tagName) {
|
|
645
730
|
parent = {
|
|
646
731
|
namespaceURI: HTML_NAMESPACE,
|
|
@@ -657,17 +742,17 @@ function createDOMPurify() {
|
|
|
657
742
|
// it should be killed.
|
|
658
743
|
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
659
744
|
return tagName === 'svg';
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
// The only way to switch from MathML to SVG is via
|
|
745
|
+
} // The only way to switch from MathML to SVG is via
|
|
663
746
|
// svg if parent is either <annotation-xml> or MathML
|
|
664
747
|
// text integration points.
|
|
748
|
+
|
|
749
|
+
|
|
665
750
|
if (parent.namespaceURI === MATHML_NAMESPACE) {
|
|
666
751
|
return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
// We only allow elements that are defined in SVG
|
|
752
|
+
} // We only allow elements that are defined in SVG
|
|
670
753
|
// spec. All others are disallowed in SVG namespace.
|
|
754
|
+
|
|
755
|
+
|
|
671
756
|
return Boolean(ALL_SVG_TAGS[tagName]);
|
|
672
757
|
}
|
|
673
758
|
|
|
@@ -677,16 +762,16 @@ function createDOMPurify() {
|
|
|
677
762
|
// it should be killed.
|
|
678
763
|
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
679
764
|
return tagName === 'math';
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// The only way to switch from SVG to MathML is via
|
|
765
|
+
} // The only way to switch from SVG to MathML is via
|
|
683
766
|
// <math> and HTML integration points
|
|
767
|
+
|
|
768
|
+
|
|
684
769
|
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
685
770
|
return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// We only allow elements that are defined in MathML
|
|
771
|
+
} // We only allow elements that are defined in MathML
|
|
689
772
|
// spec. All others are disallowed in MathML namespace.
|
|
773
|
+
|
|
774
|
+
|
|
690
775
|
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
691
776
|
}
|
|
692
777
|
|
|
@@ -700,32 +785,30 @@ function createDOMPurify() {
|
|
|
700
785
|
|
|
701
786
|
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
|
|
702
787
|
return false;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// Certain elements are allowed in both SVG and HTML
|
|
706
|
-
// namespace. We need to specify them explicitly
|
|
707
|
-
// so that they don't get erronously deleted from
|
|
708
|
-
// HTML namespace.
|
|
709
|
-
var commonSvgAndHTMLElements = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
710
|
-
|
|
711
|
-
// We disallow tags that are specific for MathML
|
|
788
|
+
} // We disallow tags that are specific for MathML
|
|
712
789
|
// or SVG and should never appear in HTML namespace
|
|
713
|
-
return !ALL_MATHML_TAGS[tagName] && (commonSvgAndHTMLElements[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
714
|
-
}
|
|
715
790
|
|
|
716
|
-
|
|
791
|
+
|
|
792
|
+
return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
793
|
+
} // The code should never reach this place (this means
|
|
717
794
|
// that the element somehow got namespace that is not
|
|
718
795
|
// HTML, SVG or MathML). Return false just in case.
|
|
796
|
+
|
|
797
|
+
|
|
719
798
|
return false;
|
|
720
799
|
};
|
|
721
|
-
|
|
722
800
|
/**
|
|
723
801
|
* _forceRemove
|
|
724
802
|
*
|
|
725
803
|
* @param {Node} node a DOM node
|
|
726
804
|
*/
|
|
805
|
+
|
|
806
|
+
|
|
727
807
|
var _forceRemove = function _forceRemove(node) {
|
|
728
|
-
arrayPush(DOMPurify.removed, {
|
|
808
|
+
arrayPush(DOMPurify.removed, {
|
|
809
|
+
element: node
|
|
810
|
+
});
|
|
811
|
+
|
|
729
812
|
try {
|
|
730
813
|
// eslint-disable-next-line unicorn/prefer-dom-node-remove
|
|
731
814
|
node.parentNode.removeChild(node);
|
|
@@ -737,13 +820,14 @@ function createDOMPurify() {
|
|
|
737
820
|
}
|
|
738
821
|
}
|
|
739
822
|
};
|
|
740
|
-
|
|
741
823
|
/**
|
|
742
824
|
* _removeAttribute
|
|
743
825
|
*
|
|
744
826
|
* @param {String} name an Attribute name
|
|
745
827
|
* @param {Node} node a DOM node
|
|
746
828
|
*/
|
|
829
|
+
|
|
830
|
+
|
|
747
831
|
var _removeAttribute = function _removeAttribute(name, node) {
|
|
748
832
|
try {
|
|
749
833
|
arrayPush(DOMPurify.removed, {
|
|
@@ -757,9 +841,8 @@ function createDOMPurify() {
|
|
|
757
841
|
});
|
|
758
842
|
}
|
|
759
843
|
|
|
760
|
-
node.removeAttribute(name);
|
|
844
|
+
node.removeAttribute(name); // We void attribute values for unremovable "is"" attributes
|
|
761
845
|
|
|
762
|
-
// We void attribute values for unremovable "is"" attributes
|
|
763
846
|
if (name === 'is' && !ALLOWED_ATTR[name]) {
|
|
764
847
|
if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
|
|
765
848
|
try {
|
|
@@ -772,17 +855,18 @@ function createDOMPurify() {
|
|
|
772
855
|
}
|
|
773
856
|
}
|
|
774
857
|
};
|
|
775
|
-
|
|
776
858
|
/**
|
|
777
859
|
* _initDocument
|
|
778
860
|
*
|
|
779
861
|
* @param {String} dirty a string of dirty markup
|
|
780
862
|
* @return {Document} a DOM, filled with the dirty markup
|
|
781
863
|
*/
|
|
864
|
+
|
|
865
|
+
|
|
782
866
|
var _initDocument = function _initDocument(dirty) {
|
|
783
867
|
/* Create a HTML document */
|
|
784
|
-
var doc
|
|
785
|
-
var leadingWhitespace
|
|
868
|
+
var doc;
|
|
869
|
+
var leadingWhitespace;
|
|
786
870
|
|
|
787
871
|
if (FORCE_BODY) {
|
|
788
872
|
dirty = '<remove></remove>' + dirty;
|
|
@@ -802,19 +886,21 @@ function createDOMPurify() {
|
|
|
802
886
|
* Use the DOMParser API by default, fallback later if needs be
|
|
803
887
|
* DOMParser not work for svg when has multiple root element.
|
|
804
888
|
*/
|
|
889
|
+
|
|
805
890
|
if (NAMESPACE === HTML_NAMESPACE) {
|
|
806
891
|
try {
|
|
807
892
|
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
|
808
893
|
} catch (_) {}
|
|
809
894
|
}
|
|
810
|
-
|
|
811
895
|
/* Use createHTMLDocument in case DOMParser is not available */
|
|
896
|
+
|
|
897
|
+
|
|
812
898
|
if (!doc || !doc.documentElement) {
|
|
813
899
|
doc = implementation.createDocument(NAMESPACE, 'template', null);
|
|
900
|
+
|
|
814
901
|
try {
|
|
815
902
|
doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
|
|
816
|
-
} catch (_) {
|
|
817
|
-
// Syntax error if dirtyPayload is invalid xml
|
|
903
|
+
} catch (_) {// Syntax error if dirtyPayload is invalid xml
|
|
818
904
|
}
|
|
819
905
|
}
|
|
820
906
|
|
|
@@ -823,47 +909,49 @@ function createDOMPurify() {
|
|
|
823
909
|
if (dirty && leadingWhitespace) {
|
|
824
910
|
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
825
911
|
}
|
|
826
|
-
|
|
827
912
|
/* Work on whole document or just its body */
|
|
913
|
+
|
|
914
|
+
|
|
828
915
|
if (NAMESPACE === HTML_NAMESPACE) {
|
|
829
916
|
return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
|
|
830
917
|
}
|
|
831
918
|
|
|
832
919
|
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
833
920
|
};
|
|
834
|
-
|
|
835
921
|
/**
|
|
836
922
|
* _createIterator
|
|
837
923
|
*
|
|
838
924
|
* @param {Document} root document/fragment to create iterator for
|
|
839
925
|
* @return {Iterator} iterator instance
|
|
840
926
|
*/
|
|
927
|
+
|
|
928
|
+
|
|
841
929
|
var _createIterator = function _createIterator(root) {
|
|
842
|
-
return createNodeIterator.call(root.ownerDocument || root, root,
|
|
843
|
-
// eslint-disable-next-line no-bitwise
|
|
930
|
+
return createNodeIterator.call(root.ownerDocument || root, root, // eslint-disable-next-line no-bitwise
|
|
844
931
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
|
|
845
932
|
};
|
|
846
|
-
|
|
847
933
|
/**
|
|
848
934
|
* _isClobbered
|
|
849
935
|
*
|
|
850
936
|
* @param {Node} elm element to check for clobbering attacks
|
|
851
937
|
* @return {Boolean} true if clobbered, false if safe
|
|
852
938
|
*/
|
|
939
|
+
|
|
940
|
+
|
|
853
941
|
var _isClobbered = function _isClobbered(elm) {
|
|
854
942
|
return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function');
|
|
855
943
|
};
|
|
856
|
-
|
|
857
944
|
/**
|
|
858
945
|
* _isNode
|
|
859
946
|
*
|
|
860
947
|
* @param {Node} obj object to check whether it's a DOM node
|
|
861
948
|
* @return {Boolean} true is object is a DOM node
|
|
862
949
|
*/
|
|
950
|
+
|
|
951
|
+
|
|
863
952
|
var _isNode = function _isNode(object) {
|
|
864
|
-
return
|
|
953
|
+
return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
|
|
865
954
|
};
|
|
866
|
-
|
|
867
955
|
/**
|
|
868
956
|
* _executeHook
|
|
869
957
|
* Execute user configurable hooks
|
|
@@ -872,6 +960,8 @@ function createDOMPurify() {
|
|
|
872
960
|
* @param {Node} currentNode node to work on with the hook
|
|
873
961
|
* @param {Object} data additional hook parameters
|
|
874
962
|
*/
|
|
963
|
+
|
|
964
|
+
|
|
875
965
|
var _executeHook = function _executeHook(entryPoint, currentNode, data) {
|
|
876
966
|
if (!hooks[entryPoint]) {
|
|
877
967
|
return;
|
|
@@ -881,7 +971,6 @@ function createDOMPurify() {
|
|
|
881
971
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
882
972
|
});
|
|
883
973
|
};
|
|
884
|
-
|
|
885
974
|
/**
|
|
886
975
|
* _sanitizeElements
|
|
887
976
|
*
|
|
@@ -892,54 +981,67 @@ function createDOMPurify() {
|
|
|
892
981
|
* @param {Node} currentNode to check for permission to exist
|
|
893
982
|
* @return {Boolean} true if node was killed, false if left alive
|
|
894
983
|
*/
|
|
895
|
-
var _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
896
|
-
var content = void 0;
|
|
897
984
|
|
|
985
|
+
|
|
986
|
+
var _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
987
|
+
var content;
|
|
898
988
|
/* Execute a hook if present */
|
|
899
|
-
_executeHook('beforeSanitizeElements', currentNode, null);
|
|
900
989
|
|
|
990
|
+
_executeHook('beforeSanitizeElements', currentNode, null);
|
|
901
991
|
/* Check if element is clobbered or can clobber */
|
|
992
|
+
|
|
993
|
+
|
|
902
994
|
if (_isClobbered(currentNode)) {
|
|
903
995
|
_forceRemove(currentNode);
|
|
996
|
+
|
|
904
997
|
return true;
|
|
905
998
|
}
|
|
906
|
-
|
|
907
999
|
/* Check if tagname contains Unicode */
|
|
908
|
-
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
|
|
909
1003
|
_forceRemove(currentNode);
|
|
1004
|
+
|
|
910
1005
|
return true;
|
|
911
1006
|
}
|
|
912
|
-
|
|
913
1007
|
/* Now let's check the element's type and name */
|
|
914
|
-
var tagName = transformCaseFunc(currentNode.nodeName);
|
|
915
1008
|
|
|
1009
|
+
|
|
1010
|
+
var tagName = transformCaseFunc(currentNode.nodeName);
|
|
916
1011
|
/* Execute a hook if present */
|
|
1012
|
+
|
|
917
1013
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
918
1014
|
tagName: tagName,
|
|
919
1015
|
allowedTags: ALLOWED_TAGS
|
|
920
1016
|
});
|
|
921
|
-
|
|
922
1017
|
/* Detect mXSS attempts abusing namespace confusion */
|
|
923
|
-
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
|
|
924
1021
|
_forceRemove(currentNode);
|
|
1022
|
+
|
|
925
1023
|
return true;
|
|
926
1024
|
}
|
|
927
|
-
|
|
928
1025
|
/* Mitigate a problem with templates inside select */
|
|
1026
|
+
|
|
1027
|
+
|
|
929
1028
|
if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
|
|
930
1029
|
_forceRemove(currentNode);
|
|
1030
|
+
|
|
931
1031
|
return true;
|
|
932
1032
|
}
|
|
933
|
-
|
|
934
1033
|
/* Remove element if anything forbids its presence */
|
|
1034
|
+
|
|
1035
|
+
|
|
935
1036
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
936
1037
|
/* Check if we have a custom element to handle */
|
|
937
1038
|
if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
|
|
938
1039
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
939
1040
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
940
1041
|
}
|
|
941
|
-
|
|
942
1042
|
/* Keep content except for bad-listed elements */
|
|
1043
|
+
|
|
1044
|
+
|
|
943
1045
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
944
1046
|
var parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
945
1047
|
var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
@@ -954,38 +1056,46 @@ function createDOMPurify() {
|
|
|
954
1056
|
}
|
|
955
1057
|
|
|
956
1058
|
_forceRemove(currentNode);
|
|
1059
|
+
|
|
957
1060
|
return true;
|
|
958
1061
|
}
|
|
959
|
-
|
|
960
1062
|
/* Check whether element has a valid namespace */
|
|
1063
|
+
|
|
1064
|
+
|
|
961
1065
|
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
|
|
962
1066
|
_forceRemove(currentNode);
|
|
1067
|
+
|
|
963
1068
|
return true;
|
|
964
1069
|
}
|
|
965
1070
|
|
|
966
1071
|
if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
|
|
967
1072
|
_forceRemove(currentNode);
|
|
1073
|
+
|
|
968
1074
|
return true;
|
|
969
1075
|
}
|
|
970
|
-
|
|
971
1076
|
/* Sanitize element content to be template-safe */
|
|
1077
|
+
|
|
1078
|
+
|
|
972
1079
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
973
1080
|
/* Get the element's text content */
|
|
974
1081
|
content = currentNode.textContent;
|
|
975
|
-
content = stringReplace(content, MUSTACHE_EXPR
|
|
976
|
-
content = stringReplace(content, ERB_EXPR
|
|
1082
|
+
content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
|
|
1083
|
+
content = stringReplace(content, ERB_EXPR$1, ' ');
|
|
1084
|
+
|
|
977
1085
|
if (currentNode.textContent !== content) {
|
|
978
|
-
arrayPush(DOMPurify.removed, {
|
|
1086
|
+
arrayPush(DOMPurify.removed, {
|
|
1087
|
+
element: currentNode.cloneNode()
|
|
1088
|
+
});
|
|
979
1089
|
currentNode.textContent = content;
|
|
980
1090
|
}
|
|
981
1091
|
}
|
|
982
|
-
|
|
983
1092
|
/* Execute a hook if present */
|
|
1093
|
+
|
|
1094
|
+
|
|
984
1095
|
_executeHook('afterSanitizeElements', currentNode, null);
|
|
985
1096
|
|
|
986
1097
|
return false;
|
|
987
1098
|
};
|
|
988
|
-
|
|
989
1099
|
/**
|
|
990
1100
|
* _isValidAttribute
|
|
991
1101
|
*
|
|
@@ -995,45 +1105,47 @@ function createDOMPurify() {
|
|
|
995
1105
|
* @return {Boolean} Returns true if `value` is valid, otherwise false.
|
|
996
1106
|
*/
|
|
997
1107
|
// eslint-disable-next-line complexity
|
|
1108
|
+
|
|
1109
|
+
|
|
998
1110
|
var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
999
1111
|
/* Make sure attribute cannot clobber */
|
|
1000
1112
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1001
1113
|
return false;
|
|
1002
1114
|
}
|
|
1003
|
-
|
|
1004
1115
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
1005
1116
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
1006
1117
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
1007
1118
|
We don't need to check the value; it's always URI safe. */
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1119
|
+
|
|
1120
|
+
|
|
1121
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
1122
|
+
if ( // First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
1011
1123
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1012
1124
|
// and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
|
|
1013
|
-
_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||
|
|
1014
|
-
// Alternative, second condition checks if it's an `is`-attribute, AND
|
|
1125
|
+
_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || // Alternative, second condition checks if it's an `is`-attribute, AND
|
|
1015
1126
|
// the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
1016
1127
|
lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {
|
|
1017
1128
|
return false;
|
|
1018
1129
|
}
|
|
1019
1130
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
1020
|
-
|
|
1131
|
+
|
|
1132
|
+
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if (!value) ; else {
|
|
1021
1133
|
return false;
|
|
1022
1134
|
}
|
|
1023
1135
|
|
|
1024
1136
|
return true;
|
|
1025
1137
|
};
|
|
1026
|
-
|
|
1027
1138
|
/**
|
|
1028
1139
|
* _basicCustomElementCheck
|
|
1029
1140
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
1030
1141
|
* for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
|
|
1031
1142
|
* @param {string} tagName name of the tag of the node to sanitize
|
|
1032
1143
|
*/
|
|
1144
|
+
|
|
1145
|
+
|
|
1033
1146
|
var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1034
1147
|
return tagName.indexOf('-') > 0;
|
|
1035
1148
|
};
|
|
1036
|
-
|
|
1037
1149
|
/**
|
|
1038
1150
|
* _sanitizeAttributes
|
|
1039
1151
|
*
|
|
@@ -1044,16 +1156,18 @@ function createDOMPurify() {
|
|
|
1044
1156
|
*
|
|
1045
1157
|
* @param {Node} currentNode to sanitize
|
|
1046
1158
|
*/
|
|
1159
|
+
|
|
1160
|
+
|
|
1047
1161
|
var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
1048
|
-
var attr
|
|
1049
|
-
var value
|
|
1050
|
-
var lcName
|
|
1051
|
-
var l
|
|
1162
|
+
var attr;
|
|
1163
|
+
var value;
|
|
1164
|
+
var lcName;
|
|
1165
|
+
var l;
|
|
1052
1166
|
/* Execute a hook if present */
|
|
1167
|
+
|
|
1053
1168
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
|
1054
1169
|
|
|
1055
1170
|
var attributes = currentNode.attributes;
|
|
1056
|
-
|
|
1057
1171
|
/* Check if we have attributes; if not we might have a text node */
|
|
1058
1172
|
|
|
1059
1173
|
if (!attributes) {
|
|
@@ -1067,56 +1181,66 @@ function createDOMPurify() {
|
|
|
1067
1181
|
allowedAttributes: ALLOWED_ATTR
|
|
1068
1182
|
};
|
|
1069
1183
|
l = attributes.length;
|
|
1070
|
-
|
|
1071
1184
|
/* Go backwards over all attributes; safely remove bad ones */
|
|
1185
|
+
|
|
1072
1186
|
while (l--) {
|
|
1073
1187
|
attr = attributes[l];
|
|
1074
1188
|
var _attr = attr,
|
|
1075
1189
|
name = _attr.name,
|
|
1076
1190
|
namespaceURI = _attr.namespaceURI;
|
|
1077
|
-
|
|
1078
|
-
value = stringTrim(attr.value);
|
|
1191
|
+
value = name === 'value' ? attr.value : stringTrim(attr.value);
|
|
1079
1192
|
lcName = transformCaseFunc(name);
|
|
1080
|
-
|
|
1081
1193
|
/* Execute a hook if present */
|
|
1194
|
+
|
|
1082
1195
|
hookEvent.attrName = lcName;
|
|
1083
1196
|
hookEvent.attrValue = value;
|
|
1084
1197
|
hookEvent.keepAttr = true;
|
|
1085
1198
|
hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
|
|
1199
|
+
|
|
1086
1200
|
_executeHook('uponSanitizeAttribute', currentNode, hookEvent);
|
|
1201
|
+
|
|
1087
1202
|
value = hookEvent.attrValue;
|
|
1088
1203
|
/* Did the hooks approve of the attribute? */
|
|
1204
|
+
|
|
1089
1205
|
if (hookEvent.forceKeepAttr) {
|
|
1090
1206
|
continue;
|
|
1091
1207
|
}
|
|
1092
|
-
|
|
1093
1208
|
/* Remove attribute */
|
|
1094
|
-
_removeAttribute(name, currentNode);
|
|
1095
1209
|
|
|
1210
|
+
|
|
1211
|
+
_removeAttribute(name, currentNode);
|
|
1096
1212
|
/* Did the hooks approve of the attribute? */
|
|
1213
|
+
|
|
1214
|
+
|
|
1097
1215
|
if (!hookEvent.keepAttr) {
|
|
1098
1216
|
continue;
|
|
1099
1217
|
}
|
|
1100
|
-
|
|
1101
1218
|
/* Work around a security issue in jQuery 3.0 */
|
|
1219
|
+
|
|
1220
|
+
|
|
1102
1221
|
if (regExpTest(/\/>/i, value)) {
|
|
1103
1222
|
_removeAttribute(name, currentNode);
|
|
1223
|
+
|
|
1104
1224
|
continue;
|
|
1105
1225
|
}
|
|
1106
|
-
|
|
1107
1226
|
/* Sanitize attribute content to be template-safe */
|
|
1227
|
+
|
|
1228
|
+
|
|
1108
1229
|
if (SAFE_FOR_TEMPLATES) {
|
|
1109
|
-
value = stringReplace(value, MUSTACHE_EXPR
|
|
1110
|
-
value = stringReplace(value, ERB_EXPR
|
|
1230
|
+
value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
|
|
1231
|
+
value = stringReplace(value, ERB_EXPR$1, ' ');
|
|
1111
1232
|
}
|
|
1112
|
-
|
|
1113
1233
|
/* Is `value` valid for this attribute? */
|
|
1234
|
+
|
|
1235
|
+
|
|
1114
1236
|
var lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1237
|
+
|
|
1115
1238
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1116
1239
|
continue;
|
|
1117
1240
|
}
|
|
1118
|
-
|
|
1119
1241
|
/* Handle invalid data-* attribute set by try-catching it */
|
|
1242
|
+
|
|
1243
|
+
|
|
1120
1244
|
try {
|
|
1121
1245
|
if (namespaceURI) {
|
|
1122
1246
|
currentNode.setAttributeNS(namespaceURI, name, value);
|
|
@@ -1128,45 +1252,52 @@ function createDOMPurify() {
|
|
|
1128
1252
|
arrayPop(DOMPurify.removed);
|
|
1129
1253
|
} catch (_) {}
|
|
1130
1254
|
}
|
|
1131
|
-
|
|
1132
1255
|
/* Execute a hook if present */
|
|
1256
|
+
|
|
1257
|
+
|
|
1133
1258
|
_executeHook('afterSanitizeAttributes', currentNode, null);
|
|
1134
1259
|
};
|
|
1135
|
-
|
|
1136
1260
|
/**
|
|
1137
1261
|
* _sanitizeShadowDOM
|
|
1138
1262
|
*
|
|
1139
1263
|
* @param {DocumentFragment} fragment to iterate over recursively
|
|
1140
1264
|
*/
|
|
1265
|
+
|
|
1266
|
+
|
|
1141
1267
|
var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
1142
|
-
var shadowNode
|
|
1143
|
-
var shadowIterator = _createIterator(fragment);
|
|
1268
|
+
var shadowNode;
|
|
1144
1269
|
|
|
1270
|
+
var shadowIterator = _createIterator(fragment);
|
|
1145
1271
|
/* Execute a hook if present */
|
|
1272
|
+
|
|
1273
|
+
|
|
1146
1274
|
_executeHook('beforeSanitizeShadowDOM', fragment, null);
|
|
1147
1275
|
|
|
1148
1276
|
while (shadowNode = shadowIterator.nextNode()) {
|
|
1149
1277
|
/* Execute a hook if present */
|
|
1150
1278
|
_executeHook('uponSanitizeShadowNode', shadowNode, null);
|
|
1151
|
-
|
|
1152
1279
|
/* Sanitize tags and elements */
|
|
1280
|
+
|
|
1281
|
+
|
|
1153
1282
|
if (_sanitizeElements(shadowNode)) {
|
|
1154
1283
|
continue;
|
|
1155
1284
|
}
|
|
1156
|
-
|
|
1157
1285
|
/* Deep shadow DOM detected */
|
|
1286
|
+
|
|
1287
|
+
|
|
1158
1288
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
1159
1289
|
_sanitizeShadowDOM(shadowNode.content);
|
|
1160
1290
|
}
|
|
1161
|
-
|
|
1162
1291
|
/* Check attributes, sanitize if necessary */
|
|
1292
|
+
|
|
1293
|
+
|
|
1163
1294
|
_sanitizeAttributes(shadowNode);
|
|
1164
1295
|
}
|
|
1165
|
-
|
|
1166
1296
|
/* Execute a hook if present */
|
|
1297
|
+
|
|
1298
|
+
|
|
1167
1299
|
_executeHook('afterSanitizeShadowDOM', fragment, null);
|
|
1168
1300
|
};
|
|
1169
|
-
|
|
1170
1301
|
/**
|
|
1171
1302
|
* Sanitize
|
|
1172
1303
|
* Public method providing core sanitation functionality
|
|
@@ -1175,34 +1306,41 @@ function createDOMPurify() {
|
|
|
1175
1306
|
* @param {Object} configuration object
|
|
1176
1307
|
*/
|
|
1177
1308
|
// eslint-disable-next-line complexity
|
|
1309
|
+
|
|
1310
|
+
|
|
1178
1311
|
DOMPurify.sanitize = function (dirty, cfg) {
|
|
1179
|
-
var body
|
|
1180
|
-
var importedNode
|
|
1181
|
-
var currentNode
|
|
1182
|
-
var oldNode
|
|
1183
|
-
var returnNode
|
|
1312
|
+
var body;
|
|
1313
|
+
var importedNode;
|
|
1314
|
+
var currentNode;
|
|
1315
|
+
var oldNode;
|
|
1316
|
+
var returnNode;
|
|
1184
1317
|
/* Make sure we have a string to sanitize.
|
|
1185
1318
|
DO NOT return early, as this will return the wrong type if
|
|
1186
1319
|
the user has requested a DOM object rather than a string */
|
|
1320
|
+
|
|
1187
1321
|
IS_EMPTY_INPUT = !dirty;
|
|
1322
|
+
|
|
1188
1323
|
if (IS_EMPTY_INPUT) {
|
|
1189
1324
|
dirty = '<!-->';
|
|
1190
1325
|
}
|
|
1191
|
-
|
|
1192
1326
|
/* Stringify, in case dirty is an object */
|
|
1327
|
+
|
|
1328
|
+
|
|
1193
1329
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
1194
1330
|
// eslint-disable-next-line no-negated-condition
|
|
1195
1331
|
if (typeof dirty.toString !== 'function') {
|
|
1196
1332
|
throw typeErrorCreate('toString is not a function');
|
|
1197
1333
|
} else {
|
|
1198
1334
|
dirty = dirty.toString();
|
|
1335
|
+
|
|
1199
1336
|
if (typeof dirty !== 'string') {
|
|
1200
1337
|
throw typeErrorCreate('dirty is not a string, aborting');
|
|
1201
1338
|
}
|
|
1202
1339
|
}
|
|
1203
1340
|
}
|
|
1204
|
-
|
|
1205
1341
|
/* Check we can run. Otherwise fall back or ignore */
|
|
1342
|
+
|
|
1343
|
+
|
|
1206
1344
|
if (!DOMPurify.isSupported) {
|
|
1207
1345
|
if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
|
|
1208
1346
|
if (typeof dirty === 'string') {
|
|
@@ -1216,16 +1354,18 @@ function createDOMPurify() {
|
|
|
1216
1354
|
|
|
1217
1355
|
return dirty;
|
|
1218
1356
|
}
|
|
1219
|
-
|
|
1220
1357
|
/* Assign config vars */
|
|
1358
|
+
|
|
1359
|
+
|
|
1221
1360
|
if (!SET_CONFIG) {
|
|
1222
1361
|
_parseConfig(cfg);
|
|
1223
1362
|
}
|
|
1224
|
-
|
|
1225
1363
|
/* Clean up removed elements */
|
|
1226
|
-
DOMPurify.removed = [];
|
|
1227
1364
|
|
|
1365
|
+
|
|
1366
|
+
DOMPurify.removed = [];
|
|
1228
1367
|
/* Check if dirty is correctly typed for IN_PLACE */
|
|
1368
|
+
|
|
1229
1369
|
if (typeof dirty === 'string') {
|
|
1230
1370
|
IN_PLACE = false;
|
|
1231
1371
|
}
|
|
@@ -1234,6 +1374,7 @@ function createDOMPurify() {
|
|
|
1234
1374
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
1235
1375
|
if (dirty.nodeName) {
|
|
1236
1376
|
var tagName = transformCaseFunc(dirty.nodeName);
|
|
1377
|
+
|
|
1237
1378
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1238
1379
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
1239
1380
|
}
|
|
@@ -1243,6 +1384,7 @@ function createDOMPurify() {
|
|
|
1243
1384
|
elements being stripped by the parser */
|
|
1244
1385
|
body = _initDocument('<!---->');
|
|
1245
1386
|
importedNode = body.ownerDocument.importNode(dirty, true);
|
|
1387
|
+
|
|
1246
1388
|
if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
|
|
1247
1389
|
/* Node is already a body, use as is */
|
|
1248
1390
|
body = importedNode;
|
|
@@ -1254,60 +1396,67 @@ function createDOMPurify() {
|
|
|
1254
1396
|
}
|
|
1255
1397
|
} else {
|
|
1256
1398
|
/* Exit directly if we have nothing to do */
|
|
1257
|
-
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
|
|
1258
|
-
// eslint-disable-next-line unicorn/prefer-includes
|
|
1399
|
+
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
|
|
1259
1400
|
dirty.indexOf('<') === -1) {
|
|
1260
1401
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
1261
1402
|
}
|
|
1262
|
-
|
|
1263
1403
|
/* Initialize the document to work on */
|
|
1264
|
-
body = _initDocument(dirty);
|
|
1265
1404
|
|
|
1405
|
+
|
|
1406
|
+
body = _initDocument(dirty);
|
|
1266
1407
|
/* Check we have a DOM node from the data */
|
|
1408
|
+
|
|
1267
1409
|
if (!body) {
|
|
1268
1410
|
return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
|
|
1269
1411
|
}
|
|
1270
1412
|
}
|
|
1271
|
-
|
|
1272
1413
|
/* Remove first element node (ours) if FORCE_BODY is set */
|
|
1414
|
+
|
|
1415
|
+
|
|
1273
1416
|
if (body && FORCE_BODY) {
|
|
1274
1417
|
_forceRemove(body.firstChild);
|
|
1275
1418
|
}
|
|
1276
|
-
|
|
1277
1419
|
/* Get node iterator */
|
|
1278
|
-
var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
|
|
1279
1420
|
|
|
1421
|
+
|
|
1422
|
+
var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
|
|
1280
1423
|
/* Now start iterating over the created document */
|
|
1424
|
+
|
|
1425
|
+
|
|
1281
1426
|
while (currentNode = nodeIterator.nextNode()) {
|
|
1282
1427
|
/* Fix IE's strange behavior with manipulated textNodes #89 */
|
|
1283
1428
|
if (currentNode.nodeType === 3 && currentNode === oldNode) {
|
|
1284
1429
|
continue;
|
|
1285
1430
|
}
|
|
1286
|
-
|
|
1287
1431
|
/* Sanitize tags and elements */
|
|
1432
|
+
|
|
1433
|
+
|
|
1288
1434
|
if (_sanitizeElements(currentNode)) {
|
|
1289
1435
|
continue;
|
|
1290
1436
|
}
|
|
1291
|
-
|
|
1292
1437
|
/* Shadow DOM detected, sanitize it */
|
|
1438
|
+
|
|
1439
|
+
|
|
1293
1440
|
if (currentNode.content instanceof DocumentFragment) {
|
|
1294
1441
|
_sanitizeShadowDOM(currentNode.content);
|
|
1295
1442
|
}
|
|
1296
|
-
|
|
1297
1443
|
/* Check attributes, sanitize if necessary */
|
|
1444
|
+
|
|
1445
|
+
|
|
1298
1446
|
_sanitizeAttributes(currentNode);
|
|
1299
1447
|
|
|
1300
1448
|
oldNode = currentNode;
|
|
1301
1449
|
}
|
|
1302
1450
|
|
|
1303
1451
|
oldNode = null;
|
|
1304
|
-
|
|
1305
1452
|
/* If we sanitized `dirty` in-place, return it. */
|
|
1453
|
+
|
|
1306
1454
|
if (IN_PLACE) {
|
|
1307
1455
|
return dirty;
|
|
1308
1456
|
}
|
|
1309
|
-
|
|
1310
1457
|
/* Return sanitized string or DOM */
|
|
1458
|
+
|
|
1459
|
+
|
|
1311
1460
|
if (RETURN_DOM) {
|
|
1312
1461
|
if (RETURN_DOM_FRAGMENT) {
|
|
1313
1462
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
@@ -1335,42 +1484,45 @@ function createDOMPurify() {
|
|
|
1335
1484
|
}
|
|
1336
1485
|
|
|
1337
1486
|
var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1338
|
-
|
|
1339
1487
|
/* Serialize doctype if allowed */
|
|
1488
|
+
|
|
1340
1489
|
if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
1341
1490
|
serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
|
|
1342
1491
|
}
|
|
1343
|
-
|
|
1344
1492
|
/* Sanitize final string template-safe */
|
|
1493
|
+
|
|
1494
|
+
|
|
1345
1495
|
if (SAFE_FOR_TEMPLATES) {
|
|
1346
|
-
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR
|
|
1347
|
-
serializedHTML = stringReplace(serializedHTML, ERB_EXPR
|
|
1496
|
+
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
|
|
1497
|
+
serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
|
|
1348
1498
|
}
|
|
1349
1499
|
|
|
1350
1500
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
1351
1501
|
};
|
|
1352
|
-
|
|
1353
1502
|
/**
|
|
1354
1503
|
* Public method to set the configuration once
|
|
1355
1504
|
* setConfig
|
|
1356
1505
|
*
|
|
1357
1506
|
* @param {Object} cfg configuration object
|
|
1358
1507
|
*/
|
|
1508
|
+
|
|
1509
|
+
|
|
1359
1510
|
DOMPurify.setConfig = function (cfg) {
|
|
1360
1511
|
_parseConfig(cfg);
|
|
1512
|
+
|
|
1361
1513
|
SET_CONFIG = true;
|
|
1362
1514
|
};
|
|
1363
|
-
|
|
1364
1515
|
/**
|
|
1365
1516
|
* Public method to remove the configuration
|
|
1366
1517
|
* clearConfig
|
|
1367
1518
|
*
|
|
1368
1519
|
*/
|
|
1520
|
+
|
|
1521
|
+
|
|
1369
1522
|
DOMPurify.clearConfig = function () {
|
|
1370
1523
|
CONFIG = null;
|
|
1371
1524
|
SET_CONFIG = false;
|
|
1372
1525
|
};
|
|
1373
|
-
|
|
1374
1526
|
/**
|
|
1375
1527
|
* Public method to check if an attribute value is valid.
|
|
1376
1528
|
* Uses last set config, if any. Otherwise, uses config defaults.
|
|
@@ -1381,6 +1533,8 @@ function createDOMPurify() {
|
|
|
1381
1533
|
* @param {string} value Attribute value.
|
|
1382
1534
|
* @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
|
|
1383
1535
|
*/
|
|
1536
|
+
|
|
1537
|
+
|
|
1384
1538
|
DOMPurify.isValidAttribute = function (tag, attr, value) {
|
|
1385
1539
|
/* Initialize shared config vars if necessary. */
|
|
1386
1540
|
if (!CONFIG) {
|
|
@@ -1391,7 +1545,6 @@ function createDOMPurify() {
|
|
|
1391
1545
|
var lcName = transformCaseFunc(attr);
|
|
1392
1546
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1393
1547
|
};
|
|
1394
|
-
|
|
1395
1548
|
/**
|
|
1396
1549
|
* AddHook
|
|
1397
1550
|
* Public method to add DOMPurify hooks
|
|
@@ -1399,6 +1552,8 @@ function createDOMPurify() {
|
|
|
1399
1552
|
* @param {String} entryPoint entry point for the hook to add
|
|
1400
1553
|
* @param {Function} hookFunction function to execute
|
|
1401
1554
|
*/
|
|
1555
|
+
|
|
1556
|
+
|
|
1402
1557
|
DOMPurify.addHook = function (entryPoint, hookFunction) {
|
|
1403
1558
|
if (typeof hookFunction !== 'function') {
|
|
1404
1559
|
return;
|
|
@@ -1407,37 +1562,41 @@ function createDOMPurify() {
|
|
|
1407
1562
|
hooks[entryPoint] = hooks[entryPoint] || [];
|
|
1408
1563
|
arrayPush(hooks[entryPoint], hookFunction);
|
|
1409
1564
|
};
|
|
1410
|
-
|
|
1411
1565
|
/**
|
|
1412
1566
|
* RemoveHook
|
|
1413
1567
|
* Public method to remove a DOMPurify hook at a given entryPoint
|
|
1414
1568
|
* (pops it from the stack of hooks if more are present)
|
|
1415
1569
|
*
|
|
1416
1570
|
* @param {String} entryPoint entry point for the hook to remove
|
|
1571
|
+
* @return {Function} removed(popped) hook
|
|
1417
1572
|
*/
|
|
1573
|
+
|
|
1574
|
+
|
|
1418
1575
|
DOMPurify.removeHook = function (entryPoint) {
|
|
1419
1576
|
if (hooks[entryPoint]) {
|
|
1420
|
-
arrayPop(hooks[entryPoint]);
|
|
1577
|
+
return arrayPop(hooks[entryPoint]);
|
|
1421
1578
|
}
|
|
1422
1579
|
};
|
|
1423
|
-
|
|
1424
1580
|
/**
|
|
1425
1581
|
* RemoveHooks
|
|
1426
1582
|
* Public method to remove all DOMPurify hooks at a given entryPoint
|
|
1427
1583
|
*
|
|
1428
1584
|
* @param {String} entryPoint entry point for the hooks to remove
|
|
1429
1585
|
*/
|
|
1586
|
+
|
|
1587
|
+
|
|
1430
1588
|
DOMPurify.removeHooks = function (entryPoint) {
|
|
1431
1589
|
if (hooks[entryPoint]) {
|
|
1432
1590
|
hooks[entryPoint] = [];
|
|
1433
1591
|
}
|
|
1434
1592
|
};
|
|
1435
|
-
|
|
1436
1593
|
/**
|
|
1437
1594
|
* RemoveAllHooks
|
|
1438
1595
|
* Public method to remove all DOMPurify hooks
|
|
1439
1596
|
*
|
|
1440
1597
|
*/
|
|
1598
|
+
|
|
1599
|
+
|
|
1441
1600
|
DOMPurify.removeAllHooks = function () {
|
|
1442
1601
|
hooks = {};
|
|
1443
1602
|
};
|
|
@@ -1447,5 +1606,5 @@ function createDOMPurify() {
|
|
|
1447
1606
|
|
|
1448
1607
|
var purify = createDOMPurify();
|
|
1449
1608
|
|
|
1450
|
-
export default
|
|
1609
|
+
export { purify as default };
|
|
1451
1610
|
//# sourceMappingURL=purify.es.js.map
|