sarif-explorer
Version:
A modern SARIF report viewer that converts SARIF files into interactive, shareable HTML reports with file explorer, collapsible issue lists, and code snippets.
95 lines (92 loc) • 3.4 kB
JavaScript
import fs from 'fs/promises';
/**
* Generate HTML report from SARIF data
*/
export async function generateHtmlReport(sarifData, outputPath) {
// TODO: Implement HTML generation in Phase 3
// For now, create a basic placeholder HTML
const htmlContent = generateBasicHtml(sarifData);
// Write the HTML file
await fs.writeFile(outputPath, htmlContent, 'utf8');
}
/**
* Generate basic HTML content (placeholder implementation)
*/
function generateBasicHtml(sarifData) {
const { files, fileViolations, totalViolations, statistics } = sarifData;
return `
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SARIF Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background: #f0f0f0; padding: 20px; border-radius: 5px; }
.stats { display: flex; gap: 20px; margin: 20px 0; }
.stat { background: #e0e0e0; padding: 10px; border-radius: 3px; }
.file { margin: 20px 0; border: 1px solid #ccc; border-radius: 5px; }
.file-header { background: #f5f5f5; padding: 10px; font-weight: bold; }
.violation { margin: 10px; padding: 10px; border-left: 4px solid #ff4444; }
.violation.error { border-left-color: #ff4444; }
.violation.warning { border-left-color: #ff8800; }
.violation.info { border-left-color: #0176d3; }
.code-snippet { background: #f8f8f8; padding: 10px; font-family: monospace; white-space: pre; }
</style>
</head>
<body>
<div class="header">
<h1>SARIF Report</h1>
<p>Generated by SARIF Explorer</p>
</div>
<div class="stats">
<div class="stat">Files with Issues: ${files.length}</div>
<div class="stat">Total Violations: ${totalViolations}</div>
<div class="stat">Errors: ${statistics.errorCount}</div>
<div class="stat">Warnings: ${statistics.warningCount}</div>
<div class="stat">Info: ${statistics.infoCount}</div>
</div>
${files.map(file => generateFileHtml(file, fileViolations[file])).join('')}
<script>
// TODO: Add interactive functionality in Phase 3
console.log('SARIF Report loaded');
</script>
</body>
</html>`;
}
/**
* Generate HTML for a single file
*/
function generateFileHtml(fileName, violations) {
return `
<div class="file">
<div class="file-header">${escapeHtml(fileName)} (${violations.length} violations)</div>
${violations.map(violation => generateViolationHtml(violation)).join('')}
</div>
`;
}
/**
* Generate HTML for a single violation
*/
function generateViolationHtml(violation) {
return `
<div class="violation ${violation.level}">
<div><strong>${escapeHtml(violation.ruleId)}</strong> (${violation.level})</div>
<div>${escapeHtml(violation.message)}</div>
<div>Line ${violation.line}, Column ${violation.column}</div>
${violation.snippet ? `<div class="code-snippet">${escapeHtml(violation.snippet)}</div>` : ''}
</div>
`;
}
/**
* Escape HTML to prevent XSS
*/
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
//# sourceMappingURL=html-generator.js.map