dompurify 2.3.5 → 2.3.8

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