Add support for appendices: landscape diagrams, tables, and images; implement Kroki URL configurability; enhance directive parsing logic.
This commit is contained in:
+74
-9
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -43,9 +44,15 @@ func ParseMarkdown(mdPath string) (Config, ast.Node, []byte, error) {
|
||||
|
||||
// parserState tracks transient state during the AST walk.
|
||||
type parserState struct {
|
||||
nextCodeIsAppendix bool
|
||||
appendixTitle string
|
||||
listStack []listFrame // stack for nested list tracking
|
||||
nextCodeIsAppendix bool
|
||||
nextAppendixLandscape bool // set by @AnhangUMLQuer: — landscape for diagram appendix
|
||||
appendixTitle string
|
||||
nextTableCaption string // set by @Tabelle: directive
|
||||
nextTableIsAppendix bool // set by @TabelleAnhang: or @TabelleAnhangQuer:
|
||||
nextTableIsLandscape bool // set by @TabelleAnhangQuer:
|
||||
nextDiagramLandscape bool // set by @DiagrammQuer: directive
|
||||
nextDiagramCaption string // caption for the landscape diagram page
|
||||
listStack []listFrame // stack for nested list tracking
|
||||
}
|
||||
|
||||
// listFrame tracks the type and item counter for one list nesting level.
|
||||
@@ -107,13 +114,29 @@ func RenderAST(doc ast.Node, content []byte, r *IHKRenderer) error {
|
||||
|
||||
if lang == "mermaid" || lang == "plantuml" || lang == "puml" {
|
||||
imgPath, err := RenderDiagramViaKroki(lang, code)
|
||||
if err != nil {
|
||||
log.Printf("warning: diagram render failed (%s): %v — falling back to code block", lang, err)
|
||||
state.nextDiagramLandscape = false
|
||||
state.nextDiagramCaption = ""
|
||||
state.nextCodeIsAppendix = false
|
||||
state.nextAppendixLandscape = false
|
||||
}
|
||||
if err == nil {
|
||||
caption := lang
|
||||
if state.nextCodeIsAppendix {
|
||||
r.AddAppendix(state.appendixTitle + " | " + imgPath)
|
||||
switch {
|
||||
case state.nextDiagramLandscape:
|
||||
r.RenderLandscapeDiagram(imgPath, state.nextDiagramCaption)
|
||||
state.nextDiagramLandscape = false
|
||||
state.nextDiagramCaption = ""
|
||||
case state.nextCodeIsAppendix:
|
||||
if state.nextAppendixLandscape {
|
||||
r.AddLandscapeAppendix(state.appendixTitle + " | " + imgPath)
|
||||
state.nextAppendixLandscape = false
|
||||
} else {
|
||||
r.AddAppendix(state.appendixTitle + " | " + imgPath)
|
||||
}
|
||||
state.nextCodeIsAppendix = false
|
||||
} else {
|
||||
r.RenderImage(imgPath, "Diagram ("+caption+")")
|
||||
default:
|
||||
r.RenderImage(imgPath, "Diagram ("+lang+")")
|
||||
}
|
||||
return ast.WalkSkipChildren, nil
|
||||
}
|
||||
@@ -162,6 +185,11 @@ func RenderAST(doc ast.Node, content []byte, r *IHKRenderer) error {
|
||||
if len(state.listStack) > 0 {
|
||||
state.listStack = state.listStack[:len(state.listStack)-1]
|
||||
}
|
||||
// Add breathing room after the outermost list so the next
|
||||
// paragraph is not glued to the last bullet.
|
||||
if len(state.listStack) == 0 {
|
||||
r.pdf.Ln(dinSpaceAfterList)
|
||||
}
|
||||
}
|
||||
return ast.WalkContinue, nil
|
||||
|
||||
@@ -192,7 +220,20 @@ func RenderAST(doc ast.Node, content []byte, r *IHKRenderer) error {
|
||||
}
|
||||
tableData = append(tableData, rowData)
|
||||
}
|
||||
r.RenderTable(tableData, "")
|
||||
if state.nextTableIsAppendix {
|
||||
if state.nextTableIsLandscape {
|
||||
r.AddTableAppendixLandscape(state.nextTableCaption, tableData)
|
||||
state.nextTableIsLandscape = false
|
||||
} else {
|
||||
r.AddTableAppendix(state.nextTableCaption, tableData)
|
||||
}
|
||||
state.nextTableIsAppendix = false
|
||||
state.nextTableCaption = ""
|
||||
} else {
|
||||
caption := state.nextTableCaption
|
||||
state.nextTableCaption = ""
|
||||
r.RenderTable(tableData, caption)
|
||||
}
|
||||
return ast.WalkSkipChildren, nil
|
||||
}
|
||||
|
||||
@@ -226,10 +267,34 @@ func handleDirectives(text string, state *parserState, r *IHKRenderer) bool {
|
||||
case strings.HasPrefix(line, "@Anhang:"):
|
||||
r.AddAppendix(strings.TrimSpace(strings.TrimPrefix(line, "@Anhang:")))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@AnhangBildQuer:"):
|
||||
r.AddLandscapeAppendix(strings.TrimSpace(strings.TrimPrefix(line, "@AnhangBildQuer:")))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@AnhangUMLQuer:"):
|
||||
state.nextCodeIsAppendix = true
|
||||
state.nextAppendixLandscape = true
|
||||
state.appendixTitle = strings.TrimSpace(strings.TrimPrefix(line, "@AnhangUMLQuer:"))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@AnhangUML:"):
|
||||
state.nextCodeIsAppendix = true
|
||||
state.appendixTitle = strings.TrimSpace(strings.TrimPrefix(line, "@AnhangUML:"))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@TabelleAnhangQuer:"):
|
||||
state.nextTableIsAppendix = true
|
||||
state.nextTableIsLandscape = true
|
||||
state.nextTableCaption = strings.TrimSpace(strings.TrimPrefix(line, "@TabelleAnhangQuer:"))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@TabelleAnhang:"):
|
||||
state.nextTableIsAppendix = true
|
||||
state.nextTableCaption = strings.TrimSpace(strings.TrimPrefix(line, "@TabelleAnhang:"))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@Tabelle:"):
|
||||
state.nextTableCaption = strings.TrimSpace(strings.TrimPrefix(line, "@Tabelle:"))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@DiagrammQuer:"):
|
||||
state.nextDiagramLandscape = true
|
||||
state.nextDiagramCaption = strings.TrimSpace(strings.TrimPrefix(line, "@DiagrammQuer:"))
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
return handled
|
||||
|
||||
Reference in New Issue
Block a user