@dogsbay/format-mkdocs 0.2.0-beta.13 → 0.2.0-beta.130
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 +0 -1
- package/dist/cli.js +115 -5
- package/dist/export/capabilities.d.ts +22 -0
- package/dist/export/capabilities.js +213 -0
- package/dist/export/to-astro.d.ts +0 -1
- package/dist/export/to-astro.js +10 -2
- package/dist/export/to-mkdocs-project.d.ts +12 -1
- package/dist/export/to-mkdocs-project.js +279 -64
- package/dist/export/to-mkdocs.d.ts +53 -4
- package/dist/export/to-mkdocs.js +905 -104
- package/dist/importer.d.ts +0 -1
- package/dist/importer.js +3 -2
- package/dist/index.d.ts +21 -4
- package/dist/index.js +40 -4
- package/dist/inline-walker.d.ts +0 -1
- package/dist/inline-walker.js +0 -1
- package/dist/loader.d.ts +1 -2
- package/dist/loader.js +28 -9
- package/dist/parse.d.ts +0 -1
- package/dist/parse.js +0 -1
- package/dist/renderers/mermaid.d.ts +0 -1
- package/dist/renderers/mermaid.js +0 -1
- package/dist/rules/admonition.d.ts +0 -1
- package/dist/rules/admonition.js +0 -1
- package/dist/rules/annotations.d.ts +0 -1
- package/dist/rules/annotations.js +0 -1
- package/dist/rules/autodoc.d.ts +1 -2
- package/dist/rules/autodoc.js +1 -3
- package/dist/rules/blocks.d.ts +0 -1
- package/dist/rules/blocks.js +0 -1
- package/dist/rules/content-tabs.d.ts +0 -1
- package/dist/rules/content-tabs.js +0 -1
- package/dist/rules/docusaurus-admonitions.d.ts +0 -1
- package/dist/rules/docusaurus-admonitions.js +0 -1
- package/dist/rules/file-include.d.ts +0 -1
- package/dist/rules/file-include.js +0 -1
- package/dist/rules/footnotes.d.ts +0 -1
- package/dist/rules/footnotes.js +0 -1
- package/dist/rules/icon-shortcode.d.ts +0 -1
- package/dist/rules/icon-shortcode.js +0 -1
- package/dist/rules/keys.d.ts +0 -1
- package/dist/rules/keys.js +0 -1
- package/dist/rules/link-rewrite.d.ts +0 -1
- package/dist/rules/link-rewrite.js +0 -1
- package/dist/rules/math.d.ts +0 -1
- package/dist/rules/math.js +0 -1
- package/dist/rules/md-in-html.d.ts +0 -1
- package/dist/rules/md-in-html.js +0 -1
- package/dist/rules/snippets.d.ts +0 -1
- package/dist/rules/snippets.js +0 -1
- package/dist/rules/templates.d.ts +0 -1
- package/dist/rules/templates.js +0 -1
- package/dist/rules/variants.d.ts +0 -1
- package/dist/rules/variants.js +0 -1
- package/dist/tree.d.ts +0 -1
- package/dist/tree.js +0 -1
- package/dist/utils/indent.d.ts +0 -1
- package/dist/utils/indent.js +0 -1
- package/dist/utils/types.d.ts +0 -1
- package/dist/utils/types.js +0 -1
- package/dist/walker.d.ts +0 -1
- package/dist/walker.js +0 -1
- package/package.json +13 -12
- package/dist/autodoc/markdown-generator.d.ts +0 -6
- package/dist/autodoc/markdown-generator.d.ts.map +0 -1
- package/dist/autodoc/markdown-generator.js +0 -242
- package/dist/autodoc/markdown-generator.js.map +0 -1
- package/dist/autodoc/module-resolver.d.ts +0 -8
- package/dist/autodoc/module-resolver.d.ts.map +0 -1
- package/dist/autodoc/module-resolver.js +0 -218
- package/dist/autodoc/module-resolver.js.map +0 -1
- package/dist/autodoc/python-docstring.d.ts +0 -7
- package/dist/autodoc/python-docstring.d.ts.map +0 -1
- package/dist/autodoc/python-docstring.js +0 -324
- package/dist/autodoc/python-docstring.js.map +0 -1
- package/dist/autodoc/python-parser.d.ts +0 -10
- package/dist/autodoc/python-parser.d.ts.map +0 -1
- package/dist/autodoc/python-parser.js +0 -541
- package/dist/autodoc/python-parser.js.map +0 -1
- package/dist/autodoc/tree-builder.d.ts +0 -9
- package/dist/autodoc/tree-builder.d.ts.map +0 -1
- package/dist/autodoc/tree-builder.js +0 -279
- package/dist/autodoc/tree-builder.js.map +0 -1
- package/dist/autodoc/types.d.ts +0 -128
- package/dist/autodoc/types.d.ts.map +0 -1
- package/dist/autodoc/types.js +0 -2
- package/dist/autodoc/types.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/export/to-astro.d.ts.map +0 -1
- package/dist/export/to-astro.js.map +0 -1
- package/dist/export/to-mkdocs-project.d.ts.map +0 -1
- package/dist/export/to-mkdocs-project.js.map +0 -1
- package/dist/export/to-mkdocs.d.ts.map +0 -1
- package/dist/export/to-mkdocs.js.map +0 -1
- package/dist/importer.d.ts.map +0 -1
- package/dist/importer.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inline-walker.d.ts.map +0 -1
- package/dist/inline-walker.js.map +0 -1
- package/dist/loader.d.ts.map +0 -1
- package/dist/loader.js.map +0 -1
- package/dist/parse.d.ts.map +0 -1
- package/dist/parse.js.map +0 -1
- package/dist/renderers/mermaid.d.ts.map +0 -1
- package/dist/renderers/mermaid.js.map +0 -1
- package/dist/rules/admonition.d.ts.map +0 -1
- package/dist/rules/admonition.js.map +0 -1
- package/dist/rules/annotations.d.ts.map +0 -1
- package/dist/rules/annotations.js.map +0 -1
- package/dist/rules/autodoc.d.ts.map +0 -1
- package/dist/rules/autodoc.js.map +0 -1
- package/dist/rules/blocks.d.ts.map +0 -1
- package/dist/rules/blocks.js.map +0 -1
- package/dist/rules/content-tabs.d.ts.map +0 -1
- package/dist/rules/content-tabs.js.map +0 -1
- package/dist/rules/docusaurus-admonitions.d.ts.map +0 -1
- package/dist/rules/docusaurus-admonitions.js.map +0 -1
- package/dist/rules/file-include.d.ts.map +0 -1
- package/dist/rules/file-include.js.map +0 -1
- package/dist/rules/footnotes.d.ts.map +0 -1
- package/dist/rules/footnotes.js.map +0 -1
- package/dist/rules/icon-shortcode.d.ts.map +0 -1
- package/dist/rules/icon-shortcode.js.map +0 -1
- package/dist/rules/keys.d.ts.map +0 -1
- package/dist/rules/keys.js.map +0 -1
- package/dist/rules/link-rewrite.d.ts.map +0 -1
- package/dist/rules/link-rewrite.js.map +0 -1
- package/dist/rules/math.d.ts.map +0 -1
- package/dist/rules/math.js.map +0 -1
- package/dist/rules/md-in-html.d.ts.map +0 -1
- package/dist/rules/md-in-html.js.map +0 -1
- package/dist/rules/snippets.d.ts.map +0 -1
- package/dist/rules/snippets.js.map +0 -1
- package/dist/rules/templates.d.ts.map +0 -1
- package/dist/rules/templates.js.map +0 -1
- package/dist/rules/variants.d.ts.map +0 -1
- package/dist/rules/variants.js.map +0 -1
- package/dist/tree.d.ts.map +0 -1
- package/dist/tree.js.map +0 -1
- package/dist/utils/indent.d.ts.map +0 -1
- package/dist/utils/indent.js.map +0 -1
- package/dist/utils/types.d.ts.map +0 -1
- package/dist/utils/types.js.map +0 -1
- package/dist/walker.d.ts.map +0 -1
- package/dist/walker.js.map +0 -1
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
1
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readdirSync, writeFileSync, copyFileSync } from "node:fs";
|
|
2
|
+
import { dirname, extname, join } from "node:path";
|
|
3
3
|
import { importMkdocsProject } from "./importer.js";
|
|
4
|
+
import { exportMkdocsProject } from "./export/to-mkdocs-project.js";
|
|
5
|
+
import { formatLedgerReport } from "@dogsbay/serialize-core";
|
|
6
|
+
import { MKDOCS_CAPABILITIES } from "./export/capabilities.js";
|
|
4
7
|
export const plugin = {
|
|
5
8
|
name: "mkdocs",
|
|
6
9
|
canImport: true,
|
|
7
10
|
canExport: true,
|
|
11
|
+
capabilities: MKDOCS_CAPABILITIES,
|
|
8
12
|
detectSource: (path) => existsSync(join(path, "mkdocs.yml")),
|
|
9
13
|
importOptions: [
|
|
10
14
|
{ flags: "--theme <name>", description: "Theme preset (default, material)", default: "default" },
|
|
@@ -12,7 +16,15 @@ export const plugin = {
|
|
|
12
16
|
{ flags: "--custom-css <files>", description: "Custom CSS files to copy (comma-separated)" },
|
|
13
17
|
{ flags: "--docusaurus-admonitions", description: "Enable Docusaurus-style ::: admonitions" },
|
|
14
18
|
],
|
|
15
|
-
|
|
19
|
+
// NOT `--theme`: `dogsbay convert` already owns that flag for the Astro
|
|
20
|
+
// preset, with a default of "default" — which reached this exporter as
|
|
21
|
+
// `theme: name: default`, a theme MkDocs does not have, and every
|
|
22
|
+
// `convert --to mkdocs` project failed its first `mkdocs build`.
|
|
23
|
+
exportOptions: [
|
|
24
|
+
{ flags: "--mkdocs-theme <name>", description: "MkDocs theme for the emitted mkdocs.yml (material | mkdocs | readthedocs)", default: "material" },
|
|
25
|
+
{ flags: "--site-url <url>", description: "site_url for the emitted mkdocs.yml" },
|
|
26
|
+
{ flags: "--repo-url <url>", description: "repo_url for the emitted mkdocs.yml" },
|
|
27
|
+
],
|
|
16
28
|
async import(source, opts) {
|
|
17
29
|
const { pages, nav, config } = await importMkdocsProject(source, opts);
|
|
18
30
|
// Attach config metadata for the exporter to consume
|
|
@@ -26,7 +38,105 @@ export const plugin = {
|
|
|
26
38
|
if (extraCss && Array.isArray(extraCss)) {
|
|
27
39
|
opts.extraCss = extraCss;
|
|
28
40
|
}
|
|
29
|
-
|
|
41
|
+
// Slugs are relative to `docs_dir`, not to the project root — so an
|
|
42
|
+
// `{% include %}` in a page means a file under THERE.
|
|
43
|
+
return { pages, nav, contentRoot: join(source, config.docsDir) };
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* Export: TreeNode pages + nav → a complete MkDocs project.
|
|
47
|
+
*
|
|
48
|
+
* `exportMkdocsProject` is I/O-free and returns a path → content map, so
|
|
49
|
+
* everything this method does is create directories and write bytes. It was
|
|
50
|
+
* written and unit-tested long before it was reachable: `cli.ts` declared
|
|
51
|
+
* `canExport: true` with no `export` method, and `resolveExporter()` filters
|
|
52
|
+
* on `canExport && f.export`, so `--to mkdocs` reported an unknown target
|
|
53
|
+
* while the serializer sat in the same package. That predicate exists
|
|
54
|
+
* BECAUSE of this plugin.
|
|
55
|
+
*/
|
|
56
|
+
async export(pages, nav, output, opts) {
|
|
57
|
+
const result = exportMkdocsProject(pages, nav, {
|
|
58
|
+
siteName: opts.siteName ?? "Documentation",
|
|
59
|
+
siteUrl: opts.siteUrl,
|
|
60
|
+
repoUrl: opts.repoUrl,
|
|
61
|
+
copyright: opts.copyright,
|
|
62
|
+
poweredBy: opts.poweredBy,
|
|
63
|
+
theme: mkdocsTheme(opts),
|
|
64
|
+
});
|
|
65
|
+
for (const [filePath, content] of result.files) {
|
|
66
|
+
const fullPath = join(output, filePath);
|
|
67
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
68
|
+
writeFileSync(fullPath, content);
|
|
69
|
+
}
|
|
70
|
+
console.log(`Generated ${result.files.size} MkDocs files`);
|
|
71
|
+
// Mounted asset dirs, copied under docs/ at the ROOT their refs were
|
|
72
|
+
// rewritten to (`_assets` for an imported corpus, `images`/`assets` for
|
|
73
|
+
// hand-authored content). The serializer emits those refs relative to
|
|
74
|
+
// each page, so the file has to land exactly there or every image 404s
|
|
75
|
+
// with a clean exit code.
|
|
76
|
+
const mounts = opts.assetMounts;
|
|
77
|
+
for (const mount of mounts ?? []) {
|
|
78
|
+
if (!existsSync(mount.dir))
|
|
79
|
+
continue;
|
|
80
|
+
const root = mount.root ?? "_assets";
|
|
81
|
+
const dest = mount.into ? join(output, "docs", root, mount.into) : join(output, "docs", root);
|
|
82
|
+
mkdirSync(dest, { recursive: true });
|
|
83
|
+
if (mount.mediaOnly) {
|
|
84
|
+
copyMediaTree(mount.dir, dest);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
// Skip symlinks rather than copy them: relative links are rewritten to
|
|
88
|
+
// ABSOLUTE paths into the source checkout, so the output only works on
|
|
89
|
+
// the machine that produced it. AsciiBinder corpora are full of them.
|
|
90
|
+
cpSync(mount.dir, dest, {
|
|
91
|
+
recursive: true,
|
|
92
|
+
dereference: false,
|
|
93
|
+
filter: (src) => !lstatSync(src).isSymbolicLink(),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// Co-located media next to the markdown (the mkdocs shape itself).
|
|
97
|
+
const sourceDir = opts.sourceDir;
|
|
98
|
+
if (sourceDir && existsSync(sourceDir))
|
|
99
|
+
copyMediaTree(sourceDir, join(output, "docs"));
|
|
100
|
+
if (!result.ledger.isEmpty) {
|
|
101
|
+
console.log(formatLedgerReport(result.ledger, "mkdocs"));
|
|
102
|
+
}
|
|
30
103
|
},
|
|
31
104
|
};
|
|
32
|
-
|
|
105
|
+
const MEDIA_EXT = new Set([".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".avif", ".mp4", ".webm", ".pdf", ".ico"]);
|
|
106
|
+
/**
|
|
107
|
+
* Copy media files only, preserving the directory shape. Never follows a
|
|
108
|
+
* symlink: AsciiBinder corpora symlink every section back to one images
|
|
109
|
+
* tree, and following them copied a 64 MB tree once per link.
|
|
110
|
+
*/
|
|
111
|
+
function copyMediaTree(from, to) {
|
|
112
|
+
for (const entry of readdirSync(from, { withFileTypes: true })) {
|
|
113
|
+
if (entry.isSymbolicLink())
|
|
114
|
+
continue;
|
|
115
|
+
const src = join(from, entry.name);
|
|
116
|
+
if (entry.isDirectory()) {
|
|
117
|
+
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
118
|
+
continue;
|
|
119
|
+
copyMediaTree(src, join(to, entry.name));
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (!MEDIA_EXT.has(extname(entry.name).toLowerCase()))
|
|
123
|
+
continue;
|
|
124
|
+
// Always copy. A same-size skip saved nothing measurable and silently
|
|
125
|
+
// kept a stale file when a one-character SVG edit left the size unchanged.
|
|
126
|
+
mkdirSync(to, { recursive: true });
|
|
127
|
+
copyFileSync(src, join(to, entry.name));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const MKDOCS_THEMES = new Set(["material", "mkdocs", "readthedocs"]);
|
|
131
|
+
/**
|
|
132
|
+
* The MkDocs theme to write. `--mkdocs-theme` wins; a bare `theme` is honoured
|
|
133
|
+
* only when it names a theme MkDocs actually has, so the Astro preset default
|
|
134
|
+
* ("default") that `convert` passes through can never reach mkdocs.yml.
|
|
135
|
+
*/
|
|
136
|
+
function mkdocsTheme(opts) {
|
|
137
|
+
for (const candidate of [opts.mkdocsTheme, opts.theme]) {
|
|
138
|
+
if (typeof candidate === "string" && MKDOCS_THEMES.has(candidate))
|
|
139
|
+
return candidate;
|
|
140
|
+
}
|
|
141
|
+
return "material";
|
|
142
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the MkDocs (Material + PyMdown) exporter can and cannot represent.
|
|
3
|
+
*
|
|
4
|
+
* This is a CONTRACT, not commentary: `validateCapabilities` rejects any
|
|
5
|
+
* non-full entry without a note, and `tests/capabilities.test.ts` asserts every
|
|
6
|
+
* row of the component × format matrix (`MATRIX_ROWS` in
|
|
7
|
+
* @dogsbay/serialize-core) is declared exactly once. Each cell was set by
|
|
8
|
+
* reading `to-mkdocs.ts` / `to-mkdocs-project.ts` AND running the serializer
|
|
9
|
+
* on real parsed dogsbay-md, not from the extension list.
|
|
10
|
+
*
|
|
11
|
+
* Support levels:
|
|
12
|
+
* full — round-trips faithfully (given the extensions the project
|
|
13
|
+
* emitter enables in mkdocs.yml)
|
|
14
|
+
* partial — survives with reduced fidelity (styling/semantics lost)
|
|
15
|
+
* none — no MkDocs construct; the wrapper is dropped and the content
|
|
16
|
+
* flattened into plain blocks (recorded as the node type)
|
|
17
|
+
*
|
|
18
|
+
* A `partial` here is not necessarily recorded per page — several are known
|
|
19
|
+
* structural limits the serializer does not ledger (noted where so).
|
|
20
|
+
*/
|
|
21
|
+
import type { CapabilityDeclaration } from "@dogsbay/serialize-core";
|
|
22
|
+
export declare const MKDOCS_CAPABILITIES: CapabilityDeclaration[];
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
export const MKDOCS_CAPABILITIES = [
|
|
2
|
+
// ── Blocks ──────────────────────────────────────────────
|
|
3
|
+
{
|
|
4
|
+
feature: "heading",
|
|
5
|
+
support: "partial",
|
|
6
|
+
rendersAs: "`#`–`######` with the authored id as `{ #id }` (attr_list)",
|
|
7
|
+
note: "The id survives; heading classes (`{.cls}`) are dropped, unrecorded.",
|
|
8
|
+
},
|
|
9
|
+
{ feature: "paragraph", support: "full" },
|
|
10
|
+
{ feature: "blockquote", support: "full", rendersAs: "`> …`" },
|
|
11
|
+
{ feature: "unordered-list", support: "full", rendersAs: "`- item`, four-space continuation; task items via pymdownx.tasklist" },
|
|
12
|
+
{ feature: "ordered-list", support: "full", rendersAs: "`1. item` (start number kept)" },
|
|
13
|
+
{ feature: "hr", support: "full", rendersAs: "`---`" },
|
|
14
|
+
{
|
|
15
|
+
feature: "table",
|
|
16
|
+
support: "partial",
|
|
17
|
+
rendersAs: "GFM pipe table; `<table markdown>` with `markdown=\"block\"` cells when a cell holds block content or spans",
|
|
18
|
+
note: "The table's caption, id and classes are dropped, unrecorded.",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
feature: "code",
|
|
22
|
+
support: "partial",
|
|
23
|
+
rendersAs: "fence with language, `title=\"…\"` and `hl_lines` (pymdownx.highlight + superfences)",
|
|
24
|
+
note: "Code annotations are not recreated: the `(N)!` markers come back as literal `(N)` in the code (no `.annotate` class, no `content.code.annotate` feature), unrecorded.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
feature: "math-block",
|
|
28
|
+
support: "partial",
|
|
29
|
+
rendersAs: "`$$ … $$` (pymdownx.arithmatex, generic)",
|
|
30
|
+
note: "The LaTeX survives, but arithmatex `generic` needs MathJax/KaTeX in `extra_javascript` and the emitted mkdocs.yml adds none, so it is not typeset until one is added.",
|
|
31
|
+
},
|
|
32
|
+
{ feature: "deflist", support: "full", rendersAs: "`Term` / `: definition` (def_list)" },
|
|
33
|
+
{ feature: "figure", support: "full", rendersAs: "`<figure markdown>` + `<figcaption>` (md_in_html); the bare image when there is no caption" },
|
|
34
|
+
{ feature: "footnote-list", support: "full", rendersAs: "`[^label]: …` (footnotes)" },
|
|
35
|
+
{ feature: "html", support: "full", rendersAs: "raw HTML passed through, site-rooted asset paths made relative" },
|
|
36
|
+
{ feature: "html-container", support: "full", rendersAs: "`<tag attrs markdown>` (md_in_html); `on*` attributes stripped" },
|
|
37
|
+
{
|
|
38
|
+
feature: "diagram",
|
|
39
|
+
support: "partial",
|
|
40
|
+
rendersAs: "```mermaid fence (superfences custom fence → Material's Mermaid)",
|
|
41
|
+
note: "Only Mermaid is rendered. Any other diagram language (plantuml, d2, …) is emitted as a fence no configured extension renders, so it shows as source code — unrecorded.",
|
|
42
|
+
},
|
|
43
|
+
{ feature: "youtube", support: "full", rendersAs: "`<iframe>` on youtube-nocookie.com" },
|
|
44
|
+
// ── Components ──────────────────────────────────────────
|
|
45
|
+
{
|
|
46
|
+
feature: "callout",
|
|
47
|
+
support: "partial",
|
|
48
|
+
rendersAs: "`!!! type \"title\"` (admonition)",
|
|
49
|
+
note: "Variants Material lacks map to the nearest (`caution`/`important` → warning, keeping the word as the title); a custom per-callout icon is dropped, unrecorded.",
|
|
50
|
+
},
|
|
51
|
+
{ feature: "details", support: "full", rendersAs: "`??? type \"title\"` / `???+` when open (pymdownx.details)" },
|
|
52
|
+
{ feature: "details-sheet", support: "partial", rendersAs: "a normal collapsible block", note: "MkDocs Material has no side-sheet component: a `sheet` details is written as an ordinary collapsible block, content intact." },
|
|
53
|
+
{ feature: "theme", support: "partial", rendersAs: "the content, unthemed", note: "MkDocs Material has no scoped themes: the wrapper is dropped and the content kept, in the page's own theme." },
|
|
54
|
+
{ feature: "tabs-variant", support: "partial", rendersAs: "the default tabs", note: "MkDocs Material draws one tab style: a pills or underline variant shows as the default." },
|
|
55
|
+
{ feature: "tone", support: "partial", rendersAs: "untinted cards", note: "MkDocs Material cards take no tone: the colour is lost, the content kept." },
|
|
56
|
+
{ feature: "tabs", support: "full", rendersAs: "`=== \"Label\"` (pymdownx.tabbed, alternate_style)" },
|
|
57
|
+
{
|
|
58
|
+
feature: "steps",
|
|
59
|
+
support: "partial",
|
|
60
|
+
rendersAs: "ordered list with bold step titles",
|
|
61
|
+
note: "MkDocs has no steps component; recorded as `steps` degraded.",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
feature: "accordion",
|
|
65
|
+
support: "partial",
|
|
66
|
+
rendersAs: "one `??? note \"Label\"` fold per item (pymdownx.details)",
|
|
67
|
+
note: "Material has no accordion: items fold independently, so opening one does not close the others, and a `defaultValue` is not applied.",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
feature: "cards",
|
|
71
|
+
support: "partial",
|
|
72
|
+
rendersAs: "`<div class=\"grid cards\" markdown>` list (Material grid cards)",
|
|
73
|
+
note: "A column count is dropped — Material's grid is responsive. Unrecorded.",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
feature: "card",
|
|
77
|
+
support: "partial",
|
|
78
|
+
rendersAs: "grid-card list item: bold title, body, `[:octicons-arrow-right-24: Title](href)`",
|
|
79
|
+
note: "The card's icon is dropped (unrecorded); an href becomes a trailing link rather than a clickable card.",
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
feature: "link-card",
|
|
83
|
+
support: "partial",
|
|
84
|
+
rendersAs: "bold title, description, trailing arrow link (a grid card when inside `cards`)",
|
|
85
|
+
note: "No link-card component; outside a card grid it is plain blocks. Unrecorded.",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
feature: "files",
|
|
89
|
+
support: "partial",
|
|
90
|
+
rendersAs: "the nested list",
|
|
91
|
+
note: "No file-tree view: folders and files are a nested bulleted list.",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
feature: "grid",
|
|
95
|
+
support: "partial",
|
|
96
|
+
rendersAs: "`<div class=\"grid cards\" markdown>` list",
|
|
97
|
+
note: "Rendered with CARD styling (not Material's plain `grid`); the column count is dropped and each `grid-item` wrapper is recorded as `grid-item`.",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
feature: "link-button",
|
|
101
|
+
support: "partial",
|
|
102
|
+
rendersAs: "`[label](href){ .md-button .md-button--primary }`",
|
|
103
|
+
note: "Always the primary style — a variant is dropped. An unsafe href is dropped and recorded.",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
feature: "related",
|
|
107
|
+
support: "partial",
|
|
108
|
+
rendersAs: "bold label + the link list",
|
|
109
|
+
note: "No related-links component: the semantic block becomes plain markdown.",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
feature: "example",
|
|
113
|
+
support: "partial",
|
|
114
|
+
rendersAs: "the rendered children as plain blocks",
|
|
115
|
+
note: "No MkDocs example container: the wrapper is dropped (recorded) and the example's source listing (`props.source`) is lost; the preview content is kept.",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
feature: "container",
|
|
119
|
+
support: "partial",
|
|
120
|
+
rendersAs: "the children as plain blocks",
|
|
121
|
+
note: "No MkDocs equivalent: the wrapper, its name and classes are dropped (recorded); the content is kept.",
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
feature: "annotation-list",
|
|
125
|
+
support: "partial",
|
|
126
|
+
rendersAs: "a plain ordered list after the code block",
|
|
127
|
+
note: "Material code annotations are not recreated (see `code`): the list renders as an ordinary numbered list. Unrecorded.",
|
|
128
|
+
},
|
|
129
|
+
// ── API reference ───────────────────────────────────────
|
|
130
|
+
{
|
|
131
|
+
feature: "endpoint",
|
|
132
|
+
support: "none",
|
|
133
|
+
rendersAs: "children only, or `<!-- unsupported: endpoint -->`",
|
|
134
|
+
note: "No case: method, path and summary are lost; any children are kept as plain blocks. Recorded as `endpoint` (action `degraded`, even when nothing survives).",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
feature: "api-doc",
|
|
138
|
+
support: "partial",
|
|
139
|
+
rendersAs: "the docstring HTML converted to inline markdown",
|
|
140
|
+
note: "`props.html` is FLATTENED to one line: paragraphs, lists and code blocks run together with no separators (`<p>A.</p><ul><li>one</li>` → `A.one`). Unrecorded. Children-only api-docs are fine.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
feature: "api-class",
|
|
144
|
+
support: "partial",
|
|
145
|
+
rendersAs: "`### kind \\`name\\``, `Bases:` line, signature as a python fence",
|
|
146
|
+
note: "Plain headings and code, not mkdocstrings' object markup; the signature is always labelled python.",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
feature: "api-member",
|
|
150
|
+
support: "partial",
|
|
151
|
+
rendersAs: "`#### kind \\`name\\``, signature as a python fence",
|
|
152
|
+
note: "As api-class.",
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
feature: "api-params",
|
|
156
|
+
support: "partial",
|
|
157
|
+
rendersAs: "raw HTML PARAMETER/DESCRIPTION table (mkdocstrings' layout)",
|
|
158
|
+
note: "Raw HTML without mkdocstrings' classes, so Material styles it as a plain table.",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
feature: "api-source",
|
|
162
|
+
support: "partial",
|
|
163
|
+
rendersAs: "`*Source: file:line*` + a python fence",
|
|
164
|
+
note: "Not a collapsible source block; the code is always labelled python.",
|
|
165
|
+
},
|
|
166
|
+
// ── Inline ──────────────────────────────────────────────
|
|
167
|
+
{
|
|
168
|
+
feature: "link",
|
|
169
|
+
support: "partial",
|
|
170
|
+
rendersAs: "`[text](href \"title\"){ attrs }`; exported pages as relative `.md` links",
|
|
171
|
+
note: "An inline `:button[…]` link loses its button styling (no `.md-button`), unrecorded. An unsafe href is dropped (text kept) and recorded.",
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
feature: "image",
|
|
175
|
+
support: "full",
|
|
176
|
+
rendersAs: "`{ width height }` with a page-relative path (an unsafe src is refused, alt kept, and recorded)",
|
|
177
|
+
},
|
|
178
|
+
{ feature: "kbd", support: "full", rendersAs: "`++ctrl+s++` (pymdownx.keys); a non-name key as a quoted key" },
|
|
179
|
+
{
|
|
180
|
+
feature: "math",
|
|
181
|
+
support: "partial",
|
|
182
|
+
rendersAs: "`$…$` (pymdownx.arithmatex, generic)",
|
|
183
|
+
note: "As math-block: not typeset until MathJax/KaTeX is added to `extra_javascript`.",
|
|
184
|
+
},
|
|
185
|
+
{ feature: "highlight", support: "full", rendersAs: "`==text==` (pymdownx.mark)" },
|
|
186
|
+
{
|
|
187
|
+
feature: "badge",
|
|
188
|
+
support: "partial",
|
|
189
|
+
rendersAs: "plain text",
|
|
190
|
+
note: "No badge construct: the label is kept, the variant dropped. Recorded as `badge` degraded.",
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
feature: "icon",
|
|
194
|
+
support: "partial",
|
|
195
|
+
rendersAs: "`:name:` (pymdownx.emoji, Material/octicons/fontawesome/simple icon sets)",
|
|
196
|
+
note: "The library prefix is dropped (`lucide:check` → `:check:`); a name outside the Material emoji index renders as literal `:name:` text. Unrecorded.",
|
|
197
|
+
},
|
|
198
|
+
{ feature: "footnote-ref", support: "full", rendersAs: "`[^label]` (footnotes)" },
|
|
199
|
+
{ feature: "html-inline", support: "full", rendersAs: "raw inline HTML passed through" },
|
|
200
|
+
// ── Named concerns the exporter already records ─────────
|
|
201
|
+
{
|
|
202
|
+
feature: "include",
|
|
203
|
+
support: "partial",
|
|
204
|
+
rendersAs: "`--8<-- \"path\"` (pymdownx.snippets)",
|
|
205
|
+
note: "Includes are realized before export; one that arrives unresolved is emitted as a snippet reference and recorded.",
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
feature: "nav-entry",
|
|
209
|
+
support: "partial",
|
|
210
|
+
rendersAs: "mkdocs.yml `nav:` entry",
|
|
211
|
+
note: "A nav entry pointing at a page not in the export (or a section with no exported pages) is dropped and recorded.",
|
|
212
|
+
},
|
|
213
|
+
];
|
|
@@ -23,4 +23,3 @@ export declare function escapeAttr(s: string): string;
|
|
|
23
23
|
/** Escape text for use directly in an Astro template (not inside an expression). */
|
|
24
24
|
export declare function escapeTemplate(s: string): string;
|
|
25
25
|
export declare function treeToAstro(nodes: TreeNode[], options?: AstroGenOptions): AstroGenResult;
|
|
26
|
-
//# sourceMappingURL=to-astro.d.ts.map
|
package/dist/export/to-astro.js
CHANGED
|
@@ -57,7 +57,12 @@ export function escapeExpr(s) {
|
|
|
57
57
|
// JSON.stringify handles all special characters (quotes, backslashes, newlines, etc.)
|
|
58
58
|
// and produces a valid JS string literal. This avoids template literal edge cases
|
|
59
59
|
// where backtick + brace combinations create false expression boundaries.
|
|
60
|
-
|
|
60
|
+
//
|
|
61
|
+
// `<` becomes \u003c: Astro parses the template as HTML before the expression is
|
|
62
|
+
// JavaScript, so a `<script>` inside a string (a code block showing one, say) would
|
|
63
|
+
// be taken for a real script tag and its text compiled as JavaScript. Vite's
|
|
64
|
+
// dependency scan then fails to parse it and a production build breaks.
|
|
65
|
+
return JSON.stringify(s).replace(/</g, "\\u003c");
|
|
61
66
|
}
|
|
62
67
|
/** Escape for use in an HTML attribute value (double-quoted). */
|
|
63
68
|
export function escapeAttr(s) {
|
|
@@ -244,6 +249,8 @@ function inlineNodeToTemplate(node) {
|
|
|
244
249
|
return `<sup><a href="#fn-${escapeAttr(node.label)}" id="fnref-${escapeAttr(node.label)}" class="text-primary hover:underline">[${escapeTemplate(node.label)}]</a></sup>`;
|
|
245
250
|
case "kbd":
|
|
246
251
|
return node.keys.map((k) => `<kbd>${escapeTemplate(k)}</kbd>`).join("+");
|
|
252
|
+
case "badge":
|
|
253
|
+
return `<span data-badge data-variant="${escapeAttr(node.variant ?? "default")}">${escapeTemplate(node.text)}</span>`;
|
|
247
254
|
case "math":
|
|
248
255
|
return `<code class="math-inline">${escapeTemplate(node.latex)}</code>`;
|
|
249
256
|
case "icon":
|
|
@@ -285,6 +292,8 @@ function inlineNodeToHtml(node) {
|
|
|
285
292
|
return `<sup><a href="#fn-${escapeAttr(node.label)}" id="fnref-${escapeAttr(node.label)}" class="text-primary hover:underline">[${escapeHtml(node.label)}]</a></sup>`;
|
|
286
293
|
case "kbd":
|
|
287
294
|
return node.keys.map((k) => `<kbd>${escapeHtml(k)}</kbd>`).join("+");
|
|
295
|
+
case "badge":
|
|
296
|
+
return `<span data-badge data-variant="${escapeAttr(node.variant ?? "default")}">${escapeHtml(node.text)}</span>`;
|
|
288
297
|
case "math":
|
|
289
298
|
return `<code class="math-inline">${escapeHtml(node.latex)}</code>`;
|
|
290
299
|
case "icon":
|
|
@@ -548,4 +557,3 @@ function indentStr(text, spaces) {
|
|
|
548
557
|
function escapeHtml(s) {
|
|
549
558
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
550
559
|
}
|
|
551
|
-
//# sourceMappingURL=to-astro.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ExportPage, NavItem } from "@dogsbay/types";
|
|
2
|
+
import { ExportLedger } from "@dogsbay/serialize-core";
|
|
2
3
|
/**
|
|
3
4
|
* Options for project export.
|
|
4
5
|
*/
|
|
@@ -10,6 +11,15 @@ export interface MkdocsProjectOptions {
|
|
|
10
11
|
extraExtensions?: string[];
|
|
11
12
|
/** Theme name (default: "material") */
|
|
12
13
|
theme?: string;
|
|
14
|
+
/** Existing footer copyright, if the site declares one. */
|
|
15
|
+
copyright?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Append "Powered by DogsBay" to the footer. Default ON; `poweredBy: false`
|
|
18
|
+
* in dogsbay.config.yml removes it. MkDocs has no attribution slot, so it
|
|
19
|
+
* rides along in `copyright:` — the one string Material renders in the
|
|
20
|
+
* footer. See docs/powered-by.md.
|
|
21
|
+
*/
|
|
22
|
+
poweredBy?: boolean;
|
|
13
23
|
}
|
|
14
24
|
/**
|
|
15
25
|
* Result of a project export.
|
|
@@ -18,10 +28,11 @@ export interface MkdocsProjectOptions {
|
|
|
18
28
|
export interface MkdocsProjectExport {
|
|
19
29
|
files: Map<string, string>;
|
|
20
30
|
mkdocsYml: string;
|
|
31
|
+
/** What could not be represented, per page. Empty is the goal, not the assumption. */
|
|
32
|
+
ledger: ExportLedger;
|
|
21
33
|
}
|
|
22
34
|
/**
|
|
23
35
|
* Export a set of pages + navigation to a complete MkDocs project.
|
|
24
36
|
* Returns file map (path → content) including mkdocs.yml and all .md files.
|
|
25
37
|
*/
|
|
26
38
|
export declare function exportMkdocsProject(pages: ExportPage[], nav: NavItem[], options: MkdocsProjectOptions): MkdocsProjectExport;
|
|
27
|
-
//# sourceMappingURL=to-mkdocs-project.d.ts.map
|