@ai-matrx/rich-content 0.0.0 → 0.2.3
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 +80 -0
- package/LICENSE +1 -1
- package/README.md +58 -3
- 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/math-vendor-LICENSE-NOTICE.md +18 -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 +132 -5
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { parse as parseYaml } from "yaml";
|
|
2
|
+
import { parse as parseToml } from "smol-toml";
|
|
3
|
+
const OPEN = { "---": "yaml", "+++": "toml" };
|
|
4
|
+
function splitFrontmatter(source) {
|
|
5
|
+
if (!source) return null;
|
|
6
|
+
const bom = source.charCodeAt(0) === 65279 ? 1 : 0;
|
|
7
|
+
const firstBreak = source.indexOf("\n");
|
|
8
|
+
if (firstBreak < 0) return null;
|
|
9
|
+
const opener = source.slice(bom, firstBreak).replace(/\r$/, "");
|
|
10
|
+
const format = OPEN[opener];
|
|
11
|
+
if (!format) return null;
|
|
12
|
+
let pos = firstBreak + 1;
|
|
13
|
+
while (pos <= source.length) {
|
|
14
|
+
const next = source.indexOf("\n", pos);
|
|
15
|
+
const lineEnd = next < 0 ? source.length : next;
|
|
16
|
+
const line = source.slice(pos, lineEnd).replace(/\r$/, "");
|
|
17
|
+
if (line === opener || format === "yaml" && line === "...") {
|
|
18
|
+
const end = next < 0 ? source.length : next + 1;
|
|
19
|
+
return {
|
|
20
|
+
format,
|
|
21
|
+
raw: source.slice(0, end),
|
|
22
|
+
inner: source.slice(firstBreak + 1, pos).replace(/\r?\n$/, ""),
|
|
23
|
+
body: source.slice(end)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (next < 0) break;
|
|
27
|
+
pos = next + 1;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function hasUnclosedFrontmatter(source) {
|
|
32
|
+
if (!/^(---|\+\+\+)(\r?\n|$)/.test(source)) return false;
|
|
33
|
+
return splitFrontmatter(source) === null;
|
|
34
|
+
}
|
|
35
|
+
const EMPTY = { properties: {}, format: null, raw: null, error: null };
|
|
36
|
+
function extractFrontmatter(source) {
|
|
37
|
+
const split = splitFrontmatter(source);
|
|
38
|
+
if (!split) return EMPTY;
|
|
39
|
+
try {
|
|
40
|
+
const parsed = split.format === "yaml" ? parseYaml(split.inner) : parseToml(split.inner);
|
|
41
|
+
if (parsed === null || parsed === void 0) {
|
|
42
|
+
return { properties: {}, format: split.format, raw: split.raw, error: null };
|
|
43
|
+
}
|
|
44
|
+
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
45
|
+
return {
|
|
46
|
+
properties: {},
|
|
47
|
+
format: split.format,
|
|
48
|
+
raw: split.raw,
|
|
49
|
+
error: `The ${split.format.toUpperCase()} front matter is not a set of "key: value" properties.`
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
properties: parsed,
|
|
54
|
+
format: split.format,
|
|
55
|
+
raw: split.raw,
|
|
56
|
+
error: null
|
|
57
|
+
};
|
|
58
|
+
} catch (err) {
|
|
59
|
+
const why = err instanceof Error ? err.message.split("\n")[0] : String(err);
|
|
60
|
+
return {
|
|
61
|
+
properties: {},
|
|
62
|
+
format: split.format,
|
|
63
|
+
raw: split.raw,
|
|
64
|
+
error: `The ${split.format.toUpperCase()} front matter could not be read: ${why}`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
extractFrontmatter,
|
|
70
|
+
hasUnclosedFrontmatter,
|
|
71
|
+
splitFrontmatter
|
|
72
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GFM's ONE table-cell rule for pipes (spec example 200; GitHub renders it so):
|
|
3
|
+
* a row is split into cells FIRST, then the `\|` that kept a pipe inside a
|
|
4
|
+
* cell is unescaped — inside code spans too. Every surface that shows a table
|
|
5
|
+
* cell goes through this: Studio/Preview (remark-table-code-pipes, on code in
|
|
6
|
+
* a table cell), the chat and artifact table (StreamingTableRenderer, on each
|
|
7
|
+
* cell's inline source before the inline core reads it) and the table writer's
|
|
8
|
+
* read-back (rich-editor/core/table-source). verify-RC-B4 R4-3, R5-2.
|
|
9
|
+
* The rule itself lives in @ai-matrx/content-ir/source; this is its door here.
|
|
10
|
+
*/
|
|
11
|
+
export { unescapeCellPipes } from "@ai-matrx/content-ir/source";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { KBD_CLASS } from "./containers.js";
|
|
2
|
+
import { type MNode } from "./mdast-helpers.js";
|
|
3
|
+
/** What the numbering pass knows about each label in this document. */
|
|
4
|
+
export interface XrefTarget {
|
|
5
|
+
kind: "fig" | "tbl" | "eq" | "sec";
|
|
6
|
+
/** "Figure 2", "Table 1", "(3)", or the section's heading text. */
|
|
7
|
+
display: string;
|
|
8
|
+
}
|
|
9
|
+
export interface InlineContext {
|
|
10
|
+
xrefs: Map<string, XrefTarget>;
|
|
11
|
+
/** Footnote identifiers DEFINED in this tree (a `[^x]` left as text is defined elsewhere). */
|
|
12
|
+
footnotes: Set<string>;
|
|
13
|
+
/**
|
|
14
|
+
* The document's footnote numbers (DocumentNumbering.footnotes): a `[^x]`
|
|
15
|
+
* left as text becomes a reference only when the DOCUMENT defines and cites
|
|
16
|
+
* `x`; an undefined label stays text, as GFM leaves it.
|
|
17
|
+
*/
|
|
18
|
+
documentFootnotes?: ReadonlyMap<string, number>;
|
|
19
|
+
}
|
|
20
|
+
export declare function xrefNode(label: string, kindHint: XrefTarget["kind"] | null, ctx: InlineContext, style: "at" | "eqref" | "ref"): MNode;
|
|
21
|
+
/** Split one string into text + element nodes. */
|
|
22
|
+
export declare function scanInline(value: string, ctx: InlineContext): MNode[] | null;
|
|
23
|
+
/** Run the inline scanner over every eligible text node in the tree. */
|
|
24
|
+
export declare function transformInline(node: MNode, ctx: InlineContext): void;
|
|
25
|
+
/** `:kbd[…]`'s class, re-exported for the raw `<kbd>` default element. */
|
|
26
|
+
export { KBD_CLASS };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { KBD_CLASS, MARK_CLASS } from "./containers.js";
|
|
2
|
+
import { el, text } from "./mdast-helpers.js";
|
|
3
|
+
const XREF_PREFIX = { fig: "fig", tbl: "tbl", eq: "eq", sec: "sec" };
|
|
4
|
+
const XREF_WORD = { fig: "figure", tbl: "table", eq: "equation", sec: "section" };
|
|
5
|
+
function xrefNode(label, kindHint, ctx, style) {
|
|
6
|
+
const target = ctx.xrefs.get(label);
|
|
7
|
+
const kind = target?.kind ?? kindHint ?? "sec";
|
|
8
|
+
let shown;
|
|
9
|
+
if (target) {
|
|
10
|
+
shown = style === "ref" && target.kind === "eq" ? target.display.replace(/[()]/g, "") : target.display;
|
|
11
|
+
} else {
|
|
12
|
+
shown = style === "at" ? `@${label}` : `(${label})`;
|
|
13
|
+
}
|
|
14
|
+
return el(
|
|
15
|
+
"matrx-xref",
|
|
16
|
+
{
|
|
17
|
+
href: `#${label}`,
|
|
18
|
+
dataXref: label,
|
|
19
|
+
dataXrefKind: kind,
|
|
20
|
+
dataXrefStyle: style,
|
|
21
|
+
dataXrefResolved: target ? "true" : "false",
|
|
22
|
+
title: target ? void 0 : `No ${XREF_WORD[kind]} labelled "${label}" in this document`
|
|
23
|
+
},
|
|
24
|
+
[text(shown)]
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function wikiTarget(inner) {
|
|
28
|
+
const cut = inner.search(/\\?\|/);
|
|
29
|
+
if (cut < 0) return { target: inner.trim(), alias: null };
|
|
30
|
+
const sepLength = inner[cut] === "\\" ? 2 : 1;
|
|
31
|
+
return { target: inner.slice(0, cut).trim(), alias: inner.slice(cut + sepLength).trim() || null };
|
|
32
|
+
}
|
|
33
|
+
const RULES = [
|
|
34
|
+
{
|
|
35
|
+
// Wikilink / embed. Target: no brackets, no newline.
|
|
36
|
+
re: /(!?)\[\[([^[\]\n]+?)\]\]/g,
|
|
37
|
+
build: (m) => {
|
|
38
|
+
const { target, alias } = wikiTarget(m[2] ?? "");
|
|
39
|
+
if (!target) return null;
|
|
40
|
+
const embed = m[1] === "!";
|
|
41
|
+
return el(
|
|
42
|
+
embed ? "matrx-embed" : "matrx-wikilink",
|
|
43
|
+
{ dataTarget: target, ...alias ? { dataAlias: alias } : {} },
|
|
44
|
+
[text(alias ?? target)]
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
re: /(^|[^\w@])@(fig|tbl|eq|sec):([\w.-]*[\w])/g,
|
|
50
|
+
build: (m, ctx) => {
|
|
51
|
+
const label = `${m[2]}:${m[3]}`;
|
|
52
|
+
return xrefNode(label, XREF_PREFIX[m[2] ?? ""] ?? null, ctx, "at");
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
re: /\\(eqref|ref)\{([^{}\s]+)\}/g,
|
|
57
|
+
build: (m, ctx) => xrefNode(m[2] ?? "", m[1] === "eqref" ? "eq" : null, ctx, m[1] === "eqref" ? "eqref" : "ref")
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
// ==highlight== — no space just inside either marker, never part of `===`.
|
|
61
|
+
re: /(?<![=\\])==(?=[^\s=])([^\n]*?[^\s=\\])==(?!=)/g,
|
|
62
|
+
build: (m) => el("mark", { className: MARK_CLASS }, [text(m[1] ?? "")], "matrxMark")
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
// x^2^ — Pandoc superscript: no whitespace inside.
|
|
66
|
+
re: /(?<![\\^])\^([^\s^]+?)\^/g,
|
|
67
|
+
build: (m) => el("sup", {}, [text(m[1] ?? "")], "matrxSup")
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
// H~2~O — Pandoc subscript (single tilde; GFM's ~~strike~~ is parsed first).
|
|
71
|
+
re: /(?<![\\~])~([^\s~]+?)~(?!~)/g,
|
|
72
|
+
build: (m) => el("sub", {}, [text(m[1] ?? "")], "matrxSub")
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
// A footnote reference whose definition lives in another rendered block
|
|
76
|
+
// (the document defines it; an undefined `[^x]` stays text).
|
|
77
|
+
re: /\[\^([^\]\s]+)\](?!:)/g,
|
|
78
|
+
build: (m, ctx) => {
|
|
79
|
+
const id = m[1] ?? "";
|
|
80
|
+
if (ctx.footnotes.has(id.toLowerCase()) || !ctx.documentFootnotes?.has(id.toLowerCase())) return null;
|
|
81
|
+
return el("sup", { className: ["matrx-fnref"] }, [
|
|
82
|
+
// The id is the note's back-link target when this is the first reference.
|
|
83
|
+
el("a", { href: `#user-content-fn-${encodeURIComponent(id.toLowerCase())}`, id: `user-content-fnref-${encodeURIComponent(id.toLowerCase())}`, dataFootnoteRef: true, ariaDescribedBy: "footnote-label" }, [text(id)])
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
function leadingContext(m, rule) {
|
|
89
|
+
return rule === RULES[1] ? m[1] ?? "" : "";
|
|
90
|
+
}
|
|
91
|
+
function scanInline(value, ctx) {
|
|
92
|
+
if (!value) return null;
|
|
93
|
+
if (!/[[=^~@\\]/.test(value)) return null;
|
|
94
|
+
const out = [];
|
|
95
|
+
let pos = 0;
|
|
96
|
+
let changed = false;
|
|
97
|
+
while (pos < value.length) {
|
|
98
|
+
let best = null;
|
|
99
|
+
for (const rule of RULES) {
|
|
100
|
+
rule.re.lastIndex = pos;
|
|
101
|
+
const m = rule.re.exec(value);
|
|
102
|
+
if (!m) continue;
|
|
103
|
+
const start2 = m.index + leadingContext(m, rule).length;
|
|
104
|
+
if (!best || start2 < best.m.index + leadingContext(best.m, best.rule).length) best = { m, rule };
|
|
105
|
+
}
|
|
106
|
+
if (!best) break;
|
|
107
|
+
const lead = leadingContext(best.m, best.rule);
|
|
108
|
+
const start = best.m.index + lead.length;
|
|
109
|
+
const end = best.m.index + best.m[0].length;
|
|
110
|
+
const node = best.rule.build(best.m, ctx);
|
|
111
|
+
if (!node) {
|
|
112
|
+
out.push(text(value.slice(pos, start + 1)));
|
|
113
|
+
pos = start + 1;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (start > pos) out.push(text(value.slice(pos, start)));
|
|
117
|
+
if (node.type === "matrxMark" || node.type === "matrxSup" || node.type === "matrxSub") {
|
|
118
|
+
const inner = node.children?.[0]?.value ?? "";
|
|
119
|
+
const nested = scanInline(inner, ctx);
|
|
120
|
+
if (nested) node.children = nested;
|
|
121
|
+
}
|
|
122
|
+
out.push(node);
|
|
123
|
+
pos = end;
|
|
124
|
+
changed = true;
|
|
125
|
+
}
|
|
126
|
+
if (!changed) return null;
|
|
127
|
+
if (pos < value.length) out.push(text(value.slice(pos)));
|
|
128
|
+
const merged = [];
|
|
129
|
+
for (const n of out) {
|
|
130
|
+
const prev = merged[merged.length - 1];
|
|
131
|
+
if (n.type === "text" && prev?.type === "text") prev.value = (prev.value ?? "") + (n.value ?? "");
|
|
132
|
+
else merged.push(n);
|
|
133
|
+
}
|
|
134
|
+
return merged;
|
|
135
|
+
}
|
|
136
|
+
const SKIP_TYPES = /* @__PURE__ */ new Set(["link", "linkReference", "inlineCode", "code", "math", "inlineMath", "html", "matrxMark", "matrxSup", "matrxSub"]);
|
|
137
|
+
const SKIP_ELEMENTS = /* @__PURE__ */ new Set(["matrx-wikilink", "matrx-embed", "matrx-xref", "matrx-mention", "a", "kbd", "code", "matrx-csv"]);
|
|
138
|
+
function transformInline(node, ctx) {
|
|
139
|
+
const children = node.children;
|
|
140
|
+
if (!children || SKIP_TYPES.has(node.type)) return;
|
|
141
|
+
if (node.data?.hName && SKIP_ELEMENTS.has(node.data.hName)) return;
|
|
142
|
+
let next = null;
|
|
143
|
+
children.forEach((child, i) => {
|
|
144
|
+
if (child.type === "text") {
|
|
145
|
+
const replaced = scanInline(child.value ?? "", ctx);
|
|
146
|
+
if (replaced) {
|
|
147
|
+
next ??= children.slice(0, i);
|
|
148
|
+
next.push(...replaced);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
transformInline(child, ctx);
|
|
153
|
+
}
|
|
154
|
+
next?.push(child);
|
|
155
|
+
});
|
|
156
|
+
if (next) node.children = next;
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
KBD_CLASS,
|
|
160
|
+
scanInline,
|
|
161
|
+
transformInline,
|
|
162
|
+
xrefNode
|
|
163
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linear-time stand-ins for regexes on the markdown render hot path that
|
|
3
|
+
* backtracked super-linearly (kind-never-raw round 11, F1 sweep). Each
|
|
4
|
+
* function is EXACTLY the regex named in its doc (differentially fuzzed
|
|
5
|
+
* against it) and runs in time linear in its input. Guard:
|
|
6
|
+
* `components/markdown-core/__tests__/regex-linear-time.guard.test.ts`.
|
|
7
|
+
*/
|
|
8
|
+
/** Exactly `text.replace(/[ \t]+$/, "")`. */
|
|
9
|
+
export declare function trimTrailingSpaceTab(text: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Exactly `/[ \t]*\{#([\w:.-]+)\}[ \t]*$/.exec(text)` as `{ index, id }`: a
|
|
12
|
+
* trailing `{#id}` attribute (an id never holds `{` or `}`, so it is the LAST
|
|
13
|
+
* `{#`), its match starting at the spaces before it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function trailingHeadingId(text: string): {
|
|
16
|
+
index: number;
|
|
17
|
+
id: string;
|
|
18
|
+
} | null;
|
|
19
|
+
/**
|
|
20
|
+
* Exactly `/^#{1,6}[ \t]+(.*?)[ \t]*\{#(sec:[\w:.-]+)\}[ \t]*$/.exec(line)` as
|
|
21
|
+
* `[title, id]` (title = capture 1, the spaces around it excluded).
|
|
22
|
+
*/
|
|
23
|
+
export declare function sectionHeading(line: string): [string, string] | null;
|
|
24
|
+
/**
|
|
25
|
+
* Exactly capture 1 of `/^(#{1,6}[ \t].*?)[ \t]*\{#[^}\n]*$/.exec(line)` — a
|
|
26
|
+
* heading whose `{#id` attribute is still arriving — or null.
|
|
27
|
+
*/
|
|
28
|
+
export declare function unfinishedHeadingIdHead(line: string): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Exactly `text.replace(/(!?)\[([^\]\n]*)\]\[([^\]\n]+)\]/g, fn)` (the
|
|
31
|
+
* reference-style use `![alt][id]` / `[text][id]`), linear: every `[` of one
|
|
32
|
+
* label run closes at the same `]`, so a failed run is skipped whole.
|
|
33
|
+
*/
|
|
34
|
+
export declare function replaceReferenceUses(text: string, fn: (whole: string, bang: string, label: string, id: string, offset: number) => string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Exactly `/(?<!\])(!?)\[([^\]\n]*)\](\[[^\]\n]*)?$/.exec(text)` as
|
|
37
|
+
* `{ index, whole, bang, label, reference }` — a closed `[text]` / `![alt]`
|
|
38
|
+
* at the very end, optionally followed by an unfinished `[id`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function trailingBracketedTail(text: string): {
|
|
41
|
+
index: number;
|
|
42
|
+
whole: string;
|
|
43
|
+
bang: string;
|
|
44
|
+
label: string;
|
|
45
|
+
reference: string | undefined;
|
|
46
|
+
} | null;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
const isSpaceTab = (ch) => ch === " " || ch === " ";
|
|
2
|
+
const isLineTerminator = (ch) => ch === "\n" || ch === "\r" || ch === "\u2028" || ch === "\u2029";
|
|
3
|
+
const ID_TEXT = /^[\w:.-]+$/;
|
|
4
|
+
function trimTrailingSpaceTab(text) {
|
|
5
|
+
let end = text.length;
|
|
6
|
+
while (end > 0 && isSpaceTab(text[end - 1])) end--;
|
|
7
|
+
return end === text.length ? text : text.slice(0, end);
|
|
8
|
+
}
|
|
9
|
+
function trailingHeadingId(text) {
|
|
10
|
+
const body = trimTrailingSpaceTab(text);
|
|
11
|
+
if (!body.endsWith("}")) return null;
|
|
12
|
+
const open = body.lastIndexOf("{#");
|
|
13
|
+
if (open === -1) return null;
|
|
14
|
+
const id = body.slice(open + 2, -1);
|
|
15
|
+
if (!ID_TEXT.test(id)) return null;
|
|
16
|
+
let index = open;
|
|
17
|
+
while (index > 0 && isSpaceTab(body[index - 1])) index--;
|
|
18
|
+
return { index, id };
|
|
19
|
+
}
|
|
20
|
+
function atxHeadLength(line) {
|
|
21
|
+
let hashes = 0;
|
|
22
|
+
while (line[hashes] === "#") hashes++;
|
|
23
|
+
if (hashes < 1 || hashes > 6 || !isSpaceTab(line[hashes])) return -1;
|
|
24
|
+
return hashes;
|
|
25
|
+
}
|
|
26
|
+
function sectionHeading(line) {
|
|
27
|
+
const hashes = atxHeadLength(line);
|
|
28
|
+
if (hashes < 0) return null;
|
|
29
|
+
const tail = trailingHeadingId(line);
|
|
30
|
+
if (!tail || !tail.id.startsWith("sec:") || tail.id.length <= 4) return null;
|
|
31
|
+
let start = hashes;
|
|
32
|
+
while (isSpaceTab(line[start])) start++;
|
|
33
|
+
if (start === hashes) return null;
|
|
34
|
+
const title = start >= tail.index ? "" : line.slice(start, tail.index);
|
|
35
|
+
for (const ch of title) if (isLineTerminator(ch)) return null;
|
|
36
|
+
return [title, tail.id];
|
|
37
|
+
}
|
|
38
|
+
function unfinishedHeadingIdHead(line) {
|
|
39
|
+
const hashes = atxHeadLength(line);
|
|
40
|
+
if (hashes < 0) return null;
|
|
41
|
+
const minEnd = hashes + 1;
|
|
42
|
+
let lastStop = -1;
|
|
43
|
+
for (let i = line.length - 1; i >= 0; i--) {
|
|
44
|
+
if (line[i] === "}" || line[i] === "\n") {
|
|
45
|
+
lastStop = i;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const open = line.indexOf("{#", Math.max(lastStop + 1, minEnd));
|
|
50
|
+
if (open === -1) return null;
|
|
51
|
+
let end = open;
|
|
52
|
+
while (end > minEnd && isSpaceTab(line[end - 1])) end--;
|
|
53
|
+
for (let i = minEnd; i < end; i++) if (isLineTerminator(line[i])) return null;
|
|
54
|
+
return line.slice(0, end);
|
|
55
|
+
}
|
|
56
|
+
function forwardFinder(text, chars) {
|
|
57
|
+
let askedFrom = -1;
|
|
58
|
+
let answer = -1;
|
|
59
|
+
return (from) => {
|
|
60
|
+
if (askedFrom >= 0 && from >= askedFrom && (answer === -1 || answer >= from)) return answer;
|
|
61
|
+
askedFrom = from;
|
|
62
|
+
answer = -1;
|
|
63
|
+
for (let i = from; i < text.length; i++) {
|
|
64
|
+
if (chars.includes(text[i])) {
|
|
65
|
+
answer = i;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return answer;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function replaceReferenceUses(text, fn) {
|
|
73
|
+
if (!text.includes("][")) return text;
|
|
74
|
+
const stop = forwardFinder(text, "]\n");
|
|
75
|
+
let out = "";
|
|
76
|
+
let copied = 0;
|
|
77
|
+
let at = text.indexOf("[");
|
|
78
|
+
while (at !== -1) {
|
|
79
|
+
const labelEnd = stop(at + 1);
|
|
80
|
+
if (labelEnd === -1) break;
|
|
81
|
+
let matched = false;
|
|
82
|
+
if (text[labelEnd] === "]" && text[labelEnd + 1] === "[") {
|
|
83
|
+
const idEnd = stop(labelEnd + 2);
|
|
84
|
+
if (idEnd > labelEnd + 2 && text[idEnd] === "]") {
|
|
85
|
+
const start = at > copied && text[at - 1] === "!" ? at - 1 : at;
|
|
86
|
+
const bang = start < at ? "!" : "";
|
|
87
|
+
out += text.slice(copied, start) + fn(text.slice(start, idEnd + 1), bang, text.slice(at + 1, labelEnd), text.slice(labelEnd + 2, idEnd), start);
|
|
88
|
+
copied = idEnd + 1;
|
|
89
|
+
matched = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
at = text.indexOf("[", matched ? copied : Math.max(at + 1, labelEnd));
|
|
93
|
+
}
|
|
94
|
+
return copied === 0 ? text : out + text.slice(copied);
|
|
95
|
+
}
|
|
96
|
+
function trailingBracketedTail(text) {
|
|
97
|
+
const lastStop = (end) => {
|
|
98
|
+
for (let i = end - 1; i >= 0; i--) if (text[i] === "]" || text[i] === "\n") return i;
|
|
99
|
+
return -1;
|
|
100
|
+
};
|
|
101
|
+
let close;
|
|
102
|
+
let reference;
|
|
103
|
+
if (text.endsWith("]")) {
|
|
104
|
+
close = text.length - 1;
|
|
105
|
+
} else {
|
|
106
|
+
const stop = lastStop(text.length);
|
|
107
|
+
if (stop === -1 || text[stop] !== "]" || text[stop + 1] !== "[") return null;
|
|
108
|
+
close = stop;
|
|
109
|
+
reference = text.slice(stop + 1);
|
|
110
|
+
}
|
|
111
|
+
for (let x = lastStop(close) + 1; x < close; x++) {
|
|
112
|
+
if (text[x - 1] === "]") continue;
|
|
113
|
+
if (text[x] === "[") {
|
|
114
|
+
return { index: x, whole: text.slice(x), bang: "", label: text.slice(x + 1, close), reference };
|
|
115
|
+
}
|
|
116
|
+
if (text[x] === "!" && text[x + 1] === "[" && x + 1 < close) {
|
|
117
|
+
return { index: x, whole: text.slice(x), bang: "!", label: text.slice(x + 2, close), reference };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
replaceReferenceUses,
|
|
124
|
+
sectionHeading,
|
|
125
|
+
trailingBracketedTail,
|
|
126
|
+
trailingHeadingId,
|
|
127
|
+
trimTrailingSpaceTab,
|
|
128
|
+
unfinishedHeadingIdHead
|
|
129
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface MData {
|
|
2
|
+
hName?: string;
|
|
3
|
+
hProperties?: Record<string, unknown>;
|
|
4
|
+
hChildren?: unknown[];
|
|
5
|
+
directiveLabel?: boolean;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
export interface MNode {
|
|
9
|
+
type: string;
|
|
10
|
+
value?: string;
|
|
11
|
+
children?: MNode[];
|
|
12
|
+
data?: MData;
|
|
13
|
+
position?: {
|
|
14
|
+
start: {
|
|
15
|
+
offset?: number;
|
|
16
|
+
};
|
|
17
|
+
end: {
|
|
18
|
+
offset?: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
name?: string;
|
|
22
|
+
attributes?: Record<string, string | null | undefined> | null;
|
|
23
|
+
lang?: string | null;
|
|
24
|
+
meta?: string | null;
|
|
25
|
+
depth?: number;
|
|
26
|
+
identifier?: string;
|
|
27
|
+
label?: string | null;
|
|
28
|
+
checked?: boolean | null;
|
|
29
|
+
url?: string;
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
export interface SyntaxFile {
|
|
33
|
+
value?: unknown;
|
|
34
|
+
data?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
/** An mdast node that becomes the hast element `tag` with `props`. */
|
|
37
|
+
export declare function el(tag: string, props: Record<string, unknown>, children?: MNode[], type?: string): MNode;
|
|
38
|
+
export declare function text(value: string): MNode;
|
|
39
|
+
/** Plain text of a node (mdast-util-to-string semantics, minus images' alt). */
|
|
40
|
+
export declare function toText(node: MNode | undefined): string;
|
|
41
|
+
/** The node's own source text, when the parser recorded where it came from. */
|
|
42
|
+
export declare function rawOf(node: MNode, file: SyntaxFile | undefined): string | null;
|
|
43
|
+
/** Merge adjacent text nodes (after a pass restored literal text). */
|
|
44
|
+
export declare function mergeText(children: MNode[]): MNode[];
|
|
45
|
+
/** Depth-first, pre-order walk over every parent's children array. */
|
|
46
|
+
export declare function walkParents(node: MNode, visit: (parent: MNode) => void): void;
|
|
47
|
+
/** Id-safe slug for a label the author wrote (`fig:growth` stays `fig:growth`). */
|
|
48
|
+
export declare function safeId(label: string): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function el(tag, props, children = [], type = "matrxElement") {
|
|
2
|
+
return { type, data: { hName: tag, hProperties: props }, children };
|
|
3
|
+
}
|
|
4
|
+
function text(value) {
|
|
5
|
+
return { type: "text", value };
|
|
6
|
+
}
|
|
7
|
+
function toText(node) {
|
|
8
|
+
if (!node) return "";
|
|
9
|
+
if (typeof node.value === "string") return node.value;
|
|
10
|
+
if (!node.children) return "";
|
|
11
|
+
return node.children.map(toText).join("");
|
|
12
|
+
}
|
|
13
|
+
function rawOf(node, file) {
|
|
14
|
+
const source = typeof file?.value === "string" ? file.value : null;
|
|
15
|
+
const start = node.position?.start.offset;
|
|
16
|
+
const end = node.position?.end.offset;
|
|
17
|
+
if (source === null || start === void 0 || end === void 0) return null;
|
|
18
|
+
return source.slice(start, end);
|
|
19
|
+
}
|
|
20
|
+
function mergeText(children) {
|
|
21
|
+
const out = [];
|
|
22
|
+
for (const child of children) {
|
|
23
|
+
const prev = out[out.length - 1];
|
|
24
|
+
if (child.type === "text" && prev && prev.type === "text" && !prev.data && !child.data) {
|
|
25
|
+
out[out.length - 1] = { type: "text", value: (prev.value ?? "") + (child.value ?? "") };
|
|
26
|
+
} else {
|
|
27
|
+
out.push(child);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
function walkParents(node, visit) {
|
|
33
|
+
if (!node.children) return;
|
|
34
|
+
visit(node);
|
|
35
|
+
for (const child of node.children) walkParents(child, visit);
|
|
36
|
+
}
|
|
37
|
+
function safeId(label) {
|
|
38
|
+
return label.trim().replace(/\s+/g, "-").replace(/[^\w:.\-]/g, "");
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
el,
|
|
42
|
+
mergeText,
|
|
43
|
+
rawOf,
|
|
44
|
+
safeId,
|
|
45
|
+
text,
|
|
46
|
+
toText,
|
|
47
|
+
walkParents
|
|
48
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { el, text, toText } from "./mdast-helpers.js";
|
|
2
|
+
import { isUuidShape } from "@ai-matrx/kit/uuid";
|
|
3
|
+
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4
|
+
const SCHEME = /^([a-z][a-z0-9_]*):(.+)$/;
|
|
5
|
+
function mentionFor(link) {
|
|
6
|
+
const m = SCHEME.exec(link.url ?? "");
|
|
7
|
+
if (!m) return null;
|
|
8
|
+
const scheme = m[1];
|
|
9
|
+
const value = m[2];
|
|
10
|
+
const label = toText(link).trim();
|
|
11
|
+
if (!label) return null;
|
|
12
|
+
if (scheme === "user") {
|
|
13
|
+
return isUuidShape(value) ? el("matrx-mention", { dataKind: "person", dataId: value.toLowerCase(), dataLabel: label }, [text(label)]) : null;
|
|
14
|
+
}
|
|
15
|
+
if (scheme === "date") {
|
|
16
|
+
return ISO_DATE.test(value) ? el("matrx-mention", { dataKind: "date", dataId: value, dataLabel: label }, [text(label)]) : null;
|
|
17
|
+
}
|
|
18
|
+
if (isUuidShape(value)) {
|
|
19
|
+
return el("matrx-wikilink", { dataTarget: `${scheme}:${value.toLowerCase()}`, dataAlias: label, dataMention: true }, [text(label)]);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
function transformMentions(node) {
|
|
24
|
+
const children = node.children;
|
|
25
|
+
if (!children || node.type === "link" || node.type === "inlineCode" || node.type === "code") return;
|
|
26
|
+
for (let i = 0; i < children.length; i++) {
|
|
27
|
+
const child = children[i];
|
|
28
|
+
const prev = children[i - 1];
|
|
29
|
+
if (child.type === "link" && prev?.type === "text" && (prev.value ?? "").endsWith("@")) {
|
|
30
|
+
const mention = mentionFor(child);
|
|
31
|
+
if (mention) {
|
|
32
|
+
prev.value = (prev.value ?? "").slice(0, -1);
|
|
33
|
+
children[i] = mention;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
transformMentions(child);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
transformMentions
|
|
42
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** `:::name` containers with their own rendering. */
|
|
2
|
+
export declare const CONTAINER_DIRECTIVES: Set<string>;
|
|
3
|
+
/** `::name` leaf directives. */
|
|
4
|
+
export declare const LEAF_DIRECTIVES: Set<string>;
|
|
5
|
+
/** `:name[text]{…}` inline directives. */
|
|
6
|
+
export declare const TEXT_DIRECTIVES: Set<string>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const CONTAINER_DIRECTIVES = /* @__PURE__ */ new Set([
|
|
2
|
+
"details",
|
|
3
|
+
"columns",
|
|
4
|
+
"column",
|
|
5
|
+
"tabs",
|
|
6
|
+
"tab",
|
|
7
|
+
"figure",
|
|
8
|
+
"table",
|
|
9
|
+
"aside",
|
|
10
|
+
"toc"
|
|
11
|
+
]);
|
|
12
|
+
const LEAF_DIRECTIVES = /* @__PURE__ */ new Set(["toc"]);
|
|
13
|
+
const TEXT_DIRECTIVES = /* @__PURE__ */ new Set(["span", "mark", "kbd", "abbr", "sup", "sub"]);
|
|
14
|
+
export {
|
|
15
|
+
CONTAINER_DIRECTIVES,
|
|
16
|
+
LEAF_DIRECTIVES,
|
|
17
|
+
TEXT_DIRECTIVES
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function rewriteContainerSpellings(source: string): string;
|