@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.
- package/CHANGELOG.md +72 -0
- package/LICENSE +21 -0
- package/README.md +61 -2
- package/dist/display/blocks/csv/CsvBlock.d.ts +10 -0
- package/dist/display/blocks/csv/CsvBlock.js +245 -0
- package/dist/display/blocks/table/parseMarkdownTable.d.ts +20 -0
- package/dist/display/blocks/table/parseMarkdownTable.js +35 -0
- package/dist/display/chat-markdown/citations/remarkMatrxCite.d.ts +33 -0
- package/dist/display/chat-markdown/citations/remarkMatrxCite.js +71 -0
- package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.d.ts +29 -0
- package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.js +71 -0
- package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.d.ts +55 -0
- package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.js +108 -0
- package/dist/display/chat-markdown/rehypeSafeRawHtml.d.ts +59 -0
- package/dist/display/chat-markdown/rehypeSafeRawHtml.js +140 -0
- package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.d.ts +14 -0
- package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.js +171 -0
- package/dist/display/markdown-classification/processors/types.d.ts +120 -0
- package/dist/display/markdown-classification/processors/types.js +10 -0
- package/dist/display/markdown-classification/processors/utils/client-blocks.d.ts +169 -0
- package/dist/display/markdown-classification/processors/utils/client-blocks.js +0 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-core.d.ts +223 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-core.js +1791 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-v2.d.ts +15 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-v2.js +19 -0
- package/dist/display/markdown-classification/processors/utils/expand-text-blocks.d.ts +9 -0
- package/dist/display/markdown-classification/processors/utils/expand-text-blocks.js +36 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-lines.d.ts +5 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-lines.js +40 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.d.ts +16 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.js +385 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.d.ts +43 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.js +33 -0
- package/dist/display/markdown-classification/processors/utils/table-data-parser.d.ts +9 -0
- package/dist/display/markdown-classification/processors/utils/table-data-parser.js +30 -0
- package/dist/display/markdown-classification/processors/utils/thinking-parser.d.ts +7 -0
- package/dist/display/markdown-classification/processors/utils/thinking-parser.js +70 -0
- package/dist/display/render-block.d.ts +23 -0
- package/dist/display/render-block.js +0 -0
- package/dist/display/themes.d.ts +1023 -0
- package/dist/display/themes.js +1105 -0
- package/dist/display/types.d.ts +32 -0
- package/dist/display/types.js +0 -0
- package/dist/host/ContentIrHostBoundary.d.ts +8 -0
- package/dist/host/ContentIrHostBoundary.js +15 -0
- package/dist/host/ErrorActions.d.ts +4 -0
- package/dist/host/ErrorActions.js +11 -0
- package/dist/host/NestedContent.d.ts +3 -0
- package/dist/host/NestedContent.js +12 -0
- package/dist/host/ResourcePeek.d.ts +6 -0
- package/dist/host/ResourcePeek.js +14 -0
- package/dist/host/component-registry.d.ts +2 -0
- package/dist/host/component-registry.js +25 -0
- package/dist/host/diagnostics.d.ts +2 -0
- package/dist/host/diagnostics.js +15 -0
- package/dist/host/index.d.ts +3 -0
- package/dist/host/index.js +18 -0
- package/dist/host/kind-incident.d.ts +3 -0
- package/dist/host/kind-incident.js +12 -0
- package/dist/host/kind-registry.d.ts +2 -0
- package/dist/host/kind-registry.js +35 -0
- package/dist/host/people.d.ts +3 -0
- package/dist/host/people.js +12 -0
- package/dist/host/registry.d.ts +27 -0
- package/dist/host/registry.js +55 -0
- package/dist/host/splitter-envelopes.d.ts +2 -0
- package/dist/host/splitter-envelopes.js +7 -0
- package/dist/host/tables.d.ts +6 -0
- package/dist/host/tables.js +8 -0
- package/dist/host/toast.d.ts +2 -0
- package/dist/host/toast.js +57 -0
- package/dist/host/types.d.ts +157 -0
- package/dist/host/types.js +0 -0
- package/dist/host/wikilinks.d.ts +15 -0
- package/dist/host/wikilinks.js +23 -0
- package/dist/kinds/host/route-env.d.ts +33 -0
- package/dist/kinds/host/route-env.js +16 -0
- package/dist/kinds/react/KindEscapedNotice.d.ts +14 -0
- package/dist/kinds/react/KindEscapedNotice.js +72 -0
- package/dist/kinds/react/ProvisionalKindBoundary.d.ts +19 -0
- package/dist/kinds/react/ProvisionalKindBoundary.js +17 -0
- package/dist/kinds/react/ensure-kind-renderable.d.ts +14 -0
- package/dist/kinds/react/ensure-kind-renderable.js +45 -0
- package/dist/kinds/react/kind-problems.d.ts +62 -0
- package/dist/kinds/react/kind-problems.js +134 -0
- package/dist/kinds/react/kind-route.d.ts +23 -0
- package/dist/kinds/react/kind-route.js +24 -0
- package/dist/kinds/react/loading/infer-loading-slug.d.ts +58 -0
- package/dist/kinds/react/loading/infer-loading-slug.js +100 -0
- package/dist/kinds/react/loading/kind-loading-components.d.ts +48 -0
- package/dist/kinds/react/loading/kind-loading-components.js +447 -0
- package/dist/kinds/react/loading/kind-loading-registry.d.ts +21 -0
- package/dist/kinds/react/loading/kind-loading-registry.js +62 -0
- package/dist/kinds/react/loading/kind-loading-slugs.d.ts +18 -0
- package/dist/kinds/react/loading/kind-loading-slugs.js +34 -0
- package/dist/kinds/react/loading/kind-loading.types.d.ts +79 -0
- package/dist/kinds/react/loading/kind-loading.types.js +31 -0
- package/dist/kinds/react/loading/resolve-loading-slug.d.ts +29 -0
- package/dist/kinds/react/loading/resolve-loading-slug.js +51 -0
- package/dist/kinds/react/partial-kind-route.d.ts +32 -0
- package/dist/kinds/react/partial-kind-route.js +27 -0
- package/dist/kinds/react/registry-versioned.d.ts +54 -0
- package/dist/kinds/react/registry-versioned.js +18 -0
- package/dist/kinds/react/route-at-version.d.ts +38 -0
- package/dist/kinds/react/route-at-version.js +78 -0
- package/dist/kinds/react/slot/KindSlot.d.ts +87 -0
- package/dist/kinds/react/slot/KindSlot.js +65 -0
- package/dist/kinds/react/use-registry-repaint.d.ts +6 -0
- package/dist/kinds/react/use-registry-repaint.js +36 -0
- package/dist/kinds/react/useIrNode.d.ts +9 -0
- package/dist/kinds/react/useIrNode.js +46 -0
- package/dist/kinds/react/useLiveJsonRegion.d.ts +15 -0
- package/dist/kinds/react/useLiveJsonRegion.js +84 -0
- package/dist/kinds/redux/render-block-envelope.d.ts +14 -0
- package/dist/kinds/redux/render-block-envelope.js +26 -0
- package/dist/kinds/registry/kind-correctors.d.ts +63 -0
- package/dist/kinds/registry/kind-correctors.js +94 -0
- package/dist/kinds/registry/legacy-quiz-envelope.d.ts +1 -0
- package/dist/kinds/registry/legacy-quiz-envelope.js +1 -0
- package/dist/kinds/registry/region-envelope-memo.d.ts +45 -0
- package/dist/kinds/registry/region-envelope-memo.js +94 -0
- package/dist/kinds/registry/registry-debug.d.ts +38 -0
- package/dist/kinds/registry/registry-debug.js +39 -0
- package/dist/markdown-core/MarkdownCore.d.ts +6 -0
- package/dist/markdown-core/MarkdownCore.js +32 -0
- package/dist/markdown-core/MarkdownCoreImpl.d.ts +3 -0
- package/dist/markdown-core/MarkdownCoreImpl.js +27 -0
- package/dist/markdown-core/MarkdownCoreServer.d.ts +4 -0
- package/dist/markdown-core/MarkdownCoreServer.js +26 -0
- package/dist/markdown-core/heading-anchors-context.d.ts +2 -0
- package/dist/markdown-core/heading-anchors-context.js +11 -0
- package/dist/markdown-core/heading-anchors-props.d.ts +2 -0
- package/dist/markdown-core/heading-anchors-props.js +6 -0
- package/dist/markdown-core/markdown-core-html.d.ts +3 -0
- package/dist/markdown-core/markdown-core-html.js +33 -0
- package/dist/markdown-core/markdown-core-presets.d.ts +22 -0
- package/dist/markdown-core/markdown-core-presets.js +118 -0
- package/dist/markdown-core/markdown-core-types.d.ts +43 -0
- package/dist/markdown-core/markdown-core-types.js +0 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-flow.d.ts +15 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-flow.js +143 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-text.d.ts +24 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-text.js +127 -0
- package/dist/markdown-core/math/vendor/micromark-math-syntax.d.ts +30 -0
- package/dist/markdown-core/math/vendor/micromark-math-syntax.js +15 -0
- package/dist/markdown-core/math/vendor/rehype-katex.d.ts +15 -0
- package/dist/markdown-core/math/vendor/rehype-katex.js +83 -0
- package/dist/markdown-core/math/vendor/remark-math.d.ts +9 -0
- package/dist/markdown-core/math/vendor/remark-math.js +20 -0
- package/dist/markdown-core/math-normalizer.d.ts +57 -0
- package/dist/markdown-core/math-normalizer.js +315 -0
- package/dist/markdown-core/plain-title.d.ts +2 -0
- package/dist/markdown-core/plain-title.js +1 -0
- package/dist/markdown-core/stream-heal.d.ts +2 -0
- package/dist/markdown-core/stream-heal.js +184 -0
- package/dist/markdown-core/streaming-context.d.ts +2 -0
- package/dist/markdown-core/streaming-context.js +11 -0
- package/dist/markdown-core/syntax/callout-types.d.ts +9 -0
- package/dist/markdown-core/syntax/callout-types.js +101 -0
- package/dist/markdown-core/syntax/containers.d.ts +17 -0
- package/dist/markdown-core/syntax/containers.js +353 -0
- package/dist/markdown-core/syntax/document-numbering.d.ts +52 -0
- package/dist/markdown-core/syntax/document-numbering.js +184 -0
- package/dist/markdown-core/syntax/elements/CalloutIcon.d.ts +3 -0
- package/dist/markdown-core/syntax/elements/CalloutIcon.js +41 -0
- package/dist/markdown-core/syntax/elements/CrossRef.d.ts +12 -0
- package/dist/markdown-core/syntax/elements/CrossRef.js +57 -0
- package/dist/markdown-core/syntax/elements/CsvFence.d.ts +4 -0
- package/dist/markdown-core/syntax/elements/CsvFence.js +18 -0
- package/dist/markdown-core/syntax/elements/DetailsElements.d.ts +12 -0
- package/dist/markdown-core/syntax/elements/DetailsElements.js +38 -0
- package/dist/markdown-core/syntax/elements/DocumentNumbering.d.ts +20 -0
- package/dist/markdown-core/syntax/elements/DocumentNumbering.js +37 -0
- package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.d.ts +4 -0
- package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.js +46 -0
- package/dist/markdown-core/syntax/elements/InDocAnchor.d.ts +11 -0
- package/dist/markdown-core/syntax/elements/InDocAnchor.js +87 -0
- package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.d.ts +24 -0
- package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.js +28 -0
- package/dist/markdown-core/syntax/elements/MatrxTabs.d.ts +10 -0
- package/dist/markdown-core/syntax/elements/MatrxTabs.js +59 -0
- package/dist/markdown-core/syntax/elements/MentionChip.d.ts +7 -0
- package/dist/markdown-core/syntax/elements/MentionChip.js +69 -0
- package/dist/markdown-core/syntax/elements/NestedBody.d.ts +3 -0
- package/dist/markdown-core/syntax/elements/NestedBody.js +13 -0
- package/dist/markdown-core/syntax/elements/TableOfContents.d.ts +5 -0
- package/dist/markdown-core/syntax/elements/TableOfContents.js +44 -0
- package/dist/markdown-core/syntax/elements/TaskCheckbox.d.ts +7 -0
- package/dist/markdown-core/syntax/elements/TaskCheckbox.js +63 -0
- package/dist/markdown-core/syntax/elements/WikiEmbed.d.ts +7 -0
- package/dist/markdown-core/syntax/elements/WikiEmbed.js +68 -0
- package/dist/markdown-core/syntax/elements/WikiLink.d.ts +10 -0
- package/dist/markdown-core/syntax/elements/WikiLink.js +114 -0
- package/dist/markdown-core/syntax/elements/core-syntax-elements.d.ts +22 -0
- package/dist/markdown-core/syntax/elements/core-syntax-elements.js +70 -0
- package/dist/markdown-core/syntax/elements/find-in-document.d.ts +3 -0
- package/dist/markdown-core/syntax/elements/find-in-document.js +20 -0
- package/dist/markdown-core/syntax/elements/wiki-target.d.ts +5 -0
- package/dist/markdown-core/syntax/elements/wiki-target.js +8 -0
- package/dist/markdown-core/syntax/frontmatter.d.ts +26 -0
- package/dist/markdown-core/syntax/frontmatter.js +72 -0
- package/dist/markdown-core/syntax/gfm-cell-pipes.d.ts +11 -0
- package/dist/markdown-core/syntax/gfm-cell-pipes.js +4 -0
- package/dist/markdown-core/syntax/inline-syntax.d.ts +26 -0
- package/dist/markdown-core/syntax/inline-syntax.js +163 -0
- package/dist/markdown-core/syntax/linear-scan.d.ts +46 -0
- package/dist/markdown-core/syntax/linear-scan.js +129 -0
- package/dist/markdown-core/syntax/mdast-helpers.d.ts +48 -0
- package/dist/markdown-core/syntax/mdast-helpers.js +48 -0
- package/dist/markdown-core/syntax/mentions.d.ts +2 -0
- package/dist/markdown-core/syntax/mentions.js +42 -0
- package/dist/markdown-core/syntax/names.d.ts +6 -0
- package/dist/markdown-core/syntax/names.js +18 -0
- package/dist/markdown-core/syntax/prepare-syntax-source.d.ts +1 -0
- package/dist/markdown-core/syntax/prepare-syntax-source.js +78 -0
- package/dist/markdown-core/syntax/rehype-matrx-syntax.d.ts +9 -0
- package/dist/markdown-core/syntax/rehype-matrx-syntax.js +180 -0
- package/dist/markdown-core/syntax/remark-inline-only.d.ts +23 -0
- package/dist/markdown-core/syntax/remark-inline-only.js +25 -0
- package/dist/markdown-core/syntax/remark-matrx-syntax.d.ts +7 -0
- package/dist/markdown-core/syntax/remark-matrx-syntax.js +351 -0
- package/dist/markdown-core/syntax/remark-table-code-pipes.d.ts +7 -0
- package/dist/markdown-core/syntax/remark-table-code-pipes.js +23 -0
- package/dist/markdown-core/syntax/stream-heal-syntax.d.ts +2 -0
- package/dist/markdown-core/syntax/stream-heal-syntax.js +108 -0
- package/dist/markdown-core/syntax/task-source.d.ts +10 -0
- package/dist/markdown-core/syntax/task-source.js +34 -0
- package/dist/markdown-core/syntax/useDocumentProperties.d.ts +3 -0
- package/dist/markdown-core/syntax/useDocumentProperties.js +8 -0
- package/dist/styles.css +0 -0
- package/dist/utils/addressWithoutNavigating.d.ts +68 -0
- package/dist/utils/addressWithoutNavigating.js +60 -0
- package/dist/utils/client-lazy.d.ts +13 -0
- package/dist/utils/client-lazy.js +24 -0
- package/dist/utils/decision-options.d.ts +21 -0
- package/dist/utils/decision-options.js +32 -0
- package/dist/utils/gfm-lexer.d.ts +5 -0
- package/dist/utils/gfm-lexer.js +10 -0
- package/dist/utils/json.d.ts +63 -0
- package/dist/utils/json.js +22 -0
- package/dist/utils/plain-title.d.ts +25 -0
- package/dist/utils/plain-title.js +51 -0
- package/dist/utils/table-source.d.ts +62 -0
- package/dist/utils/table-source.js +191 -0
- package/dist/utils/youtube.d.ts +52 -0
- package/dist/utils/youtube.js +137 -0
- package/package.json +134 -4
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { resolveCalloutType } from "./callout-types.js";
|
|
2
|
+
import { CONTAINER_DIRECTIVES } from "./names.js";
|
|
3
|
+
import { fenceLineKinds } from "@ai-matrx/content-ir/source";
|
|
4
|
+
const MKDOCS_OPEN = /^(!!!|\?\?\?\+?)[ \t]+([A-Za-z][\w-]*)(?:[ \t]+[\w-]+)*(?:[ \t]+"((?:[^"\\]|\\.)*)")?[ \t]*$/;
|
|
5
|
+
const DOCUSAURUS_TITLED = /^(:{3,})([A-Za-z][\w-]*)[ \t]+([^\s{[][^\n]*?)[ \t]*$/;
|
|
6
|
+
const INDENT = /^(?: {4}|\t|(?:\u00A0){8})/;
|
|
7
|
+
const BLANKISH = /^[ \t\u00A0]*$|^ $/;
|
|
8
|
+
function escapeLabel(text) {
|
|
9
|
+
return text.replace(/\\"/g, '"').replace(/([[\]])/g, "\\$1");
|
|
10
|
+
}
|
|
11
|
+
function longestColonRun(lines) {
|
|
12
|
+
let max = 0;
|
|
13
|
+
for (const line of lines) {
|
|
14
|
+
const m = /^[ \t]*(:{3,})/.exec(line);
|
|
15
|
+
if (m && m[1].length > max) max = m[1].length;
|
|
16
|
+
}
|
|
17
|
+
return max;
|
|
18
|
+
}
|
|
19
|
+
function rewriteContainerSpellings(source) {
|
|
20
|
+
if (!source || !source.includes("!!!") && !source.includes("???") && !source.includes(":::")) {
|
|
21
|
+
return source;
|
|
22
|
+
}
|
|
23
|
+
const lines = source.split("\n");
|
|
24
|
+
const kinds = fenceLineKinds(source);
|
|
25
|
+
const out = [];
|
|
26
|
+
let changed = false;
|
|
27
|
+
for (let i = 0; i < lines.length; i++) {
|
|
28
|
+
const line = lines[i] ?? "";
|
|
29
|
+
if (kinds[i] !== "prose") {
|
|
30
|
+
out.push(line);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const mk = MKDOCS_OPEN.exec(line);
|
|
34
|
+
if (mk && resolveCalloutType(mk[2])) {
|
|
35
|
+
const opener = mk[1];
|
|
36
|
+
const type = mk[2].toLowerCase();
|
|
37
|
+
const title = mk[3];
|
|
38
|
+
const body = [];
|
|
39
|
+
let j = i + 1;
|
|
40
|
+
while (j < lines.length) {
|
|
41
|
+
const candidate = lines[j] ?? "";
|
|
42
|
+
if (INDENT.test(candidate)) {
|
|
43
|
+
body.push(candidate.replace(INDENT, ""));
|
|
44
|
+
j++;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (BLANKISH.test(candidate)) {
|
|
48
|
+
let k = j;
|
|
49
|
+
while (k < lines.length && BLANKISH.test(lines[k] ?? "")) k++;
|
|
50
|
+
if (k < lines.length && INDENT.test(lines[k] ?? "")) {
|
|
51
|
+
for (let b = j; b < k; b++) body.push("");
|
|
52
|
+
j = k;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
const colons = ":".repeat(Math.max(3, longestColonRun(body) + 1));
|
|
59
|
+
const label = title && title.length > 0 ? `[${escapeLabel(title)}]` : "";
|
|
60
|
+
const attrs = opener === "???" ? "{fold}" : opener === "???+" ? "{fold=open}" : "";
|
|
61
|
+
out.push(`${colons}${type}${label}${attrs}`, ...body, colons);
|
|
62
|
+
i = j - 1;
|
|
63
|
+
changed = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const docu = DOCUSAURUS_TITLED.exec(line);
|
|
67
|
+
if (docu && (resolveCalloutType(docu[2]) || CONTAINER_DIRECTIVES.has(docu[2].toLowerCase()))) {
|
|
68
|
+
out.push(`${docu[1]}${docu[2]}[${escapeLabel(docu[3])}]`);
|
|
69
|
+
changed = true;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
out.push(line);
|
|
73
|
+
}
|
|
74
|
+
return changed ? out.join("\n") : source;
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
rewriteContainerSpellings
|
|
78
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Root } from "hast";
|
|
2
|
+
import type { DocumentNumbering } from "./document-numbering.js";
|
|
3
|
+
export interface RehypeMatrxSyntaxOptions {
|
|
4
|
+
/** The whole document's numbering — footnotes are numbered document-wide from it. */
|
|
5
|
+
numbering?: DocumentNumbering | null;
|
|
6
|
+
}
|
|
7
|
+
export default function rehypeMatrxSyntax(options?: RehypeMatrxSyntaxOptions): (tree: Root) => void;
|
|
8
|
+
/** The prefix GitHub puts on every id an author controls. */
|
|
9
|
+
export declare const USER_ID_PREFIX = "user-content-";
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { toString as hastToString } from "hast-util-to-string";
|
|
2
|
+
const HEADINGS = /* @__PURE__ */ new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
3
|
+
function isElement(node) {
|
|
4
|
+
return node.type === "element";
|
|
5
|
+
}
|
|
6
|
+
function walk(node, visit) {
|
|
7
|
+
for (const child of node.children) {
|
|
8
|
+
if (isElement(child)) {
|
|
9
|
+
visit(child, node);
|
|
10
|
+
walk(child, visit);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function classList(el) {
|
|
15
|
+
const cls = el.properties?.className;
|
|
16
|
+
if (Array.isArray(cls)) return cls.map(String);
|
|
17
|
+
return typeof cls === "string" ? String(cls).split(/\s+/) : [];
|
|
18
|
+
}
|
|
19
|
+
const ANCHOR_CLASS = [
|
|
20
|
+
"matrx-heading-anchor",
|
|
21
|
+
"relative",
|
|
22
|
+
"left-2",
|
|
23
|
+
"inline-block",
|
|
24
|
+
"w-0",
|
|
25
|
+
"whitespace-nowrap",
|
|
26
|
+
"[@media(hover:none)]:hidden",
|
|
27
|
+
"select-none",
|
|
28
|
+
"text-[0.8em]",
|
|
29
|
+
"font-normal",
|
|
30
|
+
"text-muted-foreground",
|
|
31
|
+
"no-underline",
|
|
32
|
+
"opacity-0",
|
|
33
|
+
"transition-opacity",
|
|
34
|
+
"hover:text-primary",
|
|
35
|
+
"focus:opacity-100",
|
|
36
|
+
"[:hover>&]:opacity-100",
|
|
37
|
+
"after:content-['#']"
|
|
38
|
+
];
|
|
39
|
+
function tocList(entries) {
|
|
40
|
+
const min = Math.min(...entries.map((e) => e.depth));
|
|
41
|
+
const root = { type: "element", tagName: "ol", properties: { className: ["matrx-toc-list", "space-y-0.5"] }, children: [] };
|
|
42
|
+
const stack = [{ depth: min, list: root }];
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
while (stack.length > 1 && entry.depth < stack[stack.length - 1].depth) stack.pop();
|
|
45
|
+
let top = stack[stack.length - 1];
|
|
46
|
+
if (entry.depth > top.depth) {
|
|
47
|
+
const nested = { type: "element", tagName: "ol", properties: { className: ["ml-4", "mt-0.5", "space-y-0.5"] }, children: [] };
|
|
48
|
+
const lastItem = top.list.children[top.list.children.length - 1];
|
|
49
|
+
if (lastItem && isElement(lastItem)) lastItem.children.push(nested);
|
|
50
|
+
else top.list.children.push(nested);
|
|
51
|
+
stack.push({ depth: entry.depth, list: nested });
|
|
52
|
+
top = stack[stack.length - 1];
|
|
53
|
+
}
|
|
54
|
+
top.list.children.push({
|
|
55
|
+
type: "element",
|
|
56
|
+
tagName: "li",
|
|
57
|
+
properties: {},
|
|
58
|
+
children: [
|
|
59
|
+
{
|
|
60
|
+
type: "element",
|
|
61
|
+
tagName: "a",
|
|
62
|
+
properties: { href: `#${entry.id}`, className: ["text-foreground/80", "hover:text-primary", "no-underline"] },
|
|
63
|
+
children: [{ type: "text", value: entry.text }]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return root;
|
|
69
|
+
}
|
|
70
|
+
function rehypeMatrxSyntax(options = {}) {
|
|
71
|
+
const numbering = options.numbering ?? null;
|
|
72
|
+
return (tree) => {
|
|
73
|
+
const headings = [];
|
|
74
|
+
const tocs = [];
|
|
75
|
+
let taskIndex = 0;
|
|
76
|
+
walk(tree, (el) => {
|
|
77
|
+
if (HEADINGS.has(el.tagName)) {
|
|
78
|
+
const id = el.properties?.id;
|
|
79
|
+
if (typeof id === "string" && id !== "footnote-label" && !classList(el).includes("sr-only")) {
|
|
80
|
+
headings.push({ id, depth: Number(el.tagName.slice(1)), text: hastToString(el).trim() });
|
|
81
|
+
el.children.push({
|
|
82
|
+
type: "element",
|
|
83
|
+
tagName: "a",
|
|
84
|
+
// data-content-chrome: renderer-added UI, not the source's words (the annotation text mapper skips it).
|
|
85
|
+
// The "#" is drawn by CSS and the link is hidden from assistive
|
|
86
|
+
// tech: it used to join the heading's accessible name and copied
|
|
87
|
+
// text ("Clinic intake checklist#"). The heading's id stays the
|
|
88
|
+
// link target; the hover "#" is a mouse convenience.
|
|
89
|
+
properties: { href: `#${id}`, className: ANCHOR_CLASS, ariaHidden: "true", tabIndex: -1, title: "Link to this section", dataHeadingAnchor: true, dataContentChrome: true },
|
|
90
|
+
children: []
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (el.tagName === "matrx-toc") {
|
|
96
|
+
tocs.push(el);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (el.tagName === "li" && classList(el).includes("task-list-item")) {
|
|
100
|
+
const input = findCheckbox(el);
|
|
101
|
+
if (input) {
|
|
102
|
+
input.properties = {
|
|
103
|
+
...input.properties,
|
|
104
|
+
dataTaskIndex: taskIndex++,
|
|
105
|
+
dataTaskText: taskText(el)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (el.tagName === "section" && el.properties?.dataFootnotes !== void 0) {
|
|
111
|
+
el.properties = {
|
|
112
|
+
...el.properties,
|
|
113
|
+
className: [...classList(el), "matrx-footnotes", "mt-6", "border-t", "border-border", "pt-3", "text-sm", "text-muted-foreground"]
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
for (const toc of tocs) {
|
|
118
|
+
const entries = headings.filter((h) => h.depth <= 4);
|
|
119
|
+
toc.properties = { ...toc.properties, dataTocCount: entries.length };
|
|
120
|
+
toc.children = entries.length > 0 ? [tocList(entries)] : [];
|
|
121
|
+
}
|
|
122
|
+
if (numbering && numbering.footnotes.size > 0) numberFootnotes(tree, numbering.footnotes);
|
|
123
|
+
prefixAuthorIds(tree);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const FN_PREFIX = "user-content-fn-";
|
|
127
|
+
function footnoteId(href) {
|
|
128
|
+
const at = href.indexOf(FN_PREFIX);
|
|
129
|
+
if (at < 0) return null;
|
|
130
|
+
try {
|
|
131
|
+
return decodeURIComponent(href.slice(at + FN_PREFIX.length)).toLowerCase();
|
|
132
|
+
} catch {
|
|
133
|
+
return href.slice(at + FN_PREFIX.length).toLowerCase();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function numberFootnotes(tree, numbers) {
|
|
137
|
+
walk(tree, (el) => {
|
|
138
|
+
if (el.tagName === "a" && el.properties?.dataFootnoteRef !== void 0) {
|
|
139
|
+
const id = footnoteId(String(el.properties?.href ?? ""));
|
|
140
|
+
const n = id ? numbers.get(id) : void 0;
|
|
141
|
+
if (n !== void 0) el.children = [{ type: "text", value: String(n) }];
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (el.tagName === "li") {
|
|
145
|
+
const id = footnoteId(String(el.properties?.id ?? ""));
|
|
146
|
+
const n = id ? numbers.get(id) : void 0;
|
|
147
|
+
if (n !== void 0) el.properties = { ...el.properties, value: String(n) };
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
const USER_ID_PREFIX = "user-content-";
|
|
152
|
+
function prefixAuthorIds(tree) {
|
|
153
|
+
walk(tree, (el) => {
|
|
154
|
+
const id = el.properties?.id;
|
|
155
|
+
if (typeof id !== "string" || !id || id === "footnote-label" || id.startsWith(USER_ID_PREFIX)) return;
|
|
156
|
+
el.properties = { ...el.properties, id: `${USER_ID_PREFIX}${id}` };
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function findCheckbox(li) {
|
|
160
|
+
for (const child of li.children) {
|
|
161
|
+
if (!isElement(child)) continue;
|
|
162
|
+
if (child.tagName === "input" && child.properties?.type === "checkbox") return child;
|
|
163
|
+
if (child.tagName === "p") {
|
|
164
|
+
const inner = findCheckbox(child);
|
|
165
|
+
if (inner) return inner;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
function taskText(li) {
|
|
171
|
+
const own = {
|
|
172
|
+
...li,
|
|
173
|
+
children: li.children.filter((c) => !(isElement(c) && (c.tagName === "ul" || c.tagName === "ol")))
|
|
174
|
+
};
|
|
175
|
+
return hastToString(own).replace(/\s+/g, " ").trim();
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
USER_ID_PREFIX,
|
|
179
|
+
rehypeMatrxSyntax as default
|
|
180
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse INLINE constructs only — what a GFM table cell is (verify-RC-B4 R6-1).
|
|
3
|
+
*
|
|
4
|
+
* GFM splits a table row into cells and parses each cell's text as INLINE
|
|
5
|
+
* content: `> 90%` is the text "> 90%", `- n/a` is "- n/a", `# 3` is "# 3",
|
|
6
|
+
* `1. first` is "1. first". The inline level of <RichContent> parses its source
|
|
7
|
+
* as a document (then draws block elements as spans), so a cell starting with
|
|
8
|
+
* block syntax lost its first characters. This turns every block-level
|
|
9
|
+
* construct off in the parser for that one source, so the core reads a cell
|
|
10
|
+
* exactly as GFM does — no stripping, no escaping of the source.
|
|
11
|
+
*
|
|
12
|
+
* Used by the `chat-cell` preset (markdown-core-presets.ts), reached through
|
|
13
|
+
* `<RichContent level="inline" gfmCell>`.
|
|
14
|
+
*/
|
|
15
|
+
type ProcessorData = {
|
|
16
|
+
micromarkExtensions?: unknown[];
|
|
17
|
+
};
|
|
18
|
+
/** Block constructs a table cell never contains (names from micromark and its extensions). */
|
|
19
|
+
export declare const BLOCK_CONSTRUCTS: readonly ["blockQuote", "codeFenced", "codeIndented", "definition", "headingAtx", "htmlFlow", "list", "setextUnderline", "thematicBreak", "gfmFootnoteDefinition", "mathFlow", "directiveContainer", "directiveLeaf", "frontmatter", "table"];
|
|
20
|
+
export default function remarkInlineOnly(this: {
|
|
21
|
+
data: () => ProcessorData;
|
|
22
|
+
}): void;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const BLOCK_CONSTRUCTS = [
|
|
2
|
+
"blockQuote",
|
|
3
|
+
"codeFenced",
|
|
4
|
+
"codeIndented",
|
|
5
|
+
"definition",
|
|
6
|
+
"headingAtx",
|
|
7
|
+
"htmlFlow",
|
|
8
|
+
"list",
|
|
9
|
+
"setextUnderline",
|
|
10
|
+
"thematicBreak",
|
|
11
|
+
"gfmFootnoteDefinition",
|
|
12
|
+
"mathFlow",
|
|
13
|
+
"directiveContainer",
|
|
14
|
+
"directiveLeaf",
|
|
15
|
+
"frontmatter",
|
|
16
|
+
"table"
|
|
17
|
+
];
|
|
18
|
+
function remarkInlineOnly() {
|
|
19
|
+
const data = this.data();
|
|
20
|
+
(data.micromarkExtensions ??= []).push({ disable: { null: [...BLOCK_CONSTRUCTS] } });
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
BLOCK_CONSTRUCTS,
|
|
24
|
+
remarkInlineOnly as default
|
|
25
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type DocumentNumbering } from "./document-numbering.js";
|
|
2
|
+
import { type MNode, type SyntaxFile } from "./mdast-helpers.js";
|
|
3
|
+
export interface RemarkMatrxSyntaxOptions {
|
|
4
|
+
/** The whole document's numbering (computeDocumentNumbering), when this tree is one block of it. */
|
|
5
|
+
numbering?: DocumentNumbering | null;
|
|
6
|
+
}
|
|
7
|
+
export default function remarkMatrxSyntax(options?: RemarkMatrxSyntaxOptions): (tree: MNode, file: SyntaxFile) => void;
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { isTocLine } from "@ai-matrx/print/directives";
|
|
2
|
+
import { extractFrontmatter } from "./frontmatter.js";
|
|
3
|
+
import { captionKey, DOCUMENT_FOOTNOTES_MARKER } from "./document-numbering.js";
|
|
4
|
+
import { transformContainers } from "./containers.js";
|
|
5
|
+
import { trailingHeadingId } from "./linear-scan.js";
|
|
6
|
+
import { transformMentions } from "./mentions.js";
|
|
7
|
+
import { transformInline } from "./inline-syntax.js";
|
|
8
|
+
import { el, rawOf, text, toText, walkParents } from "./mdast-helpers.js";
|
|
9
|
+
function stripFrontmatter(tree, file) {
|
|
10
|
+
const children = tree.children ?? [];
|
|
11
|
+
const first = children[0];
|
|
12
|
+
if (!first || first.type !== "yaml" && first.type !== "toml") return;
|
|
13
|
+
tree.children = children.slice(1);
|
|
14
|
+
if (file) {
|
|
15
|
+
const source = typeof file.value === "string" ? file.value : "";
|
|
16
|
+
file.data = { ...file.data ?? {}, matrxFrontmatter: extractFrontmatter(source) };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const DEFLIST_ELEMENTS = {
|
|
20
|
+
defList: { tag: "dl", className: ["matrx-dl", "my-3", "space-y-1"] },
|
|
21
|
+
defListTerm: { tag: "dt", className: ["font-semibold", "text-foreground"] },
|
|
22
|
+
defListDescription: { tag: "dd", className: ["ml-5", "mb-2", "text-foreground/90", "[&>p]:mb-1"] }
|
|
23
|
+
};
|
|
24
|
+
function tagDefinitionLists(tree) {
|
|
25
|
+
walkParents(tree, (parent) => {
|
|
26
|
+
for (const child of parent.children ?? []) {
|
|
27
|
+
const spec = DEFLIST_ELEMENTS[child.type];
|
|
28
|
+
if (spec) child.data = { ...child.data ?? {}, hName: spec.tag, hProperties: { className: spec.className } };
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const ABBR_LINE = /^\*\[([^\]\n]+)\]:[ \t]*(\S[^\n]*)$/;
|
|
33
|
+
function collectAbbreviations(tree, file) {
|
|
34
|
+
const found = /* @__PURE__ */ new Map();
|
|
35
|
+
walkParents(tree, (parent) => {
|
|
36
|
+
const kept = [];
|
|
37
|
+
let removed = false;
|
|
38
|
+
for (const child of parent.children ?? []) {
|
|
39
|
+
if (child.type === "paragraph") {
|
|
40
|
+
const raw = rawOf(child, file) ?? toText(child);
|
|
41
|
+
const lines = raw.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
42
|
+
const parsed = lines.map((l) => ABBR_LINE.exec(l));
|
|
43
|
+
if (lines.length > 0 && parsed.every(Boolean)) {
|
|
44
|
+
for (const m of parsed) if (m) found.set((m[1] ?? "").trim(), (m[2] ?? "").trim());
|
|
45
|
+
removed = true;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
kept.push(child);
|
|
50
|
+
}
|
|
51
|
+
if (removed) parent.children = kept;
|
|
52
|
+
});
|
|
53
|
+
return found;
|
|
54
|
+
}
|
|
55
|
+
function escapeRegExp(s) {
|
|
56
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
57
|
+
}
|
|
58
|
+
function applyAbbreviations(tree, abbrs) {
|
|
59
|
+
if (abbrs.size === 0) return;
|
|
60
|
+
const keys = [...abbrs.keys()].sort((a, b) => b.length - a.length).map(escapeRegExp);
|
|
61
|
+
const re = new RegExp(`(?<![\\w])(${keys.join("|")})(?![\\w])`, "g");
|
|
62
|
+
const visit = (node) => {
|
|
63
|
+
if (!node.children || node.type === "link" || node.type === "inlineCode" || node.data?.hName === "abbr") return;
|
|
64
|
+
const next = [];
|
|
65
|
+
let changed = false;
|
|
66
|
+
for (const child of node.children) {
|
|
67
|
+
if (child.type !== "text") {
|
|
68
|
+
visit(child);
|
|
69
|
+
next.push(child);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const value = child.value ?? "";
|
|
73
|
+
let pos = 0;
|
|
74
|
+
re.lastIndex = 0;
|
|
75
|
+
let m;
|
|
76
|
+
while ((m = re.exec(value)) !== null) {
|
|
77
|
+
if (m.index > pos) next.push(text(value.slice(pos, m.index)));
|
|
78
|
+
next.push(el("abbr", { title: abbrs.get(m[1] ?? ""), className: ["cursor-help", "underline", "decoration-dotted", "underline-offset-2"] }, [text(m[1] ?? "")]));
|
|
79
|
+
pos = m.index + m[0].length;
|
|
80
|
+
changed = true;
|
|
81
|
+
}
|
|
82
|
+
if (pos === 0) next.push(child);
|
|
83
|
+
else if (pos < value.length) next.push(text(value.slice(pos)));
|
|
84
|
+
}
|
|
85
|
+
if (changed) node.children = next;
|
|
86
|
+
};
|
|
87
|
+
visit(tree);
|
|
88
|
+
}
|
|
89
|
+
function applyHeadingIds(tree) {
|
|
90
|
+
walkParents(tree, (parent) => {
|
|
91
|
+
for (const child of parent.children ?? []) {
|
|
92
|
+
if (child.type !== "heading") continue;
|
|
93
|
+
const last = child.children?.[child.children.length - 1];
|
|
94
|
+
if (!last || last.type !== "text") continue;
|
|
95
|
+
const m = trailingHeadingId(last.value ?? "");
|
|
96
|
+
if (!m) continue;
|
|
97
|
+
last.value = (last.value ?? "").slice(0, m.index);
|
|
98
|
+
child.data = {
|
|
99
|
+
...child.data ?? {},
|
|
100
|
+
hProperties: { ...child.data?.hProperties ?? {}, id: m.id }
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function titledImageFigures(tree) {
|
|
106
|
+
const visit = (parent) => {
|
|
107
|
+
const children = parent.children;
|
|
108
|
+
if (!children || parent.type === "matrxFigure") return;
|
|
109
|
+
for (let i = 0; i < children.length; i++) {
|
|
110
|
+
const child = children[i];
|
|
111
|
+
if (child.type === "paragraph") {
|
|
112
|
+
const meaningful = (child.children ?? []).filter((n) => !(n.type === "text" && !(n.value ?? "").trim()));
|
|
113
|
+
const only = meaningful.length === 1 ? meaningful[0] : null;
|
|
114
|
+
const title = only?.type === "image" && typeof only.title === "string" ? only.title.trim() : "";
|
|
115
|
+
if (only && title) {
|
|
116
|
+
const figure = el("figure", { className: ["matrx-figure", "my-4", "text-center"] }, [only], "matrxFigure");
|
|
117
|
+
figure.matrxFigure = { kind: "fig", caption: [text(title)], id: null };
|
|
118
|
+
figure.position = child.position;
|
|
119
|
+
children[i] = figure;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
visit(child);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
visit(tree);
|
|
127
|
+
}
|
|
128
|
+
function setMathValue(node, value) {
|
|
129
|
+
const previous = node.value;
|
|
130
|
+
node.value = value;
|
|
131
|
+
const patch = (list) => {
|
|
132
|
+
for (const child of list ?? []) {
|
|
133
|
+
const c = child;
|
|
134
|
+
if (c.type === "text" && c.value === previous) c.value = value;
|
|
135
|
+
patch(c.children);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
patch(node.data?.hChildren);
|
|
139
|
+
}
|
|
140
|
+
const LABEL_RE = /\\label\{([^{}]+)\}/g;
|
|
141
|
+
const TAG_RE = /\\tag\*?\{([^{}]*)\}/;
|
|
142
|
+
function numberTargets(tree, numbering) {
|
|
143
|
+
const xrefs = new Map(numbering ? numbering.byLabel : []);
|
|
144
|
+
const captionCursor = /* @__PURE__ */ new Map();
|
|
145
|
+
let figures = 0;
|
|
146
|
+
let tables = 0;
|
|
147
|
+
let equations = 0;
|
|
148
|
+
const visit = (parent) => {
|
|
149
|
+
const children = parent.children;
|
|
150
|
+
if (!children) return;
|
|
151
|
+
for (let i = 0; i < children.length; i++) {
|
|
152
|
+
const child = children[i];
|
|
153
|
+
const meta = child.matrxFigure;
|
|
154
|
+
if (meta) {
|
|
155
|
+
const n = meta.kind === "fig" ? ++figures : ++tables;
|
|
156
|
+
const word = meta.kind === "fig" ? "Figure" : "Table";
|
|
157
|
+
let display = `${word} ${n}`;
|
|
158
|
+
if (numbering) {
|
|
159
|
+
if (meta.id) display = numbering.byLabel.get(meta.id)?.display ?? display;
|
|
160
|
+
else {
|
|
161
|
+
const key = captionKey(meta.kind, toText({ type: "root", children: meta.caption }));
|
|
162
|
+
const seen = captionCursor.get(key) ?? 0;
|
|
163
|
+
const global = numbering.byCaption.get(key)?.[seen];
|
|
164
|
+
captionCursor.set(key, seen + 1);
|
|
165
|
+
if (global) display = global;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (meta.id) xrefs.set(meta.id, { kind: meta.kind, display });
|
|
169
|
+
const hp = child.data?.hProperties ?? {};
|
|
170
|
+
child.data = { ...child.data ?? {}, hProperties: { ...hp, dataXrefLabel: display } };
|
|
171
|
+
const caption = el(
|
|
172
|
+
"figcaption",
|
|
173
|
+
{ className: ["mt-1.5", "text-center", "text-sm", "text-muted-foreground"] },
|
|
174
|
+
[el("span", { className: ["font-semibold", "text-foreground"], dataContentChrome: true }, [text(`${display}.`)]), ...meta.caption.length > 0 ? [text(" "), ...meta.caption] : []]
|
|
175
|
+
);
|
|
176
|
+
const body = child.children ?? [];
|
|
177
|
+
child.children = meta.kind === "tbl" ? [caption, ...body] : [...body, caption];
|
|
178
|
+
delete child.matrxFigure;
|
|
179
|
+
}
|
|
180
|
+
if (child.type === "heading") {
|
|
181
|
+
const id = child.data?.hProperties?.id;
|
|
182
|
+
if (typeof id === "string" && id.startsWith("sec:")) {
|
|
183
|
+
xrefs.set(id, { kind: "sec", display: toText(child).trim() });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (child.type === "math" && typeof child.value === "string" && child.value.includes("\\label")) {
|
|
187
|
+
const labels = [...child.value.matchAll(LABEL_RE)].map((m) => (m[1] ?? "").trim());
|
|
188
|
+
const explicit = TAG_RE.exec(child.value);
|
|
189
|
+
let number;
|
|
190
|
+
if (explicit) {
|
|
191
|
+
number = explicit[1] ?? "";
|
|
192
|
+
setMathValue(child, child.value.replace(LABEL_RE, ""));
|
|
193
|
+
} else {
|
|
194
|
+
const local = String(++equations);
|
|
195
|
+
const global = labels[0] ? numbering?.byLabel.get(labels[0]) : void 0;
|
|
196
|
+
number = global?.kind === "eq" ? global.display.replace(/[()]/g, "") : local;
|
|
197
|
+
let first = true;
|
|
198
|
+
setMathValue(
|
|
199
|
+
child,
|
|
200
|
+
child.value.replace(LABEL_RE, () => {
|
|
201
|
+
if (!first) return "";
|
|
202
|
+
first = false;
|
|
203
|
+
return `\\tag{${number}}`;
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
const display = `(${number})`;
|
|
208
|
+
const label = labels[0];
|
|
209
|
+
if (label) {
|
|
210
|
+
xrefs.set(label, { kind: "eq", display });
|
|
211
|
+
children.splice(i, 0, el("span", { id: label, className: ["matrx-eq-anchor", "block", "h-0"], dataXrefLabel: `Equation ${display}` }));
|
|
212
|
+
i++;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
visit(child);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
visit(tree);
|
|
219
|
+
return xrefs;
|
|
220
|
+
}
|
|
221
|
+
function resolveMathRefs(tree, xrefs) {
|
|
222
|
+
const visit = (node) => {
|
|
223
|
+
if ((node.type === "math" || node.type === "inlineMath") && typeof node.value === "string" && /\\(eq)?ref\{/.test(node.value)) {
|
|
224
|
+
setMathValue(
|
|
225
|
+
node,
|
|
226
|
+
node.value.replace(/\\(eqref|ref)\{([^{}]+)\}/g, (_m, kind, label) => {
|
|
227
|
+
const target = xrefs.get(label.trim());
|
|
228
|
+
const shown = target ? target.display.replace(/[()]/g, "") : "??";
|
|
229
|
+
return kind === "eqref" ? `\\text{(${shown})}` : `\\text{${shown}}`;
|
|
230
|
+
})
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
node.children?.forEach(visit);
|
|
234
|
+
};
|
|
235
|
+
visit(tree);
|
|
236
|
+
}
|
|
237
|
+
function applyTocMarkers(tree, file) {
|
|
238
|
+
walkParents(tree, (parent) => {
|
|
239
|
+
const children = parent.children ?? [];
|
|
240
|
+
for (let i = 0; i < children.length; i++) {
|
|
241
|
+
const child = children[i];
|
|
242
|
+
if (child.type !== "paragraph" && child.type !== "html") continue;
|
|
243
|
+
const raw = rawOf(child, file) ?? (child.type === "html" ? child.value ?? "" : toText(child));
|
|
244
|
+
if (!raw.includes("\n") && isTocLine(raw)) children[i] = el("matrx-toc", {}, [], "matrxToc");
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
function applyCsvFences(tree) {
|
|
249
|
+
walkParents(tree, (parent) => {
|
|
250
|
+
const children = parent.children ?? [];
|
|
251
|
+
for (let i = 0; i < children.length; i++) {
|
|
252
|
+
const child = children[i];
|
|
253
|
+
if (child.type !== "code") continue;
|
|
254
|
+
const lang = (child.lang ?? "").toLowerCase();
|
|
255
|
+
if (lang !== "csv" && lang !== "tsv") continue;
|
|
256
|
+
children[i] = el("matrx-csv", { dataSource: child.value ?? "", dataDelimiter: lang === "tsv" ? "tab" : "comma" }, [], "matrxCsv");
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
function footnoteIds(tree) {
|
|
261
|
+
const defined = /* @__PURE__ */ new Set();
|
|
262
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
263
|
+
const visit = (node) => {
|
|
264
|
+
if (node.type === "footnoteDefinition" && node.identifier) defined.add(node.identifier.toLowerCase());
|
|
265
|
+
if (node.type === "footnoteReference" && node.identifier) referenced.add(node.identifier.toLowerCase());
|
|
266
|
+
node.children?.forEach(visit);
|
|
267
|
+
};
|
|
268
|
+
visit(tree);
|
|
269
|
+
return { defined, referenced };
|
|
270
|
+
}
|
|
271
|
+
function renderFootnoteSection(tree, numbers) {
|
|
272
|
+
if (!numbers) return;
|
|
273
|
+
const children = tree.children ?? [];
|
|
274
|
+
const isSection = children.some((c) => c.type === "html" && (c.value ?? "").trim() === DOCUMENT_FOOTNOTES_MARKER);
|
|
275
|
+
const notes = [];
|
|
276
|
+
const kept = [];
|
|
277
|
+
for (const child of children) {
|
|
278
|
+
if (child.type === "html" && (child.value ?? "").trim() === DOCUMENT_FOOTNOTES_MARKER) continue;
|
|
279
|
+
const n = child.type === "footnoteDefinition" && child.identifier ? numbers.get(child.identifier.toLowerCase()) : void 0;
|
|
280
|
+
if (n === void 0) {
|
|
281
|
+
kept.push(child);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
if (isSection && !notes.some((note) => note.n === n)) notes.push({ n, def: child });
|
|
285
|
+
}
|
|
286
|
+
tree.children = kept;
|
|
287
|
+
if (notes.length === 0) return;
|
|
288
|
+
notes.sort((a, b) => a.n - b.n);
|
|
289
|
+
const items = notes.map(({ n, def }) => {
|
|
290
|
+
const id = encodeURIComponent((def.identifier ?? "").toLowerCase());
|
|
291
|
+
const back = el(
|
|
292
|
+
"a",
|
|
293
|
+
{ href: `#user-content-fnref-${id}`, dataFootnoteBackref: "", ariaLabel: `Back to reference ${n}`, className: ["data-footnote-backref"] },
|
|
294
|
+
[text("\u21A9")]
|
|
295
|
+
);
|
|
296
|
+
const body = [...def.children ?? []];
|
|
297
|
+
const tail = body[body.length - 1];
|
|
298
|
+
if (tail?.type === "paragraph") {
|
|
299
|
+
body[body.length - 1] = { ...tail, children: [...tail.children ?? [], text(" "), back] };
|
|
300
|
+
} else {
|
|
301
|
+
body.push(back);
|
|
302
|
+
}
|
|
303
|
+
return el("li", { id: `user-content-fn-${id}`, value: n }, body);
|
|
304
|
+
});
|
|
305
|
+
tree.children.push(
|
|
306
|
+
el("section", { dataFootnotes: true, className: ["footnotes"] }, [
|
|
307
|
+
el("h2", { id: "footnote-label", className: ["sr-only"] }, [text("Footnotes")]),
|
|
308
|
+
el("ol", {}, items)
|
|
309
|
+
])
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
function unwrapStandaloneEmbeds(tree) {
|
|
313
|
+
walkParents(tree, (parent) => {
|
|
314
|
+
const children = parent.children ?? [];
|
|
315
|
+
for (let i = 0; i < children.length; i++) {
|
|
316
|
+
const child = children[i];
|
|
317
|
+
if (child.type !== "paragraph") continue;
|
|
318
|
+
const meaningful = (child.children ?? []).filter((n) => !(n.type === "text" && !(n.value ?? "").trim()));
|
|
319
|
+
const only = meaningful.length === 1 ? meaningful[0] : null;
|
|
320
|
+
if (only?.data?.hName === "matrx-embed") {
|
|
321
|
+
only.data.hProperties = { ...only.data.hProperties ?? {}, dataBlock: true };
|
|
322
|
+
children[i] = only;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
function remarkMatrxSyntax(options = {}) {
|
|
328
|
+
const numbering = options.numbering ?? null;
|
|
329
|
+
return (tree, file) => {
|
|
330
|
+
stripFrontmatter(tree, file);
|
|
331
|
+
transformContainers(tree, file);
|
|
332
|
+
tagDefinitionLists(tree);
|
|
333
|
+
const abbrs = collectAbbreviations(tree, file);
|
|
334
|
+
applyHeadingIds(tree);
|
|
335
|
+
applyTocMarkers(tree, file);
|
|
336
|
+
titledImageFigures(tree);
|
|
337
|
+
const xrefs = numberTargets(tree, numbering);
|
|
338
|
+
resolveMathRefs(tree, xrefs);
|
|
339
|
+
const { defined } = footnoteIds(tree);
|
|
340
|
+
const ctx = { xrefs, footnotes: defined, documentFootnotes: numbering?.footnotes };
|
|
341
|
+
transformMentions(tree);
|
|
342
|
+
transformInline(tree, ctx);
|
|
343
|
+
unwrapStandaloneEmbeds(tree);
|
|
344
|
+
applyAbbreviations(tree, abbrs);
|
|
345
|
+
applyCsvFences(tree);
|
|
346
|
+
renderFootnoteSection(tree, numbering?.footnotes ?? null);
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
export {
|
|
350
|
+
remarkMatrxSyntax as default
|
|
351
|
+
};
|