n8n-nodes-pdf-accessibility
Version:
AI-powered PDF accessibility automation for N8N - comprehensive WCAG compliance analysis, intelligent remediation, and professional audit reporting with 5 integrated accessibility tools
286 lines (275 loc) • 11.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AdvancedReportingEngine = void 0;
class AdvancedReportingEngine {
/**
* Generate comprehensive accessibility audit report
*/
static generateAuditReport(toolResults, documentInfo, wcagLevel, beforeScore, afterScore) {
const allIssues = toolResults.flatMap(result => result.issuesFound);
const allFixes = toolResults.flatMap(result => result.fixesApplied);
const issuesBySeverity = this.groupIssuesBySeverity(allIssues);
const fixesByType = this.groupFixesByType(allFixes);
const wcagCompliance = this.calculateWCAGCompliance(allIssues, wcagLevel);
return {
executive_summary: {
document_name: documentInfo.fileName,
audit_date: new Date().toISOString(),
wcag_level: wcagLevel,
overall_score: afterScore,
total_issues: allIssues.length,
total_fixes: allFixes.filter(fix => fix.applied).length,
compliance_status: this.determineComplianceStatus(afterScore),
},
document_analysis: {
file_info: {
name: documentInfo.fileName,
size: documentInfo.fileSize || 0,
pages: documentInfo.pageCount || 0,
language: documentInfo.language || 'unknown',
},
content_analysis: {
has_images: documentInfo.hasImages || false,
has_tables: documentInfo.hasTables || false,
has_links: documentInfo.hasLinks || false,
text_length: documentInfo.textLength || 0,
},
},
accessibility_findings: {
issues_by_severity: issuesBySeverity,
wcag_compliance: wcagCompliance,
},
improvements_applied: {
fixes_by_type: fixesByType,
before_after_comparison: {
before_score: beforeScore,
after_score: afterScore,
improvement_percentage: Math.round(((afterScore - beforeScore) / beforeScore) * 100),
},
},
tool_execution_details: toolResults,
recommendations: this.generateRecommendations(allIssues, wcagLevel),
export_formats: this.generateExportFormats(toolResults, documentInfo, wcagLevel),
};
}
/**
* Generate visual diff representation of changes
*/
static generateVisualDiff(beforeData, _afterData) {
const changes = [];
// Mock implementation showing the structure for visual diff
if (beforeData.hasImages && !beforeData.altTextPresent) {
changes.push({
category: 'Images',
before: 'No alt-text provided',
after: 'Descriptive alt-text added for all images',
improvement_type: 'WCAG 1.1.1 Non-text Content',
});
}
if (beforeData.hasTables && !beforeData.tableHeaders) {
changes.push({
category: 'Tables',
before: 'Tables lack proper headers',
after: 'Table headers and captions added',
improvement_type: 'WCAG 1.3.1 Info and Relationships',
});
}
const wcagCriteria = [...new Set(changes.map(change => change.improvement_type))];
return {
summary: `${changes.length} accessibility improvements implemented`,
changes,
metrics: {
total_changes: changes.length,
accessibility_improvements: changes.length,
wcag_criteria_addressed: wcagCriteria,
},
};
}
/**
* Export report in multiple formats
*/
static exportReport(report, format) {
switch (format) {
case 'json':
return JSON.stringify(report, null, 2);
case 'html':
return this.generateHTMLReport(report);
case 'markdown':
return this.generateMarkdownReport(report);
case 'csv':
return this.generateCSVReport(report);
default:
return JSON.stringify(report, null, 2);
}
}
static groupIssuesBySeverity(issues) {
return {
critical: issues.filter(issue => issue.severity === 'critical'),
high: issues.filter(issue => issue.severity === 'high'),
medium: issues.filter(issue => issue.severity === 'medium'),
low: issues.filter(issue => issue.severity === 'low'),
};
}
static groupFixesByType(fixes) {
const grouped = {};
fixes.forEach(fix => {
if (!grouped[fix.type]) {
grouped[fix.type] = [];
}
grouped[fix.type].push(fix);
});
return grouped;
}
static calculateWCAGCompliance(issues, _wcagLevel) {
// Mock implementation - would need real WCAG criteria mapping
const levelACriteria = ['1.1.1', '1.3.1', '2.4.1', '2.4.4', '3.1.1'];
const levelAACriteria = ['2.4.6', '3.1.2', '3.2.4'];
const levelAAACriteria = ['2.4.9', '2.4.10'];
const failedCriteria = new Set(issues.flatMap(issue => issue.wcagCriteria));
return {
level_a: {
total: levelACriteria.length,
failed: levelACriteria.filter(criteria => failedCriteria.has(criteria)).length,
passed: levelACriteria.length - levelACriteria.filter(criteria => failedCriteria.has(criteria)).length,
},
level_aa: {
total: levelAACriteria.length,
failed: levelAACriteria.filter(criteria => failedCriteria.has(criteria)).length,
passed: levelAACriteria.length - levelAACriteria.filter(criteria => failedCriteria.has(criteria)).length,
},
level_aaa: {
total: levelAAACriteria.length,
failed: levelAAACriteria.filter(criteria => failedCriteria.has(criteria)).length,
passed: levelAAACriteria.length - levelAAACriteria.filter(criteria => failedCriteria.has(criteria)).length,
},
};
}
static determineComplianceStatus(score) {
if (score >= 90)
return 'compliant';
if (score >= 70)
return 'partial';
return 'non_compliant';
}
static generateRecommendations(issues, wcagLevel) {
const critical = issues.filter(issue => issue.severity === 'critical');
const high = issues.filter(issue => issue.severity === 'high');
return {
immediate_actions: [
...critical.map(issue => issue.suggestion),
...high.slice(0, 3).map(issue => issue.suggestion),
],
long_term_improvements: [
'Implement accessibility testing in development workflow',
'Train content creators on WCAG guidelines',
'Regular accessibility audits for all documents',
],
best_practices: [
'Use semantic HTML structure in source documents',
'Provide meaningful alt-text for all images',
'Ensure proper heading hierarchy',
'Test with screen readers and assistive technologies',
`Maintain ${wcagLevel} compliance standards across all documents`,
],
};
}
static generateExportFormats(_toolResults, _documentInfo, _wcagLevel) {
// Simplified export format generation
return {
json: 'Full JSON report available for API integration',
html: 'Professional HTML report suitable for stakeholder presentation',
markdown: 'Markdown format for documentation and version control',
csv: 'CSV format for data analysis and tracking',
};
}
static generateHTMLReport(report) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PDF Accessibility Audit Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background: #f4f4f4; padding: 20px; border-radius: 5px; }
.score { font-size: 2em; color: ${report.executive_summary.overall_score >= 80 ? '#28a745' : '#dc3545'}; }
.section { margin: 20px 0; }
.issue { background: #fff3cd; padding: 10px; margin: 5px 0; border-left: 4px solid #ffc107; }
.fix { background: #d4edda; padding: 10px; margin: 5px 0; border-left: 4px solid #28a745; }
</style>
</head>
<body>
<div class="header">
<h1>PDF Accessibility Audit Report</h1>
<p><strong>Document:</strong> ${report.executive_summary.document_name}</p>
<p><strong>WCAG Level:</strong> ${report.executive_summary.wcag_level}</p>
<p><strong>Overall Score:</strong> <span class="score">${report.executive_summary.overall_score}%</span></p>
<p><strong>Compliance Status:</strong> ${report.executive_summary.compliance_status}</p>
</div>
<div class="section">
<h2>Executive Summary</h2>
<ul>
<li>Total Issues Found: ${report.executive_summary.total_issues}</li>
<li>Total Fixes Applied: ${report.executive_summary.total_fixes}</li>
<li>Audit Date: ${new Date(report.executive_summary.audit_date).toLocaleDateString()}</li>
</ul>
</div>
<div class="section">
<h2>Recommendations</h2>
<h3>Immediate Actions</h3>
<ul>
${report.recommendations.immediate_actions.map(action => `<li>${action}</li>`).join('')}
</ul>
</div>
</body>
</html>`;
}
static generateMarkdownReport(report) {
return `
# PDF Accessibility Audit Report
## Executive Summary
- **Document:** ${report.executive_summary.document_name}
- **WCAG Level:** ${report.executive_summary.wcag_level}
- **Overall Score:** ${report.executive_summary.overall_score}%
- **Compliance Status:** ${report.executive_summary.compliance_status}
- **Total Issues:** ${report.executive_summary.total_issues}
- **Total Fixes:** ${report.executive_summary.total_fixes}
## Document Analysis
- **File Size:** ${report.document_analysis.file_info.size} bytes
- **Pages:** ${report.document_analysis.file_info.pages}
- **Language:** ${report.document_analysis.file_info.language}
## Immediate Actions Required
${report.recommendations.immediate_actions.map(action => `- ${action}`).join('\n')}
## Best Practices
${report.recommendations.best_practices.map(practice => `- ${practice}`).join('\n')}
`;
}
static generateCSVReport(report) {
const headers = ['Category', 'Severity', 'Description', 'WCAG Criteria', 'Status'];
const rows = [headers.join(',')];
// Add issues
Object.entries(report.accessibility_findings.issues_by_severity).forEach(([severity, issues]) => {
issues.forEach(issue => {
rows.push([
issue.type,
severity,
`"${issue.description}"`,
issue.wcagCriteria.join(';'),
'Issue'
].join(','));
});
});
// Add fixes
Object.values(report.improvements_applied.fixes_by_type).flat().forEach(fix => {
rows.push([
fix.type,
'N/A',
`"${fix.description}"`,
fix.wcagImprovement.join(';'),
fix.applied ? 'Fixed' : 'Pending'
].join(','));
});
return rows.join('\n');
}
}
exports.AdvancedReportingEngine = AdvancedReportingEngine;