dompurify 2.4.9 → 2.5.1

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