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.es.js CHANGED
@@ -1,39 +1,75 @@
1
- var freeze$1 = Object.freeze || function (x) {
2
- return x;
3
- };
1
+ function _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
4
2
 
5
- var html = freeze$1(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
3
+ var hasOwnProperty = Object.hasOwnProperty;
4
+ var setPrototypeOf = Object.setPrototypeOf;
5
+ var isFrozen = Object.isFrozen;
6
+ var objectKeys = Object.keys;
7
+ var freeze = Object.freeze;
8
+ var seal = Object.seal; // eslint-disable-line import/no-mutable-exports
6
9
 
7
- // SVG
8
- var svg = freeze$1(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern']);
10
+ var _ref = typeof Reflect !== 'undefined' && Reflect;
11
+ var apply = _ref.apply;
12
+ var construct = _ref.construct;
9
13
 
10
- var svgFilters = freeze$1(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
14
+ if (!apply) {
15
+ apply = function apply(fun, thisValue, args) {
16
+ return fun.apply(thisValue, args);
17
+ };
18
+ }
19
+
20
+ if (!freeze) {
21
+ freeze = function freeze(x) {
22
+ return x;
23
+ };
24
+ }
11
25
 
12
- var mathMl = freeze$1(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
26
+ if (!seal) {
27
+ seal = function seal(x) {
28
+ return x;
29
+ };
30
+ }
13
31
 
14
- var text = freeze$1(['#text']);
32
+ if (!construct) {
33
+ construct = function construct(Func, args) {
34
+ return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
35
+ };
36
+ }
15
37
 
16
- var freeze$2 = Object.freeze || function (x) {
17
- return x;
18
- };
38
+ var arrayForEach = unapply(Array.prototype.forEach);
39
+ var arrayIndexOf = unapply(Array.prototype.indexOf);
40
+ var arrayJoin = unapply(Array.prototype.join);
41
+ var arrayPop = unapply(Array.prototype.pop);
42
+ var arrayPush = unapply(Array.prototype.push);
43
+ var arraySlice = unapply(Array.prototype.slice);
19
44
 
20
- var html$1 = freeze$2(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
45
+ var stringToLowerCase = unapply(String.prototype.toLowerCase);
46
+ var stringMatch = unapply(String.prototype.match);
47
+ var stringReplace = unapply(String.prototype.replace);
48
+ var stringIndexOf = unapply(String.prototype.indexOf);
49
+ var stringTrim = unapply(String.prototype.trim);
21
50
 
22
- var svg$1 = freeze$2(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
51
+ var regExpTest = unapply(RegExp.prototype.test);
52
+ var regExpCreate = unconstruct(RegExp);
23
53
 
24
- 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']);
54
+ var typeErrorCreate = unconstruct(TypeError);
25
55
 
26
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
56
+ function unapply(func) {
57
+ return function (thisArg) {
58
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
59
+ args[_key - 1] = arguments[_key];
60
+ }
27
61
 
28
- var hasOwnProperty = Object.hasOwnProperty;
29
- var setPrototypeOf = Object.setPrototypeOf;
62
+ return apply(func, thisArg, args);
63
+ };
64
+ }
30
65
 
31
- var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
32
- var apply$1 = _ref$1.apply;
66
+ function unconstruct(func) {
67
+ return function () {
68
+ for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
69
+ args[_key2] = arguments[_key2];
70
+ }
33
71
 
34
- if (!apply$1) {
35
- apply$1 = function apply(fun, thisValue, args) {
36
- return fun.apply(thisValue, args);
72
+ return construct(func, args);
37
73
  };
38
74
  }
39
75
 
@@ -50,10 +86,10 @@ function addToSet(set, array) {
50
86
  while (l--) {
51
87
  var element = array[l];
52
88
  if (typeof element === 'string') {
53
- var lcElement = element.toLowerCase();
89
+ var lcElement = stringToLowerCase(element);
54
90
  if (lcElement !== element) {
55
91
  // Config presets (e.g. tags.js, attrs.js) are immutable.
56
- if (!Object.isFrozen(array)) {
92
+ if (!isFrozen(array)) {
57
93
  array[l] = lcElement;
58
94
  }
59
95
 
@@ -73,7 +109,7 @@ function clone(object) {
73
109
 
74
110
  var property = void 0;
75
111
  for (property in object) {
76
- if (apply$1(hasOwnProperty, object, [property])) {
112
+ if (apply(hasOwnProperty, object, [property])) {
77
113
  newObject[property] = object[property];
78
114
  }
79
115
  }
@@ -81,9 +117,24 @@ function clone(object) {
81
117
  return newObject;
82
118
  }
83
119
 
84
- var seal = Object.seal || function (x) {
85
- return x;
86
- };
120
+ var html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
121
+
122
+ // SVG
123
+ var svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern']);
124
+
125
+ var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
126
+
127
+ var mathMl = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
128
+
129
+ var text = freeze(['#text']);
130
+
131
+ var html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);
132
+
133
+ var svg$1 = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
134
+
135
+ var mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
136
+
137
+ var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
87
138
 
88
139
  var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
89
140
  var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
@@ -99,22 +150,10 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
99
150
 
100
151
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
101
152
 
102
- var _ref = typeof Reflect !== 'undefined' && Reflect;
103
- var apply = _ref.apply;
104
-
105
- var arraySlice = Array.prototype.slice;
106
- var freeze = Object.freeze;
107
-
108
153
  var getGlobal = function getGlobal() {
109
154
  return typeof window === 'undefined' ? null : window;
110
155
  };
111
156
 
112
- if (!apply) {
113
- apply = function apply(fun, thisValue, args) {
114
- return fun.apply(thisValue, args);
115
- };
116
- }
117
-
118
157
  /**
119
158
  * Creates a no-op policy for internal use only.
120
159
  * Don't export this function outside this module!
@@ -165,7 +204,7 @@ function createDOMPurify() {
165
204
  * Version label, exposed for easier checks
166
205
  * if DOMPurify is up to date or not
167
206
  */
168
- DOMPurify.version = '2.0.7';
207
+ DOMPurify.version = '2.0.8';
169
208
 
170
209
  /**
171
210
  * Array of elements that DOMPurify removed during sanitation.
@@ -195,7 +234,7 @@ function createDOMPurify() {
195
234
  Text = window.Text,
196
235
  Comment = window.Comment,
197
236
  DOMParser = window.DOMParser,
198
- TrustedTypes = window.TrustedTypes;
237
+ trustedTypes = window.trustedTypes;
199
238
 
200
239
  // As per issue #47, the web-components registry is inherited by a
201
240
  // new document created via createHTMLDocument. As per the spec
@@ -211,7 +250,7 @@ function createDOMPurify() {
211
250
  }
212
251
  }
213
252
 
214
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
253
+ var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
215
254
  var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
216
255
 
217
256
  var _document = document,
@@ -372,9 +411,7 @@ function createDOMPurify() {
372
411
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
373
412
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
374
413
  IN_PLACE = cfg.IN_PLACE || false; // Default false
375
-
376
414
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
377
-
378
415
  if (SAFE_FOR_TEMPLATES) {
379
416
  ALLOW_DATA_ATTR = false;
380
417
  }
@@ -463,7 +500,7 @@ function createDOMPurify() {
463
500
  * @param {Node} node a DOM node
464
501
  */
465
502
  var _forceRemove = function _forceRemove(node) {
466
- DOMPurify.removed.push({ element: node });
503
+ arrayPush(DOMPurify.removed, { element: node });
467
504
  try {
468
505
  node.parentNode.removeChild(node);
469
506
  } catch (error) {
@@ -479,12 +516,12 @@ function createDOMPurify() {
479
516
  */
480
517
  var _removeAttribute = function _removeAttribute(name, node) {
481
518
  try {
482
- DOMPurify.removed.push({
519
+ arrayPush(DOMPurify.removed, {
483
520
  attribute: node.getAttributeNode(name),
484
521
  from: node
485
522
  });
486
523
  } catch (error) {
487
- DOMPurify.removed.push({
524
+ arrayPush(DOMPurify.removed, {
488
525
  attribute: null,
489
526
  from: node
490
527
  });
@@ -508,17 +545,15 @@ function createDOMPurify() {
508
545
  dirty = '<remove></remove>' + dirty;
509
546
  } else {
510
547
  /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
511
- var matches = dirty.match(/^[\s]+/);
548
+ var matches = stringMatch(dirty, /^[\s]+/);
512
549
  leadingWhitespace = matches && matches[0];
513
- if (leadingWhitespace) {
514
- dirty = dirty.slice(leadingWhitespace.length);
515
- }
516
550
  }
517
551
 
552
+ var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
518
553
  /* Use DOMParser to workaround Firefox bug (see comment below) */
519
554
  if (useDOMParser) {
520
555
  try {
521
- doc = new DOMParser().parseFromString(dirty, 'text/html');
556
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
522
557
  } catch (error) {}
523
558
  }
524
559
 
@@ -535,7 +570,7 @@ function createDOMPurify() {
535
570
  body = _doc.body;
536
571
 
537
572
  body.parentNode.removeChild(body.parentNode.firstElementChild);
538
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
573
+ body.outerHTML = dirtyPayload;
539
574
  }
540
575
 
541
576
  if (dirty && leadingWhitespace) {
@@ -568,7 +603,7 @@ function createDOMPurify() {
568
603
  (function () {
569
604
  try {
570
605
  var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
571
- if (/<\/title/.test(doc.querySelector('title').innerHTML)) {
606
+ if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
572
607
  removeTitle = true;
573
608
  }
574
609
  } catch (error) {}
@@ -628,7 +663,7 @@ function createDOMPurify() {
628
663
  return;
629
664
  }
630
665
 
631
- hooks[entryPoint].forEach(function (hook) {
666
+ arrayForEach(hooks[entryPoint], function (hook) {
632
667
  hook.call(DOMPurify, currentNode, data, CONFIG);
633
668
  });
634
669
  };
@@ -657,7 +692,7 @@ function createDOMPurify() {
657
692
  }
658
693
 
659
694
  /* Now let's check the element's type and name */
660
- var tagName = currentNode.nodeName.toLowerCase();
695
+ var tagName = stringToLowerCase(currentNode.nodeName);
661
696
 
662
697
  /* Execute a hook if present */
663
698
  _executeHook('uponSanitizeElement', currentNode, {
@@ -686,23 +721,23 @@ function createDOMPurify() {
686
721
  }
687
722
 
688
723
  /* Remove in case a noscript/noembed XSS is suspected */
689
- if (tagName === 'noscript' && /<\/noscript/i.test(currentNode.innerHTML)) {
724
+ if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
690
725
  _forceRemove(currentNode);
691
726
  return true;
692
727
  }
693
728
 
694
- if (tagName === 'noembed' && /<\/noembed/i.test(currentNode.innerHTML)) {
729
+ if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
695
730
  _forceRemove(currentNode);
696
731
  return true;
697
732
  }
698
733
 
699
734
  /* Convert markup to cover jQuery behavior */
700
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
701
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
735
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && regExpTest(/</g, currentNode.textContent)) {
736
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
702
737
  if (currentNode.innerHTML) {
703
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
738
+ currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '&lt;');
704
739
  } else {
705
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
740
+ currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '&lt;');
706
741
  }
707
742
  }
708
743
 
@@ -710,10 +745,10 @@ function createDOMPurify() {
710
745
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
711
746
  /* Get the element's text content */
712
747
  content = currentNode.textContent;
713
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
714
- content = content.replace(ERB_EXPR$$1, ' ');
748
+ content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
749
+ content = stringReplace(content, ERB_EXPR$$1, ' ');
715
750
  if (currentNode.textContent !== content) {
716
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
751
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
717
752
  currentNode.textContent = content;
718
753
  }
719
754
  }
@@ -743,9 +778,9 @@ function createDOMPurify() {
743
778
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
744
779
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
745
780
  We don't need to check the value; it's always URI safe. */
746
- if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
781
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
747
782
  // This attribute is safe
748
- } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
783
+ } else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
749
784
  // This attribute is safe
750
785
  /* Otherwise, check the name is permitted */
751
786
  } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
@@ -756,16 +791,16 @@ function createDOMPurify() {
756
791
  // This attribute is safe
757
792
  /* Check no script, data or unknown possibly unsafe URI
758
793
  unless we know URI values are safe for that attribute */
759
- } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
794
+ } else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
760
795
  // This attribute is safe
761
796
  /* Keep image data URIs alive if src/xlink:href is allowed */
762
797
  /* Further prevent gadget XSS for dynamically built script tags */
763
- } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {
798
+ } else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) {
764
799
  // This attribute is safe
765
800
  /* Allow unknown protocols: This provides support for links that
766
801
  are handled by protocol handlers which may be unknown ahead of
767
802
  time, e.g. fb:, spotify: */
768
- } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
803
+ } else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) {
769
804
  // This attribute is safe
770
805
  /* Check for binary attributes */
771
806
  // eslint-disable-next-line no-negated-condition
@@ -822,15 +857,20 @@ function createDOMPurify() {
822
857
  name = _attr.name,
823
858
  namespaceURI = _attr.namespaceURI;
824
859
 
825
- value = attr.value.trim();
826
- lcName = name.toLowerCase();
860
+ value = stringTrim(attr.value);
861
+ lcName = stringToLowerCase(name);
827
862
 
828
863
  /* Execute a hook if present */
829
864
  hookEvent.attrName = lcName;
830
865
  hookEvent.attrValue = value;
831
866
  hookEvent.keepAttr = true;
867
+ hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
832
868
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
833
869
  value = hookEvent.attrValue;
870
+ /* Did the hooks approve of the attribute? */
871
+ if (hookEvent.forceKeepAttr) {
872
+ continue;
873
+ }
834
874
 
835
875
  /* Remove attribute */
836
876
  // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
@@ -838,10 +878,10 @@ function createDOMPurify() {
838
878
  // attribute at the time.
839
879
  if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
840
880
  idAttr = attributes.id;
841
- attributes = apply(arraySlice, attributes, []);
881
+ attributes = arraySlice(attributes, []);
842
882
  _removeAttribute('id', currentNode);
843
883
  _removeAttribute(name, currentNode);
844
- if (attributes.indexOf(idAttr) > l) {
884
+ if (arrayIndexOf(attributes, idAttr) > l) {
845
885
  currentNode.setAttribute('id', idAttr.value);
846
886
  }
847
887
  } else if (
@@ -865,16 +905,22 @@ function createDOMPurify() {
865
905
  continue;
866
906
  }
867
907
 
908
+ /* Work around a security issue in jQuery 3.0 */
909
+ if (SAFE_FOR_JQUERY && regExpTest(/\/>/i, value)) {
910
+ _removeAttribute(name, currentNode);
911
+ continue;
912
+ }
913
+
868
914
  /* Take care of an mXSS pattern using namespace switches */
869
- if (/svg|math/i.test(currentNode.namespaceURI) && new RegExp('</(' + Object.keys(FORBID_CONTENTS).join('|') + ')', 'i').test(value)) {
915
+ if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
870
916
  _removeAttribute(name, currentNode);
871
917
  continue;
872
918
  }
873
919
 
874
920
  /* Sanitize attribute content to be template-safe */
875
921
  if (SAFE_FOR_TEMPLATES) {
876
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
877
- value = value.replace(ERB_EXPR$$1, ' ');
922
+ value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
923
+ value = stringReplace(value, ERB_EXPR$$1, ' ');
878
924
  }
879
925
 
880
926
  /* Is `value` valid for this attribute? */
@@ -892,7 +938,7 @@ function createDOMPurify() {
892
938
  currentNode.setAttribute(name, value);
893
939
  }
894
940
 
895
- DOMPurify.removed.pop();
941
+ arrayPop(DOMPurify.removed);
896
942
  } catch (error) {}
897
943
  }
898
944
 
@@ -959,11 +1005,11 @@ function createDOMPurify() {
959
1005
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
960
1006
  // eslint-disable-next-line no-negated-condition
961
1007
  if (typeof dirty.toString !== 'function') {
962
- throw new TypeError('toString is not a function');
1008
+ throw typeErrorCreate('toString is not a function');
963
1009
  } else {
964
1010
  dirty = dirty.toString();
965
1011
  if (typeof dirty !== 'string') {
966
- throw new TypeError('dirty is not a string, aborting');
1012
+ throw typeErrorCreate('dirty is not a string, aborting');
967
1013
  }
968
1014
  }
969
1015
  }
@@ -991,6 +1037,11 @@ function createDOMPurify() {
991
1037
  /* Clean up removed elements */
992
1038
  DOMPurify.removed = [];
993
1039
 
1040
+ /* Check if dirty is correctly typed for IN_PLACE */
1041
+ if (typeof dirty === 'string') {
1042
+ IN_PLACE = false;
1043
+ }
1044
+
994
1045
  if (IN_PLACE) {
995
1046
  /* No special handling necessary for in-place sanitization */
996
1047
  } else if (dirty instanceof Node) {
@@ -1089,8 +1140,8 @@ function createDOMPurify() {
1089
1140
 
1090
1141
  /* Sanitize final string template-safe */
1091
1142
  if (SAFE_FOR_TEMPLATES) {
1092
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1093
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1143
+ serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
1144
+ serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
1094
1145
  }
1095
1146
 
1096
1147
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
@@ -1133,8 +1184,8 @@ function createDOMPurify() {
1133
1184
  _parseConfig({});
1134
1185
  }
1135
1186
 
1136
- var lcTag = tag.toLowerCase();
1137
- var lcName = attr.toLowerCase();
1187
+ var lcTag = stringToLowerCase(tag);
1188
+ var lcName = stringToLowerCase(attr);
1138
1189
  return _isValidAttribute(lcTag, lcName, value);
1139
1190
  };
1140
1191
 
@@ -1151,7 +1202,7 @@ function createDOMPurify() {
1151
1202
  }
1152
1203
 
1153
1204
  hooks[entryPoint] = hooks[entryPoint] || [];
1154
- hooks[entryPoint].push(hookFunction);
1205
+ arrayPush(hooks[entryPoint], hookFunction);
1155
1206
  };
1156
1207
 
1157
1208
  /**
@@ -1163,7 +1214,7 @@ function createDOMPurify() {
1163
1214
  */
1164
1215
  DOMPurify.removeHook = function (entryPoint) {
1165
1216
  if (hooks[entryPoint]) {
1166
- hooks[entryPoint].pop();
1217
+ arrayPop(hooks[entryPoint]);
1167
1218
  }
1168
1219
  };
1169
1220