Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Writing documentation

bunsen has two kinds of documentation, rustdoc and this book, and each fact belongs in exactly one of them. This page covers the book’s side, for anyone writing it: how the book links into the API, how code in the book stays correct, and how to build the book. STYLE.md’s rustdoc chapter has the rules for rustdoc, including which facts belong there.

rustdoc is the reference

rustdoc documents every interface and every lifecycle; the book explains what rustdoc can’t hold, names each concept, and links to it. When a book page needs a fact that rustdoc doesn’t have, the fix is in rustdoc. STYLE.md’s rustdoc is the reference is the rule, including what the book never restates.

Module docs must render

A private module’s //! never reaches the API docs, so prose written there is invisible. STYLE.md’s Module docs must render says where that prose goes instead, and CI enforces it with tools/check_hidden_module_docs.py.

Linking into the API

API links in the book are rustdoc intra-doc paths, not URLs:

To linkWrite
an item[`ShapeContract`](bunsen::contracts::ShapeContract)
a module[`bunsen::ops`]
a section of a page[the ops/blocks rule](bunsen::ops#ops-and-blocks)
a method[`try_init`](bunsen::burner::module::ModuleInit::try_init)
a macro[`shape_contract!`](bunsen::contracts#macros-and-methods), the section of its module’s page that lists it (see below)
another published crate[`bunsen_firehose`]

Macros are the one exception to linking the item itself. rustdoc can’t resolve a path to a macro_rules! macro that another crate re-exports (bunsen::contracts::shape_contract! reports “no item named bunsen in scope”), so a book link to a bunsen macro goes to the module section that documents it.

mdbook-rustdoc-links resolves them at build time with rustdoc’s own resolver, so a link in the book is exactly as valid as the same link in a doc comment. Renaming or moving an item, method or field leaves the link unresolved, and that fails the book build in CI, in the same PR as the rename.

Only what docs.rs shows resolves. bunsen is built with the feature list in its [package.metadata.docs.rs], and the other published crates with their defaults (docs.rs may build one with more), so an item behind a feature that docs.rs doesn’t build can’t be linked. The crates/dev and crates/validation crates and the examples are not in that build. Link them, and other repository files, as GitHub URLs, and keep those few.

The base URL the links point at is chosen per build:

  • Local builds link to /api, a symlink from book/src/api to target/doc, and include the API docs in the book’s output, so a local book reads against the API at HEAD, offline.
  • Release builds, selected when CI is set, link to docs.rs, pinned to each crate’s version from Cargo.lock. That is why a book for readers is built only from a release (Releasing).
  • MDBOOK_PREPROCESSOR__RUSTDOC_LINKS__BASE_URL overrides both.

Links between chapters are relative .md paths. mdbook-linkcheck2 checks that the file exists, but not the #anchor.

Square brackets in prose are read as links, and an unresolved one fails the build. Escape a stray bracket (\[x\]) or put it in a code span.

Code in the book

Every Rust block in the book is compiled, or it is plainly a sketch:

  • Runnable code that names bunsen items is pulled in from compiled code with an mdbook include, {{#include path:anchor}}, from crates/dev/book-snippets or an example. The included region sits between // ANCHOR: name and // ANCHOR_END: name in a test or a main, so cargo test runs it, and CI builds, lints and formats it like any other workspace member. Prefer including code an example already has over writing a new snippet.
  • A sketch that names no bunsen items may use a text or rust,ignore fence, and the prose around it says it is a sketch.
  • The book never copies a rustdoc example. It links to the doctest.

Shapes, math and diagrams

  • Tensor shapes are one code span in square brackets, with the dimension arithmetic inside, such as [batch, h_wins*size, w_wins*size, channels]. This is STYLE.md’s shape notation, the same in rustdoc and the book, and it reads like the shape contract that checks the shape. The code span also keeps the brackets away from the link resolver.
  • Math is KaTeX, between dollar signs. Book-wide macros, such as \RR, \NN and \ZZ for the number sets, are defined in book/katex-macros.txt. Add a macro there rather than repeating a definition on a page.
  • Diagrams are mermaid, or text fences. Prefer a text diagram when the same picture may belong in rustdoc.

Building the book

The book’s tasks are in Makefile.toml. Each installs the pinned mdbook tools on first use, at the versions CI uses:

TaskWhat it does
cargo make bookbuilds the book against the local API docs; an unresolved API link is a warning
cargo make book-checkthe same build CI runs: an unresolved API link is an error
cargo make book-serveserves the book locally, rebuilding as you edit
cargo make book-releasethe publishing build: API links pinned to this release on docs.rs

Run book-check before pushing a change that touches the book or renames anything public. The build runs cargo doc itself, so the first run is slow. The release workflow makes the book-release build and publishes it (Releasing); run it locally only to preview that.

Writing a page

Open each page with a sentence or two on what it covers. Say what a thing is for and when to reach for it, and stop when the why is told: one good paragraph and a link beat a list of features. Every API noun is a link.