@dogsbay/format-myst 0.2.0-beta.101

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/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # @dogsbay/format-myst
2
+
3
+ Import [MyST Markdown](https://mystmd.org) — the Markdown flavour used by
4
+ [Sphinx `myst-parser`](https://myst-parser.readthedocs.io),
5
+ [Jupyter Book](https://jupyterbook.org), and
6
+ [`mystmd`](https://mystmd.org) — into Dogsbay.
7
+
8
+ MyST is CommonMark + Sphinx-style **directives**, **roles**, and
9
+ **targets**. This package translates those constructs to Dogsbay-MD and
10
+ reuses the canonical `@dogsbay/format-dogsbay-md` parser — no Python, no
11
+ new document-node types.
12
+
13
+ ## Use it via the CLI
14
+
15
+ ```bash
16
+ # Convert a MyST corpus to canonical Dogsbay-MD (pure content, no SSG)
17
+ npx dogsbay convert ./my-myst-docs --to dogsbay-md -o ./out
18
+
19
+ # One-way migrate to a scaffolded Dogsbay site (content/ + astro/ + config)
20
+ npx dogsbay migrate-myst ./my-myst-docs -o ./my-site
21
+ cd ./my-site && npx dogsbay site dev
22
+ ```
23
+
24
+ The format is auto-detected — a `myst.yml` / `_toc.yml`, or MyST-specific
25
+ syntax in the Markdown, is enough.
26
+
27
+ ## What it converts
28
+
29
+ - **Admonitions** (`{note}`, `{warning}`, `{tip}`, …) → callouts
30
+ - **sphinx-design** `{tab-set}`/`{tab-item}`, `{grid}`, `{dropdown}`,
31
+ `{card}` → tabs / grid / details / card
32
+ - **Code** `{code-block}` (with `:caption:` / `:linenos:`) → fenced code
33
+ - **Math** `{math}` and `$$…$$` → KaTeX; inline `$…$` and `` {math}`…` ``
34
+ - **Figures / images** `{figure}` / `{image}` → Markdown images + captions
35
+ - **Roles** `{ref}` `{doc}` `{eq}` `{sub}` `{sup}` `{abbr}` `{kbd}`
36
+ `{download}` `{file}` … → links / HTML / code
37
+ - **Targets** `(label)=` → heading `{#id}` anchors for cross-references
38
+ - **Version notes** `{versionadded}` / `{versionchanged}` / `{deprecated}`
39
+ → compact inline notes
40
+ - **Nav** from `_toc.yml`, `myst.yml`, `{toctree}`, or directory structure
41
+
42
+ Constructs that can't be cleanly mapped (`{list-table}`, `{include}`,
43
+ unknown directives/roles) are kept as best-effort content and recorded in a
44
+ per-page **ledger** — never silently dropped.
45
+
46
+ ## Programmatic API
47
+
48
+ ```ts
49
+ import { parseMyst, mystToDogsbayMd, loadMyst } from "@dogsbay/format-myst";
50
+
51
+ const { tree, markdown, ledger, toctree } = parseMyst(mystSource);
52
+ const { markdown } = mystToDogsbayMd(bodyOnly); // translate, no parse
53
+ const { pages, nav, navSource } = /* via the CLI plugin */;
54
+ ```
55
+
56
+ See [plans/format-myst.md](../../plans/format-myst.md) for the full
57
+ construct-mapping table.
58
+
59
+ ## License
60
+
61
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { FormatPlugin, ExportPage, NavItem } from "@dogsbay/types";
2
+ export interface MystImportResult {
3
+ pages: ExportPage[];
4
+ nav: NavItem[];
5
+ /** Directory to mirror non-Markdown assets from. */
6
+ docsDir: string;
7
+ navSource: string;
8
+ }
9
+ export declare function importMyst(source: string, opts: Record<string, unknown>): Promise<MystImportResult>;
10
+ export declare const plugin: FormatPlugin;
11
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAW,MAAM,gBAAgB,CAAC;AAajF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CA8C3B;AAED,eAAO,MAAM,MAAM,EAAE,YAWpB,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * FormatPlugin for MyST Markdown as a source format.
3
+ *
4
+ * Orchestrates: detect corpus → loadMyst (config/TOC + page walk + nav) →
5
+ * translate each page (parseMyst) → assemble ExportPage[] + NavItem[].
6
+ *
7
+ * MyST is Markdown, so this plugin MUST be registered after GitBook/rST and
8
+ * before the generic dogsbay-md detector — `detectMyst` requires an explicit
9
+ * MyST config/TOC or MyST-specific syntax, so it won't claim a plain-Markdown
10
+ * or GitBook corpus.
11
+ */
12
+ import { existsSync, readFileSync } from "node:fs";
13
+ import { extractHeadings } from "@dogsbay/format-dogsbay-md";
14
+ import { parseMyst } from "./parse.js";
15
+ import { loadMyst, detectMyst } from "./loaders/load.js";
16
+ function prettify(slug) {
17
+ return slug
18
+ .split(/[-_/]/)
19
+ .filter(Boolean)
20
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
21
+ .join(" ");
22
+ }
23
+ export async function importMyst(source, opts) {
24
+ if (!existsSync(source)) {
25
+ throw new Error(`Source directory not found: ${source}`);
26
+ }
27
+ const hrefPrefix = typeof opts.hrefPrefix === "string" ? opts.hrefPrefix : "";
28
+ const { pages: pageSources, nav, docsDir, navSource } = loadMyst(source, { hrefPrefix });
29
+ const pages = [];
30
+ let failed = 0;
31
+ let ledgerTotal = 0;
32
+ for (const ps of pageSources) {
33
+ try {
34
+ const content = readFileSync(ps.filePath, "utf-8");
35
+ const { tree, frontmatter, body, ledger } = parseMyst(content);
36
+ ledgerTotal += ledger.length;
37
+ const headings = extractHeadings(tree);
38
+ const h1 = headings.find((h) => h.depth === 1);
39
+ const fmTitle = typeof frontmatter.title === "string" && frontmatter.title.trim()
40
+ ? frontmatter.title
41
+ : undefined;
42
+ const title = fmTitle || h1?.text || prettify(ps.slug.split("/").pop() ?? ps.slug);
43
+ pages.push({
44
+ slug: ps.slug,
45
+ title,
46
+ tree,
47
+ headings,
48
+ frontmatter,
49
+ meta: ledger.length ? { mystLedger: ledger } : {},
50
+ bodyMarkdown: body,
51
+ });
52
+ }
53
+ catch (err) {
54
+ failed += 1;
55
+ const msg = err instanceof Error ? err.message : String(err);
56
+ console.warn(`myst import: failed to convert ${ps.filePath} (slug "${ps.slug}"), skipping: ${msg}`);
57
+ }
58
+ }
59
+ if (failed > 0) {
60
+ console.warn(`myst import: ${failed} of ${pageSources.length} page(s) failed and were skipped`);
61
+ }
62
+ if (ledgerTotal > 0) {
63
+ console.warn(`myst import: ${ledgerTotal} construct(s) mapped with caveats (see per-page ledger)`);
64
+ }
65
+ return { pages, nav, docsDir, navSource };
66
+ }
67
+ export const plugin = {
68
+ name: "myst",
69
+ canImport: true,
70
+ canExport: false,
71
+ detectSource: (path) => detectMyst(path),
72
+ importOptions: [],
73
+ exportOptions: [],
74
+ async import(source, opts) {
75
+ const { pages, nav, docsDir } = await importMyst(source, opts);
76
+ return { pages, nav, contentRoot: docsDir };
77
+ },
78
+ };
79
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @dogsbay/format-myst — MyST Markdown format plugin. Imports MyST
3
+ * (Sphinx myst-parser / Jupyter Book / mystmd) corpora into TreeNode[] by
4
+ * translating MyST directives, roles, and targets to Dogsbay-MD, then
5
+ * parsing with the canonical dogsbay-md parser (zero new node types).
6
+ *
7
+ * See plans/format-myst.md.
8
+ */
9
+ export { parseMyst, type ParseMystResult } from "./parse.js";
10
+ export { mystToDogsbayMd, type TranslateResult, type TranslateLedgerEntry, } from "./translate.js";
11
+ export { loadMyst, detectMyst, walkMarkdown, pathToSlug, type MystLoadResult, type MystPageSource, } from "./loaders/load.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EACL,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @dogsbay/format-myst — MyST Markdown format plugin. Imports MyST
3
+ * (Sphinx myst-parser / Jupyter Book / mystmd) corpora into TreeNode[] by
4
+ * translating MyST directives, roles, and targets to Dogsbay-MD, then
5
+ * parsing with the canonical dogsbay-md parser (zero new node types).
6
+ *
7
+ * See plans/format-myst.md.
8
+ */
9
+ export { parseMyst } from "./parse.js";
10
+ export { mystToDogsbayMd, } from "./translate.js";
11
+ export { loadMyst, detectMyst, walkMarkdown, pathToSlug, } from "./loaders/load.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAwB,MAAM,YAAY,CAAC;AAC7D,OAAO,EACL,eAAe,GAGhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,UAAU,GAGX,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { NavItem } from "@dogsbay/types";
2
+ export interface MystPageSource {
3
+ filePath: string;
4
+ /** Root-relative slug (README/index → index). */
5
+ slug: string;
6
+ }
7
+ export interface MystLoadResult {
8
+ pages: MystPageSource[];
9
+ nav: NavItem[];
10
+ /** Directory the docs live under (for asset mirroring). */
11
+ docsDir: string;
12
+ /** How nav was derived — surfaced by migrate-myst for its summary. */
13
+ navSource: "_toc.yml" | "myst.yml" | "toctree" | "directory";
14
+ }
15
+ /** Slug for a source path relative to the docs root (README/index → index). */
16
+ export declare function pathToSlug(rel: string): string;
17
+ /** Walk `dir` for every Markdown page (skipping build/dot dirs). */
18
+ export declare function walkMarkdown(dir: string): MystPageSource[];
19
+ /**
20
+ * Detect: does this directory look like a MyST corpus? A config/TOC file is
21
+ * a definitive signal; otherwise require MyST syntax in at least one sampled
22
+ * Markdown file (bounded scan — never read the whole tree).
23
+ */
24
+ export declare function detectMyst(sourceDir: string): boolean;
25
+ export interface MystLoadOptions {
26
+ hrefPrefix?: string;
27
+ }
28
+ export declare function loadMyst(source: string, opts?: MystLoadOptions): MystLoadResult;
29
+ /** Directory-structure nav (best-effort; the author can curate nav.yml). */
30
+ export declare function inferNav(pages: MystPageSource[], titles: Map<string, string>, hrefPrefix?: string): NavItem[];
31
+ //# sourceMappingURL=load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/loaders/load.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAI9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,CAAC;CAC9D;AAKD,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK9C;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAwB1D;AAiBD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAoBrD;AAuCD,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,cAAc,CAiDnF;AAoCD,4EAA4E;AAC5E,wBAAgB,QAAQ,CACtB,KAAK,EAAE,cAAc,EAAE,EACvB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,UAAU,SAAK,GACd,OAAO,EAAE,CA4BX"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * MyST corpus loader — discover pages, build nav, detect the format.
3
+ *
4
+ * MyST content is Markdown (`.md`, sometimes `.ipynb`), so — unlike rST —
5
+ * "has .md files" can't be the signal. A MyST corpus is recognised by an
6
+ * explicit config/TOC (`myst.yml`, `_toc.yml`) OR by MyST-specific syntax
7
+ * (```` ```{directive} ````, `:::{directive}`, `` {role}`…` ``, `(target)=`)
8
+ * appearing across its Markdown. Registered BEFORE the generic dogsbay-md
9
+ * detector, AFTER GitBook/rST, so it never steals a plain-Markdown or
10
+ * GitBook corpus.
11
+ *
12
+ * Nav, in priority order:
13
+ * 1. `_toc.yml` (Jupyter Book)
14
+ * 2. `myst.yml` (mystmd `project.toc`)
15
+ * 3. `{toctree}` directives, resolved recursively from the root doc
16
+ * 4. directory structure (best-effort fallback)
17
+ */
18
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
19
+ import { basename, join, relative } from "node:path";
20
+ import { parseMyst } from "../parse.js";
21
+ import { parseJupyterToc, parseMystYmlToc, refToSlug } from "./toc.js";
22
+ const SKIP_DIRS = new Set(["_build", "_static", "_templates", "node_modules", "dist", ".git"]);
23
+ const MD_EXT = /\.(md|markdown)$/i;
24
+ /** Slug for a source path relative to the docs root (README/index → index). */
25
+ export function pathToSlug(rel) {
26
+ let p = rel.replace(/\\/g, "/").replace(MD_EXT, "");
27
+ if (p === "README" || p === "index")
28
+ return "index";
29
+ p = p.replace(/\/(README|index)$/i, "/index");
30
+ return p;
31
+ }
32
+ /** Walk `dir` for every Markdown page (skipping build/dot dirs). */
33
+ export function walkMarkdown(dir) {
34
+ const out = [];
35
+ const walk = (d) => {
36
+ let entries;
37
+ try {
38
+ entries = readdirSync(d);
39
+ }
40
+ catch {
41
+ return;
42
+ }
43
+ for (const name of entries) {
44
+ if (name.startsWith(".") || SKIP_DIRS.has(name))
45
+ continue;
46
+ const full = join(d, name);
47
+ let st;
48
+ try {
49
+ st = statSync(full);
50
+ }
51
+ catch {
52
+ continue;
53
+ }
54
+ if (st.isDirectory())
55
+ walk(full);
56
+ else if (MD_EXT.test(name))
57
+ out.push({ filePath: full, slug: pathToSlug(relative(dir, full)) });
58
+ }
59
+ };
60
+ walk(dir);
61
+ return out;
62
+ }
63
+ // ── Detection ──────────────────────────────────────────────────────────────
64
+ /** MyST directive / role / target markers used for syntax sniffing. */
65
+ const MYST_MARKERS = [
66
+ /^```\{[a-zA-Z0-9_+-]+\}/m, // ```{note}
67
+ /^:::+\{[a-zA-Z0-9_+-]+\}/m, // :::{note}
68
+ /\{(?:ref|doc|eq|numref|math|sub|sup|abbr|kbd|download|term)\}`/, // roles
69
+ /^\([A-Za-z0-9_.:+-]+\)=\s*$/m, // (target)=
70
+ ];
71
+ /** Does the file's text carry recognisable MyST syntax? */
72
+ function hasMystSyntax(text) {
73
+ return MYST_MARKERS.some((re) => re.test(text));
74
+ }
75
+ /**
76
+ * Detect: does this directory look like a MyST corpus? A config/TOC file is
77
+ * a definitive signal; otherwise require MyST syntax in at least one sampled
78
+ * Markdown file (bounded scan — never read the whole tree).
79
+ */
80
+ export function detectMyst(sourceDir) {
81
+ if (!existsSync(sourceDir))
82
+ return false;
83
+ try {
84
+ if (!statSync(sourceDir).isDirectory())
85
+ return false;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ if (findConfig(sourceDir))
91
+ return true;
92
+ // Syntax sniff — sample up to 40 Markdown files.
93
+ const pages = walkMarkdown(sourceDir);
94
+ if (pages.length === 0)
95
+ return false;
96
+ for (const p of pages.slice(0, 40)) {
97
+ try {
98
+ if (hasMystSyntax(readFileSync(p.filePath, "utf-8")))
99
+ return true;
100
+ }
101
+ catch {
102
+ // unreadable — skip
103
+ }
104
+ }
105
+ return false;
106
+ }
107
+ /** Find a MyST config/TOC at (or one level under) the source root. */
108
+ function findConfig(dir) {
109
+ for (const [file, kind] of [
110
+ ["_toc.yml", "_toc.yml"],
111
+ ["myst.yml", "myst.yml"],
112
+ ]) {
113
+ const p = join(dir, file);
114
+ if (existsSync(p))
115
+ return { kind, path: p, base: dir };
116
+ }
117
+ // One level down (a `docs/` or `content/` subdir).
118
+ let entries = [];
119
+ try {
120
+ entries = readdirSync(dir);
121
+ }
122
+ catch {
123
+ return null;
124
+ }
125
+ for (const name of entries) {
126
+ if (name.startsWith(".") || SKIP_DIRS.has(name))
127
+ continue;
128
+ const sub = join(dir, name);
129
+ try {
130
+ if (!statSync(sub).isDirectory())
131
+ continue;
132
+ }
133
+ catch {
134
+ continue;
135
+ }
136
+ for (const [file, kind] of [
137
+ ["_toc.yml", "_toc.yml"],
138
+ ["myst.yml", "myst.yml"],
139
+ ]) {
140
+ const p = join(sub, file);
141
+ if (existsSync(p))
142
+ return { kind, path: p, base: sub };
143
+ }
144
+ }
145
+ return null;
146
+ }
147
+ export function loadMyst(source, opts = {}) {
148
+ const hrefPrefix = opts.hrefPrefix ?? "";
149
+ const cfg = findConfig(source);
150
+ const docsDir = cfg ? cfg.base : source;
151
+ const pages = walkMarkdown(docsDir);
152
+ const slugToHref = (slug) => slug === "index" ? `${hrefPrefix}/`.replace(/\/+$/, "/") : `${hrefPrefix}/${slug}`.replace(/\/+/g, "/");
153
+ // Titles + per-page toctree, parsed once (cheap — used for nav labels and
154
+ // toctree nav). Reused by the importer so pages aren't parsed twice there.
155
+ const titles = new Map();
156
+ const toctrees = new Map();
157
+ for (const p of pages) {
158
+ try {
159
+ const parsed = parseMyst(readFileSync(p.filePath, "utf-8"));
160
+ const t = (typeof parsed.frontmatter.title === "string" && parsed.frontmatter.title.trim()) ||
161
+ // Scan the translated BODY, not the full markdown — a `# comment`
162
+ // line inside YAML frontmatter must not be misread as the title.
163
+ firstHeading(parsed.body);
164
+ if (t)
165
+ titles.set(p.slug, t);
166
+ if (parsed.toctree.length)
167
+ toctrees.set(p.slug, parsed.toctree);
168
+ }
169
+ catch {
170
+ // unreadable/unparseable page — skip for nav; importer will report it
171
+ }
172
+ }
173
+ // 1 + 2: explicit config TOC.
174
+ if (cfg) {
175
+ const yamlText = readFileSync(cfg.path, "utf-8");
176
+ const toc = cfg.kind === "_toc.yml"
177
+ ? parseJupyterToc(yamlText, titles, slugToHref)
178
+ : parseMystYmlToc(yamlText, titles, slugToHref);
179
+ if (toc && toc.nav.length) {
180
+ return { pages, nav: toc.nav, docsDir, navSource: cfg.kind };
181
+ }
182
+ }
183
+ // 3: toctree-derived nav from the root doc.
184
+ const rootSlug = pages.some((p) => p.slug === "index") ? "index" : undefined;
185
+ if (rootSlug && toctrees.size > 0) {
186
+ const nav = buildToctreeNav(rootSlug, toctrees, titles, slugToHref, new Set());
187
+ if (nav.length)
188
+ return { pages, nav, docsDir, navSource: "toctree" };
189
+ }
190
+ // 4: directory-structure fallback.
191
+ return { pages, nav: inferNav(pages, titles, hrefPrefix), docsDir, navSource: "directory" };
192
+ }
193
+ /** First `# heading` text in a Markdown string, if any. */
194
+ function firstHeading(md) {
195
+ const m = md.match(/^#\s+(.+?)\s*(\{#[^}]+\})?\s*$/m);
196
+ return m ? m[1].trim() : undefined;
197
+ }
198
+ /**
199
+ * Build nav by resolving `{toctree}` entries recursively from `slug`. A
200
+ * doc that itself has a toctree becomes a group whose children are its
201
+ * toctree entries. `seen` guards against cyclic toctrees.
202
+ */
203
+ function buildToctreeNav(slug, toctrees, titles, slugToHref, seen) {
204
+ if (seen.has(slug))
205
+ return [];
206
+ seen.add(slug);
207
+ const entries = toctrees.get(slug) ?? [];
208
+ const out = [];
209
+ for (const ref of entries) {
210
+ if (ref.includes("*"))
211
+ continue; // globs need a walk; orphans cover them
212
+ const childSlug = refToSlug(ref);
213
+ const label = titles.get(childSlug) ?? prettify(childSlug);
214
+ const node = { label, href: slugToHref(childSlug) };
215
+ const grandkids = buildToctreeNav(childSlug, toctrees, titles, slugToHref, seen);
216
+ if (grandkids.length)
217
+ node.children = grandkids;
218
+ out.push(node);
219
+ }
220
+ return out;
221
+ }
222
+ /** Directory-structure nav (best-effort; the author can curate nav.yml). */
223
+ export function inferNav(pages, titles, hrefPrefix = "") {
224
+ const root = [];
225
+ const groups = new Map();
226
+ const ensureGroup = (dir) => {
227
+ if (!dir)
228
+ return null;
229
+ const existing = groups.get(dir);
230
+ if (existing)
231
+ return existing;
232
+ const parentDir = dir.includes("/") ? dir.slice(0, dir.lastIndexOf("/")) : "";
233
+ const group = { label: prettify(dir.slice(dir.lastIndexOf("/") + 1)), children: [] };
234
+ groups.set(dir, group);
235
+ const parent = ensureGroup(parentDir);
236
+ (parent ? parent.children : root).push(group);
237
+ return group;
238
+ };
239
+ for (const p of pages.slice().sort((a, b) => a.slug.localeCompare(b.slug))) {
240
+ if (p.slug === "index")
241
+ continue;
242
+ const dir = p.slug.includes("/") ? p.slug.slice(0, p.slug.lastIndexOf("/")) : "";
243
+ const base = p.slug.slice(p.slug.lastIndexOf("/") + 1);
244
+ const href = `${hrefPrefix}/${p.slug}`.replace(/\/+/g, "/");
245
+ if (base === "index") {
246
+ const g = ensureGroup(dir);
247
+ if (g)
248
+ g.href = href;
249
+ }
250
+ else {
251
+ const g = ensureGroup(dir);
252
+ (g ? g.children : root).push({ label: titles.get(p.slug) ?? prettify(base), href });
253
+ }
254
+ }
255
+ return root;
256
+ }
257
+ function prettify(slug) {
258
+ const base = basename(slug);
259
+ return base
260
+ .split(/[-_]/)
261
+ .filter(Boolean)
262
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
263
+ .join(" ");
264
+ }
265
+ //# sourceMappingURL=load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/loaders/load.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { NavItem } from "@dogsbay/types";
2
+ /** Normalize a MyST doc reference to a root-relative slug. */
3
+ export declare function refToSlug(ref: string): string;
4
+ export interface TocResult {
5
+ nav: NavItem[];
6
+ /** Slugs referenced by the TOC, in order (root first). */
7
+ slugs: string[];
8
+ }
9
+ /**
10
+ * Parse a Jupyter Book `_toc.yml`. Returns null when the YAML isn't a
11
+ * jb-book TOC (so the caller can fall back to another nav source).
12
+ */
13
+ export declare function parseJupyterToc(yamlText: string, titles: Map<string, string>, slugToHref: (slug: string) => string): TocResult | null;
14
+ /**
15
+ * Parse a mystmd `myst.yml` `project.toc`. Returns null when there's no
16
+ * usable `project.toc`.
17
+ */
18
+ export declare function parseMystYmlToc(yamlText: string, titles: Map<string, string>, slugToHref: (slug: string) => string): TocResult | null;
19
+ //# sourceMappingURL=toc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toc.d.ts","sourceRoot":"","sources":["../../src/loaders/toc.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,8DAA8D;AAC9D,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO7C;AAWD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,0DAA0D;IAC1D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GACnC,SAAS,GAAG,IAAI,CAgElB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GACnC,SAAS,GAAG,IAAI,CA8ClB"}