gbu-accessibility-package 1.5.0 → 3.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/README.md +97 -51
- package/cli.js +196 -101
- package/demo/advanced-test.html +44 -0
- package/demo/advanced-test.html.backup +44 -0
- package/demo/aria-label-test.html +32 -0
- package/demo/backup-test.html +18 -0
- package/demo/backup-test2.html +13 -0
- package/demo/backup-test3.html +12 -0
- package/demo/comprehensive-test.html +21 -0
- package/demo/comprehensive-test.html.backup +21 -0
- package/lib/fixer.js +725 -11
- package/package.json +8 -1
- package/demo/duplicate-roles.html.backup +0 -45
- package/demo/picture-test.html +0 -37
- package/demo/picture-test.html.backup +0 -37
- package/demo/sample.html.backup +0 -47
package/cli.js
CHANGED
|
@@ -14,14 +14,19 @@ const args = process.argv.slice(2);
|
|
|
14
14
|
const options = {
|
|
15
15
|
directory: '.',
|
|
16
16
|
language: 'ja',
|
|
17
|
-
backupFiles: true,
|
|
17
|
+
backupFiles: true, // Default to true for safety
|
|
18
18
|
dryRun: false,
|
|
19
19
|
help: false,
|
|
20
20
|
cleanupOnly: false,
|
|
21
|
-
comprehensive: false,
|
|
21
|
+
comprehensive: false, // Keep for backward compatibility
|
|
22
22
|
altOnly: false,
|
|
23
23
|
langOnly: false,
|
|
24
|
-
roleOnly: false
|
|
24
|
+
roleOnly: false,
|
|
25
|
+
formsOnly: false,
|
|
26
|
+
buttonsOnly: false,
|
|
27
|
+
linksOnly: false,
|
|
28
|
+
landmarksOnly: false,
|
|
29
|
+
headingsOnly: false
|
|
25
30
|
};
|
|
26
31
|
|
|
27
32
|
// Parse arguments
|
|
@@ -41,6 +46,9 @@ for (let i = 0; i < args.length; i++) {
|
|
|
41
46
|
case '-l':
|
|
42
47
|
options.language = args[++i];
|
|
43
48
|
break;
|
|
49
|
+
case '--backup':
|
|
50
|
+
options.backupFiles = true;
|
|
51
|
+
break;
|
|
44
52
|
case '--no-backup':
|
|
45
53
|
options.backupFiles = false;
|
|
46
54
|
break;
|
|
@@ -52,7 +60,7 @@ for (let i = 0; i < args.length; i++) {
|
|
|
52
60
|
break;
|
|
53
61
|
case '--comprehensive':
|
|
54
62
|
case '--all':
|
|
55
|
-
options.comprehensive = true;
|
|
63
|
+
options.comprehensive = true; // Keep for backward compatibility
|
|
56
64
|
break;
|
|
57
65
|
case '--alt-only':
|
|
58
66
|
options.altOnly = true;
|
|
@@ -63,6 +71,21 @@ for (let i = 0; i < args.length; i++) {
|
|
|
63
71
|
case '--role-only':
|
|
64
72
|
options.roleOnly = true;
|
|
65
73
|
break;
|
|
74
|
+
case '--forms-only':
|
|
75
|
+
options.formsOnly = true;
|
|
76
|
+
break;
|
|
77
|
+
case '--buttons-only':
|
|
78
|
+
options.buttonsOnly = true;
|
|
79
|
+
break;
|
|
80
|
+
case '--links-only':
|
|
81
|
+
options.linksOnly = true;
|
|
82
|
+
break;
|
|
83
|
+
case '--landmarks-only':
|
|
84
|
+
options.landmarksOnly = true;
|
|
85
|
+
break;
|
|
86
|
+
case '--headings-only':
|
|
87
|
+
options.headingsOnly = true;
|
|
88
|
+
break;
|
|
66
89
|
default:
|
|
67
90
|
if (!arg.startsWith('-')) {
|
|
68
91
|
options.directory = arg;
|
|
@@ -80,25 +103,34 @@ Usage: node cli.js [options] [directory]
|
|
|
80
103
|
Options:
|
|
81
104
|
-d, --directory <path> Target directory (default: current directory)
|
|
82
105
|
-l, --language <lang> Language for lang attribute (default: ja)
|
|
106
|
+
--backup Create backup files (default: enabled)
|
|
83
107
|
--no-backup Don't create backup files
|
|
84
108
|
--dry-run Preview changes without applying
|
|
85
|
-
--comprehensive, --all Run
|
|
109
|
+
--comprehensive, --all Run comprehensive fixes (same as default)
|
|
86
110
|
--cleanup-only Only cleanup duplicate role attributes
|
|
87
|
-
--alt-only
|
|
88
|
-
--lang-only
|
|
89
|
-
--role-only
|
|
111
|
+
--alt-only Fix alt attributes + cleanup
|
|
112
|
+
--lang-only Fix HTML lang attributes + cleanup
|
|
113
|
+
--role-only Fix role attributes + cleanup
|
|
114
|
+
--forms-only Fix form labels + cleanup
|
|
115
|
+
--buttons-only Fix button names + cleanup
|
|
116
|
+
--links-only Fix link names + cleanup
|
|
117
|
+
--landmarks-only Fix landmarks + cleanup
|
|
118
|
+
--headings-only Analyze heading structure (no auto-fix)
|
|
90
119
|
-h, --help Show this help message
|
|
91
120
|
|
|
92
121
|
Examples:
|
|
93
|
-
node cli.js #
|
|
94
|
-
node cli.js --comprehensive #
|
|
95
|
-
node cli.js --alt-only #
|
|
96
|
-
node cli.js --
|
|
97
|
-
node cli.js --
|
|
122
|
+
node cli.js # Comprehensive fixes (default mode)
|
|
123
|
+
node cli.js --comprehensive # Comprehensive fixes (same as default)
|
|
124
|
+
node cli.js --alt-only # Fix alt attributes + cleanup
|
|
125
|
+
node cli.js --forms-only # Fix form labels + cleanup
|
|
126
|
+
node cli.js --buttons-only # Fix button names + cleanup
|
|
127
|
+
node cli.js --links-only # Fix link names + cleanup
|
|
128
|
+
node cli.js --landmarks-only # Fix landmarks + cleanup
|
|
129
|
+
node cli.js --headings-only # Analyze heading structure only
|
|
98
130
|
node cli.js --cleanup-only # Only cleanup duplicate roles
|
|
99
|
-
node cli.js ./src # Fix src directory
|
|
100
|
-
node cli.js -l en --dry-run ./dist # Preview fixes
|
|
101
|
-
node cli.js --no-backup ./public #
|
|
131
|
+
node cli.js ./src # Fix src directory (comprehensive)
|
|
132
|
+
node cli.js -l en --dry-run ./dist # Preview comprehensive fixes in English
|
|
133
|
+
node cli.js --no-backup ./public # Comprehensive fixes without backups
|
|
102
134
|
|
|
103
135
|
Features:
|
|
104
136
|
✅ Alt attributes for images
|
|
@@ -110,6 +142,23 @@ Features:
|
|
|
110
142
|
process.exit(0);
|
|
111
143
|
}
|
|
112
144
|
|
|
145
|
+
|
|
146
|
+
// Helper function to show completion message with backup info
|
|
147
|
+
function showCompletionMessage(options, mode = 'fixes') {
|
|
148
|
+
if (options.dryRun) {
|
|
149
|
+
console.log(chalk.cyan('\n💡 This was a dry run. Use without --dry-run to apply changes.'));
|
|
150
|
+
} else {
|
|
151
|
+
console.log(chalk.green(`\n🎉 ${mode} completed successfully!`));
|
|
152
|
+
if (options.backupFiles) {
|
|
153
|
+
console.log(chalk.gray(' 📁 Backup files created with .backup extension'));
|
|
154
|
+
console.log(chalk.gray(' 💡 Use --no-backup to disable backups in future runs'));
|
|
155
|
+
} else {
|
|
156
|
+
console.log(chalk.yellow(' ⚠️ No backup files created (--no-backup was used)'));
|
|
157
|
+
console.log(chalk.gray(' 💡 Use --backup to enable backups for safety'));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
113
162
|
// Main function
|
|
114
163
|
async function main() {
|
|
115
164
|
console.log(chalk.blue('🚀 Starting Accessibility Fixer...'));
|
|
@@ -126,14 +175,30 @@ async function main() {
|
|
|
126
175
|
});
|
|
127
176
|
|
|
128
177
|
try {
|
|
129
|
-
// Handle different modes
|
|
130
|
-
if (options.
|
|
131
|
-
|
|
178
|
+
// Handle different modes - All modes now include cleanup
|
|
179
|
+
if (options.cleanupOnly || options.altOnly || options.langOnly || options.roleOnly ||
|
|
180
|
+
options.formsOnly || options.buttonsOnly || options.linksOnly || options.landmarksOnly || options.headingsOnly) {
|
|
181
|
+
// Individual modes - handle each separately, then run cleanup
|
|
182
|
+
} else {
|
|
183
|
+
// Default mode: Run comprehensive fix (all fixes including cleanup)
|
|
132
184
|
console.log(chalk.blue('🎯 Running comprehensive accessibility fixes...'));
|
|
133
185
|
const results = await fixer.fixAllAccessibilityIssues(options.directory);
|
|
134
186
|
|
|
135
187
|
// Results already logged in the method
|
|
136
188
|
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Individual modes
|
|
192
|
+
if (options.cleanupOnly) {
|
|
193
|
+
// Only cleanup duplicate roles
|
|
194
|
+
console.log(chalk.blue('🧹 Running cleanup for duplicate role attributes...'));
|
|
195
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
196
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
197
|
+
|
|
198
|
+
console.log(chalk.green(`\n✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
199
|
+
|
|
200
|
+
showCompletionMessage(options, 'Cleanup');
|
|
201
|
+
return;
|
|
137
202
|
|
|
138
203
|
} else if (options.cleanupOnly) {
|
|
139
204
|
// Only cleanup duplicate roles
|
|
@@ -143,117 +208,147 @@ async function main() {
|
|
|
143
208
|
|
|
144
209
|
console.log(chalk.green(`\n✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
145
210
|
|
|
146
|
-
|
|
147
|
-
console.log(chalk.cyan('\n💡 This was a dry run. Use without --dry-run to apply changes.'));
|
|
148
|
-
} else {
|
|
149
|
-
console.log(chalk.green('\n🎉 Cleanup completed successfully!'));
|
|
150
|
-
}
|
|
211
|
+
showCompletionMessage(options, 'Cleanup');
|
|
151
212
|
return;
|
|
152
213
|
|
|
153
214
|
} else if (options.altOnly) {
|
|
154
|
-
//
|
|
155
|
-
console.log(chalk.blue('🖼️ Running alt attribute fixes
|
|
215
|
+
// Fix alt attributes + cleanup
|
|
216
|
+
console.log(chalk.blue('🖼️ Running alt attribute fixes + cleanup...'));
|
|
156
217
|
const altResults = await fixer.fixEmptyAltAttributes(options.directory);
|
|
157
218
|
const altFixed = altResults.filter(r => r.status === 'fixed').length;
|
|
158
219
|
const totalAltIssues = altResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
159
220
|
|
|
160
221
|
console.log(chalk.green(`\n✅ Fixed alt attributes in ${altFixed} files (${totalAltIssues} issues)`));
|
|
161
222
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
223
|
+
// Run cleanup
|
|
224
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
225
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
226
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
227
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
228
|
+
|
|
229
|
+
showCompletionMessage(options, 'Alt attribute fixes + cleanup');
|
|
167
230
|
return;
|
|
168
231
|
|
|
169
232
|
} else if (options.langOnly) {
|
|
170
|
-
//
|
|
171
|
-
console.log(chalk.blue('📝 Running HTML lang attribute fixes
|
|
233
|
+
// Fix lang attributes + cleanup
|
|
234
|
+
console.log(chalk.blue('📝 Running HTML lang attribute fixes + cleanup...'));
|
|
172
235
|
const langResults = await fixer.fixHtmlLang(options.directory);
|
|
173
236
|
const langFixed = langResults.filter(r => r.status === 'fixed').length;
|
|
174
237
|
|
|
175
238
|
console.log(chalk.green(`\n✅ Fixed lang attributes in ${langFixed} files`));
|
|
176
239
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
240
|
+
// Run cleanup
|
|
241
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
242
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
243
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
244
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
245
|
+
|
|
246
|
+
showCompletionMessage(options, 'Lang attribute fixes + cleanup');
|
|
182
247
|
return;
|
|
183
248
|
|
|
184
249
|
} else if (options.roleOnly) {
|
|
185
|
-
//
|
|
186
|
-
console.log(chalk.blue('🎭 Running role attribute fixes
|
|
250
|
+
// Fix role attributes + cleanup
|
|
251
|
+
console.log(chalk.blue('🎭 Running role attribute fixes + cleanup...'));
|
|
187
252
|
const roleResults = await fixer.fixRoleAttributes(options.directory);
|
|
188
253
|
const roleFixed = roleResults.filter(r => r.status === 'fixed').length;
|
|
189
254
|
const totalRoleIssues = roleResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
190
255
|
|
|
191
256
|
console.log(chalk.green(`\n✅ Fixed role attributes in ${roleFixed} files (${totalRoleIssues} issues)`));
|
|
192
257
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
258
|
+
// Run cleanup
|
|
259
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
260
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
261
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
262
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
263
|
+
|
|
264
|
+
showCompletionMessage(options, 'Role attribute fixes + cleanup');
|
|
265
|
+
return;
|
|
266
|
+
|
|
267
|
+
} else if (options.formsOnly) {
|
|
268
|
+
// Fix form labels + cleanup
|
|
269
|
+
console.log(chalk.blue('📋 Running form label fixes + cleanup...'));
|
|
270
|
+
const formResults = await fixer.fixFormLabels(options.directory);
|
|
271
|
+
const formFixed = formResults.filter(r => r.status === 'fixed').length;
|
|
272
|
+
const totalFormIssues = formResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
273
|
+
|
|
274
|
+
console.log(chalk.green(`\n✅ Fixed form labels in ${formFixed} files (${totalFormIssues} issues)`));
|
|
275
|
+
|
|
276
|
+
// Run cleanup
|
|
277
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
278
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
279
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
280
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
281
|
+
|
|
282
|
+
showCompletionMessage(options, 'Form label fixes + cleanup');
|
|
283
|
+
return;
|
|
284
|
+
|
|
285
|
+
} else if (options.buttonsOnly) {
|
|
286
|
+
// Fix button names + cleanup
|
|
287
|
+
console.log(chalk.blue('🔘 Running button name fixes + cleanup...'));
|
|
288
|
+
const buttonResults = await fixer.fixButtonNames(options.directory);
|
|
289
|
+
const buttonFixed = buttonResults.filter(r => r.status === 'fixed').length;
|
|
290
|
+
const totalButtonIssues = buttonResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
291
|
+
|
|
292
|
+
console.log(chalk.green(`\n✅ Fixed button names in ${buttonFixed} files (${totalButtonIssues} issues)`));
|
|
293
|
+
|
|
294
|
+
// Run cleanup
|
|
295
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
296
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
297
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
298
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
299
|
+
|
|
300
|
+
showCompletionMessage(options, 'Button name fixes + cleanup');
|
|
301
|
+
return;
|
|
302
|
+
|
|
303
|
+
} else if (options.linksOnly) {
|
|
304
|
+
// Fix link names + cleanup
|
|
305
|
+
console.log(chalk.blue('🔗 Running link name fixes + cleanup...'));
|
|
306
|
+
const linkResults = await fixer.fixLinkNames(options.directory);
|
|
307
|
+
const linkFixed = linkResults.filter(r => r.status === 'fixed').length;
|
|
308
|
+
const totalLinkIssues = linkResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
309
|
+
|
|
310
|
+
console.log(chalk.green(`\n✅ Fixed link names in ${linkFixed} files (${totalLinkIssues} issues)`));
|
|
311
|
+
|
|
312
|
+
// Run cleanup
|
|
313
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
314
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
315
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
316
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
317
|
+
|
|
318
|
+
showCompletionMessage(options, 'Link name fixes + cleanup');
|
|
319
|
+
return;
|
|
320
|
+
|
|
321
|
+
} else if (options.landmarksOnly) {
|
|
322
|
+
// Fix landmarks + cleanup
|
|
323
|
+
console.log(chalk.blue('🏛️ Running landmark fixes + cleanup...'));
|
|
324
|
+
const landmarkResults = await fixer.fixLandmarks(options.directory);
|
|
325
|
+
const landmarkFixed = landmarkResults.filter(r => r.status === 'fixed').length;
|
|
326
|
+
const totalLandmarkIssues = landmarkResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
327
|
+
|
|
328
|
+
console.log(chalk.green(`\n✅ Fixed landmarks in ${landmarkFixed} files (${totalLandmarkIssues} issues)`));
|
|
329
|
+
|
|
330
|
+
// Run cleanup
|
|
331
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
332
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
333
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
334
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
335
|
+
|
|
336
|
+
showCompletionMessage(options, 'Landmark fixes + cleanup');
|
|
337
|
+
return;
|
|
338
|
+
|
|
339
|
+
} else if (options.headingsOnly) {
|
|
340
|
+
// Analyze headings only (no fixes, no cleanup)
|
|
341
|
+
console.log(chalk.blue('📑 Running heading analysis only...'));
|
|
342
|
+
const headingResults = await fixer.analyzeHeadings(options.directory);
|
|
343
|
+
const totalSuggestions = headingResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
344
|
+
|
|
345
|
+
console.log(chalk.green(`\n✅ Analyzed headings in ${headingResults.length} files (${totalSuggestions} suggestions)`));
|
|
346
|
+
console.log(chalk.gray('💡 Heading issues require manual review and cannot be auto-fixed'));
|
|
347
|
+
|
|
348
|
+
showCompletionMessage(options, 'Heading analysis');
|
|
198
349
|
return;
|
|
199
350
|
}
|
|
200
351
|
|
|
201
|
-
// Standard mode - run individual fixes
|
|
202
|
-
// Fix HTML lang attributes
|
|
203
|
-
console.log(chalk.yellow('📝 Step 1: Fixing HTML lang attributes...'));
|
|
204
|
-
const langResults = await fixer.fixHtmlLang(options.directory);
|
|
205
|
-
const langFixed = langResults.filter(r => r.status === 'fixed').length;
|
|
206
|
-
console.log(chalk.green(`✅ Fixed lang attributes in ${langFixed} files`));
|
|
207
|
-
console.log('');
|
|
208
|
-
|
|
209
|
-
// Fix alt attributes
|
|
210
|
-
console.log(chalk.yellow('🖼️ Step 2: Fixing alt attributes...'));
|
|
211
|
-
const altResults = await fixer.fixEmptyAltAttributes(options.directory);
|
|
212
|
-
const altFixed = altResults.filter(r => r.status === 'fixed').length;
|
|
213
|
-
const totalAltIssues = altResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
214
|
-
console.log(chalk.green(`✅ Fixed alt attributes in ${altFixed} files (${totalAltIssues} issues)`));
|
|
215
|
-
console.log('');
|
|
216
|
-
|
|
217
|
-
// Fix role attributes
|
|
218
|
-
console.log(chalk.yellow('🎭 Step 3: Fixing role attributes...'));
|
|
219
|
-
const roleResults = await fixer.fixRoleAttributes(options.directory);
|
|
220
|
-
const roleFixed = roleResults.filter(r => r.status === 'fixed').length;
|
|
221
|
-
const totalRoleIssues = roleResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
222
|
-
console.log(chalk.green(`✅ Fixed role attributes in ${roleFixed} files (${totalRoleIssues} issues)`));
|
|
223
|
-
console.log('');
|
|
224
|
-
|
|
225
|
-
// Summary
|
|
226
|
-
const totalFiles = new Set([
|
|
227
|
-
...langResults.map(r => r.file),
|
|
228
|
-
...altResults.map(r => r.file),
|
|
229
|
-
...roleResults.map(r => r.file)
|
|
230
|
-
]).size;
|
|
231
|
-
|
|
232
|
-
const totalFixed = new Set([
|
|
233
|
-
...langResults.filter(r => r.status === 'fixed').map(r => r.file),
|
|
234
|
-
...altResults.filter(r => r.status === 'fixed').map(r => r.file),
|
|
235
|
-
...roleResults.filter(r => r.status === 'fixed').map(r => r.file)
|
|
236
|
-
]).size;
|
|
237
|
-
|
|
238
|
-
const totalIssues = totalAltIssues + totalRoleIssues + langFixed;
|
|
239
|
-
|
|
240
|
-
console.log(chalk.blue('📊 Summary:'));
|
|
241
|
-
console.log(chalk.white(` Total files scanned: ${totalFiles}`));
|
|
242
|
-
console.log(chalk.green(` Files fixed: ${totalFixed}`));
|
|
243
|
-
console.log(chalk.yellow(` Total issues resolved: ${totalIssues}`));
|
|
244
|
-
|
|
245
|
-
if (options.dryRun) {
|
|
246
|
-
console.log(chalk.cyan('\n💡 This was a dry run. Use without --dry-run to apply changes.'));
|
|
247
|
-
} else {
|
|
248
|
-
console.log(chalk.green('\n🎉 All accessibility fixes completed successfully!'));
|
|
249
|
-
if (options.backupFiles) {
|
|
250
|
-
console.log(chalk.gray(' Backup files created with .backup extension'));
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Suggest cleanup if not comprehensive mode
|
|
255
|
-
console.log(chalk.blue('\n💡 Pro tip: Use --comprehensive to include duplicate role cleanup!'));
|
|
256
|
-
|
|
257
352
|
} catch (error) {
|
|
258
353
|
console.error(chalk.red('❌ Error occurred:'), error.message);
|
|
259
354
|
process.exit(1);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Advanced Accessibility Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Advanced Accessibility Test</h1>
|
|
9
|
+
|
|
10
|
+
<!-- Form issues -->
|
|
11
|
+
<form>
|
|
12
|
+
<input type="text" placeholder="Name">
|
|
13
|
+
<input type="email" id="email">
|
|
14
|
+
<input type="password">
|
|
15
|
+
<input type="submit">
|
|
16
|
+
</form>
|
|
17
|
+
|
|
18
|
+
<!-- Button issues -->
|
|
19
|
+
<button></button>
|
|
20
|
+
<button onclick="alert('test')"></button>
|
|
21
|
+
<input type="button">
|
|
22
|
+
|
|
23
|
+
<!-- Link issues -->
|
|
24
|
+
<a href="/home"></a>
|
|
25
|
+
<a href="/more">Click here</a>
|
|
26
|
+
<a href="/read">Read more</a>
|
|
27
|
+
<a href="/image"><img src="icon.png"></a>
|
|
28
|
+
|
|
29
|
+
<!-- Heading issues -->
|
|
30
|
+
<h3>Skipped h2</h3>
|
|
31
|
+
<h1>Second h1</h1>
|
|
32
|
+
<h4></h4>
|
|
33
|
+
|
|
34
|
+
<!-- Landmark issues -->
|
|
35
|
+
<div class="content">
|
|
36
|
+
<p>Main content without landmark</p>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<ul class="navigation">
|
|
40
|
+
<li><a href="/home">Home</a></li>
|
|
41
|
+
<li><a href="/about">About</a></li>
|
|
42
|
+
</ul>
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Advanced Accessibility Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Advanced Accessibility Test</h1>
|
|
9
|
+
|
|
10
|
+
<!-- Form issues -->
|
|
11
|
+
<form>
|
|
12
|
+
<input type="text" placeholder="Name">
|
|
13
|
+
<input type="email" id="email">
|
|
14
|
+
<input type="password">
|
|
15
|
+
<input type="submit">
|
|
16
|
+
</form>
|
|
17
|
+
|
|
18
|
+
<!-- Button issues -->
|
|
19
|
+
<button></button>
|
|
20
|
+
<button onclick="alert('test')"></button>
|
|
21
|
+
<input type="button">
|
|
22
|
+
|
|
23
|
+
<!-- Link issues -->
|
|
24
|
+
<a href="/home"></a>
|
|
25
|
+
<a href="/more">Click here</a>
|
|
26
|
+
<a href="/read">Read more</a>
|
|
27
|
+
<a href="/image"><img src="icon.png"></a>
|
|
28
|
+
|
|
29
|
+
<!-- Heading issues -->
|
|
30
|
+
<h3>Skipped h2</h3>
|
|
31
|
+
<h1>Second h1</h1>
|
|
32
|
+
<h4></h4>
|
|
33
|
+
|
|
34
|
+
<!-- Landmark issues -->
|
|
35
|
+
<div class="content">
|
|
36
|
+
<p>Main content without landmark</p>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<ul class="navigation">
|
|
40
|
+
<li><a href="/home">Home</a></li>
|
|
41
|
+
<li><a href="/about">About</a></li>
|
|
42
|
+
</ul>
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="ja">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Aria Label Test</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>Aria Label Test Cases</h1>
|
|
10
|
+
|
|
11
|
+
<!-- Test case 1: Image with alt but no aria-label -->
|
|
12
|
+
<img src="test1.jpg" alt="Test image 1" role="img" aria-label="Test image 1">
|
|
13
|
+
|
|
14
|
+
<!-- Test case 2: Image with alt and existing aria-label (should not change) -->
|
|
15
|
+
<img src="test2.jpg" alt="Test image 2" aria-label="Custom label" role="img">
|
|
16
|
+
|
|
17
|
+
<!-- Test case 3: Image with empty alt (should not add aria-label) -->
|
|
18
|
+
<img src="test3.jpg" alt="" role="img">
|
|
19
|
+
|
|
20
|
+
<!-- Test case 4: Image without alt (should generate alt and aria-label) -->
|
|
21
|
+
<img src="logo.png" role="img">
|
|
22
|
+
|
|
23
|
+
<!-- Test case 5: Picture with role and img with alt -->
|
|
24
|
+
<picture>
|
|
25
|
+
<source srcset="responsive.webp" type="image/webp">
|
|
26
|
+
<img src="responsive.jpg" alt="Responsive image" role="img" aria-label="Responsive image">
|
|
27
|
+
</picture>
|
|
28
|
+
|
|
29
|
+
<!-- Test case 6: Image with role but no aria-label -->
|
|
30
|
+
<img src="test6.jpg" alt="Test image 6" role="img" aria-label="Test image 6">
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Backup Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Backup Test File</h1>
|
|
9
|
+
|
|
10
|
+
<!-- This will be fixed -->
|
|
11
|
+
<img src="test.jpg" alt="Test image" role="img" aria-label="Test image">
|
|
12
|
+
|
|
13
|
+
<!-- This will also be fixed -->
|
|
14
|
+
<a href="/home" role="link">Home Link</a>
|
|
15
|
+
|
|
16
|
+
<p>This file is used to test backup functionality.</p>
|
|
17
|
+
</body>
|
|
18
|
+
</html>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>No Backup Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>No Backup Test File</h1>
|
|
9
|
+
|
|
10
|
+
<img src="test2.jpg" alt="Test image 2" role="img" aria-label="Test image 2">
|
|
11
|
+
<a href="/about" role="link">About Link</a>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Explicit Backup Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Explicit Backup Test File</h1>
|
|
9
|
+
|
|
10
|
+
<img src="test3.jpg" alt="Test image 3" role="img" aria-label="Test image 3">
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Comprehensive Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Comprehensive Test File</h1>
|
|
9
|
+
|
|
10
|
+
<!-- Missing alt -->
|
|
11
|
+
<img src="test.jpg">
|
|
12
|
+
|
|
13
|
+
<!-- Missing role -->
|
|
14
|
+
<a href="/home">Home</a>
|
|
15
|
+
|
|
16
|
+
<!-- Duplicate roles -->
|
|
17
|
+
<img src="dup.jpg" alt="Duplicate" role="img" role="img">
|
|
18
|
+
|
|
19
|
+
<p>This tests comprehensive mode as default.</p>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Comprehensive Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Comprehensive Test File</h1>
|
|
9
|
+
|
|
10
|
+
<!-- Missing alt -->
|
|
11
|
+
<img src="test.jpg">
|
|
12
|
+
|
|
13
|
+
<!-- Missing role -->
|
|
14
|
+
<a href="/home">Home</a>
|
|
15
|
+
|
|
16
|
+
<!-- Duplicate roles -->
|
|
17
|
+
<img src="dup.jpg" alt="Duplicate" role="img" role="img">
|
|
18
|
+
|
|
19
|
+
<p>This tests comprehensive mode as default.</p>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|