a11yanalyze
Version:
A command-line tool for developers and QA engineers to test web pages and websites for WCAG 2.2 AA accessibility compliance
844 lines ⢠35.3 kB
JavaScript
;
/**
* Console Reporter for Accessibility Analysis
* Provides human-readable console output with progress indicators
*/
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;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConsoleReporter = void 0;
const chalk_1 = __importDefault(require("chalk"));
const cliProgress = __importStar(require("cli-progress"));
const figures_1 = __importDefault(require("figures"));
const ora_1 = __importDefault(require("ora"));
/**
* Comprehensive console reporter for accessibility analysis
*/
class ConsoleReporter {
constructor(config = {}) {
this.config = {
colors: true,
verbose: false,
debug: false,
quiet: false,
showProgress: true,
maxWidth: 80,
showSpinner: true,
...config,
};
this.progressBars = new Map();
this.spinners = new Map();
this.startTime = new Date();
this.progressState = {
phase: 'initializing',
currentStep: 0,
totalSteps: 0,
overallProgress: 0,
currentOperation: 'Initializing...',
phaseStartTime: new Date(),
};
// Configure chalk for color support
if (!this.config.colors) {
chalk_1.default.level = 0;
}
}
/**
* Initialize the console reporter
*/
init() {
if (this.config.quiet)
return;
this.showHeader();
this.initializeMultiBar();
}
/**
* Show application header
*/
showHeader() {
if (this.config.quiet)
return;
const title = 'A11Y Analyze - Accessibility Testing Tool';
const subtitle = 'Comprehensive WCAG 2.2 Compliance Analysis';
const separator = '='.repeat(Math.min(title.length, this.config.maxWidth));
console.log(chalk_1.default.bold.blue('\n' + separator));
console.log(chalk_1.default.bold.blue(title));
console.log(chalk_1.default.gray(subtitle));
console.log(chalk_1.default.blue(separator + '\n'));
}
/**
* Initialize multi-progress bar system
*/
initializeMultiBar() {
if (!this.config.showProgress || this.config.quiet)
return;
this.multiBar = new cliProgress.MultiBar({
clearOnComplete: false,
hideCursor: true,
format: ' {bar} | {phase} | {percentage}% | {current}/{total} | {operation}',
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
});
}
/**
* Update current phase and operation
*/
updatePhase(phase, operation, totalSteps) {
this.progressState.phase = phase;
this.progressState.currentOperation = operation;
this.progressState.currentStep = 0;
this.progressState.phaseStartTime = new Date();
if (totalSteps !== undefined) {
this.progressState.totalSteps = totalSteps;
}
if (!this.config.quiet) {
this.showPhaseHeader(phase, operation);
}
}
/**
* Show phase header with status
*/
showPhaseHeader(phase, operation) {
const phaseIcons = {
initializing: figures_1.default.play,
crawling: figures_1.default.arrowRight,
scanning: figures_1.default.pointer,
analyzing: figures_1.default.hamburger,
reporting: figures_1.default.tick,
complete: figures_1.default.checkboxOn,
};
const phaseColors = {
initializing: chalk_1.default.blue,
crawling: chalk_1.default.yellow,
scanning: chalk_1.default.magenta,
analyzing: chalk_1.default.cyan,
reporting: chalk_1.default.green,
complete: chalk_1.default.green.bold,
};
const icon = phaseIcons[phase] || figures_1.default.bullet;
const colorFn = phaseColors[phase] || chalk_1.default.white;
const phaseText = phase.charAt(0).toUpperCase() + phase.slice(1);
console.log(colorFn(`\n${icon} ${phaseText}: ${operation}`));
}
/**
* Create or update a progress bar
*/
createProgressBar(id, label, total) {
if (!this.config.showProgress || this.config.quiet)
return;
if (this.multiBar) {
const bar = this.multiBar.create(total, 0, {
phase: label,
operation: 'Starting...',
});
this.progressBars.set(id, bar);
}
}
/**
* Update progress bar
*/
updateProgress(id, current, operation) {
if (!this.config.showProgress || this.config.quiet)
return;
const bar = this.progressBars.get(id);
if (bar) {
bar.update(current, { operation: operation || 'Processing...' });
}
}
/**
* Complete a progress bar
*/
completeProgress(id, finalMessage) {
if (!this.config.showProgress || this.config.quiet)
return;
const bar = this.progressBars.get(id);
if (bar) {
bar.update(bar.getTotal(), { operation: finalMessage || 'Complete' });
}
}
/**
* Create a spinner for indefinite operations
*/
createSpinner(id, text) {
if (!this.config.showSpinner || this.config.quiet)
return;
const spinner = (0, ora_1.default)({
text,
color: 'blue',
spinner: 'dots',
}).start();
this.spinners.set(id, spinner);
}
/**
* Update spinner text
*/
updateSpinner(id, text) {
const spinner = this.spinners.get(id);
if (spinner) {
spinner.text = text;
}
}
/**
* Complete spinner with success
*/
succeedSpinner(id, text) {
const spinner = this.spinners.get(id);
if (spinner) {
spinner.succeed(text);
this.spinners.delete(id);
}
}
/**
* Complete spinner with failure
*/
failSpinner(id, text) {
const spinner = this.spinners.get(id);
if (spinner) {
spinner.fail(text);
this.spinners.delete(id);
}
}
/**
* Log crawling progress
*/
logCrawlProgress(session) {
if (this.config.quiet)
return;
const stats = session.stats;
const elapsed = Date.now() - session.startTime.getTime();
const elapsedSeconds = Math.floor(elapsed / 1000);
if (this.config.verbose) {
console.log(chalk_1.default.gray(` URLs: ${stats.urlCounts.completed}/${stats.urlCounts.total} | ` +
`Pages: ${stats.pagesScanned} | ` +
`Time: ${this.formatDuration(elapsedSeconds)} | ` +
`Rate: ${stats.performance.pagesPerMinute.toFixed(1)} pages/min`));
}
}
/**
* Log scanning progress for a page
*/
logPageScanStart(url, pageNumber, totalPages) {
if (this.config.quiet)
return;
if (this.config.verbose) {
console.log(chalk_1.default.gray(` [${pageNumber}/${totalPages}] Scanning: ${url}`));
}
}
/**
* Log scanning completion for a page
*/
logPageScanComplete(url, scanResult) {
if (this.config.quiet)
return;
const scoreColor = this.getScoreColor(scanResult.score);
const issueCount = scanResult.issues.length;
const criticalIssues = scanResult.issues.filter(i => i.severity === 'critical').length;
let status = `${scoreColor(scanResult.score.toFixed(1))}`;
if (issueCount > 0) {
status += ` (${issueCount} issues`;
if (criticalIssues > 0) {
status += `, ${chalk_1.default.red(criticalIssues + ' critical')}`;
}
status += ')';
}
if (this.config.verbose) {
console.log(chalk_1.default.gray(` ā Score: ${status}`));
}
}
/**
* Display page scan results summary
*/
showPageResults(scanResult, scoreBreakdown) {
if (this.config.quiet)
return;
const url = scanResult.url;
const score = scanResult.score;
const issues = scanResult.issues;
console.log(chalk_1.default.bold(`\nš Page Results: ${url}`));
console.log('ā'.repeat(Math.min(url.length + 15, this.config.maxWidth)));
// Score display
const scoreColor = this.getScoreColor(score);
console.log(`${chalk_1.default.bold('Score:')} ${scoreColor(score.toFixed(1))}/100`);
// Score breakdown if available
if (scoreBreakdown && this.config.verbose) {
this.showScoreBreakdown(scoreBreakdown);
}
// Issues summary
if (issues.length > 0) {
this.showIssuesSummary(issues);
}
else {
console.log(chalk_1.default.green(`${figures_1.default.tick} No accessibility issues found!`));
}
// Performance metrics
if (scanResult.metadata) {
this.showPerformanceMetrics(scanResult.metadata);
}
}
/**
* Display detailed score breakdown
*/
showScoreBreakdown(breakdown) {
console.log(chalk_1.default.bold('\nš Score Breakdown:'));
console.log(` Base Score: ${breakdown.baseScore}`);
if (breakdown.issueDeductions.length > 0) {
const totalDeductions = breakdown.issueDeductions.reduce((sum, d) => sum + d.pointsDeducted, 0);
console.log(` Issue Deductions: ${chalk_1.default.red('-' + totalDeductions.toFixed(1))}`);
}
if (breakdown.bonuses.length > 0) {
const totalBonuses = breakdown.bonuses.reduce((sum, b) => sum + b.points, 0);
console.log(` Bonuses: ${chalk_1.default.green('+' + totalBonuses.toFixed(1))}`);
if (this.config.verbose) {
breakdown.bonuses.forEach(bonus => {
console.log(chalk_1.default.gray(` ⢠${bonus.description}: +${bonus.points}`));
});
}
}
if (breakdown.penalties.length > 0) {
const totalPenalties = breakdown.penalties.reduce((sum, p) => sum + p.points, 0);
console.log(` Penalties: ${chalk_1.default.red('-' + totalPenalties.toFixed(1))}`);
if (this.config.verbose) {
breakdown.penalties.forEach(penalty => {
console.log(chalk_1.default.gray(` ⢠${penalty.description}: -${penalty.points}`));
});
}
}
console.log(` ${chalk_1.default.bold('Final Score:')} ${this.getScoreColor(breakdown.finalScore)(breakdown.finalScore.toFixed(1))}`);
}
/**
* Display issues summary
*/
showIssuesSummary(issues) {
const severityCounts = issues.reduce((counts, issue) => {
counts[issue.severity] = (counts[issue.severity] || 0) + 1;
return counts;
}, {});
console.log(chalk_1.default.bold(`\nā ļø Issues Found (${issues.length} total):`));
const severityOrder = ['critical', 'serious', 'moderate', 'minor', 'warning'];
const severityColors = {
critical: chalk_1.default.red.bold,
serious: chalk_1.default.red,
moderate: chalk_1.default.yellow,
minor: chalk_1.default.blue,
warning: chalk_1.default.gray,
};
severityOrder.forEach(severity => {
const count = severityCounts[severity];
if (count) {
const colorFn = severityColors[severity];
console.log(` ${colorFn(severity.padEnd(8))}: ${count}`);
}
});
// Show top issues if verbose
if (this.config.verbose && issues.length > 0) {
console.log(chalk_1.default.bold('\nš Top Issues:'));
issues.slice(0, 5).forEach((issue, index) => {
const severityIcon = this.getSeverityIcon(issue.severity);
console.log(` ${index + 1}. ${severityIcon} ${issue.wcagReference} - ${issue.message}`);
});
}
}
/**
* Display performance metrics
*/
showPerformanceMetrics(metadata) {
if (!this.config.verbose)
return;
console.log(chalk_1.default.bold('\nā” Performance:'));
if (metadata.pageLoadTime) {
const loadTime = metadata.pageLoadTime;
const loadColor = loadTime < 2000 ? chalk_1.default.green : loadTime < 5000 ? chalk_1.default.yellow : chalk_1.default.red;
console.log(` Page Load: ${loadColor(loadTime + 'ms')}`);
}
if (metadata.scanDuration) {
console.log(` Scan Duration: ${metadata.scanDuration}ms`);
}
if (metadata.totalElements && metadata.testedElements) {
const coverage = (metadata.testedElements / metadata.totalElements) * 100;
const coverageColor = coverage > 95 ? chalk_1.default.green : coverage > 80 ? chalk_1.default.yellow : chalk_1.default.red;
console.log(` Test Coverage: ${coverageColor(coverage.toFixed(1) + '%')} (${metadata.testedElements}/${metadata.totalElements} elements)`);
}
}
/**
* Display site-wide results summary
*/
showSiteResults(siteScore, crawlSession) {
if (this.config.quiet)
return;
console.log(chalk_1.default.bold('\nš Site-Wide Results'));
console.log('ā'.repeat(Math.min(20, this.config.maxWidth)));
// Overall score
const scoreColor = this.getScoreColor(siteScore.overallScore);
console.log(`${chalk_1.default.bold('Overall Score:')} ${scoreColor(siteScore.overallScore.toFixed(1))}/100`);
console.log(`Aggregation Method: ${siteScore.aggregationMethod}`);
// Site statistics
console.log(chalk_1.default.bold('\nš Site Statistics:'));
console.log(` Pages Scanned: ${siteScore.pageScores.length}`);
console.log(` Total Issues: ${crawlSession.stats.totalIssues}`);
console.log(` Average Score: ${siteScore.distribution.average.toFixed(1)}`);
console.log(` Score Range: ${siteScore.distribution.minimum.toFixed(1)} - ${siteScore.distribution.maximum.toFixed(1)}`);
// Score distribution
this.showScoreDistribution(siteScore.distribution);
// Consistency metrics
if (this.config.verbose) {
this.showConsistencyMetrics(siteScore.consistency);
}
// Page scores summary
if (this.config.verbose) {
this.showPageScoresSummary(siteScore.pageScores);
}
// Site-wide bonuses
if (siteScore.siteWideBonuses.length > 0) {
console.log(chalk_1.default.bold('\nš Site-Wide Bonuses:'));
siteScore.siteWideBonuses.forEach(bonus => {
console.log(` ${chalk_1.default.green('+')} ${bonus.description}: +${bonus.points} points`);
});
}
}
/**
* Display score distribution
*/
showScoreDistribution(distribution) {
console.log(chalk_1.default.bold('\nš Score Distribution:'));
const ranges = [
{ name: 'Excellent', min: 90, count: distribution.ranges.excellent, color: chalk_1.default.green },
{ name: 'Good', min: 80, count: distribution.ranges.good, color: chalk_1.default.blue },
{ name: 'Fair', min: 70, count: distribution.ranges.fair, color: chalk_1.default.yellow },
{ name: 'Poor', min: 60, count: distribution.ranges.poor, color: chalk_1.default.hex('#FFA500') },
{ name: 'Critical', min: 0, count: distribution.ranges.critical, color: chalk_1.default.red },
];
ranges.forEach(range => {
if (range.count > 0) {
const totalPages = distribution.ranges.excellent + distribution.ranges.good +
distribution.ranges.fair + distribution.ranges.poor + distribution.ranges.critical;
const percentage = range.count > 0 ? (range.count / totalPages) * 100 : 0;
console.log(` ${range.color(range.name.padEnd(9))}: ${range.count} pages (${percentage.toFixed(1)}%)`);
}
});
}
/**
* Display consistency metrics
*/
showConsistencyMetrics(consistency) {
console.log(chalk_1.default.bold('\nšÆ Consistency Analysis:'));
console.log(` Consistency Score: ${consistency.consistencyScore.toFixed(1)}/100`);
console.log(` Score Variance: ${consistency.scoreVariance.toFixed(1)}`);
if (consistency.outlierPages.length > 0) {
console.log(` Outlier Pages: ${consistency.outlierPages.length}`);
if (this.config.verbose) {
consistency.outlierPages.slice(0, 3).forEach((url) => {
console.log(chalk_1.default.gray(` ⢠${url}`));
});
}
}
if (consistency.commonIssues.length > 0) {
console.log(` Common Issues: ${consistency.commonIssues.slice(0, 3).join(', ')}`);
}
}
/**
* Display page scores summary
*/
showPageScoresSummary(pageScores) {
console.log(chalk_1.default.bold('\nš Page Scores Summary:'));
// Sort by score (lowest first to highlight issues)
const sortedPages = [...pageScores].sort((a, b) => a.score - b.score);
sortedPages.slice(0, 10).forEach((page, index) => {
const scoreColor = this.getScoreColor(page.score);
const importanceIcon = this.getImportanceIcon(page.importance);
console.log(` ${importanceIcon} ${scoreColor(page.score.toFixed(1))} - ${page.url}`);
});
if (pageScores.length > 10) {
console.log(chalk_1.default.gray(` ... and ${pageScores.length - 10} more pages`));
}
}
/**
* Display final summary
*/
showFinalSummary(siteScore, crawlSession) {
if (this.config.quiet)
return;
const duration = Date.now() - this.startTime.getTime();
const pagesScanned = siteScore.pageScores.length;
const totalIssues = crawlSession.stats.totalIssues;
const criticalIssues = crawlSession.stats.issuesBySeverity.critical;
console.log(chalk_1.default.bold('\nš Accessibility Analysis Complete!'));
console.log('ā'.repeat(Math.min(35, this.config.maxWidth)));
console.log(`${chalk_1.default.bold('Overall Score:')} ${this.getScoreColor(siteScore.overallScore)(siteScore.overallScore.toFixed(1))}/100`);
console.log(`Pages Analyzed: ${pagesScanned}`);
console.log(`Total Issues: ${totalIssues} (${criticalIssues} critical)`);
console.log(`Analysis Time: ${this.formatDuration(Math.floor(duration / 1000))}`);
// Compliance status
const complianceRate = crawlSession.stats.wcagCompliance.complianceRate * 100;
const complianceColor = complianceRate > 80 ? chalk_1.default.green : complianceRate > 60 ? chalk_1.default.yellow : chalk_1.default.red;
console.log(`WCAG Compliance: ${complianceColor(complianceRate.toFixed(1) + '%')}`);
// Next steps recommendation
this.showRecommendations(siteScore, crawlSession);
}
/**
* Show recommendations based on results
*/
showRecommendations(siteScore, crawlSession) {
console.log(chalk_1.default.bold('\nš” Recommendations:'));
if (siteScore.overallScore >= 90) {
console.log(chalk_1.default.green(' ā Excellent accessibility! Consider periodic monitoring.'));
}
else if (siteScore.overallScore >= 70) {
console.log(chalk_1.default.yellow(' ā Focus on critical and serious issues first.'));
}
else {
console.log(chalk_1.default.red(' ā Significant accessibility issues require immediate attention.'));
}
if (crawlSession.stats.issuesBySeverity.critical > 0) {
console.log(chalk_1.default.red(` ā ${crawlSession.stats.issuesBySeverity.critical} critical issues need immediate fixing.`));
}
if (siteScore.consistency.consistencyScore < 70) {
console.log(chalk_1.default.yellow(' ā Inconsistent accessibility across pages. Review templates and components.'));
}
console.log(chalk_1.default.gray('\n Use --verbose for detailed issue analysis.'));
console.log(chalk_1.default.gray(' Generate JSON report with --output for developer review.'));
}
/**
* Log errors and warnings
*/
logWarning(message) {
if (!this.config.quiet) {
console.log(chalk_1.default.yellow(`ā Warning: ${message}`));
}
}
logError(message, error) {
if (!this.config.quiet) {
console.log(chalk_1.default.red(`šØ Error: ${message}`));
if (error) {
console.log(chalk_1.default.red(error.stack || error.message));
}
}
}
logPass(message) {
if (!this.config.quiet) {
console.log(chalk_1.default.green(`ā Pass: ${message}`));
}
}
logInfo(message) {
if (!this.config.quiet) {
console.log(chalk_1.default.cyan(message));
}
}
logSummary(summary) {
if (!this.config.quiet) {
console.log(chalk_1.default.cyan('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
for (const line of summary) {
console.log(chalk_1.default.cyan(line));
}
console.log(chalk_1.default.cyan('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
}
}
/**
* Display error summary from error logger
*/
showErrorSummary(errorLogger) {
if (this.config.quiet)
return;
const stats = errorLogger.getErrorStatistics();
const totalErrors = Object.values(stats.byLevel).reduce((sum, count) => sum + count, 0);
if (totalErrors === 0) {
console.log(chalk_1.default.green(`\n${figures_1.default.tick} No errors encountered during analysis`));
return;
}
console.log(chalk_1.default.bold('\nšØ Error Summary'));
console.log('ā'.repeat(Math.min(15, this.config.maxWidth)));
// Error counts by level
console.log(`Total Errors: ${totalErrors}`);
if (stats.byLevel.fatal > 0) {
console.log(` ${chalk_1.default.red.bold('Fatal')}: ${stats.byLevel.fatal}`);
}
if (stats.byLevel.error > 0) {
console.log(` ${chalk_1.default.red('Error')}: ${stats.byLevel.error}`);
}
if (stats.byLevel.warn > 0) {
console.log(` ${chalk_1.default.yellow('Warning')}: ${stats.byLevel.warn}`);
}
if (stats.byLevel.info > 0 && this.config.verbose) {
console.log(` ${chalk_1.default.blue('Info')}: ${stats.byLevel.info}`);
}
if (stats.byLevel.debug > 0 && this.config.debug) {
console.log(` ${chalk_1.default.gray('Debug')}: ${stats.byLevel.debug}`);
}
// Recovery statistics
if (stats.recovery.totalAttempts > 0) {
const recoveryRate = Math.round(stats.recovery.recoveryRate * 100);
const recoveryColor = recoveryRate > 80 ? chalk_1.default.green : recoveryRate > 50 ? chalk_1.default.yellow : chalk_1.default.red;
console.log(`Recovery Rate: ${recoveryColor(recoveryRate + '%')} (${stats.recovery.successfulRecoveries}/${stats.recovery.totalAttempts})`);
}
// Most frequent errors
if (this.config.verbose && stats.frequentErrors.length > 0) {
console.log(chalk_1.default.bold('\nš Most Frequent Errors:'));
stats.frequentErrors.slice(0, 5).forEach((error, index) => {
const levelColor = this.getErrorLevelColor(error.level);
console.log(` ${index + 1}. ${levelColor(error.level.toUpperCase())}: ${error.message} (${error.count}x)`);
});
}
}
/**
* Display detailed error entries
*/
showDetailedErrors(errorLogger, maxErrors = 10) {
if (this.config.quiet)
return;
const errors = errorLogger.getErrors().slice(-maxErrors); // Show recent errors
if (errors.length === 0)
return;
console.log(chalk_1.default.bold('\nš Recent Errors'));
console.log('ā'.repeat(Math.min(15, this.config.maxWidth)));
errors.forEach((error, index) => {
const levelColor = this.getErrorLevelColor(error.level);
const categoryIcon = this.getErrorCategoryIcon(error.category);
console.log(`${index + 1}. ${categoryIcon} ${levelColor(error.level.toUpperCase())} [${error.category}]`);
console.log(` ${error.message}`);
if (error.url) {
console.log(chalk_1.default.gray(` URL: ${error.url}`));
}
if (error.source !== 'unknown') {
console.log(chalk_1.default.gray(` Source: ${error.source}`));
}
if (error.recoveryAction) {
const recoveryColor = error.recovered ? chalk_1.default.green : chalk_1.default.yellow;
console.log(recoveryColor(` Recovery: ${error.recoveryAction}`));
}
if (this.config.debug && error.stack) {
console.log(chalk_1.default.gray(` Stack: ${error.stack.split('\n')[0]}`));
}
console.log(''); // Add spacing
});
}
/**
* Display technical issues
*/
showTechnicalIssues(errorLogger) {
if (this.config.quiet)
return;
const issues = errorLogger.getTechnicalIssues();
if (issues.length === 0)
return;
console.log(chalk_1.default.bold('\nš§ Technical Issues Detected'));
console.log('ā'.repeat(Math.min(30, this.config.maxWidth)));
issues.forEach((issue, index) => {
const severityColor = this.getTechnicalIssueSeverityColor(issue.severity);
const typeIcon = this.getTechnicalIssueTypeIcon(issue.type);
console.log(`${index + 1}. ${typeIcon} ${severityColor(issue.severity.toUpperCase())} - ${issue.title}`);
console.log(` ${issue.description}`);
if (issue.affectedUrls.length > 0) {
const urlsToShow = issue.affectedUrls.slice(0, 3);
console.log(chalk_1.default.gray(` Affected URLs: ${urlsToShow.join(', ')}`));
if (issue.affectedUrls.length > 3) {
console.log(chalk_1.default.gray(` ... and ${issue.affectedUrls.length - 3} more`));
}
}
if (issue.occurrenceCount > 1) {
console.log(chalk_1.default.gray(` Occurrences: ${issue.occurrenceCount}`));
}
if (this.config.verbose && issue.suggestedFixes.length > 0) {
console.log(chalk_1.default.bold(' š” Suggested Fixes:'));
issue.suggestedFixes.slice(0, 3).forEach(fix => {
console.log(chalk_1.default.gray(` ⢠${fix}`));
});
}
console.log(''); // Add spacing
});
}
/**
* Display system diagnostics information
*/
async showSystemDiagnostics(errorLogger) {
if (this.config.quiet || !this.config.debug)
return;
try {
const diagnostics = await errorLogger.collectSystemDiagnostics();
console.log(chalk_1.default.bold('\nš„ļø System Diagnostics'));
console.log('ā'.repeat(Math.min(20, this.config.maxWidth)));
// System information
console.log(chalk_1.default.bold('System:'));
console.log(` Platform: ${diagnostics.system.platform} (${diagnostics.system.arch})`);
console.log(` Node.js: ${diagnostics.system.nodeVersion}`);
console.log(` Memory: ${Math.round(diagnostics.system.memory.percentage)}% used (${Math.round(diagnostics.system.memory.used / 1024 / 1024)}MB / ${Math.round(diagnostics.system.memory.total / 1024 / 1024)}MB)`);
console.log(` CPU: ${diagnostics.system.cpu.model} (${diagnostics.system.cpu.cores} cores)`);
// Browser information
console.log(chalk_1.default.bold('\nBrowser:'));
console.log(` Engine: ${diagnostics.browser.name} ${diagnostics.browser.version}`);
console.log(` User Agent: ${diagnostics.browser.userAgent}`);
// Network information
console.log(chalk_1.default.bold('\nNetwork:'));
const connectivityColor = diagnostics.network.connectivity === 'online' ? chalk_1.default.green : chalk_1.default.red;
console.log(` Connectivity: ${connectivityColor(diagnostics.network.connectivity)}`);
console.log(` DNS Resolution: ${diagnostics.network.dnsResolution ? chalk_1.default.green('OK') : chalk_1.default.red('Failed')}`);
}
catch (error) {
console.log(chalk_1.default.red('Failed to collect system diagnostics'));
}
}
/**
* Show comprehensive error report
*/
showErrorReport(errorLogger) {
if (this.config.quiet)
return;
this.showErrorSummary(errorLogger);
if (this.config.verbose) {
this.showTechnicalIssues(errorLogger);
this.showDetailedErrors(errorLogger, 5);
}
}
/**
* Helper methods for error display
*/
getErrorLevelColor(level) {
switch (level) {
case 'fatal': return chalk_1.default.red.bold;
case 'error': return chalk_1.default.red;
case 'warn': return chalk_1.default.yellow;
case 'info': return chalk_1.default.blue;
case 'debug': return chalk_1.default.gray;
default: return chalk_1.default.white;
}
}
getErrorCategoryIcon(category) {
const icons = {
browser: 'š',
network: 'š”',
parsing: 'š',
timeout: 'ā±ļø',
validation: 'ā
',
configuration: 'āļø',
scanning: 'š',
crawling: 'š·ļø',
output: 'š',
system: 'š»',
unknown: 'ā',
};
return icons[category] || 'ā';
}
getTechnicalIssueSeverityColor(severity) {
switch (severity) {
case 'critical': return chalk_1.default.red.bold;
case 'high': return chalk_1.default.red;
case 'medium': return chalk_1.default.yellow;
case 'low': return chalk_1.default.blue;
default: return chalk_1.default.white;
}
}
getTechnicalIssueTypeIcon(type) {
const icons = {
performance: 'ā”',
compatibility: 'š',
resource: 'š¦',
security: 'š',
accessibility: 'āæ',
other: 'š§',
};
return icons[type] || 'š§';
}
/**
* Clean up resources
*/
cleanup() {
// Stop all spinners
this.spinners.forEach(spinner => spinner.stop());
this.spinners.clear();
// Stop multi-bar
if (this.multiBar) {
this.multiBar.stop();
}
// Clear progress bars
this.progressBars.clear();
}
/**
* Helper methods
*/
getScoreColor(score) {
if (score >= 90)
return chalk_1.default.green.bold;
if (score >= 80)
return chalk_1.default.green;
if (score >= 70)
return chalk_1.default.yellow;
if (score >= 60)
return chalk_1.default.hex('#FFA500'); // Orange color
return chalk_1.default.red;
}
getSeverityIcon(severity) {
const icons = {
critical: chalk_1.default.red(figures_1.default.cross),
serious: chalk_1.default.red(figures_1.default.warning),
moderate: chalk_1.default.yellow(figures_1.default.warning),
minor: chalk_1.default.blue(figures_1.default.info),
warning: chalk_1.default.gray(figures_1.default.bullet),
};
return icons[severity] || figures_1.default.bullet;
}
getImportanceIcon(importance) {
const icons = {
critical: chalk_1.default.red(figures_1.default.star),
high: chalk_1.default.yellow(figures_1.default.star),
medium: chalk_1.default.blue(figures_1.default.circle),
low: chalk_1.default.gray(figures_1.default.circle),
};
return icons[importance] || figures_1.default.circle;
}
formatDuration(seconds) {
if (seconds < 60) {
return `${seconds}s`;
}
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}m ${remainingSeconds}s`;
}
/**
* Static factory methods
*/
static createDefault() {
return new ConsoleReporter();
}
static createVerbose() {
return new ConsoleReporter({ verbose: true });
}
static createQuiet() {
return new ConsoleReporter({ quiet: true, showProgress: false, showSpinner: false });
}
static createDebug() {
return new ConsoleReporter({ verbose: true, debug: true });
}
}
exports.ConsoleReporter = ConsoleReporter;
//# sourceMappingURL=console-reporter.js.map