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