@dogsbay/format-gitbook 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/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +94 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/loaders/config.d.ts +9 -0
- package/dist/loaders/config.d.ts.map +1 -0
- package/dist/loaders/config.js +51 -0
- package/dist/loaders/config.js.map +1 -0
- package/dist/loaders/load.d.ts +33 -0
- package/dist/loaders/load.d.ts.map +1 -0
- package/dist/loaders/load.js +199 -0
- package/dist/loaders/load.js.map +1 -0
- package/dist/loaders/summary.d.ts +28 -0
- package/dist/loaders/summary.d.ts.map +1 -0
- package/dist/loaders/summary.js +95 -0
- package/dist/loaders/summary.js.map +1 -0
- package/dist/parse.d.ts +13 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +33 -0
- package/dist/parse.js.map +1 -0
- package/dist/translate.d.ts +44 -0
- package/dist/translate.d.ts.map +1 -0
- package/dist/translate.js +427 -0
- package/dist/translate.js.map +1 -0
- package/package.json +38 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FormatPlugin, ExportPage, NavItem } from "@dogsbay/types";
|
|
2
|
+
export interface GitbookImportResult {
|
|
3
|
+
pages: ExportPage[];
|
|
4
|
+
nav: NavItem[];
|
|
5
|
+
redirects: Record<string, string>;
|
|
6
|
+
spaces: string[];
|
|
7
|
+
/** Docs roots to mirror non-`.md` assets from (dir + slug prefix). */
|
|
8
|
+
assetRoots: {
|
|
9
|
+
dir: string;
|
|
10
|
+
prefix: string;
|
|
11
|
+
}[];
|
|
12
|
+
}
|
|
13
|
+
export declare function importGitbook(source: string, opts: Record<string, unknown>): Promise<GitbookImportResult>;
|
|
14
|
+
export declare const plugin: FormatPlugin;
|
|
15
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAW,MAAM,gBAAgB,CAAC;AAajF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sEAAsE;IACtE,UAAU,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/C;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAwD9B;AAED,eAAO,MAAM,MAAM,EAAE,YAiBpB,CAAC"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FormatPlugin for GitBook as a source format.
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates: detect corpus → loadGitbook (config + SUMMARY + pages) →
|
|
5
|
+
* translate each page (parseGitbook) → assemble ExportPage[] + NavItem[].
|
|
6
|
+
* Fragments (`.gitbook/includes/*`) are emitted with `fragment: true` so
|
|
7
|
+
* the CLI writes them as `{% include %}` targets, not routable pages —
|
|
8
|
+
* the same fragment model AsciiBinder/Antora use.
|
|
9
|
+
*
|
|
10
|
+
* The redirects from `.gitbook.yaml` are surfaced on the result so
|
|
11
|
+
* `migrate-gitbook` can carry them into the site config.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
14
|
+
import { basename } from "node:path";
|
|
15
|
+
import { extractHeadings } from "@dogsbay/format-dogsbay-md";
|
|
16
|
+
import { parseGitbook } from "./parse.js";
|
|
17
|
+
import { loadGitbook, detectGitbook } from "./loaders/load.js";
|
|
18
|
+
function prettify(slug) {
|
|
19
|
+
return slug
|
|
20
|
+
.split(/[-_/]/)
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
23
|
+
.join(" ");
|
|
24
|
+
}
|
|
25
|
+
export async function importGitbook(source, opts) {
|
|
26
|
+
if (!existsSync(source)) {
|
|
27
|
+
throw new Error(`Source directory not found: ${source}`);
|
|
28
|
+
}
|
|
29
|
+
const space = typeof opts.space === "string" ? opts.space : undefined;
|
|
30
|
+
const hrefPrefix = typeof opts.hrefPrefix === "string" ? opts.hrefPrefix : "";
|
|
31
|
+
const { pages: pageSources, nav, redirects, spaces, assetRoots } = loadGitbook(source, {
|
|
32
|
+
space,
|
|
33
|
+
hrefPrefix,
|
|
34
|
+
});
|
|
35
|
+
const pages = [];
|
|
36
|
+
let failed = 0;
|
|
37
|
+
let ledgerTotal = 0;
|
|
38
|
+
for (const ps of pageSources) {
|
|
39
|
+
try {
|
|
40
|
+
const content = readFileSync(ps.filePath, "utf-8");
|
|
41
|
+
const { tree, frontmatter, body, ledger } = parseGitbook(content);
|
|
42
|
+
ledgerTotal += ledger.length;
|
|
43
|
+
const headings = extractHeadings(tree);
|
|
44
|
+
const h1 = headings.find((h) => h.depth === 1);
|
|
45
|
+
// A whitespace-only source `title:` must not win — `.trim()` so a
|
|
46
|
+
// blank falls through to the H1 / slug (review #6).
|
|
47
|
+
const fmTitle = typeof frontmatter.title === "string" && frontmatter.title.trim()
|
|
48
|
+
? frontmatter.title
|
|
49
|
+
: undefined;
|
|
50
|
+
const title = fmTitle || h1?.text || prettify(basename(ps.slug));
|
|
51
|
+
pages.push({
|
|
52
|
+
slug: ps.slug,
|
|
53
|
+
title,
|
|
54
|
+
tree,
|
|
55
|
+
headings,
|
|
56
|
+
frontmatter,
|
|
57
|
+
meta: {},
|
|
58
|
+
...(ps.fragment ? { fragment: true } : {}),
|
|
59
|
+
// Translated Dogsbay-MD body — what migrate-gitbook writes to disk.
|
|
60
|
+
bodyMarkdown: body,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
failed += 1;
|
|
65
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
66
|
+
console.warn(`gitbook import: failed to convert ${ps.filePath} (slug "${ps.slug}"), skipping: ${msg}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (failed > 0) {
|
|
70
|
+
console.warn(`gitbook import: ${failed} of ${pageSources.length} page(s) failed and were skipped`);
|
|
71
|
+
}
|
|
72
|
+
if (ledgerTotal > 0) {
|
|
73
|
+
console.warn(`gitbook import: ${ledgerTotal} construct(s) mapped with caveats (see per-page ledger)`);
|
|
74
|
+
}
|
|
75
|
+
return { pages, nav, redirects, spaces, assetRoots };
|
|
76
|
+
}
|
|
77
|
+
export const plugin = {
|
|
78
|
+
name: "gitbook",
|
|
79
|
+
canImport: true,
|
|
80
|
+
canExport: false,
|
|
81
|
+
detectSource: (path) => detectGitbook(path),
|
|
82
|
+
importOptions: [
|
|
83
|
+
{
|
|
84
|
+
flags: "--space <dir>",
|
|
85
|
+
description: "Import a single space (subdirectory containing SUMMARY.md) from a multi-space GitBook repo. Omit to import every space as a top-level section.",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
exportOptions: [],
|
|
89
|
+
async import(source, opts) {
|
|
90
|
+
const { pages, nav } = await importGitbook(source, opts);
|
|
91
|
+
return { pages, nav };
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
//# 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,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dogsbay/format-gitbook — GitBook (Git Sync + legacy gitbook-cli)
|
|
3
|
+
* format plugin. Imports GitBook corpora into TreeNode[] by translating
|
|
4
|
+
* the Git Sync markdown dialect to Dogsbay-MD, then parsing with the
|
|
5
|
+
* canonical dogsbay-md parser.
|
|
6
|
+
*
|
|
7
|
+
* See plans/format-gitbook.md.
|
|
8
|
+
*/
|
|
9
|
+
export { parseGitbook, type ParseGitbookResult } from "./parse.js";
|
|
10
|
+
export { gitbookToDogsbayMd, type TranslateResult, type TranslateLedgerEntry, } from "./translate.js";
|
|
11
|
+
//# 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,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EACL,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dogsbay/format-gitbook — GitBook (Git Sync + legacy gitbook-cli)
|
|
3
|
+
* format plugin. Imports GitBook corpora into TreeNode[] by translating
|
|
4
|
+
* the Git Sync markdown dialect to Dogsbay-MD, then parsing with the
|
|
5
|
+
* canonical dogsbay-md parser.
|
|
6
|
+
*
|
|
7
|
+
* See plans/format-gitbook.md.
|
|
8
|
+
*/
|
|
9
|
+
export { parseGitbook } from "./parse.js";
|
|
10
|
+
export { gitbookToDogsbayMd, } from "./translate.js";
|
|
11
|
+
//# 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,YAAY,EAA2B,MAAM,YAAY,CAAC;AACnE,OAAO,EACL,kBAAkB,GAGnB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface GitbookConfig {
|
|
2
|
+
root: string;
|
|
3
|
+
readme: string;
|
|
4
|
+
summary: string;
|
|
5
|
+
redirects: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
/** Read `.gitbook.yaml` from `dir` if present; else return defaults. */
|
|
8
|
+
export declare function readGitbookConfig(dir: string): GitbookConfig;
|
|
9
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/loaders/config.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AASD,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAwB5D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.gitbook.yaml` reader.
|
|
3
|
+
*
|
|
4
|
+
* Documented schema (verified against GitBook docs + real corpora):
|
|
5
|
+
* root: ./docs/ # lookup dir, default ./ ; other paths relative to it
|
|
6
|
+
* structure:
|
|
7
|
+
* readme: README.md # landing page, default README.md
|
|
8
|
+
* summary: SUMMARY.md # table of contents, default SUMMARY.md
|
|
9
|
+
* redirects:
|
|
10
|
+
* old/path: new/page.md # old URL → target md file
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import YAML from "yaml";
|
|
15
|
+
const DEFAULTS = {
|
|
16
|
+
root: "./",
|
|
17
|
+
readme: "README.md",
|
|
18
|
+
summary: "SUMMARY.md",
|
|
19
|
+
redirects: {},
|
|
20
|
+
};
|
|
21
|
+
/** Read `.gitbook.yaml` from `dir` if present; else return defaults. */
|
|
22
|
+
export function readGitbookConfig(dir) {
|
|
23
|
+
const p = join(dir, ".gitbook.yaml");
|
|
24
|
+
if (!existsSync(p))
|
|
25
|
+
return { ...DEFAULTS };
|
|
26
|
+
let parsed;
|
|
27
|
+
try {
|
|
28
|
+
parsed = YAML.parse(readFileSync(p, "utf-8"));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return { ...DEFAULTS };
|
|
32
|
+
}
|
|
33
|
+
if (!parsed || typeof parsed !== "object")
|
|
34
|
+
return { ...DEFAULTS };
|
|
35
|
+
const o = parsed;
|
|
36
|
+
const structure = (o.structure ?? {});
|
|
37
|
+
const redirects = {};
|
|
38
|
+
if (o.redirects && typeof o.redirects === "object") {
|
|
39
|
+
for (const [k, v] of Object.entries(o.redirects)) {
|
|
40
|
+
if (typeof v === "string")
|
|
41
|
+
redirects[k] = v;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
root: typeof o.root === "string" ? o.root : DEFAULTS.root,
|
|
46
|
+
readme: typeof structure.readme === "string" ? structure.readme : DEFAULTS.readme,
|
|
47
|
+
summary: typeof structure.summary === "string" ? structure.summary : DEFAULTS.summary,
|
|
48
|
+
redirects,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/loaders/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,MAAM,CAAC;AASxB,MAAM,QAAQ,GAAkB;IAC9B,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,SAAS,EAAE,EAAE;CACd,CAAC;AAEF,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACrC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC3C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzB,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IAClE,MAAM,CAAC,GAAG,MAAiC,CAAC;IAC5C,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAA4B,CAAC;IACjE,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QACnD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAoC,CAAC,EAAE,CAAC;YAC5E,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI;QACzD,MAAM,EAAE,OAAO,SAAS,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM;QACjF,OAAO,EAAE,OAAO,SAAS,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO;QACrF,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { NavItem } from "@dogsbay/types";
|
|
2
|
+
export interface GitbookPageSource {
|
|
3
|
+
filePath: string;
|
|
4
|
+
slug: string;
|
|
5
|
+
/** True for `.gitbook/includes/*` — mirrored as a fragment, not a page. */
|
|
6
|
+
fragment?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/** A resolved docs root to mirror assets from, and its slug prefix. */
|
|
9
|
+
export interface GitbookAssetRoot {
|
|
10
|
+
/** Absolute docs directory (space dir + `.gitbook.yaml` `root:`). */
|
|
11
|
+
dir: string;
|
|
12
|
+
/** Slug prefix for pages/assets under this root ("" or "<space>/"). */
|
|
13
|
+
prefix: string;
|
|
14
|
+
}
|
|
15
|
+
export interface GitbookLoadResult {
|
|
16
|
+
pages: GitbookPageSource[];
|
|
17
|
+
nav: NavItem[];
|
|
18
|
+
redirects: Record<string, string>;
|
|
19
|
+
/** Space directories detected (relative to source); ≥2 ⇒ multi-space. */
|
|
20
|
+
spaces: string[];
|
|
21
|
+
/** Docs roots to mirror non-`.md` assets from, with their slug prefix. */
|
|
22
|
+
assetRoots: GitbookAssetRoot[];
|
|
23
|
+
}
|
|
24
|
+
export interface GitbookLoadOptions {
|
|
25
|
+
/** Restrict to a single space directory (relative to source root). */
|
|
26
|
+
space?: string;
|
|
27
|
+
/** URL prefix applied to nav hrefs. */
|
|
28
|
+
hrefPrefix?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Does this directory look like a GitBook corpus? */
|
|
31
|
+
export declare function detectGitbook(sourceDir: string): boolean;
|
|
32
|
+
export declare function loadGitbook(sourceDir: string, opts?: GitbookLoadOptions): GitbookLoadResult;
|
|
33
|
+
//# sourceMappingURL=load.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/loaders/load.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAI9C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,yEAAyE;IACzE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0EAA0E;IAC1E,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,sDAAsD;AACtD,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAYxD;AAsFD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,iBAAiB,CA4D/F"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitBook corpus loader — discover the docs root, read `.gitbook.yaml`,
|
|
3
|
+
* parse `SUMMARY.md` for nav, enumerate every page (including orphans not
|
|
4
|
+
* in the summary), and surface redirects + include fragments.
|
|
5
|
+
*
|
|
6
|
+
* Multi-space corpora (e.g. snyk/user-docs holds six spaces, each a dir
|
|
7
|
+
* with its own SUMMARY.md) are detected: when the caller doesn't point at
|
|
8
|
+
* a single space, every dir containing a SUMMARY.md is a space. The
|
|
9
|
+
* default import concatenates all spaces (each summary's nav becomes a
|
|
10
|
+
* top-level section); `--space <dir>` selects one.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
13
|
+
import { basename, join, relative } from "node:path";
|
|
14
|
+
import { readGitbookConfig } from "./config.js";
|
|
15
|
+
import { parseSummary, pathToSlug } from "./summary.js";
|
|
16
|
+
/** Does this directory look like a GitBook corpus? */
|
|
17
|
+
export function detectGitbook(sourceDir) {
|
|
18
|
+
if (!existsSync(sourceDir))
|
|
19
|
+
return false;
|
|
20
|
+
try {
|
|
21
|
+
if (!statSync(sourceDir).isDirectory())
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
// A .gitbook.yaml anywhere near the top, or a SUMMARY.md, is the signal.
|
|
28
|
+
if (existsSync(join(sourceDir, ".gitbook.yaml")))
|
|
29
|
+
return true;
|
|
30
|
+
if (existsSync(join(sourceDir, "SUMMARY.md")))
|
|
31
|
+
return true;
|
|
32
|
+
// Or a single-level space dir carrying either marker.
|
|
33
|
+
return findSpaces(sourceDir).length > 0;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Directories (relative) that contain a SUMMARY.md — each is a space.
|
|
37
|
+
*
|
|
38
|
+
* If the ROOT itself has a SUMMARY.md, the corpus is single-space and we
|
|
39
|
+
* return just `["."]` — we do NOT also scan subdirectories, because a
|
|
40
|
+
* nested `SUMMARY.md` (e.g. a stray one under `api/`) would otherwise be
|
|
41
|
+
* misread as a second space, duplicating that subtree's pages and adding
|
|
42
|
+
* a phantom top-level nav section (review #8). Multi-space is the
|
|
43
|
+
* monorepo shape where the root has NO SUMMARY.md but ≥1 subdir does.
|
|
44
|
+
*/
|
|
45
|
+
function findSpaces(sourceDir) {
|
|
46
|
+
if (existsSync(join(sourceDir, "SUMMARY.md")) || existsSync(join(sourceDir, ".gitbook.yaml"))) {
|
|
47
|
+
return ["."];
|
|
48
|
+
}
|
|
49
|
+
const out = [];
|
|
50
|
+
const seen = new Set();
|
|
51
|
+
const consider = (dir) => {
|
|
52
|
+
if (existsSync(join(dir, "SUMMARY.md"))) {
|
|
53
|
+
const rel = relative(sourceDir, dir) || ".";
|
|
54
|
+
if (!seen.has(rel)) {
|
|
55
|
+
seen.add(rel);
|
|
56
|
+
out.push(rel);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
// One level down (the snyk monorepo shape: docs/, platform-administration/…).
|
|
61
|
+
let entries = [];
|
|
62
|
+
try {
|
|
63
|
+
entries = readdirSync(sourceDir);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
for (const name of entries) {
|
|
69
|
+
if (name.startsWith(".") || name === "node_modules")
|
|
70
|
+
continue;
|
|
71
|
+
const full = join(sourceDir, name);
|
|
72
|
+
try {
|
|
73
|
+
if (statSync(full).isDirectory())
|
|
74
|
+
consider(full);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* ignore */
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
/** Walk `spaceDir` for every `.md` file; classify includes as fragments. */
|
|
83
|
+
function walkPages(spaceDir, sourceDir) {
|
|
84
|
+
const out = [];
|
|
85
|
+
const walk = (dir) => {
|
|
86
|
+
let entries;
|
|
87
|
+
try {
|
|
88
|
+
entries = readdirSync(dir);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
for (const name of entries) {
|
|
94
|
+
if (name === "node_modules")
|
|
95
|
+
continue;
|
|
96
|
+
const full = join(dir, name);
|
|
97
|
+
let st;
|
|
98
|
+
try {
|
|
99
|
+
st = statSync(full);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (st.isDirectory()) {
|
|
105
|
+
// Hidden dirs are skipped EXCEPT `.gitbook` (holds includes).
|
|
106
|
+
if (name.startsWith(".") && name !== ".gitbook")
|
|
107
|
+
continue;
|
|
108
|
+
walk(full);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (!name.toLowerCase().endsWith(".md"))
|
|
112
|
+
continue;
|
|
113
|
+
if (name === "SUMMARY.md" || name === "GLOSSARY.md")
|
|
114
|
+
continue;
|
|
115
|
+
const relFromSpace = relative(spaceDir, full).replace(/\\/g, "/");
|
|
116
|
+
const isInclude = relFromSpace.includes(".gitbook/includes/");
|
|
117
|
+
out.push({
|
|
118
|
+
filePath: full,
|
|
119
|
+
slug: pathToSlug(relFromSpace),
|
|
120
|
+
...(isInclude ? { fragment: true } : {}),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
walk(spaceDir);
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
export function loadGitbook(sourceDir, opts = {}) {
|
|
128
|
+
const hrefPrefix = opts.hrefPrefix ?? "";
|
|
129
|
+
const allSpaces = findSpaces(sourceDir);
|
|
130
|
+
// Which spaces to load: an explicit --space, else all detected (or the
|
|
131
|
+
// root itself if none matched).
|
|
132
|
+
let spaces = opts.space ? [opts.space] : allSpaces;
|
|
133
|
+
if (spaces.length === 0)
|
|
134
|
+
spaces = ["."];
|
|
135
|
+
const pages = [];
|
|
136
|
+
const nav = [];
|
|
137
|
+
const redirects = {};
|
|
138
|
+
const assetRoots = [];
|
|
139
|
+
const multi = spaces.length > 1;
|
|
140
|
+
for (const space of spaces) {
|
|
141
|
+
const spaceDir = space === "." ? sourceDir : join(sourceDir, space);
|
|
142
|
+
if (!existsSync(spaceDir))
|
|
143
|
+
continue;
|
|
144
|
+
const config = readGitbookConfig(spaceDir);
|
|
145
|
+
// `root:` relocates the docs dir within the space.
|
|
146
|
+
const docsDir = config.root && config.root !== "./" ? join(spaceDir, config.root) : spaceDir;
|
|
147
|
+
// Page prefix so multi-space slugs don't collide (space dir name).
|
|
148
|
+
const slugPrefix = multi && space !== "." ? `${space}/` : "";
|
|
149
|
+
assetRoots.push({ dir: docsDir, prefix: slugPrefix });
|
|
150
|
+
for (const p of walkPages(docsDir, docsDir)) {
|
|
151
|
+
pages.push({ ...p, slug: `${slugPrefix}${p.slug}`.replace(/\/+/g, "/") });
|
|
152
|
+
}
|
|
153
|
+
// Nav from SUMMARY.md (under docsDir per config.summary).
|
|
154
|
+
const summaryPath = join(docsDir, config.summary);
|
|
155
|
+
const navPrefix = `${hrefPrefix}${slugPrefix ? "/" + slugPrefix.replace(/\/$/, "") : ""}`;
|
|
156
|
+
if (existsSync(summaryPath)) {
|
|
157
|
+
const parsed = parseSummary(readFileSync(summaryPath, "utf-8"), navPrefix);
|
|
158
|
+
if (multi) {
|
|
159
|
+
nav.push({ label: prettify(space), children: parsed.nav });
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
nav.push(...parsed.nav);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// No SUMMARY.md — infer nav from folder structure (paths → slugs).
|
|
167
|
+
const inferred = inferNavFromPages(pages.filter((p) => !p.fragment && p.slug.startsWith(slugPrefix)));
|
|
168
|
+
if (multi)
|
|
169
|
+
nav.push({ label: prettify(space), children: inferred });
|
|
170
|
+
else
|
|
171
|
+
nav.push(...inferred);
|
|
172
|
+
}
|
|
173
|
+
// Redirect keys (old URL) AND values (target .md) are relative to the
|
|
174
|
+
// space, so BOTH get the space slug prefix in a multi-space import —
|
|
175
|
+
// else a redirect in space `docs` would point at an unprefixed target
|
|
176
|
+
// that doesn't exist under `docs/`.
|
|
177
|
+
for (const [k, v] of Object.entries(config.redirects)) {
|
|
178
|
+
const key = slugPrefix ? `${slugPrefix}${k}` : k;
|
|
179
|
+
const val = slugPrefix ? `${slugPrefix}${v.replace(/^\.\//, "")}` : v;
|
|
180
|
+
redirects[key] = val;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { pages, nav, redirects, spaces: allSpaces, assetRoots };
|
|
184
|
+
}
|
|
185
|
+
/** Fallback nav: flat list from page slugs when there's no SUMMARY.md. */
|
|
186
|
+
function inferNavFromPages(pages) {
|
|
187
|
+
return pages
|
|
188
|
+
.filter((p) => p.slug !== "index")
|
|
189
|
+
.map((p) => ({ label: prettify(basename(p.slug)), href: `/${p.slug}` }))
|
|
190
|
+
.sort((a, b) => a.label.localeCompare(b.label));
|
|
191
|
+
}
|
|
192
|
+
function prettify(s) {
|
|
193
|
+
return s
|
|
194
|
+
.split(/[-_/]/)
|
|
195
|
+
.filter(Boolean)
|
|
196
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
197
|
+
.join(" ");
|
|
198
|
+
}
|
|
199
|
+
//# 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,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SUMMARY.md → NavItem[] + referenced page paths.
|
|
3
|
+
*
|
|
4
|
+
* GitBook's table of contents is a markdown file:
|
|
5
|
+
* - `# Table of contents` / `# Summary` header → ignored
|
|
6
|
+
* - `## Group title` (optionally trailing `<a href id>`) → a nav group
|
|
7
|
+
* - `* [Title](path.md)` list items; nesting by indentation
|
|
8
|
+
* - external `* [Title](https://…)` → external link leaf
|
|
9
|
+
* - `folder/README.md` links → the folder's landing page
|
|
10
|
+
*
|
|
11
|
+
* Slug convention (matches Dogsbay's directory-landing model):
|
|
12
|
+
* - `README.md` → `index`
|
|
13
|
+
* - `folder/README.md` → `folder/index`
|
|
14
|
+
* - `folder/page.md` → `folder/page`
|
|
15
|
+
* so a folder group with a linked landing page serves at `/folder`.
|
|
16
|
+
*
|
|
17
|
+
* See dogsbay-research/content/formats/gitbook-import-support.md §1.
|
|
18
|
+
*/
|
|
19
|
+
import type { NavItem } from "@dogsbay/types";
|
|
20
|
+
export interface ParsedSummary {
|
|
21
|
+
nav: NavItem[];
|
|
22
|
+
/** Every local page path referenced by the summary (posix, .md kept). */
|
|
23
|
+
referenced: string[];
|
|
24
|
+
}
|
|
25
|
+
/** Normalize a GitBook page path to a Dogsbay slug (README → index). */
|
|
26
|
+
export declare function pathToSlug(relPath: string): string;
|
|
27
|
+
export declare function parseSummary(content: string, hrefPrefix?: string): ParsedSummary;
|
|
28
|
+
//# sourceMappingURL=summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/loaders/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,OAAO,EAAE,CAAC;IACf,yEAAyE;IACzE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKlD;AAaD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,SAAK,GAAG,aAAa,CA6C5E"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** Normalize a GitBook page path to a Dogsbay slug (README → index). */
|
|
2
|
+
export function pathToSlug(relPath) {
|
|
3
|
+
let p = relPath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\.md$/i, "");
|
|
4
|
+
if (p === "README" || p === "readme")
|
|
5
|
+
return "index";
|
|
6
|
+
p = p.replace(/\/README$/i, "/index");
|
|
7
|
+
return p;
|
|
8
|
+
}
|
|
9
|
+
const HEADING_RE = /^(#{1,6})\s+(.*?)\s*$/;
|
|
10
|
+
const ITEM_RE = /^(\s*)[*+-]\s+(.*)$/;
|
|
11
|
+
// [Label](target) — target either `<dest with spaces>` (CommonMark
|
|
12
|
+
// angle form; GitBook uses it for exported filenames like
|
|
13
|
+
// `<README (1).md>`) or a bare `dest`. Trailing markup after the link
|
|
14
|
+
// is tolerated.
|
|
15
|
+
const LINK_RE = /^\[([^\]]*)\]\(\s*(?:<([^>]*)>|([^)\s]+))[^)]*\)/;
|
|
16
|
+
const EXTERNAL_RE = /^(https?:\/\/|mailto:|tel:)/i;
|
|
17
|
+
// Strip a trailing `<a href id>` anchor GitBook adds to group headings.
|
|
18
|
+
const ANCHOR_TAIL_RE = /\s*<a\b[^>]*><\/a>\s*$/;
|
|
19
|
+
export function parseSummary(content, hrefPrefix = "") {
|
|
20
|
+
const referenced = [];
|
|
21
|
+
const top = [];
|
|
22
|
+
// Current group container the following items attach to (null = top level).
|
|
23
|
+
let group = null;
|
|
24
|
+
// Stack of {indent, item} for list nesting within the current section.
|
|
25
|
+
let stack = [];
|
|
26
|
+
const container = () => (group ? group.children : top);
|
|
27
|
+
for (const raw of content.split("\n")) {
|
|
28
|
+
const line = raw.replace(/\s+$/, "");
|
|
29
|
+
if (!line)
|
|
30
|
+
continue;
|
|
31
|
+
const h = line.match(HEADING_RE);
|
|
32
|
+
if (h) {
|
|
33
|
+
// `#` = doc title (ignore). `##`+ = a page group.
|
|
34
|
+
if (h[1].length === 1)
|
|
35
|
+
continue;
|
|
36
|
+
const label = h[2].replace(ANCHOR_TAIL_RE, "").trim();
|
|
37
|
+
group = { label, children: [] };
|
|
38
|
+
top.push(group);
|
|
39
|
+
stack = [];
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const it = line.match(ITEM_RE);
|
|
43
|
+
if (!it)
|
|
44
|
+
continue;
|
|
45
|
+
const indent = it[1].replace(/\t/g, " ").length;
|
|
46
|
+
const item = parseItem(it[2], hrefPrefix, referenced);
|
|
47
|
+
if (!item)
|
|
48
|
+
continue;
|
|
49
|
+
// Attach by indentation. Pop deeper-or-equal entries; the remaining
|
|
50
|
+
// top of stack is the parent.
|
|
51
|
+
while (stack.length && stack[stack.length - 1].indent >= indent)
|
|
52
|
+
stack.pop();
|
|
53
|
+
if (stack.length === 0) {
|
|
54
|
+
container().push(item);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const parent = stack[stack.length - 1].item;
|
|
58
|
+
(parent.children ??= []).push(item);
|
|
59
|
+
}
|
|
60
|
+
stack.push({ indent, item });
|
|
61
|
+
}
|
|
62
|
+
strip(top);
|
|
63
|
+
return { nav: top, referenced };
|
|
64
|
+
}
|
|
65
|
+
function parseItem(text, hrefPrefix, referenced) {
|
|
66
|
+
const m = text.match(LINK_RE);
|
|
67
|
+
if (!m) {
|
|
68
|
+
// A plain-text item (no link) — a group-ish header without a page.
|
|
69
|
+
const label = text.replace(ANCHOR_TAIL_RE, "").trim();
|
|
70
|
+
return label ? { label } : null;
|
|
71
|
+
}
|
|
72
|
+
const target = (m[2] ?? m[3] ?? "").trim();
|
|
73
|
+
const label = m[1].replace(/[*_`]/g, "").trim() || target;
|
|
74
|
+
if (EXTERNAL_RE.test(target))
|
|
75
|
+
return { label, href: target };
|
|
76
|
+
// Local page. Split off a #fragment, record the file, slugify.
|
|
77
|
+
const hashIdx = target.indexOf("#");
|
|
78
|
+
const filePart = hashIdx === -1 ? target : target.slice(0, hashIdx);
|
|
79
|
+
const frag = hashIdx === -1 ? "" : target.slice(hashIdx);
|
|
80
|
+
if (filePart)
|
|
81
|
+
referenced.push(filePart.replace(/^\.\//, ""));
|
|
82
|
+
const slug = pathToSlug(filePart);
|
|
83
|
+
const href = `${hrefPrefix}/${slug}`.replace(/\/+/g, "/");
|
|
84
|
+
return { label, href: `${href}${frag}` };
|
|
85
|
+
}
|
|
86
|
+
/** Drop empty `children: []` so leaves don't read as empty groups. */
|
|
87
|
+
function strip(items) {
|
|
88
|
+
for (const it of items) {
|
|
89
|
+
if (it.children && it.children.length === 0)
|
|
90
|
+
delete it.children;
|
|
91
|
+
else if (it.children)
|
|
92
|
+
strip(it.children);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../../src/loaders/summary.ts"],"names":[],"mappings":"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"}
|
package/dist/parse.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TreeNode } from "@dogsbay/types";
|
|
2
|
+
import { type TranslateLedgerEntry } from "./translate.js";
|
|
3
|
+
export interface ParseGitbookResult {
|
|
4
|
+
tree: TreeNode[];
|
|
5
|
+
frontmatter: Record<string, unknown>;
|
|
6
|
+
/** Frontmatter + translated body — the editable Dogsbay-MD for migrate. */
|
|
7
|
+
markdown: string;
|
|
8
|
+
/** Translated body only (no frontmatter) — for callers writing their own. */
|
|
9
|
+
body: string;
|
|
10
|
+
ledger: TranslateLedgerEntry[];
|
|
11
|
+
}
|
|
12
|
+
export declare function parseGitbook(src: string): ParseGitbookResult;
|
|
13
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAsB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE/E,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAID,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAc5D"}
|
package/dist/parse.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitBook page → { tree, frontmatter, markdown, ledger }.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline:
|
|
5
|
+
* 1. Split YAML frontmatter off the body (so the body transform can't
|
|
6
|
+
* disturb it).
|
|
7
|
+
* 2. Translate the GitBook Git Sync body → Dogsbay-MD text
|
|
8
|
+
* (`gitbookToDogsbayMd`).
|
|
9
|
+
* 3. Parse the translated Dogsbay-MD with the canonical
|
|
10
|
+
* `dogsbayMdToTree` — GitBook markdown is a near-superset of
|
|
11
|
+
* Dogsbay-MD, so its own parser is the definition of correctness
|
|
12
|
+
* and yields the TreeNode with zero new node types.
|
|
13
|
+
*
|
|
14
|
+
* `markdown` (frontmatter + translated body) is what `migrate-gitbook`
|
|
15
|
+
* writes to disk — canonical, editable Dogsbay-MD. `tree` feeds the
|
|
16
|
+
* runtime path (format-astro emit, headings, title).
|
|
17
|
+
*/
|
|
18
|
+
import { dogsbayMdToTree } from "@dogsbay/format-dogsbay-md";
|
|
19
|
+
import { gitbookToDogsbayMd } from "./translate.js";
|
|
20
|
+
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n?/;
|
|
21
|
+
export function parseGitbook(src) {
|
|
22
|
+
const normalized = src.replace(/\r\n?/g, "\n");
|
|
23
|
+
const fmMatch = normalized.match(FRONTMATTER_RE);
|
|
24
|
+
const fmBlock = fmMatch ? fmMatch[0] : "";
|
|
25
|
+
const body = fmMatch ? normalized.slice(fmMatch[0].length) : normalized;
|
|
26
|
+
const { markdown: translatedBody, ledger } = gitbookToDogsbayMd(body);
|
|
27
|
+
const markdown = fmBlock ? `${fmBlock.replace(/\n?$/, "\n")}\n${translatedBody}` : translatedBody;
|
|
28
|
+
// dogsbayMdToTree extracts frontmatter itself (gray-matter) and parses
|
|
29
|
+
// the body into TreeNode[]. Feed it the recombined markdown.
|
|
30
|
+
const { tree, frontmatter } = dogsbayMdToTree(markdown);
|
|
31
|
+
return { tree, frontmatter: frontmatter ?? {}, markdown, body: translatedBody, ledger };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAA6B,MAAM,gBAAgB,CAAC;AAY/E,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAElD,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IAExE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,cAAc,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC;IAElG,uEAAuE;IACvE,6DAA6D;IAC7D,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAExD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;AAC1F,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitBook Git Sync markdown → Dogsbay-MD text translator.
|
|
3
|
+
*
|
|
4
|
+
* GitBook's Git Sync dialect is CommonMark + liquid-style `{% tag %}`
|
|
5
|
+
* blocks + a handful of raw-HTML emissions. Dogsbay-MD is CommonMark +
|
|
6
|
+
* `:::` block directives + `{attrs}`. So translation is largely a
|
|
7
|
+
* delimiter rewrite: the inline/prose/list/table markdown passes through
|
|
8
|
+
* untouched; only the `{% %}` tags and specific HTML shapes are rewritten.
|
|
9
|
+
*
|
|
10
|
+
* Two structural classes of `{% %}` tag:
|
|
11
|
+
* - **Directive tags** (hint, tabs/tab, stepper/step, columns/column,
|
|
12
|
+
* expandable) map to `:::` block directives and can nest. These are
|
|
13
|
+
* parsed into a region tree and emitted with DEPTH-AWARE fence lengths
|
|
14
|
+
* (outer directives get more colons than inner) — markdown-it-container
|
|
15
|
+
* closes an outer `:::` at the first bare `:::` otherwise, so equal
|
|
16
|
+
* fence lengths would break nesting. Mirrors format-dogsbay-md's
|
|
17
|
+
* serializer fence-scaling.
|
|
18
|
+
* - **Leaf/opaque tags** (code, embed, content-ref, file, page-ref,
|
|
19
|
+
* include, openapi, swagger, math) transform to a self-contained
|
|
20
|
+
* markdown string in one shot; they don't participate in `:::` nesting.
|
|
21
|
+
*
|
|
22
|
+
* Fence-aware throughout: `{% %}` inside a fenced code block is literal
|
|
23
|
+
* and never rewritten.
|
|
24
|
+
*
|
|
25
|
+
* Anything unmapped is recorded in the returned `ledger` (never silent
|
|
26
|
+
* loss — same discipline as format-dita) and passed through as raw text.
|
|
27
|
+
*
|
|
28
|
+
* See plans/format-gitbook.md and
|
|
29
|
+
* dogsbay-research/content/formats/gitbook-import-support.md.
|
|
30
|
+
*/
|
|
31
|
+
export interface TranslateLedgerEntry {
|
|
32
|
+
/** The GitBook construct that wasn't cleanly mapped. */
|
|
33
|
+
construct: string;
|
|
34
|
+
/** Human-readable note on how it was handled. */
|
|
35
|
+
note: string;
|
|
36
|
+
/** 1-based source line, when known. */
|
|
37
|
+
line?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface TranslateResult {
|
|
40
|
+
markdown: string;
|
|
41
|
+
ledger: TranslateLedgerEntry[];
|
|
42
|
+
}
|
|
43
|
+
export declare function gitbookToDogsbayMd(src: string): TranslateResult;
|
|
44
|
+
//# sourceMappingURL=translate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAgED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAsG/D"}
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitBook Git Sync markdown → Dogsbay-MD text translator.
|
|
3
|
+
*
|
|
4
|
+
* GitBook's Git Sync dialect is CommonMark + liquid-style `{% tag %}`
|
|
5
|
+
* blocks + a handful of raw-HTML emissions. Dogsbay-MD is CommonMark +
|
|
6
|
+
* `:::` block directives + `{attrs}`. So translation is largely a
|
|
7
|
+
* delimiter rewrite: the inline/prose/list/table markdown passes through
|
|
8
|
+
* untouched; only the `{% %}` tags and specific HTML shapes are rewritten.
|
|
9
|
+
*
|
|
10
|
+
* Two structural classes of `{% %}` tag:
|
|
11
|
+
* - **Directive tags** (hint, tabs/tab, stepper/step, columns/column,
|
|
12
|
+
* expandable) map to `:::` block directives and can nest. These are
|
|
13
|
+
* parsed into a region tree and emitted with DEPTH-AWARE fence lengths
|
|
14
|
+
* (outer directives get more colons than inner) — markdown-it-container
|
|
15
|
+
* closes an outer `:::` at the first bare `:::` otherwise, so equal
|
|
16
|
+
* fence lengths would break nesting. Mirrors format-dogsbay-md's
|
|
17
|
+
* serializer fence-scaling.
|
|
18
|
+
* - **Leaf/opaque tags** (code, embed, content-ref, file, page-ref,
|
|
19
|
+
* include, openapi, swagger, math) transform to a self-contained
|
|
20
|
+
* markdown string in one shot; they don't participate in `:::` nesting.
|
|
21
|
+
*
|
|
22
|
+
* Fence-aware throughout: `{% %}` inside a fenced code block is literal
|
|
23
|
+
* and never rewritten.
|
|
24
|
+
*
|
|
25
|
+
* Anything unmapped is recorded in the returned `ledger` (never silent
|
|
26
|
+
* loss — same discipline as format-dita) and passed through as raw text.
|
|
27
|
+
*
|
|
28
|
+
* See plans/format-gitbook.md and
|
|
29
|
+
* dogsbay-research/content/formats/gitbook-import-support.md.
|
|
30
|
+
*/
|
|
31
|
+
/** GitBook hint style → Dogsbay callout directive name. */
|
|
32
|
+
const HINT_STYLE_TO_CALLOUT = {
|
|
33
|
+
info: "info",
|
|
34
|
+
success: "success",
|
|
35
|
+
warning: "warning",
|
|
36
|
+
danger: "danger",
|
|
37
|
+
note: "note",
|
|
38
|
+
tip: "tip",
|
|
39
|
+
};
|
|
40
|
+
/** Leaf tags with no matching `{% end… %}` — transformed inline. */
|
|
41
|
+
const LEAF_TAGS = new Set(["include", "page-ref"]);
|
|
42
|
+
/** Directive tags: GitBook tag → Dogsbay directive name (or resolver). */
|
|
43
|
+
const DIRECTIVE_TAGS = new Set([
|
|
44
|
+
"hint",
|
|
45
|
+
"tabs",
|
|
46
|
+
"tab",
|
|
47
|
+
"stepper",
|
|
48
|
+
"step",
|
|
49
|
+
"columns",
|
|
50
|
+
"column",
|
|
51
|
+
"expandable",
|
|
52
|
+
]);
|
|
53
|
+
// ── Attribute parsing ─────────────────────────────────────────────────────
|
|
54
|
+
/** Parse `key="value"` pairs (and bare `key`) from a tag's attribute text. */
|
|
55
|
+
function parseAttrs(attrText) {
|
|
56
|
+
const out = {};
|
|
57
|
+
const re = /(\w[\w-]*)\s*=\s*"([^"]*)"/g;
|
|
58
|
+
let m;
|
|
59
|
+
while ((m = re.exec(attrText)))
|
|
60
|
+
out[m[1]] = m[2];
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
/** Serialize a Dogsbay `{key="value"}` attribute block (empty → ""). */
|
|
64
|
+
function attrBlock(attrs) {
|
|
65
|
+
const keys = Object.keys(attrs);
|
|
66
|
+
if (keys.length === 0)
|
|
67
|
+
return "";
|
|
68
|
+
const inner = keys.map((k) => `${k}="${attrs[k].replace(/"/g, """)}"`).join(" ");
|
|
69
|
+
return `{${inner}}`;
|
|
70
|
+
}
|
|
71
|
+
// ── Fence-aware line scanning ─────────────────────────────────────────────
|
|
72
|
+
const CODE_FENCE_RE = /^(\s*)(`{3,}|~{3,})/;
|
|
73
|
+
/** Match a full-line opening tag `{% name attrs %}` (name captured). */
|
|
74
|
+
const OPEN_TAG_RE = /^\s*\{%\s*([a-z][a-z-]*)\b([^%]*?)\s*%\}\s*$/;
|
|
75
|
+
/** Match a full-line closing tag `{% endname %}`. */
|
|
76
|
+
const CLOSE_TAG_RE = /^\s*\{%\s*end([a-z][a-z-]*)\s*%\}\s*$/;
|
|
77
|
+
/** Match a self-closing/leaf `{% include "…" %}` anywhere on a line. */
|
|
78
|
+
const INCLUDE_RE = /\{%\s*include\s+"([^"]+)"\s*%\}/g;
|
|
79
|
+
// ── Main entry ─────────────────────────────────────────────────────────────
|
|
80
|
+
export function gitbookToDogsbayMd(src) {
|
|
81
|
+
const ledger = [];
|
|
82
|
+
const lines = src.replace(/\r\n?/g, "\n").split("\n");
|
|
83
|
+
// Region stack — index 0 is the root's children.
|
|
84
|
+
const root = [];
|
|
85
|
+
const stack = [root];
|
|
86
|
+
const dirStack = []; // GitBook tag names of open directives, for close matching
|
|
87
|
+
let fence = null; // active code-fence marker
|
|
88
|
+
let i = 0;
|
|
89
|
+
const pushText = (text) => {
|
|
90
|
+
stack[stack.length - 1].push({ kind: "text", text });
|
|
91
|
+
};
|
|
92
|
+
while (i < lines.length) {
|
|
93
|
+
const line = lines[i];
|
|
94
|
+
// Inside a fenced code block: copy verbatim until the fence closes.
|
|
95
|
+
if (fence !== null) {
|
|
96
|
+
pushText(line);
|
|
97
|
+
const fm = line.match(CODE_FENCE_RE);
|
|
98
|
+
if (fm && fm[2][0] === fence[0] && fm[2].length >= fence.length)
|
|
99
|
+
fence = null;
|
|
100
|
+
i++;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const fm = line.match(CODE_FENCE_RE);
|
|
104
|
+
if (fm) {
|
|
105
|
+
fence = fm[2];
|
|
106
|
+
pushText(line);
|
|
107
|
+
i++;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
// Close tags MUST be tested before open tags: `{% endtab %}` also
|
|
111
|
+
// matches OPEN_TAG_RE (as a tag literally named "endtab"), so checking
|
|
112
|
+
// open first would swallow every close and never pop the region stack.
|
|
113
|
+
const close = line.match(CLOSE_TAG_RE);
|
|
114
|
+
if (close) {
|
|
115
|
+
const closeTag = close[1];
|
|
116
|
+
// Only pop when the close matches the CURRENTLY OPEN directive. An
|
|
117
|
+
// orphaned close — e.g. `{% endembed %}` left behind when a leaf
|
|
118
|
+
// embed inside a tab bailed (see consumeSpecialBlock), or any
|
|
119
|
+
// unbalanced/foreign close — must NOT pop, or it would tear down an
|
|
120
|
+
// enclosing :::tab/:::step and spill its content out. Non-matching
|
|
121
|
+
// closes are dropped (the marker line vanishes).
|
|
122
|
+
if (dirStack.length > 0 && dirStack[dirStack.length - 1] === closeTag) {
|
|
123
|
+
stack.pop();
|
|
124
|
+
dirStack.pop();
|
|
125
|
+
}
|
|
126
|
+
i++;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const open = line.match(OPEN_TAG_RE);
|
|
130
|
+
if (open) {
|
|
131
|
+
const tag = open[1];
|
|
132
|
+
const attrText = open[2] ?? "";
|
|
133
|
+
// Leaf tags (no close): include / page-ref. Route through the
|
|
134
|
+
// inline transformer, which also handles their mid-line form.
|
|
135
|
+
if (LEAF_TAGS.has(tag)) {
|
|
136
|
+
pushText(transformContentLine(line, ledger, i + 1));
|
|
137
|
+
i++;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (DIRECTIVE_TAGS.has(tag)) {
|
|
141
|
+
const { name, attrs } = mapDirectiveOpen(tag, attrText, ledger, i + 1);
|
|
142
|
+
const node = { kind: "dir", name, attrs, children: [] };
|
|
143
|
+
stack[stack.length - 1].push(node);
|
|
144
|
+
stack.push(node.children);
|
|
145
|
+
// Track the GITBOOK tag (not the dogsbay name) so a close is
|
|
146
|
+
// matched by its `{% end<tag> %}`.
|
|
147
|
+
dirStack.push(tag);
|
|
148
|
+
i++;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
// Opaque/special block tags: consume to their matching close.
|
|
152
|
+
const consumed = consumeSpecialBlock(tag, attrText, lines, i, ledger);
|
|
153
|
+
if (consumed) {
|
|
154
|
+
pushText(consumed.text);
|
|
155
|
+
i = consumed.nextIndex;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
// Unknown open tag — record and pass through verbatim.
|
|
159
|
+
ledger.push({ construct: `{% ${tag} %}`, note: "unknown tag, passed through verbatim", line: i + 1 });
|
|
160
|
+
pushText(line);
|
|
161
|
+
i++;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
// Content line — apply inline transforms (leaf includes, HTML, emoji).
|
|
165
|
+
pushText(transformContentLine(line, ledger, i + 1));
|
|
166
|
+
i++;
|
|
167
|
+
}
|
|
168
|
+
return { markdown: renderNodes(root, 0).trimEnd() + "\n", ledger };
|
|
169
|
+
}
|
|
170
|
+
// ── Directive open mapping ────────────────────────────────────────────────
|
|
171
|
+
function mapDirectiveOpen(tag, attrText, ledger, line) {
|
|
172
|
+
const a = parseAttrs(attrText);
|
|
173
|
+
switch (tag) {
|
|
174
|
+
case "hint": {
|
|
175
|
+
const style = (a.style ?? "info").toLowerCase();
|
|
176
|
+
const name = HINT_STYLE_TO_CALLOUT[style];
|
|
177
|
+
if (!name) {
|
|
178
|
+
ledger.push({ construct: `{% hint style="${style}" %}`, note: `unknown hint style → :::note`, line });
|
|
179
|
+
return { name: "note", attrs: "" };
|
|
180
|
+
}
|
|
181
|
+
return { name, attrs: "" };
|
|
182
|
+
}
|
|
183
|
+
case "tabs":
|
|
184
|
+
return { name: "tabs", attrs: "" };
|
|
185
|
+
case "tab":
|
|
186
|
+
return { name: "tab", attrs: a.title ? attrBlock({ title: a.title }) : "" };
|
|
187
|
+
case "stepper":
|
|
188
|
+
return { name: "steps", attrs: "" };
|
|
189
|
+
case "step":
|
|
190
|
+
return { name: "step", attrs: a.title ? attrBlock({ title: a.title }) : "" };
|
|
191
|
+
case "columns":
|
|
192
|
+
return { name: "grid", attrs: "" };
|
|
193
|
+
case "column":
|
|
194
|
+
return { name: "grid-item", attrs: "" };
|
|
195
|
+
case "expandable":
|
|
196
|
+
return { name: "details", attrs: a.title ? attrBlock({ title: a.title }) : "" };
|
|
197
|
+
default:
|
|
198
|
+
return { name: tag, attrs: "" };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// ── Special/opaque block tags ─────────────────────────────────────────────
|
|
202
|
+
/**
|
|
203
|
+
* Handle a block tag whose body needs whole-span transformation rather
|
|
204
|
+
* than `:::` nesting. Returns the emitted markdown + the index of the
|
|
205
|
+
* line after the tag's close, or null if `tag` isn't a special block.
|
|
206
|
+
*/
|
|
207
|
+
function consumeSpecialBlock(tag, attrText, lines, openIndex, ledger) {
|
|
208
|
+
const specials = new Set([
|
|
209
|
+
"code",
|
|
210
|
+
"embed",
|
|
211
|
+
"content-ref",
|
|
212
|
+
"file",
|
|
213
|
+
"openapi",
|
|
214
|
+
"swagger",
|
|
215
|
+
"hint-close-guard", // placeholder, never matches
|
|
216
|
+
]);
|
|
217
|
+
if (!specials.has(tag))
|
|
218
|
+
return null;
|
|
219
|
+
const a = parseAttrs(attrText);
|
|
220
|
+
const line = openIndex + 1;
|
|
221
|
+
// `code` bodies hold a fenced code block that always closes with
|
|
222
|
+
// `{% endcode %}` and may legitimately contain `{`-ish text, so scan
|
|
223
|
+
// it straight through. Every other body-tag (embed, file, content-ref,
|
|
224
|
+
// openapi) ALSO has a leaf form with no close: `{% embed url %}` and
|
|
225
|
+
// `{% file src %}` frequently appear bare, sometimes two in a row. If a
|
|
226
|
+
// foreign `{% %}` tag appears before the close, this is the leaf form —
|
|
227
|
+
// bail so we don't swallow following siblings (GitBook's own tabs.md
|
|
228
|
+
// embed, and snyk's back-to-back file tags, both hit this).
|
|
229
|
+
const closeRe = new RegExp(`^\\s*\\{%\\s*end${tag}\\s*%\\}\\s*$`);
|
|
230
|
+
const body = [];
|
|
231
|
+
let j = openIndex + 1;
|
|
232
|
+
let bailedLeaf = false;
|
|
233
|
+
while (j < lines.length && !closeRe.test(lines[j])) {
|
|
234
|
+
if (tag !== "code" && /^\s*\{%/.test(lines[j])) {
|
|
235
|
+
bailedLeaf = true;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
body.push(lines[j]);
|
|
239
|
+
j++;
|
|
240
|
+
}
|
|
241
|
+
const leaf = bailedLeaf || j >= lines.length;
|
|
242
|
+
// Leaf form consumes only the open line; block form consumes the close.
|
|
243
|
+
const nextIndex = leaf ? openIndex + 1 : j + 1;
|
|
244
|
+
const effBody = leaf ? [] : body;
|
|
245
|
+
switch (tag) {
|
|
246
|
+
case "code":
|
|
247
|
+
return { text: transformCodeBlock(a, effBody), nextIndex };
|
|
248
|
+
case "content-ref":
|
|
249
|
+
return { text: transformContentRef(a, effBody), nextIndex };
|
|
250
|
+
case "embed":
|
|
251
|
+
return { text: transformEmbed(a, effBody), nextIndex };
|
|
252
|
+
case "file":
|
|
253
|
+
return { text: transformFile(a, effBody), nextIndex };
|
|
254
|
+
case "openapi":
|
|
255
|
+
ledger.push({ construct: "{% openapi %}", note: "emitted :::api-endpoint placeholder; wire to format-openapi to render", line });
|
|
256
|
+
return { text: transformOpenapi(a, effBody), nextIndex };
|
|
257
|
+
case "swagger":
|
|
258
|
+
ledger.push({ construct: "{% swagger %}", note: "legacy API block emitted as :::api-endpoint placeholder", line });
|
|
259
|
+
return { text: transformSwagger(a, lines, openIndex), nextIndex: skipSwagger(lines, openIndex) };
|
|
260
|
+
default:
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/** `{% code title lineNumbers overflow %}` wrapping a fence → fence + info. */
|
|
265
|
+
function transformCodeBlock(a, body) {
|
|
266
|
+
// Body holds a normal fenced code block. Fold title/lineNumbers into the
|
|
267
|
+
// fence info string (Dogsbay reads `title="…"` and `{…}` attrs there).
|
|
268
|
+
const text = body.join("\n");
|
|
269
|
+
const fenceMatch = text.match(/^(\s*)(`{3,}|~{3,})([^\n]*)\n([\s\S]*?)\n\1\2\s*$/);
|
|
270
|
+
const extra = {};
|
|
271
|
+
if (a.title)
|
|
272
|
+
extra.title = a.title;
|
|
273
|
+
if (a.lineNumbers === "true")
|
|
274
|
+
extra.lineNumbers = "true";
|
|
275
|
+
if (!fenceMatch) {
|
|
276
|
+
// No inner fence — wrap the raw body in one.
|
|
277
|
+
const info = a.title ? ` title="${a.title}"` : "";
|
|
278
|
+
return "```" + info + "\n" + text + "\n```";
|
|
279
|
+
}
|
|
280
|
+
const [, indent, ticks, lang, code] = fenceMatch;
|
|
281
|
+
const attrs = Object.keys(extra).length
|
|
282
|
+
? " " + Object.entries(extra).map(([k, v]) => `${k}="${v}"`).join(" ")
|
|
283
|
+
: "";
|
|
284
|
+
return `${indent}${ticks}${lang.trim()}${attrs}\n${code}\n${indent}${ticks}`;
|
|
285
|
+
}
|
|
286
|
+
/** `{% content-ref url="x" %}[label](x){% endcontent-ref %}` → link-card. */
|
|
287
|
+
function transformContentRef(a, body) {
|
|
288
|
+
const url = a.url ?? "";
|
|
289
|
+
// Body usually holds a fallback `[label](url)`. Prefer its label.
|
|
290
|
+
const linkMatch = body.join("\n").match(/\[([^\]]*)\]\(([^)]+)\)/);
|
|
291
|
+
const label = linkMatch?.[1] || url;
|
|
292
|
+
if (!url)
|
|
293
|
+
return body.join("\n");
|
|
294
|
+
// Heading-target refs (url has #frag) are plain links in GitBook's own
|
|
295
|
+
// normalization; keep those as links, page refs as link-cards.
|
|
296
|
+
if (url.includes("#"))
|
|
297
|
+
return `[${label}](${url})`;
|
|
298
|
+
return `:::link-card{href="${url}"}\n${label}\n:::`;
|
|
299
|
+
}
|
|
300
|
+
/** `{% embed url="x" %}caption{% endembed %}` → link (caption or url). */
|
|
301
|
+
function transformEmbed(a, body) {
|
|
302
|
+
const url = a.url ?? "";
|
|
303
|
+
const caption = body.join(" ").trim();
|
|
304
|
+
if (!url)
|
|
305
|
+
return caption;
|
|
306
|
+
return `[${caption || url}](${url})`;
|
|
307
|
+
}
|
|
308
|
+
/** `{% file src="x" %}caption{% endfile %}` → download link. */
|
|
309
|
+
function transformFile(a, body) {
|
|
310
|
+
const src = a.src ?? "";
|
|
311
|
+
const caption = body.join(" ").trim();
|
|
312
|
+
if (!src)
|
|
313
|
+
return caption;
|
|
314
|
+
return `[${caption || src.split("/").pop() || "file"}](${src})`;
|
|
315
|
+
}
|
|
316
|
+
/** `{% openapi src path method %}` → :::api-endpoint placeholder. */
|
|
317
|
+
function transformOpenapi(a, body) {
|
|
318
|
+
const attrs = {};
|
|
319
|
+
if (a.src)
|
|
320
|
+
attrs.spec = a.src;
|
|
321
|
+
if (a.path)
|
|
322
|
+
attrs.path = a.path;
|
|
323
|
+
if (a.method)
|
|
324
|
+
attrs.method = a.method;
|
|
325
|
+
const fallback = body.join("\n").trim();
|
|
326
|
+
const inner = fallback ? `\n${fallback}\n` : "\n";
|
|
327
|
+
return `:::api-endpoint${attrBlock(attrs)}${inner}:::`;
|
|
328
|
+
}
|
|
329
|
+
/** Legacy `{% swagger %}` + nested `{% swagger-* %}` → api-endpoint stub. */
|
|
330
|
+
function transformSwagger(a, lines, openIndex) {
|
|
331
|
+
const attrs = {};
|
|
332
|
+
if (a.baseUrl)
|
|
333
|
+
attrs.baseUrl = a.baseUrl;
|
|
334
|
+
if (a.path)
|
|
335
|
+
attrs.path = a.path;
|
|
336
|
+
if (a.method)
|
|
337
|
+
attrs.method = a.method;
|
|
338
|
+
if (a.summary)
|
|
339
|
+
attrs.summary = a.summary;
|
|
340
|
+
return `:::api-endpoint${attrBlock(attrs)}\n:::`;
|
|
341
|
+
}
|
|
342
|
+
/** Skip a whole `{% swagger %}…{% endswagger %}` span (nested tags included). */
|
|
343
|
+
function skipSwagger(lines, openIndex) {
|
|
344
|
+
let j = openIndex + 1;
|
|
345
|
+
while (j < lines.length && !/^\s*\{%\s*endswagger\s*%\}/.test(lines[j]))
|
|
346
|
+
j++;
|
|
347
|
+
return j < lines.length ? j + 1 : j;
|
|
348
|
+
}
|
|
349
|
+
// ── Content-line inline transforms ────────────────────────────────────────
|
|
350
|
+
/**
|
|
351
|
+
* Rewrite inline GitBook constructs on a content line:
|
|
352
|
+
* - `{% include "path" %}` → kept verbatim (Dogsbay Minja resolves it)
|
|
353
|
+
* - `{% page-ref page="x" %}` → link
|
|
354
|
+
* - `<figure><img …><figcaption>…</figcaption></figure>` → image + caption
|
|
355
|
+
* - `data-gb-custom-inline` emoji spans → the emoji text
|
|
356
|
+
*
|
|
357
|
+
* Everything else (bold/italic/links/`<table>`/`<mark>`/inline `<img>`)
|
|
358
|
+
* is valid Dogsbay-MD as-is and passes through untouched.
|
|
359
|
+
*/
|
|
360
|
+
function transformContentLine(line, ledger, lineNo) {
|
|
361
|
+
let out = line;
|
|
362
|
+
// page-ref → link (leaf inline tag).
|
|
363
|
+
out = out.replace(/\{%\s*page-ref\s+page="([^"]+)"\s*%\}/g, (_m, p) => {
|
|
364
|
+
const label = String(p).replace(/\.md$/, "").split("/").pop() || p;
|
|
365
|
+
return `[${label}](${p})`;
|
|
366
|
+
});
|
|
367
|
+
// `{% include "…" %}` stays verbatim — Dogsbay's Minja include resolves
|
|
368
|
+
// it at build time (mirrored fragments), same as the AsciiDoc pipeline.
|
|
369
|
+
// (No rewrite; listed here so the intent is explicit.)
|
|
370
|
+
void INCLUDE_RE;
|
|
371
|
+
// Block-image figure → markdown image, caption kept on its own line.
|
|
372
|
+
// Parse the <img> tag and pull src/alt order-independently — GitBook
|
|
373
|
+
// emits both `<img src alt>` and `<img alt src>`, and a positional
|
|
374
|
+
// regex dropped the alt whenever alt came first (review #7).
|
|
375
|
+
out = out.replace(/<figure>\s*(<img\s+[^>]*>)\s*<figcaption>(?:<p>)?([\s\S]*?)(?:<\/p>)?<\/figcaption>\s*<\/figure>/g, (_m, imgTag, cap = "") => {
|
|
376
|
+
const src = imgTag.match(/\bsrc="([^"]*)"/)?.[1] ?? "";
|
|
377
|
+
const alt = imgTag.match(/\balt="([^"]*)"/)?.[1] ?? "";
|
|
378
|
+
const caption = String(cap).trim();
|
|
379
|
+
const img = ``;
|
|
380
|
+
return caption ? `${img}\n\n_${caption}_` : img;
|
|
381
|
+
});
|
|
382
|
+
// data-gb-custom-inline emoji span → the emoji glyph child.
|
|
383
|
+
out = out.replace(/<span[^>]*data-gb-custom-inline[^>]*data-tag="emoji"[^>]*>([^<]*)<\/span>/g, (_m, glyph) => String(glyph));
|
|
384
|
+
return out;
|
|
385
|
+
}
|
|
386
|
+
// ── Render region tree with depth-aware fences ────────────────────────────
|
|
387
|
+
/** Longest run of `:` in a line-start `:::…` directive fence within text. */
|
|
388
|
+
function longestColonFence(text) {
|
|
389
|
+
let max = 0;
|
|
390
|
+
for (const line of text.split("\n")) {
|
|
391
|
+
const m = line.match(/^(:{3,})/);
|
|
392
|
+
if (m)
|
|
393
|
+
max = Math.max(max, m[1].length);
|
|
394
|
+
}
|
|
395
|
+
return max;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Fence length for a directive node: strictly longer than every `:::`
|
|
399
|
+
* fence in its inner content, whether that content is a nested `dir`
|
|
400
|
+
* child OR a TEXT node that already holds a `:::` directive (link-card /
|
|
401
|
+
* api-endpoint, emitted by consumeSpecialBlock for content-ref / openapi
|
|
402
|
+
* / swagger). Ignoring the text case let a callout wrapping a content-ref
|
|
403
|
+
* get an equal-length fence and close early (review #1).
|
|
404
|
+
*/
|
|
405
|
+
function fenceLen(node) {
|
|
406
|
+
let innerMax = 0;
|
|
407
|
+
for (const c of node.children) {
|
|
408
|
+
innerMax = Math.max(innerMax, c.kind === "dir" ? fenceLen(c) : longestColonFence(c.text));
|
|
409
|
+
}
|
|
410
|
+
return Math.max(3, innerMax + 1);
|
|
411
|
+
}
|
|
412
|
+
function renderNodes(nodes, depth) {
|
|
413
|
+
const parts = [];
|
|
414
|
+
for (const n of nodes) {
|
|
415
|
+
if (n.kind === "text") {
|
|
416
|
+
parts.push(n.text);
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
const colons = ":".repeat(fenceLen(n));
|
|
420
|
+
const inner = renderNodes(n.children, depth + 1).trim();
|
|
421
|
+
parts.push(`${colons}${n.name}${n.attrs}\n${inner}\n${colons}`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
// Join preserving blank-line paragraph separation; collapse >2 blanks.
|
|
425
|
+
return parts.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
426
|
+
}
|
|
427
|
+
//# sourceMappingURL=translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dogsbay/format-gitbook",
|
|
3
|
+
"version": "0.2.0-beta.101",
|
|
4
|
+
"description": "GitBook format plugin for Dogsbay — imports GitBook Git Sync (and legacy gitbook-cli) corpora into TreeNode[] by translating the Git Sync markdown dialect to Dogsbay-MD.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./cli": {
|
|
14
|
+
"types": "./dist/cli.d.ts",
|
|
15
|
+
"import": "./dist/cli.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"yaml": "^2.9.0",
|
|
24
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.101",
|
|
25
|
+
"@dogsbay/types": "0.2.0-beta.101"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^25.9.5",
|
|
29
|
+
"typescript": "^5.9.3",
|
|
30
|
+
"vitest": "^4.1.10"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest"
|
|
37
|
+
}
|
|
38
|
+
}
|