"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.MarkdownExporter = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); class MarkdownExporter { async export(finding, outputDir) { fs.mkdirSync(outputDir, { recursive: true }); const date = finding.createdAt.toISOString().split('T')[0]; const seed = finding.actionTrace[0]?.seed ?? 'N/A'; const replayCmd = `npm run replay -- --report ${outputDir}/report.json`; const steps = finding.actionTrace .map((action, i) => { switch (action.type) { case 'navigate': return `${i + 1}. Navigate to \`${action.url}\``; case 'click': return `${i + 1}. Click element \`${action.selector}\``; case 'fill': return `${i + 1}. Fill \`${action.selector}\` with \`${JSON.stringify(action.value ?? '')}\``; case 'select': return `${i + 1}. Select \`${action.value}\` in \`${action.selector}\``; case 'submit': return `${i + 1}. Submit form \`${action.selector}\``; default: return `${i + 1}. ${action.type}`; } }) .join('\n'); const httpTable = finding.evidence.httpLog.length > 0 ? [ '| Method | URL | Status | Duration |', '|--------|-----|--------|----------|', ...finding.evidence.httpLog.map((r) => `| ${r.method} | ${r.url} | ${r.status} | ${r.durationMs}ms |`), ].join('\n') : '_No HTTP log available._'; const rawErrors = finding.evidence.rawErrors.length > 0 ? '```\n' + finding.evidence.rawErrors.join('\n') + '\n```' : '_No raw errors recorded._'; const md = `# Bug Report — ${finding.type.value} — ${date} ## Summary ${finding.description} ## Severity **${finding.severity.value}** — detected by ABE heuristic rule \`${finding.type.value}\` ## Status **${finding.status.value}** ## Reproduction Steps ${steps.length > 0 ? steps : '_No steps recorded._'} **Seed used**: \`${seed}\` **Replay command**: \`${replayCmd}\` ## Observed Behavior ${finding.description} ## Evidence - Screenshot: \`${finding.evidence.screenshotPath ?? 'N/A'}\` - DOM Snapshot: \`${finding.evidence.domSnapshotPath ?? 'N/A'}\` - HTTP Log: ${httpTable} ## Raw Errors ${rawErrors} `; const filePath = path.join(outputDir, 'report.md'); fs.writeFileSync(filePath, md, 'utf8'); return filePath; } } exports.MarkdownExporter = MarkdownExporter;