PDF-Export: keine zerrissenen Zeilen mehr + HTML-Entities dekodieren

rowPageBreak 'avoid' verhindert das Splitten einer Zeile am Seitenumbruch,
das bisher Datum/Art/Status auf der Folgeseite leer liess. Firma/Stelle/Art
werden HTML-dekodiert (z.B. "&" -> "&"), leere Werte zeigen "—".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 14:20:27 +02:00
co-authored by Claude Opus 4.8
parent 78b1ea78d0
commit d1c6743d2f
+24 -3
View File
@@ -348,6 +348,24 @@ function generatePdfDocument(settings, applications, month, year) {
return new Date(lv ? lv.datum : app.datum);
};
// Imported/scraped values can contain HTML entities (e.g. "GmbH &amp; Co. KG")
// and sanitizeInput() stores "< > \" '" escaped — decode them so the PDF shows
// real characters instead of the raw entity text.
const decodeEntities = (str) => {
if (str == null) return '';
return String(str)
.replace(/&#(\d+);/g, (_, n) => String.fromCharCode(parseInt(n, 10)))
.replace(/&#x([0-9a-fA-F]+);/g, (_, n) => String.fromCharCode(parseInt(n, 16)))
.replace(/&quot;/g, '"')
.replace(/&apos;/g, "'")
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&');
};
// Cleaned cell text with an em-dash fallback for missing/empty values.
const cell = (v) => decodeEntities(v).trim() || '—';
// Determine the year shown in the title. When no year was picked in the form,
// derive it from the data so the title still reads e.g. "Juni 2026".
const yearsInData = [...new Set(
@@ -599,11 +617,14 @@ function generatePdfDocument(settings, applications, month, year) {
head: [['Datum', 'Firma', 'Stelle', 'Art', 'Status']],
body: tableRows.map(({ app, date, status }) => ([
isNaN(date) ? '—' : date.toLocaleDateString('de-DE'),
app.firma || '—',
app.stelle || '—',
app.art || '—',
cell(app.firma),
cell(app.stelle),
cell(app.art),
status
])),
// Never split a row across a page boundary — a split row leaves the
// single-line cells (Datum, Art, Status) blank on the continuation page.
rowPageBreak: 'avoid',
styles: {
font: 'helvetica', fontSize: 9, cellPadding: 2.4,
textColor: [31, 41, 55], lineColor: [226, 232, 240],