@mulmoclaude/core 4.5.0 → 4.7.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/dist/collection/core/schemaZ.d.ts +1 -1
- package/dist/collection/registry/server/index.cjs +1 -1
- package/dist/collection/registry/server/index.js +1 -1
- package/dist/collection/server/index.cjs +2 -1
- package/dist/collection/server/index.js +2 -2
- package/dist/collection/server/skillAssets.d.ts +20 -0
- package/dist/collection-watchers/index.cjs +1 -1
- package/dist/collection-watchers/index.js +1 -1
- package/dist/feeds/server/index.cjs +1 -1
- package/dist/feeds/server/index.js +1 -1
- package/dist/global-config/index.cjs +1 -1
- package/dist/google/index.cjs +1 -1
- package/dist/{paths-ClV946_f.cjs → paths-C8-jxR0s.cjs} +1 -2
- package/dist/{paths-ClV946_f.cjs.map → paths-C8-jxR0s.cjs.map} +1 -1
- package/dist/plugin-vue/index.cjs +214 -75
- package/dist/plugin-vue/index.cjs.map +1 -1
- package/dist/plugin-vue/index.js +214 -75
- package/dist/plugin-vue/index.js.map +1 -1
- package/dist/{server-Wz4_ALLl.cjs → server-DXUt34Rt.cjs} +79 -29
- package/dist/server-DXUt34Rt.cjs.map +1 -0
- package/dist/{server-BENtFplH.js → server-DyYwfNB6.js} +74 -30
- package/dist/server-DyYwfNB6.js.map +1 -0
- package/package.json +4 -4
- package/dist/server-BENtFplH.js.map +0 -1
- package/dist/server-Wz4_ALLl.cjs.map +0 -1
|
@@ -138,7 +138,7 @@ IconGlyph.props = {
|
|
|
138
138
|
};
|
|
139
139
|
//#endregion
|
|
140
140
|
//#region ../../node_modules/dompurify/dist/purify.es.mjs
|
|
141
|
-
/*! @license DOMPurify 3.4.
|
|
141
|
+
/*! @license DOMPurify 3.4.14 | (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.14/LICENSE */
|
|
142
142
|
function _arrayLikeToArray(r, a) {
|
|
143
143
|
(null == a || a > r.length) && (a = r.length);
|
|
144
144
|
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
@@ -297,9 +297,11 @@ function clone(object) {
|
|
|
297
297
|
var _ref3 = _slicedToArray(_ref2, 2);
|
|
298
298
|
const property = _ref3[0];
|
|
299
299
|
const value = _ref3[1];
|
|
300
|
-
if (objectHasOwnProperty(object, property))
|
|
301
|
-
|
|
302
|
-
|
|
300
|
+
if (objectHasOwnProperty(object, property)) {
|
|
301
|
+
if (arrayIsArray(value)) newObject[property] = cleanArray(value);
|
|
302
|
+
else if (value && typeof value === "object" && value.constructor === Object) newObject[property] = clone(value);
|
|
303
|
+
else newObject[property] = value;
|
|
304
|
+
}
|
|
303
305
|
}
|
|
304
306
|
return newObject;
|
|
305
307
|
}
|
|
@@ -867,6 +869,7 @@ var svg = freeze([
|
|
|
867
869
|
"patterncontentunits",
|
|
868
870
|
"patterntransform",
|
|
869
871
|
"patternunits",
|
|
872
|
+
"pointer-events",
|
|
870
873
|
"points",
|
|
871
874
|
"preservealpha",
|
|
872
875
|
"preserveaspectratio",
|
|
@@ -921,6 +924,7 @@ var svg = freeze([
|
|
|
921
924
|
"u2",
|
|
922
925
|
"unicode",
|
|
923
926
|
"values",
|
|
927
|
+
"vector-effect",
|
|
924
928
|
"viewbox",
|
|
925
929
|
"visibility",
|
|
926
930
|
"version",
|
|
@@ -1034,6 +1038,24 @@ var NODE_TYPE = {
|
|
|
1034
1038
|
documentFragment: 11,
|
|
1035
1039
|
notation: 12
|
|
1036
1040
|
};
|
|
1041
|
+
var LITERAL_TEXT_ELEMENT_NAMES = [
|
|
1042
|
+
"style",
|
|
1043
|
+
"script",
|
|
1044
|
+
"xmp",
|
|
1045
|
+
"iframe",
|
|
1046
|
+
"noembed",
|
|
1047
|
+
"noframes",
|
|
1048
|
+
"plaintext",
|
|
1049
|
+
"noscript"
|
|
1050
|
+
];
|
|
1051
|
+
var LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES));
|
|
1052
|
+
var LITERAL_TEXT_CLOSE = function() {
|
|
1053
|
+
const map = {};
|
|
1054
|
+
arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, (name) => {
|
|
1055
|
+
map[name] = seal(new RegExp("</" + name + "(?=[\\t\\n\\f\\r />])", "i"));
|
|
1056
|
+
});
|
|
1057
|
+
return freeze(map);
|
|
1058
|
+
}();
|
|
1037
1059
|
var getGlobal = function getGlobal() {
|
|
1038
1060
|
return typeof window === "undefined" ? null : window;
|
|
1039
1061
|
};
|
|
@@ -1093,10 +1115,25 @@ var _createHooksMap = function _createHooksMap() {
|
|
|
1093
1115
|
var _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) {
|
|
1094
1116
|
return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
|
|
1095
1117
|
};
|
|
1118
|
+
/**
|
|
1119
|
+
* Resolve an object-valued configuration option: a prototype-free clone
|
|
1120
|
+
* of cfg[key] when it is an own, truthy object property, else a fresh
|
|
1121
|
+
* fallback built by makeFallback (fresh on every parse, so a previous
|
|
1122
|
+
* parse can never leak state into the next one).
|
|
1123
|
+
*
|
|
1124
|
+
* @param cfg the cloned, prototype-free configuration object
|
|
1125
|
+
* @param key the configuration property to read
|
|
1126
|
+
* @param makeFallback builds the fallback value when the option is absent
|
|
1127
|
+
* @returns the resolved object
|
|
1128
|
+
*/
|
|
1129
|
+
var _resolveObjectOption = function _resolveObjectOption(cfg, key, makeFallback) {
|
|
1130
|
+
const value = objectHasOwnProperty(cfg, key) ? cfg[key] : void 0;
|
|
1131
|
+
return value && typeof value === "object" ? clone(value) : makeFallback();
|
|
1132
|
+
};
|
|
1096
1133
|
function createDOMPurify() {
|
|
1097
1134
|
let window = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
|
|
1098
1135
|
const DOMPurify = (root) => createDOMPurify(root);
|
|
1099
|
-
DOMPurify.version = "3.4.
|
|
1136
|
+
DOMPurify.version = "3.4.14";
|
|
1100
1137
|
DOMPurify.removed = [];
|
|
1101
1138
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
1102
1139
|
DOMPurify.isSupported = false;
|
|
@@ -1121,6 +1158,12 @@ function createDOMPurify() {
|
|
|
1121
1158
|
const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null;
|
|
1122
1159
|
const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null;
|
|
1123
1160
|
const getOwnerDocument = Node && Node.prototype ? lookupGetter(Node.prototype, "ownerDocument") : null;
|
|
1161
|
+
const _readNodeType = function _readNodeType(node) {
|
|
1162
|
+
return getNodeType ? getNodeType(node) : node.nodeType;
|
|
1163
|
+
};
|
|
1164
|
+
const _readNodeName = function _readNodeName(node) {
|
|
1165
|
+
return getNodeName ? getNodeName(node) : node.nodeName;
|
|
1166
|
+
};
|
|
1124
1167
|
if (typeof HTMLTemplateElement === "function") {
|
|
1125
1168
|
const template = document.createElement("template");
|
|
1126
1169
|
if (template.content && template.content.ownerDocument) document = template.content.ownerDocument;
|
|
@@ -1378,9 +1421,9 @@ function createDOMPurify() {
|
|
|
1378
1421
|
IN_PLACE = cfg.IN_PLACE || false;
|
|
1379
1422
|
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
|
|
1380
1423
|
NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
|
|
1381
|
-
MATHML_TEXT_INTEGRATION_POINTS =
|
|
1382
|
-
HTML_INTEGRATION_POINTS =
|
|
1383
|
-
const customElementHandling =
|
|
1424
|
+
MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(cfg, "MATHML_TEXT_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS));
|
|
1425
|
+
HTML_INTEGRATION_POINTS = _resolveObjectOption(cfg, "HTML_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS));
|
|
1426
|
+
const customElementHandling = _resolveObjectOption(cfg, "CUSTOM_ELEMENT_HANDLING", () => create(null));
|
|
1384
1427
|
CUSTOM_ELEMENT_HANDLING = create(null);
|
|
1385
1428
|
if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
|
|
1386
1429
|
if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck;
|
|
@@ -1427,11 +1470,6 @@ function createDOMPurify() {
|
|
|
1427
1470
|
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
1428
1471
|
}
|
|
1429
1472
|
}
|
|
1430
|
-
if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
1431
|
-
if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) {
|
|
1432
|
-
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
1433
|
-
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
1434
|
-
}
|
|
1435
1473
|
if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
|
|
1436
1474
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
1437
1475
|
addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
|
|
@@ -1548,6 +1586,32 @@ function createDOMPurify() {
|
|
|
1548
1586
|
}
|
|
1549
1587
|
};
|
|
1550
1588
|
/**
|
|
1589
|
+
* _stripAttributeNode
|
|
1590
|
+
*
|
|
1591
|
+
* Remove a single Attr node case/namespace-exactly on an attribute-teardown
|
|
1592
|
+
* path. Name-based removeAttribute() ASCII-lowercases its lookup key for an
|
|
1593
|
+
* HTML element in an HTML document and so silently misses a case-preserved
|
|
1594
|
+
* handler (e.g. `ONERROR` off an XML/XHTML import) - the same defect
|
|
1595
|
+
* _removeAttribute() was fixed for, which a name-based call would reintroduce
|
|
1596
|
+
* on these IN_PLACE teardown paths. Unlike _removeAttribute this does not
|
|
1597
|
+
* record into DOMPurify.removed: the neutralize passes intentionally do not
|
|
1598
|
+
* book-keep. A clobbered/detached node falls back to best-effort name-based
|
|
1599
|
+
* removal.
|
|
1600
|
+
*
|
|
1601
|
+
* @param element the element to strip the attribute from
|
|
1602
|
+
* @param attribute the Attr node to remove
|
|
1603
|
+
* @param name the attribute's name, for the fallback path
|
|
1604
|
+
*/
|
|
1605
|
+
const _stripAttributeNode = function _stripAttributeNode(element, attribute, name) {
|
|
1606
|
+
try {
|
|
1607
|
+
element.removeAttributeNode(attribute);
|
|
1608
|
+
} catch (_) {
|
|
1609
|
+
try {
|
|
1610
|
+
element.removeAttribute(name);
|
|
1611
|
+
} catch (_) {}
|
|
1612
|
+
}
|
|
1613
|
+
};
|
|
1614
|
+
/**
|
|
1551
1615
|
* _neutralizeRoot
|
|
1552
1616
|
*
|
|
1553
1617
|
* Fail-closed teardown of an in-place root after the sanitize walk aborts
|
|
@@ -1581,36 +1645,53 @@ function createDOMPurify() {
|
|
|
1581
1645
|
if (attributes) for (let i = attributes.length - 1; i >= 0; --i) {
|
|
1582
1646
|
const attribute = attributes[i];
|
|
1583
1647
|
const name = attribute && attribute.name;
|
|
1584
|
-
if (typeof name === "string")
|
|
1585
|
-
root.removeAttribute(name);
|
|
1586
|
-
} catch (_) {}
|
|
1648
|
+
if (typeof name === "string") _stripAttributeNode(root, attribute, name);
|
|
1587
1649
|
}
|
|
1588
1650
|
};
|
|
1589
1651
|
/**
|
|
1590
1652
|
* _removeAttribute
|
|
1591
1653
|
*
|
|
1654
|
+
* Name-based getAttributeNode()/removeAttribute() ASCII-lowercase their
|
|
1655
|
+
* lookup key for HTML elements in an HTML document, so they silently miss an
|
|
1656
|
+
* attribute whose stored qualified name still contains uppercase ASCII
|
|
1657
|
+
* letters. That happens when the node came from a case-preserving source
|
|
1658
|
+
* (an XML/XHTML document imported via importNode(), or createAttributeNS()),
|
|
1659
|
+
* where e.g. `ONERROR` survives the walk: the policy check lowercases to
|
|
1660
|
+
* `onerror` and rejects it, but `removeAttribute('ONERROR')` looks up
|
|
1661
|
+
* `onerror` and finds nothing. Remove the exact Attr node instead, which is
|
|
1662
|
+
* case- and namespace-exact, and fall back to name-based removal only when
|
|
1663
|
+
* the caller could not supply the node.
|
|
1664
|
+
*
|
|
1592
1665
|
* @param name an Attribute name
|
|
1593
1666
|
* @param element a DOM node
|
|
1667
|
+
* @param attr the exact Attr node to remove, when the caller has it
|
|
1594
1668
|
*/
|
|
1595
|
-
const _removeAttribute = function _removeAttribute(name, element) {
|
|
1669
|
+
const _removeAttribute = function _removeAttribute(name, element, attr) {
|
|
1670
|
+
if (!attr) try {
|
|
1671
|
+
attr = element.getAttributeNode(name);
|
|
1672
|
+
} catch (_) {
|
|
1673
|
+
attr = null;
|
|
1674
|
+
}
|
|
1675
|
+
arrayPush(DOMPurify.removed, {
|
|
1676
|
+
attribute: attr || null,
|
|
1677
|
+
from: element
|
|
1678
|
+
});
|
|
1596
1679
|
try {
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
from: element
|
|
1600
|
-
});
|
|
1680
|
+
if (attr) element.removeAttributeNode(attr);
|
|
1681
|
+
else element.removeAttribute(name);
|
|
1601
1682
|
} catch (_) {
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1683
|
+
try {
|
|
1684
|
+
element.removeAttribute(name);
|
|
1685
|
+
} catch (_) {}
|
|
1686
|
+
}
|
|
1687
|
+
if (name === "is") {
|
|
1688
|
+
if (RETURN_DOM || RETURN_DOM_FRAGMENT) try {
|
|
1689
|
+
_forceRemove(element);
|
|
1690
|
+
} catch (_) {}
|
|
1691
|
+
else try {
|
|
1692
|
+
element.setAttribute(name, "");
|
|
1693
|
+
} catch (_) {}
|
|
1606
1694
|
}
|
|
1607
|
-
element.removeAttribute(name);
|
|
1608
|
-
if (name === "is") if (RETURN_DOM || RETURN_DOM_FRAGMENT) try {
|
|
1609
|
-
_forceRemove(element);
|
|
1610
|
-
} catch (_) {}
|
|
1611
|
-
else try {
|
|
1612
|
-
element.setAttribute(name, "");
|
|
1613
|
-
} catch (_) {}
|
|
1614
1695
|
};
|
|
1615
1696
|
/**
|
|
1616
1697
|
* _stripDisallowedAttributes
|
|
@@ -1629,9 +1710,7 @@ function createDOMPurify() {
|
|
|
1629
1710
|
const attribute = attributes[i];
|
|
1630
1711
|
const name = attribute && attribute.name;
|
|
1631
1712
|
if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) continue;
|
|
1632
|
-
|
|
1633
|
-
element.removeAttribute(name);
|
|
1634
|
-
} catch (_) {}
|
|
1713
|
+
_stripAttributeNode(element, attribute, name);
|
|
1635
1714
|
}
|
|
1636
1715
|
};
|
|
1637
1716
|
/**
|
|
@@ -1660,7 +1739,7 @@ function createDOMPurify() {
|
|
|
1660
1739
|
const stack = [root];
|
|
1661
1740
|
while (stack.length > 0) {
|
|
1662
1741
|
const node = stack.pop();
|
|
1663
|
-
if ((
|
|
1742
|
+
if (_readNodeType(node) === NODE_TYPE.element) _stripDisallowedAttributes(node);
|
|
1664
1743
|
const childNodes = getChildNodes(node);
|
|
1665
1744
|
if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]);
|
|
1666
1745
|
}
|
|
@@ -1700,12 +1779,28 @@ function createDOMPurify() {
|
|
|
1700
1779
|
*
|
|
1701
1780
|
* @param root the in-place root to sweep
|
|
1702
1781
|
*/
|
|
1782
|
+
/**
|
|
1783
|
+
* Central policy for declarative-partial-updates patch-linkage attributes,
|
|
1784
|
+
* shared by the _neutralizePatchLinkage pre-pass and _isValidAttribute so
|
|
1785
|
+
* the two sites cannot drift: `patchsrc` always links, `for` links
|
|
1786
|
+
* everywhere except on <label>/<output>, and the whole policy is gated on
|
|
1787
|
+
* SAFE_FOR_XML (see the rationale block in _isValidAttribute).
|
|
1788
|
+
*
|
|
1789
|
+
* @param lcName the transformCaseFunc'd attribute name
|
|
1790
|
+
* @param lcTag the transformCaseFunc'd tag name of the carrying element
|
|
1791
|
+
* @return true if the attribute is patch linkage and must be dropped
|
|
1792
|
+
*/
|
|
1793
|
+
const _isPatchLinkageAttribute = function _isPatchLinkageAttribute(lcName, lcTag) {
|
|
1794
|
+
if (!SAFE_FOR_XML) return false;
|
|
1795
|
+
if (lcName === "patchsrc") return true;
|
|
1796
|
+
return lcName === "for" && lcTag !== "label" && lcTag !== "output";
|
|
1797
|
+
};
|
|
1703
1798
|
const _neutralizePatchLinkage = function _neutralizePatchLinkage(root) {
|
|
1704
1799
|
if (!SAFE_FOR_XML) return;
|
|
1705
1800
|
const stack = [root];
|
|
1706
1801
|
while (stack.length > 0) {
|
|
1707
1802
|
const node = stack.pop();
|
|
1708
|
-
const nodeType =
|
|
1803
|
+
const nodeType = _readNodeType(node);
|
|
1709
1804
|
if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) {
|
|
1710
1805
|
try {
|
|
1711
1806
|
remove(node);
|
|
@@ -1714,10 +1809,10 @@ function createDOMPurify() {
|
|
|
1714
1809
|
}
|
|
1715
1810
|
if (nodeType === NODE_TYPE.element) {
|
|
1716
1811
|
const element = node;
|
|
1717
|
-
const lcTag = transformCaseFunc(
|
|
1812
|
+
const lcTag = transformCaseFunc(_readNodeName(node));
|
|
1718
1813
|
try {
|
|
1719
1814
|
if (element.hasAttribute && element.hasAttribute("patchsrc")) element.removeAttribute("patchsrc");
|
|
1720
|
-
if (element.hasAttribute && element.hasAttribute("for") &&
|
|
1815
|
+
if (element.hasAttribute && element.hasAttribute("for") && _isPatchLinkageAttribute("for", lcTag)) element.removeAttribute("for");
|
|
1721
1816
|
} catch (_) {}
|
|
1722
1817
|
}
|
|
1723
1818
|
const childNodes = getChildNodes(node);
|
|
@@ -1886,12 +1981,32 @@ function createDOMPurify() {
|
|
|
1886
1981
|
*/
|
|
1887
1982
|
const _isUnsafeNode = function _isUnsafeNode(currentNode, tagName) {
|
|
1888
1983
|
if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) return true;
|
|
1889
|
-
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "
|
|
1984
|
+
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;
|
|
1890
1985
|
if (currentNode.nodeType === NODE_TYPE.processingInstruction) return true;
|
|
1891
1986
|
if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) return true;
|
|
1892
1987
|
return false;
|
|
1893
1988
|
};
|
|
1894
1989
|
/**
|
|
1990
|
+
* Evaluate a CUSTOM_ELEMENT_HANDLING check (a RegExp or a predicate
|
|
1991
|
+
* function, per the validation in _parseConfig) against a name.
|
|
1992
|
+
* Additional arguments are forwarded to predicate functions - the
|
|
1993
|
+
* attributeNameCheck predicate receives the tag name as its second
|
|
1994
|
+
* argument. A null/absent check never matches.
|
|
1995
|
+
*
|
|
1996
|
+
* @param check the configured tagNameCheck / attributeNameCheck value
|
|
1997
|
+
* @param name the name to test
|
|
1998
|
+
* @param args extra arguments forwarded to a predicate function
|
|
1999
|
+
* @return true if the check matches the name
|
|
2000
|
+
*/
|
|
2001
|
+
const _matchesNameCheck = function _matchesNameCheck(check, name) {
|
|
2002
|
+
if (check instanceof RegExp) return regExpTest(check, name);
|
|
2003
|
+
if (check instanceof Function) {
|
|
2004
|
+
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) args[_key - 2] = arguments[_key];
|
|
2005
|
+
return Boolean(check(name, ...args));
|
|
2006
|
+
}
|
|
2007
|
+
return false;
|
|
2008
|
+
};
|
|
2009
|
+
/**
|
|
1895
2010
|
* Handle a node whose tag is forbidden or not allowlisted: keep
|
|
1896
2011
|
* allowed custom elements (false return exits _sanitizeElements
|
|
1897
2012
|
* early - the namespace and fallback-tag removal checks are
|
|
@@ -1909,10 +2024,7 @@ function createDOMPurify() {
|
|
|
1909
2024
|
* @return true if the node was removed, false if kept
|
|
1910
2025
|
*/
|
|
1911
2026
|
const _sanitizeDisallowedNode = function _sanitizeDisallowedNode(currentNode, tagName, root) {
|
|
1912
|
-
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName))
|
|
1913
|
-
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
1914
|
-
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
1915
|
-
}
|
|
2027
|
+
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
1916
2028
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
1917
2029
|
const parentNode = getParentNode(currentNode);
|
|
1918
2030
|
const childNodes = getChildNodes(currentNode);
|
|
@@ -1946,6 +2058,42 @@ function createDOMPurify() {
|
|
|
1946
2058
|
return set === defaultSet || set === setConfigSet ? clone(set) : set;
|
|
1947
2059
|
};
|
|
1948
2060
|
/**
|
|
2061
|
+
* Shared guard for a node that a hook has detached from the walk tree,
|
|
2062
|
+
* used after each element-hook site in _sanitizeElements. Detaching is a
|
|
2063
|
+
* long-standing user pattern (issue #469; draw.io-style foreignObject
|
|
2064
|
+
* filtering). Per the cached, unclobberable parentNode getter the node is
|
|
2065
|
+
* genuinely out of the tree, so it can reach neither the serialized
|
|
2066
|
+
* output nor an IN_PLACE live tree; treat it as removed and stop
|
|
2067
|
+
* processing it. Without this guard, the unsafe-node / namespace checks
|
|
2068
|
+
* would call _forceRemove on a parentless node and hit the REPORT-3
|
|
2069
|
+
* fail-closed throw — which exists for nodes DOMPurify wants gone but
|
|
2070
|
+
* *cannot* detach (clobbered / parentless roots), the opposite of a node
|
|
2071
|
+
* that is already safely gone. The walk root is exempt: a detached
|
|
2072
|
+
* IN_PLACE root is legitimate input and must still be fully sanitized,
|
|
2073
|
+
* and a kill-decision on it must keep hitting the REPORT-3 throw.
|
|
2074
|
+
*
|
|
2075
|
+
* Nodes detached by hooks stay the hook's responsibility for placement:
|
|
2076
|
+
* they are not recorded in DOMPurify.removed, so the post-walk IN_PLACE
|
|
2077
|
+
* pass (which iterates DOMPurify.removed) does not reach them. But a
|
|
2078
|
+
* hook-detached subtree can still hold a queued resource-event handler -
|
|
2079
|
+
* e.g. an <img onload> that began loading when the caller built the live
|
|
2080
|
+
* tree - which fires in page scope after sanitize returns even though the
|
|
2081
|
+
* handler never reached the returned tree. That is the audit-5 F1 hazard,
|
|
2082
|
+
* and the documented node.remove() hook pattern walks straight into it.
|
|
2083
|
+
* So on the IN_PLACE path we neutralize the detached subtree inline,
|
|
2084
|
+
* stripping its non-allow-listed attributes before returning, exactly as
|
|
2085
|
+
* the post-walk pass does for _forceRemove'd subtrees.
|
|
2086
|
+
*
|
|
2087
|
+
* @param currentNode the node a hook may have detached
|
|
2088
|
+
* @param root the current walk root
|
|
2089
|
+
* @return true if the node is detached and now handled, false otherwise
|
|
2090
|
+
*/
|
|
2091
|
+
const _handleHookDetachedNode = function _handleHookDetachedNode(currentNode, root) {
|
|
2092
|
+
if (currentNode === root || getParentNode(currentNode) !== null) return false;
|
|
2093
|
+
if (IN_PLACE) _neutralizeSubtree(currentNode);
|
|
2094
|
+
return true;
|
|
2095
|
+
};
|
|
2096
|
+
/**
|
|
1949
2097
|
* _sanitizeElements
|
|
1950
2098
|
*
|
|
1951
2099
|
* @protect nodeName
|
|
@@ -1956,24 +2104,18 @@ function createDOMPurify() {
|
|
|
1956
2104
|
*/
|
|
1957
2105
|
const _sanitizeElements = function _sanitizeElements(currentNode, root) {
|
|
1958
2106
|
_executeHooks(hooks.beforeSanitizeElements, currentNode, null);
|
|
1959
|
-
if (currentNode
|
|
1960
|
-
if (IN_PLACE) _neutralizeSubtree(currentNode);
|
|
1961
|
-
return true;
|
|
1962
|
-
}
|
|
2107
|
+
if (_handleHookDetachedNode(currentNode, root)) return true;
|
|
1963
2108
|
if (_isClobbered(currentNode)) {
|
|
1964
2109
|
_forceRemove(currentNode);
|
|
1965
2110
|
return true;
|
|
1966
2111
|
}
|
|
1967
|
-
const tagName = transformCaseFunc(
|
|
2112
|
+
const tagName = transformCaseFunc(_readNodeName(currentNode));
|
|
1968
2113
|
ALLOWED_TAGS = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS);
|
|
1969
2114
|
_executeHooks(hooks.uponSanitizeElement, currentNode, {
|
|
1970
2115
|
tagName,
|
|
1971
2116
|
allowedTags: ALLOWED_TAGS
|
|
1972
2117
|
});
|
|
1973
|
-
if (currentNode
|
|
1974
|
-
if (IN_PLACE) _neutralizeSubtree(currentNode);
|
|
1975
|
-
return true;
|
|
1976
|
-
}
|
|
2118
|
+
if (_handleHookDetachedNode(currentNode, root)) return true;
|
|
1977
2119
|
if (_isUnsafeNode(currentNode, tagName)) {
|
|
1978
2120
|
_forceRemove(currentNode);
|
|
1979
2121
|
return true;
|
|
@@ -1983,7 +2125,7 @@ function createDOMPurify() {
|
|
|
1983
2125
|
if (removed === false) _executeHooks(hooks.afterSanitizeElements, currentNode, null);
|
|
1984
2126
|
return removed;
|
|
1985
2127
|
}
|
|
1986
|
-
if ((
|
|
2128
|
+
if (_readNodeType(currentNode) === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
|
|
1987
2129
|
_forceRemove(currentNode);
|
|
1988
2130
|
return true;
|
|
1989
2131
|
}
|
|
@@ -2011,20 +2153,17 @@ function createDOMPurify() {
|
|
|
2011
2153
|
*/
|
|
2012
2154
|
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
2013
2155
|
if (FORBID_ATTR[lcName]) return false;
|
|
2014
|
-
if (
|
|
2015
|
-
if (SAFE_FOR_XML && lcName === "for" && lcTag !== "label" && lcTag !== "output") return false;
|
|
2156
|
+
if (_isPatchLinkageAttribute(lcName, lcTag)) return false;
|
|
2016
2157
|
if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document || value in formElement)) return false;
|
|
2017
2158
|
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
2018
|
-
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName));
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
else if (value) return false;
|
|
2027
|
-
return true;
|
|
2159
|
+
if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) return true;
|
|
2160
|
+
if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) return true;
|
|
2161
|
+
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);
|
|
2162
|
+
if (URI_SAFE_ATTRIBUTES[lcName]) return true;
|
|
2163
|
+
if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true;
|
|
2164
|
+
if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) return true;
|
|
2165
|
+
if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true;
|
|
2166
|
+
return !value;
|
|
2028
2167
|
};
|
|
2029
2168
|
const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, [
|
|
2030
2169
|
"annotation-xml",
|
|
@@ -2126,29 +2265,29 @@ function createDOMPurify() {
|
|
|
2126
2265
|
_executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
|
|
2127
2266
|
value = hookEvent.attrValue;
|
|
2128
2267
|
if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
|
|
2129
|
-
_removeAttribute(name, currentNode);
|
|
2268
|
+
_removeAttribute(name, currentNode, attr);
|
|
2130
2269
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
2131
2270
|
}
|
|
2132
2271
|
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
2133
|
-
_removeAttribute(name, currentNode);
|
|
2272
|
+
_removeAttribute(name, currentNode, attr);
|
|
2134
2273
|
continue;
|
|
2135
2274
|
}
|
|
2136
2275
|
if (lcName === "attributename" && stringMatch(value, "href")) {
|
|
2137
|
-
_removeAttribute(name, currentNode);
|
|
2276
|
+
_removeAttribute(name, currentNode, attr);
|
|
2138
2277
|
continue;
|
|
2139
2278
|
}
|
|
2140
2279
|
if (hookEvent.forceKeepAttr) continue;
|
|
2141
2280
|
if (!hookEvent.keepAttr) {
|
|
2142
|
-
_removeAttribute(name, currentNode);
|
|
2281
|
+
_removeAttribute(name, currentNode, attr);
|
|
2143
2282
|
continue;
|
|
2144
2283
|
}
|
|
2145
2284
|
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
|
|
2146
|
-
_removeAttribute(name, currentNode);
|
|
2285
|
+
_removeAttribute(name, currentNode, attr);
|
|
2147
2286
|
continue;
|
|
2148
2287
|
}
|
|
2149
2288
|
if (SAFE_FOR_TEMPLATES) value = _stripTemplateExpressions(value);
|
|
2150
2289
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
2151
|
-
_removeAttribute(name, currentNode);
|
|
2290
|
+
_removeAttribute(name, currentNode, attr);
|
|
2152
2291
|
continue;
|
|
2153
2292
|
}
|
|
2154
2293
|
value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
|
|
@@ -2170,7 +2309,7 @@ function createDOMPurify() {
|
|
|
2170
2309
|
_sanitizeElements(shadowNode, fragment);
|
|
2171
2310
|
_sanitizeAttributes(shadowNode);
|
|
2172
2311
|
if (_isDocumentFragment(shadowNode.content)) _sanitizeShadowDOM2(shadowNode.content);
|
|
2173
|
-
if ((
|
|
2312
|
+
if (_readNodeType(shadowNode) === NODE_TYPE.element) {
|
|
2174
2313
|
const innerSr = getShadowRoot(shadowNode);
|
|
2175
2314
|
if (_isDocumentFragment(innerSr)) {
|
|
2176
2315
|
_sanitizeAttachedShadowRoots(innerSr);
|
|
@@ -2211,7 +2350,7 @@ function createDOMPurify() {
|
|
|
2211
2350
|
continue;
|
|
2212
2351
|
}
|
|
2213
2352
|
const node = item.node;
|
|
2214
|
-
const isElement = (
|
|
2353
|
+
const isElement = _readNodeType(node) === NODE_TYPE.element;
|
|
2215
2354
|
const childNodes = getChildNodes(node);
|
|
2216
2355
|
if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push({
|
|
2217
2356
|
node: childNodes[i],
|
|
@@ -2262,7 +2401,7 @@ function createDOMPurify() {
|
|
|
2262
2401
|
const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
|
|
2263
2402
|
if (inPlace) {
|
|
2264
2403
|
_neutralizePatchLinkage(dirty);
|
|
2265
|
-
const nn =
|
|
2404
|
+
const nn = _readNodeName(dirty);
|
|
2266
2405
|
if (typeof nn === "string") {
|
|
2267
2406
|
const tagName = transformCaseFunc(nn);
|
|
2268
2407
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|