diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 47a9c21..b34a452 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,20 +4,12 @@
-
-
-
-
-
-
-
-
-
+
+
-
+
-
@@ -101,7 +93,9 @@
-
+
+
+
diff --git a/MarkdownToIHKChemnits b/MarkdownToIHKChemnits
index fd1f740..a097859 100755
Binary files a/MarkdownToIHKChemnits and b/MarkdownToIHKChemnits differ
diff --git a/markdown_parser.go b/markdown_parser.go
index 100b734..f20ac04 100644
--- a/markdown_parser.go
+++ b/markdown_parser.go
@@ -119,8 +119,8 @@ func RenderAST(doc ast.Node, content []byte, r *IHKRenderer) error {
}
// Fall through: render as plain code block on error
}
- // Render non-diagram code blocks as monospace paragraphs
- r.RenderParagraphSpans([]InlineSpan{{Text: code, Code: true}})
+ // Render as a numbered code block (gutter + monospace body).
+ r.RenderCodeBlock(lang, code)
return ast.WalkSkipChildren, nil
// ── Images ────────────────────────────────────────────────────────────
diff --git a/pdf_content.go b/pdf_content.go
index 96c075f..9e07bc4 100644
--- a/pdf_content.go
+++ b/pdf_content.go
@@ -3,6 +3,7 @@ package main
import (
"fmt"
"strconv"
+ "strings"
"github.com/go-pdf/fpdf"
)
@@ -89,13 +90,28 @@ func (r *IHKRenderer) RenderListItem(spans []InlineSpan, ordered bool, index, in
r.pdf.SetFont("Helvetica", "", dinFontBody)
lm, _, _, _ := r.pdf.GetMargins()
- indentMM := float64(indent+1) * 8.0
- r.pdf.SetX(lm + indentMM)
+
+ // 3 mm base indent + 5 mm per nesting level (reduced from previous 8 mm per level)
+ indentMM := 3.0 + float64(indent)*5.0
prefix := "• "
if ordered {
prefix = strconv.Itoa(index) + ". "
}
+ prefixW := r.pdf.GetStringWidth(prefix) + 1.0
+
+ // textX is where the item text starts; wrapped lines must align here too.
+ textX := lm + indentMM + prefixW
+ textW := r.usableWidth() - indentMM - prefixW
+
+ // Temporarily move the left margin to textX so that MultiCell wraps
+ // continuation lines flush with the text, not back to the page margin.
+ r.pdf.SetLeftMargin(textX)
+ defer r.pdf.SetLeftMargin(lm)
+
+ // Render bullet/number; CellFormat advances X to textX automatically.
+ r.pdf.SetX(lm + indentMM)
+ r.pdf.CellFormat(prefixW, dinLineHtBody, r.tr(prefix), "", 0, "L", false, 0, "")
hasFormatting := false
for _, s := range spans {
@@ -105,15 +121,13 @@ func (r *IHKRenderer) RenderListItem(spans []InlineSpan, ordered bool, index, in
}
}
- uw := r.usableWidth() - indentMM
if !hasFormatting {
- text := prefix
+ text := ""
for _, s := range spans {
text += s.Text
}
- r.pdf.MultiCell(uw, dinLineHtBody, r.tr(text), "", "L", false)
+ r.pdf.MultiCell(textW, dinLineHtBody, r.tr(text), "", "L", false)
} else {
- r.pdf.Write(dinLineHtBody, r.tr(prefix))
for _, span := range spans {
style := fontStyle(span.Bold, span.Italic)
if span.Code {
@@ -254,6 +268,72 @@ func (r *IHKRenderer) RenderImage(path string, caption string) {
r.pdf.Ln(dinSpaceAfterParagraph)
}
+// Code block layout constants.
+const (
+ codeFont = 9.0 // pt — Courier, smaller than body text
+ codeLineHt = 4.5 // mm ≈ 9 pt × 1.3 line spacing
+ codeGutterW = 11.0 // mm — column reserved for line numbers
+)
+
+// RenderCodeBlock renders a fenced code block with a line-number gutter.
+//
+// Layout:
+//
+// ┌──────┬──────────────────────────────────┐
+// │ 1 │ package main │
+// │ 2 │ │
+// │ 3 │ func main() { … } │
+// └──────┴──────────────────────────────────┘
+//
+// The language label is shown in small italic text above the block.
+// Lines that exceed the printable width are clipped — code should be
+// formatted to reasonable lengths before conversion.
+func (r *IHKRenderer) RenderCodeBlock(lang, code string) {
+ lines := strings.Split(strings.TrimRight(code, "\n"), "\n")
+ if len(lines) == 0 {
+ return
+ }
+
+ r.pdf.Ln(dinSpaceAfterParagraph)
+
+ // Language label — top-right, italic, grey
+ if lang != "" {
+ r.pdf.SetFont("Helvetica", "I", dinFontCaption)
+ r.pdf.SetTextColor(100, 100, 100)
+ r.pdf.CellFormat(0, dinLineHtCaption, r.tr(lang), "", 1, "R", false, 0, "")
+ r.pdf.SetTextColor(0, 0, 0)
+ }
+
+ lm, _, _, bm := r.pdf.GetMargins()
+ _, pageH := r.pdf.GetPageSize()
+ uw := r.usableWidth()
+ codeW := uw - codeGutterW
+
+ r.pdf.SetFont("Courier", "", codeFont)
+
+ for i, line := range lines {
+ // Start a new page if this line would fall below the bottom margin.
+ if r.pdf.GetY()+codeLineHt > pageH-bm {
+ r.pdf.AddPage()
+ }
+
+ // Gutter: darker grey, right-aligned line number.
+ r.pdf.SetFillColor(218, 218, 218)
+ r.pdf.SetX(lm)
+ r.pdf.CellFormat(codeGutterW, codeLineHt,
+ fmt.Sprintf("%4d ", i+1), "", 0, "R", true, 0, "")
+
+ // Code line: lighter grey, left-aligned, small leading space.
+ r.pdf.SetFillColor(246, 246, 246)
+ r.pdf.CellFormat(codeW, codeLineHt,
+ r.tr(" "+line), "", 1, "L", true, 0, "")
+ }
+
+ // Reset colours so subsequent content is unaffected.
+ r.pdf.SetFillColor(255, 255, 255)
+ r.pdf.Ln(dinSpaceAfterParagraph)
+}
+
// fontStyle returns the fpdf font style string for a given bold/italic combination.
func fontStyle(bold, italic bool) string {
switch {
diff --git a/projektarbeit.pdf b/projektarbeit.pdf
index 9260162..ab0bdae 100644
Binary files a/projektarbeit.pdf and b/projektarbeit.pdf differ
diff --git a/report.md b/report.md
index 4876bb7..e6290ad 100644
--- a/report.md
+++ b/report.md
@@ -48,7 +48,7 @@ manuelle Sorgfalt bei jedem Absatz.
Ziel ist ein Go-Tool, das **Markdown** in PDF umwandelt und dabei alle
formalen Anforderungen der IHK Chemnitz erfüllt. Es soll:
-- die Prüfungsvorbereitung erleichtern,
+- die Prüfungsvorbereitung erleichtern, die Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen und
- die Qualität der Dokumente *einheitlich* sicherstellen und
- den Prozess vollständig automatisieren.