Add support for code appendices: enable code blocks with language labels, line-number gutter, and directive-based integration.
This commit is contained in:
Generated
+6
-7
@@ -4,14 +4,10 @@
|
||||
<option name="autoReloadType" value="ALL" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="c64f46d5-641a-468c-8fc1-94edec1f2deb" name="Changes" comment="Refactor PDF content rendering: improve list indentation logic, add numbered code block rendering with gutter, and update text wrapping alignment.">
|
||||
<list default="true" id="c64f46d5-641a-468c-8fc1-94edec1f2deb" name="Changes" comment="Update MarkdownToIHKChemnitz: modify core functionality for improved PDF rendering">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/MarkdownToIHKChemnits" beforeDir="false" afterPath="$PROJECT_DIR$/MarkdownToIHKChemnits" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/diagram.go" beforeDir="false" afterPath="$PROJECT_DIR$/diagram.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/main.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/markdown_parser.go" beforeDir="false" afterPath="$PROJECT_DIR$/markdown_parser.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/pdf_content.go" beforeDir="false" afterPath="$PROJECT_DIR$/pdf_content.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/pdf_pages.go" beforeDir="false" afterPath="$PROJECT_DIR$/pdf_pages.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/pdf_renderer.go" beforeDir="false" afterPath="$PROJECT_DIR$/pdf_renderer.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/projektarbeit.pdf" beforeDir="false" afterPath="$PROJECT_DIR$/projektarbeit.pdf" afterDir="false" />
|
||||
@@ -23,7 +19,7 @@
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="EmbeddingIndexingInfo">
|
||||
<option name="cachedIndexableFilesCount" value="22" />
|
||||
<option name="cachedIndexableFilesCount" value="23" />
|
||||
<option name="fileBasedEmbeddingIndicesEnabled" value="true" />
|
||||
</component>
|
||||
<component name="GOROOT" url="file:///usr/lib/go" />
|
||||
@@ -103,7 +99,10 @@
|
||||
<MESSAGE value="Remove outdated `toc_pages.txt`, add new Go modules for IHK Chemnitz PDF rendering including diagrams, tables, and TOC functionality." />
|
||||
<MESSAGE value="Refactor PDF content rendering: improve list indentation logic, add numbered code block rendering with gutter, and update text wrapping alignment." />
|
||||
<MESSAGE value="Add table annex handling, update diagram rendering with configurable Kroki URL, and improve Markdown directive parsing" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Add table annex handling, update diagram rendering with configurable Kroki URL, and improve Markdown directive parsing" />
|
||||
<MESSAGE value="Add new features: diagram rendering via Kroki, table handling improvements including appendices, and Docker Compose setup for self-hosted Kroki." />
|
||||
<MESSAGE value="Add support for appendices: landscape diagrams, tables, and images; implement Kroki URL configurability; enhance directive parsing logic." />
|
||||
<MESSAGE value="Update MarkdownToIHKChemnitz: modify core functionality for improved PDF rendering" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Update MarkdownToIHKChemnitz: modify core functionality for improved PDF rendering" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
|
||||
Binary file not shown.
+21
-9
@@ -44,15 +44,17 @@ func ParseMarkdown(mdPath string) (Config, ast.Node, []byte, error) {
|
||||
|
||||
// parserState tracks transient state during the AST walk.
|
||||
type parserState struct {
|
||||
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
|
||||
nextCodeIsAppendix bool
|
||||
nextAppendixLandscape bool // set by @AnhangUMLQuer: — landscape for diagram appendix
|
||||
appendixTitle string
|
||||
nextCodeBlockAppendix bool // set by @AnhangCode: — next non-diagram code block → appendix
|
||||
codeBlockAppendixTitle 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.
|
||||
@@ -142,6 +144,12 @@ func RenderAST(doc ast.Node, content []byte, r *IHKRenderer) error {
|
||||
}
|
||||
// Fall through: render as plain code block on error
|
||||
}
|
||||
if state.nextCodeBlockAppendix {
|
||||
r.AddCodeAppendix(state.codeBlockAppendixTitle, lang, code)
|
||||
state.nextCodeBlockAppendix = false
|
||||
state.codeBlockAppendixTitle = ""
|
||||
return ast.WalkSkipChildren, nil
|
||||
}
|
||||
// Render as a numbered code block (gutter + monospace body).
|
||||
r.RenderCodeBlock(lang, code)
|
||||
return ast.WalkSkipChildren, nil
|
||||
@@ -264,6 +272,10 @@ func handleDirectives(text string, state *parserState, r *IHKRenderer) bool {
|
||||
case strings.HasPrefix(line, "@Quelle:"):
|
||||
r.AddSource(strings.TrimSpace(strings.TrimPrefix(line, "@Quelle:")))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@AnhangCode:"):
|
||||
state.nextCodeBlockAppendix = true
|
||||
state.codeBlockAppendixTitle = strings.TrimSpace(strings.TrimPrefix(line, "@AnhangCode:"))
|
||||
handled = true
|
||||
case strings.HasPrefix(line, "@Anhang:"):
|
||||
r.AddAppendix(strings.TrimSpace(strings.TrimPrefix(line, "@Anhang:")))
|
||||
handled = true
|
||||
|
||||
+2
-1
@@ -171,8 +171,9 @@ func (r *IHKRenderer) RenderAppendices() {
|
||||
case AppendixKindImage:
|
||||
r.renderAppendixImage(app.Path)
|
||||
case AppendixKindTable:
|
||||
// Render without numbering/recording; the annex header already identifies the table.
|
||||
r.renderTableBody(app.TableData, "")
|
||||
case AppendixKindCode:
|
||||
r.RenderCodeBlock(app.Lang, app.Code)
|
||||
}
|
||||
|
||||
if app.Landscape {
|
||||
|
||||
+15
-4
@@ -38,10 +38,8 @@ const (
|
||||
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
|
||||
dinLineHtList = dinLineHtBody // 1.5× IHK standard, same as body text
|
||||
dinSpaceAfterList = 3.0 // gap inserted after the outermost list exits
|
||||
)
|
||||
|
||||
// AppendixKind distinguishes between image and table annexes.
|
||||
@@ -50,6 +48,7 @@ type AppendixKind int
|
||||
const (
|
||||
AppendixKindImage AppendixKind = iota
|
||||
AppendixKindTable
|
||||
AppendixKindCode
|
||||
)
|
||||
|
||||
// Appendix holds the content for one annex entry.
|
||||
@@ -59,6 +58,8 @@ type Appendix struct {
|
||||
Title string
|
||||
Path string // image path (Kind == AppendixKindImage)
|
||||
TableData [][]string // table rows (Kind == AppendixKindTable)
|
||||
Lang string // language label (Kind == AppendixKindCode)
|
||||
Code string // source code (Kind == AppendixKindCode)
|
||||
}
|
||||
|
||||
// IHKRenderer is the central PDF generator for IHK Chemnitz project documentation.
|
||||
@@ -183,6 +184,16 @@ func (r *IHKRenderer) AddTableAppendix(title string, data [][]string) {
|
||||
})
|
||||
}
|
||||
|
||||
// AddCodeAppendix registers a source-code annex rendered with line-number gutter.
|
||||
func (r *IHKRenderer) AddCodeAppendix(title, lang, code string) {
|
||||
r.appendices = append(r.appendices, Appendix{
|
||||
Kind: AppendixKindCode,
|
||||
Title: title,
|
||||
Lang: lang,
|
||||
Code: code,
|
||||
})
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
Binary file not shown.
@@ -282,6 +282,38 @@ eine konfigurierbare Spaltenbreite für Tabellen umfassen.
|
||||
| Bildanhang | @Anhang: Titel \| Pfad | Fügt ein Bild als nummerierte Anlage in den Anhang ein |
|
||||
| Diagrammanhang | @AnhangUML: Titel | Rendert den folgenden Mermaid/PlantUML-Block als Anlage |
|
||||
|
||||
@AnhangCode: Implementierung – Tabellen-Renderer (prepareRow)
|
||||
|
||||
```go
|
||||
func (r *IHKRenderer) prepareRow(rawCells []string, numCols int,
|
||||
colW, lineHt float64, bold bool) tableRowData {
|
||||
|
||||
r.pdf.SetFont("Helvetica", map[bool]string{true: "B", false: ""}[bold], dinFontCaption)
|
||||
|
||||
cells := make([][]string, numCols)
|
||||
maxLines := 0
|
||||
for j := 0; j < numCols; j++ {
|
||||
raw := ""
|
||||
if j < len(rawCells) {
|
||||
raw = rawCells[j]
|
||||
}
|
||||
split := r.pdf.SplitLines([]byte(r.tr(raw)), colW-2)
|
||||
lines := make([]string, len(split))
|
||||
for k, b := range split {
|
||||
lines[k] = string(b)
|
||||
}
|
||||
if len(lines) == 0 {
|
||||
lines = []string{""}
|
||||
}
|
||||
cells[j] = lines
|
||||
if len(lines) > maxLines {
|
||||
maxLines = len(lines)
|
||||
}
|
||||
}
|
||||
return tableRowData{cells: cells, height: float64(maxLines) * lineHt}
|
||||
}
|
||||
```
|
||||
|
||||
@AnhangUML: Systemarchitektur – Datenflussdiagramm
|
||||
|
||||
```mermaid
|
||||
|
||||
Reference in New Issue
Block a user