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:
+24
-3
@@ -348,6 +348,24 @@ function generatePdfDocument(settings, applications, month, year) {
|
|||||||
return new Date(lv ? lv.datum : app.datum);
|
return new Date(lv ? lv.datum : app.datum);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Imported/scraped values can contain HTML entities (e.g. "GmbH & 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(/"/g, '"')
|
||||||
|
.replace(/'/g, "'")
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/ /g, ' ')
|
||||||
|
.replace(/&/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,
|
// 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".
|
// derive it from the data so the title still reads e.g. "Juni 2026".
|
||||||
const yearsInData = [...new Set(
|
const yearsInData = [...new Set(
|
||||||
@@ -599,11 +617,14 @@ function generatePdfDocument(settings, applications, month, year) {
|
|||||||
head: [['Datum', 'Firma', 'Stelle', 'Art', 'Status']],
|
head: [['Datum', 'Firma', 'Stelle', 'Art', 'Status']],
|
||||||
body: tableRows.map(({ app, date, status }) => ([
|
body: tableRows.map(({ app, date, status }) => ([
|
||||||
isNaN(date) ? '—' : date.toLocaleDateString('de-DE'),
|
isNaN(date) ? '—' : date.toLocaleDateString('de-DE'),
|
||||||
app.firma || '—',
|
cell(app.firma),
|
||||||
app.stelle || '—',
|
cell(app.stelle),
|
||||||
app.art || '—',
|
cell(app.art),
|
||||||
status
|
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: {
|
styles: {
|
||||||
font: 'helvetica', fontSize: 9, cellPadding: 2.4,
|
font: 'helvetica', fontSize: 9, cellPadding: 2.4,
|
||||||
textColor: [31, 41, 55], lineColor: [226, 232, 240],
|
textColor: [31, 41, 55], lineColor: [226, 232, 240],
|
||||||
|
|||||||
Reference in New Issue
Block a user