Add ForewordParser pipeline step, document all Song/SongLine fields, Foreword type, ForewordPage variant, BookConfig subtypes, all ChordPro directives, and new Configuration section for songbook.yaml options. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Build & Test Commands
# Build everything
gradle build
# Run all tests
gradle test
# 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
Requires Java 21 (configured in gradle.properties). Kotlin 2.1.10, Gradle 9.3.1.
Architecture
Pipeline: Parse → Validate → Measure → Paginate → Render
SongbookPipeline (in app) orchestrates the full flow:
ConfigParserreadssongbook.yaml→BookConfigChordProParserreads.chopro/.cho/.crdfiles →SongobjectsForewordParserreads optionalforeword.txt→Foreword(if configured)Validatorchecks config and songsMeasurementEnginecalculates each song's height in mm usingFontMetricsTocGeneratorestimates TOC page count and creates entriesPaginationEnginearranges songs into pages (greedy spread packing)PdfBookRenderergenerates 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)
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.
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. Also hasaliases,lyricist,composer,key,tags,notes: List<String>,references: Map<String, Int>(bookId → page),capoSongLine— holdssegmentsplus optionalimagePath(when set, the line is an inline image)Foreword—quote,paragraphs,signatures— parsed from a plain-text filePageContent— sealed class:SongPage,FillerImage,BlankPage,ForewordPageSectionType— enum:VERSE,CHORUS,BRIDGE,REPEATBookConfig— top-level config withFontsConfig,LayoutConfig,TocConfig,ForewordConfig,ReferenceBooklist.FontSpec.filesupports custom font files.LayoutConfig.metadataLabels("abbreviated"or"german") andmetadataPosition("top"or"bottom") control metadata renderingBuildResult— returned bySongbookPipeline.build()with success/errors/counts
Song Format
ChordPro-compatible .chopro/.cho/.crd files: directives in {braces}, chords in [brackets] inline with lyrics, comments with #. See songs/ for examples.
Metadata directives: {title: } / {t: }, {alias: }, {lyricist: }, {composer: }, {key: }, {tags: }, {note: }, {capo: }
Section directives: {start_of_verse} / {sov}, {end_of_verse} / {eov}, {start_of_chorus} / {soc}, {end_of_chorus} / {eoc}, {start_of_repeat} / {sor}, {end_of_repeat} / {eor}. Section starts accept an optional label. {chorus} inserts a chorus reference, {repeat} sets a repeat label.
Notes block: {start_of_notes} / {son} … {end_of_notes} / {eon} — multi-paragraph rich-text notes rendered at the end of a song.
Inline image: {image: path} — embeds an image within a song section.
Reference: {ref: bookId pageNumber} — cross-reference to a page in another songbook (configured in reference_books).
Configuration
songbook.yaml at the project root. Key options beyond the basics:
fonts.<role>.file— path to a custom font file (TTF/OTF) for any font role (lyrics,chords,title,metadata,toc)layout.metadata_labels—"abbreviated"(M:/T:) or"german"(Worte:/Weise:)layout.metadata_position—"top"(after title) or"bottom"(bottom of last page)toc.highlight_column— abbreviation of the reference-book column to highlight (e.g."CL")foreword.file— path to a foreword text file (default./foreword.txt)reference_books— list of{id, name, abbreviation}for cross-reference columns in the TOCsongs.order—"alphabetical"or"manual"(file-system order)
Test Patterns
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.
Package
All code under de.pfadfinder.songbook.* — subpackages match module names (.model, .parser, .layout, .renderer.pdf, .app, .cli, .gui).