Skip to content

feat(ci): add Markdown and Mermaid linting#933

Open
pimlock wants to merge 2 commits intomainfrom
feat/markdown-mermaid-lint
Open

feat(ci): add Markdown and Mermaid linting#933
pimlock wants to merge 2 commits intomainfrom
feat/markdown-mermaid-lint

Conversation

@pimlock
Copy link
Copy Markdown
Collaborator

@pimlock pimlock commented Apr 23, 2026

Summary

  • Adds mise run markdown:lint which chains markdownlint-cli2 (structural markdown) and a Mermaid validator that calls the official mermaid.parse() via a jsdom shim — no Chromium/Puppeteer required.
  • Runs in CI via a new Markdown job in branch-checks.yml.
  • Fixes existing violations across the repo so the new checks pass from day one.

Why mermaid.parse() (tooling research)

Evaluated several options before landing on the official mermaid npm package + jsdom:

  • @mermaid-js/mermaid-cli (mmdc) — uses the real parser/renderer, but pulls Puppeteer + Chromium (~300MB). Too heavy for pre-commit; CI-only at best.
  • @probelabs/maid — fast, Chevrotain-based. Rejected: produced false positives AND missed a real error in this repo (the exec()s sequence-diagram bug in architecture/sandbox-connect.md).
  • go-mermaid — pure Go single binary, but custom parser that lags the official grammar. Would drift silently.
  • @mermaid-js/parser (Langium, official) — library only, currently covers only a subset of diagram types (flowchart/sequence/class still partly on the legacy Jison grammar inside mermaid). Incomplete for our mix.
  • mermaid.parse() from the mermaid package — chosen. Uses the same grammar that actually renders on GitHub and in Fern previews (so "passes here" == "renders there"), needs only a small jsdom shim, runs in ~2s across the repo.

Long-form rationale lives in the header comment of scripts/lint-mermaid/lint-mermaid.mjs.

Changes

Tooling

  • .markdownlint-cli2.jsonc — root config. gitignore: true, rule overrides for project style (MD013 off, MD033 allowlist, MD024 siblings_only, MD034 off, MD060 padded).
  • docs/.markdownlint-cli2.jsonc — per-directory MDX override (MD041, MD033 off for JSX/frontmatter).
  • scripts/lint-mermaid/ — Node validator (lint-mermaid.mjs) plus package.json + committed package-lock.json. CI installs via npm ci from the lockfile for reproducible, deterministic builds — deps are pinned and won't drift.
  • tasks/markdown.tomlmarkdown:lint, markdown:lint:md, markdown:lint:mermaid, markdown:format, markdown:deps (mise sources/outputs cache the install).
  • mise.toml"npm:markdownlint-cli2" = "0.15.0" so contributors get the CLI via mise install.
  • tasks/ci.toml — wires markdown:lint into the umbrella lint task.
  • .github/workflows/branch-checks.yml — new Markdown job.

Doc cleanups to satisfy the new checks

  • Adds text language to 43 previously-bare code fences across 21 files (via one-shot codemod, kept in-tree as scripts/lint-mermaid/default-fence-lang.mjs).
  • Fixes ordered-list indentation at the 1-digit → 2-digit boundary in architecture/sandbox.md (CommonMark requires 4-space sub-bullet indent under 10. ).
  • Minor blank-line and trailing-newline fixes.

Testing

  • mise run markdown:lint — 0 errors across 73 markdown files + 80 mermaid-scanned files.
  • Mermaid validator catches the real exec()s parse error that maid and @mermaid-js/parser previously missed.
  • npm ci in scripts/lint-mermaid/ reproduces the exact lockfile.
  • YAML-validated the new workflow.
  • CI job passes on this PR.

Checklist

  • Conventional commit format.
  • Follows repo style.
  • No secrets; unrelated changes scoped out.

Introduce `markdown:lint` which chains structural markdown checks
(markdownlint-cli2) and Mermaid diagram validation. Both run as part of
`mise run lint` and as a dedicated GitHub Actions job.

Mermaid diagrams are validated by calling `mermaid.parse()` via a small
Node script with a jsdom shim — no Chromium/Puppeteer required. This
catches real parse errors (e.g. the `exec()s` sequence-diagram bug in
`architecture/sandbox-connect.md`) that browser-free alternatives like
`maid` silently miss.

Tooling:
- `.markdownlint-cli2.jsonc` with `gitignore: true`, sensible rule
  overrides (MD033 allowlist for GitHub-rendered HTML, MD060 padded
  table style, MD013/MD034 off to match project style).
- `docs/.markdownlint-cli2.jsonc` overrides for MDX (no top-level H1,
  JSX components may look like HTML).
- `scripts/lint-mermaid/` hosts the validator with a committed
  `package-lock.json` for reproducible CI installs (`npm ci`).
- `markdownlint-cli2` pinned via mise `npm:` backend.

Existing doc fixes applied to satisfy the new checks: adds `text`
language to bare code fences (via one-shot codemod), corrects list
indentation at the single-digit → double-digit boundary in
`architecture/sandbox.md`, plus minor blank-line and trailing-newline
fixes.
@pimlock pimlock requested a review from a team as a code owner April 23, 2026 01:38
@github-actions
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant