dompurify 2.2.5 → 2.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/purify.js CHANGED
@@ -143,7 +143,12 @@
143
143
  object = getPrototypeOf(object);
144
144
  }
145
145
 
146
- return null;
146
+ function fallbackValue(element) {
147
+ console.warn('fallback value for', element);
148
+ return null;
149
+ }
150
+
151
+ return fallbackValue;
147
152
  }
148
153
 
149
154
  var html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', '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']);
@@ -167,7 +172,7 @@
167
172
 
168
173
  var text = freeze(['#text']);
169
174
 
170
- var html$1 = 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', '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']);
175
+ var html$1 = 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', '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']);
171
176
 
172
177
  var svg$1 = 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', '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']);
173
178
 
@@ -244,7 +249,7 @@
244
249
  * Version label, exposed for easier checks
245
250
  * if DOMPurify is up to date or not
246
251
  */
247
- DOMPurify.version = '2.2.5';
252
+ DOMPurify.version = '2.2.9';
248
253
 
249
254
  /**
250
255
  * Array of elements that DOMPurify removed during sanitation.
@@ -302,7 +307,6 @@
302
307
  var _document = document,
303
308
  implementation = _document.implementation,
304
309
  createNodeIterator = _document.createNodeIterator,
305
- getElementsByTagName = _document.getElementsByTagName,
306
310
  createDocumentFragment = _document.createDocumentFragment;
307
311
  var importNode = originalDocument.importNode;
308
312
 
@@ -317,7 +321,7 @@
317
321
  /**
318
322
  * Expose whether this browser supports running the full DOMPurify.
319
323
  */
320
- DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
324
+ DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
321
325
 
322
326
  var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,
323
327
  ERB_EXPR$$1 = ERB_EXPR,
@@ -420,6 +424,13 @@
420
424
  var URI_SAFE_ATTRIBUTES = null;
421
425
  var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);
422
426
 
427
+ var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
428
+ var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
429
+ var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
430
+ /* Document namespace */
431
+ var NAMESPACE = HTML_NAMESPACE;
432
+ var IS_EMPTY_INPUT = false;
433
+
423
434
  /* Keep a reference to config to pass to hooks */
424
435
  var CONFIG = null;
425
436
 
@@ -469,6 +480,7 @@
469
480
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
470
481
  IN_PLACE = cfg.IN_PLACE || false; // Default false
471
482
  IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;
483
+ NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
472
484
  if (SAFE_FOR_TEMPLATES) {
473
485
  ALLOW_DATA_ATTR = false;
474
486
  }
@@ -565,10 +577,6 @@
565
577
  var ALL_MATHML_TAGS = addToSet({}, mathMl);
566
578
  addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
567
579
 
568
- var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
569
- var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
570
- var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
571
-
572
580
  /**
573
581
  *
574
582
  *
@@ -668,6 +676,7 @@
668
676
  var _forceRemove = function _forceRemove(node) {
669
677
  arrayPush(DOMPurify.removed, { element: node });
670
678
  try {
679
+ // eslint-disable-next-line unicorn/prefer-dom-node-remove
671
680
  node.parentNode.removeChild(node);
672
681
  } catch (_) {
673
682
  try {
@@ -698,6 +707,19 @@
698
707
  }
699
708
 
700
709
  node.removeAttribute(name);
710
+
711
+ // We void attribute values for unremovable "is"" attributes
712
+ if (name === 'is' && !ALLOWED_ATTR[name]) {
713
+ if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
714
+ try {
715
+ _forceRemove(node);
716
+ } catch (_) {}
717
+ } else {
718
+ try {
719
+ node.setAttribute(name, '');
720
+ } catch (_) {}
721
+ }
722
+ }
701
723
  };
702
724
 
703
725
  /**
@@ -720,27 +742,34 @@
720
742
  }
721
743
 
722
744
  var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
723
- /* Use the DOMParser API by default, fallback later if needs be */
724
- try {
725
- doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
726
- } catch (_) {}
745
+ /*
746
+ * Use the DOMParser API by default, fallback later if needs be
747
+ * DOMParser not work for svg when has multiple root element.
748
+ */
749
+ if (NAMESPACE === HTML_NAMESPACE) {
750
+ try {
751
+ doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');
752
+ } catch (_) {}
753
+ }
727
754
 
728
755
  /* Use createHTMLDocument in case DOMParser is not available */
729
756
  if (!doc || !doc.documentElement) {
730
- doc = implementation.createHTMLDocument('');
731
- var _doc = doc,
732
- body = _doc.body;
733
-
734
- body.parentNode.removeChild(body.parentNode.firstElementChild);
735
- body.outerHTML = dirtyPayload;
757
+ doc = implementation.createDocument(NAMESPACE, 'template', null);
758
+ try {
759
+ doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
760
+ } catch (_) {
761
+ // Syntax error if dirtyPayload is invalid xml
762
+ }
736
763
  }
737
764
 
765
+ var body = doc.body || doc.documentElement;
766
+
738
767
  if (dirty && leadingWhitespace) {
739
- doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);
768
+ body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
740
769
  }
741
770
 
742
771
  /* Work on whole document or just its body */
743
- return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
772
+ return WHOLE_DOCUMENT ? doc.documentElement : body;
744
773
  };
745
774
 
746
775
  /**
@@ -750,9 +779,7 @@
750
779
  * @return {Iterator} iterator instance
751
780
  */
752
781
  var _createIterator = function _createIterator(root) {
753
- return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {
754
- return NodeFilter.FILTER_ACCEPT;
755
- }, false);
782
+ return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
756
783
  };
757
784
 
758
785
  /**
@@ -848,11 +875,15 @@
848
875
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
849
876
  /* Keep content except for bad-listed elements */
850
877
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
851
- var parentNode = getParentNode(currentNode);
852
- var childNodes = getChildNodes(currentNode);
853
- var childCount = childNodes.length;
854
- for (var i = childCount - 1; i >= 0; --i) {
855
- parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
878
+ var parentNode = getParentNode(currentNode) || currentNode.parentNode;
879
+ var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
880
+
881
+ if (childNodes && parentNode) {
882
+ var childCount = childNodes.length;
883
+
884
+ for (var i = childCount - 1; i >= 0; --i) {
885
+ parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
886
+ }
856
887
  }
857
888
  }
858
889
 
@@ -1069,7 +1100,8 @@
1069
1100
  /* Make sure we have a string to sanitize.
1070
1101
  DO NOT return early, as this will return the wrong type if
1071
1102
  the user has requested a DOM object rather than a string */
1072
- if (!dirty) {
1103
+ IS_EMPTY_INPUT = !dirty;
1104
+ if (IS_EMPTY_INPUT) {
1073
1105
  dirty = '<!-->';
1074
1106
  }
1075
1107
 
@@ -1125,7 +1157,7 @@
1125
1157
  } else if (importedNode.nodeName === 'HTML') {
1126
1158
  body = importedNode;
1127
1159
  } else {
1128
- // eslint-disable-next-line unicorn/prefer-node-append
1160
+ // eslint-disable-next-line unicorn/prefer-dom-node-append
1129
1161
  body.appendChild(importedNode);
1130
1162
  }
1131
1163
  } else {
@@ -1189,7 +1221,7 @@
1189
1221
  returnNode = createDocumentFragment.call(body.ownerDocument);
1190
1222
 
1191
1223
  while (body.firstChild) {
1192
- // eslint-disable-next-line unicorn/prefer-node-append
1224
+ // eslint-disable-next-line unicorn/prefer-dom-node-append
1193
1225
  returnNode.appendChild(body.firstChild);
1194
1226
  }
1195
1227
  } else {