Generate PDF Documentation
Overview and tools needed
The full-document PDF is generated by rendering the Hugo site and converting the resulting HTML with Prince. Prince supports print-specific CSS, bookmarks, cross-reference page numbers, links, and the JavaScript needed for equation rendering. Its non-commercial license is sufficient for local and project use, but it adds a watermark to generated documents. A license suitable for public distribution is required before publishing an unwatermarked PDF.
Install Hugo Extended, Go, Python 3, curl, and Prince before running the
generator. The minimum Prince version for the MathJax compatibility script is
20210624; the latest Prince release is recommended.
Build process
The repository-root pdf-docs.sh script performs the complete build directly
with Hugo. It performs four steps:
- Hugo renders the PDF outputs and selected documentation pages into a temporary directory.
- Hugo generates a Prince input list from the documentation, tutorials, and appendix sidebars.
- A temporary local HTTP server serves the rendered HTML and static assets.
- Prince reads the input list and writes the final PDF.
Render the PDF target with Hugo
Run the script from the repository root:
./pdf-docs.sh
Internally, the Hugo step is equivalent to:
hugo --gc --minify --cleanDestinationDir \
--environment pdf \
--renderSegments pdf \
--destination public-pdf \
--baseURL http://127.0.0.1:4173/
The pdf environment is defined in config/pdf/hugo.toml. It adds the title
page, table of contents, part-title pages, and Prince input-list output. The
pdf segment limits normal HTML output to the documentation and tutorial
sections included in the PDF.
Generate the Prince input list
The list is generated at public-pdf/pdf/prince-list.txt; it must not be
edited manually. layouts/partials/pdf/prince-list.txt traverses the Hugo
sidebar data and includes only entries whose sidebar output contains pdf.
The current order is:
- title page;
- table of contents;
- documentation part page and documentation pages;
- tutorials part page and tutorial pages; and
- appendix part page and appendix pages.
The generated list contains local absolute URLs, for example:
http://127.0.0.1:4173/pdf/title.html
http://127.0.0.1:4173/pdf/toc.html
http://127.0.0.1:4173/docs/fundamentals/overview/
layouts/partials/pdf/page-for-url.html resolves sidebar URLs and aliases to
the corresponding Hugo page, so renamed pages can still be included.
Convert the rendered pages to PDF
After the temporary server is ready, the script invokes Prince with the generated list:
prince --javascript \
--input-list=public-pdf/pdf/prince-list.txt \
-o pdf/docs.pdf
The final document is written to pdf/docs.pdf. The server is stopped and its
temporary log is removed automatically when the script exits.
The output directory, output file, and local server port can be changed using environment variables:
PDF_BUILD_DIR=/tmp/precice-pdf \
PDF_OUTPUT=/tmp/precice-docs.pdf \
PDF_PORT=4174 \
./pdf-docs.sh
Styling
When params.output is pdf, the base and content layouts use the print
markup instead of the normal navigation and sidebar wrappers. The print
templates and PDF-specific partials are in layouts/partials/pdf/, while
layouts/partials/head_print.html loads the local print resources.
PDF-only styles are in static/css/printstyles.css. They define page headers
and footers, page counters, table-of-contents leaders, page breaks, image
limits, and print-friendly alert boxes. Do not edit minified vendor CSS for a
PDF-only adjustment; add a scoped rule to printstyles.css instead.
Prince compatibility scripts and print assets are served locally from
static/js/, static/fonts/, and static/webfonts/. Keeping these resources
in the generated site prevents the PDF build from depending on a browser or
on CDN availability.
Contents, title page, and table of contents
The Hugo sidebars in data/sidebars/ define the PDF contents. Add pdf to a
sidebar entry’s output value when a page belongs in the document, for example
output: web, pdf. Entries without pdf remain available on the website but
are excluded from the PDF. The appendix uses
data/sidebars/pdf_appendix_sidebar.yaml.
The title page, table of contents, and part-title pages are separate Hugo outputs. The table of contents is built recursively from the sidebar folders, preserving nested sections and the order defined in the data files.
Troubleshooting
Prince warnings
Prince validates CSS more strictly than a browser. Warnings about unsupported Bootstrap properties, modern pseudo-classes, or browser-only media features are expected when they do not affect the printed output. A missing resource, failed URL, or non-zero Prince exit status requires investigation.
Missing resources
Prince reads one URL at a time from the local server. Run the script rather
than opening generated HTML with a file:// URL, and check that referenced
stylesheets, images, scripts, and fonts exist below public-pdf/.
Missing glyphs or fonts
If Prince reports missing glyphs, verify that the required Fira Sans, Fira
Mono, Font Awesome, and KaTeX resources are present in static/fonts/,
static/webfonts/, and static/css/fonts/. See the Prince troubleshooting
documentation for details.
Debugging one page
To debug a specific page, copy its local URL into a temporary input list and run Prince against that list. This avoids rebuilding the entire document while investigating CSS, images, or equations.