UNPKG

@dawans/promptshield

Version:

Secure your LLM stack with enterprise-grade RulePacks for AI safety scanning

121 lines (120 loc) 4.93 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MarkdownRenderer = void 0; const Result_1 = require("../../../../shared/types/Result"); const Violation_1 = require("../../../../shared/types/Violation"); const ScanMetrics_1 = require("../../../../shared/types/ScanMetrics"); /** * Markdown format renderer */ class MarkdownRenderer { /** * Renders a report to Markdown format */ async render(report) { try { const violations = report.getFilteredViolations(); const summary = Violation_1.ViolationUtils.createSummary(violations); const metrics = report.scanResult.metrics; let output = ''; // Header output += '# PromptShield Scan Report\n\n'; // Summary output += '## Summary\n\n'; output += `**Total Violations:** ${summary.total}\n\n`; if (summary.total > 0) { // Severity breakdown output += '### By Severity\n\n'; for (const [severity, count] of Object.entries(summary.bySeverity)) { const emoji = this.getSeverityEmoji(severity); output += `${emoji} **${severity}:** ${count}\n`; } output += '\n'; // Category breakdown if (Object.keys(summary.byCategory).length > 0) { output += '### By Category\n\n'; for (const [category, count] of Object.entries(summary.byCategory)) { output += `- **${category}:** ${count}\n`; } output += '\n'; } } // Metrics if (report.shouldIncludeMetrics()) { output += '## Metrics\n\n'; output += `- **Objects Scanned:** ${metrics.objectsScanned}\n`; output += `- **Processing Time:** ${ScanMetrics_1.ScanMetricsUtils.formatProcessingTime(metrics.processingTime)}\n`; output += `- **Memory Usage:** ${ScanMetrics_1.ScanMetricsUtils.formatMemoryUsage(metrics.memoryUsage)}\n`; output += `- **Rules Applied:** ${metrics.rulesApplied}\n`; output += `- **Processing Rate:** ${ScanMetrics_1.ScanMetricsUtils.calculateProcessingRate(metrics).toFixed(2)} objects/sec\n`; if (metrics.streamingUsed) { output += `- **Streaming:** Used\n`; } output += '\n'; } // Violations if (violations.length > 0) { output += '## Violations\n\n'; for (const violation of violations) { const emoji = this.getSeverityEmoji(violation.severity); output += `### ${emoji} ${violation.ruleId}\n\n`; output += `**Description:** ${violation.ruleDescription}\n\n`; output += `**Severity:** ${violation.severity}\n\n`; output += `**Category:** ${violation.category}\n\n`; output += `**Message:** ${violation.message}\n\n`; if (violation.field) { output += `**Field:** ${violation.field}\n\n`; } if (violation.context) { output += `**Context:**\n\`\`\`\n${violation.context.match}\n\`\`\`\n\n`; } if (violation.position) { output += `**Position:** ${violation.position.start}-${violation.position.end}\n\n`; } output += '---\n\n'; } } else { output += '## No Violations Found\n\n'; output += '✅ No safety violations detected in the scanned content.\n\n'; } // Footer output += `*Generated at ${new Date().toISOString()} by PromptShield v1.0.0*\n`; return (0, Result_1.ok)(output); } catch (error) { return (0, Result_1.err)(new Error(`Failed to render Markdown report: ${error}`)); } } /** * Gets the output format this renderer handles */ getFormat() { return 'markdown'; } /** * Checks if this renderer supports streaming */ supportsStreaming() { return false; } /** * Gets emoji for severity level */ getSeverityEmoji(severity) { switch (severity.toLowerCase()) { case 'critical': return '🔴'; case 'high': return '🟠'; case 'medium': return '🟡'; case 'low': return '🟢'; default: return '⚪'; } } } exports.MarkdownRenderer = MarkdownRenderer;