hoeditor-web 2.0.49 → 2.0.50

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