dompurify 2.3.4 → 2.3.7

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