Post-processing scripts for the static HTML produced by the 4D Docusaurus documentation build. They run after Docusaurus has emitted the site and before publication, to fix issues that can't be solved at the source level without a costly migration of the markdown layout.
The 4D docs are versioned. The latest unversioned version (currently 21-R3
BETA) lives under docs/, while older releases live under versionned_docs/.
The folder layout differs between the two, e.g.:
| Version | Source folder | Doc id |
|---|---|---|
| Latest (unversioned) | docs/language-legacy/Messages/alert.md |
language-legacy/Messages/alert |
21-R2 |
versionned_docs/versions-21-R2/commands-legacy/alert.md |
commands-legacy/alert |
21 |
versionned_docs/versions-21/commands-legacy/alert.md |
commands-legacy/alert |
The slug is the same across versions (/commands/alert), but the doc id
differs, because Docusaurus derives it from the folder path. The version
dropdown in the navbar matches pages by doc id, not by slug, so when the doc id
isn't found in the target version, the dropdown link falls back to a default
page like GettingStarted/installation. The user ends up on "Getting started"
instead of the same command in another version.
Reorganising the markdown to use a single layout across all versions would be a large migration. Patching the built HTML is cheaper and safer.
fix-version-menu.js post-processing script (see below)
action.yml composite GitHub Action wrapping the script
tests/ fixtures used to develop and verify the scripts
markdown/ sample markdown sources for one page across versions
gh-pages/ matching built HTML output Docusaurus would emit
tests/ only contains fixtures — the script itself does not read or depend on
them. They exist so you can run the script against a known input and check the
result. Example:
node fix-version-menu.js tests/gh-pages --dry-runRewrites the version-dropdown links in built HTML so that switching version
keeps the user on the same page (matched by slug) instead of falling back to
GettingStarted/installation.
Usage:
node fix-version-menu.js [<gh-pages-dir>] [--dry-run] [--out <dir>]<gh-pages-dir>— the built site directory. Defaults to./gh-pages.--dry-run— print the plannedfrom -> tosubstitutions without writing.--out <dir>— mirror the entire input tree to<dir>and apply fixes there, leaving the input untouched. The output is a drop-in replacement for<gh-pages-dir>. Without this flag, files are edited in place.
What it does:
- Scans every HTML file under
<gh-pages-dir>/commands/and<gh-pages-dir>/<version>/commands/. - For each page, locates the version dropdown (the
<ul class=dropdown__menu>whose items don't carry alang=attribute) and rewrites each entry'shrefto the slug-equivalent URL when the corresponding HTML file actually exists in that version's tree. - Links pointing at versions that aren't present on disk (e.g. older releases not deployed in this build) are left untouched.
- The script is idempotent: a second run finds nothing to change.
Examples:
# Show what would change, don't write
node fix-version-menu.js gh-pages --dry-run
# Edit gh-pages in place
node fix-version-menu.js gh-pages
# Write a fixed copy to ./out, leave gh-pages untouched
node fix-version-menu.js gh-pages --out outThis repo also exposes fix-version-menu.js as a composite GitHub Action, so
the post-processing can run inside the pipeline that builds and publishes the
docs.
Inputs:
| Name | Required | Default | Description |
|---|---|---|---|
path |
yes | — | Path to the built Docusaurus output (the equivalent of gh-pages). |
dry-run |
no | false |
If true, print planned substitutions without writing. |
out |
no | '' |
Optional output dir. When set, the input is mirrored there and fixes are applied to the copy. |
Example — run after the Docusaurus build, before deploying to GitHub Pages:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Build docs
run: |
npm ci
npm run build # produces ./build
- name: Fix version-dropdown links
uses: doc4d/doc_postprocessing@v1
with:
path: build
- name: Deploy to GitHub Pages
uses: doc4d/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: buildEach issue gets its own self-contained script at the repo root. Scripts should:
- Be a single
.jsfile with no npm dependencies (run asnode script.js). - Default to a sensible input directory (typically
./gh-pages). - Support
--dry-runfor safe preview. - Be idempotent — re-running on already-processed output should be a no-op.