Release Notes¶
0.10.5 (2026-07-25)¶
Fixed a real bug found by reproducing it directly: a cross-page
\ref{id} under zensical build depended on whether the page defining
id happened to be rendered before the page referencing it, in the same
Python process - zensical build renders pages neither in nav order nor
necessarily all in one process, so this was pure luck. Reproduced
locally on a 3-page site: the previous release left 1-5 references as
?? per build, varying from one otherwise-identical build to the next
(only 2 of 12 clean builds fully resolved).
prodockit.headings now pre-scans every nav page's headings (ids,
levels, section numbers) into the shared registry before any page is
converted - the same idea prodockit.citations/prodockit.glossary
already use for their own cross-page definitions - so resolution no
longer depends on build order. A page actually rendered in this process
still supersedes its own pre-scanned entries with the real ones. 20
consecutive clean builds now produce byte-identical, fully-resolved
output; prodockit-template's entire built site is byte-identical
before and after this change.
Also fixed a second bug found while testing the above: extension order
isn't guaranteed, so prodockit.refs can construct its own default
HeadingsExtension and trigger the pre-scan with per-document numbering
before a project's configured numbering = "continuous" instance runs
- silently showing a cross-page reference's number one step behind
(1.1 instead of 2.1) roughly 1 build in 12. The pre-scan now reruns
if a differently-configured instance appears.
Fixes #54.
See #99 for
a related, separate limitation found along the way (this pre-scan can go
stale under zensical serve's live-reload - not fixed here).
0.10.4 (2026-07-25)¶
- Added
CONTRIBUTING.mdand a.github/pull_request_template.md, adapted from prodockit-template's own - library-specific setup (pip install -e ".[dev]",pytest/ruff/mypy, the real-pandocrequirement forprodockit.bibliography's own tests) rather than the template's assignment-writing framing. Linked from README.md's Development section. - Docs: added an admonition to
headings.mddocumenting a real gap this project's own docs hit directly while enabling every prodockit extension on its own site (#87) - Zensical's automatic cross-page id sharing only warns (rather than raising) on a heading name shared across pages, and build order isn't guaranteed stable, so the "keeping the first" winner can change between builds. Documents the fix - an explicit, page-prefixed id viaattr_list- pointing to this project's own docs as a worked example.
No code changes.
0.10.3 (2026-07-25)¶
Docs: several extension pages mixed "why it was built this way" design rationale into their opening paragraph, ahead of the practical "what it does"/"how to use it" content most readers want first - moved that reasoning further down each page instead:
bibliography.md: trimmed the intro to the core value proposition, moved the Pandoc-delegation rationale and architecture diagram out of Requirements (now just what to install) into a new "How it works" section after Reference, and folded the "can be enabled alongside prodockit.citations" note into Comparing the two approaches.citations.md/glossary.md: moved the "why bundled into one extension, unlike headings/refs" rationale from the intro into their own Syntax section.tables.md: moved the "auto-enables Python-Markdown's own tables extension" implementation note from the intro into Syntax.index-terms.md: moved the "why a Markdown extension, not attr_list" rationale from the intro to the end of CSS hooks, wrapped in its own admonition naming the subject explicitly.
headings.md/refs.md were already lean and needed no changes. No
syntax, behaviour, or code changes.
0.10.2 (2026-07-25)¶
Docs: extensions/index-terms.md described the live website's search as
generic "browser/Ctrl-F search" - updated to point at
Zensical's own built-in site search
instead, a more accurate and discoverable description of how a reader
actually finds a term on the live website. No code changes.
0.10.1 (2026-07-24)¶
Docs: prodockit.index's marking syntax and prodockit.pdf's back-of-book
index generation were split across two pages (extensions/index-terms.md
and pdf.md respectively), even though the marker is useless without
turning pdf_include_index on and vice versa - prodockit.bibliography's
own docs already combine marking and generation into one page. Moved the
generation content into extensions/index-terms.md as a new "Generating
the index" section, merged the per-feature rendered-output examples into
their existing marking sections instead of duplicating them, and renamed
the page from "Index terms" to "Index (pdf-only)" now that it covers the
whole feature. pdf.md keeps only a short pointer, matching how
prodockit.bibliography is treated there. No code changes.
0.10.0 (2026-07-24)¶
prodockit.bibliography's \bibliography marker now takes two optional,
positional parameters - \bibliography{<file>}{<true|false>} - so a
project can generate both a strict References section (only sources
actually \citebib{}-cited in the text) and a broader Bibliography
section (every entry, including background reading that's never
individually cited) in one build, from the same or different .bib
files:
Bare \bibliography is completely unchanged - fully backward compatible,
no breaking change. A \citebib{id} citation now cross-links to
whichever marker's page actually defines that entry (via a new,
lightweight .bib entry-key discovery helper, not a CSL reimplementation)
rather than assuming a single global bibliography page - the common
single-file case is unaffected. See
Multiple sections: References and Bibliography
for the full syntax and worked examples.
Fixes #89.
0.9.0 (2026-07-24)¶
Breaking: copyright/pdf_copyright are now a real HTML fragment,
rendered as a real DOM element in the PDF's running footer via CSS Paged
Media's position: running()/content: element(), instead of being
escaped into a CSS content: "..." string. This is what makes a real
<a href="../..."> link inside either value survive as a real, clickable
link in the PDF - on every page, not just wherever the source element
itself sits - matching how Zensical's own website-side copyright
setting already works. Use a real <br> for a forced line break; the
\A CSS-escape trick added in 0.8.0 only ever worked for a plain
string, not real markup, and no longer applies - update any existing
pdf_copyright using it to a real <br> instead.
prodockit.pdf.css.build_css() no longer takes a copyright_text
parameter (site_name is unaffected, still a plain CSS content string)
- no formal, versioned public API surface yet for prodockit.pdf (see
prodockit-extension#7), so this is an acceptable break at this stage.
This project's own cover page (docs/index.md's hero subtitle) no
longer hyperlinks the word "Zensical" - it stays as plain text, matching
this project's own PDF footer now crediting Zensical/prodockit with
real links instead of the cover page doing it via a website-only,
PDF-invisible link.
0.8.1 (2026-07-24)¶
Docs: this project's own docs site and PDF were missing the "Made with
Zensical and prodockit" credit line that overrides/partials/
copyright.html/pdf_copyright (new in 0.8.0) already give a downstream
project - added both here too, via a new overrides/partials/
copyright.html for the website and extra.pdf_copyright in
zensical.toml for the PDF, so this site credits itself the same way a
project built with it does. No library code changed.
0.8.0 (2026-07-24)¶
New pdf_copyright setting: project.copyright (a plain, native Zensical
setting) already feeds the footer of both the website and the PDF by
default - pdf_copyright is an opt-in override for the PDF's footer only,
for a project that wants its PDF footer to say something different from
its website's (e.g. adding a "Made with Zensical and prodockit" credit
line only to the downloadable PDF, not the live site). Write a forced
line break in either setting with a literal \A inside a TOML literal
string ('''...''') - see Copyright text for
the full mechanism and why a literal string is required.
Also fixed a real, previously-undocumented rendering gap found while
building this: a \A forced line break inside a content string only
actually renders as a line break under white-space: pre-line - under
WeasyPrint's default white-space: normal it silently collapsed to a
plain space instead. Both the single-sided and double-sided verso
copyright footer boxes now set white-space: pre-line so the forced
break always works as expected.
0.7.1 (2026-07-24)¶
This project's own documentation site now enables every prodockit
extension (prodockit.headings, prodockit.refs, prodockit.citations,
prodockit.glossary, prodockit.bibliography, in addition to the
prodockit.tables/prodockit.index already enabled) via zensical.toml,
dogfooding the full set rather than just the two used to build this
site previously.
Doing so surfaced a real bug: Zensical does not render pages in a stable
order between builds, so a heading name shared across two or more pages
(e.g. "Quick start", "Syntax", "Options") non-deterministically resolves
its id collision differently from one zensical build to the next -
confirmed by running repeated clean builds and observing the reported
"keeping the first" winner change between runs. Fixed by giving every
colliding heading across the docs an explicit, unique, page-prefixed id
via attr_list (e.g. ## Quick start {: #refs-quick-start }), rather
than relying on build order at all. No library code changed - this is a
docs-content-only fix, and not something a project sharing a heading
name across its own pages will normally have to think about, since a
one-off name collision is far less likely there than in this project's
consciously-parallel per-extension documentation structure.
0.7.0 (2026-07-24)¶
Breaking: prodockit.bibliography now uses its own \citebib{id}
syntax instead of \cite{id}. Previously it registered the same
\cite{id} pattern prodockit.citations uses, at the same inline-pattern
priority - enabling both extensions together left it undefined which one
actually resolved a given \cite{...} occurrence. Renaming
prodockit.bibliography's own syntax removes the conflict entirely: both
extensions can now be enabled in the same build with no interference,
each citing its own sources by its own marker. A project still using
prodockit.bibliography on its own needs to update every \cite{id} in
its source to \citebib{id} - the old syntax no longer resolves.
0.6.8 (2026-07-21)¶
build_pdf_from_zensical_config() (what prodockit pdf runs) now supports
cover page markers, so a project no longer needs its own custom Python
just to fill in a cover page's word count/repo URL/release tag - found via
prodockit-template, whose build_pdf.py had grown to nearly nothing
except this one piece:
{WORDCOUNT}- the site-wide word count (the same value a{{ word_count }}website macro shows).{REPOURL}- the git-detected repo URL.{RELEASE}- the latest published GitHub/GitLab release tag - the whole line is dropped instead if there isn't one.{{ site_name }}- substituted literally, sinceprodockit pdfnever evaluates Jinja.
All four are opt-in by literally writing the marker in your nav's index
page - no new zensical.toml setting needed. See
Cover page markers.
Also new: pdf_extra_css, a stylesheet meant only for the PDF (e.g. a
rule that would look wrong on the live website), concatenated after
extra_css - the same ["stylesheets/print.css"] role a project's own
custom PDF-build script might have hardcoded outside zensical.toml
entirely before, now expressible as ordinary configuration.
Also fixed two real bugs found while building this:
extra_css's (and nowpdf_extra_css's) own relativeurl(...)references (e.g. a light/dark logo swap or a header background image) were passed through unresolved, pointing nowhere once compiled into the PDF's own temporary work directory - now resolved and base64-embedded, matching how a local<img>reference already was.copyright/site_namewere passed straight intobuild_pdf()'s generated CSScontent: "..."string with no escaping at all -project.copyrightis commonly a triple-quoted TOML string spanning multiple lines, and a raw embedded newline (or a literal") silently broke the whole generated rule, dropping the running header/footer entirely with no error. Both are now collapsed to one line and escaped before being passed through.
0.6.7 (2026-07-21)¶
Fixed prodockit.pdf.html.fix_up_page_html() permanently embedding
both halves of a #only-light/#only-dark (or GitHub's
#gh-light-mode-only/#gh-dark-mode-only) image pair in a PDF, stacked
one after the other, instead of just one - found via prodockit-template's
own cover page hero graphic showing twice. A PDF has no light/dark toggle
to make that convention meaningful, but to_base64_data_uri() already
strips anything from # onward before resolving the file (to find the
right one), so the resulting data: URI has no trace of the fragment
left for any stylesheet to hide either half by. The #only-dark/
#gh-dark-mode-only half is now dropped entirely rather than embedded.
0.6.6 (2026-07-21)¶
- Docs: the cover page hero graphic (
docs/assets/cover-hero-*.svg) used a different colour palette in light mode (blue) than in dark mode (green) - recoloured the light variant to match dark exactly, so the hero reads the same regardless of theme. The "Download PDF" button also picked up this same green, rather than the theme's default primary colour. prodockit.pdf.css's back-of-book index letter-group headings (h2.prodockit-index-letter- the "A", "B", "C" separators) were hardcoded to the hero graphic's old light-theme blue - updated to match the now-green hero, which a PDF always shows regardless of a project's own website light/dark toggle.- No functional (Python package behaviour) changes beyond the index letter colour.
0.6.5 (2026-07-21)¶
Extends the 0.6.4 always-excluded-directory mechanism in
prodockit.pdf.source_bundle to two more classes of vendored, never
student-written content:
- Any directory literally named
styles- a ValeStylesPath(conventionally named this way) holds downloaded rule packs (e.g. the Microsoft, proselint, and Readability style guides), typically tracked for offline/CI builds rather than gitignored. - Common dependency lockfiles by exact file name -
package-lock.json,npm-shrinkwrap.json,yarn.lock,pnpm-lock.yaml,Pipfile.lock,poetry.lock,Cargo.lock- machine-generated by a package manager, never hand-written, and often thousands of lines each.
Neither is project-configurable, matching 0.6.4's .icons exclusion: a
project can't reach for the same knob to narrow what a bundle archives.
Also fixes source_bundle.pdf's running header naming the wrong file: a
file's own last page could show the next file's name instead of its
own, because the invisible marker that sets the header text had no page
break of its own - only the following content did - so it rendered on
the tail end of the previous file's last page. The break now moves onto
the marker itself, so the string-set and the page it applies to always
agree.
0.6.4 (2026-07-21)¶
prodockit.pdf.source_bundle now always excludes any directory literally
named .icons (e.g. a custom_icons directory, per pymdownx.emoji's
own convention) from source_bundle.pdf, regardless of .gitignore -
found via prodockit-template, whose own vendored icon packs
(overrides/.icons/bootstrap, overrides/.icons/gitlab - together
~2,500 unused SVGs) turned a source bundle meant to hold a student's own
report content into a 3,000-page dump of unreferenced vendor assets.
.gitignore alone can't fix this, since these directories are typically
tracked (needed for the site/PDF to build at all) - deliberately not a
project-configurable setting, so a project can't reach for the same knob
to exclude something that should actually be archived.
0.6.3 (2026-07-20)¶
Bug fixes found by an in-depth test-coverage review of the extensions and PDF pipeline test suites - each paired with a new regression test.
- Fixed
prodockit pdf's CLI command showing a raw, unhandled traceback instead of a cleanError: ...message whenpdf_source_bundlewas enabled and the underlyinggit/weasyprintinvocation failed -SourceBundleErrorwasn't in the CLI's caught exception tuple. - Fixed
prodockit.headingsnumbering a skipped heading level (e.g. h1 followed directly by h3, or a document starting below h1) with a literal "0" segment (e.g. "1.0.1") - a shallower level with no heading of its own yet is now treated as an implicit first one instead. - Fixed
prodockit.pdf.mermaidletting an uncaughtOSError/PermissionError(e.g. a non-executablemmdcbinary) escape instead of failing just that one diagram gracefully. - Fixed
prodockit.pdf.source_bundlecrashing the whole bundle build on a file that's valid UTF-8 in the first 8 KiB sniffed to decide "is this text?" but not further in - now skipped like any other binary file instead. - Fixed
prodockit.pdf's generated Lua filter producing broken syntax if a configured math/tex2svg path contained a quote or backslash - both are now escaped. - Fixed
prodockit.pdf.build_pdf()having no timeout on the underlyingpandoc/WeasyPrint invocation, so a hang (e.g. a pathological CSS layout) could block the whole build indefinitely - added apandoc_timeoutparameter (default 30 minutes). - Fixed a back-of-book index term nested more than three levels deep rendering with no extra indent at all, since the generated CSS only defines an indent step up to level 3 - now clamped to the deepest available indent instead.
- Substantially expanded test coverage across the extensions and PDF pipeline test suites (shared registries, cross-page linking, malformed input, table/index edge cases, icon/rotation/CSS edge cases) - no other functional changes.
0.6.2 (2026-07-20)¶
- Docs: fixed a real bug found by checking the live site after 0.6.1 -
four spots in
docs/extensions/index-terms.md/docs/pdf.md(plus two more in this same changelog) tried to show the code-styled\index{}syntax as literal example text using inline backticks around a hierarchical, code-styled path. Confirmed directly this doesn't work the way it does for the plain syntax - the code-styled pattern has to run before Python-Markdown's own backtick handling (see 0.6.0's own entry below), so inline backticks don't protect it, and the live site was rendering a raw internal Python-Markdown placeholder string instead of the intended literal text. Moved each one to a fenced code block (already documented as the safe way to show this syntax) or reworded to avoid the literal example entirely. - No functional changes.
0.6.1 (2026-07-20)¶
- Docs:
prodockit.index(new in 0.6.0) was missing fromREADME.md- and so from PyPI's own project page - entirely: added it to the "Status" line and the extensions table, and mentionedpdf_include_indexalongsideprodockit.pdf's other PDF-only features. Also added it topyproject.toml's owndescription(PyPI's summary line) andsrc/prodockit/__init__.py's module docstring, both of which had the same gap. - No functional changes.
0.6.0 (2026-07-20)¶
- New
prodockit.indexextension: mark a term inline with\index{Term}for a traditional, PDF-only back-of-book index (browser/Ctrl-F search covers this on the live website, so there's no equivalent there) - the term displays inline exactly as written and is marked for indexing in one go, no separate "definition" step. Needed its own extension rather than the usualattr_listmarker convention every other prodockit extension uses - confirmed directly plainattr_listcan't wrap arbitrary inline text in a span on its own.- Sub-entries:
\index{Parent!Child!Grandchild}(up to three levels deep in practice, matching LaTeXmakeidx's own\index{primary!secondary!tertiary}convention) nests related entries together instead of listing every term flat. - Code-styled terms: backticks around the last segment - or,
combined with sub-entries, around just the last segment of a
hierarchical path - mark a command/code term: it displays inline in
a real
<code>element, and the generated index entry renders the same way. - A term can be a markdown link or contain nested emphasis/code -
confirmed directly neither needs special handling, since a term
isn't exempted from Python-Markdown's own later inline-pattern
passes the way
\ref{id}/\cite{id}/\gls{id}are.
- Sub-entries:
- New
prodockit.pdf.index: the two-pass build (a term's own page number can only be known once WeasyPrint has already laid the PDF out once) behindpdf_include_index/pdf_index_title(both off/unset by default) - a traditional, two-column, letter-headed index page (matching this project's own cover page hero graphic colour), alphabetised ignoring leading punctuation (so--set-upstream optionfiles under "S", not a separate symbols section), with consecutive pages collapsed into an en-dash range (67–70). Requires the new optionalpymupdfdependency -pip install prodockit[index]. - Fixed a real bug found while writing tests: code-styling a non-last segment of a hierarchical term - never a supported combination, but this shouldn't have corrupted anything either - used to leak a raw Python-Markdown internal stash placeholder into the generated index instead of failing gracefully - a real rendered PDF would have shown a nonsense category label instead of "Git".
0.5.0 (2026-07-19)¶
- New
prodockit.pdf.source_bundle: bundles every text/source file.gitignoredoesn't exclude into a separatesource_bundle.pdfat a project's own top-level directory - 8pt Courier, wrapped lines, each file starting its own page, a running header (site_nameon the left, that page's own file path on the right), and a "Page N of M" footer. Off by default; setpdf_source_bundle = trueunder[project.extra]to turn it on. Independent of the rest ofprodockit.pdf- there's no Markdown involved, so it skips Pandoc entirely and hands a small, self-contained HTML document straight to WeasyPrint. File discovery shells out togit ls-files --cached --others --exclude-standardrather than reimplementing.gitignore's own matching rules; text/ binary filtering is content-based, not by file extension. - Docs: this site's own header now shows a PDF download icon next to
"view" (an
overrides/partials/actions.htmloverride, linking to that page's own per-page PDF) instead of a "Download this page as PDF" text link at the top of the page - removed from every page that had one. Since the new icon is template markup rather than Markdown content, it also no longer shows up inside the PDF itself (no.web-onlyCSS trick needed, unlike the link it replaces).
0.4.2 (2026-07-19)¶
- Docs: matched more of this site's own theme config to
prodockit-userguide's -
the header's repo link now shows the actual GitHub logo instead of
Zensical's default Git icon; the "View source of this page" button now
shows an eye icon instead of a generic file icon; every admonition
(e.g. the "tip" callout in
citations.md) now uses the same custom FontAwesome icon set userguide uses instead of Zensical's own bundled defaults - this also feeds intoprodockit.pdf's own admonition icons, so PDF output picks it up too; added the matching theme features userguide already had (content.tabs.linkin particular actually affects this project's own tabbed content); and swapped the palette toggle icons to match userguide's own light/dark convention. - No functional (Python package) changes.
0.4.1 (2026-07-18)¶
- Docs: reworked this site's own chrome to match prodockit-userguide's - a new split hero cover page ("Home"), reusing that project's own logo/ favicon/illustration assets; top-level nav moved to a top tab bar with the right-hand page TOC merged into the left sidebar instead; the previous cover page's own prose moved to a new "Introduction" page.
- Fixed a real bug found along the way:
zensical.toml's owncopyrightwas a triple-quoted, multi-line TOML string -prodockit.pdfsubstitutes it verbatim into a CSScontent: "..."string for the PDF's running footer, and the embedded newline silently broke that declaration, dropping the whole footer with no error (this site's own PDF footer had no copyright text at all). Fixed to a single-line string, and switched©to a literal©character - a CSS content string doesn't decode HTML entities either. - Fixed the deploy workflow missing a per-page PDF build step for the new Introduction page (its own "Download this page as PDF" link 404'd), and that page's leftover PDF link (still the old cover page's, pointing at the whole-site PDF) to the same per-page convention every other content page already uses.
- No functional (Python package) changes.
0.4.0 (2026-07-18)¶
- New
pdf_double_sidedoption: a duplex-printing layout for book/ handbook-style documents printed and bound on both sides. Verso (left- hand) and recto (right-hand) pages mirror their header/footer content and page margins (newpdf_margin_inner/pdf_margin_outer, replacingpdf_margin_left/_rightin this mode) via CSS Paged Media's@page :left/:rightselectors - chapter title and page number always on the outer, fore-edge corner; site name and copyright always on the inner, spine-side corner, whichever physical side that is for a given page. Every numbered heading now starts its own recto page (break-before: recto, auto-inserting a blank page as needed - confirmed directly this needs no Python-side page-counting logic at all), and aprodockit-table-rotatedlandscape page's own rotation direction now alternates by its final page position (270 degrees on recto, 90 on verso - the spine sits on the opposite physical side either way). - New
recto_titlefront matter key: overrides a page's own running header text with a shorter title, from the next page onward (the heading's own page still shows its full title - confirmed directly this is a consequence of CSSstring()'s "first value on this page wins" default policy) - useful for a chapter title too long to fit comfortably in the header, with or withoutpdf_double_sided. - Off by default: a single-sided build is completely unchanged.
0.3.1 (2026-07-18)¶
- Docs: renamed
glossary.md's heading to "Acronyms and Glossary" andcitations.md's to "Citations or References" (and their matching nav labels); added a flow diagram tobibliography.md's Requirements section (and fixed a real, unrelated gap found along the way - this docs site had no Mermaidcustom_fencesconfig at all, so a plain```mermaidfence never rendered as a diagram anywhere on the site); switched the citation-style example toharvard-cite-them-right.csl; added an admonition pointing fromprodockit.citationstoprodockit.bibliography; and notedprodockit.bibliography's own independent Pandoc invocation inprodockit.pdf's "Limitations and workarounds". - Docs: updated
README.md(and so PyPI's own project page description) to includeprodockit.tables/prodockit.bibliography, and to mention sideways tables/.web-only/.pdf-onlyunder PDF generation - it had gone stale since both extensions shipped in 0.3.0. - No functional changes.
0.3.0 (2026-07-18)¶
- New
prodockit.bibliographyextension: an alternative toprodockit.citationsfor a.bib-backed reference list instead of a hand-authored one. Define sources in a BibTeX/BibLaTeX.bibfile, cite them with the same\cite{id}syntax, and get the resolved citation text and a full, auto-generated reference list formatted in any Citation Style Language (CSL) style (APA, IEEE, Harvard, ...) via Pandoc's own--citeproc- confirmed directly against real Pandoc output rather than reimplementing citation formatting, and rejected an actual LaTeX/biblatex toolchain as a new hard dependency along the way. Makespandoca required dependency for this extension specifically, including for a website-only build with no PDF. Newdocs/extensions/bibliography.mdincludes a "References and Bibliography" comparison of this,prodockit.citations, and whatprodockit-template/prodockit-userguidecurrently do. - New sideways (90-degree anticlockwise) tables in the PDF: wrap a table
and its own caption in
<div class="prodockit-table-rotated" markdown="1">to print it on its own landscape-sized page(s), spanning multiple pages with a repeated heading row exactly like any other table. Confirmed directly that a CSStransform: rotate()doesn't work for this (clips the table to one page and loses its heading row) - the actual rotation is applied afterwards via a/Rotatepost-process on the finished PDF (newprodockit.pdf.rotatemodule, newpypdfdependency). .web-onlycontent is now hidden in every PDF build automatically, viaprodockit.pdf.css's own always-included stylesheet - no project-side CSS needed any more..pdf-onlyis documented as a one-line, centrally- sourced snippet instead (prodockithas no way to reach into a project's own website stylesheet), in a new "Web-only / PDF-only content" section in the PDF generation docs.
0.2.0 (2026-07-18)¶
- New
prodockit.tablesextension: gives a table column a percentage or fixed width via awidthattribute already attachable to a header cell withattr_list- no new syntax. Column-width distribution beyond what's explicitly given is left to CSS's owntable-layout: fixedalgorithm rather than computed in Python. Ships with the matching CSS inprodockit.pdf's generated stylesheet, and documents the equivalent rule a project's own website theme needs (see the new Tables docs page). - New
prodockit pdf --markdown-file/-moption: builds a PDF from a single markdown file instead of the wholenav, using the samezensical.tomlsettings as a full build. prodockit.pdf's generated table CSS now draws a full grey 0.5pt grid - outer border and internal row and column lines (there was previously no line between columns at all) - and reads a project's ownextra_css(fromzensical.toml), so a project-specific@media printrule (e.g. hiding a website-only "Download PDF" link/button) also applies in the PDF.prodockit.citations: a resolved\cite{id}link now always getsclass="prodockit-cite-resolved"(previously no class at all), matchingprodockit.refs/prodockit.glossary's existing convention of a stable class for both the resolved and unresolved case.- Docs: added a "CSS hooks" section to
refs.md/citations.md/glossary.md(headings.mdalready had one), documenting every class/ attribute each extension itself emits; replaced the docs site's "edit this page" link with "view this page" (acontent.action.viewlink to the raw source rather than a GitHub edit form); added a whole-site PDF download button on the front page and a per-page download link on every other page, both built via the new--markdown-fileoption above. - Fixed
prodockit.__version__reporting a stale"0.10.0"(left over from before thezendoc→prodockitrename) instead of matching this package's actual,pyproject.toml-declared version.
0.1.1 (2026-07-17)¶
- Docs: reworded the package intro on the docs site and README (dropped
the
pymdown-extensionscomparison, added a mention of the website macros and a one-line "kit for professional documentation" summary) - no functional changes.
0.10.0 (2026-07-15)¶
- New
prodockit.zensical_macros: Jinja variables/macros for Zensical's own macros plugin -{{ word_count }}(site-wide prose word count, excluding the cover page and any page flaggedexclude_from_word_count: true),{{ repo_url }}(git-detected repository URL),{{ site_name }}, andheading_counter_reset(page)/reference_style()/acronym_style()/glossary_style()macros. Add it alongside a project's ownmacros.pyviazensical.toml'smodules = ["prodockit.zensical_macros"]- or use it alone if the project has no macros of its own. - New
prodockit.wordcount: the generic prose word-count utility (count_words()/compute_word_count()) behind bothprodockit.pdf's{WORDCOUNT}-style cover-page use andprodockit.zensical_macros'{{ word_count }}- previously duplicated independently by each downstream project needing both. - New
prodockit.settings:flatten_nav(),heading_numbering_enabled(), andreference_style_values()- theproject.extra.*reading shared byprodockit.pdf.configandprodockit.zensical_macros, so the two agree on one set of fallback defaults instead of each hand-maintaining its own copy.prodockit.pdf.config.build_pdf_from_zensical_config()now uses these too (previously inlined), and itspdf_math_dirsetting is now created automatically if configured to a directory that doesn't already exist (matching the auto-detected default's existing behaviour).
0.9.0 (2026-07-15)¶
- New
prodockit pdfcommand: builds a complete PDF with no Python required, reading everything - nav, docs directory, fonts, page size, and all PDF-specific settings - from the project's ownzensical.toml, the same wayzensical build/zensical servedo. Installingprodockitnow registers aprodockitconsole script (pip install prodockitis enough - no separate build script to write). See the newprodockit.pdf.configmodule (build_pdf_from_zensical_config()) for the config-to-build_pdf()orchestration this wraps: nav-tree flattening, per-pageis_appendixfront-matter detection, and auto-detection of a localmmdc(Mermaid) binary and MathJaxtex2svgscript, so a typical project needs no extra configuration beyond what it likely already has. build_pdf()gainedinclude_table_of_contents/table_of_contents_titleparameters (both used automatically byprodockit pdf): a generated table of contents is now inserted by default, right after a cover page if one is markedis_index=True, or at the very start otherwise.- Rewrote the PDF generation docs page around the
prodockit pdfcommand as the primary, and for most projects only necessary, way to useprodockit.pdf-build_pdf()and the individual pipeline pieces are now documented as the advanced, scripting-your-own-pipeline path.
0.8.0 (2026-07-15)¶
- New
prodockit.pdf.build_pdf(): a one-call convenience wrapper around the rest ofprodockit.pdf- hand it a list of already-rendered pages (prodockit.pdf.Page) and where to write the PDF, and it fixes up each page's HTML, generates the Lua filter and CSS, concatenates everything, and runspandoc/WeasyPrint for you. Takesoutput_path(the PDF's own destination path) plus font/page-size/margin/header-footer/reference- style/numbering/math parameters, all with sensible defaults. Raises the newprodockit.pdf.PdfBuildError(with the underlyingpandocexit code and stderr attached) if the build fails, rather than failing silently.prodockit.pdf.html/.lua/.css/.icons/.mermaidremain directly importable if you need more control over how the pieces fit together. - Rewrote the PDF generation docs page around
build_pdf()as the primary documented way to useprodockit.pdf, leading with a short, practical quick-start example rather than the implementation-level detail of how Pandoc/WeasyPrint's own quirks are worked around (that detail is still there, now further down, for anyone who wants it).
0.7.0 (2026-07-15)¶
- New
prodockit.pdf: a Pandoc/WeasyPrint pipeline for building a standalone PDF from Zensical-rendered HTML - not a Python-Markdown extension (nomarkdown.extensionsentry point), a plain function library, since a PDF build pipeline isn't a Markdown syntax extension:prodockit.pdf.html:fix_up_page_html()and link/anchor/image helpers- fixes up one page's already-rendered HTML for Pandoc's own reader/
writer quirks (attribute loss on
<p>, raw<svg>not surviving the round trip to WeasyPrint, footnote/caption structural mismatches, cross-page link rewriting for a concatenated multi-page PDF, and more). prodockit.pdf.lua:build_lua_filter()- chapter/appendix numbering, caption chapter-prefix numbering, tabbed-set reconstruction, and MathJax pre-rendering, generated as a parameterized Lua filter.prodockit.pdf.css:build_css()- the compiled CSS a PDF needs on top of a project's own website stylesheet, including WeasyPrint-specific page-break tuning for headings, paragraphs, tables, code blocks, figures/captions, admonitions, and grid cards.prodockit.pdf.icons/prodockit.pdf.mermaid: admonition icon resolution and Mermaid diagram pre-rendering, as standalone helpers.
- Fixed a real bug found while writing tests: the iframe→"Watch Video"
admonition link builder stripped the video id from every single
conversion (a replace-then-split ordering removed the just-added
?v=...too) - now produces a working YouTube watch link. - No formal, versioned public API surface yet (see prodockit-extension#7) - import whatever's needed directly, the same informal way as the rest of this package.
- New dependency:
beautifulsoup4(>= 4.12). - Broadened the package's own description: prodockit is now framed as a family
of extensions for Zensical needed for professional and academic
documentation, rather than "Python-Markdown extensions" specifically -
prodockit.pdfisn't one, and the framing was due to broaden anyway now that PDF generation is in scope alongside cross-references/citations/ glossary.
0.6.0 (2026-07-14)¶
prodockit.headings: newnumbering="continuous"option (Zensical only) -h1numbering carries on from wherever the previous nav page left off, instead of restarting at 1 on every page. Fixes\ref{id}showing the wrong number for a heading on a different page (it previously always showed that page's own per-document number, not the number actually displayed on the page - see zendoc-template#89).- New
appendix_attroption (defaultis_appendix): a page whose front matter sets this flag is numbered with a letter instead - "A", "A.1", "A.1.1" - and doesn't consume a number from the numeric sequence, so later pages aren't left with a gap. Letters are assigned sequentially in nav order. - New public
prodockit.headings.prescan(appendix_attr="is_appendix")function: returns the same(start_counts, appendix_letters)pre-scanHeadingsExtensionuses internally, for a consuming project's own build tooling (e.g. a template macro driving a presentational CSS counter-reset) to stay in sync automatically rather than re-deriving the same page-order/heading-count logic independently.
0.5.1 (2026-07-14)¶
prodockit.glossary: a resolved\gls{id}now always renders withclass="prodockit-gls"(previously it had no class at all), matchingprodockit.refs' always-present base class. The unresolved case now rendersclass="prodockit-gls prodockit-gls-unresolved"(previously justprodockit-gls-unresolved, missing the base class), so a stylesheet has one stable hook (.prodockit-gls) regardless of resolution state, with.prodockit-gls-unresolvedlayered on top only when needed.
0.5.0 (2026-07-14)¶
- New
prodockit.glossaryextension: define a term once viaattr_list(an id plus adata-termshort display string), then insert it by id from anywhere with\gls{id}, which resolves to the term's own text, linked to its definition - e.g.\gls{css}→CSS. Unlikeprodockit.citations'\cite{id}(which generates new bracketed citation text),\gls{id}inserts the term's own registered text in place - closer to LaTeX'sglossariespackage. - One shared
GlossaryRegistrycovers both acronym-style and glossary-style entries - they're the same kind of thing (an id with a short display text), so acronym and glossary pages can reference each other, or be referenced from any other page, with no special wiring. - Supports forward references within a document, an
unresolvedmarker (?by default) for an unknown id, and the same automatic Zensical cross-page registry sharing and nav pre-scan (for citing/using a term before its defining page has been converted) thatprodockit.citationsgot in 0.4.0. - Refactored the nav pre-scan logic (previously private to
prodockit.citations) into a shared, genericprodockit._zensical.preseed_attr_from_navhelper, sinceprodockit.glossaryneeded the identical scan.
0.4.0 (2026-07-14)¶
Fixes found migrating a real multi-page site's references page to
prodockit.citations for real - all discovered by actually building a
real multi-page site, not just single-document tests:
- Fixed a real correctness bug:
prodockit.refs/prodockit.citationswere emitting a bare#idfragment for every resolved link, including a cross-page one - which only works by coincidence in a single concatenated PDF document, but 404s on an actual multi-page website (an#idfragment only navigates within the current page). Both now emit a real relative link (e.g.references.md#id, correctly adjusted for the citing page's own directory depth) when the target is on a different page, which Zensical already knows how to rewrite into the right clean URL - the same way a hand-typed cross-page Markdown link already works. - New:
prodockit.citationspre-scans every page in a Zensical build's nav for citation definitions before any page is actually converted, so citing a source before it's defined - the common case, since a references page is usually kept at the end of nav as an appendix - resolves correctly in a singlezensical buildpass, rather than only working fromzensical serve's live-reload. NewCitationRegistry.preseed()method backs this; a real registration always supersedes a preseeded stub. RefsExtensiongained asourceoption (mirroringHeadingsExtension's), needed for the same-page-vs-cross-page link decision above.- Fixed the nav pre-scan matching a citation-definition attr_list example
shown literally inside a fenced code block in documentation - it now
skips fenced content, the same protection
CitationDefTreeprocessoralready gets for free from the real Python-Markdown parser.
0.3.0 (2026-07-14)¶
- New
prodockit.citationsextension: define a source once viaattr_list(an id plus adata-cite-textshort display string), then cite it by key from anywhere with\cite{id}(or\cite{id1,id2,...}for multiple), auto-generating a bracketed, linked citation -[Skoulikari, 2023]- instead of hand-typing the link and text at every citation site. - Supports forward references within a document, an
unresolvedmarker (?by default) for an unknown key, and the same automatic Zensical cross-page registry sharing (with soft-fail on key collisions) thatprodockit.headings/prodockit.refsgot in 0.2.0. - Auto-generating the references page's own listing from structured bibliographic data isn't built yet - see the extension's docs for the current scope.
- Fixed the
zensical.tomlinstallation examples in the docs: nested[project.markdown_extensions.prodockit.headings]tables don't work (Zensical only hoists thepymdownx/zensicalnamespaces that way) - the quoted-key form ([project.markdown_extensions."prodockit.headings"]) is required.
0.2.0 (2026-07-14)¶
prodockit.headings/prodockit.refsnow share their registry automatically under Zensical, without any explicitregistry/sourceconfiguration: each extension detects Zensical's per-page rendering context and derives a stablesourcefrom the page's own path, fixing cross-page\ref{id}references not resolving.- A heading id collision across two different sources, when detected via
this automatic Zensical sharing, now logs a warning and keeps the first
registration instead of raising
DuplicateIdError- so two unrelated pages that happen to share a heading title (e.g. both have an "Overview" section) no longer break the build. Explicitly-shared registries (the manual multi-page pattern) still raise on a collision, unchanged. - Fixed an extension-ordering bug:
prodockit.headingsandprodockit.refsnow find and share each other's registry regardless of which order they're listed in - previously, onlyprodockit.headings-then-prodockit.refsworked reliably, and Zensical's own TOML-to-extension-list conversion doesn't preserve list order at all.
0.1.0 (2026-07-14)¶
Initial release.
prodockit.headings: heading ids and hierarchical section numbering, backed by a sharedIdRegistry.prodockit.refs:\ref{id}section cross-references, resolving to the target's current section number, including forward references within a document and across a shared registry.- Documentation site built with Zensical, published at buckwem.github.io/prodockit-extension.