dompurify 2.4.8 → 2.5.0

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.8 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.8/LICENSE */
1
+ /*! @license DOMPurify 2.5.0 | (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.0/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,25 +216,24 @@ 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);
265
228
  var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
266
229
  );
267
230
  var DOCTYPE_NAME = seal(/^html$/i);
268
- var CUSTOM_ELEMENT = seal(/^[a-z][a-z\d]*(-[a-z\d]+)+$/i);
231
+ var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
269
232
 
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.0';
328
287
 
329
-
330
- DOMPurify.version = '2.4.8';
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,98 @@ 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
+ /* Ideally, do not touch anything below this line */
559
513
  /* ______________________________________________ */
560
514
 
561
515
  var formElement = document.createElement('form');
562
-
563
516
  var isRegexOrFunction = function isRegexOrFunction(testValue) {
564
517
  return testValue instanceof RegExp || testValue instanceof Function;
565
518
  };
519
+
566
520
  /**
567
521
  * _parseConfig
568
522
  *
569
523
  * @param {Object} cfg optional config literal
570
524
  */
571
525
  // eslint-disable-next-line complexity
572
-
573
-
574
526
  var _parseConfig = function _parseConfig(cfg) {
575
527
  if (CONFIG && CONFIG === cfg) {
576
528
  return;
577
529
  }
578
- /* Shield configuration object from tampering */
579
-
580
530
 
531
+ /* Shield configuration object from tampering */
581
532
  if (!cfg || _typeof(cfg) !== 'object') {
582
533
  cfg = {};
583
534
  }
584
- /* Shield configuration object from prototype pollution */
585
-
586
535
 
536
+ /* Shield configuration object from prototype pollution */
587
537
  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.
538
+ PARSER_MEDIA_TYPE =
539
+ // eslint-disable-next-line unicorn/prefer-includes
540
+ 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
541
 
542
+ // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
591
543
  transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
592
- /* Set configuration parameters */
593
544
 
545
+ /* Set configuration parameters */
594
546
  ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
595
547
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
596
548
  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
549
+ URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES),
550
+ // eslint-disable-line indent
551
+ cfg.ADD_URI_SAFE_ATTR,
552
+ // eslint-disable-line indent
599
553
  transformCaseFunc // eslint-disable-line indent
600
554
  ) // eslint-disable-line indent
601
555
  : 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
556
+ DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS),
557
+ // eslint-disable-line indent
558
+ cfg.ADD_DATA_URI_TAGS,
559
+ // eslint-disable-line indent
604
560
  transformCaseFunc // eslint-disable-line indent
605
561
  ) // eslint-disable-line indent
606
562
  : DEFAULT_DATA_URI_TAGS;
@@ -609,161 +565,128 @@ function createDOMPurify() {
609
565
  FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
610
566
  USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
611
567
  ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
612
-
613
568
  ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
614
-
615
569
  ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
616
-
617
570
  ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true
618
-
619
571
  SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
620
-
572
+ SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true
621
573
  WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
622
-
623
574
  RETURN_DOM = cfg.RETURN_DOM || false; // Default false
624
-
625
575
  RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
626
-
627
576
  RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
628
-
629
577
  FORCE_BODY = cfg.FORCE_BODY || false; // Default false
630
-
631
578
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
632
-
633
579
  SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
634
-
635
580
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
636
-
637
581
  IN_PLACE = cfg.IN_PLACE || false; // Default false
638
-
639
582
  IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
640
583
  NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
641
584
  CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
642
-
643
585
  if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
644
586
  CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
645
587
  }
646
-
647
588
  if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
648
589
  CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
649
590
  }
650
-
651
591
  if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
652
592
  CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
653
593
  }
654
-
655
594
  if (SAFE_FOR_TEMPLATES) {
656
595
  ALLOW_DATA_ATTR = false;
657
596
  }
658
-
659
597
  if (RETURN_DOM_FRAGMENT) {
660
598
  RETURN_DOM = true;
661
599
  }
662
- /* Parse profile info */
663
-
664
600
 
601
+ /* Parse profile info */
665
602
  if (USE_PROFILES) {
666
603
  ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
667
604
  ALLOWED_ATTR = [];
668
-
669
605
  if (USE_PROFILES.html === true) {
670
606
  addToSet(ALLOWED_TAGS, html$1);
671
607
  addToSet(ALLOWED_ATTR, html);
672
608
  }
673
-
674
609
  if (USE_PROFILES.svg === true) {
675
610
  addToSet(ALLOWED_TAGS, svg$1);
676
611
  addToSet(ALLOWED_ATTR, svg);
677
612
  addToSet(ALLOWED_ATTR, xml);
678
613
  }
679
-
680
614
  if (USE_PROFILES.svgFilters === true) {
681
615
  addToSet(ALLOWED_TAGS, svgFilters);
682
616
  addToSet(ALLOWED_ATTR, svg);
683
617
  addToSet(ALLOWED_ATTR, xml);
684
618
  }
685
-
686
619
  if (USE_PROFILES.mathMl === true) {
687
620
  addToSet(ALLOWED_TAGS, mathMl$1);
688
621
  addToSet(ALLOWED_ATTR, mathMl);
689
622
  addToSet(ALLOWED_ATTR, xml);
690
623
  }
691
624
  }
692
- /* Merge configuration parameters */
693
-
694
625
 
626
+ /* Merge configuration parameters */
695
627
  if (cfg.ADD_TAGS) {
696
628
  if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
697
629
  ALLOWED_TAGS = clone(ALLOWED_TAGS);
698
630
  }
699
-
700
631
  addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
701
632
  }
702
-
703
633
  if (cfg.ADD_ATTR) {
704
634
  if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
705
635
  ALLOWED_ATTR = clone(ALLOWED_ATTR);
706
636
  }
707
-
708
637
  addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
709
638
  }
710
-
711
639
  if (cfg.ADD_URI_SAFE_ATTR) {
712
640
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
713
641
  }
714
-
715
642
  if (cfg.FORBID_CONTENTS) {
716
643
  if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
717
644
  FORBID_CONTENTS = clone(FORBID_CONTENTS);
718
645
  }
719
-
720
646
  addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
721
647
  }
722
- /* Add #text in case KEEP_CONTENT is set to true */
723
-
724
648
 
649
+ /* Add #text in case KEEP_CONTENT is set to true */
725
650
  if (KEEP_CONTENT) {
726
651
  ALLOWED_TAGS['#text'] = true;
727
652
  }
728
- /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
729
-
730
653
 
654
+ /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
731
655
  if (WHOLE_DOCUMENT) {
732
656
  addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
733
657
  }
734
- /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
735
-
736
658
 
659
+ /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
737
660
  if (ALLOWED_TAGS.table) {
738
661
  addToSet(ALLOWED_TAGS, ['tbody']);
739
662
  delete FORBID_TAGS.tbody;
740
- } // Prevent further manipulation of configuration.
741
- // Not available in IE8, Safari 5, etc.
742
-
663
+ }
743
664
 
665
+ // Prevent further manipulation of configuration.
666
+ // Not available in IE8, Safari 5, etc.
744
667
  if (freeze) {
745
668
  freeze(cfg);
746
669
  }
747
-
748
670
  CONFIG = cfg;
749
671
  };
750
-
751
672
  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
673
+ var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);
674
+
675
+ // Certain elements are allowed in both SVG and HTML
753
676
  // namespace. We need to specify them explicitly
754
677
  // so that they don't get erroneously deleted from
755
678
  // HTML namespace.
756
-
757
679
  var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
680
+
758
681
  /* Keep track of all possible SVG and MathML tags
759
682
  * so that we can perform the namespace checks
760
683
  * correctly. */
761
-
762
684
  var ALL_SVG_TAGS = addToSet({}, svg$1);
763
685
  addToSet(ALL_SVG_TAGS, svgFilters);
764
686
  addToSet(ALL_SVG_TAGS, svgDisallowed);
765
687
  var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
766
688
  addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
689
+
767
690
  /**
768
691
  *
769
692
  *
@@ -772,64 +695,59 @@ function createDOMPurify() {
772
695
  * namespace that a spec-compliant parser would never
773
696
  * return. Return true otherwise.
774
697
  */
775
-
776
698
  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.
699
+ var parent = getParentNode(element);
779
700
 
701
+ // In JSDOM, if we're inside shadow DOM, then parentNode
702
+ // can be null. We just simulate parent in this case.
780
703
  if (!parent || !parent.tagName) {
781
704
  parent = {
782
705
  namespaceURI: NAMESPACE,
783
706
  tagName: 'template'
784
707
  };
785
708
  }
786
-
787
709
  var tagName = stringToLowerCase(element.tagName);
788
710
  var parentTagName = stringToLowerCase(parent.tagName);
789
-
790
711
  if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
791
712
  return false;
792
713
  }
793
-
794
714
  if (element.namespaceURI === SVG_NAMESPACE) {
795
715
  // The only way to switch from HTML namespace to SVG
796
716
  // is via <svg>. If it happens via any other tag, then
797
717
  // it should be killed.
798
718
  if (parent.namespaceURI === HTML_NAMESPACE) {
799
719
  return tagName === 'svg';
800
- } // The only way to switch from MathML to SVG is via`
720
+ }
721
+
722
+ // The only way to switch from MathML to SVG is via`
801
723
  // svg if parent is either <annotation-xml> or MathML
802
724
  // text integration points.
803
-
804
-
805
725
  if (parent.namespaceURI === MATHML_NAMESPACE) {
806
726
  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
-
727
+ }
810
728
 
729
+ // We only allow elements that are defined in SVG
730
+ // spec. All others are disallowed in SVG namespace.
811
731
  return Boolean(ALL_SVG_TAGS[tagName]);
812
732
  }
813
-
814
733
  if (element.namespaceURI === MATHML_NAMESPACE) {
815
734
  // The only way to switch from HTML namespace to MathML
816
735
  // is via <math>. If it happens via any other tag, then
817
736
  // it should be killed.
818
737
  if (parent.namespaceURI === HTML_NAMESPACE) {
819
738
  return tagName === 'math';
820
- } // The only way to switch from SVG to MathML is via
821
- // <math> and HTML integration points
822
-
739
+ }
823
740
 
741
+ // The only way to switch from SVG to MathML is via
742
+ // <math> and HTML integration points
824
743
  if (parent.namespaceURI === SVG_NAMESPACE) {
825
744
  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
-
745
+ }
829
746
 
747
+ // We only allow elements that are defined in MathML
748
+ // spec. All others are disallowed in MathML namespace.
830
749
  return Boolean(ALL_MATHML_TAGS[tagName]);
831
750
  }
832
-
833
751
  if (element.namespaceURI === HTML_NAMESPACE) {
834
752
  // The only way to switch from SVG to HTML is via
835
753
  // HTML integration points, and from MathML to HTML
@@ -837,39 +755,36 @@ function createDOMPurify() {
837
755
  if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
838
756
  return false;
839
757
  }
840
-
841
758
  if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
842
759
  return false;
843
- } // We disallow tags that are specific for MathML
844
- // or SVG and should never appear in HTML namespace
845
-
760
+ }
846
761
 
762
+ // We disallow tags that are specific for MathML
763
+ // or SVG and should never appear in HTML namespace
847
764
  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
-
765
+ }
850
766
 
767
+ // For XHTML and XML documents that support custom namespaces
851
768
  if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
852
769
  return true;
853
- } // The code should never reach this place (this means
770
+ }
771
+
772
+ // The code should never reach this place (this means
854
773
  // that the element somehow got namespace that is not
855
774
  // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
856
775
  // Return false just in case.
857
-
858
-
859
776
  return false;
860
777
  };
778
+
861
779
  /**
862
780
  * _forceRemove
863
781
  *
864
782
  * @param {Node} node a DOM node
865
783
  */
866
-
867
-
868
784
  var _forceRemove = function _forceRemove(node) {
869
785
  arrayPush(DOMPurify.removed, {
870
786
  element: node
871
787
  });
872
-
873
788
  try {
874
789
  // eslint-disable-next-line unicorn/prefer-dom-node-remove
875
790
  node.parentNode.removeChild(node);
@@ -881,14 +796,13 @@ function createDOMPurify() {
881
796
  }
882
797
  }
883
798
  };
799
+
884
800
  /**
885
801
  * _removeAttribute
886
802
  *
887
803
  * @param {String} name an Attribute name
888
804
  * @param {Node} node a DOM node
889
805
  */
890
-
891
-
892
806
  var _removeAttribute = function _removeAttribute(name, node) {
893
807
  try {
894
808
  arrayPush(DOMPurify.removed, {
@@ -901,9 +815,9 @@ function createDOMPurify() {
901
815
  from: node
902
816
  });
903
817
  }
818
+ node.removeAttribute(name);
904
819
 
905
- node.removeAttribute(name); // We void attribute values for unremovable "is"" attributes
906
-
820
+ // We void attribute values for unremovable "is"" attributes
907
821
  if (name === 'is' && !ALLOWED_ATTR[name]) {
908
822
  if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
909
823
  try {
@@ -916,19 +830,17 @@ function createDOMPurify() {
916
830
  }
917
831
  }
918
832
  };
833
+
919
834
  /**
920
835
  * _initDocument
921
836
  *
922
837
  * @param {String} dirty a string of dirty markup
923
838
  * @return {Document} a DOM, filled with the dirty markup
924
839
  */
925
-
926
-
927
840
  var _initDocument = function _initDocument(dirty) {
928
841
  /* Create a HTML document */
929
842
  var doc;
930
843
  var leadingWhitespace;
931
-
932
844
  if (FORCE_BODY) {
933
845
  dirty = '<remove></remove>' + dirty;
934
846
  } else {
@@ -936,83 +848,74 @@ function createDOMPurify() {
936
848
  var matches = stringMatch(dirty, /^[\r\n\t ]+/);
937
849
  leadingWhitespace = matches && matches[0];
938
850
  }
939
-
940
851
  if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
941
852
  // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
942
853
  dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
943
854
  }
944
-
945
855
  var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
946
856
  /*
947
857
  * Use the DOMParser API by default, fallback later if needs be
948
858
  * DOMParser not work for svg when has multiple root element.
949
859
  */
950
-
951
860
  if (NAMESPACE === HTML_NAMESPACE) {
952
861
  try {
953
862
  doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
954
863
  } catch (_) {}
955
864
  }
956
- /* Use createHTMLDocument in case DOMParser is not available */
957
-
958
865
 
866
+ /* Use createHTMLDocument in case DOMParser is not available */
959
867
  if (!doc || !doc.documentElement) {
960
868
  doc = implementation.createDocument(NAMESPACE, 'template', null);
961
-
962
869
  try {
963
870
  doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
964
- } catch (_) {// Syntax error if dirtyPayload is invalid xml
871
+ } catch (_) {
872
+ // Syntax error if dirtyPayload is invalid xml
965
873
  }
966
874
  }
967
-
968
875
  var body = doc.body || doc.documentElement;
969
-
970
876
  if (dirty && leadingWhitespace) {
971
877
  body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
972
878
  }
973
- /* Work on whole document or just its body */
974
-
975
879
 
880
+ /* Work on whole document or just its body */
976
881
  if (NAMESPACE === HTML_NAMESPACE) {
977
882
  return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
978
883
  }
979
-
980
884
  return WHOLE_DOCUMENT ? doc.documentElement : body;
981
885
  };
886
+
982
887
  /**
983
888
  * _createIterator
984
889
  *
985
890
  * @param {Document} root document/fragment to create iterator for
986
891
  * @return {Iterator} iterator instance
987
892
  */
988
-
989
-
990
893
  var _createIterator = function _createIterator(root) {
991
- return createNodeIterator.call(root.ownerDocument || root, root, // eslint-disable-next-line no-bitwise
992
- NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null, false);
894
+ return createNodeIterator.call(root.ownerDocument || root, root,
895
+ // eslint-disable-next-line no-bitwise
896
+ NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null, false);
993
897
  };
898
+
994
899
  /**
995
900
  * _isClobbered
996
901
  *
997
902
  * @param {Node} elm element to check for clobbering attacks
998
903
  * @return {Boolean} true if clobbered, false if safe
999
904
  */
1000
-
1001
-
1002
905
  var _isClobbered = function _isClobbered(elm) {
1003
906
  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');
1004
907
  };
908
+
1005
909
  /**
1006
910
  * _isNode
1007
911
  *
1008
912
  * @param {Node} obj object to check whether it's a DOM node
1009
913
  * @return {Boolean} true is object is a DOM node
1010
914
  */
1011
-
1012
-
1013
915
  var _isNode = function _isNode(object) {
1014
916
  return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
1015
917
  };
918
+
1016
919
  /**
1017
920
  * _executeHook
1018
921
  * Execute user configurable hooks
@@ -1021,17 +924,15 @@ function createDOMPurify() {
1021
924
  * @param {Node} currentNode node to work on with the hook
1022
925
  * @param {Object} data additional hook parameters
1023
926
  */
1024
-
1025
-
1026
927
  var _executeHook = function _executeHook(entryPoint, currentNode, data) {
1027
928
  if (!hooks[entryPoint]) {
1028
929
  return;
1029
930
  }
1030
-
1031
931
  arrayForEach(hooks[entryPoint], function (hook) {
1032
932
  hook.call(DOMPurify, currentNode, data, CONFIG);
1033
933
  });
1034
934
  };
935
+
1035
936
  /**
1036
937
  * _sanitizeElements
1037
938
  *
@@ -1042,110 +943,99 @@ function createDOMPurify() {
1042
943
  * @param {Node} currentNode to check for permission to exist
1043
944
  * @return {Boolean} true if node was killed, false if left alive
1044
945
  */
1045
-
1046
-
1047
946
  var _sanitizeElements = function _sanitizeElements(currentNode) {
1048
947
  var content;
1049
- /* Execute a hook if present */
1050
948
 
949
+ /* Execute a hook if present */
1051
950
  _executeHook('beforeSanitizeElements', currentNode, null);
1052
- /* Check if element is clobbered or can clobber */
1053
-
1054
951
 
952
+ /* Check if element is clobbered or can clobber */
1055
953
  if (_isClobbered(currentNode)) {
1056
954
  _forceRemove(currentNode);
1057
-
1058
955
  return true;
1059
956
  }
1060
- /* Check if tagname contains Unicode */
1061
-
1062
957
 
958
+ /* Check if tagname contains Unicode */
1063
959
  if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
1064
960
  _forceRemove(currentNode);
1065
-
1066
961
  return true;
1067
962
  }
1068
- /* Now let's check the element's type and name */
1069
-
1070
963
 
964
+ /* Now let's check the element's type and name */
1071
965
  var tagName = transformCaseFunc(currentNode.nodeName);
1072
- /* Execute a hook if present */
1073
966
 
967
+ /* Execute a hook if present */
1074
968
  _executeHook('uponSanitizeElement', currentNode, {
1075
969
  tagName: tagName,
1076
970
  allowedTags: ALLOWED_TAGS
1077
971
  });
1078
- /* Detect mXSS attempts abusing namespace confusion */
1079
-
1080
972
 
973
+ /* Detect mXSS attempts abusing namespace confusion */
1081
974
  if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
1082
975
  _forceRemove(currentNode);
1083
-
1084
976
  return true;
1085
977
  }
1086
- /* Mitigate a problem with templates inside select */
1087
-
1088
978
 
979
+ /* Mitigate a problem with templates inside select */
1089
980
  if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
1090
981
  _forceRemove(currentNode);
982
+ return true;
983
+ }
1091
984
 
985
+ /* Remove any ocurrence of processing instructions */
986
+ if (currentNode.nodeType === 7) {
987
+ _forceRemove(currentNode);
1092
988
  return true;
1093
989
  }
1094
- /* Remove element if anything forbids its presence */
1095
990
 
991
+ /* Remove any kind of possibly harmful comments */
992
+ if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\w]/g, currentNode.data)) {
993
+ _forceRemove(currentNode);
994
+ return true;
995
+ }
1096
996
 
997
+ /* Remove element if anything forbids its presence */
1097
998
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
1098
999
  /* Check if we have a custom element to handle */
1099
1000
  if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
1100
1001
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
1101
1002
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
1102
1003
  }
1103
- /* Keep content except for bad-listed elements */
1104
-
1105
1004
 
1005
+ /* Keep content except for bad-listed elements */
1106
1006
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
1107
1007
  var parentNode = getParentNode(currentNode) || currentNode.parentNode;
1108
1008
  var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
1109
-
1110
1009
  if (childNodes && parentNode) {
1111
1010
  var childCount = childNodes.length;
1112
-
1113
1011
  for (var i = childCount - 1; i >= 0; --i) {
1114
1012
  parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
1115
1013
  }
1116
1014
  }
1117
1015
  }
1118
-
1119
1016
  _forceRemove(currentNode);
1120
-
1121
1017
  return true;
1122
1018
  }
1123
- /* Check whether element has a valid namespace */
1124
-
1125
1019
 
1020
+ /* Check whether element has a valid namespace */
1126
1021
  if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
1127
1022
  _forceRemove(currentNode);
1128
-
1129
1023
  return true;
1130
1024
  }
1131
- /* Make sure that older browsers don't get fallback-tag mXSS */
1132
-
1133
1025
 
1026
+ /* Make sure that older browsers don't get fallback-tag mXSS */
1134
1027
  if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
1135
1028
  _forceRemove(currentNode);
1136
-
1137
1029
  return true;
1138
1030
  }
1139
- /* Sanitize element content to be template-safe */
1140
-
1141
1031
 
1032
+ /* Sanitize element content to be template-safe */
1142
1033
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
1143
1034
  /* Get the element's text content */
1144
1035
  content = currentNode.textContent;
1145
1036
  content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
1146
1037
  content = stringReplace(content, ERB_EXPR$1, ' ');
1147
1038
  content = stringReplace(content, TMPLIT_EXPR$1, ' ');
1148
-
1149
1039
  if (currentNode.textContent !== content) {
1150
1040
  arrayPush(DOMPurify.removed, {
1151
1041
  element: currentNode.cloneNode()
@@ -1153,13 +1043,12 @@ function createDOMPurify() {
1153
1043
  currentNode.textContent = content;
1154
1044
  }
1155
1045
  }
1156
- /* Execute a hook if present */
1157
-
1158
1046
 
1047
+ /* Execute a hook if present */
1159
1048
  _executeHook('afterSanitizeElements', currentNode, null);
1160
-
1161
1049
  return false;
1162
1050
  };
1051
+
1163
1052
  /**
1164
1053
  * _isValidAttribute
1165
1054
  *
@@ -1169,47 +1058,44 @@ function createDOMPurify() {
1169
1058
  * @return {Boolean} Returns true if `value` is valid, otherwise false.
1170
1059
  */
1171
1060
  // eslint-disable-next-line complexity
1172
-
1173
-
1174
1061
  var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1175
1062
  /* Make sure attribute cannot clobber */
1176
1063
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1177
1064
  return false;
1178
1065
  }
1066
+
1179
1067
  /* Allow valid data-* attributes: At least one character after "-"
1180
1068
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1181
1069
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1182
1070
  We don't need to check the value; it's always URI safe. */
1183
-
1184
-
1185
1071
  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]) {
1186
- if ( // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1072
+ if (
1073
+ // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1187
1074
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1188
1075
  // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
1189
- _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
1076
+ _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)) ||
1077
+ // Alternative, second condition checks if it's an `is`-attribute, AND
1190
1078
  // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1191
1079
  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 {
1192
1080
  return false;
1193
1081
  }
1194
1082
  /* Check value is safe. First, is attr inert? If so, is safe */
1195
-
1196
1083
  } 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) {
1197
1084
  return false;
1198
1085
  } else ;
1199
-
1200
1086
  return true;
1201
1087
  };
1088
+
1202
1089
  /**
1203
1090
  * _basicCustomElementCheck
1204
1091
  * checks if at least one dash is included in tagName, and it's not the first char
1205
1092
  * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
1206
1093
  * @param {string} tagName name of the tag of the node to sanitize
1207
1094
  */
1208
-
1209
-
1210
1095
  var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
1211
1096
  return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT$1);
1212
1097
  };
1098
+
1213
1099
  /**
1214
1100
  * _sanitizeAttributes
1215
1101
  *
@@ -1220,24 +1106,19 @@ function createDOMPurify() {
1220
1106
  *
1221
1107
  * @param {Node} currentNode to sanitize
1222
1108
  */
1223
-
1224
-
1225
1109
  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1226
1110
  var attr;
1227
1111
  var value;
1228
1112
  var lcName;
1229
1113
  var l;
1230
1114
  /* Execute a hook if present */
1231
-
1232
1115
  _executeHook('beforeSanitizeAttributes', currentNode, null);
1233
-
1234
1116
  var attributes = currentNode.attributes;
1235
- /* Check if we have attributes; if not we might have a text node */
1236
1117
 
1118
+ /* Check if we have attributes; if not we might have a text node */
1237
1119
  if (!attributes) {
1238
1120
  return;
1239
1121
  }
1240
-
1241
1122
  var hookEvent = {
1242
1123
  attrName: '',
1243
1124
  attrValue: '',
@@ -1245,79 +1126,67 @@ function createDOMPurify() {
1245
1126
  allowedAttributes: ALLOWED_ATTR
1246
1127
  };
1247
1128
  l = attributes.length;
1248
- /* Go backwards over all attributes; safely remove bad ones */
1249
1129
 
1130
+ /* Go backwards over all attributes; safely remove bad ones */
1250
1131
  while (l--) {
1251
1132
  attr = attributes[l];
1252
1133
  var _attr = attr,
1253
- name = _attr.name,
1254
- namespaceURI = _attr.namespaceURI;
1134
+ name = _attr.name,
1135
+ namespaceURI = _attr.namespaceURI;
1255
1136
  value = name === 'value' ? attr.value : stringTrim(attr.value);
1256
1137
  lcName = transformCaseFunc(name);
1257
- /* Execute a hook if present */
1258
1138
 
1139
+ /* Execute a hook if present */
1259
1140
  hookEvent.attrName = lcName;
1260
1141
  hookEvent.attrValue = value;
1261
1142
  hookEvent.keepAttr = true;
1262
1143
  hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1263
-
1264
1144
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1265
-
1266
1145
  value = hookEvent.attrValue;
1267
1146
  /* Did the hooks approve of the attribute? */
1268
-
1269
1147
  if (hookEvent.forceKeepAttr) {
1270
1148
  continue;
1271
1149
  }
1272
- /* Remove attribute */
1273
-
1274
1150
 
1151
+ /* Remove attribute */
1275
1152
  _removeAttribute(name, currentNode);
1276
- /* Did the hooks approve of the attribute? */
1277
-
1278
1153
 
1154
+ /* Did the hooks approve of the attribute? */
1279
1155
  if (!hookEvent.keepAttr) {
1280
1156
  continue;
1281
1157
  }
1282
- /* Work around a security issue in jQuery 3.0 */
1283
-
1284
1158
 
1159
+ /* Work around a security issue in jQuery 3.0 */
1285
1160
  if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
1286
1161
  _removeAttribute(name, currentNode);
1287
-
1288
1162
  continue;
1289
1163
  }
1290
- /* Sanitize attribute content to be template-safe */
1291
-
1292
1164
 
1165
+ /* Sanitize attribute content to be template-safe */
1293
1166
  if (SAFE_FOR_TEMPLATES) {
1294
1167
  value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
1295
1168
  value = stringReplace(value, ERB_EXPR$1, ' ');
1296
1169
  value = stringReplace(value, TMPLIT_EXPR$1, ' ');
1297
1170
  }
1298
- /* Is `value` valid for this attribute? */
1299
-
1300
1171
 
1172
+ /* Is `value` valid for this attribute? */
1301
1173
  var lcTag = transformCaseFunc(currentNode.nodeName);
1302
-
1303
1174
  if (!_isValidAttribute(lcTag, lcName, value)) {
1304
1175
  continue;
1305
1176
  }
1177
+
1306
1178
  /* Full DOM Clobbering protection via namespace isolation,
1307
1179
  * Prefix id and name attributes with `user-content-`
1308
1180
  */
1309
-
1310
-
1311
1181
  if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
1312
1182
  // Remove the attribute with this value
1313
- _removeAttribute(name, currentNode); // Prefix the value and later re-create the attribute with the sanitized value
1314
-
1183
+ _removeAttribute(name, currentNode);
1315
1184
 
1185
+ // Prefix the value and later re-create the attribute with the sanitized value
1316
1186
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
1317
1187
  }
1318
- /* Handle attributes that require Trusted Types */
1319
-
1320
1188
 
1189
+ /* Handle attributes that require Trusted Types */
1321
1190
  if (trustedTypesPolicy && _typeof(trustedTypes) === 'object' && typeof trustedTypes.getAttributeType === 'function') {
1322
1191
  if (namespaceURI) ; else {
1323
1192
  switch (trustedTypes.getAttributeType(lcTag, lcName)) {
@@ -1326,7 +1195,6 @@ function createDOMPurify() {
1326
1195
  value = trustedTypesPolicy.createHTML(value);
1327
1196
  break;
1328
1197
  }
1329
-
1330
1198
  case 'TrustedScriptURL':
1331
1199
  {
1332
1200
  value = trustedTypesPolicy.createScriptURL(value);
@@ -1335,9 +1203,8 @@ function createDOMPurify() {
1335
1203
  }
1336
1204
  }
1337
1205
  }
1338
- /* Handle invalid data-* attribute set by try-catching it */
1339
-
1340
1206
 
1207
+ /* Handle invalid data-* attribute set by try-catching it */
1341
1208
  try {
1342
1209
  if (namespaceURI) {
1343
1210
  currentNode.setAttributeNS(namespaceURI, name, value);
@@ -1345,56 +1212,47 @@ function createDOMPurify() {
1345
1212
  /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1346
1213
  currentNode.setAttribute(name, value);
1347
1214
  }
1348
-
1349
1215
  arrayPop(DOMPurify.removed);
1350
1216
  } catch (_) {}
1351
1217
  }
1352
- /* Execute a hook if present */
1353
-
1354
1218
 
1219
+ /* Execute a hook if present */
1355
1220
  _executeHook('afterSanitizeAttributes', currentNode, null);
1356
1221
  };
1222
+
1357
1223
  /**
1358
1224
  * _sanitizeShadowDOM
1359
1225
  *
1360
1226
  * @param {DocumentFragment} fragment to iterate over recursively
1361
1227
  */
1362
-
1363
-
1364
1228
  var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1365
1229
  var shadowNode;
1366
-
1367
1230
  var shadowIterator = _createIterator(fragment);
1368
- /* Execute a hook if present */
1369
-
1370
1231
 
1232
+ /* Execute a hook if present */
1371
1233
  _executeHook('beforeSanitizeShadowDOM', fragment, null);
1372
-
1373
1234
  while (shadowNode = shadowIterator.nextNode()) {
1374
1235
  /* Execute a hook if present */
1375
1236
  _executeHook('uponSanitizeShadowNode', shadowNode, null);
1376
- /* Sanitize tags and elements */
1377
-
1378
1237
 
1238
+ /* Sanitize tags and elements */
1379
1239
  if (_sanitizeElements(shadowNode)) {
1380
1240
  continue;
1381
1241
  }
1382
- /* Deep shadow DOM detected */
1383
-
1384
1242
 
1243
+ /* Deep shadow DOM detected */
1385
1244
  if (shadowNode.content instanceof DocumentFragment) {
1386
1245
  _sanitizeShadowDOM(shadowNode.content);
1387
1246
  }
1388
- /* Check attributes, sanitize if necessary */
1389
-
1390
1247
 
1248
+ /* Check attributes, sanitize if necessary */
1391
1249
  _sanitizeAttributes(shadowNode);
1392
1250
  }
1393
- /* Execute a hook if present */
1394
-
1395
1251
 
1252
+ /* Execute a hook if present */
1396
1253
  _executeHook('afterSanitizeShadowDOM', fragment, null);
1397
1254
  };
1255
+
1398
1256
  /**
1399
1257
  * Sanitize
1400
1258
  * Public method providing core sanitation functionality
@@ -1403,8 +1261,6 @@ function createDOMPurify() {
1403
1261
  * @param {Object} configuration object
1404
1262
  */
1405
1263
  // eslint-disable-next-line complexity
1406
-
1407
-
1408
1264
  DOMPurify.sanitize = function (dirty) {
1409
1265
  var cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1410
1266
  var body;
@@ -1415,19 +1271,15 @@ function createDOMPurify() {
1415
1271
  /* Make sure we have a string to sanitize.
1416
1272
  DO NOT return early, as this will return the wrong type if
1417
1273
  the user has requested a DOM object rather than a string */
1418
-
1419
1274
  IS_EMPTY_INPUT = !dirty;
1420
-
1421
1275
  if (IS_EMPTY_INPUT) {
1422
1276
  dirty = '<!-->';
1423
1277
  }
1424
- /* Stringify, in case dirty is an object */
1425
-
1426
1278
 
1279
+ /* Stringify, in case dirty is an object */
1427
1280
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
1428
1281
  if (typeof dirty.toString === 'function') {
1429
1282
  dirty = dirty.toString();
1430
-
1431
1283
  if (typeof dirty !== 'string') {
1432
1284
  throw typeErrorCreate('dirty is not a string, aborting');
1433
1285
  }
@@ -1435,43 +1287,36 @@ function createDOMPurify() {
1435
1287
  throw typeErrorCreate('toString is not a function');
1436
1288
  }
1437
1289
  }
1438
- /* Check we can run. Otherwise fall back or ignore */
1439
-
1440
1290
 
1291
+ /* Check we can run. Otherwise fall back or ignore */
1441
1292
  if (!DOMPurify.isSupported) {
1442
1293
  if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1443
1294
  if (typeof dirty === 'string') {
1444
1295
  return window.toStaticHTML(dirty);
1445
1296
  }
1446
-
1447
1297
  if (_isNode(dirty)) {
1448
1298
  return window.toStaticHTML(dirty.outerHTML);
1449
1299
  }
1450
1300
  }
1451
-
1452
1301
  return dirty;
1453
1302
  }
1454
- /* Assign config vars */
1455
-
1456
1303
 
1304
+ /* Assign config vars */
1457
1305
  if (!SET_CONFIG) {
1458
1306
  _parseConfig(cfg);
1459
1307
  }
1460
- /* Clean up removed elements */
1461
-
1462
1308
 
1309
+ /* Clean up removed elements */
1463
1310
  DOMPurify.removed = [];
1464
- /* Check if dirty is correctly typed for IN_PLACE */
1465
1311
 
1312
+ /* Check if dirty is correctly typed for IN_PLACE */
1466
1313
  if (typeof dirty === 'string') {
1467
1314
  IN_PLACE = false;
1468
1315
  }
1469
-
1470
1316
  if (IN_PLACE) {
1471
1317
  /* Do some early pre-sanitization to avoid unsafe root nodes */
1472
1318
  if (dirty.nodeName) {
1473
1319
  var tagName = transformCaseFunc(dirty.nodeName);
1474
-
1475
1320
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
1476
1321
  throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
1477
1322
  }
@@ -1481,7 +1326,6 @@ function createDOMPurify() {
1481
1326
  elements being stripped by the parser */
1482
1327
  body = _initDocument('<!---->');
1483
1328
  importedNode = body.ownerDocument.importNode(dirty, true);
1484
-
1485
1329
  if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1486
1330
  /* Node is already a body, use as is */
1487
1331
  body = importedNode;
@@ -1493,71 +1337,61 @@ function createDOMPurify() {
1493
1337
  }
1494
1338
  } else {
1495
1339
  /* Exit directly if we have nothing to do */
1496
- if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
1340
+ if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
1341
+ // eslint-disable-next-line unicorn/prefer-includes
1497
1342
  dirty.indexOf('<') === -1) {
1498
1343
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
1499
1344
  }
1500
- /* Initialize the document to work on */
1501
-
1502
1345
 
1346
+ /* Initialize the document to work on */
1503
1347
  body = _initDocument(dirty);
1504
- /* Check we have a DOM node from the data */
1505
1348
 
1349
+ /* Check we have a DOM node from the data */
1506
1350
  if (!body) {
1507
1351
  return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
1508
1352
  }
1509
1353
  }
1510
- /* Remove first element node (ours) if FORCE_BODY is set */
1511
-
1512
1354
 
1355
+ /* Remove first element node (ours) if FORCE_BODY is set */
1513
1356
  if (body && FORCE_BODY) {
1514
1357
  _forceRemove(body.firstChild);
1515
1358
  }
1516
- /* Get node iterator */
1517
-
1518
1359
 
1360
+ /* Get node iterator */
1519
1361
  var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1520
- /* Now start iterating over the created document */
1521
-
1522
1362
 
1363
+ /* Now start iterating over the created document */
1523
1364
  while (currentNode = nodeIterator.nextNode()) {
1524
1365
  /* Fix IE's strange behavior with manipulated textNodes #89 */
1525
1366
  if (currentNode.nodeType === 3 && currentNode === oldNode) {
1526
1367
  continue;
1527
1368
  }
1528
- /* Sanitize tags and elements */
1529
-
1530
1369
 
1370
+ /* Sanitize tags and elements */
1531
1371
  if (_sanitizeElements(currentNode)) {
1532
1372
  continue;
1533
1373
  }
1534
- /* Shadow DOM detected, sanitize it */
1535
-
1536
1374
 
1375
+ /* Shadow DOM detected, sanitize it */
1537
1376
  if (currentNode.content instanceof DocumentFragment) {
1538
1377
  _sanitizeShadowDOM(currentNode.content);
1539
1378
  }
1540
- /* Check attributes, sanitize if necessary */
1541
-
1542
1379
 
1380
+ /* Check attributes, sanitize if necessary */
1543
1381
  _sanitizeAttributes(currentNode);
1544
-
1545
1382
  oldNode = currentNode;
1546
1383
  }
1547
-
1548
1384
  oldNode = null;
1549
- /* If we sanitized `dirty` in-place, return it. */
1550
1385
 
1386
+ /* If we sanitized `dirty` in-place, return it. */
1551
1387
  if (IN_PLACE) {
1552
1388
  return dirty;
1553
1389
  }
1554
- /* Return sanitized string or DOM */
1555
-
1556
1390
 
1391
+ /* Return sanitized string or DOM */
1557
1392
  if (RETURN_DOM) {
1558
1393
  if (RETURN_DOM_FRAGMENT) {
1559
1394
  returnNode = createDocumentFragment.call(body.ownerDocument);
1560
-
1561
1395
  while (body.firstChild) {
1562
1396
  // eslint-disable-next-line unicorn/prefer-dom-node-append
1563
1397
  returnNode.appendChild(body.firstChild);
@@ -1565,7 +1399,6 @@ function createDOMPurify() {
1565
1399
  } else {
1566
1400
  returnNode = body;
1567
1401
  }
1568
-
1569
1402
  if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmod) {
1570
1403
  /*
1571
1404
  AdoptNode() is not used because internal state is not reset
@@ -1576,51 +1409,45 @@ function createDOMPurify() {
1576
1409
  */
1577
1410
  returnNode = importNode.call(originalDocument, returnNode, true);
1578
1411
  }
1579
-
1580
1412
  return returnNode;
1581
1413
  }
1582
-
1583
1414
  var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1584
- /* Serialize doctype if allowed */
1585
1415
 
1416
+ /* Serialize doctype if allowed */
1586
1417
  if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
1587
1418
  serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
1588
1419
  }
1589
- /* Sanitize final string template-safe */
1590
-
1591
1420
 
1421
+ /* Sanitize final string template-safe */
1592
1422
  if (SAFE_FOR_TEMPLATES) {
1593
1423
  serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
1594
1424
  serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
1595
1425
  serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR$1, ' ');
1596
1426
  }
1597
-
1598
1427
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
1599
1428
  };
1429
+
1600
1430
  /**
1601
1431
  * Public method to set the configuration once
1602
1432
  * setConfig
1603
1433
  *
1604
1434
  * @param {Object} cfg configuration object
1605
1435
  */
1606
-
1607
-
1608
1436
  DOMPurify.setConfig = function (cfg) {
1609
1437
  _parseConfig(cfg);
1610
-
1611
1438
  SET_CONFIG = true;
1612
1439
  };
1440
+
1613
1441
  /**
1614
1442
  * Public method to remove the configuration
1615
1443
  * clearConfig
1616
1444
  *
1617
1445
  */
1618
-
1619
-
1620
1446
  DOMPurify.clearConfig = function () {
1621
1447
  CONFIG = null;
1622
1448
  SET_CONFIG = false;
1623
1449
  };
1450
+
1624
1451
  /**
1625
1452
  * Public method to check if an attribute value is valid.
1626
1453
  * Uses last set config, if any. Otherwise, uses config defaults.
@@ -1631,18 +1458,16 @@ function createDOMPurify() {
1631
1458
  * @param {string} value Attribute value.
1632
1459
  * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
1633
1460
  */
1634
-
1635
-
1636
1461
  DOMPurify.isValidAttribute = function (tag, attr, value) {
1637
1462
  /* Initialize shared config vars if necessary. */
1638
1463
  if (!CONFIG) {
1639
1464
  _parseConfig({});
1640
1465
  }
1641
-
1642
1466
  var lcTag = transformCaseFunc(tag);
1643
1467
  var lcName = transformCaseFunc(attr);
1644
1468
  return _isValidAttribute(lcTag, lcName, value);
1645
1469
  };
1470
+
1646
1471
  /**
1647
1472
  * AddHook
1648
1473
  * Public method to add DOMPurify hooks
@@ -1650,16 +1475,14 @@ function createDOMPurify() {
1650
1475
  * @param {String} entryPoint entry point for the hook to add
1651
1476
  * @param {Function} hookFunction function to execute
1652
1477
  */
1653
-
1654
-
1655
1478
  DOMPurify.addHook = function (entryPoint, hookFunction) {
1656
1479
  if (typeof hookFunction !== 'function') {
1657
1480
  return;
1658
1481
  }
1659
-
1660
1482
  hooks[entryPoint] = hooks[entryPoint] || [];
1661
1483
  arrayPush(hooks[entryPoint], hookFunction);
1662
1484
  };
1485
+
1663
1486
  /**
1664
1487
  * RemoveHook
1665
1488
  * Public method to remove a DOMPurify hook at a given entryPoint
@@ -1668,40 +1491,34 @@ function createDOMPurify() {
1668
1491
  * @param {String} entryPoint entry point for the hook to remove
1669
1492
  * @return {Function} removed(popped) hook
1670
1493
  */
1671
-
1672
-
1673
1494
  DOMPurify.removeHook = function (entryPoint) {
1674
1495
  if (hooks[entryPoint]) {
1675
1496
  return arrayPop(hooks[entryPoint]);
1676
1497
  }
1677
1498
  };
1499
+
1678
1500
  /**
1679
1501
  * RemoveHooks
1680
1502
  * Public method to remove all DOMPurify hooks at a given entryPoint
1681
1503
  *
1682
1504
  * @param {String} entryPoint entry point for the hooks to remove
1683
1505
  */
1684
-
1685
-
1686
1506
  DOMPurify.removeHooks = function (entryPoint) {
1687
1507
  if (hooks[entryPoint]) {
1688
1508
  hooks[entryPoint] = [];
1689
1509
  }
1690
1510
  };
1511
+
1691
1512
  /**
1692
1513
  * RemoveAllHooks
1693
1514
  * Public method to remove all DOMPurify hooks
1694
1515
  *
1695
1516
  */
1696
-
1697
-
1698
1517
  DOMPurify.removeAllHooks = function () {
1699
1518
  hooks = {};
1700
1519
  };
1701
-
1702
1520
  return DOMPurify;
1703
1521
  }
1704
-
1705
1522
  var purify = createDOMPurify();
1706
1523
 
1707
1524
  module.exports = purify;