bookkit: running headers, numbered chapters, embedded serif, full-bleed cover - #20
Merged
Merged
Conversation
…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
force-pushed
the
claude/swe-principles-book-content-kit-fg95ke
branch
from
September 3, 2026 20:12
7cc426b to
1390587
Compare
alpibrupa
marked this pull request as ready for review
September 3, 2026 20:16
This was referenced Sep 3, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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_cssin_html.py), so both books currently built on this toolchain (and any future one) pick it up at once.string-set, shown top-center on every page of that chapter viacontent: string(...). Suppressed on the very first page and on front matter.target-counter(attr(href), page).chapter_section()now recognizes the"Chapter N — Title"convention frombook.yamland splits it into a small-caps numeral label above the heading, rather than folding the number into the title text with no visual distinction.fonts-ebgaramond, licence text copied intoassets/fonts/OFL-EBGaramond.txt): a real book serif embedded as base64 data-URI@font-facerules, subset automatically by WeasyPrint, so PDF/HTML/EPUB render identically regardless of what's installed on the reader's system.@pagewith 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)prompt-to-productionandprompt-to-evidence(PDF/EPUB/HTML) against this branch via editable installpage.get_fonts()), full-bleed cover with no visible margin or page numbermake checkclean 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