@carbon/ibmdotcom-utilities 2.22.0 → 2.24.0

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.
@@ -4,9 +4,27 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.IBMDotcomUtilities = {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
+ function _arrayLikeToArray(r, a) {
8
+ (null == a || a > r.length) && (a = r.length);
9
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
10
+ return n;
11
+ }
12
+ function _arrayWithHoles(r) {
13
+ if (Array.isArray(r)) return r;
14
+ }
15
+ function _arrayWithoutHoles(r) {
16
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
17
+ }
7
18
  function _classCallCheck(a, n) {
8
19
  if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
9
20
  }
21
+ function _construct(t, e, r) {
22
+ if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
23
+ var o = [null];
24
+ o.push.apply(o, e);
25
+ var p = new (t.bind.apply(t, o))();
26
+ return r && _setPrototypeOf(p, r.prototype), p;
27
+ }
10
28
  function _defineProperties(e, r) {
11
29
  for (var t = 0; t < r.length; t++) {
12
30
  var o = r[t];
@@ -18,6 +36,109 @@
18
36
  writable: !1
19
37
  }), e;
20
38
  }
39
+ function _createForOfIteratorHelper(r, e) {
40
+ var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
41
+ if (!t) {
42
+ if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) {
43
+ t && (r = t);
44
+ var n = 0,
45
+ F = function () {};
46
+ return {
47
+ s: F,
48
+ n: function () {
49
+ return n >= r.length ? {
50
+ done: !0
51
+ } : {
52
+ done: !1,
53
+ value: r[n++]
54
+ };
55
+ },
56
+ e: function (r) {
57
+ throw r;
58
+ },
59
+ f: F
60
+ };
61
+ }
62
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
63
+ }
64
+ var o,
65
+ a = !0,
66
+ u = !1;
67
+ return {
68
+ s: function () {
69
+ t = t.call(r);
70
+ },
71
+ n: function () {
72
+ var r = t.next();
73
+ return a = r.done, r;
74
+ },
75
+ e: function (r) {
76
+ u = !0, o = r;
77
+ },
78
+ f: function () {
79
+ try {
80
+ a || null == t.return || t.return();
81
+ } finally {
82
+ if (u) throw o;
83
+ }
84
+ }
85
+ };
86
+ }
87
+ function _isNativeReflectConstruct() {
88
+ try {
89
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
90
+ } catch (t) {}
91
+ return (_isNativeReflectConstruct = function () {
92
+ return !!t;
93
+ })();
94
+ }
95
+ function _iterableToArray(r) {
96
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
97
+ }
98
+ function _iterableToArrayLimit(r, l) {
99
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
100
+ if (null != t) {
101
+ var e,
102
+ n,
103
+ i,
104
+ u,
105
+ a = [],
106
+ f = !0,
107
+ o = !1;
108
+ try {
109
+ if (i = (t = t.call(r)).next, 0 === l) {
110
+ if (Object(t) !== t) return;
111
+ f = !1;
112
+ } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
113
+ } catch (r) {
114
+ o = !0, n = r;
115
+ } finally {
116
+ try {
117
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
118
+ } finally {
119
+ if (o) throw n;
120
+ }
121
+ }
122
+ return a;
123
+ }
124
+ }
125
+ function _nonIterableRest() {
126
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
127
+ }
128
+ function _nonIterableSpread() {
129
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
130
+ }
131
+ function _setPrototypeOf(t, e) {
132
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
133
+ return t.__proto__ = e, t;
134
+ }, _setPrototypeOf(t, e);
135
+ }
136
+ function _slicedToArray(r, e) {
137
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
138
+ }
139
+ function _toConsumableArray(r) {
140
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
141
+ }
21
142
  function _toPrimitive(t, r) {
22
143
  if ("object" != typeof t || !t) return t;
23
144
  var e = t[Symbol.toPrimitive];
@@ -41,6 +162,13 @@
41
162
  return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
42
163
  }, _typeof(o);
43
164
  }
165
+ function _unsupportedIterableToArray(r, a) {
166
+ if (r) {
167
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
168
+ var t = {}.toString.call(r).slice(8, -1);
169
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
170
+ }
171
+ }
44
172
 
45
173
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
46
174
 
@@ -582,80 +710,12 @@
582
710
 
583
711
  var purify = {exports: {}};
584
712
 
585
- /*! @license DOMPurify 2.5.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.5.6/LICENSE */
586
713
  (function (module, exports) {
587
714
  (function (global, factory) {
588
715
  module.exports = factory() ;
589
716
  })(commonjsGlobal, function () {
590
717
 
591
- function _typeof(obj) {
592
- "@babel/helpers - typeof";
593
-
594
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
595
- return typeof obj;
596
- } : function (obj) {
597
- return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
598
- }, _typeof(obj);
599
- }
600
- function _setPrototypeOf(o, p) {
601
- _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
602
- o.__proto__ = p;
603
- return o;
604
- };
605
- return _setPrototypeOf(o, p);
606
- }
607
- function _isNativeReflectConstruct() {
608
- if (typeof Reflect === "undefined" || !Reflect.construct) return false;
609
- if (Reflect.construct.sham) return false;
610
- if (typeof Proxy === "function") return true;
611
- try {
612
- Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
613
- return true;
614
- } catch (e) {
615
- return false;
616
- }
617
- }
618
- function _construct(Parent, args, Class) {
619
- if (_isNativeReflectConstruct()) {
620
- _construct = Reflect.construct;
621
- } else {
622
- _construct = function _construct(Parent, args, Class) {
623
- var a = [null];
624
- a.push.apply(a, args);
625
- var Constructor = Function.bind.apply(Parent, a);
626
- var instance = new Constructor();
627
- if (Class) _setPrototypeOf(instance, Class.prototype);
628
- return instance;
629
- };
630
- }
631
- return _construct.apply(null, arguments);
632
- }
633
- function _toConsumableArray(arr) {
634
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
635
- }
636
- function _arrayWithoutHoles(arr) {
637
- if (Array.isArray(arr)) return _arrayLikeToArray(arr);
638
- }
639
- function _iterableToArray(iter) {
640
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
641
- }
642
- function _unsupportedIterableToArray(o, minLen) {
643
- if (!o) return;
644
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
645
- var n = Object.prototype.toString.call(o).slice(8, -1);
646
- if (n === "Object" && o.constructor) n = o.constructor.name;
647
- if (n === "Map" || n === "Set") return Array.from(o);
648
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
649
- }
650
- function _arrayLikeToArray(arr, len) {
651
- if (len == null || len > arr.length) len = arr.length;
652
- for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
653
- return arr2;
654
- }
655
- function _nonIterableSpread() {
656
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
657
- }
658
- var hasOwnProperty = Object.hasOwnProperty,
718
+ var entries = Object.entries,
659
719
  setPrototypeOf = Object.setPrototypeOf,
660
720
  isFrozen = Object.isFrozen,
661
721
  getPrototypeOf = Object.getPrototypeOf,
@@ -666,11 +726,6 @@
666
726
  var _ref = typeof Reflect !== 'undefined' && Reflect,
667
727
  apply = _ref.apply,
668
728
  construct = _ref.construct;
669
- if (!apply) {
670
- apply = function apply(fun, thisValue, args) {
671
- return fun.apply(thisValue, args);
672
- };
673
- }
674
729
  if (!freeze) {
675
730
  freeze = function freeze(x) {
676
731
  return x;
@@ -681,30 +736,53 @@
681
736
  return x;
682
737
  };
683
738
  }
739
+ if (!apply) {
740
+ apply = function apply(fun, thisValue, args) {
741
+ return fun.apply(thisValue, args);
742
+ };
743
+ }
684
744
  if (!construct) {
685
745
  construct = function construct(Func, args) {
686
746
  return _construct(Func, _toConsumableArray(args));
687
747
  };
688
748
  }
689
749
  var arrayForEach = unapply(Array.prototype.forEach);
750
+ var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
690
751
  var arrayPop = unapply(Array.prototype.pop);
691
752
  var arrayPush = unapply(Array.prototype.push);
753
+ var arraySplice = unapply(Array.prototype.splice);
692
754
  var stringToLowerCase = unapply(String.prototype.toLowerCase);
693
755
  var stringToString = unapply(String.prototype.toString);
694
756
  var stringMatch = unapply(String.prototype.match);
695
757
  var stringReplace = unapply(String.prototype.replace);
696
758
  var stringIndexOf = unapply(String.prototype.indexOf);
697
759
  var stringTrim = unapply(String.prototype.trim);
760
+ var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
698
761
  var regExpTest = unapply(RegExp.prototype.test);
699
762
  var typeErrorCreate = unconstruct(TypeError);
763
+ /**
764
+ * Creates a new function that calls the given function with a specified thisArg and arguments.
765
+ *
766
+ * @param func - The function to be wrapped and called.
767
+ * @returns A new function that calls the given function with a specified thisArg and arguments.
768
+ */
700
769
  function unapply(func) {
701
770
  return function (thisArg) {
771
+ if (thisArg instanceof RegExp) {
772
+ thisArg.lastIndex = 0;
773
+ }
702
774
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
703
775
  args[_key - 1] = arguments[_key];
704
776
  }
705
777
  return apply(func, thisArg, args);
706
778
  };
707
779
  }
780
+ /**
781
+ * Creates a new function that constructs an instance of the given constructor function with the provided arguments.
782
+ *
783
+ * @param func - The constructor function to be wrapped and called.
784
+ * @returns A new function that constructs an instance of the given constructor function with the provided arguments.
785
+ */
708
786
  function unconstruct(func) {
709
787
  return function () {
710
788
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
@@ -713,11 +791,16 @@
713
791
  return construct(func, args);
714
792
  };
715
793
  }
716
-
717
- /* Add properties to a lookup table */
718
- function addToSet(set, array, transformCaseFunc) {
719
- var _transformCaseFunc;
720
- transformCaseFunc = (_transformCaseFunc = transformCaseFunc) !== null && _transformCaseFunc !== void 0 ? _transformCaseFunc : stringToLowerCase;
794
+ /**
795
+ * Add properties to a lookup table
796
+ *
797
+ * @param set - The set to which elements will be added.
798
+ * @param array - The array containing elements to be added to the set.
799
+ * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.
800
+ * @returns The modified set with added elements.
801
+ */
802
+ function addToSet(set, array) {
803
+ var transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;
721
804
  if (setPrototypeOf) {
722
805
  // Make 'in' and truthy checks like Boolean(set.constructor)
723
806
  // independent of any properties defined on Object.prototype.
@@ -741,23 +824,61 @@
741
824
  }
742
825
  return set;
743
826
  }
744
-
745
- /* Shallow clone an object */
827
+ /**
828
+ * Clean up an array to harden against CSPP
829
+ *
830
+ * @param array - The array to be cleaned.
831
+ * @returns The cleaned version of the array
832
+ */
833
+ function cleanArray(array) {
834
+ for (var index = 0; index < array.length; index++) {
835
+ var isPropertyExist = objectHasOwnProperty(array, index);
836
+ if (!isPropertyExist) {
837
+ array[index] = null;
838
+ }
839
+ }
840
+ return array;
841
+ }
842
+ /**
843
+ * Shallow clone an object
844
+ *
845
+ * @param object - The object to be cloned.
846
+ * @returns A new object that copies the original.
847
+ */
746
848
  function clone(object) {
747
849
  var newObject = create(null);
748
- var property;
749
- for (property in object) {
750
- if (apply(hasOwnProperty, object, [property]) === true) {
751
- newObject[property] = object[property];
850
+ var _iterator = _createForOfIteratorHelper(entries(object)),
851
+ _step;
852
+ try {
853
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
854
+ var _step$value = _slicedToArray(_step.value, 2),
855
+ property = _step$value[0],
856
+ value = _step$value[1];
857
+ var isPropertyExist = objectHasOwnProperty(object, property);
858
+ if (isPropertyExist) {
859
+ if (Array.isArray(value)) {
860
+ newObject[property] = cleanArray(value);
861
+ } else if (value && _typeof(value) === 'object' && value.constructor === Object) {
862
+ newObject[property] = clone(value);
863
+ } else {
864
+ newObject[property] = value;
865
+ }
866
+ }
752
867
  }
868
+ } catch (err) {
869
+ _iterator.e(err);
870
+ } finally {
871
+ _iterator.f();
753
872
  }
754
873
  return newObject;
755
874
  }
756
-
757
- /* IE10 doesn't support __lookupGetter__ so lets'
758
- * simulate it. It also automatically checks
759
- * if the prop is function or getter and behaves
760
- * accordingly. */
875
+ /**
876
+ * This method automatically checks if the prop is function or getter and behaves accordingly.
877
+ *
878
+ * @param object - The object to look up the getter function in its prototype chain.
879
+ * @param prop - The property name for which to find the getter function.
880
+ * @returns The getter function found in the prototype chain or a fallback function.
881
+ */
761
882
  function lookupGetter(object, prop) {
762
883
  while (object !== null) {
763
884
  var desc = getOwnPropertyDescriptor(object, prop);
@@ -771,71 +892,96 @@
771
892
  }
772
893
  object = getPrototypeOf(object);
773
894
  }
774
- function fallbackValue(element) {
775
- console.warn('fallback value for', element);
895
+ function fallbackValue() {
776
896
  return null;
777
897
  }
778
898
  return fallbackValue;
779
899
  }
780
900
  var html$1 = 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', 'dialog', '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']);
781
-
782
- // SVG
783
901
  var svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', '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', 'view', 'vkern']);
784
- var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
785
-
902
+ var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
786
903
  // List of SVG elements that are disallowed by default.
787
904
  // We still need to know them so that we can do namespace
788
905
  // checks properly in case one wants to add them to
789
906
  // allow-list.
790
- var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
791
- var mathMl$1 = 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']);
792
-
907
+ var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
908
+ var mathMl$1 = 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', 'mprescripts']);
793
909
  // Similarly to SVG, we want to know all MathML elements,
794
910
  // even those that we disallow by default.
795
911
  var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
796
912
  var text = freeze(['#text']);
797
- var html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', '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', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns', 'slot']);
798
- var svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', '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', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', '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']);
913
+ var html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', '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', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
914
+ var svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', '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', 'exponent', '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', 'intercept', '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', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', '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']);
799
915
  var mathMl = 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']);
800
916
  var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
801
917
 
802
918
  // eslint-disable-next-line unicorn/better-regex
803
919
  var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
804
920
  var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
805
- var TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
806
- var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
921
+ var TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
922
+ var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
807
923
  var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
808
- 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
924
+ var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
809
925
  );
810
926
  var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
811
927
  var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
812
928
  );
813
929
  var DOCTYPE_NAME = seal(/^html$/i);
814
930
  var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
931
+ var EXPRESSIONS = /*#__PURE__*/Object.freeze({
932
+ __proto__: null,
933
+ ARIA_ATTR: ARIA_ATTR,
934
+ ATTR_WHITESPACE: ATTR_WHITESPACE,
935
+ CUSTOM_ELEMENT: CUSTOM_ELEMENT,
936
+ DATA_ATTR: DATA_ATTR,
937
+ DOCTYPE_NAME: DOCTYPE_NAME,
938
+ ERB_EXPR: ERB_EXPR,
939
+ IS_ALLOWED_URI: IS_ALLOWED_URI,
940
+ IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
941
+ MUSTACHE_EXPR: MUSTACHE_EXPR,
942
+ TMPLIT_EXPR: TMPLIT_EXPR
943
+ });
944
+
945
+ /* eslint-disable @typescript-eslint/indent */
946
+ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
947
+ var NODE_TYPE = {
948
+ element: 1,
949
+ attribute: 2,
950
+ text: 3,
951
+ cdataSection: 4,
952
+ entityReference: 5,
953
+ // Deprecated
954
+ entityNode: 6,
955
+ // Deprecated
956
+ progressingInstruction: 7,
957
+ comment: 8,
958
+ document: 9,
959
+ documentType: 10,
960
+ documentFragment: 11,
961
+ notation: 12 // Deprecated
962
+ };
815
963
  var getGlobal = function getGlobal() {
816
964
  return typeof window === 'undefined' ? null : window;
817
965
  };
818
-
819
966
  /**
820
967
  * Creates a no-op policy for internal use only.
821
968
  * Don't export this function outside this module!
822
- * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.
823
- * @param {Document} document The document object (to determine policy name suffix)
824
- * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
825
- * are not supported).
969
+ * @param trustedTypes The policy factory.
970
+ * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).
971
+ * @return The policy created (or null, if Trusted Types
972
+ * are not supported or creating the policy failed).
826
973
  */
827
- var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
974
+ var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {
828
975
  if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
829
976
  return null;
830
977
  }
831
-
832
978
  // Allow the callers to control the unique policy name
833
979
  // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
834
980
  // Policy creation with duplicate names throws in Trusted Types.
835
981
  var suffix = null;
836
982
  var ATTR_NAME = 'data-tt-policy-suffix';
837
- if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
838
- suffix = document.currentScript.getAttribute(ATTR_NAME);
983
+ if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
984
+ suffix = purifyHostElement.getAttribute(ATTR_NAME);
839
985
  }
840
986
  var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
841
987
  try {
@@ -855,31 +1001,35 @@
855
1001
  return null;
856
1002
  }
857
1003
  };
1004
+ var _createHooksMap = function _createHooksMap() {
1005
+ return {
1006
+ afterSanitizeAttributes: [],
1007
+ afterSanitizeElements: [],
1008
+ afterSanitizeShadowDOM: [],
1009
+ beforeSanitizeAttributes: [],
1010
+ beforeSanitizeElements: [],
1011
+ beforeSanitizeShadowDOM: [],
1012
+ uponSanitizeAttribute: [],
1013
+ uponSanitizeElement: [],
1014
+ uponSanitizeShadowNode: []
1015
+ };
1016
+ };
858
1017
  function createDOMPurify() {
859
1018
  var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
860
1019
  var DOMPurify = function DOMPurify(root) {
861
1020
  return createDOMPurify(root);
862
1021
  };
863
-
864
- /**
865
- * Version label, exposed for easier checks
866
- * if DOMPurify is up to date or not
867
- */
868
- DOMPurify.version = '2.5.6';
869
-
870
- /**
871
- * Array of elements that DOMPurify removed during sanitation.
872
- * Empty if nothing was removed.
873
- */
1022
+ DOMPurify.version = '3.2.5';
874
1023
  DOMPurify.removed = [];
875
- if (!window || !window.document || window.document.nodeType !== 9) {
1024
+ if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
876
1025
  // Not running in a browser, provide a factory function
877
1026
  // so that you can pass your own Window
878
1027
  DOMPurify.isSupported = false;
879
1028
  return DOMPurify;
880
1029
  }
881
- var originalDocument = window.document;
882
1030
  var document = window.document;
1031
+ var originalDocument = document;
1032
+ var currentScript = originalDocument.currentScript;
883
1033
  var DocumentFragment = window.DocumentFragment,
884
1034
  HTMLTemplateElement = window.HTMLTemplateElement,
885
1035
  Node = window.Node,
@@ -892,10 +1042,10 @@
892
1042
  trustedTypes = window.trustedTypes;
893
1043
  var ElementPrototype = Element.prototype;
894
1044
  var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
1045
+ var remove = lookupGetter(ElementPrototype, 'remove');
895
1046
  var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
896
1047
  var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
897
1048
  var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
898
-
899
1049
  // As per issue #47, the web-components registry is inherited by a
900
1050
  // new document created via createHTMLDocument. As per the spec
901
1051
  // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
@@ -908,54 +1058,45 @@
908
1058
  document = template.content.ownerDocument;
909
1059
  }
910
1060
  }
911
- var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
912
- var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
1061
+ var trustedTypesPolicy;
1062
+ var emptyHTML = '';
913
1063
  var _document = document,
914
1064
  implementation = _document.implementation,
915
1065
  createNodeIterator = _document.createNodeIterator,
916
1066
  createDocumentFragment = _document.createDocumentFragment,
917
1067
  getElementsByTagName = _document.getElementsByTagName;
918
1068
  var importNode = originalDocument.importNode;
919
- var documentMode = {};
920
- try {
921
- documentMode = clone(document).documentMode ? document.documentMode : {};
922
- } catch (_) {}
923
- var hooks = {};
924
-
1069
+ var hooks = _createHooksMap();
925
1070
  /**
926
1071
  * Expose whether this browser supports running the full DOMPurify.
927
1072
  */
928
- DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined && documentMode !== 9;
929
- var MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
930
- ERB_EXPR$1 = ERB_EXPR,
931
- TMPLIT_EXPR$1 = TMPLIT_EXPR,
932
- DATA_ATTR$1 = DATA_ATTR,
933
- ARIA_ATTR$1 = ARIA_ATTR,
934
- IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
935
- ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
936
- CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
937
- var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
938
-
1073
+ DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
1074
+ var MUSTACHE_EXPR = EXPRESSIONS.MUSTACHE_EXPR,
1075
+ ERB_EXPR = EXPRESSIONS.ERB_EXPR,
1076
+ TMPLIT_EXPR = EXPRESSIONS.TMPLIT_EXPR,
1077
+ DATA_ATTR = EXPRESSIONS.DATA_ATTR,
1078
+ ARIA_ATTR = EXPRESSIONS.ARIA_ATTR,
1079
+ IS_SCRIPT_OR_DATA = EXPRESSIONS.IS_SCRIPT_OR_DATA,
1080
+ ATTR_WHITESPACE = EXPRESSIONS.ATTR_WHITESPACE,
1081
+ CUSTOM_ELEMENT = EXPRESSIONS.CUSTOM_ELEMENT;
1082
+ var IS_ALLOWED_URI$1 = EXPRESSIONS.IS_ALLOWED_URI;
939
1083
  /**
940
1084
  * We consider the elements and attributes below to be safe. Ideally
941
1085
  * don't add any new ones but feel free to remove unwanted ones.
942
1086
  */
943
-
944
1087
  /* allowed element names */
945
1088
  var ALLOWED_TAGS = null;
946
1089
  var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
947
-
948
1090
  /* Allowed attribute names */
949
1091
  var ALLOWED_ATTR = null;
950
1092
  var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
951
-
952
1093
  /*
953
- * Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
1094
+ * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.
954
1095
  * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
955
1096
  * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
956
1097
  * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
957
1098
  */
958
- var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
1099
+ var CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
959
1100
  tagNameCheck: {
960
1101
  writable: true,
961
1102
  configurable: false,
@@ -975,65 +1116,49 @@
975
1116
  value: false
976
1117
  }
977
1118
  }));
978
-
979
1119
  /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
980
1120
  var FORBID_TAGS = null;
981
-
982
1121
  /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
983
1122
  var FORBID_ATTR = null;
984
-
985
1123
  /* Decide if ARIA attributes are okay */
986
1124
  var ALLOW_ARIA_ATTR = true;
987
-
988
1125
  /* Decide if custom data attributes are okay */
989
1126
  var ALLOW_DATA_ATTR = true;
990
-
991
1127
  /* Decide if unknown protocols are okay */
992
1128
  var ALLOW_UNKNOWN_PROTOCOLS = false;
993
-
994
1129
  /* Decide if self-closing tags in attributes are allowed.
995
1130
  * Usually removed due to a mXSS issue in jQuery 3.0 */
996
1131
  var ALLOW_SELF_CLOSE_IN_ATTR = true;
997
-
998
1132
  /* Output should be safe for common template engines.
999
1133
  * This means, DOMPurify removes data attributes, mustaches and ERB
1000
1134
  */
1001
1135
  var SAFE_FOR_TEMPLATES = false;
1002
-
1003
1136
  /* Output should be safe even for XML used within HTML and alike.
1004
1137
  * This means, DOMPurify removes comments when containing risky content.
1005
1138
  */
1006
1139
  var SAFE_FOR_XML = true;
1007
-
1008
1140
  /* Decide if document with <html>... should be returned */
1009
1141
  var WHOLE_DOCUMENT = false;
1010
-
1011
1142
  /* Track whether config is already set on this instance of DOMPurify. */
1012
1143
  var SET_CONFIG = false;
1013
-
1014
1144
  /* Decide if all elements (e.g. style, script) must be children of
1015
1145
  * document.body. By default, browsers might move them to document.head */
1016
1146
  var FORCE_BODY = false;
1017
-
1018
1147
  /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
1019
1148
  * string (or a TrustedHTML object if Trusted Types are supported).
1020
1149
  * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
1021
1150
  */
1022
1151
  var RETURN_DOM = false;
1023
-
1024
1152
  /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
1025
1153
  * string (or a TrustedHTML object if Trusted Types are supported) */
1026
1154
  var RETURN_DOM_FRAGMENT = false;
1027
-
1028
1155
  /* Try to return a Trusted Type object instead of a string, return a string in
1029
1156
  * case Trusted Types are not supported */
1030
1157
  var RETURN_TRUSTED_TYPE = false;
1031
-
1032
1158
  /* Output should be free from DOM clobbering attacks?
1033
1159
  * This sanitizes markups named with colliding, clobberable built-in DOM APIs.
1034
1160
  */
1035
1161
  var SANITIZE_DOM = true;
1036
-
1037
1162
  /* Achieve full DOM Clobbering protection by isolating the namespace of named
1038
1163
  * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
1039
1164
  *
@@ -1049,25 +1174,19 @@
1049
1174
  */
1050
1175
  var SANITIZE_NAMED_PROPS = false;
1051
1176
  var SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
1052
-
1053
1177
  /* Keep element content when removing element? */
1054
1178
  var KEEP_CONTENT = true;
1055
-
1056
1179
  /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
1057
1180
  * of importing it into a new Document and returning a sanitized copy */
1058
1181
  var IN_PLACE = false;
1059
-
1060
1182
  /* Allow usage of profiles like html, svg and mathMl */
1061
1183
  var USE_PROFILES = {};
1062
-
1063
1184
  /* Tags to ignore content of when KEEP_CONTENT is true */
1064
1185
  var FORBID_CONTENTS = null;
1065
1186
  var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
1066
-
1067
1187
  /* Tags that are safe for data: URIs */
1068
1188
  var DATA_URI_TAGS = null;
1069
1189
  var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
1070
-
1071
1190
  /* Attributes safe for values like "javascript:" */
1072
1191
  var URI_SAFE_ATTRIBUTES = null;
1073
1192
  var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
@@ -1077,75 +1196,61 @@
1077
1196
  /* Document namespace */
1078
1197
  var NAMESPACE = HTML_NAMESPACE;
1079
1198
  var IS_EMPTY_INPUT = false;
1080
-
1081
1199
  /* Allowed XHTML+XML namespaces */
1082
1200
  var ALLOWED_NAMESPACES = null;
1083
1201
  var DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
1084
-
1202
+ var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
1203
+ var HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);
1204
+ // Certain elements are allowed in both SVG and HTML
1205
+ // namespace. We need to specify them explicitly
1206
+ // so that they don't get erroneously deleted from
1207
+ // HTML namespace.
1208
+ var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
1085
1209
  /* Parsing of strict XHTML documents */
1086
- var PARSER_MEDIA_TYPE;
1210
+ var PARSER_MEDIA_TYPE = null;
1087
1211
  var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
1088
1212
  var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
1089
- var transformCaseFunc;
1090
-
1213
+ var transformCaseFunc = null;
1091
1214
  /* Keep a reference to config to pass to hooks */
1092
1215
  var CONFIG = null;
1093
-
1094
1216
  /* Ideally, do not touch anything below this line */
1095
1217
  /* ______________________________________________ */
1096
-
1097
1218
  var formElement = document.createElement('form');
1098
1219
  var isRegexOrFunction = function isRegexOrFunction(testValue) {
1099
1220
  return testValue instanceof RegExp || testValue instanceof Function;
1100
1221
  };
1101
-
1102
1222
  /**
1103
1223
  * _parseConfig
1104
1224
  *
1105
- * @param {Object} cfg optional config literal
1225
+ * @param cfg optional config literal
1106
1226
  */
1107
1227
  // eslint-disable-next-line complexity
1108
- var _parseConfig = function _parseConfig(cfg) {
1228
+ var _parseConfig = function _parseConfig() {
1229
+ var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1109
1230
  if (CONFIG && CONFIG === cfg) {
1110
1231
  return;
1111
1232
  }
1112
-
1113
1233
  /* Shield configuration object from tampering */
1114
1234
  if (!cfg || _typeof(cfg) !== 'object') {
1115
1235
  cfg = {};
1116
1236
  }
1117
-
1118
1237
  /* Shield configuration object from prototype pollution */
1119
1238
  cfg = clone(cfg);
1120
1239
  PARSER_MEDIA_TYPE =
1121
1240
  // eslint-disable-next-line unicorn/prefer-includes
1122
- SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
1123
-
1241
+ SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
1124
1242
  // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
1125
1243
  transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
1126
-
1127
1244
  /* Set configuration parameters */
1128
- ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
1129
- ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
1130
- ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
1131
- URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES),
1132
- // eslint-disable-line indent
1133
- cfg.ADD_URI_SAFE_ATTR,
1134
- // eslint-disable-line indent
1135
- transformCaseFunc // eslint-disable-line indent
1136
- ) // eslint-disable-line indent
1137
- : DEFAULT_URI_SAFE_ATTRIBUTES;
1138
- DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS),
1139
- // eslint-disable-line indent
1140
- cfg.ADD_DATA_URI_TAGS,
1141
- // eslint-disable-line indent
1142
- transformCaseFunc // eslint-disable-line indent
1143
- ) // eslint-disable-line indent
1144
- : DEFAULT_DATA_URI_TAGS;
1145
- FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
1146
- FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
1147
- FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
1148
- USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
1245
+ ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
1246
+ ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
1247
+ ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
1248
+ URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
1249
+ DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
1250
+ FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
1251
+ FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
1252
+ FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
1253
+ USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
1149
1254
  ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
1150
1255
  ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
1151
1256
  ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
@@ -1161,8 +1266,10 @@
1161
1266
  SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
1162
1267
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
1163
1268
  IN_PLACE = cfg.IN_PLACE || false; // Default false
1164
- IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
1269
+ IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
1165
1270
  NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
1271
+ MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;
1272
+ HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;
1166
1273
  CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
1167
1274
  if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
1168
1275
  CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
@@ -1179,10 +1286,9 @@
1179
1286
  if (RETURN_DOM_FRAGMENT) {
1180
1287
  RETURN_DOM = true;
1181
1288
  }
1182
-
1183
1289
  /* Parse profile info */
1184
1290
  if (USE_PROFILES) {
1185
- ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
1291
+ ALLOWED_TAGS = addToSet({}, text);
1186
1292
  ALLOWED_ATTR = [];
1187
1293
  if (USE_PROFILES.html === true) {
1188
1294
  addToSet(ALLOWED_TAGS, html$1);
@@ -1204,7 +1310,6 @@
1204
1310
  addToSet(ALLOWED_ATTR, xml);
1205
1311
  }
1206
1312
  }
1207
-
1208
1313
  /* Merge configuration parameters */
1209
1314
  if (cfg.ADD_TAGS) {
1210
1315
  if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
@@ -1227,23 +1332,40 @@
1227
1332
  }
1228
1333
  addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
1229
1334
  }
1230
-
1231
1335
  /* Add #text in case KEEP_CONTENT is set to true */
1232
1336
  if (KEEP_CONTENT) {
1233
1337
  ALLOWED_TAGS['#text'] = true;
1234
1338
  }
1235
-
1236
1339
  /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
1237
1340
  if (WHOLE_DOCUMENT) {
1238
1341
  addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
1239
1342
  }
1240
-
1241
1343
  /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
1242
1344
  if (ALLOWED_TAGS.table) {
1243
1345
  addToSet(ALLOWED_TAGS, ['tbody']);
1244
1346
  delete FORBID_TAGS.tbody;
1245
1347
  }
1246
-
1348
+ if (cfg.TRUSTED_TYPES_POLICY) {
1349
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {
1350
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
1351
+ }
1352
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {
1353
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
1354
+ }
1355
+ // Overwrite existing TrustedTypes policy.
1356
+ trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
1357
+ // Sign local variables required by `sanitize`.
1358
+ emptyHTML = trustedTypesPolicy.createHTML('');
1359
+ } else {
1360
+ // Uninitialized policy, attempt to initialize the internal dompurify policy.
1361
+ if (trustedTypesPolicy === undefined) {
1362
+ trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
1363
+ }
1364
+ // If creating the internal policy succeeded sign internal variables.
1365
+ if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
1366
+ emptyHTML = trustedTypesPolicy.createHTML('');
1367
+ }
1368
+ }
1247
1369
  // Prevent further manipulation of configuration.
1248
1370
  // Not available in IE8, Safari 5, etc.
1249
1371
  if (freeze) {
@@ -1251,35 +1373,19 @@
1251
1373
  }
1252
1374
  CONFIG = cfg;
1253
1375
  };
1254
- var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
1255
- var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'annotation-xml']);
1256
-
1257
- // Certain elements are allowed in both SVG and HTML
1258
- // namespace. We need to specify them explicitly
1259
- // so that they don't get erroneously deleted from
1260
- // HTML namespace.
1261
- var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
1262
-
1263
1376
  /* Keep track of all possible SVG and MathML tags
1264
1377
  * so that we can perform the namespace checks
1265
1378
  * correctly. */
1266
- var ALL_SVG_TAGS = addToSet({}, svg$1);
1267
- addToSet(ALL_SVG_TAGS, svgFilters);
1268
- addToSet(ALL_SVG_TAGS, svgDisallowed);
1269
- var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
1270
- addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
1271
-
1379
+ var ALL_SVG_TAGS = addToSet({}, [].concat(_toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(svgDisallowed)));
1380
+ var ALL_MATHML_TAGS = addToSet({}, [].concat(_toConsumableArray(mathMl$1), _toConsumableArray(mathMlDisallowed)));
1272
1381
  /**
1273
- *
1274
- *
1275
- * @param {Element} element a DOM element whose namespace is being checked
1276
- * @returns {boolean} Return false if the element has a
1382
+ * @param element a DOM element whose namespace is being checked
1383
+ * @returns Return false if the element has a
1277
1384
  * namespace that a spec-compliant parser would never
1278
1385
  * return. Return true otherwise.
1279
1386
  */
1280
1387
  var _checkValidNamespace = function _checkValidNamespace(element) {
1281
1388
  var parent = getParentNode(element);
1282
-
1283
1389
  // In JSDOM, if we're inside shadow DOM, then parentNode
1284
1390
  // can be null. We just simulate parent in this case.
1285
1391
  if (!parent || !parent.tagName) {
@@ -1300,14 +1406,12 @@
1300
1406
  if (parent.namespaceURI === HTML_NAMESPACE) {
1301
1407
  return tagName === 'svg';
1302
1408
  }
1303
-
1304
1409
  // The only way to switch from MathML to SVG is via`
1305
1410
  // svg if parent is either <annotation-xml> or MathML
1306
1411
  // text integration points.
1307
1412
  if (parent.namespaceURI === MATHML_NAMESPACE) {
1308
1413
  return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
1309
1414
  }
1310
-
1311
1415
  // We only allow elements that are defined in SVG
1312
1416
  // spec. All others are disallowed in SVG namespace.
1313
1417
  return Boolean(ALL_SVG_TAGS[tagName]);
@@ -1319,13 +1423,11 @@
1319
1423
  if (parent.namespaceURI === HTML_NAMESPACE) {
1320
1424
  return tagName === 'math';
1321
1425
  }
1322
-
1323
1426
  // The only way to switch from SVG to MathML is via
1324
1427
  // <math> and HTML integration points
1325
1428
  if (parent.namespaceURI === SVG_NAMESPACE) {
1326
1429
  return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
1327
1430
  }
1328
-
1329
1431
  // We only allow elements that are defined in MathML
1330
1432
  // spec. All others are disallowed in MathML namespace.
1331
1433
  return Boolean(ALL_MATHML_TAGS[tagName]);
@@ -1340,28 +1442,24 @@
1340
1442
  if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
1341
1443
  return false;
1342
1444
  }
1343
-
1344
1445
  // We disallow tags that are specific for MathML
1345
1446
  // or SVG and should never appear in HTML namespace
1346
1447
  return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
1347
1448
  }
1348
-
1349
1449
  // For XHTML and XML documents that support custom namespaces
1350
1450
  if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
1351
1451
  return true;
1352
1452
  }
1353
-
1354
1453
  // The code should never reach this place (this means
1355
1454
  // that the element somehow got namespace that is not
1356
1455
  // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
1357
1456
  // Return false just in case.
1358
1457
  return false;
1359
1458
  };
1360
-
1361
1459
  /**
1362
1460
  * _forceRemove
1363
1461
  *
1364
- * @param {Node} node a DOM node
1462
+ * @param node a DOM node
1365
1463
  */
1366
1464
  var _forceRemove = function _forceRemove(node) {
1367
1465
  arrayPush(DOMPurify.removed, {
@@ -1369,60 +1467,53 @@
1369
1467
  });
1370
1468
  try {
1371
1469
  // eslint-disable-next-line unicorn/prefer-dom-node-remove
1372
- node.parentNode.removeChild(node);
1470
+ getParentNode(node).removeChild(node);
1373
1471
  } catch (_) {
1374
- try {
1375
- node.outerHTML = emptyHTML;
1376
- } catch (_) {
1377
- node.remove();
1378
- }
1472
+ remove(node);
1379
1473
  }
1380
1474
  };
1381
-
1382
1475
  /**
1383
1476
  * _removeAttribute
1384
1477
  *
1385
- * @param {String} name an Attribute name
1386
- * @param {Node} node a DOM node
1478
+ * @param name an Attribute name
1479
+ * @param element a DOM node
1387
1480
  */
1388
- var _removeAttribute = function _removeAttribute(name, node) {
1481
+ var _removeAttribute = function _removeAttribute(name, element) {
1389
1482
  try {
1390
1483
  arrayPush(DOMPurify.removed, {
1391
- attribute: node.getAttributeNode(name),
1392
- from: node
1484
+ attribute: element.getAttributeNode(name),
1485
+ from: element
1393
1486
  });
1394
1487
  } catch (_) {
1395
1488
  arrayPush(DOMPurify.removed, {
1396
1489
  attribute: null,
1397
- from: node
1490
+ from: element
1398
1491
  });
1399
1492
  }
1400
- node.removeAttribute(name);
1401
-
1402
- // We void attribute values for unremovable "is"" attributes
1403
- if (name === 'is' && !ALLOWED_ATTR[name]) {
1493
+ element.removeAttribute(name);
1494
+ // We void attribute values for unremovable "is" attributes
1495
+ if (name === 'is') {
1404
1496
  if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
1405
1497
  try {
1406
- _forceRemove(node);
1498
+ _forceRemove(element);
1407
1499
  } catch (_) {}
1408
1500
  } else {
1409
1501
  try {
1410
- node.setAttribute(name, '');
1502
+ element.setAttribute(name, '');
1411
1503
  } catch (_) {}
1412
1504
  }
1413
1505
  }
1414
1506
  };
1415
-
1416
1507
  /**
1417
1508
  * _initDocument
1418
1509
  *
1419
- * @param {String} dirty a string of dirty markup
1420
- * @return {Document} a DOM, filled with the dirty markup
1510
+ * @param dirty - a string of dirty markup
1511
+ * @return a DOM, filled with the dirty markup
1421
1512
  */
1422
1513
  var _initDocument = function _initDocument(dirty) {
1423
1514
  /* Create a HTML document */
1424
- var doc;
1425
- var leadingWhitespace;
1515
+ var doc = null;
1516
+ var leadingWhitespace = null;
1426
1517
  if (FORCE_BODY) {
1427
1518
  dirty = '<remove></remove>' + dirty;
1428
1519
  } else {
@@ -1444,7 +1535,6 @@
1444
1535
  doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
1445
1536
  } catch (_) {}
1446
1537
  }
1447
-
1448
1538
  /* Use createHTMLDocument in case DOMParser is not available */
1449
1539
  if (!doc || !doc.documentElement) {
1450
1540
  doc = implementation.createDocument(NAMESPACE, 'template', null);
@@ -1458,132 +1548,97 @@
1458
1548
  if (dirty && leadingWhitespace) {
1459
1549
  body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
1460
1550
  }
1461
-
1462
1551
  /* Work on whole document or just its body */
1463
1552
  if (NAMESPACE === HTML_NAMESPACE) {
1464
1553
  return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
1465
1554
  }
1466
1555
  return WHOLE_DOCUMENT ? doc.documentElement : body;
1467
1556
  };
1468
-
1469
1557
  /**
1470
- * _createIterator
1558
+ * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.
1471
1559
  *
1472
- * @param {Document} root document/fragment to create iterator for
1473
- * @return {Iterator} iterator instance
1560
+ * @param root The root element or node to start traversing on.
1561
+ * @return The created NodeIterator
1474
1562
  */
1475
- var _createIterator = function _createIterator(root) {
1563
+ var _createNodeIterator = function _createNodeIterator(root) {
1476
1564
  return createNodeIterator.call(root.ownerDocument || root, root,
1477
1565
  // eslint-disable-next-line no-bitwise
1478
- NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null, false);
1566
+ NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
1479
1567
  };
1480
-
1481
1568
  /**
1482
1569
  * _isClobbered
1483
1570
  *
1484
- * @param {Node} elm element to check for clobbering attacks
1485
- * @return {Boolean} true if clobbered, false if safe
1571
+ * @param element element to check for clobbering attacks
1572
+ * @return true if clobbered, false if safe
1486
1573
  */
1487
- var _isClobbered = function _isClobbered(elm) {
1488
- return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
1574
+ var _isClobbered = function _isClobbered(element) {
1575
+ return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');
1489
1576
  };
1490
-
1491
1577
  /**
1492
- * _isNode
1578
+ * Checks whether the given object is a DOM node.
1493
1579
  *
1494
- * @param {Node} obj object to check whether it's a DOM node
1495
- * @return {Boolean} true is object is a DOM node
1580
+ * @param value object to check whether it's a DOM node
1581
+ * @return true is object is a DOM node
1496
1582
  */
1497
- var _isNode = function _isNode(object) {
1498
- return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
1583
+ var _isNode = function _isNode(value) {
1584
+ return typeof Node === 'function' && value instanceof Node;
1499
1585
  };
1500
-
1501
- /**
1502
- * _executeHook
1503
- * Execute user configurable hooks
1504
- *
1505
- * @param {String} entryPoint Name of the hook's entry point
1506
- * @param {Node} currentNode node to work on with the hook
1507
- * @param {Object} data additional hook parameters
1508
- */
1509
- var _executeHook = function _executeHook(entryPoint, currentNode, data) {
1510
- if (!hooks[entryPoint]) {
1511
- return;
1512
- }
1513
- arrayForEach(hooks[entryPoint], function (hook) {
1586
+ function _executeHooks(hooks, currentNode, data) {
1587
+ arrayForEach(hooks, function (hook) {
1514
1588
  hook.call(DOMPurify, currentNode, data, CONFIG);
1515
1589
  });
1516
- };
1517
-
1590
+ }
1518
1591
  /**
1519
1592
  * _sanitizeElements
1520
1593
  *
1521
1594
  * @protect nodeName
1522
1595
  * @protect textContent
1523
1596
  * @protect removeChild
1524
- *
1525
- * @param {Node} currentNode to check for permission to exist
1526
- * @return {Boolean} true if node was killed, false if left alive
1597
+ * @param currentNode to check for permission to exist
1598
+ * @return true if node was killed, false if left alive
1527
1599
  */
1528
1600
  var _sanitizeElements = function _sanitizeElements(currentNode) {
1529
- var content;
1530
-
1601
+ var content = null;
1531
1602
  /* Execute a hook if present */
1532
- _executeHook('beforeSanitizeElements', currentNode, null);
1533
-
1603
+ _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
1534
1604
  /* Check if element is clobbered or can clobber */
1535
1605
  if (_isClobbered(currentNode)) {
1536
1606
  _forceRemove(currentNode);
1537
1607
  return true;
1538
1608
  }
1539
-
1540
- /* Check if tagname contains Unicode */
1541
- if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
1542
- _forceRemove(currentNode);
1543
- return true;
1544
- }
1545
-
1546
1609
  /* Now let's check the element's type and name */
1547
1610
  var tagName = transformCaseFunc(currentNode.nodeName);
1548
-
1549
1611
  /* Execute a hook if present */
1550
- _executeHook('uponSanitizeElement', currentNode, {
1612
+ _executeHooks(hooks.uponSanitizeElement, currentNode, {
1551
1613
  tagName: tagName,
1552
1614
  allowedTags: ALLOWED_TAGS
1553
1615
  });
1554
-
1555
1616
  /* Detect mXSS attempts abusing namespace confusion */
1556
- if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
1617
+ if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\w!]/g, currentNode.textContent)) {
1557
1618
  _forceRemove(currentNode);
1558
1619
  return true;
1559
1620
  }
1560
-
1561
- /* Mitigate a problem with templates inside select */
1562
- if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
1621
+ /* Remove any occurrence of processing instructions */
1622
+ if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
1563
1623
  _forceRemove(currentNode);
1564
1624
  return true;
1565
1625
  }
1566
-
1567
- /* Remove any ocurrence of processing instructions */
1568
- if (currentNode.nodeType === 7) {
1569
- _forceRemove(currentNode);
1570
- return true;
1571
- }
1572
-
1573
1626
  /* Remove any kind of possibly harmful comments */
1574
- if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\w]/g, currentNode.data)) {
1627
+ if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\w]/g, currentNode.data)) {
1575
1628
  _forceRemove(currentNode);
1576
1629
  return true;
1577
1630
  }
1578
-
1579
1631
  /* Remove element if anything forbids its presence */
1580
1632
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
1581
1633
  /* Check if we have a custom element to handle */
1582
- if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
1583
- if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
1584
- if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
1634
+ if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
1635
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
1636
+ return false;
1637
+ }
1638
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
1639
+ return false;
1640
+ }
1585
1641
  }
1586
-
1587
1642
  /* Keep content except for bad-listed elements */
1588
1643
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
1589
1644
  var parentNode = getParentNode(currentNode) || currentNode.parentNode;
@@ -1600,26 +1655,23 @@
1600
1655
  _forceRemove(currentNode);
1601
1656
  return true;
1602
1657
  }
1603
-
1604
1658
  /* Check whether element has a valid namespace */
1605
1659
  if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
1606
1660
  _forceRemove(currentNode);
1607
1661
  return true;
1608
1662
  }
1609
-
1610
1663
  /* Make sure that older browsers don't get fallback-tag mXSS */
1611
1664
  if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
1612
1665
  _forceRemove(currentNode);
1613
1666
  return true;
1614
1667
  }
1615
-
1616
1668
  /* Sanitize element content to be template-safe */
1617
- if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
1669
+ if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
1618
1670
  /* Get the element's text content */
1619
1671
  content = currentNode.textContent;
1620
- content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
1621
- content = stringReplace(content, ERB_EXPR$1, ' ');
1622
- content = stringReplace(content, TMPLIT_EXPR$1, ' ');
1672
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], function (expr) {
1673
+ content = stringReplace(content, expr, ' ');
1674
+ });
1623
1675
  if (currentNode.textContent !== content) {
1624
1676
  arrayPush(DOMPurify.removed, {
1625
1677
  element: currentNode.cloneNode()
@@ -1627,19 +1679,17 @@
1627
1679
  currentNode.textContent = content;
1628
1680
  }
1629
1681
  }
1630
-
1631
1682
  /* Execute a hook if present */
1632
- _executeHook('afterSanitizeElements', currentNode, null);
1683
+ _executeHooks(hooks.afterSanitizeElements, currentNode, null);
1633
1684
  return false;
1634
1685
  };
1635
-
1636
1686
  /**
1637
1687
  * _isValidAttribute
1638
1688
  *
1639
- * @param {string} lcTag Lowercase tag name of containing element.
1640
- * @param {string} lcName Lowercase attribute name.
1641
- * @param {string} value Attribute value.
1642
- * @return {Boolean} Returns true if `value` is valid, otherwise false.
1689
+ * @param lcTag Lowercase tag name of containing element.
1690
+ * @param lcName Lowercase attribute name.
1691
+ * @param value Attribute value.
1692
+ * @return Returns true if `value` is valid, otherwise false.
1643
1693
  */
1644
1694
  // eslint-disable-next-line complexity
1645
1695
  var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
@@ -1647,39 +1697,38 @@
1647
1697
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1648
1698
  return false;
1649
1699
  }
1650
-
1651
1700
  /* Allow valid data-* attributes: At least one character after "-"
1652
1701
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1653
1702
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1654
1703
  We don't need to check the value; it's always URI safe. */
1655
- if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
1704
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ;else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
1656
1705
  if (
1657
1706
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
1658
1707
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1659
1708
  // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
1660
- _basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||
1709
+ _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||
1661
1710
  // Alternative, second condition checks if it's an `is`-attribute, AND
1662
1711
  // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
1663
1712
  lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ;else {
1664
1713
  return false;
1665
1714
  }
1666
1715
  /* Check value is safe. First, is attr inert? If so, is safe */
1667
- } else if (URI_SAFE_ATTRIBUTES[lcName]) ;else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ;else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ;else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ;else if (value) {
1716
+ } else if (URI_SAFE_ATTRIBUTES[lcName]) ;else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ;else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ;else if (value) {
1668
1717
  return false;
1669
1718
  } else ;
1670
1719
  return true;
1671
1720
  };
1672
-
1673
1721
  /**
1674
- * _basicCustomElementCheck
1722
+ * _isBasicCustomElement
1675
1723
  * checks if at least one dash is included in tagName, and it's not the first char
1676
1724
  * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
1677
- * @param {string} tagName name of the tag of the node to sanitize
1725
+ *
1726
+ * @param tagName name of the tag of the node to sanitize
1727
+ * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
1678
1728
  */
1679
- var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
1680
- return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT$1);
1729
+ var _isBasicCustomElement = function _isBasicCustomElement(tagName) {
1730
+ return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);
1681
1731
  };
1682
-
1683
1732
  /**
1684
1733
  * _sanitizeAttributes
1685
1734
  *
@@ -1688,181 +1737,151 @@
1688
1737
  * @protect removeAttribute
1689
1738
  * @protect setAttribute
1690
1739
  *
1691
- * @param {Node} currentNode to sanitize
1740
+ * @param currentNode to sanitize
1692
1741
  */
1693
1742
  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1694
- var attr;
1695
- var value;
1696
- var lcName;
1697
- var l;
1698
1743
  /* Execute a hook if present */
1699
- _executeHook('beforeSanitizeAttributes', currentNode, null);
1744
+ _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
1700
1745
  var attributes = currentNode.attributes;
1701
-
1702
1746
  /* Check if we have attributes; if not we might have a text node */
1703
- if (!attributes) {
1747
+ if (!attributes || _isClobbered(currentNode)) {
1704
1748
  return;
1705
1749
  }
1706
1750
  var hookEvent = {
1707
1751
  attrName: '',
1708
1752
  attrValue: '',
1709
1753
  keepAttr: true,
1710
- allowedAttributes: ALLOWED_ATTR
1754
+ allowedAttributes: ALLOWED_ATTR,
1755
+ forceKeepAttr: undefined
1711
1756
  };
1712
- l = attributes.length;
1713
-
1757
+ var l = attributes.length;
1714
1758
  /* Go backwards over all attributes; safely remove bad ones */
1715
- while (l--) {
1716
- attr = attributes[l];
1717
- var _attr = attr,
1718
- name = _attr.name,
1719
- namespaceURI = _attr.namespaceURI;
1720
- value = name === 'value' ? attr.value : stringTrim(attr.value);
1721
- lcName = transformCaseFunc(name);
1722
-
1723
- /* Execute a hook if present */
1724
- hookEvent.attrName = lcName;
1725
- hookEvent.attrValue = value;
1726
- hookEvent.keepAttr = true;
1727
- hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1728
- _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1729
- value = hookEvent.attrValue;
1730
-
1731
- /* Work around a security issue with comments inside attributes */
1732
- if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
1733
- _removeAttribute(name, currentNode);
1734
- continue;
1735
- }
1736
-
1737
- /* Did the hooks approve of the attribute? */
1738
- if (hookEvent.forceKeepAttr) {
1739
- continue;
1740
- }
1741
-
1742
- /* Remove attribute */
1743
- _removeAttribute(name, currentNode);
1744
-
1745
- /* Did the hooks approve of the attribute? */
1746
- if (!hookEvent.keepAttr) {
1747
- continue;
1748
- }
1749
-
1750
- /* Work around a security issue in jQuery 3.0 */
1751
- if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
1752
- _removeAttribute(name, currentNode);
1753
- continue;
1754
- }
1755
-
1756
- /* Sanitize attribute content to be template-safe */
1757
- if (SAFE_FOR_TEMPLATES) {
1758
- value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
1759
- value = stringReplace(value, ERB_EXPR$1, ' ');
1760
- value = stringReplace(value, TMPLIT_EXPR$1, ' ');
1761
- }
1762
-
1763
- /* Is `value` valid for this attribute? */
1764
- var lcTag = transformCaseFunc(currentNode.nodeName);
1765
- if (!_isValidAttribute(lcTag, lcName, value)) {
1766
- continue;
1767
- }
1768
-
1769
- /* Full DOM Clobbering protection via namespace isolation,
1770
- * Prefix id and name attributes with `user-content-`
1771
- */
1772
- if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
1773
- // Remove the attribute with this value
1759
+ var _loop = function _loop() {
1760
+ var attr = attributes[l];
1761
+ var name = attr.name,
1762
+ namespaceURI = attr.namespaceURI,
1763
+ attrValue = attr.value;
1764
+ var lcName = transformCaseFunc(name);
1765
+ var value = name === 'value' ? attrValue : stringTrim(attrValue);
1766
+ /* Execute a hook if present */
1767
+ hookEvent.attrName = lcName;
1768
+ hookEvent.attrValue = value;
1769
+ hookEvent.keepAttr = true;
1770
+ hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1771
+ _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
1772
+ value = hookEvent.attrValue;
1773
+ /* Full DOM Clobbering protection via namespace isolation,
1774
+ * Prefix id and name attributes with `user-content-`
1775
+ */
1776
+ if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
1777
+ // Remove the attribute with this value
1778
+ _removeAttribute(name, currentNode);
1779
+ // Prefix the value and later re-create the attribute with the sanitized value
1780
+ value = SANITIZE_NAMED_PROPS_PREFIX + value;
1781
+ }
1782
+ /* Work around a security issue with comments inside attributes */
1783
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
1784
+ _removeAttribute(name, currentNode);
1785
+ return 0; // continue
1786
+ }
1787
+ /* Did the hooks approve of the attribute? */
1788
+ if (hookEvent.forceKeepAttr) {
1789
+ return 0; // continue
1790
+ }
1791
+ /* Remove attribute */
1774
1792
  _removeAttribute(name, currentNode);
1775
-
1776
- // Prefix the value and later re-create the attribute with the sanitized value
1777
- value = SANITIZE_NAMED_PROPS_PREFIX + value;
1778
- }
1779
-
1780
- /* Handle attributes that require Trusted Types */
1781
- if (trustedTypesPolicy && _typeof(trustedTypes) === 'object' && typeof trustedTypes.getAttributeType === 'function') {
1782
- if (namespaceURI) ;else {
1783
- switch (trustedTypes.getAttributeType(lcTag, lcName)) {
1784
- case 'TrustedHTML':
1785
- {
1786
- value = trustedTypesPolicy.createHTML(value);
1787
- break;
1788
- }
1789
- case 'TrustedScriptURL':
1790
- {
1791
- value = trustedTypesPolicy.createScriptURL(value);
1792
- break;
1793
- }
1794
- }
1793
+ /* Did the hooks approve of the attribute? */
1794
+ if (!hookEvent.keepAttr) {
1795
+ return 0; // continue
1795
1796
  }
1796
- }
1797
-
1798
- /* Handle invalid data-* attribute set by try-catching it */
1799
- try {
1800
- if (namespaceURI) {
1801
- currentNode.setAttributeNS(namespaceURI, name, value);
1802
- } else {
1803
- /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1804
- currentNode.setAttribute(name, value);
1797
+ /* Work around a security issue in jQuery 3.0 */
1798
+ if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
1799
+ _removeAttribute(name, currentNode);
1800
+ return 0; // continue
1805
1801
  }
1806
- if (_isClobbered(currentNode)) {
1807
- _forceRemove(currentNode);
1808
- } else {
1809
- arrayPop(DOMPurify.removed);
1802
+ /* Sanitize attribute content to be template-safe */
1803
+ if (SAFE_FOR_TEMPLATES) {
1804
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], function (expr) {
1805
+ value = stringReplace(value, expr, ' ');
1806
+ });
1810
1807
  }
1811
- } catch (_) {}
1808
+ /* Is `value` valid for this attribute? */
1809
+ var lcTag = transformCaseFunc(currentNode.nodeName);
1810
+ if (!_isValidAttribute(lcTag, lcName, value)) {
1811
+ return 0; // continue
1812
+ }
1813
+ /* Handle attributes that require Trusted Types */
1814
+ if (trustedTypesPolicy && _typeof(trustedTypes) === 'object' && typeof trustedTypes.getAttributeType === 'function') {
1815
+ if (namespaceURI) ;else {
1816
+ switch (trustedTypes.getAttributeType(lcTag, lcName)) {
1817
+ case 'TrustedHTML':
1818
+ {
1819
+ value = trustedTypesPolicy.createHTML(value);
1820
+ break;
1821
+ }
1822
+ case 'TrustedScriptURL':
1823
+ {
1824
+ value = trustedTypesPolicy.createScriptURL(value);
1825
+ break;
1826
+ }
1827
+ }
1828
+ }
1829
+ }
1830
+ /* Handle invalid data-* attribute set by try-catching it */
1831
+ try {
1832
+ if (namespaceURI) {
1833
+ currentNode.setAttributeNS(namespaceURI, name, value);
1834
+ } else {
1835
+ /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
1836
+ currentNode.setAttribute(name, value);
1837
+ }
1838
+ if (_isClobbered(currentNode)) {
1839
+ _forceRemove(currentNode);
1840
+ } else {
1841
+ arrayPop(DOMPurify.removed);
1842
+ }
1843
+ } catch (_) {}
1844
+ },
1845
+ _ret;
1846
+ while (l--) {
1847
+ _ret = _loop();
1848
+ if (_ret === 0) continue;
1812
1849
  }
1813
-
1814
1850
  /* Execute a hook if present */
1815
- _executeHook('afterSanitizeAttributes', currentNode, null);
1851
+ _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
1816
1852
  };
1817
-
1818
1853
  /**
1819
1854
  * _sanitizeShadowDOM
1820
1855
  *
1821
- * @param {DocumentFragment} fragment to iterate over recursively
1856
+ * @param fragment to iterate over recursively
1822
1857
  */
1823
1858
  var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1824
- var shadowNode;
1825
- var shadowIterator = _createIterator(fragment);
1826
-
1859
+ var shadowNode = null;
1860
+ var shadowIterator = _createNodeIterator(fragment);
1827
1861
  /* Execute a hook if present */
1828
- _executeHook('beforeSanitizeShadowDOM', fragment, null);
1862
+ _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
1829
1863
  while (shadowNode = shadowIterator.nextNode()) {
1830
1864
  /* Execute a hook if present */
1831
- _executeHook('uponSanitizeShadowNode', shadowNode, null);
1832
-
1865
+ _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
1833
1866
  /* Sanitize tags and elements */
1834
- if (_sanitizeElements(shadowNode)) {
1835
- continue;
1836
- }
1837
-
1867
+ _sanitizeElements(shadowNode);
1868
+ /* Check attributes next */
1869
+ _sanitizeAttributes(shadowNode);
1838
1870
  /* Deep shadow DOM detected */
1839
1871
  if (shadowNode.content instanceof DocumentFragment) {
1840
1872
  _sanitizeShadowDOM(shadowNode.content);
1841
1873
  }
1842
-
1843
- /* Check attributes, sanitize if necessary */
1844
- _sanitizeAttributes(shadowNode);
1845
1874
  }
1846
-
1847
1875
  /* Execute a hook if present */
1848
- _executeHook('afterSanitizeShadowDOM', fragment, null);
1876
+ _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
1849
1877
  };
1850
-
1851
- /**
1852
- * Sanitize
1853
- * Public method providing core sanitation functionality
1854
- *
1855
- * @param {String|Node} dirty string or DOM node
1856
- * @param {Object} configuration object
1857
- */
1858
1878
  // eslint-disable-next-line complexity
1859
1879
  DOMPurify.sanitize = function (dirty) {
1860
1880
  var cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1861
- var body;
1862
- var importedNode;
1863
- var currentNode;
1864
- var oldNode;
1865
- var returnNode;
1881
+ var body = null;
1882
+ var importedNode = null;
1883
+ var currentNode = null;
1884
+ var returnNode = null;
1866
1885
  /* Make sure we have a string to sanitize.
1867
1886
  DO NOT return early, as this will return the wrong type if
1868
1887
  the user has requested a DOM object rather than a string */
@@ -1870,7 +1889,6 @@
1870
1889
  if (IS_EMPTY_INPUT) {
1871
1890
  dirty = '<!-->';
1872
1891
  }
1873
-
1874
1892
  /* Stringify, in case dirty is an object */
1875
1893
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
1876
1894
  if (typeof dirty.toString === 'function') {
@@ -1882,28 +1900,16 @@
1882
1900
  throw typeErrorCreate('toString is not a function');
1883
1901
  }
1884
1902
  }
1885
-
1886
- /* Check we can run. Otherwise fall back or ignore */
1903
+ /* Return dirty HTML if DOMPurify cannot run */
1887
1904
  if (!DOMPurify.isSupported) {
1888
- if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1889
- if (typeof dirty === 'string') {
1890
- return window.toStaticHTML(dirty);
1891
- }
1892
- if (_isNode(dirty)) {
1893
- return window.toStaticHTML(dirty.outerHTML);
1894
- }
1895
- }
1896
1905
  return dirty;
1897
1906
  }
1898
-
1899
1907
  /* Assign config vars */
1900
1908
  if (!SET_CONFIG) {
1901
1909
  _parseConfig(cfg);
1902
1910
  }
1903
-
1904
1911
  /* Clean up removed elements */
1905
1912
  DOMPurify.removed = [];
1906
-
1907
1913
  /* Check if dirty is correctly typed for IN_PLACE */
1908
1914
  if (typeof dirty === 'string') {
1909
1915
  IN_PLACE = false;
@@ -1921,7 +1927,7 @@
1921
1927
  elements being stripped by the parser */
1922
1928
  body = _initDocument('<!---->');
1923
1929
  importedNode = body.ownerDocument.importNode(dirty, true);
1924
- if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
1930
+ if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {
1925
1931
  /* Node is already a body, use as is */
1926
1932
  body = importedNode;
1927
1933
  } else if (importedNode.nodeName === 'HTML') {
@@ -1937,52 +1943,34 @@
1937
1943
  dirty.indexOf('<') === -1) {
1938
1944
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
1939
1945
  }
1940
-
1941
1946
  /* Initialize the document to work on */
1942
1947
  body = _initDocument(dirty);
1943
-
1944
1948
  /* Check we have a DOM node from the data */
1945
1949
  if (!body) {
1946
1950
  return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
1947
1951
  }
1948
1952
  }
1949
-
1950
1953
  /* Remove first element node (ours) if FORCE_BODY is set */
1951
1954
  if (body && FORCE_BODY) {
1952
1955
  _forceRemove(body.firstChild);
1953
1956
  }
1954
-
1955
1957
  /* Get node iterator */
1956
- var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1957
-
1958
+ var nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);
1958
1959
  /* Now start iterating over the created document */
1959
1960
  while (currentNode = nodeIterator.nextNode()) {
1960
- /* Fix IE's strange behavior with manipulated textNodes #89 */
1961
- if (currentNode.nodeType === 3 && currentNode === oldNode) {
1962
- continue;
1963
- }
1964
-
1965
1961
  /* Sanitize tags and elements */
1966
- if (_sanitizeElements(currentNode)) {
1967
- continue;
1968
- }
1969
-
1962
+ _sanitizeElements(currentNode);
1963
+ /* Check attributes next */
1964
+ _sanitizeAttributes(currentNode);
1970
1965
  /* Shadow DOM detected, sanitize it */
1971
1966
  if (currentNode.content instanceof DocumentFragment) {
1972
1967
  _sanitizeShadowDOM(currentNode.content);
1973
1968
  }
1974
-
1975
- /* Check attributes, sanitize if necessary */
1976
- _sanitizeAttributes(currentNode);
1977
- oldNode = currentNode;
1978
1969
  }
1979
- oldNode = null;
1980
-
1981
1970
  /* If we sanitized `dirty` in-place, return it. */
1982
1971
  if (IN_PLACE) {
1983
1972
  return dirty;
1984
1973
  }
1985
-
1986
1974
  /* Return sanitized string or DOM */
1987
1975
  if (RETURN_DOM) {
1988
1976
  if (RETURN_DOM_FRAGMENT) {
@@ -1994,7 +1982,7 @@
1994
1982
  } else {
1995
1983
  returnNode = body;
1996
1984
  }
1997
- if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmod) {
1985
+ if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
1998
1986
  /*
1999
1987
  AdoptNode() is not used because internal state is not reset
2000
1988
  (e.g. the past names map of a HTMLFormElement), this is safe
@@ -2007,52 +1995,27 @@
2007
1995
  return returnNode;
2008
1996
  }
2009
1997
  var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
2010
-
2011
1998
  /* Serialize doctype if allowed */
2012
1999
  if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
2013
2000
  serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
2014
2001
  }
2015
-
2016
2002
  /* Sanitize final string template-safe */
2017
2003
  if (SAFE_FOR_TEMPLATES) {
2018
- serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
2019
- serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
2020
- serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR$1, ' ');
2004
+ arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], function (expr) {
2005
+ serializedHTML = stringReplace(serializedHTML, expr, ' ');
2006
+ });
2021
2007
  }
2022
2008
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
2023
2009
  };
2024
-
2025
- /**
2026
- * Public method to set the configuration once
2027
- * setConfig
2028
- *
2029
- * @param {Object} cfg configuration object
2030
- */
2031
- DOMPurify.setConfig = function (cfg) {
2010
+ DOMPurify.setConfig = function () {
2011
+ var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
2032
2012
  _parseConfig(cfg);
2033
2013
  SET_CONFIG = true;
2034
2014
  };
2035
-
2036
- /**
2037
- * Public method to remove the configuration
2038
- * clearConfig
2039
- *
2040
- */
2041
2015
  DOMPurify.clearConfig = function () {
2042
2016
  CONFIG = null;
2043
2017
  SET_CONFIG = false;
2044
2018
  };
2045
-
2046
- /**
2047
- * Public method to check if an attribute value is valid.
2048
- * Uses last set config, if any. Otherwise, uses config defaults.
2049
- * isValidAttribute
2050
- *
2051
- * @param {string} tag Tag name of containing element.
2052
- * @param {string} attr Attribute name.
2053
- * @param {string} value Attribute value.
2054
- * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
2055
- */
2056
2019
  DOMPurify.isValidAttribute = function (tag, attr, value) {
2057
2020
  /* Initialize shared config vars if necessary. */
2058
2021
  if (!CONFIG) {
@@ -2062,55 +2025,24 @@
2062
2025
  var lcName = transformCaseFunc(attr);
2063
2026
  return _isValidAttribute(lcTag, lcName, value);
2064
2027
  };
2065
-
2066
- /**
2067
- * AddHook
2068
- * Public method to add DOMPurify hooks
2069
- *
2070
- * @param {String} entryPoint entry point for the hook to add
2071
- * @param {Function} hookFunction function to execute
2072
- */
2073
2028
  DOMPurify.addHook = function (entryPoint, hookFunction) {
2074
2029
  if (typeof hookFunction !== 'function') {
2075
2030
  return;
2076
2031
  }
2077
- hooks[entryPoint] = hooks[entryPoint] || [];
2078
2032
  arrayPush(hooks[entryPoint], hookFunction);
2079
2033
  };
2080
-
2081
- /**
2082
- * RemoveHook
2083
- * Public method to remove a DOMPurify hook at a given entryPoint
2084
- * (pops it from the stack of hooks if more are present)
2085
- *
2086
- * @param {String} entryPoint entry point for the hook to remove
2087
- * @return {Function} removed(popped) hook
2088
- */
2089
- DOMPurify.removeHook = function (entryPoint) {
2090
- if (hooks[entryPoint]) {
2091
- return arrayPop(hooks[entryPoint]);
2034
+ DOMPurify.removeHook = function (entryPoint, hookFunction) {
2035
+ if (hookFunction !== undefined) {
2036
+ var index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
2037
+ return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];
2092
2038
  }
2039
+ return arrayPop(hooks[entryPoint]);
2093
2040
  };
2094
-
2095
- /**
2096
- * RemoveHooks
2097
- * Public method to remove all DOMPurify hooks at a given entryPoint
2098
- *
2099
- * @param {String} entryPoint entry point for the hooks to remove
2100
- */
2101
2041
  DOMPurify.removeHooks = function (entryPoint) {
2102
- if (hooks[entryPoint]) {
2103
- hooks[entryPoint] = [];
2104
- }
2042
+ hooks[entryPoint] = [];
2105
2043
  };
2106
-
2107
- /**
2108
- * RemoveAllHooks
2109
- * Public method to remove all DOMPurify hooks
2110
- *
2111
- */
2112
2044
  DOMPurify.removeAllHooks = function () {
2113
- hooks = {};
2045
+ hooks = _createHooksMap();
2114
2046
  };
2115
2047
  return DOMPurify;
2116
2048
  }
@@ -4940,10 +4872,10 @@
4940
4872
  * @type {object} Settings object
4941
4873
  * @property {string} [stablePrefix=c4d] stable prefix
4942
4874
  * @property {string} [prefix=cds] core Carbon prefix
4943
- * Carbon for IBM.com v2.22.0',
4875
+ * Carbon for IBM.com v2.24.0',
4944
4876
  */
4945
4877
  var settings = {
4946
- version: 'Carbon for IBM.com v2.22.0',
4878
+ version: 'Carbon for IBM.com v2.24.0',
4947
4879
  stablePrefix: 'c4d',
4948
4880
  prefix: 'cds'
4949
4881
  };