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