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