Add support for appendices: landscape diagrams, tables, and images; implement Kroki URL configurability; enhance directive parsing logic.

This commit is contained in:
Sebastian Unterschütz
2026-05-12 21:44:37 +02:00
parent 436cdcc516
commit 67f9d63f24
12 changed files with 1025 additions and 221 deletions
+66 -4
View File
@@ -4,6 +4,7 @@
package main
import (
"log"
"strconv"
"strings"
@@ -36,12 +37,28 @@ const (
dinSpaceBeforeHeading = 2 * dinLineHtBody // ≈ 12.7 mm
dinSpaceAfterHeading = dinLineHtBody // ≈ 6.35 mm
dinSpaceAfterParagraph = 4.0 // between body paragraphs
// List items use tighter line spacing than body text (1.2× instead of 1.5×).
// This keeps lists compact while remaining legible at 12 pt.
dinLineHtList = 5.0 // 12 pt × 1.2 ≈ 5.08 mm, rounded to 5.0
dinSpaceAfterList = 3.0 // gap inserted after the outermost list exits
)
// Appendix holds the title and image path for one annex entry.
// AppendixKind distinguishes between image and table annexes.
type AppendixKind int
const (
AppendixKindImage AppendixKind = iota
AppendixKindTable
)
// Appendix holds the content for one annex entry.
type Appendix struct {
Title string
Path string
Kind AppendixKind
Landscape bool // true → render on a landscape A4 page (15 mm symmetric margins)
Title string
Path string // image path (Kind == AppendixKindImage)
TableData [][]string // table rows (Kind == AppendixKindTable)
}
// IHKRenderer is the central PDF generator for IHK Chemnitz project documentation.
@@ -139,18 +156,63 @@ func (r *IHKRenderer) AddSource(source string) {
r.sources = append(r.sources, source)
}
// AddAppendix registers an annex entry in "Title | /path/to/image" format.
// AddAppendix registers an image annex in "Title | /path/to/image" format.
func (r *IHKRenderer) AddAppendix(titlePath string) {
parts := strings.SplitN(titlePath, "|", 2)
if len(parts) < 2 {
log.Printf("warning: @Anhang directive missing '|' separator: %q", titlePath)
return
}
r.appendices = append(r.appendices, Appendix{
Kind: AppendixKindImage,
Title: strings.TrimSpace(parts[0]),
Path: strings.TrimSpace(parts[1]),
})
}
// AddTableAppendix registers a table annex entry.
func (r *IHKRenderer) AddTableAppendix(title string, data [][]string) {
if len(data) == 0 {
log.Printf("warning: @TabelleAnhang %q has no table data — skipped", title)
return
}
r.appendices = append(r.appendices, Appendix{
Kind: AppendixKindTable,
Title: title,
TableData: data,
})
}
// AddLandscapeAppendix registers an image annex in "Title | /path/to/image" format
// that will be rendered on a landscape A4 page with 15 mm symmetric margins.
func (r *IHKRenderer) AddLandscapeAppendix(titlePath string) {
parts := strings.SplitN(titlePath, "|", 2)
if len(parts) < 2 {
log.Printf("warning: @AnhangBildQuer directive missing '|' separator: %q", titlePath)
return
}
r.appendices = append(r.appendices, Appendix{
Kind: AppendixKindImage,
Landscape: true,
Title: strings.TrimSpace(parts[0]),
Path: strings.TrimSpace(parts[1]),
})
}
// AddTableAppendixLandscape registers a table annex entry rendered on a landscape page.
func (r *IHKRenderer) AddTableAppendixLandscape(title string, data [][]string) {
if len(data) == 0 {
log.Printf("warning: @TabelleAnhangQuer %q has no table data — skipped", title)
return
}
r.appendices = append(r.appendices, Appendix{
Kind: AppendixKindTable,
Landscape: true,
Title: title,
TableData: data,
})
}
// Save writes the completed PDF to the given file path.
func (r *IHKRenderer) Save(filename string) error {
return r.pdf.OutputFileAndClose(filename)