Book publishing
Oink’s Book capability extends the documentation shell. It uses the existing
content tree or data/docs_nav.json, the same breadcrumbs and pager, and the
same output-aware component system. It does not introduce a second chapter
manifest or a parallel navigation implementation.
Create the Book root
A section Book declares its type, requests the outputs it needs, and cascades the type to descendants:
The Book root is always the current first section, even when the site enables a
sidebar root switcher. Its navigation cannot leak into sibling docs or blogs. If
a site overrides params.ui.shell_types, retain book in that list.
Request print explicitly: Oink never adds an expensive aggregate output to a
consumer configuration. For a section Book, the relevant Hugo output kind is
section; use home only when the Book is the site root:
sidebar_headings accepts false, true (level 2), or a maximum heading level
from 2 through 4. It projects the active page’s Hugo fragment tree below the
chapter row. Use explicit heading IDs for anything that will be cited:
Generated heading slugs are convenient navigation, not a durable citation API.
Describe chapters
Chapters may use the established metadata namespace:
book_number appears beside titles in the page, sidebar, and generated Book
table of contents. book_status: draft is a visible editorial label and does
not change Hugo’s publication state. Set book_draft_banner: true to add a
localized page notice as well.
Add numbered components
The numbered forms of fig, tbl, and eq require a quoted num matching
letters, numbers, dots, or hyphens. Their default IDs are fig-<num>,
tbl-<num>, and eq-<num>; set an explicit stable ID when preserving an
existing public anchor.
Figures
New figures should always provide meaningful alt. title is a migration alias
for caption and the two are mutually exclusive. A figure may use src or
inner Markdown content, never both. URLs, class tokens, and positive image
dimensions are validated.
Tables
The component keeps label, Markdown table, caption, and anchor inside one semantic figure. It does not simulate captions with a heading.
Equations
Equation content goes directly through local server-side KaTeX, even if the site
has not enabled Goldmark passthrough. The parameter-free eq form remains an
unnumbered display-math escape hatch and cannot be an xref target.
Duplicate IDs, or two components of the same kind claiming one number with different IDs, are build errors. Captions are plain text; figure and table body content follows the page’s Markdown policy.
Cross-reference safely
Reference a numbered target by kind and number:
Reference a heading on another page with explicit link text:
xref accepts at most one kind (fig, tbl, or eq), plus optional page
and anchor. A kind supplies the localized default label and derives the
default anchor. An anchor-only reference requires inner text. Cross-page lookup
uses Hugo’s current-language page resolution, so source never hard-codes an
/en/ route.
References are order-independent and may appear before their targets. In
whole-Book print, Book-aware xrefs become document-local fragments. Ordinary
Markdown cross-page links intentionally remain site URLs, so use xref for
citations that must work inside the aggregate.
Generate Book indexes
Build a table of contents from the same ordered Book tree:
Depth 1 lists chapters, depth 2 includes nested sections, and depth 3 also
projects each page’s heading tree. drafts=false filters visible editorial
drafts from this generated list only; it does not unpublish their pages.
Generate figure, table, or equation lists:
These shortcodes trigger and aggregate descendant content deterministically, then link to stable target IDs. They do not require a copied registry file.
Publish whole-Book print
The Book root’s print output emits a cover, local table of contents, then the
root and visible descendants in reading order. no_print: true, link-only
nodes, sidebar dividers, and hidden placeholders do not become chapters.
Numbered target IDs remain byte-stable. Page-local Markdown heading IDs receive
a source-page prefix in the aggregate, so repeated anchors such as summary
remain unique; generated heading links are rewritten accordingly. Book ToC,
figure-list, and xref destinations become document-local.
The result is print-oriented HTML, not a network-dependent PDF/EPUB pipeline. Pagination, PDF conversion, and EPUB packaging remain site-owned concerns.
Migrate existing books
Inventory first, transform only unambiguous forms, and stop rather than guessing missing numbers, captions, alternatives, or targets. Preserve existing public IDs independently from display numbers. Run migrations on a branch, retain a machine-readable before/after report, validate every skipped record, and require a zero-change second run.
The Oink v0.4.0 source ships a dry-run-first, idempotent migration tool and observed-site recipes for TPME, DDIA, and pg-internal. Treat those as executable patterns for the named source forms, not universal caption heuristics.
Validate a Book
- Compare the sidebar, pager, generated ToC, and whole-Book chapter order.
- Verify every numbered target ID is unique and every xref reaches a matching kind and number in each language.
- Confirm numbered figure alternatives are meaningful and caption compatible.
- Inspect standalone HTML, Markdown, print, and the whole-Book aggregate.
- Test repeated heading names and cross-chapter citations in aggregate print.
- Run the theme’s
scripts/check-book.pywhen working from a theme checkout, or implement the same rendered-anchor checks in consumer CI.