dompurify 2.0.4 → 2.0.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,39 +1,75 @@
1
- var freeze$1 = Object.freeze || function (x) {
2
- return x;
3
- };
1
+ 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); } }
4
2
 
5
- var html = freeze$1(['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', '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', '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']);
3
+ var hasOwnProperty = Object.hasOwnProperty;
4
+ var setPrototypeOf = Object.setPrototypeOf;
5
+ var isFrozen = Object.isFrozen;
6
+ var objectKeys = Object.keys;
7
+ var freeze = Object.freeze;
8
+ var seal = Object.seal; // eslint-disable-line import/no-mutable-exports
6
9
 
7
- // SVG
8
- var svg = freeze$1(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', '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', 'video', 'view', 'vkern']);
10
+ var _ref = typeof Reflect !== 'undefined' && Reflect;
11
+ var apply = _ref.apply;
12
+ var construct = _ref.construct;
9
13
 
10
- var svgFilters = freeze$1(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
14
+ if (!apply) {
15
+ apply = function apply(fun, thisValue, args) {
16
+ return fun.apply(thisValue, args);
17
+ };
18
+ }
11
19
 
12
- var mathMl = freeze$1(['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']);
20
+ if (!freeze) {
21
+ freeze = function freeze(x) {
22
+ return x;
23
+ };
24
+ }
13
25
 
14
- var text = freeze$1(['#text']);
26
+ if (!seal) {
27
+ seal = function seal(x) {
28
+ return x;
29
+ };
30
+ }
15
31
 
16
- var freeze$2 = Object.freeze || function (x) {
17
- return x;
18
- };
32
+ if (!construct) {
33
+ construct = function construct(Func, args) {
34
+ return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
35
+ };
36
+ }
19
37
 
20
- var html$1 = freeze$2(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', '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', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
38
+ var arrayForEach = unapply(Array.prototype.forEach);
39
+ var arrayIndexOf = unapply(Array.prototype.indexOf);
40
+ var arrayJoin = unapply(Array.prototype.join);
41
+ var arrayPop = unapply(Array.prototype.pop);
42
+ var arrayPush = unapply(Array.prototype.push);
43
+ var arraySlice = unapply(Array.prototype.slice);
21
44
 
22
- var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', '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', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', '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']);
45
+ var stringToLowerCase = unapply(String.prototype.toLowerCase);
46
+ var stringMatch = unapply(String.prototype.match);
47
+ var stringReplace = unapply(String.prototype.replace);
48
+ var stringIndexOf = unapply(String.prototype.indexOf);
49
+ var stringTrim = unapply(String.prototype.trim);
23
50
 
24
- var mathMl$1 = freeze$2(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', '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']);
51
+ var regExpTest = unapply(RegExp.prototype.test);
52
+ var regExpCreate = unconstruct(RegExp);
25
53
 
26
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
54
+ var typeErrorCreate = unconstruct(TypeError);
27
55
 
28
- var hasOwnProperty = Object.hasOwnProperty;
29
- var setPrototypeOf = Object.setPrototypeOf;
56
+ function unapply(func) {
57
+ return function (thisArg) {
58
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
59
+ args[_key - 1] = arguments[_key];
60
+ }
61
+
62
+ return apply(func, thisArg, args);
63
+ };
64
+ }
30
65
 
31
- var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
32
- var apply$1 = _ref$1.apply;
66
+ function unconstruct(func) {
67
+ return function () {
68
+ for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
69
+ args[_key2] = arguments[_key2];
70
+ }
33
71
 
34
- if (!apply$1) {
35
- apply$1 = function apply(fun, thisValue, args) {
36
- return fun.apply(thisValue, args);
72
+ return construct(func, args);
37
73
  };
38
74
  }
39
75
 
@@ -50,10 +86,10 @@ function addToSet(set, array) {
50
86
  while (l--) {
51
87
  var element = array[l];
52
88
  if (typeof element === 'string') {
53
- var lcElement = element.toLowerCase();
89
+ var lcElement = stringToLowerCase(element);
54
90
  if (lcElement !== element) {
55
91
  // Config presets (e.g. tags.js, attrs.js) are immutable.
56
- if (!Object.isFrozen(array)) {
92
+ if (!isFrozen(array)) {
57
93
  array[l] = lcElement;
58
94
  }
59
95
 
@@ -73,7 +109,7 @@ function clone(object) {
73
109
 
74
110
  var property = void 0;
75
111
  for (property in object) {
76
- if (apply$1(hasOwnProperty, object, [property])) {
112
+ if (apply(hasOwnProperty, object, [property])) {
77
113
  newObject[property] = object[property];
78
114
  }
79
115
  }
@@ -81,9 +117,24 @@ function clone(object) {
81
117
  return newObject;
82
118
  }
83
119
 
84
- var seal = Object.seal || function (x) {
85
- return x;
86
- };
120
+ 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', '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']);
121
+
122
+ // SVG
123
+ var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', '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', 'video', 'view', 'vkern']);
124
+
125
+ 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']);
126
+
127
+ 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']);
128
+
129
+ var text = freeze(['#text']);
130
+
131
+ var html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', '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', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
132
+
133
+ var svg$1 = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', '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', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', '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']);
134
+
135
+ 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']);
136
+
137
+ var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
87
138
 
88
139
  var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
89
140
  var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
@@ -99,22 +150,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
99
150
 
100
151
  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); } }
101
152
 
102
- var _ref = typeof Reflect !== 'undefined' && Reflect;
103
- var apply = _ref.apply;
104
-
105
- var arraySlice = Array.prototype.slice;
106
- var freeze = Object.freeze;
107
-
108
153
  var getGlobal = function getGlobal() {
109
154
  return typeof window === 'undefined' ? null : window;
110
155
  };
111
156
 
112
- if (!apply) {
113
- apply = function apply(fun, thisValue, args) {
114
- return fun.apply(thisValue, args);
115
- };
116
- }
117
-
118
157
  /**
119
158
  * Creates a no-op policy for internal use only.
120
159
  * Don't export this function outside this module!
@@ -165,7 +204,7 @@ function createDOMPurify() {
165
204
  * Version label, exposed for easier checks
166
205
  * if DOMPurify is up to date or not
167
206
  */
168
- DOMPurify.version = '2.0.4';
207
+ DOMPurify.version = '2.0.8';
169
208
 
170
209
  /**
171
210
  * Array of elements that DOMPurify removed during sanitation.
@@ -183,7 +222,6 @@ function createDOMPurify() {
183
222
 
184
223
  var originalDocument = window.document;
185
224
  var useDOMParser = false;
186
- var removeSVGAttr = false;
187
225
  var removeTitle = false;
188
226
 
189
227
  var document = window.document;
@@ -196,7 +234,7 @@ function createDOMPurify() {
196
234
  Text = window.Text,
197
235
  Comment = window.Comment,
198
236
  DOMParser = window.DOMParser,
199
- TrustedTypes = window.TrustedTypes;
237
+ trustedTypes = window.trustedTypes;
200
238
 
201
239
  // As per issue #47, the web-components registry is inherited by a
202
240
  // new document created via createHTMLDocument. As per the spec
@@ -212,7 +250,7 @@ function createDOMPurify() {
212
250
  }
213
251
  }
214
252
 
215
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
253
+ var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
216
254
  var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
217
255
 
218
256
  var _document = document,
@@ -319,7 +357,7 @@ function createDOMPurify() {
319
357
  var USE_PROFILES = {};
320
358
 
321
359
  /* Tags to ignore content of when KEEP_CONTENT is true */
322
- var FORBID_CONTENTS = addToSet({}, ['audio', 'colgroup', 'head', 'math', 'script', 'style', 'template', 'thead', 'svg', 'video']);
360
+ var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
323
361
 
324
362
  /* Tags that are safe for data: URIs */
325
363
  var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
@@ -373,9 +411,7 @@ function createDOMPurify() {
373
411
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
374
412
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
375
413
  IN_PLACE = cfg.IN_PLACE || false; // Default false
376
-
377
414
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
378
-
379
415
  if (SAFE_FOR_TEMPLATES) {
380
416
  ALLOW_DATA_ATTR = false;
381
417
  }
@@ -464,7 +500,7 @@ function createDOMPurify() {
464
500
  * @param {Node} node a DOM node
465
501
  */
466
502
  var _forceRemove = function _forceRemove(node) {
467
- DOMPurify.removed.push({ element: node });
503
+ arrayPush(DOMPurify.removed, { element: node });
468
504
  try {
469
505
  node.parentNode.removeChild(node);
470
506
  } catch (error) {
@@ -480,12 +516,12 @@ function createDOMPurify() {
480
516
  */
481
517
  var _removeAttribute = function _removeAttribute(name, node) {
482
518
  try {
483
- DOMPurify.removed.push({
519
+ arrayPush(DOMPurify.removed, {
484
520
  attribute: node.getAttributeNode(name),
485
521
  from: node
486
522
  });
487
523
  } catch (error) {
488
- DOMPurify.removed.push({
524
+ arrayPush(DOMPurify.removed, {
489
525
  attribute: null,
490
526
  from: node
491
527
  });
@@ -509,17 +545,15 @@ function createDOMPurify() {
509
545
  dirty = '<remove></remove>' + dirty;
510
546
  } else {
511
547
  /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
512
- var matches = dirty.match(/^[\s]+/);
548
+ var matches = stringMatch(dirty, /^[\s]+/);
513
549
  leadingWhitespace = matches && matches[0];
514
- if (leadingWhitespace) {
515
- dirty = dirty.slice(leadingWhitespace.length);
516
- }
517
550
  }
518
551
 
552
+ var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
519
553
  /* Use DOMParser to workaround Firefox bug (see comment below) */
520
554
  if (useDOMParser) {
521
555
  try {
522
- doc = new DOMParser().parseFromString(dirty, 'text/html');
556
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
523
557
  } catch (error) {}
524
558
  }
525
559
 
@@ -536,10 +570,10 @@ function createDOMPurify() {
536
570
  body = _doc.body;
537
571
 
538
572
  body.parentNode.removeChild(body.parentNode.firstElementChild);
539
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
573
+ body.outerHTML = dirtyPayload;
540
574
  }
541
575
 
542
- if (leadingWhitespace) {
576
+ if (dirty && leadingWhitespace) {
543
577
  doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
544
578
  }
545
579
 
@@ -569,20 +603,11 @@ function createDOMPurify() {
569
603
  (function () {
570
604
  try {
571
605
  var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
572
- if (/<\/title/.test(doc.querySelector('title').innerHTML)) {
606
+ if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
573
607
  removeTitle = true;
574
608
  }
575
609
  } catch (error) {}
576
610
  })();
577
-
578
- (function () {
579
- try {
580
- var doc = _initDocument('<svg></p></svg>');
581
- if (doc.querySelector('svg p')) {
582
- removeSVGAttr = true;
583
- }
584
- } catch (error) {}
585
- })();
586
611
  }
587
612
 
588
613
  /**
@@ -638,7 +663,7 @@ function createDOMPurify() {
638
663
  return;
639
664
  }
640
665
 
641
- hooks[entryPoint].forEach(function (hook) {
666
+ arrayForEach(hooks[entryPoint], function (hook) {
642
667
  hook.call(DOMPurify, currentNode, data, CONFIG);
643
668
  });
644
669
  };
@@ -667,7 +692,7 @@ function createDOMPurify() {
667
692
  }
668
693
 
669
694
  /* Now let's check the element's type and name */
670
- var tagName = currentNode.nodeName.toLowerCase();
695
+ var tagName = stringToLowerCase(currentNode.nodeName);
671
696
 
672
697
  /* Execute a hook if present */
673
698
  _executeHook('uponSanitizeElement', currentNode, {
@@ -675,6 +700,12 @@ function createDOMPurify() {
675
700
  allowedTags: ALLOWED_TAGS
676
701
  });
677
702
 
703
+ /* Take care of an mXSS pattern using p, br inside svg, math */
704
+ if ((tagName === 'svg' || tagName === 'math') && currentNode.querySelectorAll('p, br').length !== 0) {
705
+ _forceRemove(currentNode);
706
+ return true;
707
+ }
708
+
678
709
  /* Remove element if anything forbids its presence */
679
710
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
680
711
  /* Keep content except for black-listed elements */
@@ -690,34 +721,23 @@ function createDOMPurify() {
690
721
  }
691
722
 
692
723
  /* Remove in case a noscript/noembed XSS is suspected */
693
- if (tagName === 'noscript' && /<\/noscript/i.test(currentNode.innerHTML)) {
724
+ if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
694
725
  _forceRemove(currentNode);
695
726
  return true;
696
727
  }
697
728
 
698
- if (tagName === 'noembed' && /<\/noembed/i.test(currentNode.innerHTML)) {
699
- _forceRemove(currentNode);
700
- return true;
701
- }
702
-
703
- /* Remove in case an mXSS is suspected */
704
- if (currentNode.namespaceURI && /svg|math/i.test(currentNode.namespaceURI) && currentNode.textContent && new RegExp('</' + tagName, 'i').test(currentNode.textContent)) {
705
- _forceRemove(currentNode);
706
- return true;
707
- }
708
-
709
- if ((tagName === 'svg' || tagName === 'math') && (currentNode.querySelectorAll('template') || currentNode.querySelectorAll('svg') || currentNode.querySelectorAll('math'))) {
729
+ if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
710
730
  _forceRemove(currentNode);
711
731
  return true;
712
732
  }
713
733
 
714
734
  /* Convert markup to cover jQuery behavior */
715
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
716
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
735
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && regExpTest(/</g, currentNode.textContent)) {
736
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
717
737
  if (currentNode.innerHTML) {
718
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
738
+ currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '&lt;');
719
739
  } else {
720
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
740
+ currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '&lt;');
721
741
  }
722
742
  }
723
743
 
@@ -725,10 +745,10 @@ function createDOMPurify() {
725
745
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
726
746
  /* Get the element's text content */
727
747
  content = currentNode.textContent;
728
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
729
- content = content.replace(ERB_EXPR$$1, ' ');
748
+ content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
749
+ content = stringReplace(content, ERB_EXPR$$1, ' ');
730
750
  if (currentNode.textContent !== content) {
731
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
751
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
732
752
  currentNode.textContent = content;
733
753
  }
734
754
  }
@@ -758,9 +778,9 @@ function createDOMPurify() {
758
778
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
759
779
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
760
780
  We don't need to check the value; it's always URI safe. */
761
- if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
781
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
762
782
  // This attribute is safe
763
- } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
783
+ } else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
764
784
  // This attribute is safe
765
785
  /* Otherwise, check the name is permitted */
766
786
  } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
@@ -771,16 +791,16 @@ function createDOMPurify() {
771
791
  // This attribute is safe
772
792
  /* Check no script, data or unknown possibly unsafe URI
773
793
  unless we know URI values are safe for that attribute */
774
- } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
794
+ } else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
775
795
  // This attribute is safe
776
796
  /* Keep image data URIs alive if src/xlink:href is allowed */
777
797
  /* Further prevent gadget XSS for dynamically built script tags */
778
- } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {
798
+ } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
779
799
  // This attribute is safe
780
800
  /* Allow unknown protocols: This provides support for links that
781
801
  are handled by protocol handlers which may be unknown ahead of
782
802
  time, e.g. fb:, spotify: */
783
- } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
803
+ } else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
784
804
  // This attribute is safe
785
805
  /* Check for binary attributes */
786
806
  // eslint-disable-next-line no-negated-condition
@@ -837,21 +857,19 @@ function createDOMPurify() {
837
857
  name = _attr.name,
838
858
  namespaceURI = _attr.namespaceURI;
839
859
 
840
- value = attr.value.trim();
841
- lcName = name.toLowerCase();
860
+ value = stringTrim(attr.value);
861
+ lcName = stringToLowerCase(name);
842
862
 
843
863
  /* Execute a hook if present */
844
864
  hookEvent.attrName = lcName;
845
865
  hookEvent.attrValue = value;
846
866
  hookEvent.keepAttr = true;
867
+ hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
847
868
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
848
869
  value = hookEvent.attrValue;
849
-
850
- /* Check for possible Chrome mXSS, least aggressively */
851
- if (ALLOWED_TAGS.svg && !FORBID_TAGS.svg || ALLOWED_TAGS.math && !FORBID_TAGS.math) {
852
- if (removeSVGAttr && /<\//.test(value)) {
853
- _forceRemove(currentNode);
854
- }
870
+ /* Did the hooks approve of the attribute? */
871
+ if (hookEvent.forceKeepAttr) {
872
+ continue;
855
873
  }
856
874
 
857
875
  /* Remove attribute */
@@ -860,10 +878,10 @@ function createDOMPurify() {
860
878
  // attribute at the time.
861
879
  if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
862
880
  idAttr = attributes.id;
863
- attributes = apply(arraySlice, attributes, []);
881
+ attributes = arraySlice(attributes, []);
864
882
  _removeAttribute('id', currentNode);
865
883
  _removeAttribute(name, currentNode);
866
- if (attributes.indexOf(idAttr) > l) {
884
+ if (arrayIndexOf(attributes, idAttr) > l) {
867
885
  currentNode.setAttribute('id', idAttr.value);
868
886
  }
869
887
  } else if (
@@ -887,10 +905,22 @@ function createDOMPurify() {
887
905
  continue;
888
906
  }
889
907
 
908
+ /* Work around a security issue in jQuery 3.0 */
909
+ if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
910
+ _removeAttribute(name, currentNode);
911
+ continue;
912
+ }
913
+
914
+ /* Take care of an mXSS pattern using namespace switches */
915
+ if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
916
+ _removeAttribute(name, currentNode);
917
+ continue;
918
+ }
919
+
890
920
  /* Sanitize attribute content to be template-safe */
891
921
  if (SAFE_FOR_TEMPLATES) {
892
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
893
- value = value.replace(ERB_EXPR$$1, ' ');
922
+ value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
923
+ value = stringReplace(value, ERB_EXPR$$1, ' ');
894
924
  }
895
925
 
896
926
  /* Is `value` valid for this attribute? */
@@ -908,7 +938,7 @@ function createDOMPurify() {
908
938
  currentNode.setAttribute(name, value);
909
939
  }
910
940
 
911
- DOMPurify.removed.pop();
941
+ arrayPop(DOMPurify.removed);
912
942
  } catch (error) {}
913
943
  }
914
944
 
@@ -975,11 +1005,11 @@ function createDOMPurify() {
975
1005
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
976
1006
  // eslint-disable-next-line no-negated-condition
977
1007
  if (typeof dirty.toString !== 'function') {
978
- throw new TypeError('toString is not a function');
1008
+ throw typeErrorCreate('toString is not a function');
979
1009
  } else {
980
1010
  dirty = dirty.toString();
981
1011
  if (typeof dirty !== 'string') {
982
- throw new TypeError('dirty is not a string, aborting');
1012
+ throw typeErrorCreate('dirty is not a string, aborting');
983
1013
  }
984
1014
  }
985
1015
  }
@@ -1007,6 +1037,11 @@ function createDOMPurify() {
1007
1037
  /* Clean up removed elements */
1008
1038
  DOMPurify.removed = [];
1009
1039
 
1040
+ /* Check if dirty is correctly typed for IN_PLACE */
1041
+ if (typeof dirty === 'string') {
1042
+ IN_PLACE = false;
1043
+ }
1044
+
1010
1045
  if (IN_PLACE) {
1011
1046
  /* No special handling necessary for in-place sanitization */
1012
1047
  } else if (dirty instanceof Node) {
@@ -1105,8 +1140,8 @@ function createDOMPurify() {
1105
1140
 
1106
1141
  /* Sanitize final string template-safe */
1107
1142
  if (SAFE_FOR_TEMPLATES) {
1108
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1109
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1143
+ serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
1144
+ serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
1110
1145
  }
1111
1146
 
1112
1147
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
@@ -1149,8 +1184,8 @@ function createDOMPurify() {
1149
1184
  _parseConfig({});
1150
1185
  }
1151
1186
 
1152
- var lcTag = tag.toLowerCase();
1153
- var lcName = attr.toLowerCase();
1187
+ var lcTag = stringToLowerCase(tag);
1188
+ var lcName = stringToLowerCase(attr);
1154
1189
  return _isValidAttribute(lcTag, lcName, value);
1155
1190
  };
1156
1191
 
@@ -1167,7 +1202,7 @@ function createDOMPurify() {
1167
1202
  }
1168
1203
 
1169
1204
  hooks[entryPoint] = hooks[entryPoint] || [];
1170
- hooks[entryPoint].push(hookFunction);
1205
+ arrayPush(hooks[entryPoint], hookFunction);
1171
1206
  };
1172
1207
 
1173
1208
  /**
@@ -1179,7 +1214,7 @@ function createDOMPurify() {
1179
1214
  */
1180
1215
  DOMPurify.removeHook = function (entryPoint) {
1181
1216
  if (hooks[entryPoint]) {
1182
- hooks[entryPoint].pop();
1217
+ arrayPop(hooks[entryPoint]);
1183
1218
  }
1184
1219
  };
1185
1220