dompurify 2.3.6 → 2.3.9

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