From 87d71c1dcab47dff0d40c903ad4603f93e592f00 Mon Sep 17 00:00:00 2001 From: amertensreplit <49614208-amertensreplit@users.noreply.replit.com> Date: Wed, 10 Jun 2026 13:57:05 +0000 Subject: [PATCH] =?UTF-8?q?Bericht=20zus=C3=A4tzlich=20als=20PDF=20exporti?= =?UTF-8?q?eren?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a "Als PDF exportieren" button to the scan report page next to the existing JSON export, fulfilling Task #3. Implementation: - artifacts/skillguard/src/pages/scan-report.tsx - New primary button "Als PDF exportieren" (FileDown icon) grouped with the existing JSON export button in the report header. - handleExportPdf opens a new window, writes a self-contained print- friendly HTML document, and triggers window.print() (browser "Als PDF speichern"). No new dependencies added. - buildReportHtml(data) generates the document containing: title + verdict, metadata (date, source, file count, KI flag), optional AI warning, Risiko-Score with summary text, Achsen-Zusammenfassung table (severity + axis counts incl. total), all findings (severity/axis/ rule/detection, location, description, snippet, remediation), and the checked files table. - All labels are German via VERDICT/SEVERITY/AXIS/SOURCE/KIND label maps; no emojis used; print-friendly inline CSS with page-break-inside avoid on findings. - User-provided content is escaped via escapeHtml to prevent HTML injection in the generated document. Verification: - pnpm --filter @workspace/skillguard typecheck passes. - Created test scan (id 8) via API, confirmed button renders and German label mapping is correct for verdict/severity/axis. Deviations: none. Chose the browser print-to-PDF approach (zero new deps) over a client-side PDF library, which keeps the bundle lean and produces selectable, print-friendly output. Replit-Task-Id: e3f37193-89fd-42de-8cec-9383c8406b25 --- artifacts/skillguard/public/opengraph.jpg | Bin 44486 -> 18404 bytes .../skillguard/src/pages/scan-report.tsx | 218 +++++++++++++++++- 2 files changed, 213 insertions(+), 5 deletions(-) diff --git a/artifacts/skillguard/public/opengraph.jpg b/artifacts/skillguard/public/opengraph.jpg index 2828bf9a921ee6370ff0599b924e960ea0d456bb..01f64318e68c4cd056074cd36b12413a8766b4f3 100644 GIT binary patch literal 18404 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 literal 44486 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 z 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 { + const html = buildReportHtml(data); + const printWindow = window.open("", "_blank"); + if (!printWindow) return; + printWindow.document.open(); + printWindow.document.write(html); + printWindow.document.close(); + printWindow.focus(); + printWindow.onload = () => { + printWindow.print(); + }; + }; + return (
@@ -100,10 +114,16 @@ export default function ScanReport() { )}
- +
+ + +
{data.aiError && ( @@ -337,3 +357,191 @@ export default function ScanReport() { ); } + +const VERDICT_LABELS: Record = { + pass: "Freigabe", + review: "Manuelle Prüfung", + block: "Blockieren", +}; + +const SEVERITY_LABELS: Record = { + critical: "Kritisch", + high: "Hoch", + medium: "Mittel", + low: "Niedrig", + info: "Info", +}; + +const AXIS_LABELS: Record = { + security: "IT-Sicherheit", + privacy: "Datenschutz", +}; + +const SOURCE_LABELS: Record = { + upload: "Upload", + url: "URL", + paste: "Einfügung", +}; + +const KIND_LABELS: Record = { + instruction: "Anweisung", + script: "Skript", + resource: "Ressource", +}; + +function escapeHtml(value: unknown): string { + return String(value ?? "") + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +function riskSummary(score: number): string { + if (score < 30) return "Geringes Risiko. Keine bedenklichen Muster gefunden."; + if (score < 70) return "Mittleres Risiko. Einige Auffälligkeiten erfordern Prüfung."; + return "Hohes Risiko. Kritische Sicherheitsprobleme erkannt."; +} + +function buildReportHtml(data: ScanDetail): string { + const title = data.name || `Scan #${data.id}`; + const verdict = VERDICT_LABELS[data.verdict] ?? data.verdict; + const source = SOURCE_LABELS[data.source] ?? data.source; + const counts = data.findingCounts; + + const findingsHtml = data.findings.length === 0 + ? `

Keine Auffälligkeiten gefunden. Der analysierte Skill entspricht den Sicherheits- und Datenschutzrichtlinien.

` + : data.findings.map((f, i) => { + const location = (f.file || f.line) + ? `
Fundstelle: ${escapeHtml(f.file || "unbekannt")}${f.line ? `:${escapeHtml(f.line)}` : ""}
` + : ""; + const snippet = f.snippet + ? `
${escapeHtml(f.snippet)}
` + : ""; + const remediation = f.remediation + ? `
Empfehlung: ${escapeHtml(f.remediation)}
` + : ""; + return ` +
+
+ ${i + 1}. + ${escapeHtml(f.title)} +
+
+ Schweregrad: ${escapeHtml(SEVERITY_LABELS[f.severity] ?? f.severity)} + Bereich: ${escapeHtml(AXIS_LABELS[f.axis] ?? f.axis)} + Regel: ${escapeHtml(f.ruleId)} + Erkennung: ${f.detectedBy === "ai" ? "KI" : "Statisch"} +
+ ${location} +

${escapeHtml(f.description)}

+ ${snippet} + ${remediation} +
`; + }).join(""); + + const aiWarning = data.aiError + ? `
KI-Analyse nicht durchgeführt: ${escapeHtml(data.aiError)}. Die statische Analyse wurde dennoch abgeschlossen.
` + : ""; + + return ` + + + +SkillGuard Bericht - ${escapeHtml(title)} + + + +

SkillGuard Sicherheitsbericht

+

+ ${escapeHtml(title)}  |  ${escapeHtml(verdict)}
+ Erstellt am ${escapeHtml(formatDate(data.createdAt))}  |  Quelle: ${escapeHtml(source)}  |  ${escapeHtml(data.fileCount)} ${data.fileCount === 1 ? "Datei" : "Dateien"}${data.aiUsed ? "  |  KI-Analyse aktiv" : ""} +

+ + ${aiWarning} + +

Risiko-Score

+
+
+
${escapeHtml(data.riskScore)}
+
/ 100
+
+
${riskSummary(data.riskScore)}
+
+ +

Achsen-Zusammenfassung

+ + + + + + + + + + + + + + +
KennzahlAnzahl
Kritisch${escapeHtml(counts.critical)}
Hoch${escapeHtml(counts.high)}
Mittel${escapeHtml(counts.medium)}
Niedrig${escapeHtml(counts.low)}
Info${escapeHtml(counts.info)}
IT-Sicherheit${escapeHtml(counts.security)}
Datenschutz${escapeHtml(counts.privacy)}
Gesamt${escapeHtml(counts.total)}
+ +

Auffälligkeiten (${data.findings.length})

+ ${findingsHtml} + +

Geprüfte Dateien (${data.files.length})

+ + + + + + ${data.files.length === 0 + ? `` + : data.files.map(file => ` + + + + + + `).join("")} + +
PfadTypSpracheGröße
Keine Dateien verfügbar.
${escapeHtml(file.path)}${escapeHtml(KIND_LABELS[file.kind] ?? file.kind)}${escapeHtml(file.language || "-")}${escapeHtml(file.size)} B
+ + + +`; +}