@mulmoclaude/core 4.4.2 → 4.5.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.
Files changed (75) hide show
  1. package/assets/helps/bug-report-faq.md +13 -0
  2. package/assets/helps/business.md +4 -0
  3. package/assets/helps/error-recovery.md +71 -0
  4. package/assets/helps/gemini.md +1 -1
  5. package/assets/helps/mulmoscript.md +71 -1
  6. package/assets/helps/presentation-deck.md +4 -1
  7. package/assets/helps/storyteller.md +7 -0
  8. package/dist/collection/core/accentColor.d.ts +23 -0
  9. package/dist/collection/core/iconGlyph.d.ts +26 -0
  10. package/dist/collection/core/schema.d.ts +9 -0
  11. package/dist/collection/core/schemaZ.d.ts +18 -0
  12. package/dist/collection/core/shortcutInfo.d.ts +14 -0
  13. package/dist/collection/core/uiTypes.d.ts +6 -0
  14. package/dist/collection/index.cjs +22 -2
  15. package/dist/collection/index.cjs.map +1 -1
  16. package/dist/collection/index.d.ts +3 -0
  17. package/dist/collection/index.js +17 -3
  18. package/dist/collection/index.js.map +1 -1
  19. package/dist/collection/registry/server/index.cjs +3 -3
  20. package/dist/collection/registry/server/index.js +3 -3
  21. package/dist/collection/server/index.cjs +5 -4
  22. package/dist/collection/server/index.js +5 -5
  23. package/dist/collection/server/paths.d.ts +10 -0
  24. package/dist/collection-watchers/index.cjs +5 -5
  25. package/dist/collection-watchers/index.js +5 -5
  26. package/dist/{discovery-Dl9nRa-m.cjs → discovery-2TvulIz8.cjs} +25 -5
  27. package/dist/discovery-2TvulIz8.cjs.map +1 -0
  28. package/dist/{discovery-P64fgtuD.js → discovery-BY-nMCuh.js} +20 -6
  29. package/dist/discovery-BY-nMCuh.js.map +1 -0
  30. package/dist/feeds/index.cjs +2 -2
  31. package/dist/feeds/index.js +2 -2
  32. package/dist/feeds/server/index.cjs +5 -5
  33. package/dist/feeds/server/index.js +5 -5
  34. package/dist/files/atomic.d.ts +4 -0
  35. package/dist/files/index.cjs +1 -1
  36. package/dist/files/index.js +1 -1
  37. package/dist/google/index.cjs +3 -3
  38. package/dist/google/index.js +3 -3
  39. package/dist/iconGlyph-D8JeNg7R.js +59 -0
  40. package/dist/iconGlyph-D8JeNg7R.js.map +1 -0
  41. package/dist/iconGlyph-fSBp6k4J.cjs +70 -0
  42. package/dist/iconGlyph-fSBp6k4J.cjs.map +1 -0
  43. package/dist/{ingestTypes-CaX7_s-K.cjs → ingestTypes-DsVH9BYy.cjs} +2 -2
  44. package/dist/{ingestTypes-CaX7_s-K.cjs.map → ingestTypes-DsVH9BYy.cjs.map} +1 -1
  45. package/dist/{ingestTypes-CIy1lHjf.js → ingestTypes-GkG7bJdB.js} +2 -2
  46. package/dist/{ingestTypes-CIy1lHjf.js.map → ingestTypes-GkG7bJdB.js.map} +1 -1
  47. package/dist/{itemId-BY2YPBkT.js → itemId-4P9S_ehz.js} +48 -2
  48. package/dist/itemId-4P9S_ehz.js.map +1 -0
  49. package/dist/{itemId-CEQdK01z.cjs → itemId-CGT2J7YK.cjs} +65 -1
  50. package/dist/itemId-CGT2J7YK.cjs.map +1 -0
  51. package/dist/plugin-vue/IconGlyph.d.ts +27 -0
  52. package/dist/plugin-vue/index.cjs +117 -201
  53. package/dist/plugin-vue/index.cjs.map +1 -1
  54. package/dist/plugin-vue/index.d.ts +1 -0
  55. package/dist/plugin-vue/index.js +118 -203
  56. package/dist/plugin-vue/index.js.map +1 -1
  57. package/dist/{promptSafety-Bp780ezk.js → promptSafety-Bte62OvU.js} +2 -2
  58. package/dist/{promptSafety-Bp780ezk.js.map → promptSafety-Bte62OvU.js.map} +1 -1
  59. package/dist/{promptSafety-C0BWDsfT.cjs → promptSafety-Cv-SoTd4.cjs} +2 -2
  60. package/dist/{promptSafety-C0BWDsfT.cjs.map → promptSafety-Cv-SoTd4.cjs.map} +1 -1
  61. package/dist/{root-BMroU_mB.js → root-BcS4-Kge.js} +12 -2
  62. package/dist/root-BcS4-Kge.js.map +1 -0
  63. package/dist/{root-rPH6FGDT.cjs → root-BvwBUcol.cjs} +12 -2
  64. package/dist/root-BvwBUcol.cjs.map +1 -0
  65. package/dist/{server-BvXO49Vj.js → server-BENtFplH.js} +47 -18
  66. package/dist/{server-BvXO49Vj.js.map → server-BENtFplH.js.map} +1 -1
  67. package/dist/{server-CF1qllGV.cjs → server-Wz4_ALLl.cjs} +47 -18
  68. package/dist/{server-CF1qllGV.cjs.map → server-Wz4_ALLl.cjs.map} +1 -1
  69. package/package.json +8 -8
  70. package/dist/discovery-Dl9nRa-m.cjs.map +0 -1
  71. package/dist/discovery-P64fgtuD.js.map +0 -1
  72. package/dist/itemId-BY2YPBkT.js.map +0 -1
  73. package/dist/itemId-CEQdK01z.cjs.map +0 -1
  74. package/dist/root-BMroU_mB.js.map +0 -1
  75. package/dist/root-rPH6FGDT.cjs.map +0 -1
@@ -3,4 +3,5 @@ export { nextFileVersion, type FileChangePayload } from './fileWatch.ts';
3
3
  export { useMarkdownDoc } from './useMarkdownDoc.ts';
4
4
  export { formatScalarField, buildMarkdownDocView, type MarkdownDocField, type MarkdownDocView } from './markdownDoc.ts';
5
5
  export { useClipboardCopy, type UseClipboardCopyHandle } from './useClipboardCopy.ts';
6
+ export { IconGlyph, type IconGlyphProps } from './IconGlyph.ts';
6
7
  export { sanitizeMarkdownHtml, _resetSanitizeForTests } from './sanitizeMarkdownHtml.ts';
@@ -1,5 +1,6 @@
1
+ import { n as resolveIconGlyph } from "../iconGlyph-D8JeNg7R.js";
1
2
  import { parseFrontmatter } from "@mulmoclaude/markdown-utils/markdown/frontmatter";
2
- import { computed, onUnmounted, ref, watch } from "vue";
3
+ import { computed, h, onUnmounted, ref, watch } from "vue";
3
4
  import { useRuntime } from "gui-chat-protocol/vue";
4
5
  //#region src/plugin-vue/fileWatch.ts
5
6
  function fileWatchChannel(filePath) {
@@ -86,8 +87,57 @@ function useClipboardCopy(resetMs = DEFAULT_RESET_MS) {
86
87
  };
87
88
  }
88
89
  //#endregion
90
+ //#region src/plugin-vue/IconGlyph.ts
91
+ var DEFAULT_SIZE_CLASS = "text-base";
92
+ var DEFAULT_FONT_CLASS = "material-symbols-outlined";
93
+ var SYMBOL_CONTAINMENT = {
94
+ display: "inline-block",
95
+ width: "1em",
96
+ overflow: "hidden"
97
+ };
98
+ var GLYPH_CONTAINMENT = {
99
+ display: "inline-block",
100
+ maxWidth: "1.25em",
101
+ overflow: "hidden",
102
+ lineHeight: "1"
103
+ };
104
+ /** Both branches carry the same semantics, and the icon-font one needs them
105
+ * MORE: its text content is the ligature NAME, so an unlabelled span makes a
106
+ * screen reader announce "podcasts" / "rss_feed" as content. 48 icon spans
107
+ * across this repo already mark themselves `aria-hidden`; these are the same
108
+ * kind of span. */
109
+ function labellingFor(ariaLabel) {
110
+ return ariaLabel ? {
111
+ role: "img",
112
+ "aria-label": ariaLabel
113
+ } : { "aria-hidden": "true" };
114
+ }
115
+ var IconGlyph = (props) => {
116
+ const sizeClass = props.sizeClass ?? DEFAULT_SIZE_CLASS;
117
+ const glyph = resolveIconGlyph(props.icon, props.fallback ?? "dataset");
118
+ const labelling = labellingFor(props.ariaLabel);
119
+ if (glyph.kind === "symbol") return h("span", {
120
+ class: [props.fontClass ?? DEFAULT_FONT_CLASS, sizeClass],
121
+ style: SYMBOL_CONTAINMENT,
122
+ ...labelling
123
+ }, glyph.name);
124
+ return h("span", {
125
+ class: sizeClass,
126
+ style: GLYPH_CONTAINMENT,
127
+ ...labelling
128
+ }, glyph.text);
129
+ };
130
+ IconGlyph.displayName = "IconGlyph";
131
+ IconGlyph.props = {
132
+ icon: String,
133
+ fallback: String,
134
+ sizeClass: String,
135
+ ariaLabel: String,
136
+ fontClass: String
137
+ };
138
+ //#endregion
89
139
  //#region ../../node_modules/dompurify/dist/purify.es.mjs
90
- /*! @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 */
140
+ /*! @license DOMPurify 3.4.13 | (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.13/LICENSE */
91
141
  function _arrayLikeToArray(r, a) {
92
142
  (null == a || a > r.length) && (a = r.length);
93
143
  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
@@ -816,7 +866,6 @@ var svg = freeze([
816
866
  "patterncontentunits",
817
867
  "patterntransform",
818
868
  "patternunits",
819
- "pointer-events",
820
869
  "points",
821
870
  "preservealpha",
822
871
  "preserveaspectratio",
@@ -871,7 +920,6 @@ var svg = freeze([
871
920
  "u2",
872
921
  "unicode",
873
922
  "values",
874
- "vector-effect",
875
923
  "viewbox",
876
924
  "visibility",
877
925
  "version",
@@ -985,24 +1033,6 @@ var NODE_TYPE = {
985
1033
  documentFragment: 11,
986
1034
  notation: 12
987
1035
  };
988
- var LITERAL_TEXT_ELEMENT_NAMES = [
989
- "style",
990
- "script",
991
- "xmp",
992
- "iframe",
993
- "noembed",
994
- "noframes",
995
- "plaintext",
996
- "noscript"
997
- ];
998
- var LITERAL_TEXT_ELEMENTS = freeze(addToSet({}, LITERAL_TEXT_ELEMENT_NAMES));
999
- var LITERAL_TEXT_CLOSE = function() {
1000
- const map = {};
1001
- arrayForEach(LITERAL_TEXT_ELEMENT_NAMES, (name) => {
1002
- map[name] = seal(new RegExp("</" + name + "(?=[\\t\\n\\f\\r />])", "i"));
1003
- });
1004
- return freeze(map);
1005
- }();
1006
1036
  var getGlobal = function getGlobal() {
1007
1037
  return typeof window === "undefined" ? null : window;
1008
1038
  };
@@ -1062,25 +1092,10 @@ var _createHooksMap = function _createHooksMap() {
1062
1092
  var _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) {
1063
1093
  return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
1064
1094
  };
1065
- /**
1066
- * Resolve an object-valued configuration option: a prototype-free clone
1067
- * of cfg[key] when it is an own, truthy object property, else a fresh
1068
- * fallback built by makeFallback (fresh on every parse, so a previous
1069
- * parse can never leak state into the next one).
1070
- *
1071
- * @param cfg the cloned, prototype-free configuration object
1072
- * @param key the configuration property to read
1073
- * @param makeFallback builds the fallback value when the option is absent
1074
- * @returns the resolved object
1075
- */
1076
- var _resolveObjectOption = function _resolveObjectOption(cfg, key, makeFallback) {
1077
- const value = objectHasOwnProperty(cfg, key) ? cfg[key] : void 0;
1078
- return value && typeof value === "object" ? clone(value) : makeFallback();
1079
- };
1080
1095
  function createDOMPurify() {
1081
1096
  let window = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
1082
1097
  const DOMPurify = (root) => createDOMPurify(root);
1083
- DOMPurify.version = "3.4.14";
1098
+ DOMPurify.version = "3.4.13";
1084
1099
  DOMPurify.removed = [];
1085
1100
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
1086
1101
  DOMPurify.isSupported = false;
@@ -1105,12 +1120,6 @@ function createDOMPurify() {
1105
1120
  const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeType") : null;
1106
1121
  const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, "nodeName") : null;
1107
1122
  const getOwnerDocument = Node && Node.prototype ? lookupGetter(Node.prototype, "ownerDocument") : null;
1108
- const _readNodeType = function _readNodeType(node) {
1109
- return getNodeType ? getNodeType(node) : node.nodeType;
1110
- };
1111
- const _readNodeName = function _readNodeName(node) {
1112
- return getNodeName ? getNodeName(node) : node.nodeName;
1113
- };
1114
1123
  if (typeof HTMLTemplateElement === "function") {
1115
1124
  const template = document.createElement("template");
1116
1125
  if (template.content && template.content.ownerDocument) document = template.content.ownerDocument;
@@ -1368,9 +1377,9 @@ function createDOMPurify() {
1368
1377
  IN_PLACE = cfg.IN_PLACE || false;
1369
1378
  IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
1370
1379
  NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
1371
- MATHML_TEXT_INTEGRATION_POINTS = _resolveObjectOption(cfg, "MATHML_TEXT_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS));
1372
- HTML_INTEGRATION_POINTS = _resolveObjectOption(cfg, "HTML_INTEGRATION_POINTS", () => addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS));
1373
- const customElementHandling = _resolveObjectOption(cfg, "CUSTOM_ELEMENT_HANDLING", () => create(null));
1380
+ MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "MATHML_TEXT_INTEGRATION_POINTS") && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === "object" ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
1381
+ HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
1382
+ const customElementHandling = objectHasOwnProperty(cfg, "CUSTOM_ELEMENT_HANDLING") && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === "object" ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
1374
1383
  CUSTOM_ELEMENT_HANDLING = create(null);
1375
1384
  if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
1376
1385
  if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck;
@@ -1417,6 +1426,11 @@ function createDOMPurify() {
1417
1426
  addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
1418
1427
  }
1419
1428
  }
1429
+ if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
1430
+ if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) {
1431
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS);
1432
+ addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
1433
+ }
1420
1434
  if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
1421
1435
  if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) FORBID_CONTENTS = clone(FORBID_CONTENTS);
1422
1436
  addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
@@ -1533,32 +1547,6 @@ function createDOMPurify() {
1533
1547
  }
1534
1548
  };
1535
1549
  /**
1536
- * _stripAttributeNode
1537
- *
1538
- * Remove a single Attr node case/namespace-exactly on an attribute-teardown
1539
- * path. Name-based removeAttribute() ASCII-lowercases its lookup key for an
1540
- * HTML element in an HTML document and so silently misses a case-preserved
1541
- * handler (e.g. `ONERROR` off an XML/XHTML import) - the same defect
1542
- * _removeAttribute() was fixed for, which a name-based call would reintroduce
1543
- * on these IN_PLACE teardown paths. Unlike _removeAttribute this does not
1544
- * record into DOMPurify.removed: the neutralize passes intentionally do not
1545
- * book-keep. A clobbered/detached node falls back to best-effort name-based
1546
- * removal.
1547
- *
1548
- * @param element the element to strip the attribute from
1549
- * @param attribute the Attr node to remove
1550
- * @param name the attribute's name, for the fallback path
1551
- */
1552
- const _stripAttributeNode = function _stripAttributeNode(element, attribute, name) {
1553
- try {
1554
- element.removeAttributeNode(attribute);
1555
- } catch (_) {
1556
- try {
1557
- element.removeAttribute(name);
1558
- } catch (_) {}
1559
- }
1560
- };
1561
- /**
1562
1550
  * _neutralizeRoot
1563
1551
  *
1564
1552
  * Fail-closed teardown of an in-place root after the sanitize walk aborts
@@ -1592,45 +1580,30 @@ function createDOMPurify() {
1592
1580
  if (attributes) for (let i = attributes.length - 1; i >= 0; --i) {
1593
1581
  const attribute = attributes[i];
1594
1582
  const name = attribute && attribute.name;
1595
- if (typeof name === "string") _stripAttributeNode(root, attribute, name);
1583
+ if (typeof name === "string") try {
1584
+ root.removeAttribute(name);
1585
+ } catch (_) {}
1596
1586
  }
1597
1587
  };
1598
1588
  /**
1599
1589
  * _removeAttribute
1600
1590
  *
1601
- * Name-based getAttributeNode()/removeAttribute() ASCII-lowercase their
1602
- * lookup key for HTML elements in an HTML document, so they silently miss an
1603
- * attribute whose stored qualified name still contains uppercase ASCII
1604
- * letters. That happens when the node came from a case-preserving source
1605
- * (an XML/XHTML document imported via importNode(), or createAttributeNS()),
1606
- * where e.g. `ONERROR` survives the walk: the policy check lowercases to
1607
- * `onerror` and rejects it, but `removeAttribute('ONERROR')` looks up
1608
- * `onerror` and finds nothing. Remove the exact Attr node instead, which is
1609
- * case- and namespace-exact, and fall back to name-based removal only when
1610
- * the caller could not supply the node.
1611
- *
1612
1591
  * @param name an Attribute name
1613
1592
  * @param element a DOM node
1614
- * @param attr the exact Attr node to remove, when the caller has it
1615
1593
  */
1616
- const _removeAttribute = function _removeAttribute(name, element, attr) {
1617
- if (!attr) try {
1618
- attr = element.getAttributeNode(name);
1619
- } catch (_) {
1620
- attr = null;
1621
- }
1622
- arrayPush(DOMPurify.removed, {
1623
- attribute: attr || null,
1624
- from: element
1625
- });
1594
+ const _removeAttribute = function _removeAttribute(name, element) {
1626
1595
  try {
1627
- if (attr) element.removeAttributeNode(attr);
1628
- else element.removeAttribute(name);
1596
+ arrayPush(DOMPurify.removed, {
1597
+ attribute: element.getAttributeNode(name),
1598
+ from: element
1599
+ });
1629
1600
  } catch (_) {
1630
- try {
1631
- element.removeAttribute(name);
1632
- } catch (_) {}
1601
+ arrayPush(DOMPurify.removed, {
1602
+ attribute: null,
1603
+ from: element
1604
+ });
1633
1605
  }
1606
+ element.removeAttribute(name);
1634
1607
  if (name === "is") if (RETURN_DOM || RETURN_DOM_FRAGMENT) try {
1635
1608
  _forceRemove(element);
1636
1609
  } catch (_) {}
@@ -1655,7 +1628,9 @@ function createDOMPurify() {
1655
1628
  const attribute = attributes[i];
1656
1629
  const name = attribute && attribute.name;
1657
1630
  if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) continue;
1658
- _stripAttributeNode(element, attribute, name);
1631
+ try {
1632
+ element.removeAttribute(name);
1633
+ } catch (_) {}
1659
1634
  }
1660
1635
  };
1661
1636
  /**
@@ -1684,7 +1659,7 @@ function createDOMPurify() {
1684
1659
  const stack = [root];
1685
1660
  while (stack.length > 0) {
1686
1661
  const node = stack.pop();
1687
- if (_readNodeType(node) === NODE_TYPE.element) _stripDisallowedAttributes(node);
1662
+ if ((getNodeType ? getNodeType(node) : node.nodeType) === NODE_TYPE.element) _stripDisallowedAttributes(node);
1688
1663
  const childNodes = getChildNodes(node);
1689
1664
  if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push(childNodes[i]);
1690
1665
  }
@@ -1724,28 +1699,12 @@ function createDOMPurify() {
1724
1699
  *
1725
1700
  * @param root the in-place root to sweep
1726
1701
  */
1727
- /**
1728
- * Central policy for declarative-partial-updates patch-linkage attributes,
1729
- * shared by the _neutralizePatchLinkage pre-pass and _isValidAttribute so
1730
- * the two sites cannot drift: `patchsrc` always links, `for` links
1731
- * everywhere except on <label>/<output>, and the whole policy is gated on
1732
- * SAFE_FOR_XML (see the rationale block in _isValidAttribute).
1733
- *
1734
- * @param lcName the transformCaseFunc'd attribute name
1735
- * @param lcTag the transformCaseFunc'd tag name of the carrying element
1736
- * @return true if the attribute is patch linkage and must be dropped
1737
- */
1738
- const _isPatchLinkageAttribute = function _isPatchLinkageAttribute(lcName, lcTag) {
1739
- if (!SAFE_FOR_XML) return false;
1740
- if (lcName === "patchsrc") return true;
1741
- return lcName === "for" && lcTag !== "label" && lcTag !== "output";
1742
- };
1743
1702
  const _neutralizePatchLinkage = function _neutralizePatchLinkage(root) {
1744
1703
  if (!SAFE_FOR_XML) return;
1745
1704
  const stack = [root];
1746
1705
  while (stack.length > 0) {
1747
1706
  const node = stack.pop();
1748
- const nodeType = _readNodeType(node);
1707
+ const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
1749
1708
  if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) {
1750
1709
  try {
1751
1710
  remove(node);
@@ -1754,10 +1713,10 @@ function createDOMPurify() {
1754
1713
  }
1755
1714
  if (nodeType === NODE_TYPE.element) {
1756
1715
  const element = node;
1757
- const lcTag = transformCaseFunc(_readNodeName(node));
1716
+ const lcTag = transformCaseFunc(getNodeName ? getNodeName(node) : node.nodeName);
1758
1717
  try {
1759
1718
  if (element.hasAttribute && element.hasAttribute("patchsrc")) element.removeAttribute("patchsrc");
1760
- if (element.hasAttribute && element.hasAttribute("for") && _isPatchLinkageAttribute("for", lcTag)) element.removeAttribute("for");
1719
+ if (element.hasAttribute && element.hasAttribute("for") && lcTag !== "label" && lcTag !== "output") element.removeAttribute("for");
1761
1720
  } catch (_) {}
1762
1721
  }
1763
1722
  const childNodes = getChildNodes(node);
@@ -1926,32 +1885,12 @@ function createDOMPurify() {
1926
1885
  */
1927
1886
  const _isUnsafeNode = function _isUnsafeNode(currentNode, tagName) {
1928
1887
  if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) return true;
1929
- 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;
1888
+ if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) return true;
1930
1889
  if (currentNode.nodeType === NODE_TYPE.processingInstruction) return true;
1931
1890
  if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) return true;
1932
1891
  return false;
1933
1892
  };
1934
1893
  /**
1935
- * Evaluate a CUSTOM_ELEMENT_HANDLING check (a RegExp or a predicate
1936
- * function, per the validation in _parseConfig) against a name.
1937
- * Additional arguments are forwarded to predicate functions - the
1938
- * attributeNameCheck predicate receives the tag name as its second
1939
- * argument. A null/absent check never matches.
1940
- *
1941
- * @param check the configured tagNameCheck / attributeNameCheck value
1942
- * @param name the name to test
1943
- * @param args extra arguments forwarded to a predicate function
1944
- * @return true if the check matches the name
1945
- */
1946
- const _matchesNameCheck = function _matchesNameCheck(check, name) {
1947
- if (check instanceof RegExp) return regExpTest(check, name);
1948
- if (check instanceof Function) {
1949
- for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) args[_key - 2] = arguments[_key];
1950
- return Boolean(check(name, ...args));
1951
- }
1952
- return false;
1953
- };
1954
- /**
1955
1894
  * Handle a node whose tag is forbidden or not allowlisted: keep
1956
1895
  * allowed custom elements (false return exits _sanitizeElements
1957
1896
  * early - the namespace and fallback-tag removal checks are
@@ -1969,7 +1908,10 @@ function createDOMPurify() {
1969
1908
  * @return true if the node was removed, false if kept
1970
1909
  */
1971
1910
  const _sanitizeDisallowedNode = function _sanitizeDisallowedNode(currentNode, tagName, root) {
1972
- if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName) && _matchesNameCheck(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
1911
+ if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
1912
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
1913
+ if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
1914
+ }
1973
1915
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
1974
1916
  const parentNode = getParentNode(currentNode);
1975
1917
  const childNodes = getChildNodes(currentNode);
@@ -2003,42 +1945,6 @@ function createDOMPurify() {
2003
1945
  return set === defaultSet || set === setConfigSet ? clone(set) : set;
2004
1946
  };
2005
1947
  /**
2006
- * Shared guard for a node that a hook has detached from the walk tree,
2007
- * used after each element-hook site in _sanitizeElements. Detaching is a
2008
- * long-standing user pattern (issue #469; draw.io-style foreignObject
2009
- * filtering). Per the cached, unclobberable parentNode getter the node is
2010
- * genuinely out of the tree, so it can reach neither the serialized
2011
- * output nor an IN_PLACE live tree; treat it as removed and stop
2012
- * processing it. Without this guard, the unsafe-node / namespace checks
2013
- * would call _forceRemove on a parentless node and hit the REPORT-3
2014
- * fail-closed throw — which exists for nodes DOMPurify wants gone but
2015
- * *cannot* detach (clobbered / parentless roots), the opposite of a node
2016
- * that is already safely gone. The walk root is exempt: a detached
2017
- * IN_PLACE root is legitimate input and must still be fully sanitized,
2018
- * and a kill-decision on it must keep hitting the REPORT-3 throw.
2019
- *
2020
- * Nodes detached by hooks stay the hook's responsibility for placement:
2021
- * they are not recorded in DOMPurify.removed, so the post-walk IN_PLACE
2022
- * pass (which iterates DOMPurify.removed) does not reach them. But a
2023
- * hook-detached subtree can still hold a queued resource-event handler -
2024
- * e.g. an <img onload> that began loading when the caller built the live
2025
- * tree - which fires in page scope after sanitize returns even though the
2026
- * handler never reached the returned tree. That is the audit-5 F1 hazard,
2027
- * and the documented node.remove() hook pattern walks straight into it.
2028
- * So on the IN_PLACE path we neutralize the detached subtree inline,
2029
- * stripping its non-allow-listed attributes before returning, exactly as
2030
- * the post-walk pass does for _forceRemove'd subtrees.
2031
- *
2032
- * @param currentNode the node a hook may have detached
2033
- * @param root the current walk root
2034
- * @return true if the node is detached and now handled, false otherwise
2035
- */
2036
- const _handleHookDetachedNode = function _handleHookDetachedNode(currentNode, root) {
2037
- if (currentNode === root || getParentNode(currentNode) !== null) return false;
2038
- if (IN_PLACE) _neutralizeSubtree(currentNode);
2039
- return true;
2040
- };
2041
- /**
2042
1948
  * _sanitizeElements
2043
1949
  *
2044
1950
  * @protect nodeName
@@ -2049,18 +1955,24 @@ function createDOMPurify() {
2049
1955
  */
2050
1956
  const _sanitizeElements = function _sanitizeElements(currentNode, root) {
2051
1957
  _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
2052
- if (_handleHookDetachedNode(currentNode, root)) return true;
1958
+ if (currentNode !== root && getParentNode(currentNode) === null) {
1959
+ if (IN_PLACE) _neutralizeSubtree(currentNode);
1960
+ return true;
1961
+ }
2053
1962
  if (_isClobbered(currentNode)) {
2054
1963
  _forceRemove(currentNode);
2055
1964
  return true;
2056
1965
  }
2057
- const tagName = transformCaseFunc(_readNodeName(currentNode));
1966
+ const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
2058
1967
  ALLOWED_TAGS = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS);
2059
1968
  _executeHooks(hooks.uponSanitizeElement, currentNode, {
2060
1969
  tagName,
2061
1970
  allowedTags: ALLOWED_TAGS
2062
1971
  });
2063
- if (_handleHookDetachedNode(currentNode, root)) return true;
1972
+ if (currentNode !== root && getParentNode(currentNode) === null) {
1973
+ if (IN_PLACE) _neutralizeSubtree(currentNode);
1974
+ return true;
1975
+ }
2064
1976
  if (_isUnsafeNode(currentNode, tagName)) {
2065
1977
  _forceRemove(currentNode);
2066
1978
  return true;
@@ -2070,7 +1982,7 @@ function createDOMPurify() {
2070
1982
  if (removed === false) _executeHooks(hooks.afterSanitizeElements, currentNode, null);
2071
1983
  return removed;
2072
1984
  }
2073
- if (_readNodeType(currentNode) === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
1985
+ if ((getNodeType ? getNodeType(currentNode) : currentNode.nodeType) === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
2074
1986
  _forceRemove(currentNode);
2075
1987
  return true;
2076
1988
  }
@@ -2098,17 +2010,20 @@ function createDOMPurify() {
2098
2010
  */
2099
2011
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
2100
2012
  if (FORBID_ATTR[lcName]) return false;
2101
- if (_isPatchLinkageAttribute(lcName, lcTag)) return false;
2013
+ if (SAFE_FOR_XML && lcName === "patchsrc") return false;
2014
+ if (SAFE_FOR_XML && lcName === "for" && lcTag !== "label" && lcTag !== "output") return false;
2102
2015
  if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document || value in formElement)) return false;
2103
2016
  const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
2104
- if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) return true;
2105
- if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) return true;
2106
- 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);
2107
- if (URI_SAFE_ATTRIBUTES[lcName]) return true;
2108
- if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true;
2109
- if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) return true;
2110
- if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) return true;
2111
- return !value;
2017
+ if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName));
2018
+ else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
2019
+ else if (!nameIsPermitted) if (_isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) || lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));
2020
+ else return false;
2021
+ else if (URI_SAFE_ATTRIBUTES[lcName]);
2022
+ else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, "")));
2023
+ else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]);
2024
+ else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, "")));
2025
+ else if (value) return false;
2026
+ return true;
2112
2027
  };
2113
2028
  const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, [
2114
2029
  "annotation-xml",
@@ -2210,29 +2125,29 @@ function createDOMPurify() {
2210
2125
  _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
2211
2126
  value = hookEvent.attrValue;
2212
2127
  if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
2213
- _removeAttribute(name, currentNode, attr);
2128
+ _removeAttribute(name, currentNode);
2214
2129
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
2215
2130
  }
2216
2131
  if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
2217
- _removeAttribute(name, currentNode, attr);
2132
+ _removeAttribute(name, currentNode);
2218
2133
  continue;
2219
2134
  }
2220
2135
  if (lcName === "attributename" && stringMatch(value, "href")) {
2221
- _removeAttribute(name, currentNode, attr);
2136
+ _removeAttribute(name, currentNode);
2222
2137
  continue;
2223
2138
  }
2224
2139
  if (hookEvent.forceKeepAttr) continue;
2225
2140
  if (!hookEvent.keepAttr) {
2226
- _removeAttribute(name, currentNode, attr);
2141
+ _removeAttribute(name, currentNode);
2227
2142
  continue;
2228
2143
  }
2229
2144
  if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
2230
- _removeAttribute(name, currentNode, attr);
2145
+ _removeAttribute(name, currentNode);
2231
2146
  continue;
2232
2147
  }
2233
2148
  if (SAFE_FOR_TEMPLATES) value = _stripTemplateExpressions(value);
2234
2149
  if (!_isValidAttribute(lcTag, lcName, value)) {
2235
- _removeAttribute(name, currentNode, attr);
2150
+ _removeAttribute(name, currentNode);
2236
2151
  continue;
2237
2152
  }
2238
2153
  value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
@@ -2254,7 +2169,7 @@ function createDOMPurify() {
2254
2169
  _sanitizeElements(shadowNode, fragment);
2255
2170
  _sanitizeAttributes(shadowNode);
2256
2171
  if (_isDocumentFragment(shadowNode.content)) _sanitizeShadowDOM2(shadowNode.content);
2257
- if (_readNodeType(shadowNode) === NODE_TYPE.element) {
2172
+ if ((getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType) === NODE_TYPE.element) {
2258
2173
  const innerSr = getShadowRoot(shadowNode);
2259
2174
  if (_isDocumentFragment(innerSr)) {
2260
2175
  _sanitizeAttachedShadowRoots(innerSr);
@@ -2295,7 +2210,7 @@ function createDOMPurify() {
2295
2210
  continue;
2296
2211
  }
2297
2212
  const node = item.node;
2298
- const isElement = _readNodeType(node) === NODE_TYPE.element;
2213
+ const isElement = (getNodeType ? getNodeType(node) : node.nodeType) === NODE_TYPE.element;
2299
2214
  const childNodes = getChildNodes(node);
2300
2215
  if (childNodes) for (let i = childNodes.length - 1; i >= 0; --i) stack.push({
2301
2216
  node: childNodes[i],
@@ -2346,7 +2261,7 @@ function createDOMPurify() {
2346
2261
  const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
2347
2262
  if (inPlace) {
2348
2263
  _neutralizePatchLinkage(dirty);
2349
- const nn = _readNodeName(dirty);
2264
+ const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
2350
2265
  if (typeof nn === "string") {
2351
2266
  const tagName = transformCaseFunc(nn);
2352
2267
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
@@ -2497,6 +2412,6 @@ function _resetSanitizeForTests() {
2497
2412
  hookInstalled = false;
2498
2413
  }
2499
2414
  //#endregion
2500
- export { _resetSanitizeForTests, buildMarkdownDocView, formatScalarField, nextFileVersion, sanitizeMarkdownHtml, useClipboardCopy, useFileVersion, useFileWatch, useMarkdownDoc };
2415
+ export { IconGlyph, _resetSanitizeForTests, buildMarkdownDocView, formatScalarField, nextFileVersion, sanitizeMarkdownHtml, useClipboardCopy, useFileVersion, useFileWatch, useMarkdownDoc };
2501
2416
 
2502
2417
  //# sourceMappingURL=index.js.map