gbu-accessibility-package 1.5.0 โ 1.6.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 +83 -36
- package/cli.js +28 -30
- 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/lib/fixer.js +47 -8
- package/package.json +3 -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/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
## โจ Features
|
|
10
10
|
|
|
11
11
|
- ๐ผ๏ธ **Smart Alt Text Generation** - Context-aware alt attributes for images
|
|
12
|
+
- ๐ท๏ธ **Aria Label Support** - Automatic aria-label matching alt text
|
|
12
13
|
- ๐ **HTML Lang Attributes** - Automatic language attribute fixes
|
|
13
14
|
- ๐ญ **Role Attributes** - WCAG-compliant role attribute management
|
|
14
15
|
- ๐งน **Duplicate Cleanup** - Remove duplicate role attributes
|
|
@@ -58,6 +59,7 @@ gbu-a11y [options] [directory/file]
|
|
|
58
59
|
Options:
|
|
59
60
|
-d, --directory <path> Target directory (default: current directory)
|
|
60
61
|
-l, --language <lang> Language for lang attribute (default: ja)
|
|
62
|
+
--backup Create backup files (default: enabled)
|
|
61
63
|
--no-backup Don't create backup files
|
|
62
64
|
--dry-run Preview changes without applying
|
|
63
65
|
--comprehensive, --all Run all fixes including cleanup (recommended)
|
|
@@ -82,7 +84,7 @@ gbu-a11y -l en ./public
|
|
|
82
84
|
|
|
83
85
|
# Individual fix types
|
|
84
86
|
gbu-a11y --alt-only # Only fix alt attributes
|
|
85
|
-
gbu-a11y --lang-only # Only fix lang attributes
|
|
87
|
+
gbu-a11y --lang-only # Only fix lang attributes
|
|
86
88
|
gbu-a11y --role-only # Only fix role attributes
|
|
87
89
|
gbu-a11y --cleanup-only # Only cleanup duplicates
|
|
88
90
|
|
|
@@ -90,28 +92,29 @@ gbu-a11y --cleanup-only # Only cleanup duplicates
|
|
|
90
92
|
gbu-a11y --alt-only --dry-run ./src # Preview alt fixes only
|
|
91
93
|
gbu-a11y --role-only -l en ./public # Fix roles with English lang
|
|
92
94
|
|
|
93
|
-
#
|
|
94
|
-
gbu-a11y --
|
|
95
|
+
# Backup options
|
|
96
|
+
gbu-a11y --backup ./dist # Explicitly enable backups (default)
|
|
97
|
+
gbu-a11y --no-backup ./dist # Disable backups for faster processing
|
|
95
98
|
```
|
|
96
99
|
|
|
97
100
|
## ๐ง Programmatic Usage
|
|
98
101
|
|
|
99
102
|
```javascript
|
|
100
|
-
const AccessibilityFixer = require(
|
|
103
|
+
const AccessibilityFixer = require("gbu-accessibility-package");
|
|
101
104
|
|
|
102
105
|
const fixer = new AccessibilityFixer({
|
|
103
|
-
language:
|
|
106
|
+
language: "en",
|
|
104
107
|
backupFiles: true,
|
|
105
|
-
dryRun: false
|
|
108
|
+
dryRun: false,
|
|
106
109
|
});
|
|
107
110
|
|
|
108
111
|
// Fix all accessibility issues
|
|
109
112
|
async function fixAccessibility() {
|
|
110
113
|
try {
|
|
111
|
-
const results = await fixer.fixAllAccessibilityIssues(
|
|
112
|
-
console.log(
|
|
114
|
+
const results = await fixer.fixAllAccessibilityIssues("./src");
|
|
115
|
+
console.log("Fixed files:", results);
|
|
113
116
|
} catch (error) {
|
|
114
|
-
console.error(
|
|
117
|
+
console.error("Error:", error);
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
|
|
@@ -121,14 +124,16 @@ fixAccessibility();
|
|
|
121
124
|
## ๐ฏ Fix Modes
|
|
122
125
|
|
|
123
126
|
### Individual Fix Options
|
|
127
|
+
|
|
124
128
|
You can now fix specific accessibility issues individually:
|
|
125
129
|
|
|
126
130
|
- `--alt-only` - Only fix alt attributes for images
|
|
127
|
-
- `--lang-only` - Only fix HTML lang attributes
|
|
131
|
+
- `--lang-only` - Only fix HTML lang attributes
|
|
128
132
|
- `--role-only` - Only fix role attributes
|
|
129
133
|
- `--cleanup-only` - Only cleanup duplicate role attributes
|
|
130
134
|
|
|
131
135
|
### Combined Modes
|
|
136
|
+
|
|
132
137
|
- **Standard mode** (default) - Fixes alt, lang, and role attributes
|
|
133
138
|
- `--comprehensive` - All fixes including duplicate cleanup
|
|
134
139
|
|
|
@@ -152,36 +157,41 @@ gbu-a11y --comprehensive
|
|
|
152
157
|
## ๐ง What Gets Fixed
|
|
153
158
|
|
|
154
159
|
### 1. Alt Attributes
|
|
160
|
+
|
|
155
161
|
- **Missing alt attributes** โ Adds contextual alt text
|
|
156
162
|
- **Empty alt attributes** โ Generates meaningful descriptions
|
|
157
163
|
- **Context-aware generation** โ Uses surrounding text, headings, captions
|
|
158
164
|
|
|
159
165
|
```html
|
|
160
166
|
<!-- Before -->
|
|
161
|
-
<img src="logo.png"
|
|
162
|
-
<img src="chart.jpg" alt=""
|
|
167
|
+
<img src="logo.png" />
|
|
168
|
+
<img src="chart.jpg" alt="" />
|
|
163
169
|
|
|
164
170
|
<!-- After -->
|
|
165
|
-
<img src="logo.png" alt="ใญใด"
|
|
166
|
-
<img src="chart.jpg" alt="ใฐใฉใ"
|
|
171
|
+
<img src="logo.png" alt="ใญใด" />
|
|
172
|
+
<img src="chart.jpg" alt="ใฐใฉใ" />
|
|
167
173
|
```
|
|
168
174
|
|
|
169
175
|
### 2. HTML Lang Attributes
|
|
176
|
+
|
|
170
177
|
- **Missing lang attributes** โ Adds specified language
|
|
171
178
|
- **Empty lang attributes** โ Sets proper language code
|
|
172
179
|
|
|
173
180
|
```html
|
|
174
181
|
<!-- Before -->
|
|
175
182
|
<html>
|
|
176
|
-
<html lang="">
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
<html lang="ja">
|
|
180
|
-
|
|
183
|
+
<html lang="">
|
|
184
|
+
<!-- After -->
|
|
185
|
+
<html lang="ja">
|
|
186
|
+
<html lang="ja"></html>
|
|
187
|
+
</html>
|
|
188
|
+
</html>
|
|
189
|
+
</html>
|
|
181
190
|
```
|
|
182
191
|
|
|
183
|
-
### 3. Role Attributes
|
|
184
|
-
|
|
192
|
+
### 3. Role Attributes & Aria Labels
|
|
193
|
+
|
|
194
|
+
- **Images** โ `role="img"` + `aria-label` (matching alt text)
|
|
185
195
|
- **Picture elements** โ Moves `role="img"` from `<picture>` to `<img>` inside
|
|
186
196
|
- **Links** โ `role="link"`
|
|
187
197
|
- **Clickable elements** โ `role="button"`
|
|
@@ -190,33 +200,48 @@ gbu-a11y --comprehensive
|
|
|
190
200
|
|
|
191
201
|
```html
|
|
192
202
|
<!-- Before -->
|
|
193
|
-
<img src="icon.png" alt="Icon"
|
|
203
|
+
<img src="icon.png" alt="Icon" />
|
|
194
204
|
<picture role="img">
|
|
195
|
-
<img src="photo.jpg" alt="Photo"
|
|
205
|
+
<img src="photo.jpg" alt="Photo" />
|
|
196
206
|
</picture>
|
|
197
207
|
<a href="/home">Home</a>
|
|
198
208
|
<div class="btn-click">Click me</div>
|
|
199
209
|
|
|
200
210
|
<!-- After -->
|
|
201
|
-
<img src="icon.png" alt="Icon" role="img"
|
|
211
|
+
<img src="icon.png" alt="Icon" role="img" aria-label="Icon" />
|
|
202
212
|
<picture>
|
|
203
|
-
<img src="photo.jpg" alt="Photo" role="img"
|
|
213
|
+
<img src="photo.jpg" alt="Photo" role="img" aria-label="Photo" />
|
|
204
214
|
</picture>
|
|
205
215
|
<a href="/home" role="link">Home</a>
|
|
206
216
|
<div class="btn-click" role="button">Click me</div>
|
|
207
217
|
```
|
|
208
218
|
|
|
209
|
-
### 4.
|
|
219
|
+
### 4. Aria Label Enhancement
|
|
220
|
+
|
|
221
|
+
- **Automatic aria-label** โ Adds `aria-label` matching `alt` text for images
|
|
222
|
+
- **Preserves existing** โ Won't override existing `aria-label` attributes
|
|
223
|
+
- **Smart detection** โ Only adds when `alt` text exists and is not empty
|
|
224
|
+
|
|
225
|
+
```html
|
|
226
|
+
<!-- Before -->
|
|
227
|
+
<img src="chart.jpg" alt="Sales Chart" />
|
|
228
|
+
|
|
229
|
+
<!-- After -->
|
|
230
|
+
<img src="chart.jpg" alt="Sales Chart" role="img" aria-label="Sales Chart" />
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### 5. Duplicate Cleanup
|
|
234
|
+
|
|
210
235
|
- **Removes duplicate role attributes**
|
|
211
236
|
- **Preserves first occurrence**
|
|
212
237
|
- **Handles mixed quote styles**
|
|
213
238
|
|
|
214
239
|
```html
|
|
215
240
|
<!-- Before -->
|
|
216
|
-
<img src="test.jpg" role="img" role="img" alt="Test"
|
|
241
|
+
<img src="test.jpg" role="img" role="img" alt="Test" />
|
|
217
242
|
|
|
218
243
|
<!-- After -->
|
|
219
|
-
<img src="test.jpg" role="img" alt="Test"
|
|
244
|
+
<img src="test.jpg" role="img" alt="Test" />
|
|
220
245
|
```
|
|
221
246
|
|
|
222
247
|
## ๐ Smart Alt Text Generation
|
|
@@ -224,8 +249,9 @@ gbu-a11y --comprehensive
|
|
|
224
249
|
The package uses intelligent context analysis to generate meaningful alt text:
|
|
225
250
|
|
|
226
251
|
### Context Sources
|
|
252
|
+
|
|
227
253
|
1. **Title attributes**
|
|
228
|
-
2. **Aria-label attributes**
|
|
254
|
+
2. **Aria-label attributes**
|
|
229
255
|
3. **Definition terms (dt elements)**
|
|
230
256
|
4. **Parent link text**
|
|
231
257
|
5. **Nearby headings**
|
|
@@ -233,6 +259,7 @@ The package uses intelligent context analysis to generate meaningful alt text:
|
|
|
233
259
|
7. **Surrounding text content**
|
|
234
260
|
|
|
235
261
|
### Fallback Patterns
|
|
262
|
+
|
|
236
263
|
- `logo.png` โ "ใญใด" (Logo)
|
|
237
264
|
- `icon.svg` โ "ใขใคใณใณ" (Icon)
|
|
238
265
|
- `banner.jpg` โ "ใใใผ" (Banner)
|
|
@@ -242,6 +269,7 @@ The package uses intelligent context analysis to generate meaningful alt text:
|
|
|
242
269
|
## ๐ Output Examples
|
|
243
270
|
|
|
244
271
|
### Standard Mode
|
|
272
|
+
|
|
245
273
|
```
|
|
246
274
|
๐ Starting Accessibility Fixer...
|
|
247
275
|
๐ Step 1: Fixing HTML lang attributes...
|
|
@@ -250,7 +278,7 @@ The package uses intelligent context analysis to generate meaningful alt text:
|
|
|
250
278
|
๐ผ๏ธ Step 2: Fixing alt attributes...
|
|
251
279
|
โ
Fixed alt attributes in 12 files (34 issues)
|
|
252
280
|
|
|
253
|
-
๐ญ Step 3: Fixing role attributes...
|
|
281
|
+
๐ญ Step 3: Fixing role attributes...
|
|
254
282
|
โ
Fixed role attributes in 8 files (67 issues)
|
|
255
283
|
|
|
256
284
|
๐ Summary:
|
|
@@ -262,6 +290,7 @@ The package uses intelligent context analysis to generate meaningful alt text:
|
|
|
262
290
|
```
|
|
263
291
|
|
|
264
292
|
### Comprehensive Mode
|
|
293
|
+
|
|
265
294
|
```
|
|
266
295
|
๐ฏ Running comprehensive accessibility fixes...
|
|
267
296
|
๐ Step 1: HTML lang attributes...
|
|
@@ -272,14 +301,30 @@ The package uses intelligent context analysis to generate meaningful alt text:
|
|
|
272
301
|
๐ All accessibility fixes completed!
|
|
273
302
|
๐ Final Summary:
|
|
274
303
|
Total files scanned: 25
|
|
275
|
-
Files fixed: 15
|
|
304
|
+
Files fixed: 15
|
|
276
305
|
Total issues resolved: 106
|
|
277
306
|
```
|
|
278
307
|
|
|
279
308
|
## ๐ Safety Features
|
|
280
309
|
|
|
281
|
-
|
|
282
|
-
- **
|
|
310
|
+
### Backup Options
|
|
311
|
+
- **Default behavior**: Creates `.backup` files automatically for safety
|
|
312
|
+
- **Disable backups**: Use `--no-backup` for faster processing
|
|
313
|
+
- **Explicit enable**: Use `--backup` to be explicit about backup creation
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
# Safe mode (default) - creates backups
|
|
317
|
+
gbu-a11y --comprehensive
|
|
318
|
+
|
|
319
|
+
# Fast mode - no backups
|
|
320
|
+
gbu-a11y --no-backup --comprehensive
|
|
321
|
+
|
|
322
|
+
# Explicit backup mode
|
|
323
|
+
gbu-a11y --backup --comprehensive
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Other Safety Features
|
|
327
|
+
- **Dry run mode** for safe previewing with `--dry-run`
|
|
283
328
|
- **Non-destructive** - only adds missing attributes
|
|
284
329
|
- **Duplicate prevention** - won't add existing attributes
|
|
285
330
|
- **Error handling** - continues processing on individual file errors
|
|
@@ -287,6 +332,7 @@ The package uses intelligent context analysis to generate meaningful alt text:
|
|
|
287
332
|
## ๐ ๏ธ Configuration
|
|
288
333
|
|
|
289
334
|
### Package.json Scripts
|
|
335
|
+
|
|
290
336
|
```json
|
|
291
337
|
{
|
|
292
338
|
"scripts": {
|
|
@@ -295,19 +341,20 @@ The package uses intelligent context analysis to generate meaningful alt text:
|
|
|
295
341
|
"a11y:comprehensive": "gbu-a11y --comprehensive",
|
|
296
342
|
"a11y:cleanup": "gbu-a11y --cleanup-only",
|
|
297
343
|
"a11y:alt": "gbu-a11y --alt-only",
|
|
298
|
-
"a11y:lang": "gbu-a11y --lang-only",
|
|
344
|
+
"a11y:lang": "gbu-a11y --lang-only",
|
|
299
345
|
"a11y:role": "gbu-a11y --role-only"
|
|
300
346
|
}
|
|
301
347
|
}
|
|
302
348
|
```
|
|
303
349
|
|
|
304
350
|
### CI/CD Integration
|
|
351
|
+
|
|
305
352
|
```yaml
|
|
306
353
|
# GitHub Actions example
|
|
307
354
|
- name: Check Accessibility
|
|
308
355
|
run: npx gbu-accessibility-package --dry-run
|
|
309
356
|
|
|
310
|
-
- name: Fix Accessibility Issues
|
|
357
|
+
- name: Fix Accessibility Issues
|
|
311
358
|
run: npx gbu-accessibility-package --comprehensive
|
|
312
359
|
```
|
|
313
360
|
|
|
@@ -340,4 +387,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
|
340
387
|
|
|
341
388
|
---
|
|
342
389
|
|
|
343
|
-
Made with โค๏ธ by the GBU Team
|
|
390
|
+
Made with โค๏ธ by the GBU Team
|
package/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ 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,
|
|
@@ -41,6 +41,9 @@ for (let i = 0; i < args.length; i++) {
|
|
|
41
41
|
case '-l':
|
|
42
42
|
options.language = args[++i];
|
|
43
43
|
break;
|
|
44
|
+
case '--backup':
|
|
45
|
+
options.backupFiles = true;
|
|
46
|
+
break;
|
|
44
47
|
case '--no-backup':
|
|
45
48
|
options.backupFiles = false;
|
|
46
49
|
break;
|
|
@@ -80,6 +83,7 @@ Usage: node cli.js [options] [directory]
|
|
|
80
83
|
Options:
|
|
81
84
|
-d, --directory <path> Target directory (default: current directory)
|
|
82
85
|
-l, --language <lang> Language for lang attribute (default: ja)
|
|
86
|
+
--backup Create backup files (default: enabled)
|
|
83
87
|
--no-backup Don't create backup files
|
|
84
88
|
--dry-run Preview changes without applying
|
|
85
89
|
--comprehensive, --all Run all fixes including cleanup (recommended)
|
|
@@ -90,7 +94,7 @@ Options:
|
|
|
90
94
|
-h, --help Show this help message
|
|
91
95
|
|
|
92
96
|
Examples:
|
|
93
|
-
node cli.js # Fix current directory (
|
|
97
|
+
node cli.js # Fix current directory (with backups)
|
|
94
98
|
node cli.js --comprehensive # Run all fixes including cleanup
|
|
95
99
|
node cli.js --alt-only # Only fix alt attributes
|
|
96
100
|
node cli.js --lang-only # Only fix lang attributes
|
|
@@ -99,6 +103,7 @@ Examples:
|
|
|
99
103
|
node cli.js ./src # Fix src directory
|
|
100
104
|
node cli.js -l en --dry-run ./dist # Preview fixes for dist directory in English
|
|
101
105
|
node cli.js --no-backup ./public # Fix without creating backups
|
|
106
|
+
node cli.js --backup --comprehensive # Explicitly enable backups with all fixes
|
|
102
107
|
|
|
103
108
|
Features:
|
|
104
109
|
โ
Alt attributes for images
|
|
@@ -110,6 +115,22 @@ Features:
|
|
|
110
115
|
process.exit(0);
|
|
111
116
|
}
|
|
112
117
|
|
|
118
|
+
// Helper function to show completion message with backup info
|
|
119
|
+
function showCompletionMessage(options, mode = 'fixes') {
|
|
120
|
+
if (options.dryRun) {
|
|
121
|
+
console.log(chalk.cyan('\n๐ก This was a dry run. Use without --dry-run to apply changes.'));
|
|
122
|
+
} else {
|
|
123
|
+
console.log(chalk.green(`\n๐ ${mode} completed successfully!`));
|
|
124
|
+
if (options.backupFiles) {
|
|
125
|
+
console.log(chalk.gray(' ๐ Backup files created with .backup extension'));
|
|
126
|
+
console.log(chalk.gray(' ๐ก Use --no-backup to disable backups in future runs'));
|
|
127
|
+
} else {
|
|
128
|
+
console.log(chalk.yellow(' โ ๏ธ No backup files created (--no-backup was used)'));
|
|
129
|
+
console.log(chalk.gray(' ๐ก Use --backup to enable backups for safety'));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
113
134
|
// Main function
|
|
114
135
|
async function main() {
|
|
115
136
|
console.log(chalk.blue('๐ Starting Accessibility Fixer...'));
|
|
@@ -143,11 +164,7 @@ async function main() {
|
|
|
143
164
|
|
|
144
165
|
console.log(chalk.green(`\nโ
Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
145
166
|
|
|
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
|
-
}
|
|
167
|
+
showCompletionMessage(options, 'Cleanup');
|
|
151
168
|
return;
|
|
152
169
|
|
|
153
170
|
} else if (options.altOnly) {
|
|
@@ -159,11 +176,7 @@ async function main() {
|
|
|
159
176
|
|
|
160
177
|
console.log(chalk.green(`\nโ
Fixed alt attributes in ${altFixed} files (${totalAltIssues} issues)`));
|
|
161
178
|
|
|
162
|
-
|
|
163
|
-
console.log(chalk.cyan('\n๐ก This was a dry run. Use without --dry-run to apply changes.'));
|
|
164
|
-
} else {
|
|
165
|
-
console.log(chalk.green('\n๐ Alt attribute fixes completed successfully!'));
|
|
166
|
-
}
|
|
179
|
+
showCompletionMessage(options, 'Alt attribute fixes');
|
|
167
180
|
return;
|
|
168
181
|
|
|
169
182
|
} else if (options.langOnly) {
|
|
@@ -174,11 +187,7 @@ async function main() {
|
|
|
174
187
|
|
|
175
188
|
console.log(chalk.green(`\nโ
Fixed lang attributes in ${langFixed} files`));
|
|
176
189
|
|
|
177
|
-
|
|
178
|
-
console.log(chalk.cyan('\n๐ก This was a dry run. Use without --dry-run to apply changes.'));
|
|
179
|
-
} else {
|
|
180
|
-
console.log(chalk.green('\n๐ Lang attribute fixes completed successfully!'));
|
|
181
|
-
}
|
|
190
|
+
showCompletionMessage(options, 'Lang attribute fixes');
|
|
182
191
|
return;
|
|
183
192
|
|
|
184
193
|
} else if (options.roleOnly) {
|
|
@@ -190,11 +199,7 @@ async function main() {
|
|
|
190
199
|
|
|
191
200
|
console.log(chalk.green(`\nโ
Fixed role attributes in ${roleFixed} files (${totalRoleIssues} issues)`));
|
|
192
201
|
|
|
193
|
-
|
|
194
|
-
console.log(chalk.cyan('\n๐ก This was a dry run. Use without --dry-run to apply changes.'));
|
|
195
|
-
} else {
|
|
196
|
-
console.log(chalk.green('\n๐ Role attribute fixes completed successfully!'));
|
|
197
|
-
}
|
|
202
|
+
showCompletionMessage(options, 'Role attribute fixes');
|
|
198
203
|
return;
|
|
199
204
|
}
|
|
200
205
|
|
|
@@ -242,14 +247,7 @@ async function main() {
|
|
|
242
247
|
console.log(chalk.green(` Files fixed: ${totalFixed}`));
|
|
243
248
|
console.log(chalk.yellow(` Total issues resolved: ${totalIssues}`));
|
|
244
249
|
|
|
245
|
-
|
|
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
|
-
}
|
|
250
|
+
showCompletionMessage(options, 'All accessibility fixes');
|
|
253
251
|
|
|
254
252
|
// Suggest cleanup if not comprehensive mode
|
|
255
253
|
console.log(chalk.blue('\n๐ก Pro tip: Use --comprehensive to include duplicate role cleanup!'));
|
|
@@ -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>
|
package/lib/fixer.js
CHANGED
|
@@ -563,7 +563,7 @@ class AccessibilityFixer {
|
|
|
563
563
|
}
|
|
564
564
|
];
|
|
565
565
|
|
|
566
|
-
// Check for images that need role="img"
|
|
566
|
+
// Check for images that need role="img" and aria-label
|
|
567
567
|
const images = content.match(/<img[^>]*>/gi) || [];
|
|
568
568
|
images.forEach((img, index) => {
|
|
569
569
|
if (!img.includes('role=')) {
|
|
@@ -573,6 +573,18 @@ class AccessibilityFixer {
|
|
|
573
573
|
element: img.substring(0, 100) + '...'
|
|
574
574
|
});
|
|
575
575
|
}
|
|
576
|
+
|
|
577
|
+
// Check for missing aria-label when alt exists
|
|
578
|
+
const hasAriaLabel = /aria-label\s*=/i.test(img);
|
|
579
|
+
const altMatch = img.match(/alt\s*=\s*["']([^"']*)["']/i);
|
|
580
|
+
|
|
581
|
+
if (!hasAriaLabel && altMatch && altMatch[1].trim()) {
|
|
582
|
+
issues.push({
|
|
583
|
+
type: '๐ท๏ธ Missing aria-label',
|
|
584
|
+
description: `Image ${index + 1} should have aria-label matching alt text`,
|
|
585
|
+
element: img.substring(0, 100) + '...'
|
|
586
|
+
});
|
|
587
|
+
}
|
|
576
588
|
});
|
|
577
589
|
|
|
578
590
|
// Check for button elements with onclick that need role
|
|
@@ -676,7 +688,17 @@ class AccessibilityFixer {
|
|
|
676
688
|
const pictureWithoutRole = pictureBlock.replace(/\s*role\s*=\s*["']img["']/i, '');
|
|
677
689
|
|
|
678
690
|
// Add role="img" to img element
|
|
679
|
-
|
|
691
|
+
let imgWithRole = imgTag.replace(/(<img[^>]*?)(\s*>)/i, '$1 role="img"$2');
|
|
692
|
+
|
|
693
|
+
// Also add aria-label if img has alt but no aria-label
|
|
694
|
+
const imgHasAriaLabel = /aria-label\s*=/i.test(imgWithRole);
|
|
695
|
+
const altMatch = imgWithRole.match(/alt\s*=\s*["']([^"']*)["']/i);
|
|
696
|
+
|
|
697
|
+
if (!imgHasAriaLabel && altMatch && altMatch[1].trim()) {
|
|
698
|
+
const altText = altMatch[1].trim();
|
|
699
|
+
imgWithRole = imgWithRole.replace(/(<img[^>]*?)(\s*>)/i, `$1 aria-label="${altText}"$2`);
|
|
700
|
+
console.log(chalk.yellow(` ๐ท๏ธ Added aria-label="${altText}" to moved img element`));
|
|
701
|
+
}
|
|
680
702
|
|
|
681
703
|
// Replace the img in the modified picture block
|
|
682
704
|
const updatedPictureBlock = pictureWithoutRole.replace(imgTag, imgWithRole);
|
|
@@ -698,16 +720,33 @@ class AccessibilityFixer {
|
|
|
698
720
|
// Fix picture elements with img children - move role from picture to img
|
|
699
721
|
fixed = this.fixPictureImgRoles(fixed);
|
|
700
722
|
|
|
701
|
-
// Fix all images - add role="img"
|
|
723
|
+
// Fix all images - add role="img" and aria-label
|
|
702
724
|
fixed = fixed.replace(
|
|
703
725
|
/<img([^>]*>)/gi,
|
|
704
|
-
(match
|
|
726
|
+
(match) => {
|
|
727
|
+
let updatedImg = match;
|
|
728
|
+
let hasChanges = false;
|
|
729
|
+
|
|
705
730
|
// Check if role attribute already exists
|
|
706
|
-
if (
|
|
707
|
-
|
|
731
|
+
if (!/role\s*=/i.test(match)) {
|
|
732
|
+
updatedImg = updatedImg.replace(/(<img[^>]*?)(\s*>)/i, '$1 role="img"$2');
|
|
733
|
+
console.log(chalk.yellow(` ๐ผ๏ธ Added role="img" to image element`));
|
|
734
|
+
hasChanges = true;
|
|
708
735
|
}
|
|
709
|
-
|
|
710
|
-
|
|
736
|
+
|
|
737
|
+
// Check if aria-label already exists
|
|
738
|
+
if (!/aria-label\s*=/i.test(match)) {
|
|
739
|
+
// Extract alt text to use for aria-label
|
|
740
|
+
const altMatch = match.match(/alt\s*=\s*["']([^"']*)["']/i);
|
|
741
|
+
if (altMatch && altMatch[1].trim()) {
|
|
742
|
+
const altText = altMatch[1].trim();
|
|
743
|
+
updatedImg = updatedImg.replace(/(<img[^>]*?)(\s*>)/i, `$1 aria-label="${altText}"$2`);
|
|
744
|
+
console.log(chalk.yellow(` ๐ท๏ธ Added aria-label="${altText}" to image element`));
|
|
745
|
+
hasChanges = true;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
return updatedImg;
|
|
711
750
|
}
|
|
712
751
|
);
|
|
713
752
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gbu-accessibility-package",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Automated accessibility fixes for HTML files - Alt attributes, Lang attributes, Role attributes. Smart context-aware alt text generation with individual fix options and comprehensive role attribute management.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"lang-only": "node cli.js --lang-only",
|
|
17
17
|
"role-only": "node cli.js --role-only",
|
|
18
18
|
"cleanup-only": "node cli.js --cleanup-only",
|
|
19
|
+
"no-backup": "node cli.js --no-backup",
|
|
20
|
+
"cleanup-backups": "find . -name '*.backup' -type f -delete",
|
|
19
21
|
"test": "node test-package.js",
|
|
20
22
|
"demo": "node cli.js --dry-run demo",
|
|
21
23
|
"prepublishOnly": "npm run test"
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ja">
|
|
3
|
-
<head>
|
|
4
|
-
<title>Test Duplicate Roles</title>
|
|
5
|
-
</head>
|
|
6
|
-
<body>
|
|
7
|
-
<h1>Test Duplicate Role Attributes</h1>
|
|
8
|
-
|
|
9
|
-
<!-- Images with duplicate roles -->
|
|
10
|
-
<img src="logo.png" alt="Logo" role="img" role="img" role="img" role="img">
|
|
11
|
-
<img src="banner.jpg" alt="Banner" role="img" role="img" role="img" role="img" role="img">
|
|
12
|
-
|
|
13
|
-
<!-- Links with duplicate roles -->
|
|
14
|
-
<a href="/home" role="link" role="link" role="link" role="link">Home</a>
|
|
15
|
-
<a href="/about" role="link" role="link" role="link" role="link" role="link">About</a>
|
|
16
|
-
|
|
17
|
-
<!-- Buttons with duplicate roles -->
|
|
18
|
-
<button onclick="submit()" role="button" role="button" role="button" role="button">Submit</button>
|
|
19
|
-
<button type="button" role="button" role="button" role="button">Click Me</button>
|
|
20
|
-
|
|
21
|
-
<!-- Mixed quotes -->
|
|
22
|
-
<div onclick="toggle()" role="button" role='button' role="button" role="button">Toggle</div>
|
|
23
|
-
<span onclick="show()" role='button' role="button" role="button" role="button">Show</span>
|
|
24
|
-
|
|
25
|
-
<!-- Navigation with duplicates -->
|
|
26
|
-
<nav>
|
|
27
|
-
<ul class="nav-menu" role="menubar" role="menubar" role="menubar" role="menubar">
|
|
28
|
-
<li class="nav-item" role="menuitem" role="menuitem" role="menuitem" role="menuitem">
|
|
29
|
-
<a href="/products" role="link" role="link" role="link" role="link">Products</a>
|
|
30
|
-
</li>
|
|
31
|
-
<li class="nav-item" role="menuitem" role="menuitem" role="menuitem" role="menuitem" role="menuitem">
|
|
32
|
-
<a href="/services" role="link" role="link" role="link" role="link" role="link">Services</a>
|
|
33
|
-
</li>
|
|
34
|
-
</ul>
|
|
35
|
-
</nav>
|
|
36
|
-
|
|
37
|
-
<!-- Complex duplicates -->
|
|
38
|
-
<article>
|
|
39
|
-
<h2>Article with Issues</h2>
|
|
40
|
-
<img src="article1.jpg" alt="Article Image" role="img" role="img" role="img" role="img">
|
|
41
|
-
<p>Some content...</p>
|
|
42
|
-
<a href="/read-more" role="link" role="link" role="link" role="link" role="link" role="link">Read More</a>
|
|
43
|
-
</article>
|
|
44
|
-
</body>
|
|
45
|
-
</html>
|
package/demo/picture-test.html
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
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>Picture Role Test</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<h1>Picture Role Test Cases</h1>
|
|
10
|
-
|
|
11
|
-
<!-- Test case 1: Picture with role="img" containing img without role -->
|
|
12
|
-
<picture>
|
|
13
|
-
<source srcset="image.webp" type="image/webp">
|
|
14
|
-
<img src="image.jpg" alt="Test image" role="img">
|
|
15
|
-
</picture>
|
|
16
|
-
|
|
17
|
-
<!-- Test case 2: Picture with role="img" containing img with role (should not change) -->
|
|
18
|
-
<picture role="img">
|
|
19
|
-
<source srcset="image2.webp" type="image/webp">
|
|
20
|
-
<img src="image2.jpg" alt="Test image 2" role="img">
|
|
21
|
-
</picture>
|
|
22
|
-
|
|
23
|
-
<!-- Test case 3: Picture without role containing img without role (should add role to img) -->
|
|
24
|
-
<picture>
|
|
25
|
-
<source srcset="image3.webp" type="image/webp">
|
|
26
|
-
<img src="image3.jpg" alt="Test image 3" role="img">
|
|
27
|
-
</picture>
|
|
28
|
-
|
|
29
|
-
<!-- Test case 4: Regular img without role (should add role) -->
|
|
30
|
-
<img src="regular.jpg" alt="Regular image" role="img">
|
|
31
|
-
|
|
32
|
-
<!-- Test case 5: Picture with role="img" but no img inside (should not change) -->
|
|
33
|
-
<picture role="img">
|
|
34
|
-
<source srcset="video.webp" type="image/webp">
|
|
35
|
-
</picture>
|
|
36
|
-
</body>
|
|
37
|
-
</html>
|
|
@@ -1,37 +0,0 @@
|
|
|
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>Picture Role Test</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<h1>Picture Role Test Cases</h1>
|
|
10
|
-
|
|
11
|
-
<!-- Test case 1: Picture with role="img" containing img without role -->
|
|
12
|
-
<picture role="img">
|
|
13
|
-
<source srcset="image.webp" type="image/webp">
|
|
14
|
-
<img src="image.jpg" alt="Test image">
|
|
15
|
-
</picture>
|
|
16
|
-
|
|
17
|
-
<!-- Test case 2: Picture with role="img" containing img with role (should not change) -->
|
|
18
|
-
<picture role="img">
|
|
19
|
-
<source srcset="image2.webp" type="image/webp">
|
|
20
|
-
<img src="image2.jpg" alt="Test image 2" role="img">
|
|
21
|
-
</picture>
|
|
22
|
-
|
|
23
|
-
<!-- Test case 3: Picture without role containing img without role (should add role to img) -->
|
|
24
|
-
<picture>
|
|
25
|
-
<source srcset="image3.webp" type="image/webp">
|
|
26
|
-
<img src="image3.jpg" alt="Test image 3">
|
|
27
|
-
</picture>
|
|
28
|
-
|
|
29
|
-
<!-- Test case 4: Regular img without role (should add role) -->
|
|
30
|
-
<img src="regular.jpg" alt="Regular image">
|
|
31
|
-
|
|
32
|
-
<!-- Test case 5: Picture with role="img" but no img inside (should not change) -->
|
|
33
|
-
<picture role="img">
|
|
34
|
-
<source srcset="video.webp" type="image/webp">
|
|
35
|
-
</picture>
|
|
36
|
-
</body>
|
|
37
|
-
</html>
|
package/demo/sample.html.backup
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ja">
|
|
3
|
-
<head>
|
|
4
|
-
<title>Demo HTML for Accessibility Testing</title>
|
|
5
|
-
</head>
|
|
6
|
-
<body>
|
|
7
|
-
<h1>Sample Website</h1>
|
|
8
|
-
|
|
9
|
-
<!-- Images without alt or role -->
|
|
10
|
-
<img src="logo.png" alt="Sample Website" role="img" role="img" role="img">
|
|
11
|
-
<img src="banner.jpg" alt="Sample Website" role="img" role="img" role="img">
|
|
12
|
-
<img src="icon.svg" alt="Home Icon" role="img" role="img" role="img">
|
|
13
|
-
|
|
14
|
-
<!-- Links without role -->
|
|
15
|
-
<a href="/home" role="link" role="link" role="link">Home</a>
|
|
16
|
-
<a href="/about" role="link" role="link" role="link">About Us</a>
|
|
17
|
-
|
|
18
|
-
<!-- Buttons without role -->
|
|
19
|
-
<button onclick="submit()" role="button" role="button" role="button">Submit Form</button>
|
|
20
|
-
<button type="button">Regular Button</button>
|
|
21
|
-
|
|
22
|
-
<!-- Clickable elements -->
|
|
23
|
-
<div onclick="navigate()" class="btn" role="button" role="button" role="button" role="button" role="button" role="button">Click Me</div>
|
|
24
|
-
<span onclick="toggle()" role="button" role="button" role="button">Toggle</span>
|
|
25
|
-
|
|
26
|
-
<!-- Navigation -->
|
|
27
|
-
<nav>
|
|
28
|
-
<ul class="nav-menu" role="menubar" role="menubar" role="menubar">
|
|
29
|
-
<li class="nav-item"><a href="/products" role="link" role="link" role="link">Products</a></li>
|
|
30
|
-
<li class="nav-item"><a href="/services" role="link" role="link" role="link">Services</a></li>
|
|
31
|
-
</ul>
|
|
32
|
-
</nav>
|
|
33
|
-
|
|
34
|
-
<!-- More content -->
|
|
35
|
-
<main>
|
|
36
|
-
<article>
|
|
37
|
-
<h2>Article Title</h2>
|
|
38
|
-
<p>Some content here...</p>
|
|
39
|
-
<img src="article-image.jpg" alt="Article Title" role="img" role="img" role="img">
|
|
40
|
-
</article>
|
|
41
|
-
</main>
|
|
42
|
-
|
|
43
|
-
<footer>
|
|
44
|
-
<p>© 2024 Demo Company</p>
|
|
45
|
-
</footer>
|
|
46
|
-
</body>
|
|
47
|
-
</html>
|