@casoon/auditmysite
Version:
Professional website analysis suite with robust accessibility testing, Core Web Vitals performance monitoring, SEO analysis, and content optimization insights. Features isolated browser contexts, retry mechanisms, and comprehensive API endpoints for profe
270 lines • 10.8 kB
JavaScript
;
/**
* 🔧 CSV Report Generator
*
* Generates CSV reports for data analysis and spreadsheet integration.
* Perfect for tracking metrics over time and business reporting.
*/
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.CSVReportGenerator = void 0;
const base_generator_1 = require("../base-generator");
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
class CSVReportGenerator extends base_generator_1.ReportGenerator {
constructor() {
super('csv');
}
getExtension() {
return 'csv';
}
getMimeType() {
return 'text/csv';
}
async generate(data, options) {
const startTime = Date.now();
// Validate data
const validation = this.validateData(data);
if (!validation.valid) {
throw new Error(`Invalid report data: ${validation.errors.join(', ')}`);
}
// Generate CSV content
const csvContent = this.generateCSV(data, options);
// Create output directory (async)
await fs.mkdir(options.outputDir, { recursive: true });
// Write file (async)
const filename = this.generateFilename(options, 'accessibility');
const filePath = path.join(options.outputDir, filename);
await fs.writeFile(filePath, csvContent, 'utf8');
const duration = Date.now() - startTime;
return {
path: filePath,
format: this.format,
size: this.calculateFileSize(csvContent),
metadata: {
generatedAt: new Date(),
duration
}
};
}
generateCSV(data, options) {
const { summary, metadata } = data;
if (options.summaryOnly || !summary.results?.length) {
return this.generateSummaryCSV(summary, metadata);
}
return this.generateDetailedCSV(summary, metadata, options);
}
generateSummaryCSV(summary, metadata) {
const successRate = this.calculateSuccessRate(summary);
const headers = [
'Report Date',
'Report Time',
'Total Pages',
'Passed Pages',
'Failed Pages',
'Crashed Pages',
'Success Rate %',
'Total Errors',
'Total Warnings',
'Average Duration (ms)',
'Total Duration (ms)'
];
const date = new Date(metadata.timestamp);
const values = [
date.toISOString().split('T')[0], // Date only
date.toISOString().split('T')[1].split('.')[0], // Time only
summary.testedPages,
summary.passedPages,
summary.failedPages,
summary.crashedPages || 0,
successRate,
summary.totalErrors,
summary.totalWarnings,
Math.round(summary.totalDuration / summary.testedPages),
summary.totalDuration
];
return [
headers.join(','),
values.map(v => this.escapeCsvValue(v)).join(',')
].join('\n');
}
generateDetailedCSV(summary, metadata, options) {
const headers = [
'URL',
'Page Title',
'Status',
'Passed',
'Crashed',
'Error Count',
'Warning Count',
'Duration (ms)',
'Timestamp',
'Page Type'
];
// Add performance headers if available
const hasPerformanceMetrics = summary.results.some((r) => r.performanceMetrics);
if (hasPerformanceMetrics) {
headers.push('LCP (ms)', 'CLS', 'FID (ms)', 'TTI (ms)');
}
// Add detailed error/warning columns if requested
if (!options.summaryOnly) {
headers.push('Errors', 'Warnings');
}
// Add pa11y columns if requested
if (options.includePa11yIssues) {
headers.push('Pa11y Issues', 'Pa11y Issue Types');
}
const rows = [headers.join(',')];
summary.results.forEach((result) => {
const pageType = this.determinePageType(result.url);
const values = [
result.url,
result.title || 'Untitled',
result.passed ? 'Passed' : (result.crashed ? 'Crashed' : 'Failed'),
result.passed ? 'TRUE' : 'FALSE',
result.crashed ? 'TRUE' : 'FALSE',
result.errors?.length || 0,
result.warnings?.length || 0,
result.duration,
result.timestamp || new Date().toISOString(),
pageType
];
// Add performance metrics if available
if (hasPerformanceMetrics) {
values.push(result.performanceMetrics?.largestContentfulPaint || '', result.performanceMetrics?.cumulativeLayoutShift || '', result.performanceMetrics?.firstInputDelay || '', result.performanceMetrics?.timeToInteractive || '');
}
// Add detailed errors/warnings
if (!options.summaryOnly) {
values.push(result.errors?.join('; ') || '', result.warnings?.join('; ') || '');
}
// Add pa11y data
if (options.includePa11yIssues) {
const pa11yIssues = result.pa11yIssues || [];
const issueMessages = pa11yIssues.map((issue) => issue.message).join('; ');
const issueTypes = [...new Set(pa11yIssues.map((issue) => issue.type))].join('; ');
values.push(issueMessages, issueTypes);
}
rows.push(values.map(v => this.escapeCsvValue(v)).join(','));
});
return rows.join('\n');
}
determinePageType(url) {
try {
const pathname = new URL(url).pathname.toLowerCase();
if (pathname === '/' || pathname === '/index' || pathname === '')
return 'Home';
if (pathname.includes('/blog') || pathname.includes('/news') || pathname.includes('/article'))
return 'Blog';
if (pathname.includes('/product') || pathname.includes('/shop') || pathname.includes('/store'))
return 'Product';
if (pathname.includes('/about') || pathname.includes('/team') || pathname.includes('/company'))
return 'About';
if (pathname.includes('/contact') || pathname.includes('/support'))
return 'Contact';
if (pathname.includes('/category') || pathname.includes('/archive'))
return 'Category';
if (pathname.includes('/search') || pathname.includes('/results'))
return 'Search';
return 'Other';
}
catch {
return 'Unknown';
}
}
escapeCsvValue(value) {
if (value === null || value === undefined) {
return '';
}
const stringValue = String(value);
// If the value contains commas, quotes, or newlines, wrap it in quotes
if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n') || stringValue.includes('\r')) {
// Escape existing quotes by doubling them
const escapedValue = stringValue.replace(/"/g, '""');
return `"${escapedValue}"`;
}
return stringValue;
}
/**
* Generate a separate CSV for issues/recommendations
*/
generateIssuesCSV(data, options) {
const { issues } = data;
if (!issues?.length) {
return 'Type,Severity,Message,Count,Affected Pages,Recommendation\n';
}
const headers = ['Type', 'Severity', 'Message', 'Count', 'Affected Pages', 'Recommendation'];
const rows = [headers.join(',')];
issues.forEach(issue => {
const values = [
issue.type || 'Unknown',
issue.severity || 'Error',
issue.message,
1, // Default count
[], // Default affected pages
issue.recommendation || ''
];
rows.push(values.map(v => this.escapeCsvValue(v)).join(','));
});
return rows.join('\n');
}
/**
* Generate a separate CSV for performance metrics
*/
generatePerformanceCSV(data) {
const { summary } = data;
if (!summary.results?.length) {
return 'URL,Page Title,Duration (ms),LCP (ms),CLS,FID (ms),TTI (ms)\n';
}
const headers = ['URL', 'Page Title', 'Duration (ms)', 'LCP (ms)', 'CLS', 'FID (ms)', 'TTI (ms)'];
const rows = [headers.join(',')];
summary.results.forEach((result) => {
if (!result.performanceMetrics)
return;
const values = [
result.url,
result.title || 'Untitled',
result.duration,
result.performanceMetrics.largestContentfulPaint || '',
result.performanceMetrics.cumulativeLayoutShift || '',
result.performanceMetrics.firstInputDelay || '',
result.performanceMetrics.timeToInteractive || ''
];
rows.push(values.map(v => this.escapeCsvValue(v)).join(','));
});
return rows.join('\n');
}
}
exports.CSVReportGenerator = CSVReportGenerator;
//# sourceMappingURL=csv-generator.js.map