gbu-accessibility-package 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PACKAGE_SUMMARY.md +191 -0
- package/QUICK_START.md +137 -0
- package/README.md +305 -0
- package/cli.js +157 -0
- package/demo/demo.js +73 -0
- package/demo/sample.html +47 -0
- package/demo/sample.html.backup +47 -0
- package/example.js +121 -0
- package/index.js +8 -0
- package/lib/enhancer.js +163 -0
- package/lib/fixer.js +764 -0
- package/lib/tester.js +157 -0
- package/package.json +62 -0
package/lib/tester.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accessibility Tester
|
|
3
|
+
* Automated testing using axe-core and custom rules
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { spawn } = require('child_process');
|
|
7
|
+
const fs = require('fs').promises;
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
|
|
11
|
+
class AccessibilityTester {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
this.config = {
|
|
14
|
+
baseUrl: config.baseUrl || 'http://localhost:8080',
|
|
15
|
+
outputDir: config.outputDir || 'accessibility-reports',
|
|
16
|
+
pages: config.pages || [],
|
|
17
|
+
serverPort: config.serverPort || 8080,
|
|
18
|
+
...config
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async startServer() {
|
|
23
|
+
console.log(chalk.blue('๐ Starting local server...'));
|
|
24
|
+
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
// Try python3 first, then python
|
|
27
|
+
const pythonCmd = this.findPython();
|
|
28
|
+
const server = spawn(pythonCmd, ['-m', 'http.server', this.config.serverPort.toString()], {
|
|
29
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
server.stdout.on('data', (data) => {
|
|
33
|
+
const output = data.toString();
|
|
34
|
+
if (output.includes('Serving HTTP')) {
|
|
35
|
+
console.log(chalk.green('โ
Server started successfully'));
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
server.stderr.on('data', (data) => {
|
|
40
|
+
const error = data.toString();
|
|
41
|
+
if (!error.includes('Serving HTTP')) {
|
|
42
|
+
console.error(chalk.red(`Server error: ${error}`));
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
server.on('error', (error) => {
|
|
47
|
+
reject(new Error(`Failed to start server: ${error.message}`));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Wait for server to start
|
|
51
|
+
setTimeout(() => resolve(server), 3000);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
findPython() {
|
|
56
|
+
// Check which python command is available
|
|
57
|
+
const { execSync } = require('child_process');
|
|
58
|
+
try {
|
|
59
|
+
execSync('python3 --version', { stdio: 'ignore' });
|
|
60
|
+
return 'python3';
|
|
61
|
+
} catch {
|
|
62
|
+
try {
|
|
63
|
+
execSync('python --version', { stdio: 'ignore' });
|
|
64
|
+
return 'python';
|
|
65
|
+
} catch {
|
|
66
|
+
throw new Error('Python not found. Please install Python to run the test server.');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async testPages(pages = null) {
|
|
72
|
+
const testPages = pages || this.config.pages;
|
|
73
|
+
|
|
74
|
+
if (testPages.length === 0) {
|
|
75
|
+
throw new Error('No pages specified for testing');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(chalk.blue('๐งช Running accessibility tests...'));
|
|
79
|
+
|
|
80
|
+
// Create output directory
|
|
81
|
+
await fs.mkdir(this.config.outputDir, { recursive: true });
|
|
82
|
+
|
|
83
|
+
const results = [];
|
|
84
|
+
|
|
85
|
+
for (const page of testPages) {
|
|
86
|
+
const url = page.startsWith('http') ? page : `${this.config.baseUrl}/${page}`;
|
|
87
|
+
const filename = this.generateReportFilename(url);
|
|
88
|
+
const outputPath = path.join(this.config.outputDir, filename);
|
|
89
|
+
|
|
90
|
+
console.log(chalk.yellow(`Testing: ${url}`));
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
await this.runAxeTest(url, outputPath);
|
|
94
|
+
results.push({ url, status: 'success', reportPath: outputPath });
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error(chalk.red(`Failed to test ${url}: ${error.message}`));
|
|
97
|
+
results.push({ url, status: 'error', error: error.message });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async runAxeTest(url, outputPath) {
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
const axe = spawn('axe', [url, '--save', outputPath]);
|
|
107
|
+
|
|
108
|
+
axe.on('close', (code) => {
|
|
109
|
+
if (code === 0) {
|
|
110
|
+
resolve();
|
|
111
|
+
} else {
|
|
112
|
+
reject(new Error(`axe-core exited with code ${code}`));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
axe.on('error', (error) => {
|
|
117
|
+
reject(error);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
generateReportFilename(url) {
|
|
123
|
+
const urlObj = new URL(url);
|
|
124
|
+
const pathname = urlObj.pathname.replace(/\//g, '-').replace(/^-/, '') || 'index';
|
|
125
|
+
return `${pathname}-report.json`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async generateSummary() {
|
|
129
|
+
const reportFiles = await fs.readdir(this.config.outputDir);
|
|
130
|
+
const jsonFiles = reportFiles.filter(file => file.endsWith('.json'));
|
|
131
|
+
|
|
132
|
+
let totalViolations = 0;
|
|
133
|
+
let totalPasses = 0;
|
|
134
|
+
const violationsByType = {};
|
|
135
|
+
|
|
136
|
+
for (const file of jsonFiles) {
|
|
137
|
+
const reportPath = path.join(this.config.outputDir, file);
|
|
138
|
+
const reportData = JSON.parse(await fs.readFile(reportPath, 'utf8'));
|
|
139
|
+
|
|
140
|
+
totalViolations += reportData.violations?.length || 0;
|
|
141
|
+
totalPasses += reportData.passes?.length || 0;
|
|
142
|
+
|
|
143
|
+
reportData.violations?.forEach(violation => {
|
|
144
|
+
violationsByType[violation.id] = (violationsByType[violation.id] || 0) + 1;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
totalFiles: jsonFiles.length,
|
|
150
|
+
totalViolations,
|
|
151
|
+
totalPasses,
|
|
152
|
+
violationsByType
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = AccessibilityTester;
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gbu-accessibility-package",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Automated accessibility fixes for HTML files - Alt attributes, Lang attributes, Role attributes. Smart context-aware alt text generation and comprehensive role attribute management.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"gbu-a11y": "./cli.js",
|
|
8
|
+
"accessibility-fixer": "./cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node cli.js",
|
|
12
|
+
"fix": "node cli.js",
|
|
13
|
+
"preview": "node cli.js --dry-run",
|
|
14
|
+
"test": "node example.js",
|
|
15
|
+
"demo": "node cli.js --dry-run demo",
|
|
16
|
+
"prepublishOnly": "npm run demo"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"accessibility",
|
|
20
|
+
"a11y",
|
|
21
|
+
"html",
|
|
22
|
+
"automation",
|
|
23
|
+
"alt-text",
|
|
24
|
+
"role-attributes",
|
|
25
|
+
"lang-attributes",
|
|
26
|
+
"wcag",
|
|
27
|
+
"gbu",
|
|
28
|
+
"context-aware",
|
|
29
|
+
"smart-alt-text",
|
|
30
|
+
"accessibility-fixer",
|
|
31
|
+
"html-accessibility"
|
|
32
|
+
],
|
|
33
|
+
"author": "GBU Team",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "https://github.com/your-org/gbu-accessibility-package.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/your-org/gbu-accessibility-package#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/your-org/gbu-accessibility-package/issues"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"lib/",
|
|
45
|
+
"index.js",
|
|
46
|
+
"cli.js",
|
|
47
|
+
"example.js",
|
|
48
|
+
"demo/",
|
|
49
|
+
"README.md",
|
|
50
|
+
"QUICK_START.md",
|
|
51
|
+
"PACKAGE_SUMMARY.md"
|
|
52
|
+
],
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"chalk": "^4.1.2"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=12.0.0"
|
|
58
|
+
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
}
|
|
62
|
+
}
|