dompurify 1.0.7 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,64 +1,161 @@
1
1
  'use strict';
2
2
 
3
- var html = ['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 freeze$1 = Object.freeze || function (x) {
4
+ return x;
5
+ };
6
+
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']);
4
8
 
5
9
  // SVG
6
- var svg = ['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 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']);
11
+
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']);
7
13
 
8
- var svgFilters = ['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence'];
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']);
15
+
16
+ var text = freeze$1(['#text']);
17
+
18
+ var freeze$2 = Object.freeze || function (x) {
19
+ return x;
20
+ };
9
21
 
10
- var mathMl = ['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmuliscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mpspace', 'msqrt', 'mystyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover'];
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', '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']);
11
23
 
12
- var text = ['#text'];
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']);
13
25
 
14
- var html$1 = ['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', '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', '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'];
26
+ var mathMl$1 = freeze$2(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
15
27
 
16
- var svg$1 = ['accent-height', 'accumulate', 'additivive', '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', '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', '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', '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'];
28
+ var xml = freeze$2(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
17
29
 
18
- var mathMl$1 = ['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns'];
30
+ var hasOwnProperty = Object.hasOwnProperty;
31
+ var setPrototypeOf = Object.setPrototypeOf;
19
32
 
20
- var xml = ['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink'];
33
+ var _ref$1 = typeof Reflect !== 'undefined' && Reflect;
34
+ var apply$1 = _ref$1.apply;
35
+
36
+ if (!apply$1) {
37
+ apply$1 = function apply(fun, thisValue, args) {
38
+ return fun.apply(thisValue, args);
39
+ };
40
+ }
21
41
 
22
42
  /* Add properties to a lookup table */
23
43
  function addToSet(set, array) {
44
+ if (setPrototypeOf) {
45
+ // Make 'in' and truthy checks like Boolean(set.constructor)
46
+ // independent of any properties defined on Object.prototype.
47
+ // Prevent prototype setters from intercepting set as a this value.
48
+ setPrototypeOf(set, null);
49
+ }
50
+
24
51
  var l = array.length;
25
52
  while (l--) {
26
- if (typeof array[l] === 'string') {
27
- array[l] = array[l].toLowerCase();
53
+ var element = array[l];
54
+ if (typeof element === 'string') {
55
+ var lcElement = element.toLowerCase();
56
+ if (lcElement !== element) {
57
+ // Config presets (e.g. tags.js, attrs.js) are immutable.
58
+ if (!Object.isFrozen(array)) {
59
+ array[l] = lcElement;
60
+ }
61
+
62
+ element = lcElement;
63
+ }
28
64
  }
29
- set[array[l]] = true;
65
+
66
+ set[element] = true;
30
67
  }
68
+
31
69
  return set;
32
70
  }
33
71
 
34
72
  /* Shallow clone an object */
35
73
  function clone(object) {
36
74
  var newObject = {};
75
+
37
76
  var property = void 0;
38
77
  for (property in object) {
39
- if (Object.prototype.hasOwnProperty.call(object, property)) {
78
+ if (apply$1(hasOwnProperty, object, [property])) {
40
79
  newObject[property] = object[property];
41
80
  }
42
81
  }
82
+
43
83
  return newObject;
44
84
  }
45
85
 
46
- var MUSTACHE_EXPR = /\{\{[\s\S]*|[\s\S]*\}\}/gm; // Specify template detection regex for SAFE_FOR_TEMPLATES mode
47
- var ERB_EXPR = /<%[\s\S]*|[\s\S]*%>/gm;
48
- var DATA_ATTR = /^data-[\-\w.\u00B7-\uFFFF]/; // eslint-disable-line no-useless-escape
49
- var ARIA_ATTR = /^aria-[\-\w]+$/; // eslint-disable-line no-useless-escape
50
- var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
51
- var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
52
- var ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g; // eslint-disable-line no-control-regex
86
+ var seal = Object.seal || function (x) {
87
+ return x;
88
+ };
89
+
90
+ var MUSTACHE_EXPR = seal(/\{\{[\s\S]*|[\s\S]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
91
+ var ERB_EXPR = seal(/<%[\s\S]*|[\s\S]*%>/gm);
92
+ var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
93
+ var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
94
+ var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
95
+ );
96
+ var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
97
+ var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g // eslint-disable-line no-control-regex
98
+ );
53
99
 
54
100
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
55
101
 
56
102
  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); } }
57
103
 
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
+
58
110
  var getGlobal = function getGlobal() {
59
111
  return typeof window === 'undefined' ? null : window;
60
112
  };
61
113
 
114
+ if (!apply) {
115
+ apply = function apply(fun, thisValue, args) {
116
+ return fun.apply(thisValue, args);
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Creates a no-op policy for internal use only.
122
+ * Don't export this function outside this module!
123
+ * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
124
+ * @param {Document} document The document object (to determine policy name suffix)
125
+ * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
126
+ * are not supported).
127
+ */
128
+ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
129
+ if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
130
+ return null;
131
+ }
132
+
133
+ // Allow the callers to control the unique policy name
134
+ // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
135
+ // Policy creation with duplicate names throws in Trusted Types.
136
+ var suffix = null;
137
+ var ATTR_NAME = 'data-tt-policy-suffix';
138
+ if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
139
+ suffix = document.currentScript.getAttribute(ATTR_NAME);
140
+ }
141
+
142
+ var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
143
+
144
+ try {
145
+ return trustedTypes.createPolicy(policyName, {
146
+ createHTML: function createHTML(html$$1) {
147
+ return html$$1;
148
+ }
149
+ });
150
+ } catch (error) {
151
+ // Policy creation failed (most likely another DOMPurify script has
152
+ // already run). Skip creating the policy, as this will only cause errors
153
+ // if TT are enforced.
154
+ console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
155
+ return null;
156
+ }
157
+ };
158
+
62
159
  function createDOMPurify() {
63
160
  var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
64
161
 
@@ -70,7 +167,7 @@ function createDOMPurify() {
70
167
  * Version label, exposed for easier checks
71
168
  * if DOMPurify is up to date or not
72
169
  */
73
- DOMPurify.version = '1.0.7';
170
+ DOMPurify.version = '1.0.11';
74
171
 
75
172
  /**
76
173
  * Array of elements that DOMPurify removed during sanitation.
@@ -87,8 +184,8 @@ function createDOMPurify() {
87
184
  }
88
185
 
89
186
  var originalDocument = window.document;
90
- var useDOMParser = false; // See comment below
91
- var removeTitle = false; // See comment below
187
+ var useDOMParser = false;
188
+ var removeTitle = false;
92
189
 
93
190
  var document = window.document;
94
191
  var DocumentFragment = window.DocumentFragment,
@@ -99,7 +196,8 @@ function createDOMPurify() {
99
196
  NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
100
197
  Text = window.Text,
101
198
  Comment = window.Comment,
102
- DOMParser = window.DOMParser;
199
+ DOMParser = window.DOMParser,
200
+ TrustedTypes = window.TrustedTypes;
103
201
 
104
202
  // As per issue #47, the web-components registry is inherited by a
105
203
  // new document created via createHTMLDocument. As per the spec
@@ -115,6 +213,9 @@ function createDOMPurify() {
115
213
  }
116
214
  }
117
215
 
216
+ var trustedTypesPolicy = _createTrustedTypesPolicy(TrustedTypes, originalDocument);
217
+ var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
218
+
118
219
  var _document = document,
119
220
  implementation = _document.implementation,
120
221
  createNodeIterator = _document.createNodeIterator,
@@ -184,12 +285,14 @@ function createDOMPurify() {
184
285
  * document.body. By default, browsers might move them to document.head */
185
286
  var FORCE_BODY = false;
186
287
 
187
- /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html string.
288
+ /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
289
+ * string (or a TrustedHTML object if Trusted Types are supported).
188
290
  * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
189
291
  */
190
292
  var RETURN_DOM = false;
191
293
 
192
- /* Decide if a DOM `DocumentFragment` should be returned, instead of a html string */
294
+ /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
295
+ * string (or a TrustedHTML object if Trusted Types are supported) */
193
296
  var RETURN_DOM_FRAGMENT = false;
194
297
 
195
298
  /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
@@ -218,7 +321,8 @@ function createDOMPurify() {
218
321
  var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);
219
322
 
220
323
  /* Attributes safe for values like "javascript:" */
221
- var URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
324
+ var URI_SAFE_ATTRIBUTES = null;
325
+ var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
222
326
 
223
327
  /* Keep a reference to config to pass to hooks */
224
328
  var CONFIG = null;
@@ -235,13 +339,19 @@ function createDOMPurify() {
235
339
  */
236
340
  // eslint-disable-next-line complexity
237
341
  var _parseConfig = function _parseConfig(cfg) {
342
+ if (CONFIG && CONFIG === cfg) {
343
+ return;
344
+ }
345
+
238
346
  /* Shield configuration object from tampering */
239
- if ((typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
347
+ if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {
240
348
  cfg = {};
241
349
  }
350
+
242
351
  /* Set configuration parameters */
243
352
  ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
244
353
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
354
+ URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet({}, cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
245
355
  FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
246
356
  FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
247
357
  USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
@@ -277,16 +387,19 @@ function createDOMPurify() {
277
387
  addToSet(ALLOWED_TAGS, html);
278
388
  addToSet(ALLOWED_ATTR, html$1);
279
389
  }
390
+
280
391
  if (USE_PROFILES.svg === true) {
281
392
  addToSet(ALLOWED_TAGS, svg);
282
393
  addToSet(ALLOWED_ATTR, svg$1);
283
394
  addToSet(ALLOWED_ATTR, xml);
284
395
  }
396
+
285
397
  if (USE_PROFILES.svgFilters === true) {
286
398
  addToSet(ALLOWED_TAGS, svgFilters);
287
399
  addToSet(ALLOWED_ATTR, svg$1);
288
400
  addToSet(ALLOWED_ATTR, xml);
289
401
  }
402
+
290
403
  if (USE_PROFILES.mathMl === true) {
291
404
  addToSet(ALLOWED_TAGS, mathMl);
292
405
  addToSet(ALLOWED_ATTR, mathMl$1);
@@ -299,14 +412,18 @@ function createDOMPurify() {
299
412
  if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
300
413
  ALLOWED_TAGS = clone(ALLOWED_TAGS);
301
414
  }
415
+
302
416
  addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
303
417
  }
418
+
304
419
  if (cfg.ADD_ATTR) {
305
420
  if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
306
421
  ALLOWED_ATTR = clone(ALLOWED_ATTR);
307
422
  }
423
+
308
424
  addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
309
425
  }
426
+
310
427
  if (cfg.ADD_URI_SAFE_ATTR) {
311
428
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
312
429
  }
@@ -328,8 +445,8 @@ function createDOMPurify() {
328
445
 
329
446
  // Prevent further manipulation of configuration.
330
447
  // Not available in IE8, Safari 5, etc.
331
- if (Object && 'freeze' in Object) {
332
- Object.freeze(cfg);
448
+ if (freeze) {
449
+ freeze(cfg);
333
450
  }
334
451
 
335
452
  CONFIG = cfg;
@@ -344,8 +461,8 @@ function createDOMPurify() {
344
461
  DOMPurify.removed.push({ element: node });
345
462
  try {
346
463
  node.parentNode.removeChild(node);
347
- } catch (err) {
348
- node.outerHTML = '';
464
+ } catch (error) {
465
+ node.outerHTML = emptyHTML;
349
466
  }
350
467
  };
351
468
 
@@ -361,12 +478,13 @@ function createDOMPurify() {
361
478
  attribute: node.getAttributeNode(name),
362
479
  from: node
363
480
  });
364
- } catch (err) {
481
+ } catch (error) {
365
482
  DOMPurify.removed.push({
366
483
  attribute: null,
367
484
  from: node
368
485
  });
369
486
  }
487
+
370
488
  node.removeAttribute(name);
371
489
  };
372
490
 
@@ -379,19 +497,27 @@ function createDOMPurify() {
379
497
  var _initDocument = function _initDocument(dirty) {
380
498
  /* Create a HTML document */
381
499
  var doc = void 0;
500
+ var leadingWhitespace = void 0;
382
501
 
383
502
  if (FORCE_BODY) {
384
503
  dirty = '<remove></remove>' + dirty;
504
+ } else {
505
+ /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
506
+ var matches = dirty.match(/^[\s]+/);
507
+ leadingWhitespace = matches && matches[0];
508
+ if (leadingWhitespace) {
509
+ dirty = dirty.slice(leadingWhitespace.length);
510
+ }
385
511
  }
386
512
 
387
513
  /* Use DOMParser to workaround Firefox bug (see comment below) */
388
514
  if (useDOMParser) {
389
515
  try {
390
516
  doc = new DOMParser().parseFromString(dirty, 'text/html');
391
- } catch (err) {}
517
+ } catch (error) {}
392
518
  }
393
519
 
394
- /* Remove title to fix an mXSS bug in older MS Edge */
520
+ /* Remove title to fix a mXSS bug in older MS Edge */
395
521
  if (removeTitle) {
396
522
  addToSet(FORBID_TAGS, ['title']);
397
523
  }
@@ -404,7 +530,11 @@ function createDOMPurify() {
404
530
  body = _doc.body;
405
531
 
406
532
  body.parentNode.removeChild(body.parentNode.firstElementChild);
407
- body.outerHTML = dirty;
533
+ body.outerHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
534
+ }
535
+
536
+ if (leadingWhitespace) {
537
+ doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
408
538
  }
409
539
 
410
540
  /* Work on whole document or just its body */
@@ -423,19 +553,20 @@ function createDOMPurify() {
423
553
  if (DOMPurify.isSupported) {
424
554
  (function () {
425
555
  try {
426
- var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=alert(1)//">');
556
+ var doc = _initDocument('<svg><p><style><img src="</style><img src=x onerror=1//">');
427
557
  if (doc.querySelector('svg img')) {
428
558
  useDOMParser = true;
429
559
  }
430
- } catch (err) {}
560
+ } catch (error) {}
431
561
  })();
562
+
432
563
  (function () {
433
564
  try {
434
565
  var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');
435
- if (doc.querySelector('title').textContent.match(/<\/title/)) {
566
+ if (doc.querySelector('title').innerHTML.match(/<\/title/)) {
436
567
  removeTitle = true;
437
568
  }
438
- } catch (err) {}
569
+ } catch (error) {}
439
570
  })();
440
571
  }
441
572
 
@@ -461,9 +592,11 @@ function createDOMPurify() {
461
592
  if (elm instanceof Text || elm instanceof Comment) {
462
593
  return false;
463
594
  }
595
+
464
596
  if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function') {
465
597
  return true;
466
598
  }
599
+
467
600
  return false;
468
601
  };
469
602
 
@@ -505,6 +638,7 @@ function createDOMPurify() {
505
638
  * @param {Node} currentNode to check for permission to exist
506
639
  * @return {Boolean} true if node was killed, false if left alive
507
640
  */
641
+ // eslint-disable-next-line complexity
508
642
  var _sanitizeElements = function _sanitizeElements(currentNode) {
509
643
  var content = void 0;
510
644
 
@@ -531,9 +665,22 @@ function createDOMPurify() {
531
665
  /* Keep content except for black-listed elements */
532
666
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {
533
667
  try {
534
- currentNode.insertAdjacentHTML('AfterEnd', currentNode.innerHTML);
535
- } catch (err) {}
668
+ var htmlToInsert = currentNode.innerHTML;
669
+ currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);
670
+ } catch (error) {}
536
671
  }
672
+
673
+ _forceRemove(currentNode);
674
+ return true;
675
+ }
676
+
677
+ /* Remove in case a noscript/noembed XSS is suspected */
678
+ if (tagName === 'noscript' && currentNode.innerHTML.match(/<\/noscript/i)) {
679
+ _forceRemove(currentNode);
680
+ return true;
681
+ }
682
+
683
+ if (tagName === 'noembed' && currentNode.innerHTML.match(/<\/noembed/i)) {
537
684
  _forceRemove(currentNode);
538
685
  return true;
539
686
  }
@@ -574,18 +721,13 @@ function createDOMPurify() {
574
721
  * @param {string} value Attribute value.
575
722
  * @return {Boolean} Returns true if `value` is valid, otherwise false.
576
723
  */
724
+ // eslint-disable-next-line complexity
577
725
  var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
578
726
  /* Make sure attribute cannot clobber */
579
727
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
580
728
  return false;
581
729
  }
582
730
 
583
- /* Sanitize attribute content to be template-safe */
584
- if (SAFE_FOR_TEMPLATES) {
585
- value = value.replace(MUSTACHE_EXPR$$1, ' ');
586
- value = value.replace(ERB_EXPR$$1, ' ');
587
- }
588
-
589
731
  /* Allow valid data-* attributes: At least one character after "-"
590
732
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
591
733
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
@@ -606,7 +748,8 @@ function createDOMPurify() {
606
748
  } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {
607
749
  // This attribute is safe
608
750
  /* Keep image data URIs alive if src/xlink:href is allowed */
609
- } else if ((lcName === 'src' || lcName === 'xlink:href') && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {
751
+ /* Further prevent gadget XSS for dynamically built script tags */
752
+ } else if ((lcName === 'src' || lcName === 'xlink:href') && lcTag !== 'script' && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {
610
753
  // This attribute is safe
611
754
  /* Allow unknown protocols: This provides support for links that
612
755
  are handled by protocol handlers which may be unknown ahead of
@@ -621,6 +764,7 @@ function createDOMPurify() {
621
764
  } else {
622
765
  return false;
623
766
  }
767
+
624
768
  return true;
625
769
  };
626
770
 
@@ -632,9 +776,8 @@ function createDOMPurify() {
632
776
  * @protect removeAttribute
633
777
  * @protect setAttribute
634
778
  *
635
- * @param {Node} node to sanitize
779
+ * @param {Node} currentNode to sanitize
636
780
  */
637
- // eslint-disable-next-line complexity
638
781
  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
639
782
  var attr = void 0;
640
783
  var value = void 0;
@@ -664,7 +807,8 @@ function createDOMPurify() {
664
807
  while (l--) {
665
808
  attr = attributes[l];
666
809
  var _attr = attr,
667
- name = _attr.name;
810
+ name = _attr.name,
811
+ namespaceURI = _attr.namespaceURI;
668
812
 
669
813
  value = attr.value.trim();
670
814
  lcName = name.toLowerCase();
@@ -682,7 +826,7 @@ function createDOMPurify() {
682
826
  // attribute at the time.
683
827
  if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {
684
828
  idAttr = attributes.id;
685
- attributes = Array.prototype.slice.apply(attributes);
829
+ attributes = apply(arraySlice, attributes, []);
686
830
  _removeAttribute('id', currentNode);
687
831
  _removeAttribute(name, currentNode);
688
832
  if (attributes.indexOf(idAttr) > l) {
@@ -691,7 +835,7 @@ function createDOMPurify() {
691
835
  } else if (
692
836
  // This works around a bug in Safari, where input[type=file]
693
837
  // cannot be dynamically set after type has been removed
694
- currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
838
+ currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && hookEvent.keepAttr && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {
695
839
  continue;
696
840
  } else {
697
841
  // This avoids a crash in Safari v9.0 with double-ids.
@@ -700,6 +844,7 @@ function createDOMPurify() {
700
844
  if (name === 'id') {
701
845
  currentNode.setAttribute(name, '');
702
846
  }
847
+
703
848
  _removeAttribute(name, currentNode);
704
849
  }
705
850
 
@@ -708,6 +853,12 @@ function createDOMPurify() {
708
853
  continue;
709
854
  }
710
855
 
856
+ /* Sanitize attribute content to be template-safe */
857
+ if (SAFE_FOR_TEMPLATES) {
858
+ value = value.replace(MUSTACHE_EXPR$$1, ' ');
859
+ value = value.replace(ERB_EXPR$$1, ' ');
860
+ }
861
+
711
862
  /* Is `value` valid for this attribute? */
712
863
  var lcTag = currentNode.nodeName.toLowerCase();
713
864
  if (!_isValidAttribute(lcTag, lcName, value)) {
@@ -716,9 +867,15 @@ function createDOMPurify() {
716
867
 
717
868
  /* Handle invalid data-* attribute set by try-catching it */
718
869
  try {
719
- currentNode.setAttribute(name, value);
870
+ if (namespaceURI) {
871
+ currentNode.setAttributeNS(namespaceURI, name, value);
872
+ } else {
873
+ /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
874
+ currentNode.setAttribute(name, value);
875
+ }
876
+
720
877
  DOMPurify.removed.pop();
721
- } catch (err) {}
878
+ } catch (error) {}
722
879
  }
723
880
 
724
881
  /* Execute a hook if present */
@@ -799,10 +956,12 @@ function createDOMPurify() {
799
956
  if (typeof dirty === 'string') {
800
957
  return window.toStaticHTML(dirty);
801
958
  }
959
+
802
960
  if (_isNode(dirty)) {
803
961
  return window.toStaticHTML(dirty.outerHTML);
804
962
  }
805
963
  }
964
+
806
965
  return dirty;
807
966
  }
808
967
 
@@ -824,13 +983,16 @@ function createDOMPurify() {
824
983
  if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
825
984
  /* Node is already a body, use as is */
826
985
  body = importedNode;
986
+ } else if (importedNode.nodeName === 'HTML') {
987
+ body = importedNode;
827
988
  } else {
989
+ // eslint-disable-next-line unicorn/prefer-node-append
828
990
  body.appendChild(importedNode);
829
991
  }
830
992
  } else {
831
993
  /* Exit directly if we have nothing to do */
832
- if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
833
- return dirty;
994
+ if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
995
+ return trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
834
996
  }
835
997
 
836
998
  /* Initialize the document to work on */
@@ -838,7 +1000,7 @@ function createDOMPurify() {
838
1000
 
839
1001
  /* Check we have a DOM node from the data */
840
1002
  if (!body) {
841
- return RETURN_DOM ? null : '';
1003
+ return RETURN_DOM ? null : emptyHTML;
842
1004
  }
843
1005
  }
844
1006
 
@@ -873,6 +1035,8 @@ function createDOMPurify() {
873
1035
  oldNode = currentNode;
874
1036
  }
875
1037
 
1038
+ oldNode = null;
1039
+
876
1040
  /* If we sanitized `dirty` in-place, return it. */
877
1041
  if (IN_PLACE) {
878
1042
  return dirty;
@@ -884,6 +1048,7 @@ function createDOMPurify() {
884
1048
  returnNode = createDocumentFragment.call(body.ownerDocument);
885
1049
 
886
1050
  while (body.firstChild) {
1051
+ // eslint-disable-next-line unicorn/prefer-node-append
887
1052
  returnNode.appendChild(body.firstChild);
888
1053
  }
889
1054
  } else {
@@ -902,7 +1067,15 @@ function createDOMPurify() {
902
1067
  return returnNode;
903
1068
  }
904
1069
 
905
- return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1070
+ var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1071
+
1072
+ /* Sanitize final string template-safe */
1073
+ if (SAFE_FOR_TEMPLATES) {
1074
+ serializedHTML = serializedHTML.replace(MUSTACHE_EXPR$$1, ' ');
1075
+ serializedHTML = serializedHTML.replace(ERB_EXPR$$1, ' ');
1076
+ }
1077
+
1078
+ return trustedTypesPolicy ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
906
1079
  };
907
1080
 
908
1081
  /**
@@ -941,6 +1114,7 @@ function createDOMPurify() {
941
1114
  if (!CONFIG) {
942
1115
  _parseConfig({});
943
1116
  }
1117
+
944
1118
  var lcTag = tag.toLowerCase();
945
1119
  var lcName = attr.toLowerCase();
946
1120
  return _isValidAttribute(lcTag, lcName, value);
@@ -957,6 +1131,7 @@ function createDOMPurify() {
957
1131
  if (typeof hookFunction !== 'function') {
958
1132
  return;
959
1133
  }
1134
+
960
1135
  hooks[entryPoint] = hooks[entryPoint] || [];
961
1136
  hooks[entryPoint].push(hookFunction);
962
1137
  };