Rewrite songbook as pure LaTeX project (Carmina Leonis style)

Replace the Kotlin/Gradle multi-module pipeline with a pure LaTeX
songbook using the leadsheets package and LuaLaTeX. Style matches
the Carmina Leonis (CL6) scout songbook: Fraktur titles, chords
above lyrics, metadata at page bottom, reference book footer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
shahondin1624
2026-04-01 08:23:57 +02:00
parent e386501b57
commit 4024d0e421
65 changed files with 402 additions and 5121 deletions

118
CLAUDE.md
View File

@@ -2,79 +2,83 @@
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Test Commands
## Build Commands
```bash
# Build everything
gradle build
# Build the songbook PDF (two-pass for TOC)
make
# Run all tests
gradle test
# Remove auxiliary files
make clean
# Run tests for a specific module
gradle :parser:test
gradle :layout:test
gradle :renderer-pdf:test
gradle :app:test
# Run a single test class
gradle :parser:test --tests ChordProParserTest
# Run a single test method
gradle :parser:test --tests "ChordProParserTest.parse complete song"
# Build and run CLI
gradle :cli:run --args="build -d /path/to/project"
gradle :cli:run --args="validate -d /path/to/project"
# Launch GUI
gradle :gui:run
# Remove everything including PDF
make distclean
```
Requires Java 21 (configured in `gradle.properties`). Kotlin 2.1.10, Gradle 9.3.1.
Requires LuaLaTeX (TeX Live) and the `leadsheets` package.
## Architecture
## Project Structure
**Pipeline:** Parse → Measure → Paginate → Render
`SongbookPipeline` (in `app`) orchestrates the full flow:
1. `ConfigParser` reads `songbook.yaml``BookConfig`
2. `ChordProParser` reads `.chopro` files → `Song` objects
3. `Validator` checks config and songs
4. `MeasurementEngine` calculates each song's height in mm using `FontMetrics`
5. `TocGenerator` estimates TOC page count and creates entries
6. `PaginationEngine` arranges songs into pages (greedy spread packing)
7. `PdfBookRenderer` generates the PDF via OpenPDF
**Module dependency graph:**
```
model ← parser
model ← layout
model ← renderer-pdf
parser, layout, renderer-pdf ← app
app ← cli (Clikt)
app, parser ← gui (Compose Desktop)
songbook.tex # Main document (title page, TOC, song inputs)
songbook-style.sty # Style package (geometry, fonts, leadsheets config)
songs/ # One .tex file per song
fonts/ # Font files (UnifrakturMaguntia for titles)
images/ # Filler images (empty for now)
Makefile # Build rules (lualatex, two passes)
output/ # Generated PDF (gitignored)
```
`model` is the foundation with no dependencies — all data classes, the `FontMetrics` interface, and the `BookRenderer` interface live here. The `FontMetrics` abstraction decouples layout from rendering: `PdfFontMetrics` is the real implementation (in renderer-pdf), `StubFontMetrics` is used in layout tests.
## How It Works
**Pagination constraint:** Songs spanning 2 pages must start on a left (even) page. The `PaginationEngine` inserts filler images or blank pages to enforce this.
## Key Types
- `Song` → sections → `SongLine``LineSegment(chord?, text)` — chord is placed above the text segment
- `PageContent` — sealed class: `SongPage`, `FillerImage`, `BlankPage`
- `SectionType` — enum: `VERSE`, `CHORUS`, `BRIDGE`, `REPEAT`
- `BuildResult` — returned by `SongbookPipeline.build()` with success/errors/counts
Pure LaTeX songbook using the `leadsheets` package with LuaLaTeX. The style matches the Carmina Leonis songbook format:
- Song titles in Fraktur/blackletter font (UnifrakturMaguntia)
- Chords above lyrics in regular weight, black
- No verse labels (verses separated by blank lines)
- Metadata (Worte/Weise) at bottom of each song page
- Reference book cross-references (MO, PfLB) in footer
- Each song starts on a new page
- A5 twoside format with page numbers at bottom-outer
## Song Format
ChordPro-compatible `.chopro` files: directives in `{braces}`, chords in `[brackets]` inline with lyrics, comments with `#`. See `songs/` for examples.
Each song uses the `leadsheets` `song` environment:
## Test Patterns
```latex
\begin{song}{
title = Song Title,
lyrics = Lyricist,
composer = Composer,
key = G,
mundorgel = 42,
pfadfinderliederbuch = 118,
note = {Optional note text.},
}
Tests use `kotlin.test` annotations with Kotest assertions (`shouldBe`, `shouldHaveSize`, etc.) on JUnit 5. Layout tests use `StubFontMetrics` to avoid PDF font dependencies. App integration tests create temp directories with song files and config.
\begin{verse}
\chord{G}Lyrics with \chord{D}chords above. \\
Next \chord{C}line here.
\end{verse}
## Package
\begin{verse}
Second verse without chords (or with).
\end{verse}
All code under `de.pfadfinder.songbook.*` — subpackages match module names (`.model`, `.parser`, `.layout`, `.renderer.pdf`, `.app`, `.cli`, `.gui`).
\end{song}
```
**Important constraints:**
- Use `\\` for line breaks within verses (not blank lines)
- Never place two `\chord{}` commands without a space between them — split compound words with a hyphen: `\chord{D}Abend- \chord{A}zeit.`
- Custom properties: `alias`, `note`, `mundorgel`, `pfadfinderliederbuch`
- Verse types: `verse` (no label), `verse*` (for custom-labeled sections like Kanon, Ref.)
- `musicsymbols` library skipped (requires `musix11` font not installed)
## Style Details (songbook-style.sty)
- Page geometry: A5, margins (top 15mm, bottom 20mm, inner 20mm, outer 12mm)
- Body font: TeX Gyre Heros (Helvetica clone)
- Title font: UnifrakturMaguntia (Fraktur/blackletter, from `fonts/` directory)
- Chord format: small, regular weight, black
- Song title template: Fraktur title only (metadata rendered at bottom via `after-song` hook)
- Reference style based on Carmina Leonis (Pfadfinder scout songbook)