gbu-accessibility-package 1.1.0 → 1.2.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 +198 -241
- 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 +3 -3
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,292 @@
|
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
# Local
|
|
42
|
-
yarn add gbu-accessibility-package --dev
|
|
43
|
-
```
|
|
35
|
+
# Fix current directory
|
|
36
|
+
gbu-a11y
|
|
44
37
|
|
|
45
|
-
|
|
38
|
+
# Preview changes (dry run)
|
|
39
|
+
gbu-a11y --dry-run
|
|
46
40
|
|
|
47
|
-
|
|
41
|
+
# Fix specific directory
|
|
42
|
+
gbu-a11y ./src
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
gbu-a11y [options] [directory]
|
|
44
|
+
# Comprehensive fixes (recommended)
|
|
45
|
+
gbu-a11y --comprehensive
|
|
52
46
|
|
|
53
|
-
#
|
|
54
|
-
|
|
47
|
+
# Fix specific file
|
|
48
|
+
gbu-a11y index.html
|
|
55
49
|
```
|
|
56
50
|
|
|
57
|
-
|
|
51
|
+
## 📖 Detailed Usage
|
|
58
52
|
|
|
59
|
-
|
|
60
|
-
# Chạy từ node_modules
|
|
61
|
-
npx gbu-a11y [options] [directory]
|
|
53
|
+
### Command Line Options
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
55
|
+
```bash
|
|
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
|
+
--cleanup-only Only cleanup duplicate role attributes
|
|
64
|
+
--comprehensive, --all Run all fixes including cleanup (recommended)
|
|
65
|
+
-h, --help Show help message
|
|
71
66
|
```
|
|
72
67
|
|
|
73
|
-
###
|
|
68
|
+
### Examples
|
|
74
69
|
|
|
75
|
-
```
|
|
76
|
-
|
|
70
|
+
```bash
|
|
71
|
+
# Basic fixes for current directory
|
|
72
|
+
gbu-a11y
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
language: 'ja', // Ngôn ngữ cho lang attribute
|
|
81
|
-
backupFiles: true, // Tạo backup files
|
|
82
|
-
dryRun: false // false = apply changes, true = preview only
|
|
83
|
-
});
|
|
74
|
+
# Preview all changes
|
|
75
|
+
gbu-a11y --dry-run --comprehensive
|
|
84
76
|
|
|
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
|
-
}
|
|
77
|
+
# Fix with English language
|
|
78
|
+
gbu-a11y -l en ./public
|
|
98
79
|
|
|
99
|
-
|
|
100
|
-
|
|
80
|
+
# Only cleanup duplicates
|
|
81
|
+
gbu-a11y --cleanup-only
|
|
101
82
|
|
|
102
|
-
|
|
83
|
+
# Fix without creating backups
|
|
84
|
+
gbu-a11y --no-backup ./dist
|
|
85
|
+
```
|
|
103
86
|
|
|
104
|
-
|
|
87
|
+
## 🔧 Programmatic Usage
|
|
105
88
|
|
|
106
89
|
```javascript
|
|
107
90
|
const AccessibilityFixer = require('gbu-accessibility-package');
|
|
108
91
|
|
|
109
92
|
const fixer = new AccessibilityFixer({
|
|
110
|
-
language: '
|
|
93
|
+
language: 'en',
|
|
111
94
|
backupFiles: true,
|
|
112
95
|
dryRun: false
|
|
113
96
|
});
|
|
114
97
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
console.log('✅ Hoàn thành!');
|
|
98
|
+
// Fix all accessibility issues
|
|
99
|
+
async function fixAccessibility() {
|
|
100
|
+
try {
|
|
101
|
+
const results = await fixer.fixAllAccessibilityIssues('./src');
|
|
102
|
+
console.log('Fixed files:', results);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('Error:', error);
|
|
105
|
+
}
|
|
124
106
|
}
|
|
125
107
|
|
|
126
|
-
|
|
108
|
+
fixAccessibility();
|
|
127
109
|
```
|
|
128
110
|
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
node fix-accessibility.js
|
|
132
|
-
```
|
|
111
|
+
## 🎯 What Gets Fixed
|
|
133
112
|
|
|
134
|
-
|
|
113
|
+
### 1. Alt Attributes
|
|
114
|
+
- **Missing alt attributes** → Adds contextual alt text
|
|
115
|
+
- **Empty alt attributes** → Generates meaningful descriptions
|
|
116
|
+
- **Context-aware generation** → Uses surrounding text, headings, captions
|
|
135
117
|
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
dryRun: false // true = chỉ preview, false = apply changes
|
|
141
|
-
};
|
|
118
|
+
```html
|
|
119
|
+
<!-- Before -->
|
|
120
|
+
<img src="logo.png">
|
|
121
|
+
<img src="chart.jpg" alt="">
|
|
142
122
|
|
|
143
|
-
|
|
123
|
+
<!-- After -->
|
|
124
|
+
<img src="logo.png" alt="ロゴ">
|
|
125
|
+
<img src="chart.jpg" alt="グラフ">
|
|
144
126
|
```
|
|
145
127
|
|
|
146
|
-
|
|
128
|
+
### 2. HTML Lang Attributes
|
|
129
|
+
- **Missing lang attributes** → Adds specified language
|
|
130
|
+
- **Empty lang attributes** → Sets proper language code
|
|
147
131
|
|
|
148
|
-
|
|
149
|
-
|
|
132
|
+
```html
|
|
133
|
+
<!-- Before -->
|
|
134
|
+
<html>
|
|
135
|
+
<html lang="">
|
|
150
136
|
|
|
151
|
-
|
|
152
|
-
|
|
137
|
+
<!-- After -->
|
|
138
|
+
<html lang="ja">
|
|
139
|
+
<html lang="ja">
|
|
153
140
|
```
|
|
154
141
|
|
|
155
|
-
###
|
|
156
|
-
|
|
142
|
+
### 3. Role Attributes
|
|
143
|
+
- **Images** → `role="img"`
|
|
144
|
+
- **Links** → `role="link"`
|
|
145
|
+
- **Clickable elements** → `role="button"`
|
|
146
|
+
- **Navigation lists** → `role="menubar"`
|
|
147
|
+
- **Menu items** → `role="menuitem"`
|
|
157
148
|
|
|
158
|
-
```
|
|
159
|
-
|
|
149
|
+
```html
|
|
150
|
+
<!-- Before -->
|
|
151
|
+
<img src="icon.png" alt="Icon">
|
|
152
|
+
<a href="/home">Home</a>
|
|
153
|
+
<div class="btn-click">Click me</div>
|
|
154
|
+
|
|
155
|
+
<!-- After -->
|
|
156
|
+
<img src="icon.png" alt="Icon" role="img">
|
|
157
|
+
<a href="/home" role="link">Home</a>
|
|
158
|
+
<div class="btn-click" role="button">Click me</div>
|
|
160
159
|
```
|
|
161
160
|
|
|
162
|
-
###
|
|
163
|
-
|
|
161
|
+
### 4. Duplicate Cleanup
|
|
162
|
+
- **Removes duplicate role attributes**
|
|
163
|
+
- **Preserves first occurrence**
|
|
164
|
+
- **Handles mixed quote styles**
|
|
164
165
|
|
|
165
|
-
```
|
|
166
|
-
|
|
166
|
+
```html
|
|
167
|
+
<!-- Before -->
|
|
168
|
+
<img src="test.jpg" role="img" role="img" alt="Test">
|
|
169
|
+
|
|
170
|
+
<!-- After -->
|
|
171
|
+
<img src="test.jpg" role="img" alt="Test">
|
|
167
172
|
```
|
|
168
173
|
|
|
169
|
-
|
|
170
|
-
Xóa duplicate role attributes
|
|
174
|
+
## 🌟 Smart Alt Text Generation
|
|
171
175
|
|
|
172
|
-
|
|
173
|
-
const results = await fixer.cleanupDuplicateRoles('./src');
|
|
174
|
-
```
|
|
176
|
+
The package uses intelligent context analysis to generate meaningful alt text:
|
|
175
177
|
|
|
176
|
-
###
|
|
177
|
-
|
|
178
|
+
### Context Sources
|
|
179
|
+
1. **Title attributes**
|
|
180
|
+
2. **Aria-label attributes**
|
|
181
|
+
3. **Definition terms (dt elements)**
|
|
182
|
+
4. **Parent link text**
|
|
183
|
+
5. **Nearby headings**
|
|
184
|
+
6. **Figure captions**
|
|
185
|
+
7. **Surrounding text content**
|
|
178
186
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
187
|
+
### Fallback Patterns
|
|
188
|
+
- `logo.png` → "ロゴ" (Logo)
|
|
189
|
+
- `icon.svg` → "アイコン" (Icon)
|
|
190
|
+
- `banner.jpg` → "バナー" (Banner)
|
|
191
|
+
- `chart.png` → "グラフ" (Chart)
|
|
192
|
+
- Generic images → "画像" (Image)
|
|
182
193
|
|
|
183
|
-
|
|
184
|
-
Phát hiện và suggest main landmarks
|
|
194
|
+
## 📊 Output Examples
|
|
185
195
|
|
|
186
|
-
|
|
187
|
-
const suggestions = await fixer.addMainLandmarks('./src');
|
|
196
|
+
### Standard Mode
|
|
188
197
|
```
|
|
198
|
+
🚀 Starting Accessibility Fixer...
|
|
199
|
+
📝 Step 1: Fixing HTML lang attributes...
|
|
200
|
+
✅ Fixed lang attributes in 5 files
|
|
189
201
|
|
|
190
|
-
|
|
202
|
+
🖼️ Step 2: Fixing alt attributes...
|
|
203
|
+
✅ Fixed alt attributes in 12 files (34 issues)
|
|
191
204
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<!-- Trước -->
|
|
195
|
-
<img src="logo.png">
|
|
196
|
-
<img src="icon.png" alt="">
|
|
205
|
+
🎭 Step 3: Fixing role attributes...
|
|
206
|
+
✅ Fixed role attributes in 8 files (67 issues)
|
|
197
207
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
208
|
+
📊 Summary:
|
|
209
|
+
Total files scanned: 25
|
|
210
|
+
Files fixed: 15
|
|
211
|
+
Total issues resolved: 106
|
|
202
212
|
|
|
203
|
-
|
|
204
|
-
```html
|
|
205
|
-
<!-- Trước -->
|
|
206
|
-
<img src="photo.jpg" alt="Beautiful sunset">
|
|
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>
|
|
213
|
+
🎉 All accessibility fixes completed successfully!
|
|
214
214
|
```
|
|
215
215
|
|
|
216
|
-
###
|
|
217
|
-
```html
|
|
218
|
-
<!-- Trước -->
|
|
219
|
-
<img src="logo.png" alt="Logo" role="img" role="img" role="img">
|
|
220
|
-
<a href="/home" role="link" role="link">Home</a>
|
|
221
|
-
<button onclick="click()" role="button" role="button">Click</button>
|
|
222
|
-
|
|
223
|
-
<!-- Sau -->
|
|
224
|
-
<img src="logo.png" alt="Logo" role="img">
|
|
225
|
-
<a href="/home" role="link">Home</a>
|
|
226
|
-
<button onclick="click()" role="button">Click</button>
|
|
216
|
+
### Comprehensive Mode
|
|
227
217
|
```
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
218
|
+
🎯 Running comprehensive accessibility fixes...
|
|
219
|
+
📝 Step 1: HTML lang attributes...
|
|
220
|
+
🖼️ Step 2: Alt attributes...
|
|
221
|
+
🎭 Step 3: Role attributes...
|
|
222
|
+
🧹 Step 4: Cleanup duplicate roles...
|
|
223
|
+
|
|
224
|
+
🎉 All accessibility fixes completed!
|
|
225
|
+
📊 Final Summary:
|
|
226
|
+
Total files scanned: 25
|
|
227
|
+
Files fixed: 15
|
|
228
|
+
Total issues resolved: 106
|
|
236
229
|
```
|
|
237
230
|
|
|
238
|
-
##
|
|
231
|
+
## 🔒 Safety Features
|
|
239
232
|
|
|
240
|
-
|
|
233
|
+
- **Automatic backups** with `.backup` extension
|
|
234
|
+
- **Dry run mode** for safe previewing
|
|
235
|
+
- **Non-destructive** - only adds missing attributes
|
|
236
|
+
- **Duplicate prevention** - won't add existing attributes
|
|
237
|
+
- **Error handling** - continues processing on individual file errors
|
|
241
238
|
|
|
242
|
-
|
|
239
|
+
## 🛠️ Configuration
|
|
243
240
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
241
|
+
### Package.json Scripts
|
|
242
|
+
```json
|
|
243
|
+
{
|
|
244
|
+
"scripts": {
|
|
245
|
+
"a11y:fix": "gbu-a11y",
|
|
246
|
+
"a11y:check": "gbu-a11y --dry-run",
|
|
247
|
+
"a11y:comprehensive": "gbu-a11y --comprehensive",
|
|
248
|
+
"a11y:cleanup": "gbu-a11y --cleanup-only"
|
|
251
249
|
}
|
|
252
|
-
// ... thêm các cases khác
|
|
253
250
|
}
|
|
254
251
|
```
|
|
255
252
|
|
|
256
|
-
###
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
// Ví dụ: thêm role cho form elements
|
|
262
|
-
fixed = fixed.replace(
|
|
263
|
-
/<form([^>]*)(?!.*role\s*=)([^>]*>)/gi,
|
|
264
|
-
'<form$1 role="form"$2'
|
|
265
|
-
);
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
## 🚨 Lưu ý quan trọng
|
|
269
|
-
|
|
270
|
-
1. **Backup**: Luôn tạo backup trước khi chạy tool
|
|
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
|
|
274
|
-
|
|
275
|
-
## 📊 Monitoring Results
|
|
276
|
-
|
|
277
|
-
Tool sẽ hiển thị:
|
|
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
|
|
253
|
+
### CI/CD Integration
|
|
254
|
+
```yaml
|
|
255
|
+
# GitHub Actions example
|
|
256
|
+
- name: Check Accessibility
|
|
257
|
+
run: npx gbu-accessibility-package --dry-run
|
|
282
258
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
🖼️ Missing role: Image 1 should have role="img"
|
|
286
|
-
🔗 Missing role: Anchor 1 should have role="link"
|
|
287
|
-
🖼️ Added role="img" to image element
|
|
288
|
-
🔗 Added role="link" to anchor element
|
|
289
|
-
✅ Fixed role attributes in: index.html
|
|
290
|
-
|
|
291
|
-
📊 Summary: Found 245 role attribute issues across 50 files
|
|
259
|
+
- name: Fix Accessibility Issues
|
|
260
|
+
run: npx gbu-accessibility-package --comprehensive
|
|
292
261
|
```
|
|
293
262
|
|
|
294
|
-
##
|
|
263
|
+
## 🤝 Contributing
|
|
295
264
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
265
|
+
1. Fork the repository
|
|
266
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
267
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
268
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
269
|
+
5. Open a Pull Request
|
|
301
270
|
|
|
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
|
-
```
|
|
271
|
+
## 📝 License
|
|
316
272
|
|
|
317
|
-
|
|
318
|
-
- Chạy từng thư mục con
|
|
319
|
-
- Sử dụng `dryRun: true` để test trước
|
|
320
|
-
- Exclude thư mục không cần thiết
|
|
273
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
321
274
|
|
|
322
|
-
##
|
|
275
|
+
## 🆘 Support
|
|
323
276
|
|
|
324
|
-
|
|
277
|
+
- 📧 **Issues**: [GitHub Issues](https://github.com/your-org/gbu-accessibility-package/issues)
|
|
278
|
+
- 📖 **Documentation**: [GitHub Wiki](https://github.com/your-org/gbu-accessibility-package/wiki)
|
|
279
|
+
- 💬 **Discussions**: [GitHub Discussions](https://github.com/your-org/gbu-accessibility-package/discussions)
|
|
325
280
|
|
|
326
|
-
##
|
|
281
|
+
## 🏆 Why Choose GBU Accessibility Package?
|
|
327
282
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
283
|
+
- ✅ **Zero Configuration** - Works out of the box
|
|
284
|
+
- ✅ **Smart & Context-Aware** - Not just generic fixes
|
|
285
|
+
- ✅ **Safe & Reliable** - Automatic backups and dry run
|
|
286
|
+
- ✅ **Comprehensive** - Covers all major accessibility issues
|
|
287
|
+
- ✅ **Fast & Efficient** - Batch processing with detailed reports
|
|
288
|
+
- ✅ **WCAG Compliant** - Follows accessibility standards
|
|
332
289
|
|
|
333
290
|
---
|
|
334
291
|
|
|
335
|
-
|
|
292
|
+
Made with ❤️ by the GBU Team
|
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gbu-accessibility-package",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Automated accessibility fixes for HTML files - Alt attributes, Lang attributes, Role attributes. Smart context-aware alt text generation and comprehensive role attribute management.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"start": "node cli.js",
|
|
12
12
|
"fix": "node cli.js",
|
|
13
13
|
"preview": "node cli.js --dry-run",
|
|
14
|
-
"test": "node
|
|
14
|
+
"test": "node test-package.js",
|
|
15
15
|
"demo": "node cli.js --dry-run demo",
|
|
16
|
-
"prepublishOnly": "npm run
|
|
16
|
+
"prepublishOnly": "npm run test"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
19
19
|
"accessibility",
|