@ai-matrx/rich-content 0.0.0-stage → 0.2.2

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 (247) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/LICENSE +21 -0
  3. package/README.md +61 -2
  4. package/dist/display/blocks/csv/CsvBlock.d.ts +10 -0
  5. package/dist/display/blocks/csv/CsvBlock.js +245 -0
  6. package/dist/display/blocks/table/parseMarkdownTable.d.ts +20 -0
  7. package/dist/display/blocks/table/parseMarkdownTable.js +35 -0
  8. package/dist/display/chat-markdown/citations/remarkMatrxCite.d.ts +33 -0
  9. package/dist/display/chat-markdown/citations/remarkMatrxCite.js +71 -0
  10. package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.d.ts +29 -0
  11. package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.js +71 -0
  12. package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.d.ts +55 -0
  13. package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.js +108 -0
  14. package/dist/display/chat-markdown/rehypeSafeRawHtml.d.ts +59 -0
  15. package/dist/display/chat-markdown/rehypeSafeRawHtml.js +140 -0
  16. package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.d.ts +14 -0
  17. package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.js +171 -0
  18. package/dist/display/markdown-classification/processors/types.d.ts +120 -0
  19. package/dist/display/markdown-classification/processors/types.js +10 -0
  20. package/dist/display/markdown-classification/processors/utils/client-blocks.d.ts +169 -0
  21. package/dist/display/markdown-classification/processors/utils/client-blocks.js +0 -0
  22. package/dist/display/markdown-classification/processors/utils/content-splitter-core.d.ts +223 -0
  23. package/dist/display/markdown-classification/processors/utils/content-splitter-core.js +1791 -0
  24. package/dist/display/markdown-classification/processors/utils/content-splitter-v2.d.ts +15 -0
  25. package/dist/display/markdown-classification/processors/utils/content-splitter-v2.js +19 -0
  26. package/dist/display/markdown-classification/processors/utils/expand-text-blocks.d.ts +9 -0
  27. package/dist/display/markdown-classification/processors/utils/expand-text-blocks.js +36 -0
  28. package/dist/display/markdown-classification/processors/utils/gfm-table-lines.d.ts +5 -0
  29. package/dist/display/markdown-classification/processors/utils/gfm-table-lines.js +40 -0
  30. package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.d.ts +16 -0
  31. package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.js +385 -0
  32. package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.d.ts +43 -0
  33. package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.js +33 -0
  34. package/dist/display/markdown-classification/processors/utils/table-data-parser.d.ts +9 -0
  35. package/dist/display/markdown-classification/processors/utils/table-data-parser.js +30 -0
  36. package/dist/display/markdown-classification/processors/utils/thinking-parser.d.ts +7 -0
  37. package/dist/display/markdown-classification/processors/utils/thinking-parser.js +70 -0
  38. package/dist/display/render-block.d.ts +23 -0
  39. package/dist/display/render-block.js +0 -0
  40. package/dist/display/themes.d.ts +1023 -0
  41. package/dist/display/themes.js +1105 -0
  42. package/dist/display/types.d.ts +32 -0
  43. package/dist/display/types.js +0 -0
  44. package/dist/host/ContentIrHostBoundary.d.ts +8 -0
  45. package/dist/host/ContentIrHostBoundary.js +15 -0
  46. package/dist/host/ErrorActions.d.ts +4 -0
  47. package/dist/host/ErrorActions.js +11 -0
  48. package/dist/host/NestedContent.d.ts +3 -0
  49. package/dist/host/NestedContent.js +12 -0
  50. package/dist/host/ResourcePeek.d.ts +6 -0
  51. package/dist/host/ResourcePeek.js +14 -0
  52. package/dist/host/component-registry.d.ts +2 -0
  53. package/dist/host/component-registry.js +25 -0
  54. package/dist/host/diagnostics.d.ts +2 -0
  55. package/dist/host/diagnostics.js +15 -0
  56. package/dist/host/index.d.ts +3 -0
  57. package/dist/host/index.js +18 -0
  58. package/dist/host/kind-incident.d.ts +3 -0
  59. package/dist/host/kind-incident.js +12 -0
  60. package/dist/host/kind-registry.d.ts +2 -0
  61. package/dist/host/kind-registry.js +35 -0
  62. package/dist/host/people.d.ts +3 -0
  63. package/dist/host/people.js +12 -0
  64. package/dist/host/registry.d.ts +27 -0
  65. package/dist/host/registry.js +55 -0
  66. package/dist/host/splitter-envelopes.d.ts +2 -0
  67. package/dist/host/splitter-envelopes.js +7 -0
  68. package/dist/host/tables.d.ts +6 -0
  69. package/dist/host/tables.js +8 -0
  70. package/dist/host/toast.d.ts +2 -0
  71. package/dist/host/toast.js +57 -0
  72. package/dist/host/types.d.ts +157 -0
  73. package/dist/host/types.js +0 -0
  74. package/dist/host/wikilinks.d.ts +15 -0
  75. package/dist/host/wikilinks.js +23 -0
  76. package/dist/kinds/host/route-env.d.ts +33 -0
  77. package/dist/kinds/host/route-env.js +16 -0
  78. package/dist/kinds/react/KindEscapedNotice.d.ts +14 -0
  79. package/dist/kinds/react/KindEscapedNotice.js +72 -0
  80. package/dist/kinds/react/ProvisionalKindBoundary.d.ts +19 -0
  81. package/dist/kinds/react/ProvisionalKindBoundary.js +17 -0
  82. package/dist/kinds/react/ensure-kind-renderable.d.ts +14 -0
  83. package/dist/kinds/react/ensure-kind-renderable.js +45 -0
  84. package/dist/kinds/react/kind-problems.d.ts +62 -0
  85. package/dist/kinds/react/kind-problems.js +134 -0
  86. package/dist/kinds/react/kind-route.d.ts +23 -0
  87. package/dist/kinds/react/kind-route.js +24 -0
  88. package/dist/kinds/react/loading/infer-loading-slug.d.ts +58 -0
  89. package/dist/kinds/react/loading/infer-loading-slug.js +100 -0
  90. package/dist/kinds/react/loading/kind-loading-components.d.ts +48 -0
  91. package/dist/kinds/react/loading/kind-loading-components.js +447 -0
  92. package/dist/kinds/react/loading/kind-loading-registry.d.ts +21 -0
  93. package/dist/kinds/react/loading/kind-loading-registry.js +62 -0
  94. package/dist/kinds/react/loading/kind-loading-slugs.d.ts +18 -0
  95. package/dist/kinds/react/loading/kind-loading-slugs.js +34 -0
  96. package/dist/kinds/react/loading/kind-loading.types.d.ts +79 -0
  97. package/dist/kinds/react/loading/kind-loading.types.js +31 -0
  98. package/dist/kinds/react/loading/resolve-loading-slug.d.ts +29 -0
  99. package/dist/kinds/react/loading/resolve-loading-slug.js +51 -0
  100. package/dist/kinds/react/partial-kind-route.d.ts +32 -0
  101. package/dist/kinds/react/partial-kind-route.js +27 -0
  102. package/dist/kinds/react/registry-versioned.d.ts +54 -0
  103. package/dist/kinds/react/registry-versioned.js +18 -0
  104. package/dist/kinds/react/route-at-version.d.ts +38 -0
  105. package/dist/kinds/react/route-at-version.js +78 -0
  106. package/dist/kinds/react/slot/KindSlot.d.ts +87 -0
  107. package/dist/kinds/react/slot/KindSlot.js +65 -0
  108. package/dist/kinds/react/use-registry-repaint.d.ts +6 -0
  109. package/dist/kinds/react/use-registry-repaint.js +36 -0
  110. package/dist/kinds/react/useIrNode.d.ts +9 -0
  111. package/dist/kinds/react/useIrNode.js +46 -0
  112. package/dist/kinds/react/useLiveJsonRegion.d.ts +15 -0
  113. package/dist/kinds/react/useLiveJsonRegion.js +84 -0
  114. package/dist/kinds/redux/render-block-envelope.d.ts +14 -0
  115. package/dist/kinds/redux/render-block-envelope.js +26 -0
  116. package/dist/kinds/registry/kind-correctors.d.ts +63 -0
  117. package/dist/kinds/registry/kind-correctors.js +94 -0
  118. package/dist/kinds/registry/legacy-quiz-envelope.d.ts +1 -0
  119. package/dist/kinds/registry/legacy-quiz-envelope.js +1 -0
  120. package/dist/kinds/registry/region-envelope-memo.d.ts +45 -0
  121. package/dist/kinds/registry/region-envelope-memo.js +94 -0
  122. package/dist/kinds/registry/registry-debug.d.ts +38 -0
  123. package/dist/kinds/registry/registry-debug.js +39 -0
  124. package/dist/markdown-core/MarkdownCore.d.ts +6 -0
  125. package/dist/markdown-core/MarkdownCore.js +32 -0
  126. package/dist/markdown-core/MarkdownCoreImpl.d.ts +3 -0
  127. package/dist/markdown-core/MarkdownCoreImpl.js +27 -0
  128. package/dist/markdown-core/MarkdownCoreServer.d.ts +4 -0
  129. package/dist/markdown-core/MarkdownCoreServer.js +26 -0
  130. package/dist/markdown-core/heading-anchors-context.d.ts +2 -0
  131. package/dist/markdown-core/heading-anchors-context.js +11 -0
  132. package/dist/markdown-core/heading-anchors-props.d.ts +2 -0
  133. package/dist/markdown-core/heading-anchors-props.js +6 -0
  134. package/dist/markdown-core/markdown-core-html.d.ts +3 -0
  135. package/dist/markdown-core/markdown-core-html.js +33 -0
  136. package/dist/markdown-core/markdown-core-presets.d.ts +22 -0
  137. package/dist/markdown-core/markdown-core-presets.js +118 -0
  138. package/dist/markdown-core/markdown-core-types.d.ts +43 -0
  139. package/dist/markdown-core/markdown-core-types.js +0 -0
  140. package/dist/markdown-core/math/vendor/micromark-math-math-flow.d.ts +15 -0
  141. package/dist/markdown-core/math/vendor/micromark-math-math-flow.js +143 -0
  142. package/dist/markdown-core/math/vendor/micromark-math-math-text.d.ts +24 -0
  143. package/dist/markdown-core/math/vendor/micromark-math-math-text.js +127 -0
  144. package/dist/markdown-core/math/vendor/micromark-math-syntax.d.ts +30 -0
  145. package/dist/markdown-core/math/vendor/micromark-math-syntax.js +15 -0
  146. package/dist/markdown-core/math/vendor/rehype-katex.d.ts +15 -0
  147. package/dist/markdown-core/math/vendor/rehype-katex.js +83 -0
  148. package/dist/markdown-core/math/vendor/remark-math.d.ts +9 -0
  149. package/dist/markdown-core/math/vendor/remark-math.js +20 -0
  150. package/dist/markdown-core/math-normalizer.d.ts +57 -0
  151. package/dist/markdown-core/math-normalizer.js +315 -0
  152. package/dist/markdown-core/plain-title.d.ts +2 -0
  153. package/dist/markdown-core/plain-title.js +1 -0
  154. package/dist/markdown-core/stream-heal.d.ts +2 -0
  155. package/dist/markdown-core/stream-heal.js +184 -0
  156. package/dist/markdown-core/streaming-context.d.ts +2 -0
  157. package/dist/markdown-core/streaming-context.js +11 -0
  158. package/dist/markdown-core/syntax/callout-types.d.ts +9 -0
  159. package/dist/markdown-core/syntax/callout-types.js +101 -0
  160. package/dist/markdown-core/syntax/containers.d.ts +17 -0
  161. package/dist/markdown-core/syntax/containers.js +353 -0
  162. package/dist/markdown-core/syntax/document-numbering.d.ts +52 -0
  163. package/dist/markdown-core/syntax/document-numbering.js +184 -0
  164. package/dist/markdown-core/syntax/elements/CalloutIcon.d.ts +3 -0
  165. package/dist/markdown-core/syntax/elements/CalloutIcon.js +41 -0
  166. package/dist/markdown-core/syntax/elements/CrossRef.d.ts +12 -0
  167. package/dist/markdown-core/syntax/elements/CrossRef.js +57 -0
  168. package/dist/markdown-core/syntax/elements/CsvFence.d.ts +4 -0
  169. package/dist/markdown-core/syntax/elements/CsvFence.js +18 -0
  170. package/dist/markdown-core/syntax/elements/DetailsElements.d.ts +12 -0
  171. package/dist/markdown-core/syntax/elements/DetailsElements.js +38 -0
  172. package/dist/markdown-core/syntax/elements/DocumentNumbering.d.ts +20 -0
  173. package/dist/markdown-core/syntax/elements/DocumentNumbering.js +37 -0
  174. package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.d.ts +4 -0
  175. package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.js +46 -0
  176. package/dist/markdown-core/syntax/elements/InDocAnchor.d.ts +11 -0
  177. package/dist/markdown-core/syntax/elements/InDocAnchor.js +87 -0
  178. package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.d.ts +24 -0
  179. package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.js +28 -0
  180. package/dist/markdown-core/syntax/elements/MatrxTabs.d.ts +10 -0
  181. package/dist/markdown-core/syntax/elements/MatrxTabs.js +59 -0
  182. package/dist/markdown-core/syntax/elements/MentionChip.d.ts +7 -0
  183. package/dist/markdown-core/syntax/elements/MentionChip.js +69 -0
  184. package/dist/markdown-core/syntax/elements/NestedBody.d.ts +3 -0
  185. package/dist/markdown-core/syntax/elements/NestedBody.js +13 -0
  186. package/dist/markdown-core/syntax/elements/TableOfContents.d.ts +5 -0
  187. package/dist/markdown-core/syntax/elements/TableOfContents.js +44 -0
  188. package/dist/markdown-core/syntax/elements/TaskCheckbox.d.ts +7 -0
  189. package/dist/markdown-core/syntax/elements/TaskCheckbox.js +63 -0
  190. package/dist/markdown-core/syntax/elements/WikiEmbed.d.ts +7 -0
  191. package/dist/markdown-core/syntax/elements/WikiEmbed.js +68 -0
  192. package/dist/markdown-core/syntax/elements/WikiLink.d.ts +10 -0
  193. package/dist/markdown-core/syntax/elements/WikiLink.js +114 -0
  194. package/dist/markdown-core/syntax/elements/core-syntax-elements.d.ts +22 -0
  195. package/dist/markdown-core/syntax/elements/core-syntax-elements.js +70 -0
  196. package/dist/markdown-core/syntax/elements/find-in-document.d.ts +3 -0
  197. package/dist/markdown-core/syntax/elements/find-in-document.js +20 -0
  198. package/dist/markdown-core/syntax/elements/wiki-target.d.ts +5 -0
  199. package/dist/markdown-core/syntax/elements/wiki-target.js +8 -0
  200. package/dist/markdown-core/syntax/frontmatter.d.ts +26 -0
  201. package/dist/markdown-core/syntax/frontmatter.js +72 -0
  202. package/dist/markdown-core/syntax/gfm-cell-pipes.d.ts +11 -0
  203. package/dist/markdown-core/syntax/gfm-cell-pipes.js +4 -0
  204. package/dist/markdown-core/syntax/inline-syntax.d.ts +26 -0
  205. package/dist/markdown-core/syntax/inline-syntax.js +163 -0
  206. package/dist/markdown-core/syntax/linear-scan.d.ts +46 -0
  207. package/dist/markdown-core/syntax/linear-scan.js +129 -0
  208. package/dist/markdown-core/syntax/mdast-helpers.d.ts +48 -0
  209. package/dist/markdown-core/syntax/mdast-helpers.js +48 -0
  210. package/dist/markdown-core/syntax/mentions.d.ts +2 -0
  211. package/dist/markdown-core/syntax/mentions.js +42 -0
  212. package/dist/markdown-core/syntax/names.d.ts +6 -0
  213. package/dist/markdown-core/syntax/names.js +18 -0
  214. package/dist/markdown-core/syntax/prepare-syntax-source.d.ts +1 -0
  215. package/dist/markdown-core/syntax/prepare-syntax-source.js +78 -0
  216. package/dist/markdown-core/syntax/rehype-matrx-syntax.d.ts +9 -0
  217. package/dist/markdown-core/syntax/rehype-matrx-syntax.js +180 -0
  218. package/dist/markdown-core/syntax/remark-inline-only.d.ts +23 -0
  219. package/dist/markdown-core/syntax/remark-inline-only.js +25 -0
  220. package/dist/markdown-core/syntax/remark-matrx-syntax.d.ts +7 -0
  221. package/dist/markdown-core/syntax/remark-matrx-syntax.js +351 -0
  222. package/dist/markdown-core/syntax/remark-table-code-pipes.d.ts +7 -0
  223. package/dist/markdown-core/syntax/remark-table-code-pipes.js +23 -0
  224. package/dist/markdown-core/syntax/stream-heal-syntax.d.ts +2 -0
  225. package/dist/markdown-core/syntax/stream-heal-syntax.js +108 -0
  226. package/dist/markdown-core/syntax/task-source.d.ts +10 -0
  227. package/dist/markdown-core/syntax/task-source.js +34 -0
  228. package/dist/markdown-core/syntax/useDocumentProperties.d.ts +3 -0
  229. package/dist/markdown-core/syntax/useDocumentProperties.js +8 -0
  230. package/dist/styles.css +0 -0
  231. package/dist/utils/addressWithoutNavigating.d.ts +68 -0
  232. package/dist/utils/addressWithoutNavigating.js +60 -0
  233. package/dist/utils/client-lazy.d.ts +13 -0
  234. package/dist/utils/client-lazy.js +24 -0
  235. package/dist/utils/decision-options.d.ts +21 -0
  236. package/dist/utils/decision-options.js +32 -0
  237. package/dist/utils/gfm-lexer.d.ts +5 -0
  238. package/dist/utils/gfm-lexer.js +10 -0
  239. package/dist/utils/json.d.ts +63 -0
  240. package/dist/utils/json.js +22 -0
  241. package/dist/utils/plain-title.d.ts +25 -0
  242. package/dist/utils/plain-title.js +51 -0
  243. package/dist/utils/table-source.d.ts +62 -0
  244. package/dist/utils/table-source.js +191 -0
  245. package/dist/utils/youtube.d.ts +52 -0
  246. package/dist/utils/youtube.js +137 -0
  247. package/package.json +134 -4
@@ -0,0 +1,59 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Children, isValidElement, useId, useState } from "react";
4
+ import { cn } from "@ai-matrx/design-system";
5
+ function parseLabels(raw) {
6
+ if (typeof raw !== "string") return [];
7
+ try {
8
+ const parsed = JSON.parse(raw);
9
+ return Array.isArray(parsed) ? parsed.map(String) : [];
10
+ } catch {
11
+ return [];
12
+ }
13
+ }
14
+ function MatrxTabs(props) {
15
+ const panels = Children.toArray(props.children).filter(isValidElement);
16
+ const labels = parseLabels(props["data-labels"]);
17
+ const [active, setActive] = useState(0);
18
+ const base = useId();
19
+ if (panels.length === 0) return null;
20
+ const current = Math.min(active, panels.length - 1);
21
+ return /* @__PURE__ */ jsxs("div", { id: props.id, className: "matrx-tabs my-3 overflow-hidden rounded-md border border-border", "data-matrx-tabs": "", children: [
22
+ /* @__PURE__ */ jsx("div", { role: "tablist", className: "flex gap-1 overflow-x-auto border-b border-border bg-muted/40 px-1.5 pt-1.5", children: panels.map((_, i) => /* @__PURE__ */ jsx(
23
+ "button",
24
+ {
25
+ type: "button",
26
+ role: "tab",
27
+ id: `${base}-tab-${i}`,
28
+ "aria-selected": i === current,
29
+ "aria-controls": `${base}-panel-${i}`,
30
+ onClick: () => setActive(i),
31
+ className: cn(
32
+ "-mb-px shrink-0 rounded-t-md border border-transparent px-3 py-1.5 text-xs font-medium transition-colors",
33
+ i === current ? "border-border border-b-background bg-background text-foreground" : "text-muted-foreground hover:text-foreground"
34
+ ),
35
+ children: labels[i] || `Tab ${i + 1}`
36
+ },
37
+ i
38
+ )) }),
39
+ panels.map((panel, i) => /* @__PURE__ */ jsx(
40
+ "div",
41
+ {
42
+ role: "tabpanel",
43
+ id: `${base}-panel-${i}`,
44
+ "aria-labelledby": `${base}-tab-${i}`,
45
+ hidden: i !== current,
46
+ className: "px-3 py-2 print:block [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
47
+ children: panel
48
+ },
49
+ i
50
+ ))
51
+ ] });
52
+ }
53
+ function MatrxTab(props) {
54
+ return /* @__PURE__ */ jsx("div", { className: "[&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children: props.children });
55
+ }
56
+ export {
57
+ MatrxTab,
58
+ MatrxTabs
59
+ };
@@ -0,0 +1,7 @@
1
+ import { type ReactNode } from "react";
2
+ export declare function MentionChip(props: {
3
+ "data-kind"?: string;
4
+ "data-id"?: string;
5
+ "data-label"?: string;
6
+ children?: ReactNode;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { AtSign, CalendarDays } from "lucide-react";
5
+ import { ResourcePeekHost, hasResourcePeek } from "../../../host/ResourcePeek.js";
6
+ import { resolveVisiblePerson } from "../../../host/people.js";
7
+ function MentionChip(props) {
8
+ const kind = props["data-kind"];
9
+ const id = String(props["data-id"] ?? "");
10
+ const label = String(props["data-label"] ?? "");
11
+ const [person, setPerson] = useState(null);
12
+ const [peekOpen, setPeekOpen] = useState(false);
13
+ const key = id;
14
+ useEffect(() => {
15
+ if (kind !== "person") return;
16
+ let live = true;
17
+ resolveVisiblePerson(id).then((value) => {
18
+ if (live) setPerson({ key, value });
19
+ }).catch(() => {
20
+ if (live) setPerson({ key, value: null });
21
+ });
22
+ return () => {
23
+ live = false;
24
+ };
25
+ }, [kind, id, key]);
26
+ if (kind === "date") {
27
+ return /* @__PURE__ */ jsxs("time", { dateTime: id, "data-mention": "date", className: "mx-0.5 inline-flex items-center gap-0.5 rounded bg-muted px-1 text-foreground", children: [
28
+ /* @__PURE__ */ jsx(CalendarDays, { className: "h-3 w-3", "aria-hidden": true }),
29
+ label
30
+ ] });
31
+ }
32
+ const settled = person && person.key === key ? person.value : void 0;
33
+ if (settled === void 0) {
34
+ return /* @__PURE__ */ jsxs("span", { "data-mention": "resolving", children: [
35
+ "@",
36
+ label
37
+ ] });
38
+ }
39
+ if (!settled) {
40
+ return /* @__PURE__ */ jsxs("span", { "data-mention": "unresolved", title: "Not someone you share an organization with", children: [
41
+ "@",
42
+ label
43
+ ] });
44
+ }
45
+ const chip = /* @__PURE__ */ jsxs(Fragment, { children: [
46
+ /* @__PURE__ */ jsx(AtSign, { className: "h-3 w-3", "aria-hidden": true }),
47
+ settled.name
48
+ ] });
49
+ if (!hasResourcePeek()) {
50
+ return /* @__PURE__ */ jsx("span", { "data-mention": "person", title: `${settled.name}${settled.role ? ` \xB7 ${settled.role}` : ""}`, className: "mx-0.5 inline-flex items-center gap-0.5 rounded bg-primary/10 px-1 align-baseline text-primary-ink", children: chip });
51
+ }
52
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
53
+ /* @__PURE__ */ jsx(
54
+ "button",
55
+ {
56
+ type: "button",
57
+ onClick: () => setPeekOpen(true),
58
+ "data-mention": "person",
59
+ title: `${settled.name}${settled.role ? ` \xB7 ${settled.role}` : ""}`,
60
+ className: "mx-0.5 inline-flex items-center gap-0.5 rounded bg-primary/10 px-1 align-baseline text-primary-ink hover:bg-primary/20",
61
+ children: chip
62
+ }
63
+ ),
64
+ peekOpen ? /* @__PURE__ */ jsx(ResourcePeekHost, { kind: "user", id: settled.userId, onClose: () => setPeekOpen(false) }) : null
65
+ ] });
66
+ }
67
+ export {
68
+ MentionChip
69
+ };
@@ -0,0 +1,3 @@
1
+ export declare function NestedBody(props: {
2
+ "data-source"?: string;
3
+ }): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { lazy, Suspense } from "react";
4
+ const NestedRichContent = lazy(
5
+ () => import("../../../host/NestedContent.js").then((m) => ({ default: m.NestedRichContent }))
6
+ );
7
+ function NestedBody(props) {
8
+ const source = String(props["data-source"] ?? "");
9
+ return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap text-sm", children: source }), children: /* @__PURE__ */ jsx(NestedRichContent, { source }) });
10
+ }
11
+ export {
12
+ NestedBody
13
+ };
@@ -0,0 +1,5 @@
1
+ import { type ReactNode } from "react";
2
+ export declare function TableOfContents(props: {
3
+ children?: ReactNode;
4
+ "data-toc-count"?: number | string;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,44 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import { InDocAnchor } from "./InDocAnchor.js";
5
+ import { documentRootOf } from "./find-in-document.js";
6
+ function readHeadings(root, self) {
7
+ const out = [];
8
+ root.querySelectorAll("h1[id], h2[id], h3[id], h4[id]").forEach((h) => {
9
+ if (h.id === "footnote-label" || h.classList.contains("sr-only") || self.contains(h)) return;
10
+ if (h.closest("[data-wiki-embed]")) return;
11
+ const clone = h.cloneNode(true);
12
+ clone.querySelectorAll("[data-heading-anchor]").forEach((a) => a.remove());
13
+ out.push({ id: h.id, depth: Number(h.tagName.slice(1)), text: (clone.textContent ?? "").trim() });
14
+ });
15
+ return out;
16
+ }
17
+ function TableOfContents(props) {
18
+ const ref = useRef(null);
19
+ const [entries, setEntries] = useState(null);
20
+ useEffect(() => {
21
+ const self = ref.current;
22
+ const root = documentRootOf(self);
23
+ if (!self || !root) return;
24
+ const read = () => {
25
+ const next = readHeadings(root, self);
26
+ setEntries(
27
+ (prev) => prev && prev.length === next.length && prev.every((e, i) => e.id === next[i]?.id && e.text === next[i]?.text) ? prev : next
28
+ );
29
+ };
30
+ read();
31
+ const observer = new MutationObserver(read);
32
+ observer.observe(root, { childList: true, subtree: true });
33
+ return () => observer.disconnect();
34
+ }, []);
35
+ const staticCount = Number(props["data-toc-count"] ?? 0);
36
+ const min = entries && entries.length > 0 ? Math.min(...entries.map((e) => e.depth)) : 1;
37
+ return /* @__PURE__ */ jsxs("nav", { ref, "aria-label": "Contents", "data-matrx-toc": "", "data-content-chrome": "", className: "matrx-toc my-3 rounded-md border border-border bg-muted/30 px-3 py-2 text-sm", children: [
38
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
39
+ entries && entries.length > staticCount ? /* @__PURE__ */ jsx("ol", { className: "space-y-0.5", children: entries.map((e) => /* @__PURE__ */ jsx("li", { style: { paddingLeft: `${(e.depth - min) * 1}rem` }, children: /* @__PURE__ */ jsx(InDocAnchor, { href: `#${e.id}`, className: "text-foreground/80 no-underline hover:text-primary", children: e.text }) }, e.id)) }) : staticCount > 0 ? props.children : /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "This document has no headings yet." })
40
+ ] });
41
+ }
42
+ export {
43
+ TableOfContents
44
+ };
@@ -0,0 +1,7 @@
1
+ interface TaskCheckboxProps {
2
+ checked?: boolean;
3
+ "data-task-index"?: number | string;
4
+ "data-task-text"?: string;
5
+ }
6
+ export declare function TaskCheckbox(props: TaskCheckboxProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,63 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Check } from "lucide-react";
5
+ import { cn } from "@ai-matrx/design-system";
6
+ import { toast } from "../../../host/toast.js";
7
+ import { useMarkdownSourceEdit } from "./MarkdownSourceEdit.js";
8
+ const BOX = "mr-2 inline-flex h-4 w-4 shrink-0 translate-y-[2px] items-center justify-center rounded-[4px] border align-baseline";
9
+ function TaskCheckbox(props) {
10
+ const edit = useMarkdownSourceEdit();
11
+ const [pending, setPending] = useState(false);
12
+ const checked = !!props.checked;
13
+ const index = Number(props["data-task-index"] ?? 0);
14
+ const itemText = String(props["data-task-text"] ?? "");
15
+ const mark = checked ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3", strokeWidth: 3, "aria-hidden": true }) : null;
16
+ const stateClass = checked ? "border-primary bg-primary text-primary-foreground" : "border-muted-foreground/60 bg-background";
17
+ if (!edit) {
18
+ return /* @__PURE__ */ jsx(
19
+ "span",
20
+ {
21
+ role: "img",
22
+ "aria-label": checked ? "Done" : "Not done",
23
+ "data-task-readonly": "",
24
+ className: cn(BOX, stateClass),
25
+ children: mark
26
+ }
27
+ );
28
+ }
29
+ const onToggle = async () => {
30
+ if (pending) return;
31
+ const { toggleTaskInSource } = await import("../task-source.js");
32
+ const next = toggleTaskInSource(edit.source, { text: itemText, index, checked: !checked });
33
+ if (next === null) {
34
+ toast.error("This task could not be found in the saved text, so nothing was changed. Edit the source to update it.");
35
+ return;
36
+ }
37
+ setPending(true);
38
+ try {
39
+ await edit.save(next);
40
+ } catch (err) {
41
+ toast.error(`The task was not saved: ${err instanceof Error ? err.message : String(err)}`);
42
+ } finally {
43
+ setPending(false);
44
+ }
45
+ };
46
+ return /* @__PURE__ */ jsx(
47
+ "button",
48
+ {
49
+ type: "button",
50
+ role: "checkbox",
51
+ "aria-checked": checked,
52
+ "aria-label": checked ? "Mark as not done" : "Mark as done",
53
+ "aria-busy": pending || void 0,
54
+ "data-task-interactive": "",
55
+ onClick: onToggle,
56
+ className: cn(BOX, stateClass, "cursor-pointer transition-colors hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", pending && "opacity-60"),
57
+ children: mark
58
+ }
59
+ );
60
+ }
61
+ export {
62
+ TaskCheckbox
63
+ };
@@ -0,0 +1,7 @@
1
+ import { type ReactNode } from "react";
2
+ export declare function WikiEmbed(props: {
3
+ "data-target"?: string;
4
+ "data-alias"?: string;
5
+ "data-block"?: unknown;
6
+ children?: ReactNode;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,68 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { lazy, Suspense, useEffect, useState } from "react";
4
+ import { FileText } from "lucide-react";
5
+ import { useWikiResolution, WikiLink } from "./WikiLink.js";
6
+ import { loadWikiBody } from "../../../host/wikilinks.js";
7
+ import { ErrorAlchemyMenu } from "../../../host/ErrorActions.js";
8
+ const NestedRichContent = lazy(
9
+ () => import("../../../host/NestedContent.js").then((m) => ({ default: m.NestedRichContent }))
10
+ );
11
+ function useNoteBody(id) {
12
+ const [state, setState] = useState(null);
13
+ useEffect(() => {
14
+ if (!id) return;
15
+ let live = true;
16
+ loadWikiBody("note", id).then((r) => {
17
+ if (live) setState("body" in r ? { id, body: r.body, error: null } : { id, body: null, error: r.error });
18
+ }).catch((err) => {
19
+ if (live) setState({ id, body: null, error: err instanceof Error ? err.message : String(err) });
20
+ });
21
+ return () => {
22
+ live = false;
23
+ };
24
+ }, [id]);
25
+ return state && state.id === id ? { body: state.body, error: state.error } : { body: null, error: null };
26
+ }
27
+ function WikiEmbed(props) {
28
+ const target = String(props["data-target"] ?? "");
29
+ const resolution = useWikiResolution(target);
30
+ const isBlock = props["data-block"] !== void 0 && props["data-block"] !== false;
31
+ const noteId = isBlock && resolution?.status === "found" && resolution.token === "note" ? resolution.id : null;
32
+ const { body, error } = useNoteBody(noteId);
33
+ if (!resolution || resolution.status !== "found") {
34
+ return /* @__PURE__ */ jsx(
35
+ "span",
36
+ {
37
+ className: isBlock ? "my-2 block rounded-md border border-dashed border-border px-3 py-2 text-sm" : "inline-block rounded-md border border-dashed border-border px-1.5",
38
+ "data-wiki-embed": resolution?.status ?? "resolving",
39
+ "data-content-chrome": "",
40
+ children: /* @__PURE__ */ jsx(WikiLink, { ...props })
41
+ }
42
+ );
43
+ }
44
+ return /* @__PURE__ */ jsxs(
45
+ "span",
46
+ {
47
+ "data-wiki-embed": "found",
48
+ "data-content-chrome": "",
49
+ className: isBlock ? "my-3 block overflow-hidden rounded-md border border-border bg-card" : "inline-block overflow-hidden rounded-md border border-border bg-card align-middle",
50
+ children: [
51
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 border-b border-border bg-muted/40 px-3 py-1.5 text-xs", children: [
52
+ /* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground", "aria-hidden": true }),
53
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-medium text-foreground", children: resolution.title }),
54
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: resolution.typeLabel }),
55
+ resolution.href && /* @__PURE__ */ jsx("a", { href: resolution.href, className: "ml-auto shrink-0 text-primary hover:underline", children: "Open" })
56
+ ] }),
57
+ noteId && /* @__PURE__ */ jsx("span", { className: "block px-3 py-2", children: error ? /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
58
+ error,
59
+ " ",
60
+ /* @__PURE__ */ jsx(ErrorAlchemyMenu, { error })
61
+ ] }) : body === null ? /* @__PURE__ */ jsx("span", { className: "block h-10 animate-pulse rounded bg-muted/60", "aria-label": "Loading the embedded note" }) : body.trim() ? /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("span", { className: "block whitespace-pre-wrap text-sm", children: body }), children: /* @__PURE__ */ jsx(NestedRichContent, { source: body }) }) : /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "This note is empty." }) })
62
+ ]
63
+ }
64
+ );
65
+ }
66
+ export {
67
+ WikiEmbed
68
+ };
@@ -0,0 +1,10 @@
1
+ import { type ReactNode } from "react";
2
+ import { type WikiResolution } from "../../../host/wikilinks.js";
3
+ export declare function useWikiResolution(target: string): WikiResolution | null;
4
+ interface WikiLinkProps {
5
+ "data-target"?: string;
6
+ "data-alias"?: string;
7
+ children?: ReactNode;
8
+ }
9
+ export declare function WikiLink(props: WikiLinkProps): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,114 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { Link2Off } from "lucide-react";
5
+ import { cn } from "@ai-matrx/design-system";
6
+ import { toast } from "../../../host/toast.js";
7
+ import { createWikiPage, resolveWikiTarget } from "../../../host/wikilinks.js";
8
+ import { splitHeading } from "./wiki-target.js";
9
+ function useWikiResolution(target) {
10
+ const [state, setState] = useState(null);
11
+ useEffect(() => {
12
+ let live = true;
13
+ resolveWikiTarget(target).then((value) => {
14
+ if (live) setState({ target, value });
15
+ }).catch((err) => {
16
+ if (live) {
17
+ setState({
18
+ target,
19
+ value: { status: "unavailable", title: target, message: err instanceof Error ? err.message : String(err) }
20
+ });
21
+ }
22
+ });
23
+ return () => {
24
+ live = false;
25
+ };
26
+ }, [target]);
27
+ return state && state.target === target ? state.value : null;
28
+ }
29
+ function WikiLink(props) {
30
+ const target = String(props["data-target"] ?? "");
31
+ const resolution = useWikiResolution(target);
32
+ const [creating, setCreating] = useState(false);
33
+ const [created, setCreated] = useState(null);
34
+ const label = props.children;
35
+ if (created) {
36
+ return /* @__PURE__ */ jsx("a", { href: created, className: "text-primary underline underline-offset-2", "data-content-chrome": "", "data-wikilink": "found", children: label });
37
+ }
38
+ if (!resolution) {
39
+ return /* @__PURE__ */ jsx("span", { "data-content-chrome": "", "data-wikilink": "resolving", "aria-busy": true, className: "text-primary/80 underline decoration-dotted underline-offset-2", children: label });
40
+ }
41
+ if (resolution.status === "found") {
42
+ if (!resolution.href) {
43
+ return /* @__PURE__ */ jsx("span", { "data-content-chrome": "", "data-wikilink": "found-no-page", title: `${resolution.typeLabel} "${resolution.title}" has no page to open`, className: "underline decoration-dotted underline-offset-2", children: label });
44
+ }
45
+ return /* @__PURE__ */ jsx(
46
+ "a",
47
+ {
48
+ href: resolution.href,
49
+ title: `${resolution.typeLabel}: ${resolution.title}`,
50
+ "data-content-chrome": "",
51
+ "data-wikilink": "found",
52
+ className: "text-primary underline underline-offset-2 hover:decoration-2",
53
+ children: label
54
+ }
55
+ );
56
+ }
57
+ if (resolution.status === "unavailable") {
58
+ return /* @__PURE__ */ jsxs(
59
+ "span",
60
+ {
61
+ "data-content-chrome": "",
62
+ "data-wikilink": "unavailable",
63
+ title: `Not available: ${resolution.message}`,
64
+ className: "inline-flex items-baseline gap-0.5 text-muted-foreground",
65
+ children: [
66
+ label,
67
+ /* @__PURE__ */ jsx(Link2Off, { className: "h-3 w-3 self-center", "aria-hidden": true }),
68
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "(not available)" })
69
+ ]
70
+ }
71
+ );
72
+ }
73
+ const create = async () => {
74
+ if (creating) return;
75
+ setCreating(true);
76
+ try {
77
+ const title = splitHeading(target).page;
78
+ const result = await createWikiPage(title);
79
+ if (!result.ok) {
80
+ toast.error(`"${title}" was not created: ${result.error}`);
81
+ return;
82
+ }
83
+ toast.success(`Created the note "${title}".`);
84
+ if (result.href) setCreated(result.href);
85
+ } catch (e) {
86
+ console.error("[wikilink] creating the note failed", e);
87
+ toast.error(`"${resolution.title}" was not created: ${e instanceof Error ? e.message : String(e)}`);
88
+ } finally {
89
+ setCreating(false);
90
+ }
91
+ };
92
+ return /* @__PURE__ */ jsx(
93
+ "button",
94
+ {
95
+ type: "button",
96
+ "data-content-chrome": "",
97
+ "data-wikilink": "missing",
98
+ "data-touch-exempt": "",
99
+ onClick: create,
100
+ disabled: creating,
101
+ "aria-busy": creating || void 0,
102
+ title: creating ? `Creating "${resolution.title}"\u2026` : `No page named "${resolution.title}" yet. Click to create it.`,
103
+ className: cn(
104
+ "inline cursor-pointer border-0 bg-transparent p-0 align-baseline font-[inherit] text-[length:inherit] leading-[inherit] text-muted-foreground underline decoration-dashed underline-offset-2 hover:text-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring",
105
+ creating && "cursor-wait opacity-60"
106
+ ),
107
+ children: label
108
+ }
109
+ );
110
+ }
111
+ export {
112
+ WikiLink,
113
+ useWikiResolution
114
+ };
@@ -0,0 +1,22 @@
1
+ import type React from "react";
2
+ import type { MarkdownComponents } from "../../markdown-core-types.js";
3
+ type AnyProps = Record<string, unknown> & {
4
+ children?: React.ReactNode;
5
+ node?: unknown;
6
+ };
7
+ /** A task checkbox or any other input. Shared with the prose leaf's element map. */
8
+ export declare function renderMarkdownInput({ node: _node, type, checked, ...rest }: AnyProps & {
9
+ type?: string;
10
+ checked?: boolean;
11
+ }): React.JSX.Element;
12
+ /** True for an in-document link (`#id`) — footnotes, anchors, contents, cross-references. */
13
+ export declare function isInDocHref(href: unknown): href is string;
14
+ export declare const CORE_SYNTAX_ELEMENTS: MarkdownComponents;
15
+ /** Merge a caller's map over the core defaults (the caller wins per tag). */
16
+ export declare function withCoreSyntaxElements(components: MarkdownComponents | undefined): MarkdownComponents;
17
+ /**
18
+ * The `inline` level's versions of the block constructs this syntax adds —
19
+ * phrasing content only (every one a <span>), nothing dropped.
20
+ */
21
+ export declare const INLINE_SYNTAX_ELEMENTS: MarkdownComponents;
22
+ export {};
@@ -0,0 +1,70 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { CalloutIcon } from "./CalloutIcon.js";
3
+ import { CrossRef } from "./CrossRef.js";
4
+ import { CsvFence } from "./CsvFence.js";
5
+ import { DetailsElement, KbdElement, SummaryElement } from "./DetailsElements.js";
6
+ import { InDocAnchor } from "./InDocAnchor.js";
7
+ import { MatrxTab, MatrxTabs } from "./MatrxTabs.js";
8
+ import { NestedBody } from "./NestedBody.js";
9
+ import { MentionChip } from "./MentionChip.js";
10
+ import { TableOfContents } from "./TableOfContents.js";
11
+ import { TaskCheckbox } from "./TaskCheckbox.js";
12
+ import { WikiEmbed } from "./WikiEmbed.js";
13
+ import { WikiLink } from "./WikiLink.js";
14
+ function renderMarkdownInput({ node: _node, type, checked, ...rest }) {
15
+ if (type === "checkbox") return /* @__PURE__ */ jsx(TaskCheckbox, { checked: !!checked, ...rest });
16
+ return /* @__PURE__ */ jsx("input", { type, ...rest });
17
+ }
18
+ function isInDocHref(href) {
19
+ return typeof href === "string" && href.startsWith("#") && href.length > 1;
20
+ }
21
+ const CORE_SYNTAX_ELEMENTS = {
22
+ a: ({ node: _node, href, children, ...rest }) => isInDocHref(href) ? /* @__PURE__ */ jsx(InDocAnchor, { href, ...rest, children }) : /* @__PURE__ */ jsx("a", { href, ...rest, children }),
23
+ input: renderMarkdownInput,
24
+ details: DetailsElement,
25
+ summary: SummaryElement,
26
+ kbd: KbdElement,
27
+ "matrx-callout-icon": CalloutIcon,
28
+ "matrx-wikilink": WikiLink,
29
+ "matrx-embed": WikiEmbed,
30
+ "matrx-tabs": MatrxTabs,
31
+ "matrx-tab": MatrxTab,
32
+ "matrx-toc": TableOfContents,
33
+ "matrx-csv": CsvFence,
34
+ "matrx-xref": CrossRef,
35
+ "matrx-nested": NestedBody,
36
+ "matrx-mention": MentionChip
37
+ };
38
+ function withCoreSyntaxElements(components) {
39
+ return components ? { ...CORE_SYNTAX_ELEMENTS, ...components } : CORE_SYNTAX_ELEMENTS;
40
+ }
41
+ const inlineBlock = ({ children }) => /* @__PURE__ */ jsx("span", { "data-rc-block": true, className: "block", children });
42
+ const inlineSpan = ({ children }) => /* @__PURE__ */ jsx("span", { children });
43
+ const INLINE_SYNTAX_ELEMENTS = {
44
+ details: inlineBlock,
45
+ summary: ({ children }) => /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
46
+ children,
47
+ " "
48
+ ] }),
49
+ aside: inlineBlock,
50
+ figure: inlineBlock,
51
+ figcaption: ({ children }) => /* @__PURE__ */ jsx("span", { className: "block text-[0.9em] text-muted-foreground", children }),
52
+ section: inlineBlock,
53
+ nav: inlineBlock,
54
+ dl: inlineBlock,
55
+ dt: ({ children }) => /* @__PURE__ */ jsx("span", { className: "block font-semibold", children }),
56
+ dd: ({ children }) => /* @__PURE__ */ jsx("span", { className: "block pl-3", children }),
57
+ "matrx-tabs": inlineBlock,
58
+ "matrx-tab": inlineBlock,
59
+ "matrx-toc": () => null,
60
+ "matrx-csv": ({ ...props }) => /* @__PURE__ */ jsx("span", { "data-rc-block": true, className: "block whitespace-pre-wrap font-mono text-[0.85em]", children: String(props["data-source"] ?? "") }),
61
+ "matrx-embed": inlineSpan,
62
+ "matrx-nested": ({ ...props }) => /* @__PURE__ */ jsx("span", { "data-rc-block": true, className: "block whitespace-pre-wrap", children: String(props["data-source"] ?? "") })
63
+ };
64
+ export {
65
+ CORE_SYNTAX_ELEMENTS,
66
+ INLINE_SYNTAX_ELEMENTS,
67
+ isInDocHref,
68
+ renderMarkdownInput,
69
+ withCoreSyntaxElements
70
+ };
@@ -0,0 +1,3 @@
1
+ export declare function findInDocument(from: Element | null, id: string): HTMLElement | null;
2
+ /** The root a document-wide scan (table of contents) reads: the marked root, else the page. */
3
+ export declare function documentRootOf(from: Element | null): Element | null;
@@ -0,0 +1,20 @@
1
+ function findInDocument(from, id) {
2
+ if (!from || !id) return null;
3
+ const esc = (v) => `[id="${v.replace(/["\\]/g, "\\$&")}"]`;
4
+ const selector = id.startsWith("user-content-") ? esc(id) : `${esc(`user-content-${id}`)}, ${esc(id)}`;
5
+ let scope = from.parentElement;
6
+ while (scope) {
7
+ const hit = scope.querySelector(selector);
8
+ if (hit && hit !== from) return hit;
9
+ scope = scope.parentElement;
10
+ }
11
+ return null;
12
+ }
13
+ function documentRootOf(from) {
14
+ if (!from) return null;
15
+ return from.closest("[data-matrx-doc-root]") ?? null;
16
+ }
17
+ export {
18
+ documentRootOf,
19
+ findInDocument
20
+ };
@@ -0,0 +1,5 @@
1
+ /** `[[Page#Heading]]` → the page and the heading (pure; shared with the host's resolver). */
2
+ export declare function splitHeading(target: string): {
3
+ page: string;
4
+ heading: string | null;
5
+ };
@@ -0,0 +1,8 @@
1
+ function splitHeading(target) {
2
+ const hash = target.indexOf("#");
3
+ if (hash < 0) return { page: target.trim(), heading: null };
4
+ return { page: target.slice(0, hash).trim(), heading: target.slice(hash + 1).trim() || null };
5
+ }
6
+ export {
7
+ splitHeading
8
+ };
@@ -0,0 +1,26 @@
1
+ export type FrontmatterFormat = "yaml" | "toml";
2
+ export interface FrontmatterSplit {
3
+ format: FrontmatterFormat;
4
+ /** The whole front-matter region, fences and trailing newline included. */
5
+ raw: string;
6
+ /** The text between the fences. */
7
+ inner: string;
8
+ /** Everything after the region — the document body. */
9
+ body: string;
10
+ }
11
+ /** Cut the front matter off the top of `source`, or null when it has none (or it has not closed yet). */
12
+ export declare function splitFrontmatter(source: string): FrontmatterSplit | null;
13
+ /** True when the text opens a front-matter region that has not closed yet (a streaming prefix). */
14
+ export declare function hasUnclosedFrontmatter(source: string): boolean;
15
+ export type DocumentProperties = Record<string, unknown>;
16
+ export interface DocumentPropertiesResult {
17
+ /** Parsed properties; `{}` when the document has none. */
18
+ properties: DocumentProperties;
19
+ format: FrontmatterFormat | null;
20
+ /** The front matter text exactly as stored (fences included), or null. */
21
+ raw: string | null;
22
+ /** A sentence saying why the front matter could not be read, or null. */
23
+ error: string | null;
24
+ }
25
+ /** Read a document's front matter as properties. Never throws. */
26
+ export declare function extractFrontmatter(source: string): DocumentPropertiesResult;