blume 2.1.3 → 2.2.1
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/AGENTS.md +1 -1
- package/CHANGELOG.md +134 -0
- package/README.md +4 -4
- package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
- package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
- package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
- package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
- package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
- package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
- package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
- package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
- package/dist/cli/chunk-487b95qy.js +329 -0
- package/dist/cli/chunk-487b95qy.js.map +13 -0
- package/dist/cli/chunk-4zxh25hc.js +157 -0
- package/dist/cli/chunk-4zxh25hc.js.map +10 -0
- package/dist/cli/chunk-69rjf786.js +146 -0
- package/dist/cli/chunk-69rjf786.js.map +11 -0
- package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
- package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
- package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
- package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
- package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
- package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
- package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
- package/dist/cli/chunk-b680sv30.js.map +13 -0
- package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
- package/dist/cli/chunk-beb0z983.js.map +10 -0
- package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
- package/dist/cli/chunk-e1n41w9m.js +155 -0
- package/dist/cli/chunk-e1n41w9m.js.map +11 -0
- package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
- package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
- package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
- package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
- package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
- package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
- package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
- package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
- package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
- package/dist/cli/chunk-hktq4j5r.js.map +36 -0
- package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
- package/dist/cli/chunk-hn3g2b89.js.map +10 -0
- package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
- package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
- package/dist/cli/chunk-k45sq16q.js.map +18 -0
- package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
- package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
- package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
- package/dist/cli/chunk-nqna8dzp.js.map +10 -0
- package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
- package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
- package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
- package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
- package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
- package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
- package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
- package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
- package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
- package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
- package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
- package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
- package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
- package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
- package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
- package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
- package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
- package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
- package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
- package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
- package/dist/cli/chunk-zxd5jrgx.js.map +44 -0
- package/dist/cli/index.js +78 -42
- package/dist/cli/index.js.map +7 -6
- package/dist/types/ai/changelog-components.d.ts +18 -0
- package/dist/types/ai/changelog-markdown.d.ts +12 -0
- package/dist/types/ai/openapi-components.d.ts +7 -7
- package/dist/types/ai/operation-details.d.ts +39 -0
- package/dist/types/ai/relative-links.d.ts +3 -1
- package/dist/types/ai/serializers.d.ts +6 -4
- package/dist/types/analytics/head.d.ts +4 -2
- package/dist/types/analytics/script.d.ts +8 -2
- package/dist/types/components/content/youtube.d.ts +20 -0
- package/dist/types/components/layout/nav-utils.d.ts +8 -0
- package/dist/types/components/openapi/example-panels.d.ts +33 -0
- package/dist/types/components/openapi/helpers.d.ts +53 -11
- package/dist/types/components/openapi/snippets.d.ts +7 -1
- package/dist/types/core/alert-diagnostics.d.ts +10 -0
- package/dist/types/core/builtin-tags.d.ts +16 -0
- package/dist/types/core/changelog-list.d.ts +48 -0
- package/dist/types/core/closest-match.d.ts +6 -0
- package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
- package/dist/types/core/code-fences.d.ts +8 -1
- package/dist/types/core/config-input.d.ts +38 -6
- package/dist/types/core/content-assets.d.ts +16 -18
- package/dist/types/core/data.d.ts +6 -2
- package/dist/types/core/diagnostics.d.ts +14 -0
- package/dist/types/core/directive-diagnostics.d.ts +22 -8
- package/dist/types/core/former-routes.d.ts +14 -0
- package/dist/types/core/github.d.ts +5 -4
- package/dist/types/core/heading-markers.d.ts +65 -2
- package/dist/types/core/hidden-pages.d.ts +3 -0
- package/dist/types/core/includes.d.ts +23 -0
- package/dist/types/core/last-modified.d.ts +18 -6
- package/dist/types/core/links.d.ts +42 -2
- package/dist/types/core/load-module.d.ts +19 -4
- package/dist/types/core/manifest.d.ts +14 -1
- package/dist/types/core/markdown-mirrors.d.ts +22 -0
- package/dist/types/core/mcp-clients.d.ts +47 -0
- package/dist/types/core/mdx-elements.d.ts +32 -0
- package/dist/types/core/mdx-syntax.d.ts +100 -0
- package/dist/types/core/meta-diagnostics.d.ts +7 -0
- package/dist/types/core/meta.d.ts +32 -5
- package/dist/types/core/nav-diagnostics.d.ts +16 -2
- package/dist/types/core/navigation.d.ts +13 -0
- package/dist/types/core/ordering-prefix.d.ts +6 -0
- package/dist/types/core/pinned-ids.d.ts +23 -0
- package/dist/types/core/project-graph.d.ts +9 -1
- package/dist/types/core/redirect-patterns.d.ts +18 -0
- package/dist/types/core/relative-files.d.ts +31 -0
- package/dist/types/core/schema.d.ts +322 -11
- package/dist/types/core/sources/normalize.d.ts +101 -9
- package/dist/types/core/sources/types.d.ts +16 -0
- package/dist/types/core/static-files.d.ts +10 -0
- package/dist/types/core/static-host.d.ts +42 -0
- package/dist/types/core/svg-images.d.ts +26 -0
- package/dist/types/core/syntax-diagnostics.d.ts +14 -0
- package/dist/types/core/types.d.ts +42 -1
- package/dist/types/deploy/generated-files.d.ts +41 -0
- package/dist/types/deploy/redirects.d.ts +21 -7
- package/dist/types/markdown/code-title.d.ts +9 -5
- package/dist/types/markdown/directives.d.ts +8 -0
- package/dist/types/markdown/fence-language.d.ts +51 -0
- package/dist/types/markdown/fence-meta.d.ts +5 -0
- package/dist/types/markdown/github-alerts.d.ts +35 -0
- package/dist/types/openapi/asyncapi.d.ts +6 -5
- package/dist/types/openapi/checks.d.ts +10 -5
- package/dist/types/openapi/model.d.ts +55 -8
- package/dist/types/openapi/parse.d.ts +4 -1
- package/dist/types/ratelimit/index.d.ts +2 -0
- package/dist/types/ratelimit/memory.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +40 -0
- package/dist/types/ratelimit/unkey.d.ts +48 -0
- package/dist/types/sources/filesystem.d.ts +14 -4
- package/dist/types/sources/mdx-remote.d.ts +6 -3
- package/dist/types/sources/registry.d.ts +3 -3
- package/dist/types/theme/color.d.ts +33 -0
- package/dist/types/theme/palette.d.ts +122 -0
- package/docs/01-quickstart.mdx +1 -1
- package/docs/02-deployment.mdx +24 -8
- package/docs/04-migrating.mdx +16 -4
- package/docs/advanced/changelog.mdx +27 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +1 -1
- package/docs/cli/index.mdx +4 -2
- package/docs/cli/validate.mdx +10 -7
- package/docs/configuration/analytics.mdx +2 -0
- package/docs/configuration/customization.mdx +3 -1
- package/docs/configuration/index.mdx +7 -6
- package/docs/configuration/rate-limiting.mdx +20 -1
- package/docs/configuration/theming.mdx +5 -1
- package/docs/content/components.mdx +26 -6
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/i18n.mdx +1 -1
- package/docs/content/includes.mdx +6 -2
- package/docs/content/index.mdx +11 -1
- package/docs/content/islands.mdx +2 -0
- package/docs/content/meta.mdx +9 -3
- package/docs/content/navigation.mdx +14 -6
- package/docs/content/sources/obsidian.mdx +1 -1
- package/docs/content/sources/remote-mdx.mdx +3 -1
- package/docs/content/syntax.mdx +76 -8
- package/docs/content/variables.mdx +3 -1
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/json-api.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/mcp.mdx +40 -8
- package/docs/discoverability/open-graph.mdx +1 -1
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/graphql.mdx +2 -0
- package/docs/references/openapi.mdx +45 -7
- package/package.json +4 -4
- package/skills/blume/SKILL.md +2 -2
- package/skills/blume-migrate/SKILL.md +51 -29
- package/skills/blume-migrate/references/docsify.md +262 -0
- package/skills/blume-migrate/references/docus.md +298 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -5
- package/skills/blume-migrate/references/fern.md +327 -0
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/gitbook.md +267 -0
- package/skills/blume-migrate/references/github-wiki.md +259 -0
- package/skills/blume-migrate/references/jekyll.md +253 -0
- package/skills/blume-migrate/references/mdbook.md +256 -0
- package/skills/blume-migrate/references/mintlify.md +5 -5
- package/skills/blume-migrate/references/mkdocs.md +236 -0
- package/skills/blume-migrate/references/monorepo.md +20 -8
- package/skills/blume-migrate/references/nextra.md +5 -5
- package/skills/blume-migrate/references/readme.md +257 -0
- package/skills/blume-migrate/references/redocly.md +198 -0
- package/skills/blume-migrate/references/starlight.md +3 -3
- package/skills/blume-migrate/references/vitepress.md +204 -0
- package/skills/blume-migrate/references/vuepress.md +271 -0
- package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
- package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
- package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
- package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
- package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
- package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
- package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
- package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
- package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
- package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
- package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
- package/src/ai/changelog-components.ts +24 -0
- package/src/ai/changelog-markdown.ts +45 -41
- package/src/ai/component-markdown.ts +22 -9
- package/src/ai/llms.ts +36 -5
- package/src/ai/markdown.ts +2 -2
- package/src/ai/openapi-components.ts +25 -9
- package/src/ai/operation-details.ts +208 -0
- package/src/ai/relative-links.ts +48 -8
- package/src/ai/serializers.ts +7 -6
- package/src/ai/site-skill.ts +6 -2
- package/src/analytics/head.ts +11 -5
- package/src/analytics/script.ts +13 -3
- package/src/astro/generate.ts +47 -11
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +27 -1
- package/src/astro/mdx-source-errors.ts +46 -0
- package/src/astro/templates.ts +93 -189
- package/src/audit/checks/redirects.ts +5 -1
- package/src/audit/redirects.ts +36 -19
- package/src/audit/report.ts +22 -9
- package/src/audit/run.ts +12 -28
- package/src/audit/terms.ts +23 -0
- package/src/audit/url.ts +2 -2
- package/src/cli/build-failure.ts +256 -7
- package/src/cli/command-meta.ts +1 -1
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +12 -3
- package/src/cli/commands/check.ts +13 -2
- package/src/cli/commands/dev.ts +1 -1
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/init.ts +3 -3
- package/src/cli/commands/preview.ts +17 -1
- package/src/cli/commands/validate.ts +22 -10
- package/src/cli/prepare.ts +1 -1
- package/src/cli/preview-pages.ts +161 -0
- package/src/cli/required-secrets.ts +0 -1
- package/src/cli/unknown-flags.ts +1 -42
- package/src/components/code-copy.ts +51 -0
- package/src/components/code-language.ts +75 -0
- package/src/components/content/AccordionItem.astro +16 -1
- package/src/components/content/Callout.astro +11 -1
- package/src/components/content/Changelog.astro +189 -0
- package/src/components/content/CodeBlock.astro +8 -11
- package/src/components/content/Tabs.astro +16 -2
- package/src/components/content/YouTube.astro +6 -4
- package/src/components/content/code-block.ts +33 -0
- package/src/components/content/content-strings.ts +5 -1
- package/src/components/content/inline-markdown.ts +35 -8
- package/src/components/content/youtube.ts +49 -7
- package/src/components/layout/Analytics.astro +5 -1
- package/src/components/layout/NavTree.astro +8 -3
- package/src/components/layout/PageActions.astro +81 -23
- package/src/components/layout/RootLayout.astro +35 -32
- package/src/components/layout/SiteFooter.astro +31 -8
- package/src/components/layout/nav-utils.ts +14 -0
- package/src/components/layout/search/pagefind.ts +2 -1
- package/src/components/openapi/Operation.astro +4 -0
- package/src/components/openapi/PanelTabs.astro +9 -3
- package/src/components/openapi/RequestBody.astro +42 -8
- package/src/components/openapi/RequestPanel.astro +34 -53
- package/src/components/openapi/example-panels.ts +110 -0
- package/src/components/openapi/helpers.ts +195 -20
- package/src/components/openapi/operation-model.ts +63 -26
- package/src/components/openapi/request.ts +13 -0
- package/src/components/openapi/snippets.ts +14 -2
- package/src/core/alert-diagnostics.ts +89 -0
- package/src/core/builtin-tags.ts +76 -0
- package/src/core/changelog-list.ts +87 -0
- package/src/core/closest-match.ts +41 -0
- package/src/core/code-fence-diagnostics.ts +267 -0
- package/src/core/code-fences.ts +43 -7
- package/src/core/component-diagnostics.ts +65 -12
- package/src/core/config-input.ts +39 -5
- package/src/core/config.ts +46 -1
- package/src/core/content-assets.ts +64 -144
- package/src/core/data.ts +10 -3
- package/src/core/diagnostics.ts +36 -3
- package/src/core/directive-diagnostics.ts +265 -47
- package/src/core/former-routes.ts +46 -0
- package/src/core/git-ignored.ts +53 -0
- package/src/core/github.ts +5 -4
- package/src/core/heading-markers.ts +156 -2
- package/src/core/hidden-pages.ts +64 -0
- package/src/core/includes.ts +181 -41
- package/src/core/last-modified.ts +47 -10
- package/src/core/links.ts +438 -83
- package/src/core/load-module.ts +98 -9
- package/src/core/manifest.ts +12 -9
- package/src/core/markdown-mirrors.ts +52 -0
- package/src/core/mcp-clients.ts +87 -0
- package/src/core/mdx-elements.ts +153 -0
- package/src/core/mdx-syntax.ts +377 -0
- package/src/core/meta-diagnostics.ts +134 -0
- package/src/core/meta.ts +154 -55
- package/src/core/nav-diagnostics.ts +41 -4
- package/src/core/navigation.ts +70 -10
- package/src/core/ordering-prefix.ts +22 -2
- package/src/core/pinned-ids.ts +141 -0
- package/src/core/project-graph.ts +221 -29
- package/src/core/redirect-patterns.ts +41 -0
- package/src/core/relative-files.ts +145 -0
- package/src/core/schema.ts +110 -6
- package/src/core/sources/mdx-remote.ts +75 -14
- package/src/core/sources/normalize.ts +885 -179
- package/src/core/sources/notion.ts +5 -4
- package/src/core/sources/obsidian.ts +2 -5
- package/src/core/sources/types.ts +17 -0
- package/src/core/static-files.ts +40 -0
- package/src/core/static-host.ts +125 -0
- package/src/core/svg-images.ts +98 -0
- package/src/core/syntax-diagnostics.ts +491 -0
- package/src/core/types.ts +43 -1
- package/src/deploy/artifacts.ts +2 -28
- package/src/deploy/generated-files.ts +128 -0
- package/src/deploy/platforms/vercel.ts +25 -1
- package/src/deploy/redirects.ts +43 -16
- package/src/deploy/sitemap.ts +2 -1
- package/src/markdown/base-links.ts +87 -6
- package/src/markdown/code-title.ts +29 -13
- package/src/markdown/content-assets.ts +210 -0
- package/src/markdown/directives.ts +69 -5
- package/src/markdown/fence-language.ts +106 -0
- package/src/markdown/fence-meta.ts +42 -0
- package/src/markdown/github-alerts.ts +172 -0
- package/src/markdown/heading-anchors.ts +265 -56
- package/src/markdown/include.ts +30 -3
- package/src/markdown/index.ts +145 -40
- package/src/markdown/prompt-text.ts +95 -0
- package/src/markdown/relative-links.ts +37 -2
- package/src/markdown/route-snapshot.ts +22 -12
- package/src/markdown/svg-fallback.ts +51 -0
- package/src/markdown/title-heading.ts +134 -0
- package/src/migrate/migrate.ts +127 -2
- package/src/og/card.ts +14 -4
- package/src/openapi/asyncapi.ts +14 -6
- package/src/openapi/checks.ts +160 -15
- package/src/openapi/model.ts +172 -33
- package/src/openapi/parse.ts +13 -4
- package/src/openapi/render-mdx.ts +55 -9
- package/src/openapi/source.ts +87 -6
- package/src/ratelimit/index.ts +2 -0
- package/src/ratelimit/memory.ts +1 -1
- package/src/ratelimit/runtime.ts +81 -0
- package/src/ratelimit/schema.ts +2 -0
- package/src/ratelimit/unkey.ts +61 -0
- package/src/registry/eject.ts +0 -1
- package/src/registry/registry.ts +1 -1
- package/src/search/documents.ts +10 -2
- package/src/sources/filesystem.ts +28 -3
- package/src/sources/mdx-remote.ts +7 -15
- package/src/theme/color.ts +14 -0
- package/src/theme/entry.ts +22 -1
- package/src/theme/palette.ts +74 -1
- package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
- package/dist/cli/chunk-0w6hs479.js.map +0 -10
- package/dist/cli/chunk-150jk7km.js +0 -52
- package/dist/cli/chunk-150jk7km.js.map +0 -10
- package/dist/cli/chunk-36bxs9c7.js.map +0 -10
- package/dist/cli/chunk-53jqw8z0.js +0 -89
- package/dist/cli/chunk-53jqw8z0.js.map +0 -10
- package/dist/cli/chunk-60hz265r.js.map +0 -10
- package/dist/cli/chunk-desvm72z.js.map +0 -14
- package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
- package/dist/cli/chunk-es8h0v3j.js +0 -441
- package/dist/cli/chunk-es8h0v3j.js.map +0 -11
- package/dist/cli/chunk-kdpzw38a.js.map +0 -11
- package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
- package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
- package/dist/cli/chunk-twy7psdz.js.map +0 -10
- package/dist/cli/chunk-ydp3065p.js +0 -64
- package/dist/cli/chunk-ydp3065p.js.map +0 -10
- /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
- /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
- /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
- /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
- /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
- /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
- /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
- /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
- /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
- /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
- /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Jekyll (Just the Docs) → Blume
|
|
2
|
+
|
|
3
|
+
Jekyll is a Ruby static site generator: a `_config.yml`, Markdown pages with front matter, Liquid templating (`{% … %}`, `{{ … }}`) in every page, and Kramdown as the Markdown engine. Docs sites get their navigation from a theme, and the common docs theme is **Just the Docs** (JTD). The work is turning JTD's front-matter navigation into folders and `meta.ts` without moving a URL, and converting the Kramdown and Liquid in every page. Watch for six traps:
|
|
4
|
+
|
|
5
|
+
- **Navigation lives in front matter** (`parent`, `nav_order`), not in folders. URLs come from the file path or `permalink`, so the nav tree and the file tree often disagree.
|
|
6
|
+
- **Kramdown attribute lists (`{: .note }`) and Liquid (`{% include %}`, `{{ site.x }}`) render as literal text in a Blume `.md` page, with a green build.** Each warns at its line (`BLUME_TEMPLATE_TAG` for Liquid, `BLUME_MD_ATTRIBUTE_LIST` for an IAL). In `.mdx` both fail the build, and `blume check` names each line first: `BLUME_MDX_SYNTAX` for Liquid, `BLUME_MDX_ATTRIBUTE_LIST` for an IAL. Callouts are IALs, so most pages need converting.
|
|
7
|
+
- **URLs end in a slash** (`permalink: pretty`, `/a/b/`) or in `.html` (the default), and relative links were written against those URLs.
|
|
8
|
+
- **The page heading is the body `# H1`.** Front matter `title` is the nav label and `<title>`.
|
|
9
|
+
- **Callout names are the site's own**, declared in `_config.yml`. An IAL whose name isn't declared, or is misspelled, rendered a plain paragraph.
|
|
10
|
+
- **What a page shows depends on Liquid and CSS that ran around it** (`jekyll.environment`, `{% if %}`, `_data`, rules in `_sass/custom` that hide sections or add text). The built site is the record of what readers saw.
|
|
11
|
+
|
|
12
|
+
Scope: **Jekyll 4.x with Just the Docs** (gem or `remote_theme`) is supported, and so is a JTD site that GitHub Pages builds with its own Jekyll 3 (differences flagged below). Checked against Jekyll 4.4.1, Just the Docs 0.12.0 (navigation as of 0.10: unlimited depth, `ancestor`), kramdown 2.5.2 with kramdown-parser-gfm 1.1.0, jekyll-redirect-from 0.17.0, GitHub Pages' gem set (`github-pages` 232, Jekyll 3.10.0), and an end-to-end migration of artineering-io/flair-docs (61 pages). **Plain Jekyll and other doc themes are manual** (see the end): the codemod's Kramdown, Liquid, link, and redirect passes apply to any Jekyll site; only the navigation is JTD's.
|
|
13
|
+
|
|
14
|
+
## Detect
|
|
15
|
+
|
|
16
|
+
- **`_config.yml`** at the root or in `docs/` (GitHub Pages' "deploy from `/docs`"). It's generic Jekyll.
|
|
17
|
+
- **Just the Docs:** `theme: just-the-docs` or `remote_theme: just-the-docs/just-the-docs` (also the old `pmarsceill/just-the-docs`, with or without `@ref`) in `_config.yml`, or `gem "just-the-docs"` in the `Gemfile`. Pages carry `nav_order`/`parent`.
|
|
18
|
+
- **Not Jekyll:** a `_toc.yml` beside `_config.yml` is Jupyter Book; `hexo` in `package.json` is Hexo. A `_config.yml` holding only `theme: jekyll-theme-*` publishes a repo's README with GitHub Pages: one page.
|
|
19
|
+
- **Which Jekyll:** a `Gemfile` with `gem "jekyll", "~> 4…"` is 4.x. `gem "github-pages"`, or no `Gemfile` with a `remote_theme`, is GitHub Pages' Jekyll 3 (3.10 today), which also forces nine plugins on (`jekyll-optional-front-matter`, `-readme-index`, `-titles-from-headings`, `-relative-links`, `-default-layout`, `-github-metadata`, `-gist`, `-paginate`, `-coffeescript`): front-matterless Markdown files are pages, `README.md` is its folder's index when there's no `index.md`, an untitled page takes its first heading as `title`, and `[x](page.md)` links work.
|
|
20
|
+
|
|
21
|
+
**Where the Blume project goes:** in the Jekyll source directory (the folder holding `_config.yml`), beside `_includes/` and the pages. Set `content.root: "."` and scope `content.include` to the page files (`["*.{md,mdx}", "docs/**/*.{md,mdx}"]`), and list Jekyll's own `exclude` Markdown (`README.md`, `CHANGELOG.md`) plus `vendor/**` and `node_modules/**` in `content.exclude`, which adds to the defaults `"**/_*"` and `"**/.*"` (`references/monorepo.md` §1). `_includes/` and `_data/` stay unpublished because of their underscore. In a code repo whose Jekyll source is `docs/`, that puts `package.json` in `docs/` and keeps `dist/` out of the repo root.
|
|
22
|
+
|
|
23
|
+
## Build the old site first
|
|
24
|
+
|
|
25
|
+
The old build is your URL list, your nav tree, your heading ids, and the record of what rendered. Build a copy in a folder outside the repo (`<old>` below, an absolute path), with a project-local bundle. CI usually sets `JEKYLL_ENV=production`, which switches analytics and any `jekyll.environment` branches in includes. From the Jekyll source directory:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
rsync -a --exclude .git --exclude _site ./ <old>/src/ && cd <old>/src
|
|
29
|
+
bundle config set --local path vendor/bundle && bundle install
|
|
30
|
+
JEKYLL_ENV=production bundle exec jekyll build -d <old>/site
|
|
31
|
+
cd <old>/site && find . -name '*.html' -not -path './assets/*' | sed 's|^\.||; s|/index\.html$|/|' | sort > <old>/old-urls.txt
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
No `Gemfile` (a GitHub Pages `remote_theme` site): write one with `gem "github-pages", group: :jekyll_plugins`. Recent Rubies moved `csv`, `base64`, `bigdecimal`, and `logger` out of the default gems, so under Bundler an older Jekyll fails to load them: add the one it names to the copy's `Gemfile`. If no build works, use the live site (`pin-heading-ids.mjs --old <url>`) and its `sitemap.xml`, rebuild the nav by hand, and say so.
|
|
35
|
+
|
|
36
|
+
In `old-urls.txt`, a slashed entry is a page. An `.html` entry is a page on a non-`pretty` site, `404.html`, or a jekyll-redirect-from stub, which GitHub Pages serves without the `.html` (`/old` from `old.html`): `redirects.json` in the build lists those. Non-page files Jekyll copied (`LICENSE`, `.bat` scripts, a `Rakefile`) were published by accident unless a page links them: leave them out and report them. On Jekyll 4, a `.md` file with no front matter wasn't a page either: Jekyll copied it raw.
|
|
37
|
+
|
|
38
|
+
## Run the codemod
|
|
39
|
+
|
|
40
|
+
From the Jekyll source directory, dry-run the bundled codemod against the old build, then apply it once, before any hand edits:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
node <skill>/scripts/jekyll-codemod.mjs --old <old>/site . # report only
|
|
44
|
+
node <skill>/scripts/jekyll-codemod.mjs --old <old>/site --write .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
It's zero-dependency and deterministic, and it runs once: `--write` always writes `jekyll-migration.json` and refuses a folder that already has one, because a second pass would take each page's next H1 as its title and convert what `{% raw %}` protected. To run it again, start from a fresh copy of the Jekyll source. It reads `_config.yml` (`callouts`, `url`, `baseurl`, `permalink`, `defaults` permalinks, `exclude`, plain values for `{{ site.x }}`) and every page and Markdown partial in `_includes/`, and converts what maps exactly:
|
|
48
|
+
|
|
49
|
+
- callout IALs → directives (Callouts below), `.label` → `<Badge>`, `.no_toc` and `{#id}` on headings → `[!toc]` and `[#id]`, and JTD's utility and button classes dropped; a malformed IAL, or one naming a class `callouts:` doesn't declare, rendered a plain block, so it goes and is reported;
|
|
50
|
+
- the in-page TOC (the list, its `<details>`, its heading, a partial holding only a TOC), `{::comment}`, ALDs;
|
|
51
|
+
- the body H1 → `title` (a different old `title` → `sidebar.label` and `seo.title`), with a variable it showed written in as its value, since Blume leaves front matter as written; an H1 inside an HTML comment or `<pre>` is skipped. The front matter keys follow the table below;
|
|
52
|
+
- `{% include x.md k="v" %}` and `{% include_relative %}` → `<include k="v">/_includes/x.md</include>` (nested ones too, `{{ include.k }}` → `{{k}}`); a parameter the partial reads but the tag leaves out printed nothing in Jekyll, so it's passed as `k=""`. Also `{{ site.x }}` → `{{x}}` variables, `{{ site.baseurl }}`, `relative_url`, `absolute_url`, `{% link %}`, `{% highlight %}`, `{% comment %}`, and `{% raw %}` (unwrapped, its content untouched);
|
|
53
|
+
- links: relative links resolved against each page's old URL, `.md`, `.html`, own-origin, and trailing-slash links → routes; relative Markdown images rebased from the page's new folder, and a relative raw HTML `src` → a root path (Jekyll resolved it against the page's old URL, which the new folders don't mirror);
|
|
54
|
+
- with `--old`, the sidebar the old build rendered → folders, `slug`s, and `meta.ts` files (Navigation below);
|
|
55
|
+
- each page that now needs MDX → `.mdx`, with void tags self-closed, comments as `{/* */}`, a bare `<` as `<`, autolinks as links, and page `<script>`/`<style>` removed, inline code left as written; partials such a page includes get the same;
|
|
56
|
+
- `redirect_from`, `redirect_to`, `.html` URLs, and the variables → `jekyll-migration.json`, for the config:
|
|
57
|
+
|
|
58
|
+
```ts blume.config.ts
|
|
59
|
+
import { defineConfig } from "blume";
|
|
60
|
+
|
|
61
|
+
import migration from "./jekyll-migration.json" with { type: "json" };
|
|
62
|
+
|
|
63
|
+
export default defineConfig({
|
|
64
|
+
redirects: migration.redirects,
|
|
65
|
+
variables: migration.variables,
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Every `REVIEW` line is a to-do**, and the sections below say what to do with each: HTML includes, Liquid logic, unknown front matter, MDX hazards (a brace in prose, an indented code block), the CSS rules that hid or added content, and the theme files. A `{{ name }}` that `{% raw %}` kept as written collides with a variable of the same name, which Blume fills in everywhere, code included: rename the variable (its key in `jekyll-migration.json` and the `{{name}}` references the codemod wrote). A site whose `_config.yml` has no `callouts:` (before JTD 0.4 added the option, sites styled `.note`/`.warning` in `_sass/custom/custom.scss`) keeps its callout IALs, and the dry run says so: read those rules for the names, then pass `--callouts note,warning` on the write run.
|
|
70
|
+
|
|
71
|
+
After the first `blume build`, pin the old heading ids, rebuilding until it reports 0. Jekyll's GFM ids drop underscores (`f_position` → `#fposition`) where Blume keeps them, so about one id in twenty differs:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
node <skill>/scripts/pin-heading-ids.mjs --old <old>/site --write
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Config: `_config.yml` → `blume.config.ts`
|
|
78
|
+
|
|
79
|
+
Apply `defaults:` (front matter defaults) to the pages in each `scope.path` that the codemod didn't see through: they often set `layout`, and sometimes `parent` or `nav_exclude`.
|
|
80
|
+
|
|
81
|
+
| Jekyll | Blume |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `title` / `description` | `title` / `description` |
|
|
84
|
+
| `url` | `deployment.site`, unless the target is Vercel or Netlify (SKILL.md). GitHub Pages with a custom domain needs it |
|
|
85
|
+
| `baseurl` (`/repo`) | `deployment: { base: "/repo" }`. **The deployed URL decides:** the GitHub Pages starter workflow passes `--baseurl` from the Pages settings, so a custom domain (a `CNAME`) serves at the root whatever `_config.yml` says |
|
|
86
|
+
| `exclude` / `include` | `content.exclude` / `content.include` (Detect) |
|
|
87
|
+
| `permalink`, `defaults`, `collections` | URLs; above; Collections and posts |
|
|
88
|
+
| `plugins` | Plugins |
|
|
89
|
+
| `kramdown.syntax_highlighter_opts.block.line_numbers: true` | no site-wide switch: drop it and report it. Code without line numbers copies cleanly |
|
|
90
|
+
| `kramdown.toc_levels`, and pages built on H4 sections | Blume's outline shows H2–H3, where Kramdown's TOC listed every level. Count the H4s: when they carry the page (attribute references), set `toc: { maxHeadingLevel: 4 }`; else report it |
|
|
91
|
+
| other `markdown`, `kramdown`, `highlighter`, `sass`, `compress_html`, `liquid` keys | drop |
|
|
92
|
+
| `github_username`, `twitter`, `social.links`, a Discord link | `footer.socials` (bluesky, discord, facebook, github, hacker-news, instagram, linkedin, medium, podcast, reddit, slack, telegram, threads, website, x, youtube) |
|
|
93
|
+
| `repository` (jekyll-github-metadata) | `github: { owner, repo }` |
|
|
94
|
+
| `logo` | `logo`, file moved to `public/`. JTD shows the logo _instead of_ the title, so a wordmark needs `logo: { image, text: "" }`; a custom `_includes/title.html` that shows both keeps the text |
|
|
95
|
+
| `favicon_ico` | the file at `public/favicon.ico` (no config field) |
|
|
96
|
+
| `color_scheme: dark` | `theme.mode: "dark"`. `light`/unset → omit. A custom scheme (`_sass/color_schemes/<name>.scss`): its `$link-color` → `theme.accent` (`$blue-000` is `#2c84fa`; look the rest up in the theme's `_sass/support/_variables.scss`), and an `@import "./color_schemes/dark"` in it → `theme.mode: "dark"` |
|
|
97
|
+
| `aux_links` (`"Label": "url"` or `["url"]`) | `navigation.actions: [{ label, href }]`. `aux_links_new_tab` → drop (Blume opens `http(s)` header links in a new tab) |
|
|
98
|
+
| `nav_external_links` (`title`, `url`) | `navigation.featured` (above the sidebar, where JTD listed them below the pages) |
|
|
99
|
+
| `search_enabled: false` | `search: false`. `search.*` options → drop |
|
|
100
|
+
| `nav_enabled: false` | no site-wide switch: `mode: center` on the pages that showed no sidebar |
|
|
101
|
+
| `mermaid` | delete; ` ```mermaid ` renders natively in `.mdx` |
|
|
102
|
+
| `ga_tracking` | `googleAnalytics({ id })` from `blume/analytics`, one per `G-` id in the comma list. A `UA-` id no longer collects data: report it |
|
|
103
|
+
| `gh_edit_link` + `gh_edit_repository` + `gh_edit_branch` | `github: { owner, repo, branch }`. `gh_edit_source: docs` → `github.dir: "docs"` when `blume.config.ts` sits there |
|
|
104
|
+
| `last_edit_timestamp` | `lastModified: "frontmatter"` when pages set `last_modified_date` (the codemod maps it), else drop: JTD showed no date without it |
|
|
105
|
+
| `footer_content` / `_includes/footer_custom.html` | links → `footer.links`, social links → `footer.socials`; copyright text → `footer.copyright`, plain text: strip the tags, decode entities (`©` → `©`), and turn a Liquid year (`{{ "now" \| date: "%Y" }}`) into `${new Date().getFullYear()}` in a template literal; other text → drop (report) or a `Footer` layout slot (`defineComponents`) |
|
|
106
|
+
| `callouts`, `heading_anchors`, `enable_copy_code_button`, `back_to_top*`, `nav_sort`, `nav_error_report`, `ga_tracking_anonymize_ip`, `gh_edit_link_text`, `gh_edit_view_mode` | drop (the codemod read `callouts`) |
|
|
107
|
+
|
|
108
|
+
## Navigation: front matter → folders and `meta.ts`
|
|
109
|
+
|
|
110
|
+
JTD builds one tree from `title`, `parent`, `grand_parent`/`ancestor`, and `nav_order`, wherever the files sit, and shows it as a collapsible tree with only the current section open: set **`navigation.sidebar.display: "group"`**. The codemod rebuilds the tree from the sidebar the old build rendered, so `nav_order` ties, `child_nav_order: reversed`, and `nav_sort` are already resolved, and keeps every URL:
|
|
111
|
+
|
|
112
|
+
- A parent at `dir/index.md` with its children in `dir/` (the layout JTD's docs recommend) moves nothing.
|
|
113
|
+
- A parent that's a leaf file with its children beside it (`docs/setup.md`, `docs/install.md`) becomes a `(group)` folder: `docs/(setup)/index.md` with `slug: docs/setup`, and the children inside it keep their URLs.
|
|
114
|
+
- A child whose file sits elsewhere moves under its parent with `slug: <old route>`. A child _section_ whose folder sits elsewhere is reported: `git mv` it into the parent's folder (into a `(group)` folder, its URLs stay; into a real one, pin each page's `slug`), or leave it. The parent's `meta.ts` already lists it by its folder name.
|
|
115
|
+
- **A `parent` title that names two pages** (two sections both titled "Setup", told apart by neither `grand_parent` nor `ancestor`): JTD listed the child under both. Blume lists a page once, so it stays under the first and the codemod reports it.
|
|
116
|
+
- Each folder gets a `meta.ts`: `pages` in the old order; `title` only where Blume's label for the folder (its name, humanized) differs from JTD's; `directory: "accordion"` where the old parent page listed its children (JTD's `has_toc`, read from the old build), and `"none"` below it where a page didn't, since `directory` inherits.
|
|
117
|
+
- **The duplicate index row:** Blume links a folder's `index` from the group row and lists it again as the first row, where JTD showed it once. The codemod hides that row (`sidebar.hidden: true`); a page the group row links stays in the sitemap, search, and `llms.txt`. `BLUME_NAV_INDEX_TITLE_MISMATCH`, which fails `validate --strict`, flags a hidden index whose `title` differs from its folder's `meta.ts` `title`, unless its `sidebar.label` names the folder title. An index whose H1 differed from its JTD title gets that title as `sidebar.label`, which is the section label, so it passes too. Where neither the page's `title` nor its `sidebar.label` matches the section label (JTD always labeled a section with its page's `title`, so this is rare), the codemod leaves the row visible and says so. The check accepts three ways out: match the two titles, set the page's `sidebar.label` to the folder title, or show the row (remove `sidebar.hidden`).
|
|
118
|
+
- Pages outside the old sidebar (`nav_exclude`, no `title`, a `parent` that matched nothing) get `sidebar.hidden: true`, which also takes them out of search, the sitemap, and `llms.txt`, where JTD still searched them: set `search: { indexing: { includeHiddenPages: true } }` if they should stay searchable. A hidden home page is the exception: the root URL serves it, so it stays listed. An external `nav_external_links` entry is listed for `navigation.featured`.
|
|
119
|
+
|
|
120
|
+
What's left for you:
|
|
121
|
+
|
|
122
|
+
- **A wrapper folder JTD never showed** (the template's `docs/`, any folder whose pages sit at the nav's top level) becomes one group around them. Blume opens a group that's the sidebar's only top-level row by itself, but one beside the home page's row or another section starts closed off its own pages, so the codemod writes `collapsed: false` in its `meta.ts`. A `navigation.tabs` entry instead lifts its pages to the sidebar's top level, but there pages list above groups, so JTD's interleaved order breaks. Keep the group unless the user asks for a tab.
|
|
123
|
+
- **The home page** (`index.md`, often `layout: home` and untitled) stays the content root's `index`. When the old nav never showed it, the codemod hides its row like any page outside the nav; a hidden home page stays in the sitemap, search, and `llms.txt`. Give it a `title` (Blume renders it as the H1, where JTD showed none) or `mode: frame` to keep the sidebar without one. Where the home page headed a JTD section, Blume's root index can't head a group: its children stay in their folders, and the codemod reports it.
|
|
124
|
+
- **Moving a page changes what its relative images resolve against.** The codemod rebases the Markdown images it converted, and turns a relative raw HTML `src` into a root path, with a REVIEW to serve that file from `public/`.
|
|
125
|
+
|
|
126
|
+
## URLs and redirects
|
|
127
|
+
|
|
128
|
+
A Jekyll page's URL, for `dir/name.md`:
|
|
129
|
+
|
|
130
|
+
| `permalink` (global) | `dir/name.md` | `dir/index.md` | Blume route |
|
|
131
|
+
| --- | --- | --- | --- |
|
|
132
|
+
| `pretty` | `/dir/name/` | `/dir/` | `/dir/name`, `/dir` |
|
|
133
|
+
| unset (`date`), `none`, `ordinal` | `/dir/name.html` | `/dir/` | same |
|
|
134
|
+
| a style ending in `/` / in `:output_ext` / neither | `/dir/name/` / `.html` / `/dir/name` (file `name.html`) | `/dir/` | same |
|
|
135
|
+
|
|
136
|
+
A page's own `permalink:` wins, then one `defaults:` sets for its folder (the most specific `scope.path`), then the global style. The codemod applies all three, and with `--old` it checks each URL against the build: a page the build doesn't have at that URL gets a REVIEW and no `.html` redirect. Blume serves `<route>/index.html`, so `/dir/name/` keeps working on static hosts, and `blume dev` and `preview` redirect it to `/dir/name`.
|
|
137
|
+
|
|
138
|
+
- **`.html` URLs** become one exact redirect each (a pattern can't strip a suffix). Never add one from `/dir/`, `/dir/index.html`, or `/index.html` (SKILL.md, Redirects).
|
|
139
|
+
- **`redirect_from`** values become redirects as written (`/old` and `/old/` are different `from`s), keeping case (`/w/Main_Page`); one that is the page's own URL is skipped. **`redirect_to`** becomes a redirect from the page's route, and an empty page with it is deleted.
|
|
140
|
+
- **Raw HTML** (`<a href>`, `<img src>`, `<video><source src>`) gains `deployment.base` on a root path, as a Markdown link does, so the root paths the codemod writes from relative links, `{{ site.baseurl }}`, `relative_url`, and `{% link %}` need nothing more. `blume validate` checks a raw `<a href>` against the routes and a media `src` against `public/`.
|
|
141
|
+
- **Jekyll 3's `{% link %}`** doesn't add `baseurl` (Jekyll 4's does, so `{{ site.baseurl }}{% link … %}` doubled it there). The codemod drops both: Blume adds the base itself.
|
|
142
|
+
|
|
143
|
+
## Content: what the codemod leaves
|
|
144
|
+
|
|
145
|
+
**HTML includes** (`{% include x.html … %}`) are never spliced: `<include>` embeds a non-Markdown file as code. Replace each use and delete the partial when nothing uses it:
|
|
146
|
+
|
|
147
|
+
- a figure → a Markdown image, or `<Frame caption="…">` around it;
|
|
148
|
+
- a YouTube iframe → `<YouTube url="…" />`, inside `<Frame caption>` when the include printed a caption; a `width` → drop (report). A playlist URL (`/embed/videoseries?list=…`) works as written;
|
|
149
|
+
- a row of embeds or code blocks in a flex `<div>` → `<Columns cols={2}>`;
|
|
150
|
+
- a jQuery UI accordion (`$(".accordion").accordion()` over alternating question lines and answer `<div>`s) → `<Accordion>` with one `<AccordionItem title>` per question, the first `defaultOpen` as jQuery UI opened it; an `<details>` with Markdown in it → `<Expandable title>` (MDX wraps a `<summary>` and the text after it in one paragraph);
|
|
151
|
+
- a note include (`note.html`, `callout.html`) → a directive.
|
|
152
|
+
|
|
153
|
+
**Liquid logic** (`{% if %}`, `{% for %}`, `{% assign %}`, `{% capture %}`, a dynamic `{% include {{ var }} %}`, a parameter passed as a variable) → the output the old build shows: split a partial with `{% if include.x %}` into one partial per variant, write a `_data` loop's output once as Markdown, inline `{{ page.x }}`. A `{{ site.x }}` that isn't a plain value in `_config.yml` is left too. Liquid ran inside fenced code as well, unless wrapped in `{% raw %}`, so a REVIEW in a code block means the old page showed the rendered value.
|
|
154
|
+
|
|
155
|
+
**CSS that changed content.** The codemod lists every `display: none` and `content: "…"` rule in `_sass/` and `assets/css/`. Find what each targets in the pages: content a rule hid wasn't shown, so delete it (and report the anchors that go with it); text a `::before`/`::after` added (`.label::before { content: "New: " }`) belongs in the converted element's text.
|
|
156
|
+
|
|
157
|
+
**MDX hazards** the codemod lists in `.mdx` pages: a brace in prose (escape it `\{` or put it in backticks), an indented code block (fence it), anything else the build names with a line. A partial with a hazard fails the build at the partial's own line (`blume check` warns `BLUME_MDX_SYNTAX` there first), and an unclosed `<img>` in a partial doesn't fail at all: it pulls the rest of the partial inside its parent element. The codemod self-closes the ones it sees, and `BLUME_MDX_UNCLOSED_ELEMENT` names the partial's line for any left.
|
|
158
|
+
|
|
159
|
+
**A title in a partial:** a page that's only `{% include api/x.md %}` takes its heading from the partial's H1. Move it into the page's `title` (plain text: no `<kbd>` or backticks) and out of the partial, or Blume renders two.
|
|
160
|
+
|
|
161
|
+
**Also by hand:** definition lists (`Term` + `: Definition` → a list or `<dl>`), `*[ABBR]:` abbreviations (delete), Font Awesome `<i class="fa…">` icons (`<Icon icon>` with a Lucide name, or drop), and page scripts the codemod removed (an island, a `PageFooter` slot, or static content: two images instead of a before/after slider).
|
|
162
|
+
|
|
163
|
+
### Callouts
|
|
164
|
+
|
|
165
|
+
JTD has no built-in callout names: each site declares its own under `callouts:` with a `color` and an optional `title`, which JTD printed uppercase above every callout of that name. The codemod maps by the name's meaning, then by color:
|
|
166
|
+
|
|
167
|
+
| JTD name (template color) | Blume |
|
|
168
|
+
| --- | --- |
|
|
169
|
+
| `note` (purple), `important` (blue) | `:::note`, `:::important` (an alias of note) |
|
|
170
|
+
| `tip`, `hint` | `:::tip` |
|
|
171
|
+
| `info`, `highlight` (yellow, untitled) | `:::info` |
|
|
172
|
+
| `warning`, `attention`; `caution` | `:::warning`; `:::caution` (an alias of warning) |
|
|
173
|
+
| `danger`; `error` | `:::danger`; `:::error` (an alias of danger) |
|
|
174
|
+
| `new`, `success` (green) | `:::success` |
|
|
175
|
+
| any other name | by its color: blue → `info`, green → `success`, yellow → `warning`, red → `danger`, purple or grey → `note` |
|
|
176
|
+
|
|
177
|
+
Blume shows a type's icon, not its name, so a configured `title` that only names the directive is dropped and one that says more is kept (`new` titled "New" → `:::success[New]`). `{: .note-title }` takes its title from the blockquote's first paragraph. A callout class on a list, table, or code block rendered no box in JTD (it styles only paragraphs and blockquotes), so it's dropped. The codemod applies each IAL to the block Kramdown did: a list or blockquote that follows a paragraph without a blank line is its own block, and an IAL with blank lines on both sides applies to the next block. An IAL indented under a list item sat inside the item, where Kramdown sometimes boxed the item's paragraph: those are reported, so check the old page and write the callout inside the item by hand.
|
|
178
|
+
|
|
179
|
+
## Front matter
|
|
180
|
+
|
|
181
|
+
The codemod maps these, and reports every other key Blume's strict schema rejects:
|
|
182
|
+
|
|
183
|
+
| Jekyll / JTD | Blume |
|
|
184
|
+
| --- | --- |
|
|
185
|
+
| `title` + body H1 | `title` = the H1; a different old title → `sidebar.label` and `seo.title` |
|
|
186
|
+
| `description`, or `summary` (JTD showed it in child lists) | `description`. JTD only put it in `<meta>`; Blume shows it under the title (report) |
|
|
187
|
+
| `layout: default` / `page` / `home` / `post` / `about` | removed |
|
|
188
|
+
| `layout: minimal`, `nav_enabled: false` | `mode: center` |
|
|
189
|
+
| a custom `layout` from `_layouts/` | reported: pick a `mode` or a custom `.astro` page |
|
|
190
|
+
| JTD nav keys, `permalink`, `redirect_from`, `redirect_to` | removed (Navigation, URLs) |
|
|
191
|
+
| `search_exclude: true` | `search: { exclude: true }` |
|
|
192
|
+
| `last_modified_date` | `lastModified` (ISO date) |
|
|
193
|
+
| `published: false` | `draft: true` |
|
|
194
|
+
| `image` (a string, or `{ path }`), `canonical_url` | `seo.image`, `seo.canonical` |
|
|
195
|
+
| jekyll-seo-tag's `seo:` `type`/`name`/`links` | removed |
|
|
196
|
+
| `sitemap: false` | reported: `seo: { noindex: true }` if it shouldn't be indexed, else delete |
|
|
197
|
+
| `author`, `date`, `lang`, `tags`, `categories`, `excerpt`, `toc` | reported: delete (`tags` → `search.tags` if a hosted search filters on them) |
|
|
198
|
+
|
|
199
|
+
## Theme, layouts, and assets
|
|
200
|
+
|
|
201
|
+
- **`_sass/custom/custom.scss`** → a project-root `theme.css` with only the rules whose markup still exists (figure classes, flex rows): JTD selectors (`.main-content`, `.site-nav`, `.site-title`) match nothing in Blume. Turn hard-coded colors into Blume's tokens.
|
|
202
|
+
- **Theme hook includes** (the codemod lists them): `head_custom.html` (favicons → `public/`, `<meta>` → `seo.metatags`, analytics → adapters, icon-font CSS → drop), `header_custom.html` (an announcement → `banner`), `footer_custom.html` (Config), `title.html` (→ `logo`), `nav_footer_custom.html`, `search_placeholder_custom.html`, `toc_heading_custom.html`, `mermaid_config.js`, `js/custom.js`, `lunr/*` → drop and report what each did.
|
|
203
|
+
- **`_layouts/`** and `.html` pages with front matter → `.mdx` (with `mode: custom` for a landing page) or a custom `.astro` page. `404.html`/`404.md` → delete (Blume ships one).
|
|
204
|
+
- **Assets:** a folder the old site served by root path (`/media/…`, `/assets/images/…`) moves whole to `public/` at the same path. Keep files no page references: other sites may link them. List them, and prune only once the user confirms. JTD's own `assets/css` and `assets/js` go.
|
|
205
|
+
- **Root files** (`favicon.ico`, `apple-touch-icon.png`, `site.webmanifest`, `.well-known/`) → `public/`. A `robots.txt` replaces Blume's generated one: keep it only if it says something Blume's doesn't. `CNAME` and `.nojekyll` aren't needed with a GitHub Actions deploy.
|
|
206
|
+
|
|
207
|
+
## Collections and posts
|
|
208
|
+
|
|
209
|
+
- **A JTD collection** (`collections: { docs: { output: true, permalink: "/:collection/:path/" } }` plus `just_the_docs.collections.docs.name`): rename `_docs/` → `docs/` so the URLs stay `/docs/…`, then run the codemod; give the folder a `meta.ts` `title` from `name`. `nav_fold: true` → `collapsed: true`. A collection document without `title` took its filename as one: write it in.
|
|
210
|
+
- **`_posts/`** → `type: blog` pages (`docs/advanced/blog.mdx`), with `slug` pinned to the old dated URL (`/:categories/:year/:month/:day/:title.html` by default, so also an `.html` redirect) or redirected; `{% post_url %}` → the post's route; jekyll-feed's `/feed.xml` → a redirect to `/blog/rss.xml`.
|
|
211
|
+
|
|
212
|
+
## Plugins
|
|
213
|
+
|
|
214
|
+
| Plugin | Blume |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| `jekyll-redirect-from` | `redirects` (the codemod) |
|
|
217
|
+
| `jekyll-seo-tag`, `jekyll-sitemap` | built in (the sitemap needs `deployment.site`) |
|
|
218
|
+
| `jekyll-relative-links` | built in: the codemod turns `.md` links into routes |
|
|
219
|
+
| `jekyll-include-cache` (`include_cached`) | same as `include` |
|
|
220
|
+
| `jekyll-remote-theme`, `jekyll-default-layout`, `jekyll-optional-front-matter`, `jekyll-titles-from-headings`, `jekyll-readme-index` | delete; the old build shows the pages and titles they made |
|
|
221
|
+
| `jekyll-github-metadata` (`site.github.*`) | inline the values; `repository` → `github` |
|
|
222
|
+
| `jekyll-last-modified-at` | `lastModified: "git"` |
|
|
223
|
+
| `jemoji` (`:smile:`), `jekyll-mentions` (`@user`), `jekyll-gist` | paste the emoji; write the links; a link or a fence |
|
|
224
|
+
| `jekyll-paginate`, `jekyll-coffeescript`, `jekyll-sass-converter`, `jekyll-compose` | drop |
|
|
225
|
+
| anything else (`_plugins/*.rb` included) | read what it does; report it |
|
|
226
|
+
|
|
227
|
+
## Plain Jekyll and other themes: manual
|
|
228
|
+
|
|
229
|
+
Run the codemod without `--old` (or with it, for the URLs): its content and link passes apply to any Jekyll site. The navigation source differs, and there's no tested mapping for it:
|
|
230
|
+
|
|
231
|
+
- **Plain Jekyll / minima:** `header_pages` (a list of files) or no nav. Lay out folders by topic and report the new sidebar.
|
|
232
|
+
- **Minimal Mistakes** (docs layout): `_data/navigation.yml` holds the sidebar (a key such as `docs:` listing `title` + `children: [{ title, url }]`), and pages opt in with `sidebar: { nav: "docs" }`. Convert it like a config-declared nav (SKILL.md). Notices `{: .notice }` and `.notice--primary`/`--info`/`--warning`/`--success`/`--danger` → pass those names with `--callouts` and map the types by hand; `toc: true` and `toc_*` → delete.
|
|
233
|
+
- **Documentation Theme for Jekyll:** `_data/sidebars/*.yml` (`entries` → `folders` → `folderitems`, then `subfolders` → `subfolderitems`), with `sidebar: <file>` and a flat `permalink: name.html` on every page. `{% include note.html content="…" %}` (also `tip`, `warning`, `important`, and `callout.html` with a `type`) → directives; `summary` → `description`; `keywords` → `search.keywords`; `last_updated` → `lastModified`.
|
|
234
|
+
|
|
235
|
+
## Repo integration and teardown
|
|
236
|
+
|
|
237
|
+
- **`package.json`** beside `blume.config.ts` (a Ruby site has none: scaffold it), Node 22.19+, `.gitignore` for `node_modules/`, `.blume/`, `dist/`, `.env.local`.
|
|
238
|
+
- **CI:** replace `bundle exec jekyll build` and the Pages starter workflow with the Blume one (https://useblume.dev/guides/markdown-docs-github-pages). Its `npm ci` needs a lockfile, so commit the `package-lock.json` from `npm install` in the same change. A branch-deployed Pages site moves its source to GitHub Actions in the repo settings, where the custom domain also stays: list both as manual steps. Dependabot's `bundler` entry → `npm`. Scripts that wrapped Jekyll (`serve.bat`, `Rakefile`) → delete or repoint.
|
|
239
|
+
- **Delete** `_config.yml`, `Gemfile`, `Gemfile.lock`, `_layouts/`, `_sass/`, theme hook and HTML includes, JTD's `assets/` files, `_site/`, `.jekyll-cache/`, and `vendor/bundle/`, once everything they declared is harvested. Keep `_includes/` partials pages still `<include>`, and `jekyll-migration.json`.
|
|
240
|
+
- **Grep the whole repo** for moved page paths and for `jekyll` (CODEOWNERS, link checkers, a README "build the docs" section).
|
|
241
|
+
|
|
242
|
+
## Leftover check
|
|
243
|
+
|
|
244
|
+
Rerun until it prints only code samples, `{{name}}` variables and include props you defined, and relative links you meant:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
grep -rnE '\{:[ .#a-z:]|\{%|\{\{|^\*\[|^: |markdown="|<i class="fa|\.html[)#"]|\]\(\.\.?/[^).]*\)|\]\(/[^)]*/(#[^)]*)?\)' \
|
|
248
|
+
--include='*.md' --include='*.mdx' --exclude-dir={node_modules,vendor,_site,.blume,dist} .
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Dropped — report these
|
|
252
|
+
|
|
253
|
+
Callout title labels that only named the type, unconfigured or malformed callout IALs left plain, the button and label styling the codemod dropped, `nav_external_links` moved above the sidebar, `back_to_top`, other `footer_content` text and links inside the copyright, theme hooks, custom color schemes beyond the accent, `_sass` rules with no Blume target, content a CSS rule hid, site-wide code line numbers, deeper TOC levels, `UA-` analytics ids, `sitemap: false`, abbreviations, definition-list styling, Liquid logic and `_data` loops now frozen as content, embed widths, page scripts and widgets (sliders, accordions) not rebuilt, icon-font icons with no Lucide match, accidentally published files (`LICENSE`, `.bat`), and every plugin removed without an equivalent.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# mdBook → Blume
|
|
2
|
+
|
|
3
|
+
mdBook is the Rust project's book generator: a `book.toml`, a hand-written `SUMMARY.md` that is the whole table of contents, and chapters in `src/` rendered by pulldown-cmark after preprocessors rewrite them (the built-in `links` expands `{{#include}}`; plugins like mdbook-admonish and mdbook-mermaid add the rest). Watch for five traps:
|
|
4
|
+
|
|
5
|
+
- **Every URL ends in `.html`** (`src/guide/setup.md` → `/guide/setup.html`, a `README.md` → `index.html`), so every chapter that isn't an index needs an exact redirect.
|
|
6
|
+
- **`SUMMARY.md` is the only navigation, and its nesting rarely exists on disk.** A parent chapter is a page _and_ a group, and its file sits beside its children's folder (`guide.md` + `guide/`) or flat next to them.
|
|
7
|
+
- **`{{#include}}` pulls code from anywhere in the repo, by `ANCHOR` name or line range.** Blume's `<include>` takes whole files from inside the content root only, so code the crate compiles goes through generated excerpts (Includes). Anchors that no longer exist rendered as empty blocks on the old site, with no warning, so expect several.
|
|
8
|
+
- **Fences carry Rust-only syntax.** Hidden `# ` lines and attributes like `rust,ignore` show up as code or kill highlighting if left alone.
|
|
9
|
+
- **The page heading is the body H1, but the sidebar label and `<title>` are the `SUMMARY.md` text**, and the two often differ.
|
|
10
|
+
|
|
11
|
+
Scope: mdBook 0.4.x and 0.5.x, checked against 0.4.48, 0.4.52, and 0.5.4, mdbook-admonish 1.19.0, mdbook-mermaid 0.15.0, and an end-to-end migration of the Linera manual (39 chapters, mdBook 0.4.48). The syntax of mdbook-katex, -toc, -tabs, and -alerts comes from their docs; it wasn't run.
|
|
12
|
+
|
|
13
|
+
## Detect
|
|
14
|
+
|
|
15
|
+
- **`book.toml`**, with `[book]` and usually `[output.html]` tables: only mdBook uses it. It sits at a standalone book's root or in a folder of a code repo (`docs/`, `book/`, `doc/`, `guide/`, `mdbook/`). The chapters live in `[book] src` (default `src/`), which can point outside that folder (`src = "../docs"`).
|
|
16
|
+
- **`SUMMARY.md`** in that `src`. GitBook and HonKit use `SUMMARY.md` too, but with `.gitbook.yaml` or `book.json`, never `book.toml`.
|
|
17
|
+
- CI that runs `mdbook build`/`mdbook test`, `peaceiris/actions-mdbook`, or `cargo install mdbook mdbook-<plugin>`. The workflow that deploys may live in another repo (one that checks the code repo out as a submodule).
|
|
18
|
+
- **Fingerprint the version** from the CI pin. 0.5 removed `curly-quotes`, `multilingual`, `google-analytics`, and `copy-fonts`, rejects unknown `book.toml` keys, and fails on plugins built for 0.4 (mdbook-admonish 1.19.0 and mdbook-mermaid 0.15.0 both do), so most books with plugins still build with 0.4.x.
|
|
19
|
+
|
|
20
|
+
**Where the Blume project goes.** Beside `book.toml`, the folder `mdbook build` ran in, with `content.root` set to the book's `src` (Blume's default is `docs`, so set it unless `src = "docs"`). That keeps `package.json`, `public/`, and `dist/` out of a Rust repo's root. mdBook has no manifest: scaffold `package.json` there (SKILL.md step 6). **A `src` outside that folder (`"../docs"`) works**, edit links included, and a `meta.ts` there imports `defineMeta` from `blume` as usual. That import needs a Blume release after 2.1.3: earlier ones resolved `blume` only from the meta file's own folder up, so it failed with `BLUME_META_LOAD_FAILED … Cannot find module 'blume'`. On those, export a plain object instead (`export default { title: "Developers", display: "flat", pages: […] };`).
|
|
21
|
+
|
|
22
|
+
## Build the old book first
|
|
23
|
+
|
|
24
|
+
Before changing anything, build the book with the version CI pins and its plugins, into a folder outside the repo. Prebuilt binaries of mdBook and most plugins are on their GitHub releases pages (mdbook-admonish has none for Apple Silicon: `cargo install --root <scratch> mdbook-admonish@<version>`); install them in a scratch folder, not globally.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
mdbook build <book-root> -d /abs/path/old-book
|
|
28
|
+
MDBOOK_OUTPUT='{"markdown": {}}' mdbook build <book-root> -d /abs/path/old-md
|
|
29
|
+
(cd /abs/path/old-book && find . -name '*.html' ! -name print.html ! -name toc.html ! -name 404.html | sed 's|^\.||' | sort) > old-urls.txt
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- `old-book` is the old site: its `.html` files are the old URLs, its headings carry the old ids, and its pages show what readers saw. With two or more `[output.*]` tables (`[output.linkcheck]` counts), the HTML lands in `old-book/html/`: use that folder wherever this file says `old-book`.
|
|
33
|
+
- `old-md` is each chapter as Markdown after `{{#include}}` and the other helpers ran (admonish blocks stay as written): what every include actually showed.
|
|
34
|
+
- Under 0.4 a missing plugin only warns, and its blocks render as code; the URLs are still right. Under 0.5 it fails unless `optional = true`.
|
|
35
|
+
|
|
36
|
+
## Config: `book.toml` → `blume.config.ts`
|
|
37
|
+
|
|
38
|
+
Map only what's set. CI can override keys with `MDBOOK_BOOK__…`/`MDBOOK_OUTPUT__…` environment variables, so read those too.
|
|
39
|
+
|
|
40
|
+
| `book.toml` | Blume |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `[book] title` | `title`. Unset, mdBook showed no title: take the first chapter's H1, or ask |
|
|
43
|
+
| `description` | `description` |
|
|
44
|
+
| `src` | `content.root` |
|
|
45
|
+
| `language` (not `en`) | a one-locale `i18n` block (`i18n: { defaultLocale: "fr", locales: [{ code: "fr", label: "Français" }] }`); `text-direction = "rtl"` → that locale's `dir: "rtl"` |
|
|
46
|
+
| `authors`, `multilingual`, `[rust] edition`, `[build] build-dir`, `create-missing`, `extra-watch-dirs` | drop. With `create-missing` (on by default) mdBook created an empty page for a `SUMMARY.md` entry whose file was missing: check the old build |
|
|
47
|
+
| `use-default-preprocessors = false` | without `[preprocessor.links]`/`[preprocessor.index]`, `{{#…}}` stayed literal and `README.md` stayed `README.html`: read the old build |
|
|
48
|
+
| `[output.html] site-url = "/repo/"` | `deployment: { base: "/repo" }`. It's a path, not an origin |
|
|
49
|
+
| `cname` | `deployment: { site: "https://<cname>" }`; GitHub Pages isn't auto-detected. A project site with no domain → `{ site: "https://<owner>.github.io", base: "/<repo>" }` |
|
|
50
|
+
| `git-repository-url` on GitHub | `github: { owner, repo }`. Elsewhere → `navigation.actions` (report) |
|
|
51
|
+
| `edit-url-template` | `github.branch` from the segment after `edit/` or `blob/`. Set `github.dir` to the Blume project's path in the repo (`git rev-parse --show-prefix`), not the template's prefix: mdBook fills `{path}` with `<src>/<file>`, so a `src` outside the book root gave the old site broken edit links (`…/edit/main/../docs/x.md`) |
|
|
52
|
+
| `default-theme`, `preferred-dark-theme` | mdBook switches between them on the reader's system preference. Both dark (`coal`, `navy`, `ayu`) → `theme.mode: "dark"`; a light one plus a dark one → omit. A theme switcher deleted from `theme/index.hbs`, or a stylesheet that repaints the default theme, forces one look: read the CSS, not the name |
|
|
53
|
+
| `additional-css` | a root `theme.css` with only the rules whose markup still exists (`.content`, `.sidebar`, `.chapter`, `--links`, `--sidebar-*` match nothing). Read brand colors and fonts into `theme.accent`, `theme.background`, and `theme.fonts`; Blume already defaults to Inter and IBM Plex Mono. Delete `mdbook-admonish.css` |
|
|
54
|
+
| `additional-js` | delete the mermaid, admonish, and KaTeX assets. A gtag loader → `googleAnalytics({ id })` from `blume/analytics`; other scripts → `script()` or report |
|
|
55
|
+
| a `theme/` folder | diff it against `mdbook init --theme` from the same version first: stock files carry nothing to port, and the stock `favicon.png`/`favicon.svg` are mdBook's own logo (report, don't copy). Custom ones: `<head>` meta tags → `seo.metatags`; analytics → adapters; a favicon → `public/`; fonts → `theme.fonts`; the rest drops (report) |
|
|
56
|
+
| `google-analytics` (0.4) | `googleAnalytics({ id })` for a `G-` id; report a `UA-` id |
|
|
57
|
+
| `mathjax-support` | Math (Other syntax) |
|
|
58
|
+
| `smart-punctuation` / `curly-quotes` | Blume always converts quotes and dashes. Where the old site had it off (0.4's default), `--flag` in prose becomes an en dash: put flags in backticks |
|
|
59
|
+
| `no-section-label` | nothing. Without it, mdBook numbered the chapters (`1.`, `2.3.`) in the sidebar, and Blume can't: report it, and fix prose that cites "chapter 4" |
|
|
60
|
+
| `input-404`, `src/404.md` | delete the page; Blume ships a 404 (`pages/404.astro` to customize) |
|
|
61
|
+
| `[output.html.search]` | built in: drop. `search.chapter."<path>" = { enable = false }` → `search: { exclude: true }` on those pages |
|
|
62
|
+
| `[output.html.fold]` | Navigation |
|
|
63
|
+
| `[output.html.redirect]` | URLs and redirects |
|
|
64
|
+
| `[output.html.playground]`, `[output.html.code.hidelines]` | Code blocks |
|
|
65
|
+
| `[output.html.print]`, `hash-files`, `copy-fonts`, `sidebar-header-nav`, `git-repository-icon`, `definition-lists`, `admonitions`, `live-reload-endpoint`, `[output.markdown]` | drop |
|
|
66
|
+
| `[output.linkcheck]`, `[output.linkcheck2]` | `blume validate --strict` (`--external` for web links) |
|
|
67
|
+
| other backends (EPUB, PDF) | `export: { pdf: true }` prints one page at a time; a whole-book PDF or EPUB has no equivalent (report) |
|
|
68
|
+
|
|
69
|
+
## Preprocessors
|
|
70
|
+
|
|
71
|
+
| `[preprocessor.X]` | Blume |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `links` (built in) | Includes |
|
|
74
|
+
| `index` (built in) | rename every `README.md` chapter to `index.md` |
|
|
75
|
+
| `admonish` | Admonitions |
|
|
76
|
+
| `mermaid` | ` ```mermaid ` works as written in `.mdx`; delete `mermaid.min.js` and `mermaid-init.js` (theme settings in `mermaid-init.js` drop) |
|
|
77
|
+
| `katex` | `$…$` → `$$…$$` inside its sentence; `$$` blocks stay; `\$` → `$`. Custom delimiters → convert from those. A `macros` file has no equivalent: expand the macros |
|
|
78
|
+
| `toc` | delete the `<!-- toc -->` marker (or the configured `marker`): the outline rail replaces it |
|
|
79
|
+
| `pagetoc`, `open-on-gh` | built in (outline rail; `github` edit links): delete |
|
|
80
|
+
| `alerts` | GitHub alerts (Admonitions) |
|
|
81
|
+
| `tabs` | `{{#tabs}}` / `{{#tab name="X"}}` … `{{#endtab}}` / `{{#endtabs}}` → `<Tabs>` / `<Tab title="X">`. `global="…"` drops: Blume syncs same-titled tabs page-wide |
|
|
82
|
+
| `i18n-helpers` (gettext, `po/*.po`) | i18n (Repo integration) |
|
|
83
|
+
| `cmdrun` (`<!-- cmdrun … -->`), `template`, custom ones (`command = "cargo run …"`) | diff `old-md/` against `src/` to see what each one wrote, then freeze that output or move the generator into a prebuild script (report) |
|
|
84
|
+
| `linkcheck` | `blume validate --strict` |
|
|
85
|
+
| other diagram plugins (graphviz, plantuml, svgbob) | render each diagram to an SVG once and commit it, or redraw it in mermaid (report) |
|
|
86
|
+
| anything else | read what it does; report it |
|
|
87
|
+
|
|
88
|
+
## Navigation: `SUMMARY.md` → folders and `meta.ts`
|
|
89
|
+
|
|
90
|
+
### How mdBook reads `SUMMARY.md`
|
|
91
|
+
|
|
92
|
+
- A `# Summary` first line is ignored. **Prefix chapters** are bare `[Title](file.md)` lines before the first list, and can't nest. **Part titles** are `# Title` headings (h1 only) over the numbered chapters that follow: plain headings, not links. **Numbered chapters** are list items (`-`, `*`, or `1.`) that nest by indentation. **Suffix chapters** are bare links after the last list. A **draft** is `[Title]()` (a greyed-out entry, no page). A **separator** is a `---` line; it can also split one part's list, leaving chapters after it under no visible heading.
|
|
93
|
+
- Only listed chapters render. Any other `.md` under `src/` isn't published, but every non-Markdown file there is copied to the site at its own path.
|
|
94
|
+
- A chapter's URL is its path with `.html`; a `README.md` (any case) becomes `index.html`. **The first chapter is also written to `/index.html`.** Its sidebar label and `<title>` are the `SUMMARY.md` text (plus ` - <book title>`); the page shows its own H1.
|
|
95
|
+
|
|
96
|
+
### Put every chapter in place
|
|
97
|
+
|
|
98
|
+
Keep each chapter's path, so its route is the old URL minus `.html`, and keep a table of old URL → file → route as you go: it becomes `redirects`.
|
|
99
|
+
|
|
100
|
+
- **Every `README.md` chapter → `index.md`.** Its route is the folder's, which `x/index.html` already served. Left as is, Blume publishes it at `/x/README`.
|
|
101
|
+
- **A parent chapter beside its children's folder** (`guide.md` + `guide/`): `git mv guide.md guide/index.md`. The route stays `/guide` and the folder row links to it; left in place, `guide.md` is a separate page beside an unlinked "Guide" group. The page moved a level deeper: rewrite its relative links, images, and include paths, and every link to `guide.md`.
|
|
102
|
+
- **Children flat beside their parent** (`ch03-00-concepts.md`, `ch03-01-variables.md`): a `(group)/` folder holding the parent as `index.md` with `slug: ch03-00-concepts`, plus the children. The group adds no URL segment, the `slug` keeps the parent's route, and the group row links to it. Rebase relative paths in every moved file.
|
|
103
|
+
- **The first chapter**, when it isn't the root `README.md`: move it to the content root's `index.md` and redirect its own URL to `/` (`{ from: "/introduction.html", to: "/" }`), since mdBook served it at both.
|
|
104
|
+
- **Ordering prefixes.** Blume drops a leading `\d+[-_.]` from every segment, keeping versions (`1.2.0`) and dates (`2024-01-05`, `12-05-2022`, `2024-01`) whole (`00-overview.md` → `/overview`). Every old URL is redirected anyway, so let Blume drop them (they keep ordering the sidebar) and point those redirects at the new routes, or pin `slug` on each page to keep the old path. Say which.
|
|
105
|
+
- **Files `SUMMARY.md` doesn't list** were never published: a contributors' `README.md` beside the chapters, notes, Markdown that `{{#include}}` pulls in. Prefix them with `_`, move them out of the content root, or add them to `content.exclude` (it adds to the defaults `"**/_*"` and `"**/.*"`). Report them.
|
|
106
|
+
- **A chapter whose body is a `<meta http-equiv="refresh" content="0; url=…">`** is a redirect, not a page to keep: add a redirect from its `.html` URL to the target, a `navigation.featured` link in place of its sidebar entry, and delete it (mdBook's `print.html` ran the same tag, so it sent the whole print page away too). Report it.
|
|
107
|
+
- Delete `SUMMARY.md` once folders and `meta.ts` carry its structure: it would publish as a page.
|
|
108
|
+
- **Check that git sees the new files.** A repo `.gitignore` can cover the content root (pages added before the rule stay tracked), and then every `meta.ts` and partial you create is silently left out of `git add`. Run `git check-ignore -v <content root>/meta.ts` after writing the first one; if it prints a rule, fix that rule or report that each new file needs `git add -f`.
|
|
109
|
+
|
|
110
|
+
### Parts, order, labels, and folding
|
|
111
|
+
|
|
112
|
+
- **Display:** set `navigation: { sidebar: { display: "group" } }`. Parent chapters become collapsible rows, like mdBook's tree, and a group keeps leaf chapters between its subgroups in `meta.ts` order (SKILL.md: `flat` can't interleave them).
|
|
113
|
+
- **Part titles** → a folder per part, with `title: "<part title>"` and `display: "flat"` in its `meta.ts`: a heading, not a row. When a part's chapters already share a folder (`developers/`), that folder is the part; otherwise use a `(part)/` folder at the content root, which changes no URL. Chapters after a separator inside a part get the folder they're already in (`appendix/` reads "Appendix"), or the part's heading.
|
|
114
|
+
- **Order** → a `meta.ts` `pages` array in each folder, every child in `SUMMARY.md` order. The root `meta.ts` orders the parts.
|
|
115
|
+
- **Prefix chapters** stay loose pages at the content root, which Blume lists first, as mdBook did.
|
|
116
|
+
- **What files can't express:** at the top of the sidebar, loose pages always list above folders. Suffix chapters, and leaf chapters between parent chapters in a book with no parts, rise above them. Put each in a `(group)/` folder (it adds a heading), or accept the order. When many chapters are affected, an explicit `navigation.sidebar` keeps `SUMMARY.md`'s order exactly: a route string per leaf chapter, `{ label, root: "<route>", items }` per parent chapter, `{ label, display: "flat", items }` per part. It replaces the generated tree, so it needs an entry per new page, as `SUMMARY.md` did. Report which you chose.
|
|
117
|
+
- **Labels:** `title` is the body H1, what the page showed. `sidebar.label` is the `SUMMARY.md` text where it differs, what the sidebar and `<title>` showed. A page with no H1 takes the `SUMMARY.md` text as `title`. Give each parent chapter's folder `title: "<its SUMMARY.md text>"` in `meta.ts`, or its row shows the humanized folder name. Strip Markdown from `SUMMARY.md` text: backticks render literally in `title`.
|
|
118
|
+
- A parent's `index` page also lists as its group's first row, so the label shows twice. To show it once, as mdBook did, set `sidebar.hidden: true` on the index: it stays in `sitemap.xml` and search because the group row still links to it. If its `title` differs from the folder's `meta.ts` title, set its `sidebar.label` to the folder title, or `BLUME_NAV_INDEX_TITLE_MISMATCH` fails `validate --strict`.
|
|
119
|
+
- **`[output.html.fold]`:** with `enable = true`, sections below `level` started closed (0 closes all), which is `group` mode's default; add `collapsed: false` to the folders mdBook opened. Without folding, mdBook showed every section open: add `collapsed: false` to every folder's `meta.ts`.
|
|
120
|
+
- **Drafts and separators** have no equivalent: drop them, and report the drafts as planned chapters.
|
|
121
|
+
|
|
122
|
+
## Content
|
|
123
|
+
|
|
124
|
+
### `.md` or `.mdx`
|
|
125
|
+
|
|
126
|
+
Rename a page to `.mdx` when it ends up with a callout, mermaid, math, tabs, or another component. Those are MDX-only: in `.md` they don't render, and the build stays green (a `:::` callout only warns `BLUME_MD_DIRECTIVE`). Tables, footnotes, strikethrough, task lists, `[#id]` heading ids, `<include>`, `{{variables}}`, and raw HTML work in both (`{#id}` only in `.md`). Fix what fails `.mdx` in each renamed page: HTML comments → `{/* … */}` on one line, unclosed `<br>`/`<img>`, `<https://…>` autolinks, and `{`, `<` in prose (`Vec<T>` outside backticks).
|
|
127
|
+
|
|
128
|
+
### Includes and the other `{{#…}}` helpers
|
|
129
|
+
|
|
130
|
+
mdBook expands these as text before parsing, so they work inside fences, inline code, and link URLs, and across a line break (`{{#include` at a line's end, the path on the next, as Prettier wraps it). A path resolves from the including file.
|
|
131
|
+
|
|
132
|
+
| mdBook | Blume |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| a fence holding only `{{#include path}}`, the whole file, inside the content root | the whole fence → `<include lang="rust">path</include>` on its own line (the fence's language; its attributes drop) |
|
|
135
|
+
| a fence holding only `{{#include path:anchor}}`, `path:N`, `path:N:M`, `path:N:`, or `path::M`, or any target outside the content root | an excerpt (below), included the same way |
|
|
136
|
+
| a fence mixing includes with hand-written lines | one excerpt that joins `{ "text": "…" }` parts and selections in order, so the block stays generated |
|
|
137
|
+
| `{{#rustdoc_include path:sel}}` | an excerpt of `path:sel`: the selected lines only. The rest of the file sat behind mdBook's expand toggle, which has no equivalent (report) |
|
|
138
|
+
| `{{#playground path attrs}}` | `<include lang="rust">` of the file (an excerpt when it's outside the root); no Run button (report) |
|
|
139
|
+
| `{{#include x.md}}` on its own line | `<include>/_snippets/x.md</include>` (a leading `/` is the content root): a partial must sit under a `_` folder or name, or it publishes as a page. Images in a partial resolve from the partial's own folder (mdBook resolved them from the including chapter), so fix their paths |
|
|
140
|
+
| a one-line file included inline (`{{#include ../VERSION}}` in a URL or a command) | `{{VERSION}}`, with `variables: { VERSION: readFileSync(new URL("../VERSION", import.meta.url), "utf8").trim() }` in `blume.config.ts` (`import { readFileSync } from "node:fs"`). Variables are replaced in links, code, and inline code too |
|
|
141
|
+
| `{{#title X}}` | `seo.title: X` (Blume appends the site title, as for every page) |
|
|
142
|
+
| `\{{#include x}}` (often in a fence that documents mdBook) | drop the backslash, which mdBook removed even inside code. `{{#include x}}` stays literal in code and in `.md`; in `.mdx` prose a `{` fails the build, so put it in inline code |
|
|
143
|
+
|
|
144
|
+
**Excerpts.** `<include>` fails the build on a target outside the content root (`BLUME_INCLUDE_OUTSIDE_ROOT`) and can't select lines. Pasting each excerpt into its page would freeze code that cargo still compiles and tests, so generate them before every run with the bundled `include-excerpts.mjs`:
|
|
145
|
+
|
|
146
|
+
1. Copy `<skill>/scripts/include-excerpts.mjs` beside `blume.config.ts`. Its header documents the manifest.
|
|
147
|
+
2. Write `excerpts.json` there: `out` (`<content root>/_excerpts`, relative to the manifest; Blume doesn't publish a `_` folder), and one entry per excerpt, keyed by its file name under `out`. An include's argument works as written once its path is relative to the manifest's folder (`"counter/abi.rs": "../examples/counter/src/lib.rs:contract_abi"`): the script selects anchors and line ranges exactly as mdBook did. A mixed fence is an array: `[{ "text": "impl Contract for Token {" }, "../src/contract.rs:transfer", { "text": "}" }]`.
|
|
148
|
+
3. Run `node include-excerpts.mjs`. It checks every entry first and lists **every** missing file, missing anchor, and line range past the end of its file in one pass, then writes nothing. A clean run writes the excerpts and deletes the ones it wrote earlier that the manifest dropped (never a file it didn't write).
|
|
149
|
+
4. Replace each include with `<include lang="rust">/_excerpts/counter/abi.rs</include>`.
|
|
150
|
+
5. Run it first in `package.json` (`"dev": "node include-excerpts.mjs && blume dev"`, and the same for `build` and a `validate` script), and gitignore `<content root>/_excerpts/`. A host's build command must be `npm run build`, not `blume build`. Rerun it after editing a source file: `blume dev` doesn't watch them.
|
|
151
|
+
|
|
152
|
+
**Missing anchors.** For each anchor the script reports (the old site showed an empty block, or only a mixed block's hand-written lines), find where the code went (`git log -S "ANCHOR: <name>"`, or search the crate for the item), then:
|
|
153
|
+
|
|
154
|
+
- **When the team owns the source, re-add the `// ANCHOR: <name>` and `// ANCHOR_END: <name>` comments around the code there.** The entry keeps working as written, and the excerpt follows the code as it changes.
|
|
155
|
+
- Otherwise, point the entry at a line range (`"…/lib.rs:14:23"`). It keeps selecting those line numbers when the file changes, without an error, so say so in the report.
|
|
156
|
+
- Drop the block, with its lead-in sentence, when the code is gone.
|
|
157
|
+
|
|
158
|
+
Report each one and what you chose. Code that now fills a formerly empty block may contradict the prose around it: list what you notice.
|
|
159
|
+
|
|
160
|
+
### Code blocks
|
|
161
|
+
|
|
162
|
+
| mdBook | Blume |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| ` ```rust,ignore `, `rust,no_run,noplayground`, `rust,should_panic`, `rust,compile_fail`, `rust,edition2021`, `rust,editable`, `rust,mdbook-runnable`, `rust,hidelines=…` | ` ```rust ` (a comma-glued language doesn't highlight, and warns `BLUME_UNKNOWN_CODE_LANGUAGE`; written with a space, ` ```rust ignore `, the keyword does nothing and warns `BLUME_CODE_FENCE_OPTION`) |
|
|
165
|
+
| ` ```ignore `, or no language: rustdoc tests an unlabeled block as Rust, so books label diagrams and shell lines `ignore` | ` ```text `, or the real language |
|
|
166
|
+
| **hidden lines** in a Rust block: first non-space character `#`, then a space or the end of the line | delete the line, and a blank line it leaves at the top of the block: readers saw it only through the eye toggle, which has no equivalent. `##x` shows as `#x`; `#[derive]` and `#!` lines are code. Lines with a `[output.html.code.hidelines]` prefix (`python = "~"`), or a fence's `hidelines=<prefix>`, go the same way |
|
|
167
|
+
| the play button, `editable` | static code (report) |
|
|
168
|
+
| `mdbook test` | nothing compiles Blume's code blocks. Excerpts stay tested by cargo; hand-written blocks that `mdbook test` compiled aren't any more (report; drop the CI step and whatever it built only for that) |
|
|
169
|
+
|
|
170
|
+
### Admonitions
|
|
171
|
+
|
|
172
|
+
**mdbook-admonish** writes ` ```admonish <type> ` with options (`title="…"`, `collapsible=true`, `id`, `class`), the older `admonish <type> "Title"`, or `~~~`/four-backtick outer fences around inner code. Each becomes a callout in `.mdx`, with a longer `::::` outer fence around a nested one:
|
|
173
|
+
|
|
174
|
+
| admonish type (aliases) | Blume |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| `note`, `example` | `:::note` |
|
|
177
|
+
| `info` (`todo`), `abstract` (`summary`, `tldr`), `question` (`help`, `faq`) | `:::info` |
|
|
178
|
+
| `tip` (`hint`, `important`) | `:::tip` |
|
|
179
|
+
| `success` (`check`, `done`) | `:::success` |
|
|
180
|
+
| `warning` (`caution`, `attention`) | `:::warning` |
|
|
181
|
+
| `danger` (`error`), `failure` (`fail`, `missing`), `bug` | `:::danger` |
|
|
182
|
+
| `quote` (`cite`) | a blockquote |
|
|
183
|
+
| **any other word** (`admonish warn`) | `:::note`: admonish rendered it as a note titled "Note". Don't keep the word: Blume reads `:::warn` as a warning. Report it, with the type the author probably meant |
|
|
184
|
+
|
|
185
|
+
- `title="T"` → `:::type[T]`; `title=""` → no title. An untitled block showed the word it was written with as its title bar (`Example`, `Hint`, `TL;DR`), and an untitled Blume callout shows none: where that word isn't the Blume type's name, keep it as the title (`:::note[Example]`).
|
|
186
|
+
- `collapsible=true` → `<Expandable title="T">` (the type's name when untitled); its color drops.
|
|
187
|
+
- Custom directives (`[[preprocessor.admonish.custom]]`) → the closest callout, with the label as title.
|
|
188
|
+
- Each block had an anchor (`#admonition-<title>`, `-1` for repeats). Links to one fail `blume validate --strict`: point them at the nearest heading or drop the fragment.
|
|
189
|
+
|
|
190
|
+
**GitHub alerts** (`> [!NOTE]`, built into 0.5 and the `alerts` plugin) render as callouts in `.mdx` as written: `NOTE` and `IMPORTANT` as a note, `TIP` a tip, `WARNING` a warning, `CAUTION` a danger callout. In `.md` they stay a blockquote with a literal `[!NOTE]` and warn `BLUME_MD_GITHUB_ALERT`: rename the page to `.mdx`. A 0.4 book without the plugin showed them as plain quotes: rendering them changes the page (report).
|
|
191
|
+
|
|
192
|
+
### Other syntax
|
|
193
|
+
|
|
194
|
+
| mdBook | Blume |
|
|
195
|
+
| --- | --- |
|
|
196
|
+
| `## Heading {#id}` | the same in `.md`; `[#id]` in `.mdx` |
|
|
197
|
+
| `## Heading { #id .class }` | `{#id}` or `[#id]`; classes drop. Left as is, the spaced form stays in the heading text and makes a garbage id; `BLUME_MD_CURLY_ANCHOR` flags it only when no class follows the id (in `.mdx` it fails the build) |
|
|
198
|
+
| footnotes, tables, strikethrough, task lists | unchanged |
|
|
199
|
+
| definition lists (`term` then `: definition`, on by default in 0.5) | a list or table, or raw `<dl>`; Blume renders them as one paragraph |
|
|
200
|
+
| MathJax (`mathjax-support`): `\\( … \\)`, `\\[ … \\]` | `$$…$$` inside the sentence, or on lines of its own for a block, in `.mdx`. Undo the Markdown escapes mdBook needed inside the math (`\\\\` for a LaTeX `\\`, any `\_` or `\*`): `$$` math is read verbatim |
|
|
201
|
+
| `<i class="fa fa-x"></i>` | `<Icon icon="<lucide>" />` in `.mdx`, or delete (the icon map in `references/mintlify.md`) |
|
|
202
|
+
| `class="left"`/`"right"` floats; `class="hidden"` | drop the class; delete hidden elements (report) |
|
|
203
|
+
|
|
204
|
+
### Links and images
|
|
205
|
+
|
|
206
|
+
- mdBook only rewrote `x.md` links to `x.html`. Blume resolves a relative `.md` link to the page that file publishes: keep them, and fix the ones into or out of every moved file.
|
|
207
|
+
- Rewrite `.html` links (`installation.html#cargo`) to their `.md` files: Blume serves no `.html` URLs, so they'd depend on the redirects. `blume validate` reports each one left (`BLUME_BROKEN_ASSET`, with the page's route).
|
|
208
|
+
- **A link to `README.md` was already dead:** mdBook wrote `README.html`, a page it never creates. Point it at the renamed `index.md`.
|
|
209
|
+
- Root-relative links (`/guide/x.md`) land on the page that file publishes, read from the content root, like relative ones.
|
|
210
|
+
- Images relative to the page work as written. So does a linked download (a PDF, an archive) that mdBook copied from `src/`: Blume publishes a file a relative link names with the page, at a new URL. Move it to `public/` at the same path only if its old URL is linked from elsewhere.
|
|
211
|
+
|
|
212
|
+
## URLs and redirects
|
|
213
|
+
|
|
214
|
+
| Source file | mdBook URL | Blume route |
|
|
215
|
+
| --- | --- | --- |
|
|
216
|
+
| `src/guide/setup.md` | `/guide/setup.html` | `/guide/setup` |
|
|
217
|
+
| `src/guide/README.md` | `/guide/index.html` | `/guide` |
|
|
218
|
+
| the first chapter, `src/intro.md` | `/intro.html` and `/index.html` | `/` once moved to `index.md` |
|
|
219
|
+
| `src/01-basics.md` | `/01-basics.html` | `/basics`, or `slug: 01-basics` |
|
|
220
|
+
|
|
221
|
+
- **One exact redirect per chapter that isn't an index**, `{ from: "/guide/setup.html", to: "/guide/setup" }`, built from `old-urls.txt` and your table: a pattern can't strip `.html`. Skip `/index.html` and `/x/index.html`: static hosts serve Blume's `x/index.html` there already.
|
|
222
|
+
- **`[output.html.redirect]`**: each key is a path from the site root, and its value is a URL relative to the key's folder (`"../infra/x.html"`), root-relative, or external. Resolve the value against the key's folder, then map it like a chapter (`.html` → route, `index.html` → its folder); external URLs stay. Check each target against the old build: one that already led to a 404 → the page that replaced it, or drop it, and report.
|
|
223
|
+
- **Fragment redirects** (`"/page.html#old" = "other.html#new"`, 0.4.52 and later): servers never see fragments. A heading renamed on the same page → pin the old id on it (`[#old]`); moved to another page → no server equivalent (report). A deleted page's own entry is its redirect.
|
|
224
|
+
- **No equivalent, no redirect:** `print.html` (the whole book on one page, `noindex`), `toc.html` (the sidebar frame, `noindex`), and `404.html` (Blume writes its own). Mention `export: { pdf: true }` for printing.
|
|
225
|
+
- **Hosts:** a static build writes each redirect as a meta-refresh page at `dist/<from>/index.html`, plus `_redirects` and `vercel.json`. On Netlify use `netlify({ output: "static" })` for real 301s (SKILL.md). GitHub Pages reads neither file and serves the meta-refresh page; how it answers `/x.html` there is unverified, so check a few old URLs after deploying.
|
|
226
|
+
- **Heading anchors:** mdBook 0.5 ids match Blume's for most headings; 0.4 lowercases ASCII only (`## Über` → `#Über`), and both count the H1, so `# Install` then `## Install` gives `#install-1`. After the first build, run `node <skill>/scripts/pin-heading-ids.mjs --old old-book` (add `--map dist/blume-redirects.json` when routes changed, built with no host adapter; `--write` to apply), and rebuild until it reports 0.
|
|
227
|
+
- **Check every old URL** after `blume build`. With no host adapter (static), from the Blume project:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
node -e '
|
|
231
|
+
const fs = require("node:fs");
|
|
232
|
+
const moved = new Map(JSON.parse(fs.readFileSync("dist/blume-redirects.json", "utf8")).map((r) => [r.from, r.to]));
|
|
233
|
+
const built = (to) => /^https?:/.test(to) || fs.existsSync(`dist${to.replace(/#.*/, "").replace(/\/$/, "")}/index.html`);
|
|
234
|
+
const misses = fs.readFileSync("old-urls.txt", "utf8").split("\n").filter(Boolean).filter((url) => {
|
|
235
|
+
const to = url.endsWith("/index.html") ? url.slice(0, -"index.html".length) : moved.get(url);
|
|
236
|
+
return !(to && built(to));
|
|
237
|
+
});
|
|
238
|
+
console.log(misses.length ? misses.join("\n") : "every old URL resolves");'
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Then run `blume audit --only redirects`.
|
|
242
|
+
|
|
243
|
+
## Repo integration and teardown
|
|
244
|
+
|
|
245
|
+
- **`package.json`** beside `blume.config.ts`: `blume` plus the `dev`/`build`/`preview`/`validate` scripts, with the excerpt step first. Commit the lockfile (SKILL.md step 6).
|
|
246
|
+
- **`.gitignore`:** replace `book/` with `dist/`, `.blume/`, `node_modules/`, `.env.local`, and `<content root>/_excerpts/`.
|
|
247
|
+
- **CI:** replace `mdbook build`/`mdbook test`, `peaceiris/actions-mdbook`, and the plugin installs with Node 22, an install, `npm run build`, and `npm run validate`. A deploy workflow in another repo needs the same change: list it as a follow-up. For GitHub Pages, follow https://useblume.dev/guides/markdown-docs-github-pages (Actions as the Pages source), with `npm run validate` and `npm run build` in place of its `blume` steps so the excerpts exist, run from the Blume project's folder, and that folder's `dist` uploaded. A deploy that pushes a branch must publish `.nojekyll`, or Jekyll drops Blume's `_astro/` folder; `peaceiris/actions-gh-pages` adds it by default.
|
|
248
|
+
- **`cargo doc` output published beside the book** (`/api/…`): keep building it in CI and copy `target/doc` into the build output, or link to docs.rs. Blume doesn't generate it.
|
|
249
|
+
- **Several builds of the book** (a stable tag and `main`, `MDBOOK_BOOK__LANGUAGE` per language): migrate the current one; older versions → `versions`, or stay on the old host (report). Translations in `po/*.po` (mdbook-i18n-helpers) apply at build time: render each language's Markdown with `MDBOOK_BOOK__LANGUAGE=<xx>` and the Markdown renderer into `<xx>/`, then set `i18n`. Report it.
|
|
250
|
+
- **Prettier** on the book: extend its `*.md` overrides to `*.mdx`, and keep `{/* */}` comments on one line. Prettier 3 skips what `.gitignore` ignores, so a `.gitignore` that covers the content root also makes a `prettier --check` CI step check nothing.
|
|
251
|
+
- **A hand-written `llms.txt` in `src/`:** Blume generates `/llms.txt`, so delete the file. Its intro goes to `agents.llmsTxt.details`. A per-page summary becomes that page's `description` only where it reads well as the page's lede, since Blume shows `description` under the title; report the rest, and the sections that list things other than pages.
|
|
252
|
+
- **Delete** `book.toml`, `SUMMARY.md`, `theme/`, the `additional-css`/`additional-js` files once ported, `mdbook-admonish.css`, `mermaid.min.js`, `mermaid-init.js`, and the `book/` folder. Grep the repo for `mdbook`, `book/`, and the old `.html` URLs (READMEs, CONTRIBUTING, examples, bots).
|
|
253
|
+
|
|
254
|
+
## Dropped — report these
|
|
255
|
+
|
|
256
|
+
Section numbers, separators, and draft chapters; suffix chapters and leaf chapters that moved above folders; the print page; the theme switcher and themes beyond one light and one dark; search options; the play button, the editor, and runnable or editable examples; hidden lines and their toggle; `mdbook test` coverage of hand-written blocks; `rustdoc_include` context; admonish title bars, colors, icons, custom directives, and anchors; fragment redirects across pages; the old site's empty blocks from missing anchors, and what you did with each; definition-list styling; Font Awesome icons with no Lucide match; `class="hidden"` content; plugin output you froze (cmdrun, templates, custom preprocessors); a hand-written `llms.txt`; whole-book PDF or EPUB output; and every plugin you removed without an equivalent.
|