dompurify 2.0.7 → 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
+ }
25
+
26
+ if (!freeze) {
27
+ freeze = function freeze(x) {
28
+ return x;
29
+ };
30
+ }
17
31
 
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']);
32
+ if (!seal) {
33
+ seal = function seal(x) {
34
+ return x;
35
+ };
36
+ }
19
37
 
20
- var text = freeze$1(['#text']);
38
+ if (!construct) {
39
+ construct = function construct(Func, args) {
40
+ return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
41
+ };
42
+ }
21
43
 
22
- var freeze$2 = Object.freeze || function (x) {
23
- return x;
24
- };
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);
25
50
 
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']);
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);
27
56
 
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']);
57
+ var regExpTest = unapply(RegExp.prototype.test);
58
+ var regExpCreate = unconstruct(RegExp);
29
59
 
30
- var mathMl$1 = freeze$2(['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']);
60
+ var typeErrorCreate = unconstruct(TypeError);
31
61
 
32
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
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
+ }
33
67
 
34
- var hasOwnProperty = Object.hasOwnProperty;
35
- var setPrototypeOf = Object.setPrototypeOf;
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.7';
213
+ DOMPurify.version = '2.0.8';
175
214
 
176
215
  /**
177
216
  * Array of elements that DOMPurify removed during sanitation.
@@ -201,7 +240,7 @@ function createDOMPurify() {
201
240
  Text = window.Text,
202
241
  Comment = window.Comment,
203
242
  DOMParser = window.DOMParser,
204
- TrustedTypes = window.TrustedTypes;
243
+ trustedTypes = window.trustedTypes;
205
244
 
206
245
  // As per issue #47, the web-components registry is inherited by a
207
246
  // new document created via createHTMLDocument. As per the spec
@@ -217,7 +256,7 @@ function createDOMPurify() {
217
256
  }
218
257
  }
219
258
 
220
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
259
+ var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
221
260
  var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
222
261
 
223
262
  var _document = document,
@@ -378,9 +417,7 @@ function createDOMPurify() {
378
417
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
379
418
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
380
419
  IN_PLACE = cfg.IN_PLACE || false; // Default false
381
-
382
420
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
383
-
384
421
  if (SAFE_FOR_TEMPLATES) {
385
422
  ALLOW_DATA_ATTR = false;
386
423
  }
@@ -469,7 +506,7 @@ function createDOMPurify() {
469
506
  * @param {Node} node a DOM node
470
507
  */
471
508
  var _forceRemove = function _forceRemove(node) {
472
- DOMPurify.removed.push({ element: node });
509
+ arrayPush(DOMPurify.removed, { element: node });
473
510
  try {
474
511
  node.parentNode.removeChild(node);
475
512
  } catch (error) {
@@ -485,12 +522,12 @@ function createDOMPurify() {
485
522
  */
486
523
  var _removeAttribute = function _removeAttribute(name, node) {
487
524
  try {
488
- DOMPurify.removed.push({
525
+ arrayPush(DOMPurify.removed, {
489
526
  attribute: node.getAttributeNode(name),
490
527
  from: node
491
528
  });
492
529
  } catch (error) {
493
- DOMPurify.removed.push({
530
+ arrayPush(DOMPurify.removed, {
494
531
  attribute: null,
495
532
  from: node
496
533
  });
@@ -514,17 +551,15 @@ function createDOMPurify() {
514
551
  dirty = '<remove></remove>' + dirty;
515
552
  } else {
516
553
  /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
517
- var matches = dirty.match(/^[\s]+/);
554
+ var matches = stringMatch(dirty, /^[\s]+/);
518
555
  leadingWhitespace = matches && matches[0];
519
- if (leadingWhitespace) {
520
- dirty = dirty.slice(leadingWhitespace.length);
521
- }
522
556
  }
523
557
 
558
+ var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
524
559
  /* Use DOMParser to workaround Firefox bug (see comment below) */
525
560
  if (useDOMParser) {
526
561
  try {
527
- doc = new DOMParser().parseFromString(dirty, 'text/html');
562
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
528
563
  } catch (error) {}
529
564
  }
530
565
 
@@ -541,7 +576,7 @@ function createDOMPurify() {
541
576
  body = _doc.body;
542
577
 
543
578
  body.parentNode.removeChild(body.parentNode.firstElementChild);
544
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
579
+ body.outerHTML = dirtyPayload;
545
580
  }
546
581
 
547
582
  if (dirty && leadingWhitespace) {
@@ -574,7 +609,7 @@ function createDOMPurify() {
574
609
  (function () {
575
610
  try {
576
611
  var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
577
- if (/<\/title/.test(doc.querySelector('title').innerHTML)) {
612
+ if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
578
613
  removeTitle = true;
579
614
  }
580
615
  } catch (error) {}
@@ -634,7 +669,7 @@ function createDOMPurify() {
634
669
  return;
635
670
  }
636
671
 
637
- hooks[entryPoint].forEach(function (hook) {
672
+ arrayForEach(hooks[entryPoint], function (hook) {
638
673
  hook.call(DOMPurify, currentNode, data, CONFIG);
639
674
  });
640
675
  };
@@ -663,7 +698,7 @@ function createDOMPurify() {
663
698
  }
664
699
 
665
700
  /* Now let's check the element's type and name */
666
- var tagName = currentNode.nodeName.toLowerCase();
701
+ var tagName = stringToLowerCase(currentNode.nodeName);
667
702
 
668
703
  /* Execute a hook if present */
669
704
  _executeHook('uponSanitizeElement', currentNode, {
@@ -692,23 +727,23 @@ function createDOMPurify() {
692
727
  }
693
728
 
694
729
  /* Remove in case a noscript/noembed XSS is suspected */
695
- if (tagName === 'noscript' && /<\/noscript/i.test(currentNode.innerHTML)) {
730
+ if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
696
731
  _forceRemove(currentNode);
697
732
  return true;
698
733
  }
699
734
 
700
- if (tagName === 'noembed' && /<\/noembed/i.test(currentNode.innerHTML)) {
735
+ if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
701
736
  _forceRemove(currentNode);
702
737
  return true;
703
738
  }
704
739
 
705
740
  /* Convert markup to cover jQuery behavior */
706
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
707
- 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() });
708
743
  if (currentNode.innerHTML) {
709
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
744
+ currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '&lt;');
710
745
  } else {
711
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
746
+ currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '&lt;');
712
747
  }
713
748
  }
714
749
 
@@ -716,10 +751,10 @@ function createDOMPurify() {
716
751
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
717
752
  /* Get the element's text content */
718
753
  content = currentNode.textContent;
719
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
720
- content = content.replace(ERB_EXPR$$1, ' ');
754
+ content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
755
+ content = stringReplace(content, ERB_EXPR$$1, ' ');
721
756
  if (currentNode.textContent !== content) {
722
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
757
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
723
758
  currentNode.textContent = content;
724
759
  }
725
760
  }
@@ -749,9 +784,9 @@ function createDOMPurify() {
749
784
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
750
785
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
751
786
  We don't need to check the value; it's always URI safe. */
752
- if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
787
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
753
788
  // This attribute is safe
754
- } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
789
+ } else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
755
790
  // This attribute is safe
756
791
  /* Otherwise, check the name is permitted */
757
792
  } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
@@ -762,16 +797,16 @@ function createDOMPurify() {
762
797
  // This attribute is safe
763
798
  /* Check no script, data or unknown possibly unsafe URI
764
799
  unless we know URI values are safe for that attribute */
765
- } 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, ''))) {
766
801
  // This attribute is safe
767
802
  /* Keep image data URIs alive if src/xlink:href is allowed */
768
803
  /* Further prevent gadget XSS for dynamically built script tags */
769
- } 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]) {
770
805
  // This attribute is safe
771
806
  /* Allow unknown protocols: This provides support for links that
772
807
  are handled by protocol handlers which may be unknown ahead of
773
808
  time, e.g. fb:, spotify: */
774
- } 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, ''))) {
775
810
  // This attribute is safe
776
811
  /* Check for binary attributes */
777
812
  // eslint-disable-next-line no-negated-condition
@@ -828,15 +863,20 @@ function createDOMPurify() {
828
863
  name = _attr.name,
829
864
  namespaceURI = _attr.namespaceURI;
830
865
 
831
- value = attr.value.trim();
832
- lcName = name.toLowerCase();
866
+ value = stringTrim(attr.value);
867
+ lcName = stringToLowerCase(name);
833
868
 
834
869
  /* Execute a hook if present */
835
870
  hookEvent.attrName = lcName;
836
871
  hookEvent.attrValue = value;
837
872
  hookEvent.keepAttr = true;
873
+ hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
838
874
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
839
875
  value = hookEvent.attrValue;
876
+ /* Did the hooks approve of the attribute? */
877
+ if (hookEvent.forceKeepAttr) {
878
+ continue;
879
+ }
840
880
 
841
881
  /* Remove attribute */
842
882
  // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
@@ -844,10 +884,10 @@ function createDOMPurify() {
844
884
  // attribute at the time.
845
885
  if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
846
886
  idAttr = attributes.id;
847
- attributes = apply(arraySlice, attributes, []);
887
+ attributes = arraySlice(attributes, []);
848
888
  _removeAttribute('id', currentNode);
849
889
  _removeAttribute(name, currentNode);
850
- if (attributes.indexOf(idAttr) > l) {
890
+ if (arrayIndexOf(attributes, idAttr) > l) {
851
891
  currentNode.setAttribute('id', idAttr.value);
852
892
  }
853
893
  } else if (
@@ -871,16 +911,22 @@ function createDOMPurify() {
871
911
  continue;
872
912
  }
873
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
+
874
920
  /* Take care of an mXSS pattern using namespace switches */
875
- if (/svg|math/i.test(currentNode.namespaceURI) && new RegExp('</(' + Object.keys(FORBID_CONTENTS).join('|') + ')', 'i').test(value)) {
921
+ if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
876
922
  _removeAttribute(name, currentNode);
877
923
  continue;
878
924
  }
879
925
 
880
926
  /* Sanitize attribute content to be template-safe */
881
927
  if (SAFE_FOR_TEMPLATES) {
882
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
883
- value = value.replace(ERB_EXPR$$1, ' ');
928
+ value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
929
+ value = stringReplace(value, ERB_EXPR$$1, ' ');
884
930
  }
885
931
 
886
932
  /* Is `value` valid for this attribute? */
@@ -898,7 +944,7 @@ function createDOMPurify() {
898
944
  currentNode.setAttribute(name, value);
899
945
  }
900
946
 
901
- DOMPurify.removed.pop();
947
+ arrayPop(DOMPurify.removed);
902
948
  } catch (error) {}
903
949
  }
904
950
 
@@ -965,11 +1011,11 @@ function createDOMPurify() {
965
1011
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
966
1012
  // eslint-disable-next-line no-negated-condition
967
1013
  if (typeof dirty.toString !== 'function') {
968
- throw new TypeError('toString is not a function');
1014
+ throw typeErrorCreate('toString is not a function');
969
1015
  } else {
970
1016
  dirty = dirty.toString();
971
1017
  if (typeof dirty !== 'string') {
972
- throw new TypeError('dirty is not a string, aborting');
1018
+ throw typeErrorCreate('dirty is not a string, aborting');
973
1019
  }
974
1020
  }
975
1021
  }
@@ -997,6 +1043,11 @@ function createDOMPurify() {
997
1043
  /* Clean up removed elements */
998
1044
  DOMPurify.removed = [];
999
1045
 
1046
+ /* Check if dirty is correctly typed for IN_PLACE */
1047
+ if (typeof dirty === 'string') {
1048
+ IN_PLACE = false;
1049
+ }
1050
+
1000
1051
  if (IN_PLACE) {
1001
1052
  /* No special handling necessary for in-place sanitization */
1002
1053
  } else if (dirty instanceof Node) {
@@ -1095,8 +1146,8 @@ function createDOMPurify() {
1095
1146
 
1096
1147
  /* Sanitize final string template-safe */
1097
1148
  if (SAFE_FOR_TEMPLATES) {
1098
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1099
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1149
+ serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
1150
+ serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
1100
1151
  }
1101
1152
 
1102
1153
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
@@ -1139,8 +1190,8 @@ function createDOMPurify() {
1139
1190
  _parseConfig({});
1140
1191
  }
1141
1192
 
1142
- var lcTag = tag.toLowerCase();
1143
- var lcName = attr.toLowerCase();
1193
+ var lcTag = stringToLowerCase(tag);
1194
+ var lcName = stringToLowerCase(attr);
1144
1195
  return _isValidAttribute(lcTag, lcName, value);
1145
1196
  };
1146
1197
 
@@ -1157,7 +1208,7 @@ function createDOMPurify() {
1157
1208
  }
1158
1209
 
1159
1210
  hooks[entryPoint] = hooks[entryPoint] || [];
1160
- hooks[entryPoint].push(hookFunction);
1211
+ arrayPush(hooks[entryPoint], hookFunction);
1161
1212
  };
1162
1213
 
1163
1214
  /**
@@ -1169,7 +1220,7 @@ function createDOMPurify() {
1169
1220
  */
1170
1221
  DOMPurify.removeHook = function (entryPoint) {
1171
1222
  if (hooks[entryPoint]) {
1172
- hooks[entryPoint].pop();
1223
+ arrayPop(hooks[entryPoint]);
1173
1224
  }
1174
1225
  };
1175
1226