dompurify 2.3.5 → 2.3.8

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