@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 +61 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +79 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/loaders/load.d.ts +31 -0
- package/dist/loaders/load.d.ts.map +1 -0
- package/dist/loaders/load.js +265 -0
- package/dist/loaders/load.js.map +1 -0
- package/dist/loaders/toc.d.ts +19 -0
- package/dist/loaders/toc.d.ts.map +1 -0
- package/dist/loaders/toc.js +154 -0
- package/dist/loaders/toc.js.map +1 -0
- package/dist/parse.d.ts +15 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +37 -0
- package/dist/parse.js.map +1 -0
- package/dist/translate.d.ts +53 -0
- package/dist/translate.d.ts.map +1 -0
- package/dist/translate.js +678 -0
- package/dist/translate.js.map +1 -0
- package/package.json +38 -0
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
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
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, 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"}
|