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.
@@ -1,41 +1,77 @@
1
1
  'use strict';
2
2
 
3
- var freeze$1 = Object.freeze || function (x) {
4
- return x;
5
- };
3
+ 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); } }
6
4
 
7
- 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']);
5
+ var hasOwnProperty = Object.hasOwnProperty;
6
+ var setPrototypeOf = Object.setPrototypeOf;
7
+ var isFrozen = Object.isFrozen;
8
+ var objectKeys = Object.keys;
9
+ var freeze = Object.freeze;
10
+ var seal = Object.seal; // eslint-disable-line import/no-mutable-exports
8
11
 
9
- // SVG
10
- 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']);
12
+ var _ref = typeof Reflect !== 'undefined' && Reflect;
13
+ var apply = _ref.apply;
14
+ var construct = _ref.construct;
11
15
 
12
- 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']);
16
+ if (!apply) {
17
+ apply = function apply(fun, thisValue, args) {
18
+ return fun.apply(thisValue, args);
19
+ };
20
+ }
13
21
 
14
- 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']);
22
+ if (!freeze) {
23
+ freeze = function freeze(x) {
24
+ return x;
25
+ };
26
+ }
15
27
 
16
- var text = freeze$1(['#text']);
28
+ if (!seal) {
29
+ seal = function seal(x) {
30
+ return x;
31
+ };
32
+ }
17
33
 
18
- var freeze$2 = Object.freeze || function (x) {
19
- return x;
20
- };
34
+ if (!construct) {
35
+ construct = function construct(Func, args) {
36
+ return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
37
+ };
38
+ }
21
39
 
22
- 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']);
40
+ var arrayForEach = unapply(Array.prototype.forEach);
41
+ var arrayIndexOf = unapply(Array.prototype.indexOf);
42
+ var arrayJoin = unapply(Array.prototype.join);
43
+ var arrayPop = unapply(Array.prototype.pop);
44
+ var arrayPush = unapply(Array.prototype.push);
45
+ var arraySlice = unapply(Array.prototype.slice);
23
46
 
24
- 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']);
47
+ var stringToLowerCase = unapply(String.prototype.toLowerCase);
48
+ var stringMatch = unapply(String.prototype.match);
49
+ var stringReplace = unapply(String.prototype.replace);
50
+ var stringIndexOf = unapply(String.prototype.indexOf);
51
+ var stringTrim = unapply(String.prototype.trim);
25
52
 
26
- 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']);
53
+ var regExpTest = unapply(RegExp.prototype.test);
54
+ var regExpCreate = unconstruct(RegExp);
27
55
 
28
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
56
+ var typeErrorCreate = unconstruct(TypeError);
29
57
 
30
- var hasOwnProperty = Object.hasOwnProperty;
31
- var setPrototypeOf = Object.setPrototypeOf;
58
+ function unapply(func) {
59
+ return function (thisArg) {
60
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
61
+ args[_key - 1] = arguments[_key];
62
+ }
63
+
64
+ return apply(func, thisArg, args);
65
+ };
66
+ }
32
67
 
33
- var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
34
- var apply$1 = _ref$1.apply;
68
+ function unconstruct(func) {
69
+ return function () {
70
+ for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
71
+ args[_key2] = arguments[_key2];
72
+ }
35
73
 
36
- if (!apply$1) {
37
- apply$1 = function apply(fun, thisValue, args) {
38
- return fun.apply(thisValue, args);
74
+ return construct(func, args);
39
75
  };
40
76
  }
41
77
 
@@ -52,10 +88,10 @@ function addToSet(set, array) {
52
88
  while (l--) {
53
89
  var element = array[l];
54
90
  if (typeof element === 'string') {
55
- var lcElement = element.toLowerCase();
91
+ var lcElement = stringToLowerCase(element);
56
92
  if (lcElement !== element) {
57
93
  // Config presets (e.g. tags.js, attrs.js) are immutable.
58
- if (!Object.isFrozen(array)) {
94
+ if (!isFrozen(array)) {
59
95
  array[l] = lcElement;
60
96
  }
61
97
 
@@ -75,7 +111,7 @@ function clone(object) {
75
111
 
76
112
  var property = void 0;
77
113
  for (property in object) {
78
- if (apply$1(hasOwnProperty, object, [property])) {
114
+ if (apply(hasOwnProperty, object, [property])) {
79
115
  newObject[property] = object[property];
80
116
  }
81
117
  }
@@ -83,9 +119,24 @@ function clone(object) {
83
119
  return newObject;
84
120
  }
85
121
 
86
- var seal = Object.seal || function (x) {
87
- return x;
88
- };
122
+ 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']);
123
+
124
+ // SVG
125
+ 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']);
126
+
127
+ 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']);
128
+
129
+ 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']);
130
+
131
+ var text = freeze(['#text']);
132
+
133
+ 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']);
134
+
135
+ 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']);
136
+
137
+ 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']);
138
+
139
+ var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
89
140
 
90
141
  var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
91
142
  var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
@@ -101,22 +152,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
101
152
 
102
153
  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); } }
103
154
 
104
- var _ref = typeof Reflect !== 'undefined' && Reflect;
105
- var apply = _ref.apply;
106
-
107
- var arraySlice = Array.prototype.slice;
108
- var freeze = Object.freeze;
109
-
110
155
  var getGlobal = function getGlobal() {
111
156
  return typeof window === 'undefined' ? null : window;
112
157
  };
113
158
 
114
- if (!apply) {
115
- apply = function apply(fun, thisValue, args) {
116
- return fun.apply(thisValue, args);
117
- };
118
- }
119
-
120
159
  /**
121
160
  * Creates a no-op policy for internal use only.
122
161
  * Don't export this function outside this module!
@@ -167,7 +206,7 @@ function createDOMPurify() {
167
206
  * Version label, exposed for easier checks
168
207
  * if DOMPurify is up to date or not
169
208
  */
170
- DOMPurify.version = '2.0.4';
209
+ DOMPurify.version = '2.0.8';
171
210
 
172
211
  /**
173
212
  * Array of elements that DOMPurify removed during sanitation.
@@ -185,7 +224,6 @@ function createDOMPurify() {
185
224
 
186
225
  var originalDocument = window.document;
187
226
  var useDOMParser = false;
188
- var removeSVGAttr = false;
189
227
  var removeTitle = false;
190
228
 
191
229
  var document = window.document;
@@ -198,7 +236,7 @@ function createDOMPurify() {
198
236
  Text = window.Text,
199
237
  Comment = window.Comment,
200
238
  DOMParser = window.DOMParser,
201
- TrustedTypes = window.TrustedTypes;
239
+ trustedTypes = window.trustedTypes;
202
240
 
203
241
  // As per issue #47, the web-components registry is inherited by a
204
242
  // new document created via createHTMLDocument. As per the spec
@@ -214,7 +252,7 @@ function createDOMPurify() {
214
252
  }
215
253
  }
216
254
 
217
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
255
+ var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
218
256
  var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
219
257
 
220
258
  var _document = document,
@@ -321,7 +359,7 @@ function createDOMPurify() {
321
359
  var USE_PROFILES = {};
322
360
 
323
361
  /* Tags to ignore content of when KEEP_CONTENT is true */
324
- var FORBID_CONTENTS = addToSet({}, ['audio', 'colgroup', 'head', 'math', 'script', 'style', 'template', 'thead', 'svg', 'video']);
362
+ 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']);
325
363
 
326
364
  /* Tags that are safe for data: URIs */
327
365
  var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
@@ -375,9 +413,7 @@ function createDOMPurify() {
375
413
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
376
414
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
377
415
  IN_PLACE = cfg.IN_PLACE || false; // Default false
378
-
379
416
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
380
-
381
417
  if (SAFE_FOR_TEMPLATES) {
382
418
  ALLOW_DATA_ATTR = false;
383
419
  }
@@ -466,7 +502,7 @@ function createDOMPurify() {
466
502
  * @param {Node} node a DOM node
467
503
  */
468
504
  var _forceRemove = function _forceRemove(node) {
469
- DOMPurify.removed.push({ element: node });
505
+ arrayPush(DOMPurify.removed, { element: node });
470
506
  try {
471
507
  node.parentNode.removeChild(node);
472
508
  } catch (error) {
@@ -482,12 +518,12 @@ function createDOMPurify() {
482
518
  */
483
519
  var _removeAttribute = function _removeAttribute(name, node) {
484
520
  try {
485
- DOMPurify.removed.push({
521
+ arrayPush(DOMPurify.removed, {
486
522
  attribute: node.getAttributeNode(name),
487
523
  from: node
488
524
  });
489
525
  } catch (error) {
490
- DOMPurify.removed.push({
526
+ arrayPush(DOMPurify.removed, {
491
527
  attribute: null,
492
528
  from: node
493
529
  });
@@ -511,17 +547,15 @@ function createDOMPurify() {
511
547
  dirty = '<remove></remove>' + dirty;
512
548
  } else {
513
549
  /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
514
- var matches = dirty.match(/^[\s]+/);
550
+ var matches = stringMatch(dirty, /^[\s]+/);
515
551
  leadingWhitespace = matches && matches[0];
516
- if (leadingWhitespace) {
517
- dirty = dirty.slice(leadingWhitespace.length);
518
- }
519
552
  }
520
553
 
554
+ var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
521
555
  /* Use DOMParser to workaround Firefox bug (see comment below) */
522
556
  if (useDOMParser) {
523
557
  try {
524
- doc = new DOMParser().parseFromString(dirty, 'text/html');
558
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
525
559
  } catch (error) {}
526
560
  }
527
561
 
@@ -538,10 +572,10 @@ function createDOMPurify() {
538
572
  body = _doc.body;
539
573
 
540
574
  body.parentNode.removeChild(body.parentNode.firstElementChild);
541
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
575
+ body.outerHTML = dirtyPayload;
542
576
  }
543
577
 
544
- if (leadingWhitespace) {
578
+ if (dirty && leadingWhitespace) {
545
579
  doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
546
580
  }
547
581
 
@@ -571,20 +605,11 @@ function createDOMPurify() {
571
605
  (function () {
572
606
  try {
573
607
  var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
574
- if (/<\/title/.test(doc.querySelector('title').innerHTML)) {
608
+ if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
575
609
  removeTitle = true;
576
610
  }
577
611
  } catch (error) {}
578
612
  })();
579
-
580
- (function () {
581
- try {
582
- var doc = _initDocument('<svg></p></svg>');
583
- if (doc.querySelector('svg p')) {
584
- removeSVGAttr = true;
585
- }
586
- } catch (error) {}
587
- })();
588
613
  }
589
614
 
590
615
  /**
@@ -640,7 +665,7 @@ function createDOMPurify() {
640
665
  return;
641
666
  }
642
667
 
643
- hooks[entryPoint].forEach(function (hook) {
668
+ arrayForEach(hooks[entryPoint], function (hook) {
644
669
  hook.call(DOMPurify, currentNode, data, CONFIG);
645
670
  });
646
671
  };
@@ -669,7 +694,7 @@ function createDOMPurify() {
669
694
  }
670
695
 
671
696
  /* Now let's check the element's type and name */
672
- var tagName = currentNode.nodeName.toLowerCase();
697
+ var tagName = stringToLowerCase(currentNode.nodeName);
673
698
 
674
699
  /* Execute a hook if present */
675
700
  _executeHook('uponSanitizeElement', currentNode, {
@@ -677,6 +702,12 @@ function createDOMPurify() {
677
702
  allowedTags: ALLOWED_TAGS
678
703
  });
679
704
 
705
+ /* Take care of an mXSS pattern using p, br inside svg, math */
706
+ if ((tagName === 'svg' || tagName === 'math') && currentNode.querySelectorAll('p, br').length !== 0) {
707
+ _forceRemove(currentNode);
708
+ return true;
709
+ }
710
+
680
711
  /* Remove element if anything forbids its presence */
681
712
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
682
713
  /* Keep content except for black-listed elements */
@@ -692,34 +723,23 @@ function createDOMPurify() {
692
723
  }
693
724
 
694
725
  /* Remove in case a noscript/noembed XSS is suspected */
695
- if (tagName === 'noscript' && /<\/noscript/i.test(currentNode.innerHTML)) {
726
+ if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
696
727
  _forceRemove(currentNode);
697
728
  return true;
698
729
  }
699
730
 
700
- if (tagName === 'noembed' && /<\/noembed/i.test(currentNode.innerHTML)) {
701
- _forceRemove(currentNode);
702
- return true;
703
- }
704
-
705
- /* Remove in case an mXSS is suspected */
706
- if (currentNode.namespaceURI && /svg|math/i.test(currentNode.namespaceURI) && currentNode.textContent && new RegExp('</' + tagName, 'i').test(currentNode.textContent)) {
707
- _forceRemove(currentNode);
708
- return true;
709
- }
710
-
711
- if ((tagName === 'svg' || tagName === 'math') && (currentNode.querySelectorAll('template') || currentNode.querySelectorAll('svg') || currentNode.querySelectorAll('math'))) {
731
+ if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
712
732
  _forceRemove(currentNode);
713
733
  return true;
714
734
  }
715
735
 
716
736
  /* Convert markup to cover jQuery behavior */
717
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
718
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
737
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && regExpTest(/</g, currentNode.textContent)) {
738
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
719
739
  if (currentNode.innerHTML) {
720
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
740
+ currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '&lt;');
721
741
  } else {
722
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
742
+ currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '&lt;');
723
743
  }
724
744
  }
725
745
 
@@ -727,10 +747,10 @@ function createDOMPurify() {
727
747
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
728
748
  /* Get the element's text content */
729
749
  content = currentNode.textContent;
730
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
731
- content = content.replace(ERB_EXPR$$1, ' ');
750
+ content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
751
+ content = stringReplace(content, ERB_EXPR$$1, ' ');
732
752
  if (currentNode.textContent !== content) {
733
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
753
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
734
754
  currentNode.textContent = content;
735
755
  }
736
756
  }
@@ -760,9 +780,9 @@ function createDOMPurify() {
760
780
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
761
781
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
762
782
  We don't need to check the value; it's always URI safe. */
763
- if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
783
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
764
784
  // This attribute is safe
765
- } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
785
+ } else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
766
786
  // This attribute is safe
767
787
  /* Otherwise, check the name is permitted */
768
788
  } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
@@ -773,16 +793,16 @@ function createDOMPurify() {
773
793
  // This attribute is safe
774
794
  /* Check no script, data or unknown possibly unsafe URI
775
795
  unless we know URI values are safe for that attribute */
776
- } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
796
+ } else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
777
797
  // This attribute is safe
778
798
  /* Keep image data URIs alive if src/xlink:href is allowed */
779
799
  /* Further prevent gadget XSS for dynamically built script tags */
780
- } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {
800
+ } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
781
801
  // This attribute is safe
782
802
  /* Allow unknown protocols: This provides support for links that
783
803
  are handled by protocol handlers which may be unknown ahead of
784
804
  time, e.g. fb:, spotify: */
785
- } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
805
+ } else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
786
806
  // This attribute is safe
787
807
  /* Check for binary attributes */
788
808
  // eslint-disable-next-line no-negated-condition
@@ -839,21 +859,19 @@ function createDOMPurify() {
839
859
  name = _attr.name,
840
860
  namespaceURI = _attr.namespaceURI;
841
861
 
842
- value = attr.value.trim();
843
- lcName = name.toLowerCase();
862
+ value = stringTrim(attr.value);
863
+ lcName = stringToLowerCase(name);
844
864
 
845
865
  /* Execute a hook if present */
846
866
  hookEvent.attrName = lcName;
847
867
  hookEvent.attrValue = value;
848
868
  hookEvent.keepAttr = true;
869
+ hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
849
870
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
850
871
  value = hookEvent.attrValue;
851
-
852
- /* Check for possible Chrome mXSS, least aggressively */
853
- if (ALLOWED_TAGS.svg && !FORBID_TAGS.svg || ALLOWED_TAGS.math && !FORBID_TAGS.math) {
854
- if (removeSVGAttr && /<\//.test(value)) {
855
- _forceRemove(currentNode);
856
- }
872
+ /* Did the hooks approve of the attribute? */
873
+ if (hookEvent.forceKeepAttr) {
874
+ continue;
857
875
  }
858
876
 
859
877
  /* Remove attribute */
@@ -862,10 +880,10 @@ function createDOMPurify() {
862
880
  // attribute at the time.
863
881
  if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
864
882
  idAttr = attributes.id;
865
- attributes = apply(arraySlice, attributes, []);
883
+ attributes = arraySlice(attributes, []);
866
884
  _removeAttribute('id', currentNode);
867
885
  _removeAttribute(name, currentNode);
868
- if (attributes.indexOf(idAttr) > l) {
886
+ if (arrayIndexOf(attributes, idAttr) > l) {
869
887
  currentNode.setAttribute('id', idAttr.value);
870
888
  }
871
889
  } else if (
@@ -889,10 +907,22 @@ function createDOMPurify() {
889
907
  continue;
890
908
  }
891
909
 
910
+ /* Work around a security issue in jQuery 3.0 */
911
+ if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
912
+ _removeAttribute(name, currentNode);
913
+ continue;
914
+ }
915
+
916
+ /* Take care of an mXSS pattern using namespace switches */
917
+ if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
918
+ _removeAttribute(name, currentNode);
919
+ continue;
920
+ }
921
+
892
922
  /* Sanitize attribute content to be template-safe */
893
923
  if (SAFE_FOR_TEMPLATES) {
894
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
895
- value = value.replace(ERB_EXPR$$1, ' ');
924
+ value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
925
+ value = stringReplace(value, ERB_EXPR$$1, ' ');
896
926
  }
897
927
 
898
928
  /* Is `value` valid for this attribute? */
@@ -910,7 +940,7 @@ function createDOMPurify() {
910
940
  currentNode.setAttribute(name, value);
911
941
  }
912
942
 
913
- DOMPurify.removed.pop();
943
+ arrayPop(DOMPurify.removed);
914
944
  } catch (error) {}
915
945
  }
916
946
 
@@ -977,11 +1007,11 @@ function createDOMPurify() {
977
1007
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
978
1008
  // eslint-disable-next-line no-negated-condition
979
1009
  if (typeof dirty.toString !== 'function') {
980
- throw new TypeError('toString is not a function');
1010
+ throw typeErrorCreate('toString is not a function');
981
1011
  } else {
982
1012
  dirty = dirty.toString();
983
1013
  if (typeof dirty !== 'string') {
984
- throw new TypeError('dirty is not a string, aborting');
1014
+ throw typeErrorCreate('dirty is not a string, aborting');
985
1015
  }
986
1016
  }
987
1017
  }
@@ -1009,6 +1039,11 @@ function createDOMPurify() {
1009
1039
  /* Clean up removed elements */
1010
1040
  DOMPurify.removed = [];
1011
1041
 
1042
+ /* Check if dirty is correctly typed for IN_PLACE */
1043
+ if (typeof dirty === 'string') {
1044
+ IN_PLACE = false;
1045
+ }
1046
+
1012
1047
  if (IN_PLACE) {
1013
1048
  /* No special handling necessary for in-place sanitization */
1014
1049
  } else if (dirty instanceof Node) {
@@ -1107,8 +1142,8 @@ function createDOMPurify() {
1107
1142
 
1108
1143
  /* Sanitize final string template-safe */
1109
1144
  if (SAFE_FOR_TEMPLATES) {
1110
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1111
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1145
+ serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
1146
+ serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
1112
1147
  }
1113
1148
 
1114
1149
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
@@ -1151,8 +1186,8 @@ function createDOMPurify() {
1151
1186
  _parseConfig({});
1152
1187
  }
1153
1188
 
1154
- var lcTag = tag.toLowerCase();
1155
- var lcName = attr.toLowerCase();
1189
+ var lcTag = stringToLowerCase(tag);
1190
+ var lcName = stringToLowerCase(attr);
1156
1191
  return _isValidAttribute(lcTag, lcName, value);
1157
1192
  };
1158
1193
 
@@ -1169,7 +1204,7 @@ function createDOMPurify() {
1169
1204
  }
1170
1205
 
1171
1206
  hooks[entryPoint] = hooks[entryPoint] || [];
1172
- hooks[entryPoint].push(hookFunction);
1207
+ arrayPush(hooks[entryPoint], hookFunction);
1173
1208
  };
1174
1209
 
1175
1210
  /**
@@ -1181,7 +1216,7 @@ function createDOMPurify() {
1181
1216
  */
1182
1217
  DOMPurify.removeHook = function (entryPoint) {
1183
1218
  if (hooks[entryPoint]) {
1184
- hooks[entryPoint].pop();
1219
+ arrayPop(hooks[entryPoint]);
1185
1220
  }
1186
1221
  };
1187
1222