Skip to content

bookkit: running headers, numbered chapters, embedded serif, full-bleed cover - #20

Merged
alpibrupa merged 4 commits into
mainfrom
claude/swe-principles-book-content-kit-fg95ke
Sep 3, 2026
Merged

bookkit: running headers, numbered chapters, embedded serif, full-bleed cover#20
alpibrupa merged 4 commits into
mainfrom
claude/swe-principles-book-content-kit-fg95ke

Conversation

@alpibrupa

Copy link
Copy Markdown
Contributor

Summary

Every book built on bookkit was rendering with WeasyPrint's bare paged-media defaults — no running header, a table of contents with no page numbers, a plain chapter title with no numeral treatment, the reader's system Georgia/Times fallback instead of a real book face, and a cover image that shrank onto a page with margins and a stray page number instead of rendering full-bleed. This lives entirely in the shared stylesheet (default_css in _html.py), so both books currently built on this toolchain (and any future one) pick it up at once.

  • Running header: a chapter's title feeds a CSS string-set, shown top-center on every page of that chapter via content: string(...). Suppressed on the very first page and on front matter.
  • Table of contents: entries now get real page numbers with leader dots via target-counter(attr(href), page).
  • Chapter openers: chapter_section() now recognizes the "Chapter N — Title" convention from book.yaml and splits it into a small-caps numeral label above the heading, rather than folding the number into the title text with no visual distinction.
  • Embedded EB Garamond (OFL-1.1, packaged Debian font fonts-ebgaramond, licence text copied into assets/fonts/OFL-EBGaramond.txt): a real book serif embedded as base64 data-URI @font-face rules, subset automatically by WeasyPrint, so PDF/HTML/EPUB render identically regardless of what's installed on the reader's system.
  • Cover section: now renders full-bleed — a dedicated named @page with zero margin, no header/footer, and a negative margin that cancels the body's own padding — instead of a shrunk image centered on a page with visible margins and a page number.

Test plan

  • pytest tests/ — full bookkit suite green (all 96 tests)
  • Rebuilt prompt-to-production and prompt-to-evidence (PDF/EPUB/HTML) against this branch via editable install
  • Verified via rendered PNGs (PyMuPDF) on both books: running header text, TOC page numbers + leader dots, chapter-opener numeral styling, EB Garamond glyphs actually embedded (checked page.get_fonts()), full-bleed cover with no visible margin or page number
  • make check clean on both books (term-continuity linter unaffected — HTML/CSS-only change)

🤖 Generated with Claude Code

https://claude.ai/code/session_016kYixvQhaf5JjMoZX5oGJo


Generated by Claude Code

claude and others added 4 commits September 3, 2026 22:05
…ull-bleed cover

Every book built on this toolchain was using WeasyPrint's bare paged-media
defaults: no running header, a table of contents with no page numbers, a
plain bold chapter title with no typographic treatment, the reader's system
Georgia/Times fallback instead of a real book face, and no cover support
that actually rendered edge-to-edge. All of this lives in one shared
stylesheet (default_css in _html.py), so every book using bookkit picks up
the improvement at once rather than each book maintaining its own overrides.

- Running header: a chapter's title feeds a CSS string-set, shown top-center
  on every page of that chapter via @page's content: string(). Suppressed on
  the very first page and on front matter.
- Table of contents: entries now get real page numbers with leader dots via
  target-counter(attr(href), page), instead of being a plain link list.
- Chapter openers: chapter_section() now recognizes book.yaml's
  "Chapter N — Title" convention and splits it into a small-caps numeral
  label above the heading, rather than folding the number into the title
  text with no visual distinction.
- Embedded EB Garamond (OFL-1.1, packaged Debian font, licence copied into
  assets/fonts/): a real book serif embedded as base64 data-URI @font-face
  rules, subset automatically by WeasyPrint, so PDF/HTML/EPUB all render
  identically regardless of what's installed on the reader's system instead
  of silently falling back to Georgia.
- Cover section: now renders full-bleed (a dedicated named @page with zero
  margin, no header/footer, negative margin canceling the body's own
  padding) instead of a shrunk image centered on a page with a stray page
  number.

Verified against both current books (prompt-to-production,
prompt-to-evidence): full bookkit test suite green, rebuilt PDF/EPUB/HTML
for both, page-checked headers/TOC/cover/font rendering via rendered PNGs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kYixvQhaf5JjMoZX5oGJo
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kYixvQhaf5JjMoZX5oGJo
…mbedded font

Reported by the human author after reviewing the redesigned PDF: unordered
list items were rendering as "ᴬ[ ] Calculations were..." instead of a plain
bullet before the text. Root-caused via an isolated WeasyPrint reproduction:
the default disc list-marker glyph (U+2022) breaks specifically when EB
Garamond's embedded @font-face is active, even though the font itself has a
correct bullet glyph (confirmed via fontTools) — almost certainly a bug in
WeasyPrint's font subsetting for that particular marker glyph. A plain "Z"
or the middle-dot character (U+00B7) render fine in the same setup, and
numbered (<ol>) lists were unaffected throughout both books already.

Fix: stop relying on the native list-marker box for <ul> and render the
bullet as ordinary inline content instead (list-style: none + a "::before"
middle dot), which sidesteps the broken code path entirely rather than
working around it.

Verified against both books: rebuilt all three formats, page counts
unchanged (78 / 152), checklist and ordinary bullet lists both spot-checked
visually via rendered PNGs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kYixvQhaf5JjMoZX5oGJo
…rtions

Rebased onto main, where the concept ledger, part-grouped tables of contents
and the episode-timeline fix have landed since this branch was cut. Three
things needed fixing in the merge.

The margin boxes were still Times. Margin boxes inherit from the page context
rather than from body, so embedding a book serif and setting `font-family` on
body alone left the running header this branch adds -- and every page number --
in the reader's default face. Measured on the built PDF of Prompt to
Production: 159 page numbers and 155 running headers in Times New Roman
against an EB Garamond text block. Declaring the face inside `@page` removes
the fallback font from all four books entirely.

Part labels had no styling. This branch gave TOC entries leader dots and page
numbers; main gave the TOC part grouping. Composed, a part name rendered as a
list item indistinguishable from a chapter, in a nested list with the indent
zeroed. It now sets in small caps with the nesting visible, and picks up no
leader dots, having no anchor to number.

Two assertions were matching the stylesheet rather than the document. One
looked for the bare word "first", which the new `@page :first` rule satisfies;
the other for the bare string "toc-part", which a CSS rule mentioning the class
satisfies. Both passed for the wrong reason and are now pinned to the body.

Verified on all four books: PDF and EPUB build, `make check` clean, no
fallback font, running headers on every page but the front matter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@alpibrupa
alpibrupa force-pushed the claude/swe-principles-book-content-kit-fg95ke branch from 7cc426b to 1390587 Compare September 3, 2026 20:12
@alpibrupa
alpibrupa marked this pull request as ready for review September 3, 2026 20:16
@alpibrupa
alpibrupa merged commit e154f36 into main Sep 3, 2026
4 checks passed
@alpibrupa
alpibrupa deleted the claude/swe-principles-book-content-kit-fg95ke branch September 3, 2026 20:17
alpibrupa added a commit that referenced this pull request Sep 4, 2026
Since #20 a chapter's title ran top-centre on every page of that chapter,
including the chapter's own opening page -- where the title is already set two
inches below in 1.8em, and where book typography conventionally drops the
running head.

#29 recorded this as a limitation on the grounds that named page groups cannot
express it, and that part was right. WeasyPrint reads `:first` as the first
page of the document rather than of the page group, so `@page chapter:first`
suppresses only the very first chapter's opener. Alternating the names between
chapters, which should have broken the grouping, does not help either --
verified on 69.0, where four chapters given alternating names still print
their titles on openers two, three and four.

The mechanism that does work is not page groups at all. CSS Paged Media gives
`string()` a second argument for exactly this case: `first-except` yields the
empty string on the page where the string was set, and the set happens on the
chapter's own opening page. One keyword, no named pages, no alternating
classes, and continuation pages are untouched.

Verified across the four books in the series: 67 chapter and appendix openers,
none carrying a running head, and 328 continuation pages that still do.

Closes #29.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.

2 participants