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.js CHANGED
@@ -4,42 +4,78 @@
4
4
  (global.DOMPurify = factory());
5
5
  }(this, (function () { 'use strict';
6
6
 
7
- var freeze$1 = Object.freeze || function (x) {
8
- return x;
9
- };
7
+ 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); } }
10
8
 
11
- 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']);
9
+ var hasOwnProperty = Object.hasOwnProperty;
10
+ var setPrototypeOf = Object.setPrototypeOf;
11
+ var isFrozen = Object.isFrozen;
12
+ var objectKeys = Object.keys;
13
+ var freeze = Object.freeze;
14
+ var seal = Object.seal; // eslint-disable-line import/no-mutable-exports
12
15
 
13
- // SVG
14
- 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']);
16
+ var _ref = typeof Reflect !== 'undefined' && Reflect;
17
+ var apply = _ref.apply;
18
+ var construct = _ref.construct;
15
19
 
16
- 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']);
20
+ if (!apply) {
21
+ apply = function apply(fun, thisValue, args) {
22
+ return fun.apply(thisValue, args);
23
+ };
24
+ }
17
25
 
18
- 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']);
26
+ if (!freeze) {
27
+ freeze = function freeze(x) {
28
+ return x;
29
+ };
30
+ }
19
31
 
20
- var text = freeze$1(['#text']);
32
+ if (!seal) {
33
+ seal = function seal(x) {
34
+ return x;
35
+ };
36
+ }
21
37
 
22
- var freeze$2 = Object.freeze || function (x) {
23
- return x;
24
- };
38
+ if (!construct) {
39
+ construct = function construct(Func, args) {
40
+ return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
41
+ };
42
+ }
25
43
 
26
- 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']);
44
+ var arrayForEach = unapply(Array.prototype.forEach);
45
+ var arrayIndexOf = unapply(Array.prototype.indexOf);
46
+ var arrayJoin = unapply(Array.prototype.join);
47
+ var arrayPop = unapply(Array.prototype.pop);
48
+ var arrayPush = unapply(Array.prototype.push);
49
+ var arraySlice = unapply(Array.prototype.slice);
27
50
 
28
- 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']);
51
+ var stringToLowerCase = unapply(String.prototype.toLowerCase);
52
+ var stringMatch = unapply(String.prototype.match);
53
+ var stringReplace = unapply(String.prototype.replace);
54
+ var stringIndexOf = unapply(String.prototype.indexOf);
55
+ var stringTrim = unapply(String.prototype.trim);
29
56
 
30
- 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']);
57
+ var regExpTest = unapply(RegExp.prototype.test);
58
+ var regExpCreate = unconstruct(RegExp);
31
59
 
32
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
60
+ var typeErrorCreate = unconstruct(TypeError);
33
61
 
34
- var hasOwnProperty = Object.hasOwnProperty;
35
- var setPrototypeOf = Object.setPrototypeOf;
62
+ function unapply(func) {
63
+ return function (thisArg) {
64
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
65
+ args[_key - 1] = arguments[_key];
66
+ }
67
+
68
+ return apply(func, thisArg, args);
69
+ };
70
+ }
36
71
 
37
- var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
38
- var apply$1 = _ref$1.apply;
72
+ function unconstruct(func) {
73
+ return function () {
74
+ for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
75
+ args[_key2] = arguments[_key2];
76
+ }
39
77
 
40
- if (!apply$1) {
41
- apply$1 = function apply(fun, thisValue, args) {
42
- return fun.apply(thisValue, args);
78
+ return construct(func, args);
43
79
  };
44
80
  }
45
81
 
@@ -56,10 +92,10 @@ function addToSet(set, array) {
56
92
  while (l--) {
57
93
  var element = array[l];
58
94
  if (typeof element === 'string') {
59
- var lcElement = element.toLowerCase();
95
+ var lcElement = stringToLowerCase(element);
60
96
  if (lcElement !== element) {
61
97
  // Config presets (e.g. tags.js, attrs.js) are immutable.
62
- if (!Object.isFrozen(array)) {
98
+ if (!isFrozen(array)) {
63
99
  array[l] = lcElement;
64
100
  }
65
101
 
@@ -79,7 +115,7 @@ function clone(object) {
79
115
 
80
116
  var property = void 0;
81
117
  for (property in object) {
82
- if (apply$1(hasOwnProperty, object, [property])) {
118
+ if (apply(hasOwnProperty, object, [property])) {
83
119
  newObject[property] = object[property];
84
120
  }
85
121
  }
@@ -87,9 +123,24 @@ function clone(object) {
87
123
  return newObject;
88
124
  }
89
125
 
90
- var seal = Object.seal || function (x) {
91
- return x;
92
- };
126
+ 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']);
127
+
128
+ // SVG
129
+ 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']);
130
+
131
+ 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']);
132
+
133
+ 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']);
134
+
135
+ var text = freeze(['#text']);
136
+
137
+ 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']);
138
+
139
+ 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']);
140
+
141
+ 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']);
142
+
143
+ var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
93
144
 
94
145
  var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
95
146
  var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
@@ -105,22 +156,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
105
156
 
106
157
  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); } }
107
158
 
108
- var _ref = typeof Reflect !== 'undefined' && Reflect;
109
- var apply = _ref.apply;
110
-
111
- var arraySlice = Array.prototype.slice;
112
- var freeze = Object.freeze;
113
-
114
159
  var getGlobal = function getGlobal() {
115
160
  return typeof window === 'undefined' ? null : window;
116
161
  };
117
162
 
118
- if (!apply) {
119
- apply = function apply(fun, thisValue, args) {
120
- return fun.apply(thisValue, args);
121
- };
122
- }
123
-
124
163
  /**
125
164
  * Creates a no-op policy for internal use only.
126
165
  * Don't export this function outside this module!
@@ -171,7 +210,7 @@ function createDOMPurify() {
171
210
  * Version label, exposed for easier checks
172
211
  * if DOMPurify is up to date or not
173
212
  */
174
- DOMPurify.version = '2.0.4';
213
+ DOMPurify.version = '2.0.8';
175
214
 
176
215
  /**
177
216
  * Array of elements that DOMPurify removed during sanitation.
@@ -189,7 +228,6 @@ function createDOMPurify() {
189
228
 
190
229
  var originalDocument = window.document;
191
230
  var useDOMParser = false;
192
- var removeSVGAttr = false;
193
231
  var removeTitle = false;
194
232
 
195
233
  var document = window.document;
@@ -202,7 +240,7 @@ function createDOMPurify() {
202
240
  Text = window.Text,
203
241
  Comment = window.Comment,
204
242
  DOMParser = window.DOMParser,
205
- TrustedTypes = window.TrustedTypes;
243
+ trustedTypes = window.trustedTypes;
206
244
 
207
245
  // As per issue #47, the web-components registry is inherited by a
208
246
  // new document created via createHTMLDocument. As per the spec
@@ -218,7 +256,7 @@ function createDOMPurify() {
218
256
  }
219
257
  }
220
258
 
221
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
259
+ var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
222
260
  var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
223
261
 
224
262
  var _document = document,
@@ -325,7 +363,7 @@ function createDOMPurify() {
325
363
  var USE_PROFILES = {};
326
364
 
327
365
  /* Tags to ignore content of when KEEP_CONTENT is true */
328
- var FORBID_CONTENTS = addToSet({}, ['audio', 'colgroup', 'head', 'math', 'script', 'style', 'template', 'thead', 'svg', 'video']);
366
+ 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']);
329
367
 
330
368
  /* Tags that are safe for data: URIs */
331
369
  var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
@@ -379,9 +417,7 @@ function createDOMPurify() {
379
417
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
380
418
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
381
419
  IN_PLACE = cfg.IN_PLACE || false; // Default false
382
-
383
420
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
384
-
385
421
  if (SAFE_FOR_TEMPLATES) {
386
422
  ALLOW_DATA_ATTR = false;
387
423
  }
@@ -470,7 +506,7 @@ function createDOMPurify() {
470
506
  * @param {Node} node a DOM node
471
507
  */
472
508
  var _forceRemove = function _forceRemove(node) {
473
- DOMPurify.removed.push({ element: node });
509
+ arrayPush(DOMPurify.removed, { element: node });
474
510
  try {
475
511
  node.parentNode.removeChild(node);
476
512
  } catch (error) {
@@ -486,12 +522,12 @@ function createDOMPurify() {
486
522
  */
487
523
  var _removeAttribute = function _removeAttribute(name, node) {
488
524
  try {
489
- DOMPurify.removed.push({
525
+ arrayPush(DOMPurify.removed, {
490
526
  attribute: node.getAttributeNode(name),
491
527
  from: node
492
528
  });
493
529
  } catch (error) {
494
- DOMPurify.removed.push({
530
+ arrayPush(DOMPurify.removed, {
495
531
  attribute: null,
496
532
  from: node
497
533
  });
@@ -515,17 +551,15 @@ function createDOMPurify() {
515
551
  dirty = '<remove></remove>' + dirty;
516
552
  } else {
517
553
  /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
518
- var matches = dirty.match(/^[\s]+/);
554
+ var matches = stringMatch(dirty, /^[\s]+/);
519
555
  leadingWhitespace = matches && matches[0];
520
- if (leadingWhitespace) {
521
- dirty = dirty.slice(leadingWhitespace.length);
522
- }
523
556
  }
524
557
 
558
+ var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
525
559
  /* Use DOMParser to workaround Firefox bug (see comment below) */
526
560
  if (useDOMParser) {
527
561
  try {
528
- doc = new DOMParser().parseFromString(dirty, 'text/html');
562
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
529
563
  } catch (error) {}
530
564
  }
531
565
 
@@ -542,10 +576,10 @@ function createDOMPurify() {
542
576
  body = _doc.body;
543
577
 
544
578
  body.parentNode.removeChild(body.parentNode.firstElementChild);
545
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
579
+ body.outerHTML = dirtyPayload;
546
580
  }
547
581
 
548
- if (leadingWhitespace) {
582
+ if (dirty && leadingWhitespace) {
549
583
  doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
550
584
  }
551
585
 
@@ -575,20 +609,11 @@ function createDOMPurify() {
575
609
  (function () {
576
610
  try {
577
611
  var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
578
- if (/<\/title/.test(doc.querySelector('title').innerHTML)) {
612
+ if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
579
613
  removeTitle = true;
580
614
  }
581
615
  } catch (error) {}
582
616
  })();
583
-
584
- (function () {
585
- try {
586
- var doc = _initDocument('<svg></p></svg>');
587
- if (doc.querySelector('svg p')) {
588
- removeSVGAttr = true;
589
- }
590
- } catch (error) {}
591
- })();
592
617
  }
593
618
 
594
619
  /**
@@ -644,7 +669,7 @@ function createDOMPurify() {
644
669
  return;
645
670
  }
646
671
 
647
- hooks[entryPoint].forEach(function (hook) {
672
+ arrayForEach(hooks[entryPoint], function (hook) {
648
673
  hook.call(DOMPurify, currentNode, data, CONFIG);
649
674
  });
650
675
  };
@@ -673,7 +698,7 @@ function createDOMPurify() {
673
698
  }
674
699
 
675
700
  /* Now let's check the element's type and name */
676
- var tagName = currentNode.nodeName.toLowerCase();
701
+ var tagName = stringToLowerCase(currentNode.nodeName);
677
702
 
678
703
  /* Execute a hook if present */
679
704
  _executeHook('uponSanitizeElement', currentNode, {
@@ -681,6 +706,12 @@ function createDOMPurify() {
681
706
  allowedTags: ALLOWED_TAGS
682
707
  });
683
708
 
709
+ /* Take care of an mXSS pattern using p, br inside svg, math */
710
+ if ((tagName === 'svg' || tagName === 'math') && currentNode.querySelectorAll('p, br').length !== 0) {
711
+ _forceRemove(currentNode);
712
+ return true;
713
+ }
714
+
684
715
  /* Remove element if anything forbids its presence */
685
716
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
686
717
  /* Keep content except for black-listed elements */
@@ -696,34 +727,23 @@ function createDOMPurify() {
696
727
  }
697
728
 
698
729
  /* Remove in case a noscript/noembed XSS is suspected */
699
- if (tagName === 'noscript' && /<\/noscript/i.test(currentNode.innerHTML)) {
730
+ if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
700
731
  _forceRemove(currentNode);
701
732
  return true;
702
733
  }
703
734
 
704
- if (tagName === 'noembed' && /<\/noembed/i.test(currentNode.innerHTML)) {
705
- _forceRemove(currentNode);
706
- return true;
707
- }
708
-
709
- /* Remove in case an mXSS is suspected */
710
- if (currentNode.namespaceURI && /svg|math/i.test(currentNode.namespaceURI) && currentNode.textContent && new RegExp('</' + tagName, 'i').test(currentNode.textContent)) {
711
- _forceRemove(currentNode);
712
- return true;
713
- }
714
-
715
- if ((tagName === 'svg' || tagName === 'math') && (currentNode.querySelectorAll('template') || currentNode.querySelectorAll('svg') || currentNode.querySelectorAll('math'))) {
735
+ if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
716
736
  _forceRemove(currentNode);
717
737
  return true;
718
738
  }
719
739
 
720
740
  /* Convert markup to cover jQuery behavior */
721
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
722
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
741
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && regExpTest(/</g, currentNode.textContent)) {
742
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
723
743
  if (currentNode.innerHTML) {
724
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
744
+ currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '&lt;');
725
745
  } else {
726
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
746
+ currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '&lt;');
727
747
  }
728
748
  }
729
749
 
@@ -731,10 +751,10 @@ function createDOMPurify() {
731
751
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
732
752
  /* Get the element's text content */
733
753
  content = currentNode.textContent;
734
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
735
- content = content.replace(ERB_EXPR$$1, ' ');
754
+ content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
755
+ content = stringReplace(content, ERB_EXPR$$1, ' ');
736
756
  if (currentNode.textContent !== content) {
737
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
757
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
738
758
  currentNode.textContent = content;
739
759
  }
740
760
  }
@@ -764,9 +784,9 @@ function createDOMPurify() {
764
784
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
765
785
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
766
786
  We don't need to check the value; it's always URI safe. */
767
- if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
787
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
768
788
  // This attribute is safe
769
- } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
789
+ } else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
770
790
  // This attribute is safe
771
791
  /* Otherwise, check the name is permitted */
772
792
  } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
@@ -777,16 +797,16 @@ function createDOMPurify() {
777
797
  // This attribute is safe
778
798
  /* Check no script, data or unknown possibly unsafe URI
779
799
  unless we know URI values are safe for that attribute */
780
- } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
800
+ } else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
781
801
  // This attribute is safe
782
802
  /* Keep image data URIs alive if src/xlink:href is allowed */
783
803
  /* Further prevent gadget XSS for dynamically built script tags */
784
- } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {
804
+ } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
785
805
  // This attribute is safe
786
806
  /* Allow unknown protocols: This provides support for links that
787
807
  are handled by protocol handlers which may be unknown ahead of
788
808
  time, e.g. fb:, spotify: */
789
- } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
809
+ } else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
790
810
  // This attribute is safe
791
811
  /* Check for binary attributes */
792
812
  // eslint-disable-next-line no-negated-condition
@@ -843,21 +863,19 @@ function createDOMPurify() {
843
863
  name = _attr.name,
844
864
  namespaceURI = _attr.namespaceURI;
845
865
 
846
- value = attr.value.trim();
847
- lcName = name.toLowerCase();
866
+ value = stringTrim(attr.value);
867
+ lcName = stringToLowerCase(name);
848
868
 
849
869
  /* Execute a hook if present */
850
870
  hookEvent.attrName = lcName;
851
871
  hookEvent.attrValue = value;
852
872
  hookEvent.keepAttr = true;
873
+ hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
853
874
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
854
875
  value = hookEvent.attrValue;
855
-
856
- /* Check for possible Chrome mXSS, least aggressively */
857
- if (ALLOWED_TAGS.svg && !FORBID_TAGS.svg || ALLOWED_TAGS.math && !FORBID_TAGS.math) {
858
- if (removeSVGAttr && /<\//.test(value)) {
859
- _forceRemove(currentNode);
860
- }
876
+ /* Did the hooks approve of the attribute? */
877
+ if (hookEvent.forceKeepAttr) {
878
+ continue;
861
879
  }
862
880
 
863
881
  /* Remove attribute */
@@ -866,10 +884,10 @@ function createDOMPurify() {
866
884
  // attribute at the time.
867
885
  if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
868
886
  idAttr = attributes.id;
869
- attributes = apply(arraySlice, attributes, []);
887
+ attributes = arraySlice(attributes, []);
870
888
  _removeAttribute('id', currentNode);
871
889
  _removeAttribute(name, currentNode);
872
- if (attributes.indexOf(idAttr) > l) {
890
+ if (arrayIndexOf(attributes, idAttr) > l) {
873
891
  currentNode.setAttribute('id', idAttr.value);
874
892
  }
875
893
  } else if (
@@ -893,10 +911,22 @@ function createDOMPurify() {
893
911
  continue;
894
912
  }
895
913
 
914
+ /* Work around a security issue in jQuery 3.0 */
915
+ if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
916
+ _removeAttribute(name, currentNode);
917
+ continue;
918
+ }
919
+
920
+ /* Take care of an mXSS pattern using namespace switches */
921
+ if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
922
+ _removeAttribute(name, currentNode);
923
+ continue;
924
+ }
925
+
896
926
  /* Sanitize attribute content to be template-safe */
897
927
  if (SAFE_FOR_TEMPLATES) {
898
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
899
- value = value.replace(ERB_EXPR$$1, ' ');
928
+ value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
929
+ value = stringReplace(value, ERB_EXPR$$1, ' ');
900
930
  }
901
931
 
902
932
  /* Is `value` valid for this attribute? */
@@ -914,7 +944,7 @@ function createDOMPurify() {
914
944
  currentNode.setAttribute(name, value);
915
945
  }
916
946
 
917
- DOMPurify.removed.pop();
947
+ arrayPop(DOMPurify.removed);
918
948
  } catch (error) {}
919
949
  }
920
950
 
@@ -981,11 +1011,11 @@ function createDOMPurify() {
981
1011
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
982
1012
  // eslint-disable-next-line no-negated-condition
983
1013
  if (typeof dirty.toString !== 'function') {
984
- throw new TypeError('toString is not a function');
1014
+ throw typeErrorCreate('toString is not a function');
985
1015
  } else {
986
1016
  dirty = dirty.toString();
987
1017
  if (typeof dirty !== 'string') {
988
- throw new TypeError('dirty is not a string, aborting');
1018
+ throw typeErrorCreate('dirty is not a string, aborting');
989
1019
  }
990
1020
  }
991
1021
  }
@@ -1013,6 +1043,11 @@ function createDOMPurify() {
1013
1043
  /* Clean up removed elements */
1014
1044
  DOMPurify.removed = [];
1015
1045
 
1046
+ /* Check if dirty is correctly typed for IN_PLACE */
1047
+ if (typeof dirty === 'string') {
1048
+ IN_PLACE = false;
1049
+ }
1050
+
1016
1051
  if (IN_PLACE) {
1017
1052
  /* No special handling necessary for in-place sanitization */
1018
1053
  } else if (dirty instanceof Node) {
@@ -1111,8 +1146,8 @@ function createDOMPurify() {
1111
1146
 
1112
1147
  /* Sanitize final string template-safe */
1113
1148
  if (SAFE_FOR_TEMPLATES) {
1114
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1115
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1149
+ serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
1150
+ serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
1116
1151
  }
1117
1152
 
1118
1153
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
@@ -1155,8 +1190,8 @@ function createDOMPurify() {
1155
1190
  _parseConfig({});
1156
1191
  }
1157
1192
 
1158
- var lcTag = tag.toLowerCase();
1159
- var lcName = attr.toLowerCase();
1193
+ var lcTag = stringToLowerCase(tag);
1194
+ var lcName = stringToLowerCase(attr);
1160
1195
  return _isValidAttribute(lcTag, lcName, value);
1161
1196
  };
1162
1197
 
@@ -1173,7 +1208,7 @@ function createDOMPurify() {
1173
1208
  }
1174
1209
 
1175
1210
  hooks[entryPoint] = hooks[entryPoint] || [];
1176
- hooks[entryPoint].push(hookFunction);
1211
+ arrayPush(hooks[entryPoint], hookFunction);
1177
1212
  };
1178
1213
 
1179
1214
  /**
@@ -1185,7 +1220,7 @@ function createDOMPurify() {
1185
1220
  */
1186
1221
  DOMPurify.removeHook = function (entryPoint) {
1187
1222
  if (hooks[entryPoint]) {
1188
- hooks[entryPoint].pop();
1223
+ arrayPop(hooks[entryPoint]);
1189
1224
  }
1190
1225
  };
1191
1226