AsciiBinder AsciiDoc to Markdown to Docusaurus
The last part exported the OpenShift Markdown to MkDocs. This one takes the same pages to Docusaurus 3, which is a harder target. Docusaurus reads Markdown as MDX, and MDX is a programming language with Markdown syntax. A stray { or < that every other generator would print is a compile error here.
The site is at dogsbay.github.io/openshift-docs-docusaurus and the workflow is dogsbay/openshift-docs-docusaurus.
- Converting AsciiDoc to Markdown
- Why existing AsciiDoc converters lose your structure
- Why Jinja is the right target
- Mapping AsciiDoc variables to Jinja
- Mapping AsciiDoc conditionals to Jinja
- Mapping AsciiDoc ifeval to Jinja
- Mapping AsciiDoc includes and level offsets to Jinja
- AsciiBinder AsciiDoc to Markdown to Astro
- AsciiBinder AsciiDoc to Markdown to MkDocs
- AsciiBinder AsciiDoc to Markdown to Docusaurus — you are here
The same flag, a different target
npx dogsbay site build ./out --to docusaurus --out ./docusaurus \
--site-url https://<you>.github.io/openshift-docs-docusaurusThe output is a complete Docusaurus project, not just content:
docusaurus/
docusaurus.config.js title, url + baseUrl, presets, remark plugins
sidebars.js the nav, as sidebar categories and doc ids
package.json Docusaurus 3 + the plugins the profile wired
docs/ 1,799 pages, .md
static/images/ 675 files
src/pages/index.js the root redirectnpm install && npx docusaurus build produces the site. On GitHub's runners that is about nine minutes for 1,800 pages, most of it webpack.
Two things in that config are easy to get wrong by hand and the exporter does for you:
urlandbaseUrlare split. Docusaurus rejects a path insideurl, sohttps://you.github.io/openshift-docs-docusaurusbecomesurl: "https://you.github.io"andbaseUrl: "/openshift-docs-docusaurus/". Without the split, every link on a project Pages site 404s.- Number-prefixed filenames are not positions. Docusaurus strips a leading
4-from4-years-of-k8s.mdand reads it as a sort key, so the doc id no longer matches the sidebar and the build fails on every such page. The config setsnumberPrefixParser: falseand orders fromsidebar_positionfrontmatter instead.
Markdown that compiles
Docusaurus is configured with format: detect. .md files are CommonMark, .mdx files are MDX. The exporter emits .md, which removes most of the danger, but not all of it, because the DogsBay directives become JSX components and the content inside them is MDX again. So the exporter carries an MDX repair pass with its own adversarial test suite: unclosed fences, closers with info strings, \{ that must not double-escape, KaTeX, mis-nested tags, and prose that merely looks like a tag.
The OpenShift corpus contributed its own cases. Generated API reference pages contain map<string, string> in running text, and React rejects string, as a tag name. Those are escaped where the tag name is impossible and left alone where it is a real component. A <pre> from AsciiDoc's listing blocks is unwrapped by Docusaurus' MDXPre component unless it contains a <code>, so it gets one. And admonitions inside table cells, which Docusaurus' ::: syntax cannot express, become Infima alert alert--* blocks.
| DogsBay MD | Docusaurus |
|---|---|
:::note, :::warning, … | :::note admonitions, with the AsciiDoc kinds mapped to Docusaurus' five |
:::tabs | <Tabs> / <TabItem>, values de-duplicated because Docusaurus requires them unique |
:::steps | ordered lists, indented correctly at nesting depth |
| definition lists | Term / : definition, via remark-definition-list |
| related links | a list under the page, since a related fold has no native form |
| link buttons | a styled link, never dropped |
Definition lists are a plugin, and that is the right call
OpenShift's API reference is thousands of definition lists. CommonMark has no syntax for them, and the obvious workaround, a bold term followed by a paragraph, loses the structure that makes a glossary a glossary.
The exporter wires remark-definition-list into the emitted config instead, so the Markdown keeps the Term / : definition form and the built HTML has real <dl>, <dt> and <dd> elements. This lives in an export plugin profile: the standard profile includes definition lists, math and Mermaid, and an api profile adds OpenAPI page generation.
One Docusaurus limitation is that the plugin renders definition lists at the top level and inside containers, but not nested inside list items. Those fall back to the bold-term form instead.
Fidelity and links
On the same bare-metal UPI page used to measure the MkDocs export: 166 of 166 code blocks, 117 of 117 admonitions, and the definition-list count within two of AsciiBinder's, for the same source-side reasons.
Links are where Docusaurus is strict in a useful way. docusaurus build checks every internal link and anchor and prints an exhaustive report.
Broken links are due to an issue in the AsciiDoc source itself. The workflow leaves them as warnings, and puts the report in the run summary.
The home page issue
The MkDocs blog post showed how the published site had no root page by default. Docusaurus had the same bug in a different shape. Docs live under /docs/, nothing is served at /, so the exporter emits a redirect page to the first page in the sidebar, /docs/welcome/.
Try AsciiDoc to Docusaurus yourself
- Fork dogsbay/openshift-docs-docusaurus.
- In Settings → Pages, set the source to GitHub Actions.
- Open the Actions tab, enable workflows, and run Build Docusaurus site against
enterprise-4.22.
The workflow sparse-checks-out markdown/ from the Markdown repo's content branch, exports, runs npm install and docusaurus build, commits the project to a same-named content branch, and deploys from the artefact. It also commits the resolved package-lock.json and reuses it on the next run, so when a dependency moves it shows up as a diff next to the build it broke.
Your copy appears at https://<your-username>.github.io/openshift-docs-docusaurus/.
Pages to check
| Page | Why |
|---|---|
| /docs/welcome/glossary/ | real <dl> from the plugin |
| /docs/installing/installing_bare_metal/upi/installing-bare-metal-network-customizations/ | the measured page |
| /docs/rest_api/monitoring_apis/prometheus-monitoring-coreos-com-v1/ | the largest page, generated API reference through MDX |
| /docs/architecture/architecture/ | images under baseUrl |