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