@carbon/ibmdotcom-utilities 2.9.0 → 2.10.0-canary.9119336364.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.
@@ -590,7 +590,7 @@
590
590
 
591
591
  var purify = {exports: {}};
592
592
 
593
- /*! @license DOMPurify 2.4.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.7/LICENSE */
593
+ /*! @license DOMPurify 2.5.0 | (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.0/LICENSE */
594
594
  (function (module, exports) {
595
595
  (function (global, factory) {
596
596
  module.exports = factory() ;
@@ -671,7 +671,6 @@
671
671
  var freeze = Object.freeze,
672
672
  seal = Object.seal,
673
673
  create = Object.create; // eslint-disable-line import/no-mutable-exports
674
-
675
674
  var _ref = typeof Reflect !== 'undefined' && Reflect,
676
675
  apply = _ref.apply,
677
676
  construct = _ref.construct;
@@ -722,8 +721,8 @@
722
721
  return construct(func, args);
723
722
  };
724
723
  }
725
- /* Add properties to a lookup table */
726
724
 
725
+ /* Add properties to a lookup table */
727
726
  function addToSet(set, array, transformCaseFunc) {
728
727
  var _transformCaseFunc;
729
728
  transformCaseFunc = (_transformCaseFunc = transformCaseFunc) !== null && _transformCaseFunc !== void 0 ? _transformCaseFunc : stringToLowerCase;
@@ -750,8 +749,8 @@
750
749
  }
751
750
  return set;
752
751
  }
753
- /* Shallow clone an object */
754
752
 
753
+ /* Shallow clone an object */
755
754
  function clone(object) {
756
755
  var newObject = create(null);
757
756
  var property;
@@ -762,11 +761,11 @@
762
761
  }
763
762
  return newObject;
764
763
  }
764
+
765
765
  /* IE10 doesn't support __lookupGetter__ so lets'
766
766
  * simulate it. It also automatically checks
767
767
  * if the prop is function or getter and behaves
768
768
  * accordingly. */
769
-
770
769
  function lookupGetter(object, prop) {
771
770
  while (object !== null) {
772
771
  var desc = getOwnPropertyDescriptor(object, prop);
@@ -786,41 +785,45 @@
786
785
  }
787
786
  return fallbackValue;
788
787
  }
789
- 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']); // SVG
788
+ 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']);
790
789
 
790
+ // SVG
791
791
  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']);
792
- 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']); // List of SVG elements that are disallowed by default.
792
+ 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']);
793
+
794
+ // List of SVG elements that are disallowed by default.
793
795
  // We still need to know them so that we can do namespace
794
796
  // checks properly in case one wants to add them to
795
797
  // allow-list.
796
-
797
798
  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']);
798
- 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']); // Similarly to SVG, we want to know all MathML elements,
799
- // even those that we disallow by default.
799
+ 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']);
800
800
 
801
+ // Similarly to SVG, we want to know all MathML elements,
802
+ // even those that we disallow by default.
801
803
  var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
802
804
  var text = freeze(['#text']);
803
805
  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']);
804
806
  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']);
805
807
  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']);
806
808
  var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
807
- var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
808
809
 
810
+ // eslint-disable-next-line unicorn/better-regex
811
+ var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
809
812
  var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
810
813
  var TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
811
814
  var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/); // eslint-disable-line no-useless-escape
812
-
813
815
  var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
814
-
815
816
  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
816
817
  );
817
818
  var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
818
819
  var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
819
820
  );
820
821
  var DOCTYPE_NAME = seal(/^html$/i);
822
+ var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
821
823
  var getGlobal = function getGlobal() {
822
824
  return typeof window === 'undefined' ? null : window;
823
825
  };
826
+
824
827
  /**
825
828
  * Creates a no-op policy for internal use only.
826
829
  * Don't export this function outside this module!
@@ -829,14 +832,14 @@
829
832
  * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
830
833
  * are not supported).
831
834
  */
832
-
833
835
  var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
834
836
  if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
835
837
  return null;
836
- } // Allow the callers to control the unique policy name
838
+ }
839
+
840
+ // Allow the callers to control the unique policy name
837
841
  // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
838
842
  // Policy creation with duplicate names throws in Trusted Types.
839
-
840
843
  var suffix = null;
841
844
  var ATTR_NAME = 'data-tt-policy-suffix';
842
845
  if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
@@ -865,17 +868,17 @@
865
868
  var DOMPurify = function DOMPurify(root) {
866
869
  return createDOMPurify(root);
867
870
  };
871
+
868
872
  /**
869
873
  * Version label, exposed for easier checks
870
874
  * if DOMPurify is up to date or not
871
875
  */
876
+ DOMPurify.version = '2.5.0';
872
877
 
873
- DOMPurify.version = '2.4.7';
874
878
  /**
875
879
  * Array of elements that DOMPurify removed during sanitation.
876
880
  * Empty if nothing was removed.
877
881
  */
878
-
879
882
  DOMPurify.removed = [];
880
883
  if (!window || !window.document || window.document.nodeType !== 9) {
881
884
  // Not running in a browser, provide a factory function
@@ -899,13 +902,14 @@
899
902
  var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
900
903
  var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
901
904
  var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
902
- var getParentNode = lookupGetter(ElementPrototype, 'parentNode'); // As per issue #47, the web-components registry is inherited by a
905
+ var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
906
+
907
+ // As per issue #47, the web-components registry is inherited by a
903
908
  // new document created via createHTMLDocument. As per the spec
904
909
  // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
905
910
  // a new empty registry is used when creating a template contents owner
906
911
  // document, so we use that as our parent document to ensure nothing
907
912
  // is inherited.
908
-
909
913
  if (typeof HTMLTemplateElement === 'function') {
910
914
  var template = document.createElement('template');
911
915
  if (template.content && template.content.ownerDocument) {
@@ -925,10 +929,10 @@
925
929
  documentMode = clone(document).documentMode ? document.documentMode : {};
926
930
  } catch (_) {}
927
931
  var hooks = {};
932
+
928
933
  /**
929
934
  * Expose whether this browser supports running the full DOMPurify.
930
935
  */
931
-
932
936
  DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined && documentMode !== 9;
933
937
  var MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
934
938
  ERB_EXPR$1 = ERB_EXPR,
@@ -936,28 +940,29 @@
936
940
  DATA_ATTR$1 = DATA_ATTR,
937
941
  ARIA_ATTR$1 = ARIA_ATTR,
938
942
  IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
939
- ATTR_WHITESPACE$1 = ATTR_WHITESPACE;
943
+ ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
944
+ CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
940
945
  var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
946
+
941
947
  /**
942
948
  * We consider the elements and attributes below to be safe. Ideally
943
949
  * don't add any new ones but feel free to remove unwanted ones.
944
950
  */
945
951
 
946
952
  /* allowed element names */
947
-
948
953
  var ALLOWED_TAGS = null;
949
954
  var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
950
- /* Allowed attribute names */
951
955
 
956
+ /* Allowed attribute names */
952
957
  var ALLOWED_ATTR = null;
953
958
  var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
959
+
954
960
  /*
955
961
  * Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
956
962
  * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
957
963
  * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
958
964
  * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
959
965
  */
960
-
961
966
  var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
962
967
  tagNameCheck: {
963
968
  writable: true,
@@ -978,59 +983,65 @@
978
983
  value: false
979
984
  }
980
985
  }));
981
- /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
982
986
 
987
+ /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
983
988
  var FORBID_TAGS = null;
984
- /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
985
989
 
990
+ /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
986
991
  var FORBID_ATTR = null;
987
- /* Decide if ARIA attributes are okay */
988
992
 
993
+ /* Decide if ARIA attributes are okay */
989
994
  var ALLOW_ARIA_ATTR = true;
990
- /* Decide if custom data attributes are okay */
991
995
 
996
+ /* Decide if custom data attributes are okay */
992
997
  var ALLOW_DATA_ATTR = true;
993
- /* Decide if unknown protocols are okay */
994
998
 
999
+ /* Decide if unknown protocols are okay */
995
1000
  var ALLOW_UNKNOWN_PROTOCOLS = false;
1001
+
996
1002
  /* Decide if self-closing tags in attributes are allowed.
997
1003
  * Usually removed due to a mXSS issue in jQuery 3.0 */
998
-
999
1004
  var ALLOW_SELF_CLOSE_IN_ATTR = true;
1005
+
1000
1006
  /* Output should be safe for common template engines.
1001
1007
  * This means, DOMPurify removes data attributes, mustaches and ERB
1002
1008
  */
1003
-
1004
1009
  var SAFE_FOR_TEMPLATES = false;
1005
- /* Decide if document with <html>... should be returned */
1006
1010
 
1011
+ /* Output should be safe even for XML used within HTML and alike.
1012
+ * This means, DOMPurify removes comments when containing risky content.
1013
+ */
1014
+ var SAFE_FOR_XML = true;
1015
+
1016
+ /* Decide if document with <html>... should be returned */
1007
1017
  var WHOLE_DOCUMENT = false;
1008
- /* Track whether config is already set on this instance of DOMPurify. */
1009
1018
 
1019
+ /* Track whether config is already set on this instance of DOMPurify. */
1010
1020
  var SET_CONFIG = false;
1021
+
1011
1022
  /* Decide if all elements (e.g. style, script) must be children of
1012
1023
  * document.body. By default, browsers might move them to document.head */
1013
-
1014
1024
  var FORCE_BODY = false;
1025
+
1015
1026
  /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
1016
1027
  * string (or a TrustedHTML object if Trusted Types are supported).
1017
1028
  * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
1018
1029
  */
1019
-
1020
1030
  var RETURN_DOM = false;
1031
+
1021
1032
  /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
1022
1033
  * string (or a TrustedHTML object if Trusted Types are supported) */
1023
-
1024
1034
  var RETURN_DOM_FRAGMENT = false;
1035
+
1025
1036
  /* Try to return a Trusted Type object instead of a string, return a string in
1026
1037
  * case Trusted Types are not supported */
1027
-
1028
1038
  var RETURN_TRUSTED_TYPE = false;
1039
+
1029
1040
  /* Output should be free from DOM clobbering attacks?
1030
1041
  * This sanitizes markups named with colliding, clobberable built-in DOM APIs.
1031
1042
  */
1032
-
1033
1043
  var SANITIZE_DOM = true;
1044
+
1034
1045
  /* Achieve full DOM Clobbering protection by isolating the namespace of named
1035
1046
  * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
1036
1047
  *
@@ -1044,85 +1055,84 @@
1044
1055
  * Namespace isolation is implemented by prefixing `id` and `name` attributes
1045
1056
  * with a constant string, i.e., `user-content-`
1046
1057
  */
1047
-
1048
1058
  var SANITIZE_NAMED_PROPS = false;
1049
1059
  var SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
1050
- /* Keep element content when removing element? */
1051
1060
 
1061
+ /* Keep element content when removing element? */
1052
1062
  var KEEP_CONTENT = true;
1063
+
1053
1064
  /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
1054
1065
  * of importing it into a new Document and returning a sanitized copy */
1055
-
1056
1066
  var IN_PLACE = false;
1057
- /* Allow usage of profiles like html, svg and mathMl */
1058
1067
 
1068
+ /* Allow usage of profiles like html, svg and mathMl */
1059
1069
  var USE_PROFILES = {};
1060
- /* Tags to ignore content of when KEEP_CONTENT is true */
1061
1070
 
1071
+ /* Tags to ignore content of when KEEP_CONTENT is true */
1062
1072
  var FORBID_CONTENTS = null;
1063
1073
  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']);
1064
- /* Tags that are safe for data: URIs */
1065
1074
 
1075
+ /* Tags that are safe for data: URIs */
1066
1076
  var DATA_URI_TAGS = null;
1067
1077
  var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
1068
- /* Attributes safe for values like "javascript:" */
1069
1078
 
1079
+ /* Attributes safe for values like "javascript:" */
1070
1080
  var URI_SAFE_ATTRIBUTES = null;
1071
1081
  var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
1072
1082
  var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
1073
1083
  var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
1074
1084
  var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
1075
1085
  /* Document namespace */
1076
-
1077
1086
  var NAMESPACE = HTML_NAMESPACE;
1078
1087
  var IS_EMPTY_INPUT = false;
1079
- /* Allowed XHTML+XML namespaces */
1080
1088
 
1089
+ /* Allowed XHTML+XML namespaces */
1081
1090
  var ALLOWED_NAMESPACES = null;
1082
1091
  var DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
1083
- /* Parsing of strict XHTML documents */
1084
1092
 
1093
+ /* Parsing of strict XHTML documents */
1085
1094
  var PARSER_MEDIA_TYPE;
1086
1095
  var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
1087
1096
  var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
1088
1097
  var transformCaseFunc;
1089
- /* Keep a reference to config to pass to hooks */
1090
1098
 
1099
+ /* Keep a reference to config to pass to hooks */
1091
1100
  var CONFIG = null;
1092
- /* Ideally, do not touch anything below this line */
1093
1101
 
1102
+ /* Ideally, do not touch anything below this line */
1094
1103
  /* ______________________________________________ */
1095
1104
 
1096
1105
  var formElement = document.createElement('form');
1097
1106
  var isRegexOrFunction = function isRegexOrFunction(testValue) {
1098
1107
  return testValue instanceof RegExp || testValue instanceof Function;
1099
1108
  };
1109
+
1100
1110
  /**
1101
1111
  * _parseConfig
1102
1112
  *
1103
1113
  * @param {Object} cfg optional config literal
1104
1114
  */
1105
1115
  // eslint-disable-next-line complexity
1106
-
1107
1116
  var _parseConfig = function _parseConfig(cfg) {
1108
1117
  if (CONFIG && CONFIG === cfg) {
1109
1118
  return;
1110
1119
  }
1111
- /* Shield configuration object from tampering */
1112
1120
 
1121
+ /* Shield configuration object from tampering */
1113
1122
  if (!cfg || _typeof(cfg) !== 'object') {
1114
1123
  cfg = {};
1115
1124
  }
1116
- /* Shield configuration object from prototype pollution */
1117
1125
 
1126
+ /* Shield configuration object from prototype pollution */
1118
1127
  cfg = clone(cfg);
1119
1128
  PARSER_MEDIA_TYPE =
1120
1129
  // eslint-disable-next-line unicorn/prefer-includes
1121
- SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE; // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
1130
+ SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
1122
1131
 
1132
+ // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
1123
1133
  transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
1124
- /* Set configuration parameters */
1125
1134
 
1135
+ /* Set configuration parameters */
1126
1136
  ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
1127
1137
  ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
1128
1138
  ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
@@ -1145,33 +1155,20 @@
1145
1155
  FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
1146
1156
  USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
1147
1157
  ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
1148
-
1149
1158
  ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
1150
-
1151
1159
  ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
1152
-
1153
1160
  ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true
1154
-
1155
1161
  SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
1156
-
1162
+ SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true
1157
1163
  WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
1158
-
1159
1164
  RETURN_DOM = cfg.RETURN_DOM || false; // Default false
1160
-
1161
1165
  RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
1162
-
1163
1166
  RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
1164
-
1165
1167
  FORCE_BODY = cfg.FORCE_BODY || false; // Default false
1166
-
1167
1168
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
1168
-
1169
1169
  SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
1170
-
1171
1170
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
1172
-
1173
1171
  IN_PLACE = cfg.IN_PLACE || false; // Default false
1174
-
1175
1172
  IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
1176
1173
  NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
1177
1174
  CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
@@ -1190,8 +1187,8 @@
1190
1187
  if (RETURN_DOM_FRAGMENT) {
1191
1188
  RETURN_DOM = true;
1192
1189
  }
1193
- /* Parse profile info */
1194
1190
 
1191
+ /* Parse profile info */
1195
1192
  if (USE_PROFILES) {
1196
1193
  ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
1197
1194
  ALLOWED_ATTR = [];
@@ -1215,8 +1212,8 @@
1215
1212
  addToSet(ALLOWED_ATTR, xml);
1216
1213
  }
1217
1214
  }
1218
- /* Merge configuration parameters */
1219
1215
 
1216
+ /* Merge configuration parameters */
1220
1217
  if (cfg.ADD_TAGS) {
1221
1218
  if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
1222
1219
  ALLOWED_TAGS = clone(ALLOWED_TAGS);
@@ -1238,45 +1235,48 @@
1238
1235
  }
1239
1236
  addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
1240
1237
  }
1241
- /* Add #text in case KEEP_CONTENT is set to true */
1242
1238
 
1239
+ /* Add #text in case KEEP_CONTENT is set to true */
1243
1240
  if (KEEP_CONTENT) {
1244
1241
  ALLOWED_TAGS['#text'] = true;
1245
1242
  }
1246
- /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
1247
1243
 
1244
+ /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
1248
1245
  if (WHOLE_DOCUMENT) {
1249
1246
  addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
1250
1247
  }
1251
- /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
1252
1248
 
1249
+ /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
1253
1250
  if (ALLOWED_TAGS.table) {
1254
1251
  addToSet(ALLOWED_TAGS, ['tbody']);
1255
1252
  delete FORBID_TAGS.tbody;
1256
- } // Prevent further manipulation of configuration.
1257
- // Not available in IE8, Safari 5, etc.
1253
+ }
1258
1254
 
1255
+ // Prevent further manipulation of configuration.
1256
+ // Not available in IE8, Safari 5, etc.
1259
1257
  if (freeze) {
1260
1258
  freeze(cfg);
1261
1259
  }
1262
1260
  CONFIG = cfg;
1263
1261
  };
1264
1262
  var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
1265
- var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']); // Certain elements are allowed in both SVG and HTML
1263
+ var HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);
1264
+
1265
+ // Certain elements are allowed in both SVG and HTML
1266
1266
  // namespace. We need to specify them explicitly
1267
1267
  // so that they don't get erroneously deleted from
1268
1268
  // HTML namespace.
1269
-
1270
1269
  var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
1270
+
1271
1271
  /* Keep track of all possible SVG and MathML tags
1272
1272
  * so that we can perform the namespace checks
1273
1273
  * correctly. */
1274
-
1275
1274
  var ALL_SVG_TAGS = addToSet({}, svg$1);
1276
1275
  addToSet(ALL_SVG_TAGS, svgFilters);
1277
1276
  addToSet(ALL_SVG_TAGS, svgDisallowed);
1278
1277
  var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
1279
1278
  addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
1279
+
1280
1280
  /**
1281
1281
  *
1282
1282
  *
@@ -1285,11 +1285,11 @@
1285
1285
  * namespace that a spec-compliant parser would never
1286
1286
  * return. Return true otherwise.
1287
1287
  */
1288
-
1289
1288
  var _checkValidNamespace = function _checkValidNamespace(element) {
1290
- var parent = getParentNode(element); // In JSDOM, if we're inside shadow DOM, then parentNode
1291
- // can be null. We just simulate parent in this case.
1289
+ var parent = getParentNode(element);
1292
1290
 
1291
+ // In JSDOM, if we're inside shadow DOM, then parentNode
1292
+ // can be null. We just simulate parent in this case.
1293
1293
  if (!parent || !parent.tagName) {
1294
1294
  parent = {
1295
1295
  namespaceURI: NAMESPACE,
@@ -1307,15 +1307,17 @@
1307
1307
  // it should be killed.
1308
1308
  if (parent.namespaceURI === HTML_NAMESPACE) {
1309
1309
  return tagName === 'svg';
1310
- } // The only way to switch from MathML to SVG is via`
1310
+ }
1311
+
1312
+ // The only way to switch from MathML to SVG is via`
1311
1313
  // svg if parent is either <annotation-xml> or MathML
1312
1314
  // text integration points.
1313
-
1314
1315
  if (parent.namespaceURI === MATHML_NAMESPACE) {
1315
1316
  return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
1316
- } // We only allow elements that are defined in SVG
1317
- // spec. All others are disallowed in SVG namespace.
1317
+ }
1318
1318
 
1319
+ // We only allow elements that are defined in SVG
1320
+ // spec. All others are disallowed in SVG namespace.
1319
1321
  return Boolean(ALL_SVG_TAGS[tagName]);
1320
1322
  }
1321
1323
  if (element.namespaceURI === MATHML_NAMESPACE) {
@@ -1324,14 +1326,16 @@
1324
1326
  // it should be killed.
1325
1327
  if (parent.namespaceURI === HTML_NAMESPACE) {
1326
1328
  return tagName === 'math';
1327
- } // The only way to switch from SVG to MathML is via
1328
- // <math> and HTML integration points
1329
+ }
1329
1330
 
1331
+ // The only way to switch from SVG to MathML is via
1332
+ // <math> and HTML integration points
1330
1333
  if (parent.namespaceURI === SVG_NAMESPACE) {
1331
1334
  return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
1332
- } // We only allow elements that are defined in MathML
1333
- // spec. All others are disallowed in MathML namespace.
1335
+ }
1334
1336
 
1337
+ // We only allow elements that are defined in MathML
1338
+ // spec. All others are disallowed in MathML namespace.
1335
1339
  return Boolean(ALL_MATHML_TAGS[tagName]);
1336
1340
  }
1337
1341
  if (element.namespaceURI === HTML_NAMESPACE) {
@@ -1343,27 +1347,30 @@
1343
1347
  }
1344
1348
  if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
1345
1349
  return false;
1346
- } // We disallow tags that are specific for MathML
1347
- // or SVG and should never appear in HTML namespace
1350
+ }
1348
1351
 
1352
+ // We disallow tags that are specific for MathML
1353
+ // or SVG and should never appear in HTML namespace
1349
1354
  return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
1350
- } // For XHTML and XML documents that support custom namespaces
1355
+ }
1351
1356
 
1357
+ // For XHTML and XML documents that support custom namespaces
1352
1358
  if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
1353
1359
  return true;
1354
- } // The code should never reach this place (this means
1360
+ }
1361
+
1362
+ // The code should never reach this place (this means
1355
1363
  // that the element somehow got namespace that is not
1356
1364
  // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
1357
1365
  // Return false just in case.
1358
-
1359
1366
  return false;
1360
1367
  };
1368
+
1361
1369
  /**
1362
1370
  * _forceRemove
1363
1371
  *
1364
1372
  * @param {Node} node a DOM node
1365
1373
  */
1366
-
1367
1374
  var _forceRemove = function _forceRemove(node) {
1368
1375
  arrayPush(DOMPurify.removed, {
1369
1376
  element: node
@@ -1379,13 +1386,13 @@
1379
1386
  }
1380
1387
  }
1381
1388
  };
1389
+
1382
1390
  /**
1383
1391
  * _removeAttribute
1384
1392
  *
1385
1393
  * @param {String} name an Attribute name
1386
1394
  * @param {Node} node a DOM node
1387
1395
  */
1388
-
1389
1396
  var _removeAttribute = function _removeAttribute(name, node) {
1390
1397
  try {
1391
1398
  arrayPush(DOMPurify.removed, {
@@ -1398,8 +1405,9 @@
1398
1405
  from: node
1399
1406
  });
1400
1407
  }
1401
- node.removeAttribute(name); // We void attribute values for unremovable "is"" attributes
1408
+ node.removeAttribute(name);
1402
1409
 
1410
+ // We void attribute values for unremovable "is"" attributes
1403
1411
  if (name === 'is' && !ALLOWED_ATTR[name]) {
1404
1412
  if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
1405
1413
  try {
@@ -1412,13 +1420,13 @@
1412
1420
  }
1413
1421
  }
1414
1422
  };
1423
+
1415
1424
  /**
1416
1425
  * _initDocument
1417
1426
  *
1418
1427
  * @param {String} dirty a string of dirty markup
1419
1428
  * @return {Document} a DOM, filled with the dirty markup
1420
1429
  */
1421
-
1422
1430
  var _initDocument = function _initDocument(dirty) {
1423
1431
  /* Create a HTML document */
1424
1432
  var doc;
@@ -1439,64 +1447,65 @@
1439
1447
  * Use the DOMParser API by default, fallback later if needs be
1440
1448
  * DOMParser not work for svg when has multiple root element.
1441
1449
  */
1442
-
1443
1450
  if (NAMESPACE === HTML_NAMESPACE) {
1444
1451
  try {
1445
1452
  doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
1446
1453
  } catch (_) {}
1447
1454
  }
1448
- /* Use createHTMLDocument in case DOMParser is not available */
1449
1455
 
1456
+ /* Use createHTMLDocument in case DOMParser is not available */
1450
1457
  if (!doc || !doc.documentElement) {
1451
1458
  doc = implementation.createDocument(NAMESPACE, 'template', null);
1452
1459
  try {
1453
1460
  doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
1454
- } catch (_) {// Syntax error if dirtyPayload is invalid xml
1461
+ } catch (_) {
1462
+ // Syntax error if dirtyPayload is invalid xml
1455
1463
  }
1456
1464
  }
1457
1465
  var body = doc.body || doc.documentElement;
1458
1466
  if (dirty && leadingWhitespace) {
1459
1467
  body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
1460
1468
  }
1461
- /* Work on whole document or just its body */
1462
1469
 
1470
+ /* Work on whole document or just its body */
1463
1471
  if (NAMESPACE === HTML_NAMESPACE) {
1464
1472
  return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
1465
1473
  }
1466
1474
  return WHOLE_DOCUMENT ? doc.documentElement : body;
1467
1475
  };
1476
+
1468
1477
  /**
1469
1478
  * _createIterator
1470
1479
  *
1471
1480
  * @param {Document} root document/fragment to create iterator for
1472
1481
  * @return {Iterator} iterator instance
1473
1482
  */
1474
-
1475
1483
  var _createIterator = function _createIterator(root) {
1476
1484
  return createNodeIterator.call(root.ownerDocument || root, root,
1477
1485
  // eslint-disable-next-line no-bitwise
1478
- NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
1486
+ NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null, false);
1479
1487
  };
1488
+
1480
1489
  /**
1481
1490
  * _isClobbered
1482
1491
  *
1483
1492
  * @param {Node} elm element to check for clobbering attacks
1484
1493
  * @return {Boolean} true if clobbered, false if safe
1485
1494
  */
1486
-
1487
1495
  var _isClobbered = function _isClobbered(elm) {
1488
1496
  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');
1489
1497
  };
1498
+
1490
1499
  /**
1491
1500
  * _isNode
1492
1501
  *
1493
1502
  * @param {Node} obj object to check whether it's a DOM node
1494
1503
  * @return {Boolean} true is object is a DOM node
1495
1504
  */
1496
-
1497
1505
  var _isNode = function _isNode(object) {
1498
1506
  return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
1499
1507
  };
1508
+
1500
1509
  /**
1501
1510
  * _executeHook
1502
1511
  * Execute user configurable hooks
@@ -1505,7 +1514,6 @@
1505
1514
  * @param {Node} currentNode node to work on with the hook
1506
1515
  * @param {Object} data additional hook parameters
1507
1516
  */
1508
-
1509
1517
  var _executeHook = function _executeHook(entryPoint, currentNode, data) {
1510
1518
  if (!hooks[entryPoint]) {
1511
1519
  return;
@@ -1514,6 +1522,7 @@
1514
1522
  hook.call(DOMPurify, currentNode, data, CONFIG);
1515
1523
  });
1516
1524
  };
1525
+
1517
1526
  /**
1518
1527
  * _sanitizeElements
1519
1528
  *
@@ -1524,55 +1533,66 @@
1524
1533
  * @param {Node} currentNode to check for permission to exist
1525
1534
  * @return {Boolean} true if node was killed, false if left alive
1526
1535
  */
1527
-
1528
1536
  var _sanitizeElements = function _sanitizeElements(currentNode) {
1529
1537
  var content;
1530
- /* Execute a hook if present */
1531
1538
 
1539
+ /* Execute a hook if present */
1532
1540
  _executeHook('beforeSanitizeElements', currentNode, null);
1533
- /* Check if element is clobbered or can clobber */
1534
1541
 
1542
+ /* Check if element is clobbered or can clobber */
1535
1543
  if (_isClobbered(currentNode)) {
1536
1544
  _forceRemove(currentNode);
1537
1545
  return true;
1538
1546
  }
1539
- /* Check if tagname contains Unicode */
1540
1547
 
1548
+ /* Check if tagname contains Unicode */
1541
1549
  if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
1542
1550
  _forceRemove(currentNode);
1543
1551
  return true;
1544
1552
  }
1545
- /* Now let's check the element's type and name */
1546
1553
 
1554
+ /* Now let's check the element's type and name */
1547
1555
  var tagName = transformCaseFunc(currentNode.nodeName);
1548
- /* Execute a hook if present */
1549
1556
 
1557
+ /* Execute a hook if present */
1550
1558
  _executeHook('uponSanitizeElement', currentNode, {
1551
1559
  tagName: tagName,
1552
1560
  allowedTags: ALLOWED_TAGS
1553
1561
  });
1554
- /* Detect mXSS attempts abusing namespace confusion */
1555
1562
 
1563
+ /* Detect mXSS attempts abusing namespace confusion */
1556
1564
  if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
1557
1565
  _forceRemove(currentNode);
1558
1566
  return true;
1559
1567
  }
1560
- /* Mitigate a problem with templates inside select */
1561
1568
 
1569
+ /* Mitigate a problem with templates inside select */
1562
1570
  if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
1563
1571
  _forceRemove(currentNode);
1564
1572
  return true;
1565
1573
  }
1566
- /* Remove element if anything forbids its presence */
1567
1574
 
1575
+ /* Remove any ocurrence of processing instructions */
1576
+ if (currentNode.nodeType === 7) {
1577
+ _forceRemove(currentNode);
1578
+ return true;
1579
+ }
1580
+
1581
+ /* Remove any kind of possibly harmful comments */
1582
+ if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\w]/g, currentNode.data)) {
1583
+ _forceRemove(currentNode);
1584
+ return true;
1585
+ }
1586
+
1587
+ /* Remove element if anything forbids its presence */
1568
1588
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
1569
1589
  /* Check if we have a custom element to handle */
1570
1590
  if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
1571
1591
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
1572
1592
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
1573
1593
  }
1574
- /* Keep content except for bad-listed elements */
1575
1594
 
1595
+ /* Keep content except for bad-listed elements */
1576
1596
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
1577
1597
  var parentNode = getParentNode(currentNode) || currentNode.parentNode;
1578
1598
  var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
@@ -1586,20 +1606,20 @@
1586
1606
  _forceRemove(currentNode);
1587
1607
  return true;
1588
1608
  }
1589
- /* Check whether element has a valid namespace */
1590
1609
 
1610
+ /* Check whether element has a valid namespace */
1591
1611
  if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
1592
1612
  _forceRemove(currentNode);
1593
1613
  return true;
1594
1614
  }
1595
- /* Make sure that older browsers don't get fallback-tag mXSS */
1596
1615
 
1616
+ /* Make sure that older browsers don't get fallback-tag mXSS */
1597
1617
  if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
1598
1618
  _forceRemove(currentNode);
1599
1619
  return true;
1600
1620
  }
1601
- /* Sanitize element content to be template-safe */
1602
1621
 
1622
+ /* Sanitize element content to be template-safe */
1603
1623
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
1604
1624
  /* Get the element's text content */
1605
1625
  content = currentNode.textContent;
@@ -1613,11 +1633,12 @@
1613
1633
  currentNode.textContent = content;
1614
1634
  }
1615
1635
  }
1616
- /* Execute a hook if present */
1617
1636
 
1637
+ /* Execute a hook if present */
1618
1638
  _executeHook('afterSanitizeElements', currentNode, null);
1619
1639
  return false;
1620
1640
  };
1641
+
1621
1642
  /**
1622
1643
  * _isValidAttribute
1623
1644
  *
@@ -1627,17 +1648,16 @@
1627
1648
  * @return {Boolean} Returns true if `value` is valid, otherwise false.
1628
1649
  */
1629
1650
  // eslint-disable-next-line complexity
1630
-
1631
1651
  var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
1632
1652
  /* Make sure attribute cannot clobber */
1633
1653
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
1634
1654
  return false;
1635
1655
  }
1656
+
1636
1657
  /* Allow valid data-* attributes: At least one character after "-"
1637
1658
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
1638
1659
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
1639
1660
  We don't need to check the value; it's always URI safe. */
1640
-
1641
1661
  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]) {
1642
1662
  if (
1643
1663
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
@@ -1655,16 +1675,17 @@
1655
1675
  } else ;
1656
1676
  return true;
1657
1677
  };
1678
+
1658
1679
  /**
1659
1680
  * _basicCustomElementCheck
1660
1681
  * checks if at least one dash is included in tagName, and it's not the first char
1661
1682
  * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
1662
1683
  * @param {string} tagName name of the tag of the node to sanitize
1663
1684
  */
1664
-
1665
1685
  var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
1666
- return tagName.indexOf('-') > 0;
1686
+ return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT$1);
1667
1687
  };
1688
+
1668
1689
  /**
1669
1690
  * _sanitizeAttributes
1670
1691
  *
@@ -1675,18 +1696,16 @@
1675
1696
  *
1676
1697
  * @param {Node} currentNode to sanitize
1677
1698
  */
1678
-
1679
1699
  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
1680
1700
  var attr;
1681
1701
  var value;
1682
1702
  var lcName;
1683
1703
  var l;
1684
1704
  /* Execute a hook if present */
1685
-
1686
1705
  _executeHook('beforeSanitizeAttributes', currentNode, null);
1687
1706
  var attributes = currentNode.attributes;
1688
- /* Check if we have attributes; if not we might have a text node */
1689
1707
 
1708
+ /* Check if we have attributes; if not we might have a text node */
1690
1709
  if (!attributes) {
1691
1710
  return;
1692
1711
  }
@@ -1697,8 +1716,8 @@
1697
1716
  allowedAttributes: ALLOWED_ATTR
1698
1717
  };
1699
1718
  l = attributes.length;
1700
- /* Go backwards over all attributes; safely remove bad ones */
1701
1719
 
1720
+ /* Go backwards over all attributes; safely remove bad ones */
1702
1721
  while (l--) {
1703
1722
  attr = attributes[l];
1704
1723
  var _attr = attr,
@@ -1706,59 +1725,58 @@
1706
1725
  namespaceURI = _attr.namespaceURI;
1707
1726
  value = name === 'value' ? attr.value : stringTrim(attr.value);
1708
1727
  lcName = transformCaseFunc(name);
1709
- /* Execute a hook if present */
1710
1728
 
1729
+ /* Execute a hook if present */
1711
1730
  hookEvent.attrName = lcName;
1712
1731
  hookEvent.attrValue = value;
1713
1732
  hookEvent.keepAttr = true;
1714
1733
  hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
1715
-
1716
1734
  _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
1717
1735
  value = hookEvent.attrValue;
1718
1736
  /* Did the hooks approve of the attribute? */
1719
-
1720
1737
  if (hookEvent.forceKeepAttr) {
1721
1738
  continue;
1722
1739
  }
1723
- /* Remove attribute */
1724
1740
 
1741
+ /* Remove attribute */
1725
1742
  _removeAttribute(name, currentNode);
1726
- /* Did the hooks approve of the attribute? */
1727
1743
 
1744
+ /* Did the hooks approve of the attribute? */
1728
1745
  if (!hookEvent.keepAttr) {
1729
1746
  continue;
1730
1747
  }
1731
- /* Work around a security issue in jQuery 3.0 */
1732
1748
 
1749
+ /* Work around a security issue in jQuery 3.0 */
1733
1750
  if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
1734
1751
  _removeAttribute(name, currentNode);
1735
1752
  continue;
1736
1753
  }
1737
- /* Sanitize attribute content to be template-safe */
1738
1754
 
1755
+ /* Sanitize attribute content to be template-safe */
1739
1756
  if (SAFE_FOR_TEMPLATES) {
1740
1757
  value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
1741
1758
  value = stringReplace(value, ERB_EXPR$1, ' ');
1742
1759
  value = stringReplace(value, TMPLIT_EXPR$1, ' ');
1743
1760
  }
1744
- /* Is `value` valid for this attribute? */
1745
1761
 
1762
+ /* Is `value` valid for this attribute? */
1746
1763
  var lcTag = transformCaseFunc(currentNode.nodeName);
1747
1764
  if (!_isValidAttribute(lcTag, lcName, value)) {
1748
1765
  continue;
1749
1766
  }
1767
+
1750
1768
  /* Full DOM Clobbering protection via namespace isolation,
1751
1769
  * Prefix id and name attributes with `user-content-`
1752
1770
  */
1753
-
1754
1771
  if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
1755
1772
  // Remove the attribute with this value
1756
- _removeAttribute(name, currentNode); // Prefix the value and later re-create the attribute with the sanitized value
1773
+ _removeAttribute(name, currentNode);
1757
1774
 
1775
+ // Prefix the value and later re-create the attribute with the sanitized value
1758
1776
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
1759
1777
  }
1760
- /* Handle attributes that require Trusted Types */
1761
1778
 
1779
+ /* Handle attributes that require Trusted Types */
1762
1780
  if (trustedTypesPolicy && _typeof(trustedTypes) === 'object' && typeof trustedTypes.getAttributeType === 'function') {
1763
1781
  if (namespaceURI) ;else {
1764
1782
  switch (trustedTypes.getAttributeType(lcTag, lcName)) {
@@ -1775,8 +1793,8 @@
1775
1793
  }
1776
1794
  }
1777
1795
  }
1778
- /* Handle invalid data-* attribute set by try-catching it */
1779
1796
 
1797
+ /* Handle invalid data-* attribute set by try-catching it */
1780
1798
  try {
1781
1799
  if (namespaceURI) {
1782
1800
  currentNode.setAttributeNS(namespaceURI, name, value);
@@ -1787,43 +1805,44 @@
1787
1805
  arrayPop(DOMPurify.removed);
1788
1806
  } catch (_) {}
1789
1807
  }
1790
- /* Execute a hook if present */
1791
1808
 
1809
+ /* Execute a hook if present */
1792
1810
  _executeHook('afterSanitizeAttributes', currentNode, null);
1793
1811
  };
1812
+
1794
1813
  /**
1795
1814
  * _sanitizeShadowDOM
1796
1815
  *
1797
1816
  * @param {DocumentFragment} fragment to iterate over recursively
1798
1817
  */
1799
-
1800
1818
  var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
1801
1819
  var shadowNode;
1802
1820
  var shadowIterator = _createIterator(fragment);
1803
- /* Execute a hook if present */
1804
1821
 
1822
+ /* Execute a hook if present */
1805
1823
  _executeHook('beforeSanitizeShadowDOM', fragment, null);
1806
1824
  while (shadowNode = shadowIterator.nextNode()) {
1807
1825
  /* Execute a hook if present */
1808
1826
  _executeHook('uponSanitizeShadowNode', shadowNode, null);
1809
- /* Sanitize tags and elements */
1810
1827
 
1828
+ /* Sanitize tags and elements */
1811
1829
  if (_sanitizeElements(shadowNode)) {
1812
1830
  continue;
1813
1831
  }
1814
- /* Deep shadow DOM detected */
1815
1832
 
1833
+ /* Deep shadow DOM detected */
1816
1834
  if (shadowNode.content instanceof DocumentFragment) {
1817
1835
  _sanitizeShadowDOM(shadowNode.content);
1818
1836
  }
1819
- /* Check attributes, sanitize if necessary */
1820
1837
 
1838
+ /* Check attributes, sanitize if necessary */
1821
1839
  _sanitizeAttributes(shadowNode);
1822
1840
  }
1823
- /* Execute a hook if present */
1824
1841
 
1842
+ /* Execute a hook if present */
1825
1843
  _executeHook('afterSanitizeShadowDOM', fragment, null);
1826
1844
  };
1845
+
1827
1846
  /**
1828
1847
  * Sanitize
1829
1848
  * Public method providing core sanitation functionality
@@ -1832,7 +1851,6 @@
1832
1851
  * @param {Object} configuration object
1833
1852
  */
1834
1853
  // eslint-disable-next-line complexity
1835
-
1836
1854
  DOMPurify.sanitize = function (dirty) {
1837
1855
  var cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1838
1856
  var body;
@@ -1843,13 +1861,12 @@
1843
1861
  /* Make sure we have a string to sanitize.
1844
1862
  DO NOT return early, as this will return the wrong type if
1845
1863
  the user has requested a DOM object rather than a string */
1846
-
1847
1864
  IS_EMPTY_INPUT = !dirty;
1848
1865
  if (IS_EMPTY_INPUT) {
1849
1866
  dirty = '<!-->';
1850
1867
  }
1851
- /* Stringify, in case dirty is an object */
1852
1868
 
1869
+ /* Stringify, in case dirty is an object */
1853
1870
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
1854
1871
  if (typeof dirty.toString === 'function') {
1855
1872
  dirty = dirty.toString();
@@ -1860,8 +1877,8 @@
1860
1877
  throw typeErrorCreate('toString is not a function');
1861
1878
  }
1862
1879
  }
1863
- /* Check we can run. Otherwise fall back or ignore */
1864
1880
 
1881
+ /* Check we can run. Otherwise fall back or ignore */
1865
1882
  if (!DOMPurify.isSupported) {
1866
1883
  if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
1867
1884
  if (typeof dirty === 'string') {
@@ -1873,16 +1890,16 @@
1873
1890
  }
1874
1891
  return dirty;
1875
1892
  }
1876
- /* Assign config vars */
1877
1893
 
1894
+ /* Assign config vars */
1878
1895
  if (!SET_CONFIG) {
1879
1896
  _parseConfig(cfg);
1880
1897
  }
1881
- /* Clean up removed elements */
1882
1898
 
1899
+ /* Clean up removed elements */
1883
1900
  DOMPurify.removed = [];
1884
- /* Check if dirty is correctly typed for IN_PLACE */
1885
1901
 
1902
+ /* Check if dirty is correctly typed for IN_PLACE */
1886
1903
  if (typeof dirty === 'string') {
1887
1904
  IN_PLACE = false;
1888
1905
  }
@@ -1915,53 +1932,53 @@
1915
1932
  dirty.indexOf('<') === -1) {
1916
1933
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
1917
1934
  }
1918
- /* Initialize the document to work on */
1919
1935
 
1936
+ /* Initialize the document to work on */
1920
1937
  body = _initDocument(dirty);
1921
- /* Check we have a DOM node from the data */
1922
1938
 
1939
+ /* Check we have a DOM node from the data */
1923
1940
  if (!body) {
1924
1941
  return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
1925
1942
  }
1926
1943
  }
1927
- /* Remove first element node (ours) if FORCE_BODY is set */
1928
1944
 
1945
+ /* Remove first element node (ours) if FORCE_BODY is set */
1929
1946
  if (body && FORCE_BODY) {
1930
1947
  _forceRemove(body.firstChild);
1931
1948
  }
1932
- /* Get node iterator */
1933
1949
 
1950
+ /* Get node iterator */
1934
1951
  var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
1935
- /* Now start iterating over the created document */
1936
1952
 
1953
+ /* Now start iterating over the created document */
1937
1954
  while (currentNode = nodeIterator.nextNode()) {
1938
1955
  /* Fix IE's strange behavior with manipulated textNodes #89 */
1939
1956
  if (currentNode.nodeType === 3 && currentNode === oldNode) {
1940
1957
  continue;
1941
1958
  }
1942
- /* Sanitize tags and elements */
1943
1959
 
1960
+ /* Sanitize tags and elements */
1944
1961
  if (_sanitizeElements(currentNode)) {
1945
1962
  continue;
1946
1963
  }
1947
- /* Shadow DOM detected, sanitize it */
1948
1964
 
1965
+ /* Shadow DOM detected, sanitize it */
1949
1966
  if (currentNode.content instanceof DocumentFragment) {
1950
1967
  _sanitizeShadowDOM(currentNode.content);
1951
1968
  }
1952
- /* Check attributes, sanitize if necessary */
1953
1969
 
1970
+ /* Check attributes, sanitize if necessary */
1954
1971
  _sanitizeAttributes(currentNode);
1955
1972
  oldNode = currentNode;
1956
1973
  }
1957
1974
  oldNode = null;
1958
- /* If we sanitized `dirty` in-place, return it. */
1959
1975
 
1976
+ /* If we sanitized `dirty` in-place, return it. */
1960
1977
  if (IN_PLACE) {
1961
1978
  return dirty;
1962
1979
  }
1963
- /* Return sanitized string or DOM */
1964
1980
 
1981
+ /* Return sanitized string or DOM */
1965
1982
  if (RETURN_DOM) {
1966
1983
  if (RETURN_DOM_FRAGMENT) {
1967
1984
  returnNode = createDocumentFragment.call(body.ownerDocument);
@@ -1985,13 +2002,13 @@
1985
2002
  return returnNode;
1986
2003
  }
1987
2004
  var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
1988
- /* Serialize doctype if allowed */
1989
2005
 
2006
+ /* Serialize doctype if allowed */
1990
2007
  if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
1991
2008
  serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
1992
2009
  }
1993
- /* Sanitize final string template-safe */
1994
2010
 
2011
+ /* Sanitize final string template-safe */
1995
2012
  if (SAFE_FOR_TEMPLATES) {
1996
2013
  serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
1997
2014
  serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
@@ -1999,27 +2016,28 @@
1999
2016
  }
2000
2017
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
2001
2018
  };
2019
+
2002
2020
  /**
2003
2021
  * Public method to set the configuration once
2004
2022
  * setConfig
2005
2023
  *
2006
2024
  * @param {Object} cfg configuration object
2007
2025
  */
2008
-
2009
2026
  DOMPurify.setConfig = function (cfg) {
2010
2027
  _parseConfig(cfg);
2011
2028
  SET_CONFIG = true;
2012
2029
  };
2030
+
2013
2031
  /**
2014
2032
  * Public method to remove the configuration
2015
2033
  * clearConfig
2016
2034
  *
2017
2035
  */
2018
-
2019
2036
  DOMPurify.clearConfig = function () {
2020
2037
  CONFIG = null;
2021
2038
  SET_CONFIG = false;
2022
2039
  };
2040
+
2023
2041
  /**
2024
2042
  * Public method to check if an attribute value is valid.
2025
2043
  * Uses last set config, if any. Otherwise, uses config defaults.
@@ -2030,7 +2048,6 @@
2030
2048
  * @param {string} value Attribute value.
2031
2049
  * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
2032
2050
  */
2033
-
2034
2051
  DOMPurify.isValidAttribute = function (tag, attr, value) {
2035
2052
  /* Initialize shared config vars if necessary. */
2036
2053
  if (!CONFIG) {
@@ -2040,6 +2057,7 @@
2040
2057
  var lcName = transformCaseFunc(attr);
2041
2058
  return _isValidAttribute(lcTag, lcName, value);
2042
2059
  };
2060
+
2043
2061
  /**
2044
2062
  * AddHook
2045
2063
  * Public method to add DOMPurify hooks
@@ -2047,7 +2065,6 @@
2047
2065
  * @param {String} entryPoint entry point for the hook to add
2048
2066
  * @param {Function} hookFunction function to execute
2049
2067
  */
2050
-
2051
2068
  DOMPurify.addHook = function (entryPoint, hookFunction) {
2052
2069
  if (typeof hookFunction !== 'function') {
2053
2070
  return;
@@ -2055,6 +2072,7 @@
2055
2072
  hooks[entryPoint] = hooks[entryPoint] || [];
2056
2073
  arrayPush(hooks[entryPoint], hookFunction);
2057
2074
  };
2075
+
2058
2076
  /**
2059
2077
  * RemoveHook
2060
2078
  * Public method to remove a DOMPurify hook at a given entryPoint
@@ -2063,30 +2081,29 @@
2063
2081
  * @param {String} entryPoint entry point for the hook to remove
2064
2082
  * @return {Function} removed(popped) hook
2065
2083
  */
2066
-
2067
2084
  DOMPurify.removeHook = function (entryPoint) {
2068
2085
  if (hooks[entryPoint]) {
2069
2086
  return arrayPop(hooks[entryPoint]);
2070
2087
  }
2071
2088
  };
2089
+
2072
2090
  /**
2073
2091
  * RemoveHooks
2074
2092
  * Public method to remove all DOMPurify hooks at a given entryPoint
2075
2093
  *
2076
2094
  * @param {String} entryPoint entry point for the hooks to remove
2077
2095
  */
2078
-
2079
2096
  DOMPurify.removeHooks = function (entryPoint) {
2080
2097
  if (hooks[entryPoint]) {
2081
2098
  hooks[entryPoint] = [];
2082
2099
  }
2083
2100
  };
2101
+
2084
2102
  /**
2085
2103
  * RemoveAllHooks
2086
2104
  * Public method to remove all DOMPurify hooks
2087
2105
  *
2088
2106
  */
2089
-
2090
2107
  DOMPurify.removeAllHooks = function () {
2091
2108
  hooks = {};
2092
2109
  };