@knime/kds-table 10.1.0 → 11.0.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.
- package/CHANGELOG.md +17 -0
- package/dist/index.js +332 -88
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -745,6 +745,14 @@ var dimension = {
|
|
|
745
745
|
variable: "var(--kds-dimension-component-height-0-25x)"
|
|
746
746
|
}
|
|
747
747
|
},
|
|
748
|
+
"0.5x": {
|
|
749
|
+
value: 8,
|
|
750
|
+
unit: "px",
|
|
751
|
+
css: {
|
|
752
|
+
value: "8px",
|
|
753
|
+
variable: "var(--kds-dimension-component-height-0-5x)"
|
|
754
|
+
}
|
|
755
|
+
},
|
|
748
756
|
"0.75x": {
|
|
749
757
|
value: 12,
|
|
750
758
|
unit: "px",
|
|
@@ -891,6 +899,14 @@ var dimension = {
|
|
|
891
899
|
variable: "var(--kds-dimension-component-width-0-25x)"
|
|
892
900
|
}
|
|
893
901
|
},
|
|
902
|
+
"0.5x": {
|
|
903
|
+
value: 8,
|
|
904
|
+
unit: "px",
|
|
905
|
+
css: {
|
|
906
|
+
value: "8px",
|
|
907
|
+
variable: "var(--kds-dimension-component-width-0-5x)"
|
|
908
|
+
}
|
|
909
|
+
},
|
|
894
910
|
"0.75x": {
|
|
895
911
|
value: 12,
|
|
896
912
|
unit: "px",
|
|
@@ -1646,8 +1662,11 @@ var oe = class extends b {
|
|
|
1646
1662
|
}
|
|
1647
1663
|
};
|
|
1648
1664
|
//#endregion
|
|
1649
|
-
//#region ../../node_modules/.pnpm/dompurify@3.4.
|
|
1650
|
-
/*! @license DOMPurify 3.4.
|
|
1665
|
+
//#region ../../node_modules/.pnpm/dompurify@3.4.16/node_modules/dompurify/dist/purify.es.mjs
|
|
1666
|
+
/*! @license DOMPurify 3.4.16 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.16/LICENSE */
|
|
1667
|
+
function _OverloadYield(e, d) {
|
|
1668
|
+
this.v = e, this.k = d;
|
|
1669
|
+
}
|
|
1651
1670
|
function _arrayLikeToArray(r, a) {
|
|
1652
1671
|
(null == a || a > r.length) && (a = r.length);
|
|
1653
1672
|
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
@@ -1659,12 +1678,14 @@ function _arrayWithHoles(r) {
|
|
|
1659
1678
|
function _iterableToArrayLimit(r, l) {
|
|
1660
1679
|
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
1661
1680
|
if (null != t) {
|
|
1662
|
-
var e, n, i, u, a = [], f =
|
|
1681
|
+
var e, n, i, u, a = [], f = !0, o = !1;
|
|
1663
1682
|
try {
|
|
1664
|
-
if (i = (t = t.call(r)).next, 0 === l)
|
|
1665
|
-
|
|
1683
|
+
if (i = (t = t.call(r)).next, 0 === l) {
|
|
1684
|
+
if (Object(t) !== t) return;
|
|
1685
|
+
f = !1;
|
|
1686
|
+
} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
|
|
1666
1687
|
} catch (r) {
|
|
1667
|
-
o =
|
|
1688
|
+
o = !0, n = r;
|
|
1668
1689
|
} finally {
|
|
1669
1690
|
try {
|
|
1670
1691
|
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
@@ -1678,6 +1699,7 @@ function _iterableToArrayLimit(r, l) {
|
|
|
1678
1699
|
function _nonIterableRest() {
|
|
1679
1700
|
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
1680
1701
|
}
|
|
1702
|
+
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
|
1681
1703
|
function _slicedToArray(r, e) {
|
|
1682
1704
|
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
1683
1705
|
}
|
|
@@ -1688,9 +1710,64 @@ function _unsupportedIterableToArray(r, a) {
|
|
|
1688
1710
|
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;
|
|
1689
1711
|
}
|
|
1690
1712
|
}
|
|
1691
|
-
|
|
1692
|
-
var
|
|
1693
|
-
|
|
1713
|
+
function AsyncGenerator(e) {
|
|
1714
|
+
var t, n;
|
|
1715
|
+
function resume(t, n) {
|
|
1716
|
+
try {
|
|
1717
|
+
var r = e[t](n), o = r.value, u = o instanceof _OverloadYield;
|
|
1718
|
+
Promise.resolve(u ? o.v : o).then(function(n) {
|
|
1719
|
+
if (u) {
|
|
1720
|
+
var i = "return" === t && o.k ? t : "next";
|
|
1721
|
+
if (!o.k || n.done) return resume(i, n);
|
|
1722
|
+
n = e[i](n).value;
|
|
1723
|
+
}
|
|
1724
|
+
settle(!!r.done, n);
|
|
1725
|
+
}, function(e) {
|
|
1726
|
+
resume("throw", e);
|
|
1727
|
+
});
|
|
1728
|
+
} catch (e) {
|
|
1729
|
+
settle(2, e);
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
function settle(e, r) {
|
|
1733
|
+
2 === e ? t.reject(r) : t.resolve({
|
|
1734
|
+
value: r,
|
|
1735
|
+
done: e
|
|
1736
|
+
}), (t = t.next) ? resume(t.key, t.arg) : n = null;
|
|
1737
|
+
}
|
|
1738
|
+
this._invoke = function(e, r) {
|
|
1739
|
+
return new Promise(function(o, u) {
|
|
1740
|
+
var i = {
|
|
1741
|
+
key: e,
|
|
1742
|
+
arg: r,
|
|
1743
|
+
resolve: o,
|
|
1744
|
+
reject: u,
|
|
1745
|
+
next: null
|
|
1746
|
+
};
|
|
1747
|
+
n ? n = n.next = i : (t = n = i, resume(e, r));
|
|
1748
|
+
});
|
|
1749
|
+
}, "function" != typeof e.return && (this.return = void 0);
|
|
1750
|
+
}
|
|
1751
|
+
AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function() {
|
|
1752
|
+
return this;
|
|
1753
|
+
}, AsyncGenerator.prototype.next = function(e) {
|
|
1754
|
+
return this._invoke("next", e);
|
|
1755
|
+
}, AsyncGenerator.prototype.throw = function(e) {
|
|
1756
|
+
return this._invoke("throw", e);
|
|
1757
|
+
}, AsyncGenerator.prototype.return = function(e) {
|
|
1758
|
+
return this._invoke("return", e);
|
|
1759
|
+
};
|
|
1760
|
+
var entries = Object.entries;
|
|
1761
|
+
var setPrototypeOf = Object.setPrototypeOf;
|
|
1762
|
+
var isFrozen = Object.isFrozen;
|
|
1763
|
+
var getPrototypeOf = Object.getPrototypeOf;
|
|
1764
|
+
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
1765
|
+
var freeze = Object.freeze;
|
|
1766
|
+
var seal = Object.seal;
|
|
1767
|
+
var create = Object.create;
|
|
1768
|
+
var _ref = typeof Reflect !== "undefined" && Reflect;
|
|
1769
|
+
var apply = _ref.apply;
|
|
1770
|
+
var construct = _ref.construct;
|
|
1694
1771
|
if (!freeze) freeze = function freeze(x) {
|
|
1695
1772
|
return x;
|
|
1696
1773
|
};
|
|
@@ -1706,9 +1783,11 @@ if (!construct) construct = function construct(Func) {
|
|
|
1706
1783
|
return new Func(...args);
|
|
1707
1784
|
};
|
|
1708
1785
|
var arrayForEach = unapply(Array.prototype.forEach);
|
|
1786
|
+
Array.prototype.indexOf;
|
|
1709
1787
|
var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
|
|
1710
1788
|
var arrayPop = unapply(Array.prototype.pop);
|
|
1711
1789
|
var arrayPush = unapply(Array.prototype.push);
|
|
1790
|
+
Array.prototype.slice;
|
|
1712
1791
|
var arraySplice = unapply(Array.prototype.splice);
|
|
1713
1792
|
var arrayIsArray = Array.isArray;
|
|
1714
1793
|
var stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
@@ -2368,6 +2447,7 @@ var svg = freeze([
|
|
|
2368
2447
|
"patterncontentunits",
|
|
2369
2448
|
"patterntransform",
|
|
2370
2449
|
"patternunits",
|
|
2450
|
+
"pointer-events",
|
|
2371
2451
|
"points",
|
|
2372
2452
|
"preservealpha",
|
|
2373
2453
|
"preserveaspectratio",
|
|
@@ -2422,6 +2502,7 @@ var svg = freeze([
|
|
|
2422
2502
|
"u2",
|
|
2423
2503
|
"unicode",
|
|
2424
2504
|
"values",
|
|
2505
|
+
"vector-effect",
|
|
2425
2506
|
"viewbox",
|
|
2426
2507
|
"visibility",
|
|
2427
2508
|
"version",
|
|
@@ -2535,6 +2616,24 @@ var NODE_TYPE = {
|
|
|
2535
2616
|
documentFragment: 11,
|
|
2536
2617
|
notation: 12
|
|
2537
2618
|
};
|
|
2619
|
+
var LITERAL_TEXT_ELEMENT_NAMES = [
|
|
2620
|
+
"style",
|
|
2621
|
+
"script",
|
|
2622
|
+
"xmp",
|
|
2623
|
+
"iframe",
|
|
2624
|
+
"noembed",
|
|
2625
|
+
"noframes",
|
|
2626
|
+
"plaintext",
|
|
2627
|
+
"noscript"
|
|
2628
|
+
];
|
|
2629
|
+
var LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES));
|
|
2630
|
+
var LITERAL_TEXT_CLOSE = function() {
|
|
2631
|
+
const map = {};
|
|
2632
|
+
arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, (name) => {
|
|
2633
|
+
map[name] = seal(new RegExp("</" + name + "(?=[\\t\\n\\f\\r />])", "i"));
|
|
2634
|
+
});
|
|
2635
|
+
return freeze(map);
|
|
2636
|
+
}();
|
|
2538
2637
|
var getGlobal = function getGlobal() {
|
|
2539
2638
|
return typeof window === "undefined" ? null : window;
|
|
2540
2639
|
};
|
|
@@ -2594,10 +2693,25 @@ var _createHooksMap = function _createHooksMap() {
|
|
|
2594
2693
|
var _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) {
|
|
2595
2694
|
return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
|
|
2596
2695
|
};
|
|
2696
|
+
/**
|
|
2697
|
+
* Resolve an object-valued configuration option: a prototype-free clone
|
|
2698
|
+
* of cfg[key] when it is an own, truthy object property, else a fresh
|
|
2699
|
+
* fallback built by makeFallback (fresh on every parse, so a previous
|
|
2700
|
+
* parse can never leak state into the next one).
|
|
2701
|
+
*
|
|
2702
|
+
* @param cfg the cloned, prototype-free configuration object
|
|
2703
|
+
* @param key the configuration property to read
|
|
2704
|
+
* @param makeFallback builds the fallback value when the option is absent
|
|
2705
|
+
* @returns the resolved object
|
|
2706
|
+
*/
|
|
2707
|
+
var _resolveObjectOption = function _resolveObjectOption(cfg, key, makeFallback) {
|
|
2708
|
+
const value = objectHasOwnProperty(cfg, key) ? cfg[key] : void 0;
|
|
2709
|
+
return value && typeof value === "object" ? clone(value) : makeFallback();
|
|
2710
|
+
};
|
|
2597
2711
|
function createDOMPurify() {
|
|
2598
2712
|
let window = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
|
|
2599
2713
|
const DOMPurify = (root) => createDOMPurify(root);
|
|
2600
|
-
DOMPurify.version = "3.4.
|
|
2714
|
+
DOMPurify.version = "3.4.16";
|
|
2601
2715
|
DOMPurify.removed = [];
|
|
2602
2716
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
2603
2717
|
DOMPurify.isSupported = false;
|
|
@@ -2614,6 +2728,7 @@ function createDOMPurify() {
|
|
|
2614
2728
|
const ElementPrototype = Element.prototype;
|
|
2615
2729
|
const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
|
|
2616
2730
|
const remove = lookupGetter(ElementPrototype, "remove");
|
|
2731
|
+
const removeAttributeNode = lookupGetter(ElementPrototype, "removeAttributeNode");
|
|
2617
2732
|
const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
|
|
2618
2733
|
const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
|
|
2619
2734
|
const getParentNode = lookupGetter(ElementPrototype, "parentNode");
|
|
@@ -2622,6 +2737,12 @@ function createDOMPurify() {
|
|
|
2622
2737
|
const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null;
|
|
2623
2738
|
const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null;
|
|
2624
2739
|
const getOwnerDocument = Node && Node.prototype ? lookupGetter(Node.prototype, "ownerDocument") : null;
|
|
2740
|
+
const _readNodeType = function _readNodeType(node) {
|
|
2741
|
+
return getNodeType ? getNodeType(node) : node.nodeType;
|
|
2742
|
+
};
|
|
2743
|
+
const _readNodeName = function _readNodeName(node) {
|
|
2744
|
+
return getNodeName ? getNodeName(node) : node.nodeName;
|
|
2745
|
+
};
|
|
2625
2746
|
if (typeof HTMLTemplateElement === "function") {
|
|
2626
2747
|
const template = document.createElement("template");
|
|
2627
2748
|
if (template.content && template.content.ownerDocument) document = template.content.ownerDocument;
|
|
@@ -2879,9 +3000,9 @@ function createDOMPurify() {
|
|
|
2879
3000
|
IN_PLACE = cfg.IN_PLACE || false;
|
|
2880
3001
|
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
|
|
2881
3002
|
NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
|
|
2882
|
-
MATHML_TEXT_INTEGRATION_POINTS =
|
|
2883
|
-
HTML_INTEGRATION_POINTS =
|
|
2884
|
-
const customElementHandling =
|
|
3003
|
+
MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(cfg, "MATHML_TEXT_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS));
|
|
3004
|
+
HTML_INTEGRATION_POINTS = _resolveObjectOption(cfg, "HTML_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS));
|
|
3005
|
+
const customElementHandling = _resolveObjectOption(cfg, "CUSTOM_ELEMENT_HANDLING", () => create(null));
|
|
2885
3006
|
CUSTOM_ELEMENT_HANDLING = create(null);
|
|
2886
3007
|
if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
|
|
2887
3008
|
if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck;
|
|
@@ -2928,11 +3049,6 @@ function createDOMPurify() {
|
|
|
2928
3049
|
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
2929
3050
|
}
|
|
2930
3051
|
}
|
|
2931
|
-
if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
2932
|
-
if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) {
|
|
2933
|
-
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2934
|
-
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
2935
|
-
}
|
|
2936
3052
|
if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
|
|
2937
3053
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2938
3054
|
addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
|
|
@@ -3049,6 +3165,32 @@ function createDOMPurify() {
|
|
|
3049
3165
|
}
|
|
3050
3166
|
};
|
|
3051
3167
|
/**
|
|
3168
|
+
* _stripAttributeNode
|
|
3169
|
+
*
|
|
3170
|
+
* Remove a single Attr node case/namespace-exactly on an attribute-teardown
|
|
3171
|
+
* path. Name-based removeAttribute() ASCII-lowercases its lookup key for an
|
|
3172
|
+
* HTML element in an HTML document and so silently misses a case-preserved
|
|
3173
|
+
* handler (e.g. `ONERROR` off an XML/XHTML import) - the same defect
|
|
3174
|
+
* _removeAttribute() was fixed for, which a name-based call would reintroduce
|
|
3175
|
+
* on these IN_PLACE teardown paths. Unlike _removeAttribute this does not
|
|
3176
|
+
* record into DOMPurify.removed: the neutralize passes intentionally do not
|
|
3177
|
+
* book-keep. A clobbered/detached node falls back to best-effort name-based
|
|
3178
|
+
* removal.
|
|
3179
|
+
*
|
|
3180
|
+
* @param element the element to strip the attribute from
|
|
3181
|
+
* @param attribute the Attr node to remove
|
|
3182
|
+
* @param name the attribute's name, for the fallback path
|
|
3183
|
+
*/
|
|
3184
|
+
const _stripAttributeNode = function _stripAttributeNode(element, attribute, name) {
|
|
3185
|
+
try {
|
|
3186
|
+
removeAttributeNode(element, attribute);
|
|
3187
|
+
} catch (_) {
|
|
3188
|
+
try {
|
|
3189
|
+
element.removeAttribute(name);
|
|
3190
|
+
} catch (_) {}
|
|
3191
|
+
}
|
|
3192
|
+
};
|
|
3193
|
+
/**
|
|
3052
3194
|
* _neutralizeRoot
|
|
3053
3195
|
*
|
|
3054
3196
|
* Fail-closed teardown of an in-place root after the sanitize walk aborts
|
|
@@ -3082,30 +3224,45 @@ function createDOMPurify() {
|
|
|
3082
3224
|
if (attributes) for (let i = attributes.length - 1; i >= 0; --i) {
|
|
3083
3225
|
const attribute = attributes[i];
|
|
3084
3226
|
const name = attribute && attribute.name;
|
|
3085
|
-
if (typeof name === "string")
|
|
3086
|
-
root.removeAttribute(name);
|
|
3087
|
-
} catch (_) {}
|
|
3227
|
+
if (typeof name === "string") _stripAttributeNode(root, attribute, name);
|
|
3088
3228
|
}
|
|
3089
3229
|
};
|
|
3090
3230
|
/**
|
|
3091
3231
|
* _removeAttribute
|
|
3092
3232
|
*
|
|
3233
|
+
* Name-based getAttributeNode()/removeAttribute() ASCII-lowercase their
|
|
3234
|
+
* lookup key for HTML elements in an HTML document, so they silently miss an
|
|
3235
|
+
* attribute whose stored qualified name still contains uppercase ASCII
|
|
3236
|
+
* letters. That happens when the node came from a case-preserving source
|
|
3237
|
+
* (an XML/XHTML document imported via importNode(), or createAttributeNS()),
|
|
3238
|
+
* where e.g. `ONERROR` survives the walk: the policy check lowercases to
|
|
3239
|
+
* `onerror` and rejects it, but `removeAttribute('ONERROR')` looks up
|
|
3240
|
+
* `onerror` and finds nothing. Remove the exact Attr node instead, which is
|
|
3241
|
+
* case- and namespace-exact, and fall back to name-based removal only when
|
|
3242
|
+
* the caller could not supply the node.
|
|
3243
|
+
*
|
|
3093
3244
|
* @param name an Attribute name
|
|
3094
3245
|
* @param element a DOM node
|
|
3246
|
+
* @param attr the exact Attr node to remove, when the caller has it
|
|
3095
3247
|
*/
|
|
3096
|
-
const _removeAttribute = function _removeAttribute(name, element) {
|
|
3248
|
+
const _removeAttribute = function _removeAttribute(name, element, attr) {
|
|
3249
|
+
if (!attr) try {
|
|
3250
|
+
attr = element.getAttributeNode(name);
|
|
3251
|
+
} catch (_) {
|
|
3252
|
+
attr = null;
|
|
3253
|
+
}
|
|
3254
|
+
arrayPush(DOMPurify.removed, {
|
|
3255
|
+
attribute: attr || null,
|
|
3256
|
+
from: element
|
|
3257
|
+
});
|
|
3097
3258
|
try {
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
from: element
|
|
3101
|
-
});
|
|
3259
|
+
if (attr) removeAttributeNode(element, attr);
|
|
3260
|
+
else element.removeAttribute(name);
|
|
3102
3261
|
} catch (_) {
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
});
|
|
3262
|
+
try {
|
|
3263
|
+
element.removeAttribute(name);
|
|
3264
|
+
} catch (_) {}
|
|
3107
3265
|
}
|
|
3108
|
-
element.removeAttribute(name);
|
|
3109
3266
|
if (name === "is") if (RETURN_DOM || RETURN_DOM_FRAGMENT) try {
|
|
3110
3267
|
_forceRemove(element);
|
|
3111
3268
|
} catch (_) {}
|
|
@@ -3130,9 +3287,7 @@ function createDOMPurify() {
|
|
|
3130
3287
|
const attribute = attributes[i];
|
|
3131
3288
|
const name = attribute && attribute.name;
|
|
3132
3289
|
if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) continue;
|
|
3133
|
-
|
|
3134
|
-
element.removeAttribute(name);
|
|
3135
|
-
} catch (_) {}
|
|
3290
|
+
_stripAttributeNode(element, attribute, name);
|
|
3136
3291
|
}
|
|
3137
3292
|
};
|
|
3138
3293
|
/**
|
|
@@ -3161,7 +3316,7 @@ function createDOMPurify() {
|
|
|
3161
3316
|
const stack = [root];
|
|
3162
3317
|
while (stack.length > 0) {
|
|
3163
3318
|
const node = stack.pop();
|
|
3164
|
-
if ((
|
|
3319
|
+
if (_readNodeType(node) === NODE_TYPE.element) _stripDisallowedAttributes(node);
|
|
3165
3320
|
const childNodes = getChildNodes(node);
|
|
3166
3321
|
if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]);
|
|
3167
3322
|
}
|
|
@@ -3201,12 +3356,28 @@ function createDOMPurify() {
|
|
|
3201
3356
|
*
|
|
3202
3357
|
* @param root the in-place root to sweep
|
|
3203
3358
|
*/
|
|
3359
|
+
/**
|
|
3360
|
+
* Central policy for declarative-partial-updates patch-linkage attributes,
|
|
3361
|
+
* shared by the _neutralizePatchLinkage pre-pass and _isValidAttribute so
|
|
3362
|
+
* the two sites cannot drift: `patchsrc` always links, `for` links
|
|
3363
|
+
* everywhere except on <label>/<output>, and the whole policy is gated on
|
|
3364
|
+
* SAFE_FOR_XML (see the rationale block in _isValidAttribute).
|
|
3365
|
+
*
|
|
3366
|
+
* @param lcName the transformCaseFunc'd attribute name
|
|
3367
|
+
* @param lcTag the transformCaseFunc'd tag name of the carrying element
|
|
3368
|
+
* @return true if the attribute is patch linkage and must be dropped
|
|
3369
|
+
*/
|
|
3370
|
+
const _isPatchLinkageAttribute = function _isPatchLinkageAttribute(lcName, lcTag) {
|
|
3371
|
+
if (!SAFE_FOR_XML) return false;
|
|
3372
|
+
if (lcName === "patchsrc") return true;
|
|
3373
|
+
return lcName === "for" && lcTag !== "label" && lcTag !== "output";
|
|
3374
|
+
};
|
|
3204
3375
|
const _neutralizePatchLinkage = function _neutralizePatchLinkage(root) {
|
|
3205
3376
|
if (!SAFE_FOR_XML) return;
|
|
3206
3377
|
const stack = [root];
|
|
3207
3378
|
while (stack.length > 0) {
|
|
3208
3379
|
const node = stack.pop();
|
|
3209
|
-
const nodeType =
|
|
3380
|
+
const nodeType = _readNodeType(node);
|
|
3210
3381
|
if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) {
|
|
3211
3382
|
try {
|
|
3212
3383
|
remove(node);
|
|
@@ -3215,10 +3386,10 @@ function createDOMPurify() {
|
|
|
3215
3386
|
}
|
|
3216
3387
|
if (nodeType === NODE_TYPE.element) {
|
|
3217
3388
|
const element = node;
|
|
3218
|
-
const lcTag = transformCaseFunc(
|
|
3389
|
+
const lcTag = transformCaseFunc(_readNodeName(node));
|
|
3219
3390
|
try {
|
|
3220
3391
|
if (element.hasAttribute && element.hasAttribute("patchsrc")) element.removeAttribute("patchsrc");
|
|
3221
|
-
if (element.hasAttribute && element.hasAttribute("for") &&
|
|
3392
|
+
if (element.hasAttribute && element.hasAttribute("for") && _isPatchLinkageAttribute("for", lcTag)) element.removeAttribute("for");
|
|
3222
3393
|
} catch (_) {}
|
|
3223
3394
|
}
|
|
3224
3395
|
const childNodes = getChildNodes(node);
|
|
@@ -3329,7 +3500,7 @@ function createDOMPurify() {
|
|
|
3329
3500
|
const realTagName = getNodeName ? getNodeName(element) : null;
|
|
3330
3501
|
if (typeof realTagName !== "string") return false;
|
|
3331
3502
|
if (transformCaseFunc(realTagName) !== "form") return false;
|
|
3332
|
-
return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || element.nodeType !== getNodeType(element) || element.childNodes !== getChildNodes(element);
|
|
3503
|
+
return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.removeAttributeNode !== "function" || typeof element.getAttributeNode !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || element.nodeType !== getNodeType(element) || element.childNodes !== getChildNodes(element);
|
|
3333
3504
|
};
|
|
3334
3505
|
/**
|
|
3335
3506
|
* Checks whether the given value is a DocumentFragment from any realm.
|
|
@@ -3387,12 +3558,32 @@ function createDOMPurify() {
|
|
|
3387
3558
|
*/
|
|
3388
3559
|
const _isUnsafeNode = function _isUnsafeNode(currentNode, tagName) {
|
|
3389
3560
|
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) return true;
|
|
3390
|
-
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "
|
|
3561
|
+
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && LITERAL_TEXT_ELEMENTS[tagName] && (_isNode(currentNode.firstElementChild) || typeof currentNode.textContent === "string" && regExpTest(LITERAL_TEXT_CLOSE[tagName], currentNode.textContent))) return true;
|
|
3391
3562
|
if (currentNode.nodeType === NODE_TYPE.processingInstruction) return true;
|
|
3392
3563
|
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) return true;
|
|
3393
3564
|
return false;
|
|
3394
3565
|
};
|
|
3395
3566
|
/**
|
|
3567
|
+
* Evaluate a CUSTOM_ELEMENT_HANDLING check (a RegExp or a predicate
|
|
3568
|
+
* function, per the validation in _parseConfig) against a name.
|
|
3569
|
+
* Additional arguments are forwarded to predicate functions - the
|
|
3570
|
+
* attributeNameCheck predicate receives the tag name as its second
|
|
3571
|
+
* argument. A null/absent check never matches.
|
|
3572
|
+
*
|
|
3573
|
+
* @param check the configured tagNameCheck / attributeNameCheck value
|
|
3574
|
+
* @param name the name to test
|
|
3575
|
+
* @param args extra arguments forwarded to a predicate function
|
|
3576
|
+
* @return true if the check matches the name
|
|
3577
|
+
*/
|
|
3578
|
+
const _matchesNameCheck = function _matchesNameCheck(check, name) {
|
|
3579
|
+
if (check instanceof RegExp) return regExpTest(check, name);
|
|
3580
|
+
if (check instanceof Function) {
|
|
3581
|
+
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) args[_key - 2] = arguments[_key];
|
|
3582
|
+
return Boolean(check(name, ...args));
|
|
3583
|
+
}
|
|
3584
|
+
return false;
|
|
3585
|
+
};
|
|
3586
|
+
/**
|
|
3396
3587
|
* Handle a node whose tag is forbidden or not allowlisted: keep
|
|
3397
3588
|
* allowed custom elements (false return exits _sanitizeElements
|
|
3398
3589
|
* early - the namespace and fallback-tag removal checks are
|
|
@@ -3410,10 +3601,7 @@ function createDOMPurify() {
|
|
|
3410
3601
|
* @return true if the node was removed, false if kept
|
|
3411
3602
|
*/
|
|
3412
3603
|
const _sanitizeDisallowedNode = function _sanitizeDisallowedNode(currentNode, tagName, root) {
|
|
3413
|
-
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName))
|
|
3414
|
-
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
3415
|
-
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
3416
|
-
}
|
|
3604
|
+
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
3417
3605
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
3418
3606
|
const parentNode = getParentNode(currentNode);
|
|
3419
3607
|
const childNodes = getChildNodes(currentNode);
|
|
@@ -3447,6 +3635,42 @@ function createDOMPurify() {
|
|
|
3447
3635
|
return set === defaultSet || set === setConfigSet ? clone(set) : set;
|
|
3448
3636
|
};
|
|
3449
3637
|
/**
|
|
3638
|
+
* Shared guard for a node that a hook has detached from the walk tree,
|
|
3639
|
+
* used after each element-hook site in _sanitizeElements. Detaching is a
|
|
3640
|
+
* long-standing user pattern (issue #469; draw.io-style foreignObject
|
|
3641
|
+
* filtering). Per the cached, unclobberable parentNode getter the node is
|
|
3642
|
+
* genuinely out of the tree, so it can reach neither the serialized
|
|
3643
|
+
* output nor an IN_PLACE live tree; treat it as removed and stop
|
|
3644
|
+
* processing it. Without this guard, the unsafe-node / namespace checks
|
|
3645
|
+
* would call _forceRemove on a parentless node and hit the REPORT-3
|
|
3646
|
+
* fail-closed throw — which exists for nodes DOMPurify wants gone but
|
|
3647
|
+
* *cannot* detach (clobbered / parentless roots), the opposite of a node
|
|
3648
|
+
* that is already safely gone. The walk root is exempt: a detached
|
|
3649
|
+
* IN_PLACE root is legitimate input and must still be fully sanitized,
|
|
3650
|
+
* and a kill-decision on it must keep hitting the REPORT-3 throw.
|
|
3651
|
+
*
|
|
3652
|
+
* Nodes detached by hooks stay the hook's responsibility for placement:
|
|
3653
|
+
* they are not recorded in DOMPurify.removed, so the post-walk IN_PLACE
|
|
3654
|
+
* pass (which iterates DOMPurify.removed) does not reach them. But a
|
|
3655
|
+
* hook-detached subtree can still hold a queued resource-event handler -
|
|
3656
|
+
* e.g. an <img onload> that began loading when the caller built the live
|
|
3657
|
+
* tree - which fires in page scope after sanitize returns even though the
|
|
3658
|
+
* handler never reached the returned tree. That is the audit-5 F1 hazard,
|
|
3659
|
+
* and the documented node.remove() hook pattern walks straight into it.
|
|
3660
|
+
* So on the IN_PLACE path we neutralize the detached subtree inline,
|
|
3661
|
+
* stripping its non-allow-listed attributes before returning, exactly as
|
|
3662
|
+
* the post-walk pass does for _forceRemove'd subtrees.
|
|
3663
|
+
*
|
|
3664
|
+
* @param currentNode the node a hook may have detached
|
|
3665
|
+
* @param root the current walk root
|
|
3666
|
+
* @return true if the node is detached and now handled, false otherwise
|
|
3667
|
+
*/
|
|
3668
|
+
const _handleHookDetachedNode = function _handleHookDetachedNode(currentNode, root) {
|
|
3669
|
+
if (currentNode === root || getParentNode(currentNode) !== null) return false;
|
|
3670
|
+
if (IN_PLACE) _neutralizeSubtree(currentNode);
|
|
3671
|
+
return true;
|
|
3672
|
+
};
|
|
3673
|
+
/**
|
|
3450
3674
|
* _sanitizeElements
|
|
3451
3675
|
*
|
|
3452
3676
|
* @protect nodeName
|
|
@@ -3457,34 +3681,31 @@ function createDOMPurify() {
|
|
|
3457
3681
|
*/
|
|
3458
3682
|
const _sanitizeElements = function _sanitizeElements(currentNode, root) {
|
|
3459
3683
|
_executeHooks(hooks.beforeSanitizeElements, currentNode, null);
|
|
3460
|
-
if (currentNode
|
|
3461
|
-
if (IN_PLACE) _neutralizeSubtree(currentNode);
|
|
3462
|
-
return true;
|
|
3463
|
-
}
|
|
3684
|
+
if (_handleHookDetachedNode(currentNode, root)) return true;
|
|
3464
3685
|
if (_isClobbered(currentNode)) {
|
|
3465
3686
|
_forceRemove(currentNode);
|
|
3466
3687
|
return true;
|
|
3467
3688
|
}
|
|
3468
|
-
const tagName = transformCaseFunc(
|
|
3689
|
+
const tagName = transformCaseFunc(_readNodeName(currentNode));
|
|
3469
3690
|
ALLOWED_TAGS = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS);
|
|
3470
3691
|
_executeHooks(hooks.uponSanitizeElement, currentNode, {
|
|
3471
3692
|
tagName,
|
|
3472
3693
|
allowedTags: ALLOWED_TAGS
|
|
3473
3694
|
});
|
|
3474
|
-
if (currentNode
|
|
3475
|
-
if (IN_PLACE) _neutralizeSubtree(currentNode);
|
|
3476
|
-
return true;
|
|
3477
|
-
}
|
|
3695
|
+
if (_handleHookDetachedNode(currentNode, root)) return true;
|
|
3478
3696
|
if (_isUnsafeNode(currentNode, tagName)) {
|
|
3479
3697
|
_forceRemove(currentNode);
|
|
3480
3698
|
return true;
|
|
3481
3699
|
}
|
|
3482
3700
|
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
|
|
3483
3701
|
const removed = _sanitizeDisallowedNode(currentNode, tagName, root);
|
|
3484
|
-
if (removed === false)
|
|
3702
|
+
if (removed === false) {
|
|
3703
|
+
_executeHooks(hooks.afterSanitizeElements, currentNode, null);
|
|
3704
|
+
if (_handleHookDetachedNode(currentNode, root)) return true;
|
|
3705
|
+
}
|
|
3485
3706
|
return removed;
|
|
3486
3707
|
}
|
|
3487
|
-
if ((
|
|
3708
|
+
if (_readNodeType(currentNode) === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
|
|
3488
3709
|
_forceRemove(currentNode);
|
|
3489
3710
|
return true;
|
|
3490
3711
|
}
|
|
@@ -3500,7 +3721,7 @@ function createDOMPurify() {
|
|
|
3500
3721
|
}
|
|
3501
3722
|
}
|
|
3502
3723
|
_executeHooks(hooks.afterSanitizeElements, currentNode, null);
|
|
3503
|
-
return
|
|
3724
|
+
return _handleHookDetachedNode(currentNode, root);
|
|
3504
3725
|
};
|
|
3505
3726
|
/**
|
|
3506
3727
|
* _isValidAttribute
|
|
@@ -3512,20 +3733,17 @@ function createDOMPurify() {
|
|
|
3512
3733
|
*/
|
|
3513
3734
|
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
3514
3735
|
if (FORBID_ATTR[lcName]) return false;
|
|
3515
|
-
if (
|
|
3516
|
-
if (SAFE_FOR_XML && lcName === "for" && lcTag !== "label" && lcTag !== "output") return false;
|
|
3736
|
+
if (_isPatchLinkageAttribute(lcName, lcTag)) return false;
|
|
3517
3737
|
if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document || value in formElement)) return false;
|
|
3518
3738
|
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
3519
|
-
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName));
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
else if (value) return false;
|
|
3528
|
-
return true;
|
|
3739
|
+
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) return true;
|
|
3740
|
+
if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) return true;
|
|
3741
|
+
if (!nameIsPermitted) return _isBasicCustomElement(lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName, lcTag) || lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value);
|
|
3742
|
+
if (URI_SAFE_ATTRIBUTES[lcName]) return true;
|
|
3743
|
+
if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true;
|
|
3744
|
+
if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) return true;
|
|
3745
|
+
if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true;
|
|
3746
|
+
return !value;
|
|
3529
3747
|
};
|
|
3530
3748
|
const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, [
|
|
3531
3749
|
"annotation-xml",
|
|
@@ -3570,24 +3788,38 @@ function createDOMPurify() {
|
|
|
3570
3788
|
/**
|
|
3571
3789
|
* Write a modified attribute value back onto the element. On
|
|
3572
3790
|
* success, re-probe for clobbering introduced by the new value and
|
|
3573
|
-
* remove the element when found; otherwise
|
|
3574
|
-
*
|
|
3575
|
-
*
|
|
3791
|
+
* remove the element when found; otherwise, when this writeback is the
|
|
3792
|
+
* recreate half of the SANITIZE_NAMED_PROPS remove-and-recreate, pop the
|
|
3793
|
+
* removal entry that path recorded so it does not show as removed. On
|
|
3576
3794
|
* failure, remove the attribute instead.
|
|
3577
3795
|
*
|
|
3796
|
+
* Returns true only on a clean write (the value was set and the new value
|
|
3797
|
+
* introduced no clobbering). The caller uses that, together with its own
|
|
3798
|
+
* knowledge of whether this attribute pushed a DOMPurify.removed record, to
|
|
3799
|
+
* decide whether to pop that record. The pop must happen ONLY for the
|
|
3800
|
+
* named-prop remove-and-recreate; popping on any other value change (trim,
|
|
3801
|
+
* template scrubbing, Trusted Types) would consume an unrelated _forceRemove
|
|
3802
|
+
* subtree-cleanup record and let that detached subtree keep a live event
|
|
3803
|
+
* handler through the IN_PLACE neutralization pass (SO-001).
|
|
3804
|
+
*
|
|
3578
3805
|
* @param currentNode the element carrying the attribute
|
|
3579
3806
|
* @param name the attribute name as present on the element
|
|
3580
3807
|
* @param namespaceURI the attribute's namespace, if any
|
|
3581
3808
|
* @param value the new attribute value
|
|
3809
|
+
* @return true if the value was written without introducing clobbering
|
|
3582
3810
|
*/
|
|
3583
3811
|
const _setAttributeValue = function _setAttributeValue(currentNode, name, namespaceURI, value) {
|
|
3584
3812
|
try {
|
|
3585
3813
|
if (namespaceURI) currentNode.setAttributeNS(namespaceURI, name, value);
|
|
3586
3814
|
else currentNode.setAttribute(name, value);
|
|
3587
|
-
if (_isClobbered(currentNode))
|
|
3588
|
-
|
|
3815
|
+
if (_isClobbered(currentNode)) {
|
|
3816
|
+
_forceRemove(currentNode);
|
|
3817
|
+
return false;
|
|
3818
|
+
}
|
|
3819
|
+
return true;
|
|
3589
3820
|
} catch (_) {
|
|
3590
3821
|
_removeAttribute(name, currentNode);
|
|
3822
|
+
return false;
|
|
3591
3823
|
}
|
|
3592
3824
|
};
|
|
3593
3825
|
/**
|
|
@@ -3599,9 +3831,11 @@ function createDOMPurify() {
|
|
|
3599
3831
|
* @protect setAttribute
|
|
3600
3832
|
*
|
|
3601
3833
|
* @param currentNode to sanitize
|
|
3834
|
+
* @param root the current walk root
|
|
3602
3835
|
*/
|
|
3603
|
-
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
3836
|
+
const _sanitizeAttributes = function _sanitizeAttributes(currentNode, root) {
|
|
3604
3837
|
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
|
3838
|
+
if (_handleHookDetachedNode(currentNode, root)) return;
|
|
3605
3839
|
const attributes = currentNode.attributes;
|
|
3606
3840
|
if (!attributes || _isClobbered(currentNode)) return;
|
|
3607
3841
|
ALLOWED_ATTR = _forkSharedAllowlist(hooks.uponSanitizeAttribute, ALLOWED_ATTR, DEFAULT_ALLOWED_ATTR, SET_CONFIG_ALLOWED_ATTR);
|
|
@@ -3620,6 +3854,7 @@ function createDOMPurify() {
|
|
|
3620
3854
|
const lcName = transformCaseFunc(name);
|
|
3621
3855
|
const initValue = attrValue;
|
|
3622
3856
|
let value = name === "value" ? initValue : stringTrim(initValue);
|
|
3857
|
+
let recreatedNamedProp = false;
|
|
3623
3858
|
hookEvent.attrName = lcName;
|
|
3624
3859
|
hookEvent.attrValue = value;
|
|
3625
3860
|
hookEvent.keepAttr = true;
|
|
@@ -3627,35 +3862,39 @@ function createDOMPurify() {
|
|
|
3627
3862
|
_executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
|
|
3628
3863
|
value = hookEvent.attrValue;
|
|
3629
3864
|
if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
|
|
3630
|
-
_removeAttribute(name, currentNode);
|
|
3865
|
+
_removeAttribute(name, currentNode, attr);
|
|
3631
3866
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
3867
|
+
recreatedNamedProp = true;
|
|
3632
3868
|
}
|
|
3633
3869
|
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
3634
|
-
_removeAttribute(name, currentNode);
|
|
3870
|
+
_removeAttribute(name, currentNode, attr);
|
|
3635
3871
|
continue;
|
|
3636
3872
|
}
|
|
3637
3873
|
if (lcName === "attributename" && stringMatch(value, "href")) {
|
|
3638
|
-
_removeAttribute(name, currentNode);
|
|
3874
|
+
_removeAttribute(name, currentNode, attr);
|
|
3639
3875
|
continue;
|
|
3640
3876
|
}
|
|
3641
3877
|
if (hookEvent.forceKeepAttr) continue;
|
|
3642
3878
|
if (!hookEvent.keepAttr) {
|
|
3643
|
-
_removeAttribute(name, currentNode);
|
|
3879
|
+
_removeAttribute(name, currentNode, attr);
|
|
3644
3880
|
continue;
|
|
3645
3881
|
}
|
|
3646
3882
|
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
|
|
3647
|
-
_removeAttribute(name, currentNode);
|
|
3883
|
+
_removeAttribute(name, currentNode, attr);
|
|
3648
3884
|
continue;
|
|
3649
3885
|
}
|
|
3650
3886
|
if (SAFE_FOR_TEMPLATES) value = _stripTemplateExpressions(value);
|
|
3651
3887
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
3652
|
-
_removeAttribute(name, currentNode);
|
|
3888
|
+
_removeAttribute(name, currentNode, attr);
|
|
3653
3889
|
continue;
|
|
3654
3890
|
}
|
|
3655
3891
|
value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
|
|
3656
|
-
if (value !== initValue)
|
|
3892
|
+
if (value !== initValue) {
|
|
3893
|
+
if (_setAttributeValue(currentNode, name, namespaceURI, value) && recreatedNamedProp) arrayPop(DOMPurify.removed);
|
|
3894
|
+
}
|
|
3657
3895
|
}
|
|
3658
3896
|
_executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
|
|
3897
|
+
_handleHookDetachedNode(currentNode, root);
|
|
3659
3898
|
};
|
|
3660
3899
|
/**
|
|
3661
3900
|
* _sanitizeShadowDOM
|
|
@@ -3669,9 +3908,9 @@ function createDOMPurify() {
|
|
|
3669
3908
|
while (shadowNode = shadowIterator.nextNode()) {
|
|
3670
3909
|
_executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
|
|
3671
3910
|
_sanitizeElements(shadowNode, fragment);
|
|
3672
|
-
_sanitizeAttributes(shadowNode);
|
|
3911
|
+
_sanitizeAttributes(shadowNode, fragment);
|
|
3673
3912
|
if (_isDocumentFragment(shadowNode.content)) _sanitizeShadowDOM2(shadowNode.content);
|
|
3674
|
-
if ((
|
|
3913
|
+
if (_readNodeType(shadowNode) === NODE_TYPE.element) {
|
|
3675
3914
|
const innerSr = getShadowRoot(shadowNode);
|
|
3676
3915
|
if (_isDocumentFragment(innerSr)) {
|
|
3677
3916
|
_sanitizeAttachedShadowRoots(innerSr);
|
|
@@ -3712,7 +3951,7 @@ function createDOMPurify() {
|
|
|
3712
3951
|
continue;
|
|
3713
3952
|
}
|
|
3714
3953
|
const node = item.node;
|
|
3715
|
-
const isElement = (
|
|
3954
|
+
const isElement = _readNodeType(node) === NODE_TYPE.element;
|
|
3716
3955
|
const childNodes = getChildNodes(node);
|
|
3717
3956
|
if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push({
|
|
3718
3957
|
node: childNodes[i],
|
|
@@ -3763,7 +4002,7 @@ function createDOMPurify() {
|
|
|
3763
4002
|
const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
|
|
3764
4003
|
if (inPlace) {
|
|
3765
4004
|
_neutralizePatchLinkage(dirty);
|
|
3766
|
-
const nn =
|
|
4005
|
+
const nn = _readNodeName(dirty);
|
|
3767
4006
|
if (typeof nn === "string") {
|
|
3768
4007
|
const tagName = transformCaseFunc(nn);
|
|
3769
4008
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
@@ -3787,7 +4026,7 @@ function createDOMPurify() {
|
|
|
3787
4026
|
if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") body = importedNode;
|
|
3788
4027
|
else if (importedNode.nodeName === "HTML") body = importedNode;
|
|
3789
4028
|
else body.appendChild(importedNode);
|
|
3790
|
-
_sanitizeAttachedShadowRoots(
|
|
4029
|
+
_sanitizeAttachedShadowRoots(body);
|
|
3791
4030
|
} else {
|
|
3792
4031
|
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf("<") === -1) return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
|
|
3793
4032
|
body = _initDocument(dirty);
|
|
@@ -3799,7 +4038,7 @@ function createDOMPurify() {
|
|
|
3799
4038
|
const nodeIterator = _createNodeIterator(walkRoot);
|
|
3800
4039
|
while (currentNode = nodeIterator.nextNode()) {
|
|
3801
4040
|
_sanitizeElements(currentNode, walkRoot);
|
|
3802
|
-
_sanitizeAttributes(currentNode);
|
|
4041
|
+
_sanitizeAttributes(currentNode, walkRoot);
|
|
3803
4042
|
if (_isDocumentFragment(currentNode.content)) _sanitizeShadowDOM2(currentNode.content);
|
|
3804
4043
|
}
|
|
3805
4044
|
} catch (error) {
|
|
@@ -3812,9 +4051,14 @@ function createDOMPurify() {
|
|
|
3812
4051
|
throw error;
|
|
3813
4052
|
}
|
|
3814
4053
|
if (inPlace) {
|
|
4054
|
+
let rootWasRemoved = false;
|
|
3815
4055
|
arrayForEach(DOMPurify.removed, (entry) => {
|
|
3816
|
-
if (entry.element)
|
|
4056
|
+
if (entry.element) {
|
|
4057
|
+
if (entry.element === dirty) rootWasRemoved = true;
|
|
4058
|
+
_neutralizeSubtree(entry.element);
|
|
4059
|
+
}
|
|
3817
4060
|
});
|
|
4061
|
+
if (rootWasRemoved) throw typeErrorCreate("a node selected for removal could not be safely returned; refusing to sanitize in place");
|
|
3818
4062
|
if (SAFE_FOR_TEMPLATES) _scrubTemplateExpressions2(dirty);
|
|
3819
4063
|
return dirty;
|
|
3820
4064
|
}
|