gbu-accessibility-package 1.1.0 → 1.3.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/LICENSE +21 -0
- package/QUICK_START.md +23 -23
- package/README.md +233 -232
- package/cli.js +67 -2
- package/demo/duplicate-roles.html +15 -15
- package/demo/duplicate-roles.html.backup +15 -15
- package/demo/sample.html +13 -13
- package/demo/sample.html.backup +13 -13
- package/lib/fixer.js +56 -24
- package/package.json +12 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 GBU Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/QUICK_START.md
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
# 🚀 Quick Start Guide
|
|
2
2
|
|
|
3
|
-
Hướng dẫn nhanh để sử dụng Accessibility
|
|
3
|
+
Hướng dẫn nhanh để sử dụng GBU Accessibility Package trong 5 phút.
|
|
4
4
|
|
|
5
5
|
## ⚡ Cài đặt nhanh
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# 1.
|
|
9
|
-
|
|
8
|
+
# 1. Cài đặt global (khuyến nghị)
|
|
9
|
+
npm install -g gbu-accessibility-package
|
|
10
10
|
|
|
11
|
-
# 2.
|
|
12
|
-
|
|
13
|
-
npm install
|
|
11
|
+
# 2. Hoặc cài đặt local
|
|
12
|
+
npm install gbu-accessibility-package
|
|
14
13
|
|
|
15
14
|
# 3. Chạy ngay!
|
|
16
|
-
|
|
15
|
+
gbu-a11y
|
|
17
16
|
```
|
|
18
17
|
|
|
19
18
|
## 🎯 Sử dụng cơ bản
|
|
@@ -22,16 +21,19 @@ node cli.js
|
|
|
22
21
|
|
|
23
22
|
```bash
|
|
24
23
|
# Fix toàn bộ dự án (current directory)
|
|
25
|
-
|
|
24
|
+
gbu-a11y
|
|
26
25
|
|
|
27
26
|
# Fix thư mục cụ thể
|
|
28
|
-
|
|
27
|
+
gbu-a11y ./src
|
|
29
28
|
|
|
30
29
|
# Preview trước khi fix
|
|
31
|
-
|
|
30
|
+
gbu-a11y --dry-run
|
|
32
31
|
|
|
33
32
|
# Fix với ngôn ngữ khác
|
|
34
|
-
|
|
33
|
+
gbu-a11y -l en ./dist
|
|
34
|
+
|
|
35
|
+
# Fix comprehensive (khuyến nghị)
|
|
36
|
+
gbu-a11y --comprehensive
|
|
35
37
|
```
|
|
36
38
|
|
|
37
39
|
### Cách 2: Node.js Script
|
|
@@ -39,7 +41,7 @@ node accessibility-package/cli.js -l en ./dist
|
|
|
39
41
|
Tạo file `fix.js`:
|
|
40
42
|
|
|
41
43
|
```javascript
|
|
42
|
-
const AccessibilityFixer = require('
|
|
44
|
+
const AccessibilityFixer = require('gbu-accessibility-package');
|
|
43
45
|
|
|
44
46
|
const fixer = new AccessibilityFixer({
|
|
45
47
|
language: 'ja', // Thay đổi theo dự án
|
|
@@ -48,9 +50,8 @@ const fixer = new AccessibilityFixer({
|
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
async function fix() {
|
|
51
|
-
|
|
52
|
-
await fixer.
|
|
53
|
-
await fixer.fixRoleAttributes('.');
|
|
53
|
+
// Fix tất cả issues
|
|
54
|
+
await fixer.fixAllAccessibilityIssues('.');
|
|
54
55
|
console.log('✅ Done!');
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -61,11 +62,10 @@ Chạy: `node fix.js`
|
|
|
61
62
|
|
|
62
63
|
## 📋 Checklist nhanh
|
|
63
64
|
|
|
64
|
-
- [ ]
|
|
65
|
-
- [ ] `npm install` trong thư mục package
|
|
65
|
+
- [ ] `npm install -g gbu-accessibility-package`
|
|
66
66
|
- [ ] Backup code (git commit)
|
|
67
|
-
- [ ] Chạy
|
|
68
|
-
- [ ] Chạy
|
|
67
|
+
- [ ] Chạy `gbu-a11y --dry-run` để preview
|
|
68
|
+
- [ ] Chạy `gbu-a11y --comprehensive` để fix
|
|
69
69
|
- [ ] Kiểm tra kết quả
|
|
70
70
|
- [ ] Commit changes
|
|
71
71
|
|
|
@@ -103,19 +103,19 @@ language: 'en' // 'ja', 'vi', 'zh', etc.
|
|
|
103
103
|
|
|
104
104
|
### Không tạo backup
|
|
105
105
|
```bash
|
|
106
|
-
|
|
106
|
+
gbu-a11y --no-backup
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
### Chỉ preview
|
|
110
110
|
```bash
|
|
111
|
-
|
|
111
|
+
gbu-a11y --dry-run
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
## ❓ Troubleshooting
|
|
115
115
|
|
|
116
116
|
**Lỗi "Cannot find module"**
|
|
117
117
|
```bash
|
|
118
|
-
|
|
118
|
+
npm install -g gbu-accessibility-package
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
**Duplicate attributes**
|
|
@@ -130,7 +130,7 @@ cd accessibility-package && npm install
|
|
|
130
130
|
|
|
131
131
|
1. Đọc [README.md](./README.md) đầy đủ
|
|
132
132
|
2. Xem [example.js](./example.js)
|
|
133
|
-
3. Chạy `
|
|
133
|
+
3. Chạy `gbu-a11y --help`
|
|
134
134
|
|
|
135
135
|
---
|
|
136
136
|
|
package/README.md
CHANGED
|
@@ -1,335 +1,336 @@
|
|
|
1
1
|
# GBU Accessibility Package
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
3
|
+
🚀 **Automated accessibility fixes for HTML files** - Smart, context-aware accessibility improvements with zero configuration.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/gbu-accessibility-package)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://nodejs.org/)
|
|
7
8
|
|
|
8
|
-
##
|
|
9
|
+
## ✨ Features
|
|
9
10
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
- ✅ **Context-aware**: Phân tích nội dung xung quanh để tạo alt text phù hợp
|
|
19
|
-
- ✅ **Backup tự động**: Tạo backup files trước khi sửa
|
|
20
|
-
- ✅ **Dry run mode**: Xem preview trước khi apply changes
|
|
21
|
-
- ✅ **Comprehensive mode**: Chạy tất cả fixes trong một lần
|
|
11
|
+
- 🖼️ **Smart Alt Text Generation** - Context-aware alt attributes for images
|
|
12
|
+
- 🌐 **HTML Lang Attributes** - Automatic language attribute fixes
|
|
13
|
+
- 🎭 **Role Attributes** - WCAG-compliant role attribute management
|
|
14
|
+
- 🧹 **Duplicate Cleanup** - Remove duplicate role attributes
|
|
15
|
+
- 📁 **Batch Processing** - Process entire directories recursively
|
|
16
|
+
- 💾 **Automatic Backups** - Safe modifications with backup files
|
|
17
|
+
- 🔍 **Dry Run Mode** - Preview changes before applying
|
|
18
|
+
- 📊 **Detailed Reports** - Comprehensive fix summaries
|
|
22
19
|
|
|
23
|
-
##
|
|
20
|
+
## 🚀 Quick Start
|
|
24
21
|
|
|
25
|
-
###
|
|
22
|
+
### Installation
|
|
26
23
|
|
|
27
24
|
```bash
|
|
28
|
-
#
|
|
25
|
+
# Global installation (recommended)
|
|
29
26
|
npm install -g gbu-accessibility-package
|
|
30
27
|
|
|
31
|
-
#
|
|
32
|
-
npm install gbu-accessibility-package
|
|
28
|
+
# Local installation
|
|
29
|
+
npm install gbu-accessibility-package
|
|
33
30
|
```
|
|
34
31
|
|
|
35
|
-
###
|
|
32
|
+
### Basic Usage
|
|
36
33
|
|
|
37
34
|
```bash
|
|
38
|
-
#
|
|
39
|
-
|
|
35
|
+
# Fix current directory
|
|
36
|
+
gbu-a11y
|
|
37
|
+
|
|
38
|
+
# Preview changes (dry run)
|
|
39
|
+
gbu-a11y --dry-run
|
|
40
|
+
|
|
41
|
+
# Fix specific directory
|
|
42
|
+
gbu-a11y ./src
|
|
43
|
+
|
|
44
|
+
# Comprehensive fixes (recommended)
|
|
45
|
+
gbu-a11y --comprehensive
|
|
40
46
|
|
|
41
|
-
#
|
|
42
|
-
|
|
47
|
+
# Fix specific file
|
|
48
|
+
gbu-a11y index.html
|
|
43
49
|
```
|
|
44
50
|
|
|
45
|
-
##
|
|
51
|
+
## 📖 Detailed Usage
|
|
46
52
|
|
|
47
|
-
###
|
|
53
|
+
### Command Line Options
|
|
48
54
|
|
|
49
55
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
gbu-a11y [options] [directory/file]
|
|
57
|
+
|
|
58
|
+
Options:
|
|
59
|
+
-d, --directory <path> Target directory (default: current directory)
|
|
60
|
+
-l, --language <lang> Language for lang attribute (default: ja)
|
|
61
|
+
--no-backup Don't create backup files
|
|
62
|
+
--dry-run Preview changes without applying
|
|
63
|
+
--comprehensive, --all Run all fixes including cleanup (recommended)
|
|
64
|
+
--cleanup-only Only cleanup duplicate role attributes
|
|
65
|
+
--alt-only Only fix alt attributes for images
|
|
66
|
+
--lang-only Only fix HTML lang attributes
|
|
67
|
+
--role-only Only fix role attributes
|
|
68
|
+
-h, --help Show help message
|
|
55
69
|
```
|
|
56
70
|
|
|
57
|
-
###
|
|
71
|
+
### Examples
|
|
58
72
|
|
|
59
73
|
```bash
|
|
60
|
-
#
|
|
61
|
-
|
|
74
|
+
# Basic fixes for current directory (all standard fixes)
|
|
75
|
+
gbu-a11y
|
|
62
76
|
|
|
63
|
-
#
|
|
64
|
-
|
|
65
|
-
"scripts": {
|
|
66
|
-
"fix-a11y": "gbu-a11y --comprehensive",
|
|
67
|
-
"preview-a11y": "gbu-a11y --comprehensive --dry-run",
|
|
68
|
-
"cleanup-roles": "gbu-a11y --cleanup-only"
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
```
|
|
77
|
+
# Preview all changes
|
|
78
|
+
gbu-a11y --dry-run --comprehensive
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
# Fix with English language
|
|
81
|
+
gbu-a11y -l en ./public
|
|
74
82
|
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
# Individual fix types
|
|
84
|
+
gbu-a11y --alt-only # Only fix alt attributes
|
|
85
|
+
gbu-a11y --lang-only # Only fix lang attributes
|
|
86
|
+
gbu-a11y --role-only # Only fix role attributes
|
|
87
|
+
gbu-a11y --cleanup-only # Only cleanup duplicates
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
backupFiles: true, // Tạo backup files
|
|
82
|
-
dryRun: false // false = apply changes, true = preview only
|
|
83
|
-
});
|
|
89
|
+
# Combine with other options
|
|
90
|
+
gbu-a11y --alt-only --dry-run ./src # Preview alt fixes only
|
|
91
|
+
gbu-a11y --role-only -l en ./public # Fix roles with English lang
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// Fix lang attributes
|
|
88
|
-
const langResults = await fixer.fixHtmlLang('.');
|
|
89
|
-
|
|
90
|
-
// Fix alt attributes
|
|
91
|
-
const altResults = await fixer.fixEmptyAltAttributes('.');
|
|
92
|
-
|
|
93
|
-
// Fix role attributes
|
|
94
|
-
const roleResults = await fixer.fixRoleAttributes('.');
|
|
95
|
-
|
|
96
|
-
console.log('Hoàn thành!');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
fixAccessibility();
|
|
93
|
+
# Fix without creating backups
|
|
94
|
+
gbu-a11y --no-backup ./dist
|
|
100
95
|
```
|
|
101
96
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Tạo file `fix-accessibility.js` trong dự án:
|
|
97
|
+
## 🔧 Programmatic Usage
|
|
105
98
|
|
|
106
99
|
```javascript
|
|
107
100
|
const AccessibilityFixer = require('gbu-accessibility-package');
|
|
108
101
|
|
|
109
102
|
const fixer = new AccessibilityFixer({
|
|
110
|
-
language: '
|
|
103
|
+
language: 'en',
|
|
111
104
|
backupFiles: true,
|
|
112
105
|
dryRun: false
|
|
113
106
|
});
|
|
114
107
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
console.log('✅ Hoàn thành!');
|
|
108
|
+
// Fix all accessibility issues
|
|
109
|
+
async function fixAccessibility() {
|
|
110
|
+
try {
|
|
111
|
+
const results = await fixer.fixAllAccessibilityIssues('./src');
|
|
112
|
+
console.log('Fixed files:', results);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error('Error:', error);
|
|
115
|
+
}
|
|
124
116
|
}
|
|
125
117
|
|
|
126
|
-
|
|
118
|
+
fixAccessibility();
|
|
127
119
|
```
|
|
128
120
|
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
node fix-accessibility.js
|
|
132
|
-
```
|
|
121
|
+
## 🎯 Fix Modes
|
|
133
122
|
|
|
134
|
-
|
|
123
|
+
### Individual Fix Options
|
|
124
|
+
You can now fix specific accessibility issues individually:
|
|
135
125
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
dryRun: false // true = chỉ preview, false = apply changes
|
|
141
|
-
};
|
|
126
|
+
- `--alt-only` - Only fix alt attributes for images
|
|
127
|
+
- `--lang-only` - Only fix HTML lang attributes
|
|
128
|
+
- `--role-only` - Only fix role attributes
|
|
129
|
+
- `--cleanup-only` - Only cleanup duplicate role attributes
|
|
142
130
|
|
|
143
|
-
|
|
144
|
-
|
|
131
|
+
### Combined Modes
|
|
132
|
+
- **Standard mode** (default) - Fixes alt, lang, and role attributes
|
|
133
|
+
- `--comprehensive` - All fixes including duplicate cleanup
|
|
145
134
|
|
|
146
|
-
|
|
135
|
+
```bash
|
|
136
|
+
# Fix only missing alt attributes
|
|
137
|
+
gbu-a11y --alt-only
|
|
147
138
|
|
|
148
|
-
|
|
149
|
-
|
|
139
|
+
# Fix only HTML lang attributes
|
|
140
|
+
gbu-a11y --lang-only
|
|
150
141
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
```
|
|
142
|
+
# Fix only role attributes
|
|
143
|
+
gbu-a11y --role-only
|
|
154
144
|
|
|
155
|
-
|
|
156
|
-
|
|
145
|
+
# Clean up duplicate roles only
|
|
146
|
+
gbu-a11y --cleanup-only
|
|
157
147
|
|
|
158
|
-
|
|
159
|
-
|
|
148
|
+
# All fixes (recommended)
|
|
149
|
+
gbu-a11y --comprehensive
|
|
160
150
|
```
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
Thêm role attributes cho các elements
|
|
152
|
+
## 🔧 What Gets Fixed
|
|
164
153
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
154
|
+
### 1. Alt Attributes
|
|
155
|
+
- **Missing alt attributes** → Adds contextual alt text
|
|
156
|
+
- **Empty alt attributes** → Generates meaningful descriptions
|
|
157
|
+
- **Context-aware generation** → Uses surrounding text, headings, captions
|
|
168
158
|
|
|
169
|
-
|
|
170
|
-
|
|
159
|
+
```html
|
|
160
|
+
<!-- Before -->
|
|
161
|
+
<img src="logo.png">
|
|
162
|
+
<img src="chart.jpg" alt="">
|
|
171
163
|
|
|
172
|
-
|
|
173
|
-
|
|
164
|
+
<!-- After -->
|
|
165
|
+
<img src="logo.png" alt="ロゴ">
|
|
166
|
+
<img src="chart.jpg" alt="グラフ">
|
|
174
167
|
```
|
|
175
168
|
|
|
176
|
-
###
|
|
177
|
-
|
|
169
|
+
### 2. HTML Lang Attributes
|
|
170
|
+
- **Missing lang attributes** → Adds specified language
|
|
171
|
+
- **Empty lang attributes** → Sets proper language code
|
|
178
172
|
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
### 6. addMainLandmarks(directory)
|
|
184
|
-
Phát hiện và suggest main landmarks
|
|
173
|
+
```html
|
|
174
|
+
<!-- Before -->
|
|
175
|
+
<html>
|
|
176
|
+
<html lang="">
|
|
185
177
|
|
|
186
|
-
|
|
187
|
-
|
|
178
|
+
<!-- After -->
|
|
179
|
+
<html lang="ja">
|
|
180
|
+
<html lang="ja">
|
|
188
181
|
```
|
|
189
182
|
|
|
190
|
-
|
|
183
|
+
### 3. Role Attributes
|
|
184
|
+
- **Images** → `role="img"`
|
|
185
|
+
- **Links** → `role="link"`
|
|
186
|
+
- **Clickable elements** → `role="button"`
|
|
187
|
+
- **Navigation lists** → `role="menubar"`
|
|
188
|
+
- **Menu items** → `role="menuitem"`
|
|
191
189
|
|
|
192
|
-
### Alt Attributes
|
|
193
190
|
```html
|
|
194
|
-
<!--
|
|
195
|
-
<img src="
|
|
196
|
-
<
|
|
191
|
+
<!-- Before -->
|
|
192
|
+
<img src="icon.png" alt="Icon">
|
|
193
|
+
<a href="/home">Home</a>
|
|
194
|
+
<div class="btn-click">Click me</div>
|
|
197
195
|
|
|
198
|
-
<!--
|
|
199
|
-
<img src="
|
|
200
|
-
<
|
|
196
|
+
<!-- After -->
|
|
197
|
+
<img src="icon.png" alt="Icon" role="img">
|
|
198
|
+
<a href="/home" role="link">Home</a>
|
|
199
|
+
<div class="btn-click" role="button">Click me</div>
|
|
201
200
|
```
|
|
202
201
|
|
|
203
|
-
###
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
<a href="/about">About Us</a>
|
|
208
|
-
<button onclick="submit()">Submit</button>
|
|
209
|
-
|
|
210
|
-
<!-- Sau -->
|
|
211
|
-
<img src="photo.jpg" alt="Beautiful sunset" role="img">
|
|
212
|
-
<a href="/about" role="link">About Us</a>
|
|
213
|
-
<button onclick="submit()" role="button">Submit</button>
|
|
214
|
-
```
|
|
202
|
+
### 4. Duplicate Cleanup
|
|
203
|
+
- **Removes duplicate role attributes**
|
|
204
|
+
- **Preserves first occurrence**
|
|
205
|
+
- **Handles mixed quote styles**
|
|
215
206
|
|
|
216
|
-
### Duplicate Cleanup
|
|
217
207
|
```html
|
|
218
|
-
<!--
|
|
219
|
-
<img src="
|
|
220
|
-
<a href="/home" role="link" role="link">Home</a>
|
|
221
|
-
<button onclick="click()" role="button" role="button">Click</button>
|
|
208
|
+
<!-- Before -->
|
|
209
|
+
<img src="test.jpg" role="img" role="img" alt="Test">
|
|
222
210
|
|
|
223
|
-
<!--
|
|
224
|
-
<img src="
|
|
225
|
-
<a href="/home" role="link">Home</a>
|
|
226
|
-
<button onclick="click()" role="button">Click</button>
|
|
211
|
+
<!-- After -->
|
|
212
|
+
<img src="test.jpg" role="img" alt="Test">
|
|
227
213
|
```
|
|
228
214
|
|
|
229
|
-
|
|
230
|
-
```html
|
|
231
|
-
<!-- Trước -->
|
|
232
|
-
<html>
|
|
215
|
+
## 🌟 Smart Alt Text Generation
|
|
233
216
|
|
|
234
|
-
|
|
235
|
-
<html lang="ja">
|
|
236
|
-
```
|
|
217
|
+
The package uses intelligent context analysis to generate meaningful alt text:
|
|
237
218
|
|
|
238
|
-
|
|
219
|
+
### Context Sources
|
|
220
|
+
1. **Title attributes**
|
|
221
|
+
2. **Aria-label attributes**
|
|
222
|
+
3. **Definition terms (dt elements)**
|
|
223
|
+
4. **Parent link text**
|
|
224
|
+
5. **Nearby headings**
|
|
225
|
+
6. **Figure captions**
|
|
226
|
+
7. **Surrounding text content**
|
|
239
227
|
|
|
240
|
-
###
|
|
228
|
+
### Fallback Patterns
|
|
229
|
+
- `logo.png` → "ロゴ" (Logo)
|
|
230
|
+
- `icon.svg` → "アイコン" (Icon)
|
|
231
|
+
- `banner.jpg` → "バナー" (Banner)
|
|
232
|
+
- `chart.png` → "グラフ" (Chart)
|
|
233
|
+
- Generic images → "画像" (Image)
|
|
241
234
|
|
|
242
|
-
|
|
235
|
+
## 📊 Output Examples
|
|
243
236
|
|
|
244
|
-
|
|
245
|
-
generateAltText(imgTag, htmlContent = '', imgIndex = 0) {
|
|
246
|
-
// Thay đổi các text này theo ngôn ngữ dự án
|
|
247
|
-
if (srcValue.includes('logo')) {
|
|
248
|
-
return 'Logo'; // Thay vì 'ロゴ'
|
|
249
|
-
} else if (srcValue.includes('icon')) {
|
|
250
|
-
return 'Icon'; // Thay vì 'アイコン'
|
|
251
|
-
}
|
|
252
|
-
// ... thêm các cases khác
|
|
253
|
-
}
|
|
237
|
+
### Standard Mode
|
|
254
238
|
```
|
|
239
|
+
🚀 Starting Accessibility Fixer...
|
|
240
|
+
📝 Step 1: Fixing HTML lang attributes...
|
|
241
|
+
✅ Fixed lang attributes in 5 files
|
|
255
242
|
|
|
256
|
-
|
|
243
|
+
🖼️ Step 2: Fixing alt attributes...
|
|
244
|
+
✅ Fixed alt attributes in 12 files (34 issues)
|
|
257
245
|
|
|
258
|
-
|
|
246
|
+
🎭 Step 3: Fixing role attributes...
|
|
247
|
+
✅ Fixed role attributes in 8 files (67 issues)
|
|
259
248
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
fixed
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
249
|
+
📊 Summary:
|
|
250
|
+
Total files scanned: 25
|
|
251
|
+
Files fixed: 15
|
|
252
|
+
Total issues resolved: 106
|
|
253
|
+
|
|
254
|
+
🎉 All accessibility fixes completed successfully!
|
|
266
255
|
```
|
|
267
256
|
|
|
268
|
-
|
|
257
|
+
### Comprehensive Mode
|
|
258
|
+
```
|
|
259
|
+
🎯 Running comprehensive accessibility fixes...
|
|
260
|
+
📝 Step 1: HTML lang attributes...
|
|
261
|
+
🖼️ Step 2: Alt attributes...
|
|
262
|
+
🎭 Step 3: Role attributes...
|
|
263
|
+
🧹 Step 4: Cleanup duplicate roles...
|
|
264
|
+
|
|
265
|
+
🎉 All accessibility fixes completed!
|
|
266
|
+
📊 Final Summary:
|
|
267
|
+
Total files scanned: 25
|
|
268
|
+
Files fixed: 15
|
|
269
|
+
Total issues resolved: 106
|
|
270
|
+
```
|
|
269
271
|
|
|
270
|
-
|
|
271
|
-
2. **Test**: Chạy với `dryRun: true` trước để xem preview
|
|
272
|
-
3. **Review**: Kiểm tra kết quả sau khi chạy
|
|
273
|
-
4. **Git**: Commit code trước khi chạy tool
|
|
272
|
+
## 🔒 Safety Features
|
|
274
273
|
|
|
275
|
-
|
|
274
|
+
- **Automatic backups** with `.backup` extension
|
|
275
|
+
- **Dry run mode** for safe previewing
|
|
276
|
+
- **Non-destructive** - only adds missing attributes
|
|
277
|
+
- **Duplicate prevention** - won't add existing attributes
|
|
278
|
+
- **Error handling** - continues processing on individual file errors
|
|
276
279
|
|
|
277
|
-
|
|
278
|
-
- Số files được xử lý
|
|
279
|
-
- Số issues được tìm thấy và sửa
|
|
280
|
-
- Chi tiết từng file
|
|
281
|
-
- Thống kê tổng quan
|
|
280
|
+
## 🛠️ Configuration
|
|
282
281
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
282
|
+
### Package.json Scripts
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"scripts": {
|
|
286
|
+
"a11y:fix": "gbu-a11y",
|
|
287
|
+
"a11y:check": "gbu-a11y --dry-run",
|
|
288
|
+
"a11y:comprehensive": "gbu-a11y --comprehensive",
|
|
289
|
+
"a11y:cleanup": "gbu-a11y --cleanup-only",
|
|
290
|
+
"a11y:alt": "gbu-a11y --alt-only",
|
|
291
|
+
"a11y:lang": "gbu-a11y --lang-only",
|
|
292
|
+
"a11y:role": "gbu-a11y --role-only"
|
|
293
|
+
}
|
|
294
|
+
}
|
|
292
295
|
```
|
|
293
296
|
|
|
294
|
-
|
|
297
|
+
### CI/CD Integration
|
|
298
|
+
```yaml
|
|
299
|
+
# GitHub Actions example
|
|
300
|
+
- name: Check Accessibility
|
|
301
|
+
run: npx gbu-accessibility-package --dry-run
|
|
295
302
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
cd accessibility-package
|
|
299
|
-
npm install
|
|
303
|
+
- name: Fix Accessibility Issues
|
|
304
|
+
run: npx gbu-accessibility-package --comprehensive
|
|
300
305
|
```
|
|
301
306
|
|
|
302
|
-
|
|
303
|
-
Chạy cleanup script:
|
|
304
|
-
```javascript
|
|
305
|
-
// Tạo file cleanup.js
|
|
306
|
-
const fs = require('fs');
|
|
307
|
-
const path = require('path');
|
|
308
|
-
|
|
309
|
-
async function cleanup() {
|
|
310
|
-
// Code cleanup duplicate roles
|
|
311
|
-
const content = await fs.promises.readFile('file.html', 'utf8');
|
|
312
|
-
const fixed = content.replace(/role="([^"]+)"(\s+role="\1")+/g, 'role="$1"');
|
|
313
|
-
await fs.promises.writeFile('file.html', fixed);
|
|
314
|
-
}
|
|
315
|
-
```
|
|
307
|
+
## 🤝 Contributing
|
|
316
308
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
309
|
+
1. Fork the repository
|
|
310
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
311
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
312
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
313
|
+
5. Open a Pull Request
|
|
321
314
|
|
|
322
315
|
## 📝 License
|
|
323
316
|
|
|
324
|
-
MIT License -
|
|
317
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
325
318
|
|
|
326
|
-
##
|
|
319
|
+
## 🆘 Support
|
|
320
|
+
|
|
321
|
+
- 📧 **Issues**: [GitHub Issues](https://github.com/your-org/gbu-accessibility-package/issues)
|
|
322
|
+
- 📖 **Documentation**: [GitHub Wiki](https://github.com/your-org/gbu-accessibility-package/wiki)
|
|
323
|
+
- 💬 **Discussions**: [GitHub Discussions](https://github.com/your-org/gbu-accessibility-package/discussions)
|
|
324
|
+
|
|
325
|
+
## 🏆 Why Choose GBU Accessibility Package?
|
|
327
326
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
327
|
+
- ✅ **Zero Configuration** - Works out of the box
|
|
328
|
+
- ✅ **Smart & Context-Aware** - Not just generic fixes
|
|
329
|
+
- ✅ **Safe & Reliable** - Automatic backups and dry run
|
|
330
|
+
- ✅ **Comprehensive** - Covers all major accessibility issues
|
|
331
|
+
- ✅ **Fast & Efficient** - Batch processing with detailed reports
|
|
332
|
+
- ✅ **WCAG Compliant** - Follows accessibility standards
|
|
332
333
|
|
|
333
334
|
---
|
|
334
335
|
|
|
335
|
-
|
|
336
|
+
Made with ❤️ by the GBU Team
|
package/cli.js
CHANGED
|
@@ -18,7 +18,10 @@ const options = {
|
|
|
18
18
|
dryRun: false,
|
|
19
19
|
help: false,
|
|
20
20
|
cleanupOnly: false,
|
|
21
|
-
comprehensive: false
|
|
21
|
+
comprehensive: false,
|
|
22
|
+
altOnly: false,
|
|
23
|
+
langOnly: false,
|
|
24
|
+
roleOnly: false
|
|
22
25
|
};
|
|
23
26
|
|
|
24
27
|
// Parse arguments
|
|
@@ -51,6 +54,15 @@ for (let i = 0; i < args.length; i++) {
|
|
|
51
54
|
case '--all':
|
|
52
55
|
options.comprehensive = true;
|
|
53
56
|
break;
|
|
57
|
+
case '--alt-only':
|
|
58
|
+
options.altOnly = true;
|
|
59
|
+
break;
|
|
60
|
+
case '--lang-only':
|
|
61
|
+
options.langOnly = true;
|
|
62
|
+
break;
|
|
63
|
+
case '--role-only':
|
|
64
|
+
options.roleOnly = true;
|
|
65
|
+
break;
|
|
54
66
|
default:
|
|
55
67
|
if (!arg.startsWith('-')) {
|
|
56
68
|
options.directory = arg;
|
|
@@ -70,13 +82,19 @@ Options:
|
|
|
70
82
|
-l, --language <lang> Language for lang attribute (default: ja)
|
|
71
83
|
--no-backup Don't create backup files
|
|
72
84
|
--dry-run Preview changes without applying
|
|
73
|
-
--cleanup-only Only cleanup duplicate role attributes
|
|
74
85
|
--comprehensive, --all Run all fixes including cleanup (recommended)
|
|
86
|
+
--cleanup-only Only cleanup duplicate role attributes
|
|
87
|
+
--alt-only Only fix alt attributes for images
|
|
88
|
+
--lang-only Only fix HTML lang attributes
|
|
89
|
+
--role-only Only fix role attributes
|
|
75
90
|
-h, --help Show this help message
|
|
76
91
|
|
|
77
92
|
Examples:
|
|
78
93
|
node cli.js # Fix current directory (standard fixes)
|
|
79
94
|
node cli.js --comprehensive # Run all fixes including cleanup
|
|
95
|
+
node cli.js --alt-only # Only fix alt attributes
|
|
96
|
+
node cli.js --lang-only # Only fix lang attributes
|
|
97
|
+
node cli.js --role-only # Only fix role attributes
|
|
80
98
|
node cli.js --cleanup-only # Only cleanup duplicate roles
|
|
81
99
|
node cli.js ./src # Fix src directory
|
|
82
100
|
node cli.js -l en --dry-run ./dist # Preview fixes for dist directory in English
|
|
@@ -131,6 +149,53 @@ async function main() {
|
|
|
131
149
|
console.log(chalk.green('\n🎉 Cleanup completed successfully!'));
|
|
132
150
|
}
|
|
133
151
|
return;
|
|
152
|
+
|
|
153
|
+
} else if (options.altOnly) {
|
|
154
|
+
// Only fix alt attributes
|
|
155
|
+
console.log(chalk.blue('🖼️ Running alt attribute fixes only...'));
|
|
156
|
+
const altResults = await fixer.fixEmptyAltAttributes(options.directory);
|
|
157
|
+
const altFixed = altResults.filter(r => r.status === 'fixed').length;
|
|
158
|
+
const totalAltIssues = altResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
159
|
+
|
|
160
|
+
console.log(chalk.green(`\n✅ Fixed alt attributes in ${altFixed} files (${totalAltIssues} issues)`));
|
|
161
|
+
|
|
162
|
+
if (options.dryRun) {
|
|
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
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
|
|
169
|
+
} else if (options.langOnly) {
|
|
170
|
+
// Only fix lang attributes
|
|
171
|
+
console.log(chalk.blue('📝 Running HTML lang attribute fixes only...'));
|
|
172
|
+
const langResults = await fixer.fixHtmlLang(options.directory);
|
|
173
|
+
const langFixed = langResults.filter(r => r.status === 'fixed').length;
|
|
174
|
+
|
|
175
|
+
console.log(chalk.green(`\n✅ Fixed lang attributes in ${langFixed} files`));
|
|
176
|
+
|
|
177
|
+
if (options.dryRun) {
|
|
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
|
+
}
|
|
182
|
+
return;
|
|
183
|
+
|
|
184
|
+
} else if (options.roleOnly) {
|
|
185
|
+
// Only fix role attributes
|
|
186
|
+
console.log(chalk.blue('🎭 Running role attribute fixes only...'));
|
|
187
|
+
const roleResults = await fixer.fixRoleAttributes(options.directory);
|
|
188
|
+
const roleFixed = roleResults.filter(r => r.status === 'fixed').length;
|
|
189
|
+
const totalRoleIssues = roleResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
190
|
+
|
|
191
|
+
console.log(chalk.green(`\n✅ Fixed role attributes in ${roleFixed} files (${totalRoleIssues} issues)`));
|
|
192
|
+
|
|
193
|
+
if (options.dryRun) {
|
|
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
|
+
}
|
|
198
|
+
return;
|
|
134
199
|
}
|
|
135
200
|
|
|
136
201
|
// Standard mode - run individual fixes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
2
|
+
<html lang="ja">
|
|
3
3
|
<head>
|
|
4
4
|
<title>Test Duplicate Roles</title>
|
|
5
5
|
</head>
|
|
@@ -7,29 +7,29 @@
|
|
|
7
7
|
<h1>Test Duplicate Role Attributes</h1>
|
|
8
8
|
|
|
9
9
|
<!-- Images with duplicate roles -->
|
|
10
|
-
<img src="logo.png" alt="Logo" role="img" role="img">
|
|
11
|
-
<img src="banner.jpg" alt="Banner" role="img" role="img" role="img">
|
|
10
|
+
<img src="logo.png" alt="Logo" role="img" 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" role="img">
|
|
12
12
|
|
|
13
13
|
<!-- Links with duplicate roles -->
|
|
14
|
-
<a href="/home" role="link" role="link">Home</a>
|
|
15
|
-
<a href="/about" role="link" role="link" role="link">About</a>
|
|
14
|
+
<a href="/home" role="link" role="link" role="link" role="link" role="link">Home</a>
|
|
15
|
+
<a href="/about" role="link" role="link" role="link" role="link" role="link" role="link">About</a>
|
|
16
16
|
|
|
17
17
|
<!-- Buttons with duplicate roles -->
|
|
18
|
-
<button onclick="submit()" role="button" role="button">Submit</button>
|
|
18
|
+
<button onclick="submit()" role="button" role="button" role="button" role="button" role="button">Submit</button>
|
|
19
19
|
<button type="button" role="button" role="button" role="button">Click Me</button>
|
|
20
20
|
|
|
21
21
|
<!-- Mixed quotes -->
|
|
22
|
-
<div onclick="toggle()" role="button" role='button'>Toggle</div>
|
|
23
|
-
<span onclick="show()" role='button' role="button">Show</span>
|
|
22
|
+
<div onclick="toggle()" role="button" role='button' role="button" role="button" role="button">Toggle</div>
|
|
23
|
+
<span onclick="show()" role='button' role="button" role="button" role="button" role="button">Show</span>
|
|
24
24
|
|
|
25
25
|
<!-- Navigation with duplicates -->
|
|
26
26
|
<nav>
|
|
27
|
-
<ul class="nav-menu" role="menubar" role="menubar">
|
|
28
|
-
<li class="nav-item" role="menuitem" role="menuitem">
|
|
29
|
-
<a href="/products" role="link" role="link">Products</a>
|
|
27
|
+
<ul class="nav-menu" role="menubar" role="menubar" role="menubar" role="menubar" role="menubar">
|
|
28
|
+
<li class="nav-item" role="menuitem" role="menuitem" role="menuitem" role="menuitem" role="menuitem">
|
|
29
|
+
<a href="/products" role="link" role="link" role="link" role="link" role="link">Products</a>
|
|
30
30
|
</li>
|
|
31
|
-
<li class="nav-item" role="menuitem" role="menuitem" role="menuitem">
|
|
32
|
-
<a href="/services" role="link" role="link" role="link">Services</a>
|
|
31
|
+
<li class="nav-item" role="menuitem" role="menuitem" role="menuitem" role="menuitem" role="menuitem" role="menuitem">
|
|
32
|
+
<a href="/services" role="link" role="link" role="link" role="link" role="link" role="link">Services</a>
|
|
33
33
|
</li>
|
|
34
34
|
</ul>
|
|
35
35
|
</nav>
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
<!-- Complex duplicates -->
|
|
38
38
|
<article>
|
|
39
39
|
<h2>Article with Issues</h2>
|
|
40
|
-
<img src="article1.jpg" alt="Article Image" role="img" role="img">
|
|
40
|
+
<img src="article1.jpg" alt="Article Image" role="img" role="img" role="img" role="img" role="img">
|
|
41
41
|
<p>Some content...</p>
|
|
42
|
-
<a href="/read-more" role="link" role="link" role="link" role="link">Read More</a>
|
|
42
|
+
<a href="/read-more" role="link" role="link" role="link" role="link" role="link" role="link" role="link">Read More</a>
|
|
43
43
|
</article>
|
|
44
44
|
</body>
|
|
45
45
|
</html>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
2
|
+
<html lang="ja">
|
|
3
3
|
<head>
|
|
4
4
|
<title>Test Duplicate Roles</title>
|
|
5
5
|
</head>
|
|
@@ -7,29 +7,29 @@
|
|
|
7
7
|
<h1>Test Duplicate Role Attributes</h1>
|
|
8
8
|
|
|
9
9
|
<!-- Images with duplicate roles -->
|
|
10
|
-
<img src="logo.png" alt="Logo" role="img" role="img">
|
|
11
|
-
<img src="banner.jpg" alt="Banner" role="img" role="img" role="img">
|
|
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
12
|
|
|
13
13
|
<!-- Links with duplicate roles -->
|
|
14
|
-
<a href="/home" role="link" role="link">Home</a>
|
|
15
|
-
<a href="/about" role="link" role="link" role="link">About</a>
|
|
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
16
|
|
|
17
17
|
<!-- Buttons with duplicate roles -->
|
|
18
|
-
<button onclick="submit()" role="button" role="button">Submit</button>
|
|
18
|
+
<button onclick="submit()" role="button" role="button" role="button" role="button">Submit</button>
|
|
19
19
|
<button type="button" role="button" role="button" role="button">Click Me</button>
|
|
20
20
|
|
|
21
21
|
<!-- Mixed quotes -->
|
|
22
|
-
<div onclick="toggle()" role="button" role='button'>Toggle</div>
|
|
23
|
-
<span onclick="show()" role='button' role="button">Show</span>
|
|
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
24
|
|
|
25
25
|
<!-- Navigation with duplicates -->
|
|
26
26
|
<nav>
|
|
27
|
-
<ul class="nav-menu" role="menubar" role="menubar">
|
|
28
|
-
<li class="nav-item" role="menuitem" role="menuitem">
|
|
29
|
-
<a href="/products" role="link" role="link">Products</a>
|
|
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
30
|
</li>
|
|
31
|
-
<li class="nav-item" role="menuitem" role="menuitem" role="menuitem">
|
|
32
|
-
<a href="/services" role="link" role="link" role="link">Services</a>
|
|
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
33
|
</li>
|
|
34
34
|
</ul>
|
|
35
35
|
</nav>
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
<!-- Complex duplicates -->
|
|
38
38
|
<article>
|
|
39
39
|
<h2>Article with Issues</h2>
|
|
40
|
-
<img src="article1.jpg" alt="Article Image" role="img" role="img">
|
|
40
|
+
<img src="article1.jpg" alt="Article Image" role="img" role="img" role="img" role="img">
|
|
41
41
|
<p>Some content...</p>
|
|
42
|
-
<a href="/read-more" role="link" role="link" role="link" role="link">Read More</a>
|
|
42
|
+
<a href="/read-more" role="link" role="link" role="link" role="link" role="link" role="link">Read More</a>
|
|
43
43
|
</article>
|
|
44
44
|
</body>
|
|
45
45
|
</html>
|
package/demo/sample.html
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
2
|
+
<html lang="ja">
|
|
3
3
|
<head>
|
|
4
4
|
<title>Demo HTML for Accessibility Testing</title>
|
|
5
5
|
</head>
|
|
@@ -7,27 +7,27 @@
|
|
|
7
7
|
<h1>Sample Website</h1>
|
|
8
8
|
|
|
9
9
|
<!-- Images without alt or role -->
|
|
10
|
-
<img src="logo.png">
|
|
11
|
-
<img src="banner.jpg" alt="">
|
|
12
|
-
<img src="icon.svg" alt="Home Icon">
|
|
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
13
|
|
|
14
14
|
<!-- Links without role -->
|
|
15
|
-
<a href="/home">Home</a>
|
|
16
|
-
<a href="/about">About Us</a>
|
|
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
17
|
|
|
18
18
|
<!-- Buttons without role -->
|
|
19
|
-
<button onclick="submit()">Submit Form</button>
|
|
19
|
+
<button onclick="submit()" role="button" role="button" role="button">Submit Form</button>
|
|
20
20
|
<button type="button">Regular Button</button>
|
|
21
21
|
|
|
22
22
|
<!-- Clickable elements -->
|
|
23
|
-
<div onclick="navigate()" class="btn">Click Me</div>
|
|
24
|
-
<span onclick="toggle()">Toggle</span>
|
|
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
25
|
|
|
26
26
|
<!-- Navigation -->
|
|
27
27
|
<nav>
|
|
28
|
-
<ul class="nav-menu">
|
|
29
|
-
<li class="nav-item"><a href="/products">Products</a></li>
|
|
30
|
-
<li class="nav-item"><a href="/services">Services</a></li>
|
|
28
|
+
<ul class="nav-menu" role="menubar" role="menubar" role="menubar">
|
|
29
|
+
<li class="nav-item" role="menuitem"><a href="/products" role="link" role="link" role="link">Products</a></li>
|
|
30
|
+
<li class="nav-item" role="menuitem"><a href="/services" role="link" role="link" role="link">Services</a></li>
|
|
31
31
|
</ul>
|
|
32
32
|
</nav>
|
|
33
33
|
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<article>
|
|
37
37
|
<h2>Article Title</h2>
|
|
38
38
|
<p>Some content here...</p>
|
|
39
|
-
<img src="article-image.jpg" alt="">
|
|
39
|
+
<img src="article-image.jpg" alt="Article Title" role="img" role="img" role="img">
|
|
40
40
|
</article>
|
|
41
41
|
</main>
|
|
42
42
|
|
package/demo/sample.html.backup
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
2
|
+
<html lang="ja">
|
|
3
3
|
<head>
|
|
4
4
|
<title>Demo HTML for Accessibility Testing</title>
|
|
5
5
|
</head>
|
|
@@ -7,27 +7,27 @@
|
|
|
7
7
|
<h1>Sample Website</h1>
|
|
8
8
|
|
|
9
9
|
<!-- Images without alt or role -->
|
|
10
|
-
<img src="logo.png">
|
|
11
|
-
<img src="banner.jpg" alt="">
|
|
12
|
-
<img src="icon.svg" alt="Home Icon">
|
|
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
13
|
|
|
14
14
|
<!-- Links without role -->
|
|
15
|
-
<a href="/home">Home</a>
|
|
16
|
-
<a href="/about">About Us</a>
|
|
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
17
|
|
|
18
18
|
<!-- Buttons without role -->
|
|
19
|
-
<button onclick="submit()">Submit Form</button>
|
|
19
|
+
<button onclick="submit()" role="button" role="button" role="button">Submit Form</button>
|
|
20
20
|
<button type="button">Regular Button</button>
|
|
21
21
|
|
|
22
22
|
<!-- Clickable elements -->
|
|
23
|
-
<div onclick="navigate()" class="btn">Click Me</div>
|
|
24
|
-
<span onclick="toggle()">Toggle</span>
|
|
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
25
|
|
|
26
26
|
<!-- Navigation -->
|
|
27
27
|
<nav>
|
|
28
|
-
<ul class="nav-menu">
|
|
29
|
-
<li class="nav-item"><a href="/products">Products</a></li>
|
|
30
|
-
<li class="nav-item"><a href="/services">Services</a></li>
|
|
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
31
|
</ul>
|
|
32
32
|
</nav>
|
|
33
33
|
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<article>
|
|
37
37
|
<h2>Article Title</h2>
|
|
38
38
|
<p>Some content here...</p>
|
|
39
|
-
<img src="article-image.jpg" alt="">
|
|
39
|
+
<img src="article-image.jpg" alt="Article Title" role="img" role="img" role="img">
|
|
40
40
|
</article>
|
|
41
41
|
</main>
|
|
42
42
|
|
package/lib/fixer.js
CHANGED
|
@@ -645,73 +645,105 @@ class AccessibilityFixer {
|
|
|
645
645
|
|
|
646
646
|
// Fix all images - add role="img" (only if no role exists)
|
|
647
647
|
fixed = fixed.replace(
|
|
648
|
-
/<img([^>]
|
|
649
|
-
(match,
|
|
648
|
+
/<img([^>]*>)/gi,
|
|
649
|
+
(match, fullTag) => {
|
|
650
|
+
// Check if role attribute already exists
|
|
651
|
+
if (/role\s*=/i.test(match)) {
|
|
652
|
+
return match; // Return unchanged if role already exists
|
|
653
|
+
}
|
|
650
654
|
console.log(chalk.yellow(` 🖼️ Added role="img" to image element`));
|
|
651
|
-
return
|
|
655
|
+
return match.replace(/(<img[^>]*?)(\s*>)/i, '$1 role="img"$2');
|
|
652
656
|
}
|
|
653
657
|
);
|
|
654
658
|
|
|
655
659
|
// Fix button elements with onclick - add role="button"
|
|
656
660
|
fixed = fixed.replace(
|
|
657
|
-
/<button([^>]*onclick[^>]
|
|
658
|
-
(match
|
|
661
|
+
/<button([^>]*onclick[^>]*>)/gi,
|
|
662
|
+
(match) => {
|
|
663
|
+
// Check if role attribute already exists
|
|
664
|
+
if (/role\s*=/i.test(match)) {
|
|
665
|
+
return match; // Return unchanged if role already exists
|
|
666
|
+
}
|
|
659
667
|
console.log(chalk.yellow(` 🔘 Added role="button" to button with onclick`));
|
|
660
|
-
return
|
|
668
|
+
return match.replace(/(<button[^>]*?)(\s*>)/i, '$1 role="button"$2');
|
|
661
669
|
}
|
|
662
670
|
);
|
|
663
671
|
|
|
664
672
|
// Fix anchor elements - add role="link"
|
|
665
673
|
fixed = fixed.replace(
|
|
666
|
-
/<a([^>]*href[^>]
|
|
667
|
-
(match
|
|
674
|
+
/<a([^>]*href[^>]*>)/gi,
|
|
675
|
+
(match) => {
|
|
676
|
+
// Check if role attribute already exists
|
|
677
|
+
if (/role\s*=/i.test(match)) {
|
|
678
|
+
return match; // Return unchanged if role already exists
|
|
679
|
+
}
|
|
668
680
|
console.log(chalk.yellow(` 🔗 Added role="link" to anchor element`));
|
|
669
|
-
return
|
|
681
|
+
return match.replace(/(<a[^>]*?)(\s*>)/i, '$1 role="link"$2');
|
|
670
682
|
}
|
|
671
683
|
);
|
|
672
684
|
|
|
673
685
|
// Fix any element with onclick (except a and button) - add role="button"
|
|
674
686
|
fixed = fixed.replace(
|
|
675
|
-
/<((?!a|button)[a-zA-Z][a-zA-Z0-9]*)([^>]*onclick[^>]
|
|
676
|
-
(match, tag
|
|
687
|
+
/<((?!a|button)[a-zA-Z][a-zA-Z0-9]*)([^>]*onclick[^>]*>)/gi,
|
|
688
|
+
(match, tag) => {
|
|
689
|
+
// Check if role attribute already exists
|
|
690
|
+
if (/role\s*=/i.test(match)) {
|
|
691
|
+
return match; // Return unchanged if role already exists
|
|
692
|
+
}
|
|
677
693
|
console.log(chalk.yellow(` 🔘 Added role="button" to ${tag} with onclick`));
|
|
678
|
-
return
|
|
694
|
+
return match.replace(/(<[^>]*?)(\s*>)/i, '$1 role="button"$2');
|
|
679
695
|
}
|
|
680
696
|
);
|
|
681
697
|
|
|
682
698
|
// Fix clickable divs - add role="button"
|
|
683
699
|
fixed = fixed.replace(
|
|
684
|
-
/<div([^>]*class="[^"]*(?:btn|button|click)[^"]*"[^>]
|
|
685
|
-
(match
|
|
700
|
+
/<div([^>]*class="[^"]*(?:btn|button|click)[^"]*"[^>]*>)/gi,
|
|
701
|
+
(match) => {
|
|
702
|
+
// Check if role attribute already exists
|
|
703
|
+
if (/role\s*=/i.test(match)) {
|
|
704
|
+
return match; // Return unchanged if role already exists
|
|
705
|
+
}
|
|
686
706
|
console.log(chalk.yellow(` 🔘 Added role="button" to clickable div`));
|
|
687
|
-
return
|
|
707
|
+
return match.replace(/(<div[^>]*?)(\s*>)/i, '$1 role="button"$2');
|
|
688
708
|
}
|
|
689
709
|
);
|
|
690
710
|
|
|
691
711
|
// Fix focusable elements with tabindex
|
|
692
712
|
fixed = fixed.replace(
|
|
693
|
-
/<(div|span)([^>]*tabindex\s*=\s*[""']?[0-9-]+[""']?[^>]
|
|
694
|
-
(match, tag
|
|
713
|
+
/<(div|span)([^>]*tabindex\s*=\s*[""']?[0-9-]+[""']?[^>]*>)/gi,
|
|
714
|
+
(match, tag) => {
|
|
715
|
+
// Check if role attribute already exists
|
|
716
|
+
if (/role\s*=/i.test(match)) {
|
|
717
|
+
return match; // Return unchanged if role already exists
|
|
718
|
+
}
|
|
695
719
|
console.log(chalk.yellow(` ⌨️ Added role="button" to focusable ${tag}`));
|
|
696
|
-
return
|
|
720
|
+
return match.replace(/(<[^>]*?)(\s*>)/i, '$1 role="button"$2');
|
|
697
721
|
}
|
|
698
722
|
);
|
|
699
723
|
|
|
700
724
|
// Fix navigation lists that should be menus
|
|
701
725
|
fixed = fixed.replace(
|
|
702
|
-
/<ul([^>]*class="[^"]*(?:nav|menu)[^"]*"[^>]
|
|
703
|
-
(match
|
|
726
|
+
/<ul([^>]*class="[^"]*(?:nav|menu)[^"]*"[^>]*>)/gi,
|
|
727
|
+
(match) => {
|
|
728
|
+
// Check if role attribute already exists
|
|
729
|
+
if (/role\s*=/i.test(match)) {
|
|
730
|
+
return match; // Return unchanged if role already exists
|
|
731
|
+
}
|
|
704
732
|
console.log(chalk.yellow(` 📋 Added role="menubar" to navigation list`));
|
|
705
|
-
return
|
|
733
|
+
return match.replace(/(<ul[^>]*?)(\s*>)/i, '$1 role="menubar"$2');
|
|
706
734
|
}
|
|
707
735
|
);
|
|
708
736
|
|
|
709
737
|
// Fix list items in navigation menus
|
|
710
738
|
fixed = fixed.replace(
|
|
711
|
-
/<li([^>]*class="[^"]*(?:nav|menu)[^"]*"[^>]
|
|
712
|
-
(match
|
|
739
|
+
/<li([^>]*class="[^"]*(?:nav|menu)[^"]*"[^>]*>)/gi,
|
|
740
|
+
(match) => {
|
|
741
|
+
// Check if role attribute already exists
|
|
742
|
+
if (/role\s*=/i.test(match)) {
|
|
743
|
+
return match; // Return unchanged if role already exists
|
|
744
|
+
}
|
|
713
745
|
console.log(chalk.yellow(` 📋 Added role="menuitem" to navigation list item`));
|
|
714
|
-
return
|
|
746
|
+
return match.replace(/(<li[^>]*?)(\s*>)/i, '$1 role="menuitem"$2');
|
|
715
747
|
}
|
|
716
748
|
);
|
|
717
749
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gbu-accessibility-package",
|
|
3
|
-
"version": "1.
|
|
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.",
|
|
3
|
+
"version": "1.3.0",
|
|
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": {
|
|
7
7
|
"gbu-a11y": "./cli.js",
|
|
@@ -11,9 +11,14 @@
|
|
|
11
11
|
"start": "node cli.js",
|
|
12
12
|
"fix": "node cli.js",
|
|
13
13
|
"preview": "node cli.js --dry-run",
|
|
14
|
-
"
|
|
14
|
+
"comprehensive": "node cli.js --comprehensive",
|
|
15
|
+
"alt-only": "node cli.js --alt-only",
|
|
16
|
+
"lang-only": "node cli.js --lang-only",
|
|
17
|
+
"role-only": "node cli.js --role-only",
|
|
18
|
+
"cleanup-only": "node cli.js --cleanup-only",
|
|
19
|
+
"test": "node test-package.js",
|
|
15
20
|
"demo": "node cli.js --dry-run demo",
|
|
16
|
-
"prepublishOnly": "npm run
|
|
21
|
+
"prepublishOnly": "npm run test"
|
|
17
22
|
},
|
|
18
23
|
"keywords": [
|
|
19
24
|
"accessibility",
|
|
@@ -51,7 +56,8 @@
|
|
|
51
56
|
"PACKAGE_SUMMARY.md"
|
|
52
57
|
],
|
|
53
58
|
"dependencies": {
|
|
54
|
-
"chalk": "^4.1.2"
|
|
59
|
+
"chalk": "^4.1.2",
|
|
60
|
+
"gbu-accessibility-package": "^1.3.0"
|
|
55
61
|
},
|
|
56
62
|
"engines": {
|
|
57
63
|
"node": ">=12.0.0"
|
|
@@ -59,4 +65,4 @@
|
|
|
59
65
|
"publishConfig": {
|
|
60
66
|
"access": "public"
|
|
61
67
|
}
|
|
62
|
-
}
|
|
68
|
+
}
|