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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
8
8
 
9
- It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 2.0.7.
9
+ It's also very simple to use and get started with. DOMPurify was [started in February 2014](https://github.com/cure53/DOMPurify/commit/a630922616927373485e0e787ab19e73e3691b2b) and, meanwhile, has reached version 2.0.8.
10
10
 
11
11
  DOMPurify is written in JavaScript and works in all modern browsers (Safari, Opera (15+), Internet Explorer (10+), Edge, Firefox and Chrome - as well as almost anything else using Blink or WebKit). It doesn't break on MSIE6 or other legacy browsers. It either uses [a fall-back](#what-about-older-browsers-like-msie8) or simply does nothing.
12
12
 
@@ -48,27 +48,30 @@ If you're using an [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) module loa
48
48
 
49
49
  ```javascript
50
50
  require(['dompurify'], function(DOMPurify) {
51
- var clean = DOMPurify.sanitize(dirty);
51
+ var clean = DOMPurify.sanitize(dirty);
52
52
  });
53
53
  ```
54
54
 
55
- DOMPurify also works server-side with node.js as well as client-side via [Browserify](http://browserify.org/) or similar translators. Node.js 0.x is not supported; either [io.js](https://iojs.org) or Node.js 4.x or newer is required.
55
+ DOMPurify also works server-side with node.js as well as client-side via [Browserify](http://browserify.org/) or similar translators. Node.js 0.x is not supported; either [io.js](https://iojs.org) or Node.js 4.x or newer is required.
56
56
 
57
57
  ```bash
58
58
  npm install dompurify
59
59
  ```
60
+
60
61
  For JSDOM v10 or newer
62
+
61
63
  ```javascript
62
64
  const createDOMPurify = require('dompurify');
63
65
  const { JSDOM } = require('jsdom');
64
66
 
65
- const window = (new JSDOM('')).window;
67
+ const window = new JSDOM('').window;
66
68
  const DOMPurify = createDOMPurify(window);
67
69
 
68
70
  const clean = DOMPurify.sanitize(dirty);
69
71
  ```
70
72
 
71
73
  For JSDOM versions older than v10
74
+
72
75
  ```javascript
73
76
  const createDOMPurify = require('dompurify');
74
77
  const jsdom = require('jsdom').jsdom;
@@ -96,7 +99,7 @@ How does purified markup look like? Well, [the demo](https://cure53.de/purify) s
96
99
  ```javascript
97
100
  DOMPurify.sanitize('<img src=x onerror=alert(1)//>'); // becomes <img src="x">
98
101
  DOMPurify.sanitize('<svg><g/onload=alert(2)//<p>'); // becomes <svg><g></g></svg>
99
- DOMPurify.sanitize('<p>abc<iframe/\/src=jAva&Tab;script:alert(3)>def'); // becomes <p>abcdef</p>
102
+ DOMPurify.sanitize('<p>abc<iframe//src=jAva&Tab;script:alert(3)>def'); // becomes <p>abcdef</p>
100
103
  DOMPurify.sanitize('<math><mi//xlink:href="data:x,<script>alert(4)</script>">'); // becomes <math><mi></mi></math>
101
104
  DOMPurify.sanitize('<TABLE><tr><td>HELLO</tr></TABL>'); // becomes <table><tbody><tr><td>HELLO</td></tr></tbody></table>
102
105
  DOMPurify.sanitize('<UL><li><A HREF=//google.com>click</UL>'); // becomes <ul><li><a href="//google.com">click</a></li></ul>
@@ -114,7 +117,7 @@ If not even `toStaticHTML` is supported, DOMPurify does nothing at all. It simpl
114
117
 
115
118
  ## What about DOMPurify and Trusted Types?
116
119
 
117
- In version 1.0.9, support for [Trusted Types API](https://github.com/WICG/trusted-types) was added to DOMPurify.
120
+ In version 1.0.9, support for [Trusted Types API](https://github.com/WICG/trusted-types) was added to DOMPurify.
118
121
  In version 2.0.0, a config flag was added to control DOMPurify's behavior regarding this.
119
122
 
120
123
  When `DOMPurify.sanitize` is used in an environment where the Trusted Types API is available and `RETURN_TRUSTED_TYPE` is set to `true`, it tries to return a `TrustedHTML` value instead of a string (the behavior for `RETURN_DOM`, `RETURN_DOM_FRAGMENT`, and `RETURN_DOM_IMPORT` config options does not change).
@@ -205,6 +208,7 @@ var dirty = document.createElement('a');
205
208
  dirty.setAttribute('href', 'javascript:alert(1)');
206
209
  var clean = DOMPurify.sanitize(dirty, {IN_PLACE: true}); // see https://github.com/cure53/DOMPurify/issues/288 for more info
207
210
  ```
211
+
208
212
  There is even [more examples here](https://github.com/cure53/DOMPurify/tree/master/demos#what-is-this), showing how you can run, customize and configure DOMPurify to fit your needs.
209
213
 
210
214
  ## Persistent Configuration
@@ -216,7 +220,7 @@ Instead of repeatedly passing the same configuration to `DOMPurify.sanitize`, yo
216
220
  DOMPurify allows you to augment its functionality by attaching one or more functions with the `DOMPurify.addHook` method to one of the following hooks:
217
221
 
218
222
  - `beforeSanitizeElements`
219
- - `uponSanitizeElement`
223
+ - `uponSanitizeElement` (No 's' - called for every element)
220
224
  - `afterSanitizeElements`
221
225
  - `beforeSanitizeAttributes`
222
226
  - `uponSanitizeAttribute`
@@ -230,9 +234,14 @@ It passes the currently processed DOM node, when needed a literal with verified
230
234
  _Example_:
231
235
 
232
236
  ```javascript
233
- DOMPurify.addHook('beforeSanitizeElements', function(currentNode, data, config) {
234
- // Do something with the current node and return it
235
- return currentNode;
237
+ DOMPurify.addHook('beforeSanitizeElements', function(
238
+ currentNode,
239
+ hookEvent,
240
+ config
241
+ ) {
242
+ // Do something with the current node and return it
243
+ // You can also mutate hookEvent (i.e. set hookEvent.forceKeepAttr = true)
244
+ return currentNode;
236
245
  });
237
246
  ```
238
247
 
@@ -280,8 +289,8 @@ Feature releases will not be announced to this list.
280
289
 
281
290
  ## Who contributed?
282
291
 
283
- Many people helped DOMPurify become what it is and need to be acknowledged here!
292
+ Many people helped and help DOMPurify become what it is and need to be acknowledged here!
284
293
 
285
- @tdeekens, @neilj, @fhemberger, @Joris-van-der-Wel, @ydaniv, @filedescriptor, @ConradIrwin, @gibson042, @choumx, @0xSobky, @styfle, @koto, @tlau88, @strugee, @oparoz, @mathiasbynens, @edg2s, @dnkolegov, @dhardtke, @wirehead, @thorn0, @styu, @mozfreddyb, @mikesamuel, @jorangreef, @jimmyhchan, @jameydeorio, @jameskraus, @hyderali, @hansottowirtz, @hackvertor, @freddyb, @flavorjones, @djfarrelly, @devd, @camerondunford, @buu700, @buildog, @alabiaga, @Vector919, @Robbert, @GreLI, @FuzzySockets, @ArtemBernatskyy, [@garethheyes](https://twitter.com/garethheyes), [@filedescriptor](https://twitter.com/filedescriptor), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl), @ShikariSenpai, @ansjdnakjdnajkd, [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro) and especially @masatokinugawa
294
+ [oreoshake 💸](https://github.com/oreoshake), [dcramer 💸](https://github.com/dcramer),[tdeekens](https://github.com/tdeekens), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@filedescriptor](https://twitter.com/filedescriptor), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro) and especially [@masatokinugawa](https://twitter.com/masatokinugawa)
286
295
 
287
296
  And last but not least, thanks to [BrowserStack](https://browserstack.com) for supporting this project with their services for free and delivering excellent, dedicated and very professional support on top of that.
@@ -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
+ }
21
+
22
+ if (!freeze) {
23
+ freeze = function freeze(x) {
24
+ return x;
25
+ };
26
+ }
13
27
 
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']);
28
+ if (!seal) {
29
+ seal = function seal(x) {
30
+ return x;
31
+ };
32
+ }
15
33
 
16
- var text = freeze$1(['#text']);
34
+ if (!construct) {
35
+ construct = function construct(Func, args) {
36
+ return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray$1(args))))();
37
+ };
38
+ }
17
39
 
18
- var freeze$2 = Object.freeze || function (x) {
19
- return x;
20
- };
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);
21
46
 
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']);
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);
23
52
 
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']);
53
+ var regExpTest = unapply(RegExp.prototype.test);
54
+ var regExpCreate = unconstruct(RegExp);
25
55
 
26
- 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']);
56
+ var typeErrorCreate = unconstruct(TypeError);
27
57
 
28
- var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
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
+ }
29
63
 
30
- var hasOwnProperty = Object.hasOwnProperty;
31
- var setPrototypeOf = Object.setPrototypeOf;
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.7';
209
+ DOMPurify.version = '2.0.8';
171
210
 
172
211
  /**
173
212
  * Array of elements that DOMPurify removed during sanitation.
@@ -197,7 +236,7 @@ function createDOMPurify() {
197
236
  Text = window.Text,
198
237
  Comment = window.Comment,
199
238
  DOMParser = window.DOMParser,
200
- TrustedTypes = window.TrustedTypes;
239
+ trustedTypes = window.trustedTypes;
201
240
 
202
241
  // As per issue #47, the web-components registry is inherited by a
203
242
  // new document created via createHTMLDocument. As per the spec
@@ -213,7 +252,7 @@ function createDOMPurify() {
213
252
  }
214
253
  }
215
254
 
216
- var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
255
+ var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
217
256
  var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
218
257
 
219
258
  var _document = document,
@@ -374,9 +413,7 @@ function createDOMPurify() {
374
413
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
375
414
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
376
415
  IN_PLACE = cfg.IN_PLACE || false; // Default false
377
-
378
416
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
379
-
380
417
  if (SAFE_FOR_TEMPLATES) {
381
418
  ALLOW_DATA_ATTR = false;
382
419
  }
@@ -465,7 +502,7 @@ function createDOMPurify() {
465
502
  * @param {Node} node a DOM node
466
503
  */
467
504
  var _forceRemove = function _forceRemove(node) {
468
- DOMPurify.removed.push({ element: node });
505
+ arrayPush(DOMPurify.removed, { element: node });
469
506
  try {
470
507
  node.parentNode.removeChild(node);
471
508
  } catch (error) {
@@ -481,12 +518,12 @@ function createDOMPurify() {
481
518
  */
482
519
  var _removeAttribute = function _removeAttribute(name, node) {
483
520
  try {
484
- DOMPurify.removed.push({
521
+ arrayPush(DOMPurify.removed, {
485
522
  attribute: node.getAttributeNode(name),
486
523
  from: node
487
524
  });
488
525
  } catch (error) {
489
- DOMPurify.removed.push({
526
+ arrayPush(DOMPurify.removed, {
490
527
  attribute: null,
491
528
  from: node
492
529
  });
@@ -510,17 +547,15 @@ function createDOMPurify() {
510
547
  dirty = '<remove></remove>' + dirty;
511
548
  } else {
512
549
  /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
513
- var matches = dirty.match(/^[\s]+/);
550
+ var matches = stringMatch(dirty, /^[\s]+/);
514
551
  leadingWhitespace = matches && matches[0];
515
- if (leadingWhitespace) {
516
- dirty = dirty.slice(leadingWhitespace.length);
517
- }
518
552
  }
519
553
 
554
+ var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
520
555
  /* Use DOMParser to workaround Firefox bug (see comment below) */
521
556
  if (useDOMParser) {
522
557
  try {
523
- doc = new DOMParser().parseFromString(dirty, 'text/html');
558
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
524
559
  } catch (error) {}
525
560
  }
526
561
 
@@ -537,7 +572,7 @@ function createDOMPurify() {
537
572
  body = _doc.body;
538
573
 
539
574
  body.parentNode.removeChild(body.parentNode.firstElementChild);
540
- body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
575
+ body.outerHTML = dirtyPayload;
541
576
  }
542
577
 
543
578
  if (dirty && leadingWhitespace) {
@@ -570,7 +605,7 @@ function createDOMPurify() {
570
605
  (function () {
571
606
  try {
572
607
  var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
573
- if (/<\/title/.test(doc.querySelector('title').innerHTML)) {
608
+ if (regExpTest(/<\/title/, doc.querySelector('title').innerHTML)) {
574
609
  removeTitle = true;
575
610
  }
576
611
  } catch (error) {}
@@ -630,7 +665,7 @@ function createDOMPurify() {
630
665
  return;
631
666
  }
632
667
 
633
- hooks[entryPoint].forEach(function (hook) {
668
+ arrayForEach(hooks[entryPoint], function (hook) {
634
669
  hook.call(DOMPurify, currentNode, data, CONFIG);
635
670
  });
636
671
  };
@@ -659,7 +694,7 @@ function createDOMPurify() {
659
694
  }
660
695
 
661
696
  /* Now let's check the element's type and name */
662
- var tagName = currentNode.nodeName.toLowerCase();
697
+ var tagName = stringToLowerCase(currentNode.nodeName);
663
698
 
664
699
  /* Execute a hook if present */
665
700
  _executeHook('uponSanitizeElement', currentNode, {
@@ -688,23 +723,23 @@ function createDOMPurify() {
688
723
  }
689
724
 
690
725
  /* Remove in case a noscript/noembed XSS is suspected */
691
- if (tagName === 'noscript' && /<\/noscript/i.test(currentNode.innerHTML)) {
726
+ if (tagName === 'noscript' && regExpTest(/<\/noscript/i, currentNode.innerHTML)) {
692
727
  _forceRemove(currentNode);
693
728
  return true;
694
729
  }
695
730
 
696
- if (tagName === 'noembed' && /<\/noembed/i.test(currentNode.innerHTML)) {
731
+ if (tagName === 'noembed' && regExpTest(/<\/noembed/i, currentNode.innerHTML)) {
697
732
  _forceRemove(currentNode);
698
733
  return true;
699
734
  }
700
735
 
701
736
  /* Convert markup to cover jQuery behavior */
702
- if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {
703
- 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() });
704
739
  if (currentNode.innerHTML) {
705
- currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');
740
+ currentNode.innerHTML = stringReplace(currentNode.innerHTML, /</g, '&lt;');
706
741
  } else {
707
- currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
742
+ currentNode.innerHTML = stringReplace(currentNode.textContent, /</g, '&lt;');
708
743
  }
709
744
  }
710
745
 
@@ -712,10 +747,10 @@ function createDOMPurify() {
712
747
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
713
748
  /* Get the element's text content */
714
749
  content = currentNode.textContent;
715
- content = content.replace(MUSTACHE_EXPR$$1, ' ');
716
- content = content.replace(ERB_EXPR$$1, ' ');
750
+ content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');
751
+ content = stringReplace(content, ERB_EXPR$$1, ' ');
717
752
  if (currentNode.textContent !== content) {
718
- DOMPurify.removed.push({ element: currentNode.cloneNode() });
753
+ arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
719
754
  currentNode.textContent = content;
720
755
  }
721
756
  }
@@ -745,9 +780,9 @@ function createDOMPurify() {
745
780
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
746
781
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
747
782
  We don't need to check the value; it's always URI safe. */
748
- if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {
783
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) {
749
784
  // This attribute is safe
750
- } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {
785
+ } else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) {
751
786
  // This attribute is safe
752
787
  /* Otherwise, check the name is permitted */
753
788
  } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
@@ -758,16 +793,16 @@ function createDOMPurify() {
758
793
  // This attribute is safe
759
794
  /* Check no script, data or unknown possibly unsafe URI
760
795
  unless we know URI values are safe for that attribute */
761
- } 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, ''))) {
762
797
  // This attribute is safe
763
798
  /* Keep image data URIs alive if src/xlink:href is allowed */
764
799
  /* Further prevent gadget XSS for dynamically built script tags */
765
- } 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]) {
766
801
  // This attribute is safe
767
802
  /* Allow unknown protocols: This provides support for links that
768
803
  are handled by protocol handlers which may be unknown ahead of
769
804
  time, e.g. fb:, spotify: */
770
- } 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, ''))) {
771
806
  // This attribute is safe
772
807
  /* Check for binary attributes */
773
808
  // eslint-disable-next-line no-negated-condition
@@ -824,15 +859,20 @@ function createDOMPurify() {
824
859
  name = _attr.name,
825
860
  namespaceURI = _attr.namespaceURI;
826
861
 
827
- value = attr.value.trim();
828
- lcName = name.toLowerCase();
862
+ value = stringTrim(attr.value);
863
+ lcName = stringToLowerCase(name);
829
864
 
830
865
  /* Execute a hook if present */
831
866
  hookEvent.attrName = lcName;
832
867
  hookEvent.attrValue = value;
833
868
  hookEvent.keepAttr = true;
869
+ hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
834
870
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
835
871
  value = hookEvent.attrValue;
872
+ /* Did the hooks approve of the attribute? */
873
+ if (hookEvent.forceKeepAttr) {
874
+ continue;
875
+ }
836
876
 
837
877
  /* Remove attribute */
838
878
  // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
@@ -840,10 +880,10 @@ function createDOMPurify() {
840
880
  // attribute at the time.
841
881
  if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
842
882
  idAttr = attributes.id;
843
- attributes = apply(arraySlice, attributes, []);
883
+ attributes = arraySlice(attributes, []);
844
884
  _removeAttribute('id', currentNode);
845
885
  _removeAttribute(name, currentNode);
846
- if (attributes.indexOf(idAttr) > l) {
886
+ if (arrayIndexOf(attributes, idAttr) > l) {
847
887
  currentNode.setAttribute('id', idAttr.value);
848
888
  }
849
889
  } else if (
@@ -867,16 +907,22 @@ function createDOMPurify() {
867
907
  continue;
868
908
  }
869
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
+
870
916
  /* Take care of an mXSS pattern using namespace switches */
871
- if (/svg|math/i.test(currentNode.namespaceURI) && new RegExp('</(' + Object.keys(FORBID_CONTENTS).join('|') + ')', 'i').test(value)) {
917
+ if (regExpTest(/svg|math/i, currentNode.namespaceURI) && regExpTest(regExpCreate('</(' + arrayJoin(objectKeys(FORBID_CONTENTS), '|') + ')', 'i'), value)) {
872
918
  _removeAttribute(name, currentNode);
873
919
  continue;
874
920
  }
875
921
 
876
922
  /* Sanitize attribute content to be template-safe */
877
923
  if (SAFE_FOR_TEMPLATES) {
878
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
879
- value = value.replace(ERB_EXPR$$1, ' ');
924
+ value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');
925
+ value = stringReplace(value, ERB_EXPR$$1, ' ');
880
926
  }
881
927
 
882
928
  /* Is `value` valid for this attribute? */
@@ -894,7 +940,7 @@ function createDOMPurify() {
894
940
  currentNode.setAttribute(name, value);
895
941
  }
896
942
 
897
- DOMPurify.removed.pop();
943
+ arrayPop(DOMPurify.removed);
898
944
  } catch (error) {}
899
945
  }
900
946
 
@@ -961,11 +1007,11 @@ function createDOMPurify() {
961
1007
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
962
1008
  // eslint-disable-next-line no-negated-condition
963
1009
  if (typeof dirty.toString !== 'function') {
964
- throw new TypeError('toString is not a function');
1010
+ throw typeErrorCreate('toString is not a function');
965
1011
  } else {
966
1012
  dirty = dirty.toString();
967
1013
  if (typeof dirty !== 'string') {
968
- throw new TypeError('dirty is not a string, aborting');
1014
+ throw typeErrorCreate('dirty is not a string, aborting');
969
1015
  }
970
1016
  }
971
1017
  }
@@ -993,6 +1039,11 @@ function createDOMPurify() {
993
1039
  /* Clean up removed elements */
994
1040
  DOMPurify.removed = [];
995
1041
 
1042
+ /* Check if dirty is correctly typed for IN_PLACE */
1043
+ if (typeof dirty === 'string') {
1044
+ IN_PLACE = false;
1045
+ }
1046
+
996
1047
  if (IN_PLACE) {
997
1048
  /* No special handling necessary for in-place sanitization */
998
1049
  } else if (dirty instanceof Node) {
@@ -1091,8 +1142,8 @@ function createDOMPurify() {
1091
1142
 
1092
1143
  /* Sanitize final string template-safe */
1093
1144
  if (SAFE_FOR_TEMPLATES) {
1094
- serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1095
- serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1145
+ serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');
1146
+ serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');
1096
1147
  }
1097
1148
 
1098
1149
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
@@ -1135,8 +1186,8 @@ function createDOMPurify() {
1135
1186
  _parseConfig({});
1136
1187
  }
1137
1188
 
1138
- var lcTag = tag.toLowerCase();
1139
- var lcName = attr.toLowerCase();
1189
+ var lcTag = stringToLowerCase(tag);
1190
+ var lcName = stringToLowerCase(attr);
1140
1191
  return _isValidAttribute(lcTag, lcName, value);
1141
1192
  };
1142
1193
 
@@ -1153,7 +1204,7 @@ function createDOMPurify() {
1153
1204
  }
1154
1205
 
1155
1206
  hooks[entryPoint] = hooks[entryPoint] || [];
1156
- hooks[entryPoint].push(hookFunction);
1207
+ arrayPush(hooks[entryPoint], hookFunction);
1157
1208
  };
1158
1209
 
1159
1210
  /**
@@ -1165,7 +1216,7 @@ function createDOMPurify() {
1165
1216
  */
1166
1217
  DOMPurify.removeHook = function (entryPoint) {
1167
1218
  if (hooks[entryPoint]) {
1168
- hooks[entryPoint].pop();
1219
+ arrayPop(hooks[entryPoint]);
1169
1220
  }
1170
1221
  };
1171
1222