diff --git a/packages/core-service/src/core/expert-profile/profile-export.service.ts b/packages/core-service/src/core/expert-profile/profile-export.service.ts index 6ce362c..9a8162b 100644 --- a/packages/core-service/src/core/expert-profile/profile-export.service.ts +++ b/packages/core-service/src/core/expert-profile/profile-export.service.ts @@ -528,10 +528,9 @@ export class ProfileExportService { yRight += doc.heightOfString(companyLine, { width: contentWidth }) + 2; } - // Aufgaben (Bullet nur wenn Original-Zeile ein Aufzählungszeichen hat) + // Aufgaben: Bold für **...**-Zeilen, Bullet nur wenn Original-Zeile ein Aufzählungszeichen hat if (proj.tasks) { const taskLines = proj.tasks.split('\n').filter((l: string) => l.trim()); - doc.font('Helvetica').fontSize(8).fillColor('#444444'); for (const task of taskLines) { if (yRight > pageBottom) { doc.addPage(); @@ -539,12 +538,21 @@ export class ProfileExportService { pageBreakOccurred = true; } const raw = task.trim(); + const isBold = /^\*\*/.test(raw); const hasBullet = /^[•\u2022]\s/.test(raw) || /^\d+\.\s/.test(raw); - const cleaned = this.normalizeTaskLine(raw); + const cleaned = this.normalizeTaskLine(raw).replace(/\t/g, ' '); if (!cleaned) continue; - const displayText = `\u2022 ${this.sanitizePdfText(hasBullet ? cleaned : cleaned)}`; - doc.text(displayText, contentX + 4, yRight, { width: contentWidth - 8 }); - yRight += doc.heightOfString(displayText, { width: contentWidth - 8 }) + 1; + const sanitized = this.sanitizePdfText(cleaned); + if (isBold) { + doc.font('Helvetica-Bold').fontSize(8).fillColor('#333333'); + doc.text(sanitized, contentX + 4, yRight, { width: contentWidth - 8 }); + yRight += doc.heightOfString(sanitized, { width: contentWidth - 8 }) + 1; + } else { + const displayText = hasBullet ? `\u2022 ${sanitized}` : sanitized; + doc.font('Helvetica').fontSize(8).fillColor('#444444'); + doc.text(displayText, contentX + 4, yRight, { width: contentWidth - 8 }); + yRight += doc.heightOfString(displayText, { width: contentWidth - 8 }) + 1; + } } } @@ -609,7 +617,8 @@ export class ProfileExportService { for (const att of pdfAttachments) { try { const attBuffer = this.base64ToBuffer(att.data); - const attPdf = await PdfLib.load(attBuffer); + // ignoreEncryption: true erlaubt das Einbetten von PDFs mit Owner-Password-Schutz + const attPdf = await PdfLib.load(attBuffer, { ignoreEncryption: true }); const pageIndices = attPdf.getPageIndices(); const copiedPages = await merged.copyPages(attPdf, pageIndices); for (const page of copiedPages) { @@ -894,15 +903,15 @@ export class ProfileExportService { const taskLines = proj.tasks.split('\n').filter((l: string) => l.trim()); for (const task of taskLines) { const raw = task.trim(); + const isBold = /^\*\*/.test(raw); const hasBullet = /^[•\u2022]\s/.test(raw) || /^\d+\.\s/.test(raw); - const cleaned = this.normalizeTaskLine(raw); + const cleaned = this.normalizeTaskLine(raw).replace(/\t/g, ' '); if (!cleaned) continue; - const displayText = hasBullet ? `\u2022 ${cleaned}` : cleaned; rightParagraphs.push( new Paragraph({ - children: [ - new TextRun({ text: displayText, size: 16, color: '444444' }), - ], + children: isBold + ? [new TextRun({ text: cleaned, size: 16, color: '333333', bold: true })] + : [new TextRun({ text: hasBullet ? `\u2022 ${cleaned}` : cleaned, size: 16, color: '444444' })], spacing: { after: 20 }, }), );