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 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 Fixer trong 5 phút.
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. Copy package vào dự án
9
- cp -r accessibility-package /path/to/your/project/
8
+ # 1. Cài đặt global (khuyến nghị)
9
+ npm install -g gbu-accessibility-package
10
10
 
11
- # 2. Cài đặt dependencies
12
- cd your-project/accessibility-package
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
- node cli.js
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
- node accessibility-package/cli.js
24
+ gbu-a11y
26
25
 
27
26
  # Fix thư mục cụ thể
28
- node accessibility-package/cli.js ./src
27
+ gbu-a11y ./src
29
28
 
30
29
  # Preview trước khi fix
31
- node accessibility-package/cli.js --dry-run
30
+ gbu-a11y --dry-run
32
31
 
33
32
  # Fix với ngôn ngữ khác
34
- node accessibility-package/cli.js -l en ./dist
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('./accessibility-package/lib/fixer.js');
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
- await fixer.fixHtmlLang('.');
52
- await fixer.fixEmptyAltAttributes('.');
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
- - [ ] Copy package vào dự án
65
- - [ ] `npm install` trong thư mục package
65
+ - [ ] `npm install -g gbu-accessibility-package`
66
66
  - [ ] Backup code (git commit)
67
- - [ ] Chạy `--dry-run` để preview
68
- - [ ] Chạy tool để fix
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
- node cli.js --no-backup
106
+ gbu-a11y --no-backup
107
107
  ```
108
108
 
109
109
  ### Chỉ preview
110
110
  ```bash
111
- node cli.js --dry-run
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
- cd accessibility-package && npm install
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 `node cli.js --help`
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
- [![npm version](https://badge.fury.io/js/gbu-accessibility-package.svg)](https://badge.fury.io/js/gbu-accessibility-package)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
3
+ 🚀 **Automated accessibility fixes for HTML files** - Smart, context-aware accessibility improvements with zero configuration.
5
4
 
6
- Một công cụ tự động sửa các vấn đề accessibility phổ biến trong HTML, bao gồm alt attributes, lang attributes, và role attributes với khả năng phân tích context thông minh.
5
+ [![npm version](https://badge.fury.io/js/gbu-accessibility-package.svg)](https://www.npmjs.com/package/gbu-accessibility-package)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D12.0.0-brightgreen)](https://nodejs.org/)
7
8
 
8
- ## 🚀 Tính năng
9
+ ## Features
9
10
 
10
- - **Alt Attributes**: Tự động thêm alt text thông minh cho images
11
- - **Lang Attributes**: Thêm lang attribute cho thẻ `<html>`
12
- - **Role Attributes**: Thêm role attributes cho các elements
13
- - `role="img"` cho tất cả thẻ `<img>`
14
- - `role="link"` cho thẻ `<a>`
15
- - `role="button"` cho elements onclick
16
- - `role="menubar"` `role="menuitem"` cho navigation lists
17
- - **Duplicate Cleanup**: Tự động xóa duplicate role attributes
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
- ## 📦 Cài đặt
20
+ ## 🚀 Quick Start
24
21
 
25
- ### NPM Install (Khuyến nghị)
22
+ ### Installation
26
23
 
27
24
  ```bash
28
- # Cài đặt global
25
+ # Global installation (recommended)
29
26
  npm install -g gbu-accessibility-package
30
27
 
31
- # Hoặc cài đặt local cho dự án
32
- npm install gbu-accessibility-package --save-dev
28
+ # Local installation
29
+ npm install gbu-accessibility-package
33
30
  ```
34
31
 
35
- ### Yarn Install
32
+ ### Basic Usage
36
33
 
37
34
  ```bash
38
- # Global
39
- yarn global add gbu-accessibility-package
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
- # Local
42
- yarn add gbu-accessibility-package --dev
47
+ # Fix specific file
48
+ gbu-a11y index.html
43
49
  ```
44
50
 
45
- ## 🛠️ Sử dụng
51
+ ## 📖 Detailed Usage
46
52
 
47
- ### Cách 1: Sử dụng CLI (Global Install)
53
+ ### Command Line Options
48
54
 
49
55
  ```bash
50
- # Sau khi cài đặt global
51
- gbu-a11y [options] [directory]
52
-
53
- # Hoặc
54
- accessibility-fixer [options] [directory]
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
- ### Cách 1b: CLI (Local Install)
71
+ ### Examples
58
72
 
59
73
  ```bash
60
- # Chạy từ node_modules
61
- npx gbu-a11y [options] [directory]
74
+ # Basic fixes for current directory (all standard fixes)
75
+ gbu-a11y
62
76
 
63
- # Hoặc thêm vào package.json scripts
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
- ### Cách 2: Sử dụng trong Node.js
80
+ # Fix with English language
81
+ gbu-a11y -l en ./public
74
82
 
75
- ```javascript
76
- const AccessibilityFixer = require('gbu-accessibility-package');
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
- // Tạo instance với config
79
- const fixer = new AccessibilityFixer({
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
- });
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
- // Sử dụng các methods
86
- async function fixAccessibility() {
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
- ### Cách 3: Script nhanh
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: 'ja', // Thay đổi theo ngôn ngữ dự án
103
+ language: 'en',
111
104
  backupFiles: true,
112
105
  dryRun: false
113
106
  });
114
107
 
115
- async function fixAll() {
116
- console.log('🚀 Bắt đầu fix accessibility...');
117
-
118
- // Fix tất cả issues
119
- await fixer.fixHtmlLang('.');
120
- await fixer.fixEmptyAltAttributes('.');
121
- await fixer.fixRoleAttributes('.');
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
- fixAll();
118
+ fixAccessibility();
127
119
  ```
128
120
 
129
- Chạy script:
130
- ```bash
131
- node fix-accessibility.js
132
- ```
121
+ ## 🎯 Fix Modes
133
122
 
134
- ## ⚙️ Configuration Options
123
+ ### Individual Fix Options
124
+ You can now fix specific accessibility issues individually:
135
125
 
136
- ```javascript
137
- const config = {
138
- language: 'ja', // Lang attribute value ('ja', 'en', 'vi', etc.)
139
- backupFiles: true, // Tạo .backup files
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
- const fixer = new AccessibilityFixer(config);
144
- ```
131
+ ### Combined Modes
132
+ - **Standard mode** (default) - Fixes alt, lang, and role attributes
133
+ - `--comprehensive` - All fixes including duplicate cleanup
145
134
 
146
- ## 📋 Các Methods có sẵn
135
+ ```bash
136
+ # Fix only missing alt attributes
137
+ gbu-a11y --alt-only
147
138
 
148
- ### 1. fixHtmlLang(directory)
149
- Thêm lang attribute cho thẻ `<html>`
139
+ # Fix only HTML lang attributes
140
+ gbu-a11y --lang-only
150
141
 
151
- ```javascript
152
- const results = await fixer.fixHtmlLang('./src');
153
- ```
142
+ # Fix only role attributes
143
+ gbu-a11y --role-only
154
144
 
155
- ### 2. fixEmptyAltAttributes(directory)
156
- Sửa missing/empty alt attributes cho images
145
+ # Clean up duplicate roles only
146
+ gbu-a11y --cleanup-only
157
147
 
158
- ```javascript
159
- const results = await fixer.fixEmptyAltAttributes('./src');
148
+ # All fixes (recommended)
149
+ gbu-a11y --comprehensive
160
150
  ```
161
151
 
162
- ### 3. fixRoleAttributes(directory)
163
- Thêm role attributes cho các elements
152
+ ## 🔧 What Gets Fixed
164
153
 
165
- ```javascript
166
- const results = await fixer.fixRoleAttributes('./src');
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
- ### 4. cleanupDuplicateRoles(directory)
170
- Xóa duplicate role attributes
159
+ ```html
160
+ <!-- Before -->
161
+ <img src="logo.png">
162
+ <img src="chart.jpg" alt="">
171
163
 
172
- ```javascript
173
- const results = await fixer.cleanupDuplicateRoles('./src');
164
+ <!-- After -->
165
+ <img src="logo.png" alt="ロゴ">
166
+ <img src="chart.jpg" alt="グラフ">
174
167
  ```
175
168
 
176
- ### 5. fixAllAccessibilityIssues(directory)
177
- Chạy tất cả fixes bao gồm cleanup (khuyến nghị)
169
+ ### 2. HTML Lang Attributes
170
+ - **Missing lang attributes** Adds specified language
171
+ - **Empty lang attributes** → Sets proper language code
178
172
 
179
- ```javascript
180
- const results = await fixer.fixAllAccessibilityIssues('./src');
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
- ```javascript
187
- const suggestions = await fixer.addMainLandmarks('./src');
178
+ <!-- After -->
179
+ <html lang="ja">
180
+ <html lang="ja">
188
181
  ```
189
182
 
190
- ## 🎯 dụ kết quả
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
- <!-- Trước -->
195
- <img src="logo.png">
196
- <img src="icon.png" alt="">
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
- <!-- Sau -->
199
- <img src="logo.png" alt="ロゴ">
200
- <img src="icon.png" alt="アイコン">
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
- ### Role Attributes
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>
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
- <!-- 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>
208
+ <!-- Before -->
209
+ <img src="test.jpg" role="img" role="img" alt="Test">
222
210
 
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>
211
+ <!-- After -->
212
+ <img src="test.jpg" role="img" alt="Test">
227
213
  ```
228
214
 
229
- ### Lang Attributes
230
- ```html
231
- <!-- Trước -->
232
- <html>
215
+ ## 🌟 Smart Alt Text Generation
233
216
 
234
- <!-- Sau -->
235
- <html lang="ja">
236
- ```
217
+ The package uses intelligent context analysis to generate meaningful alt text:
237
218
 
238
- ## 🔧 Customization
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
- ### Thay đổi ngôn ngữ cho alt text
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
- Sửa method `generateAltText` trong `lib/fixer.js`:
235
+ ## 📊 Output Examples
243
236
 
244
- ```javascript
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
- ### Thêm role rules mới
243
+ 🖼️ Step 2: Fixing alt attributes...
244
+ ✅ Fixed alt attributes in 12 files (34 issues)
257
245
 
258
- Sửa method `fixRoleAttributesInContent` để thêm rules:
246
+ 🎭 Step 3: Fixing role attributes...
247
+ ✅ Fixed role attributes in 8 files (67 issues)
259
248
 
260
- ```javascript
261
- // dụ: thêm role cho form elements
262
- fixed = fixed.replace(
263
- /<form([^>]*)(?!.*role\s*=)([^>]*>)/gi,
264
- '<form$1 role="form"$2'
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
- ## 🚨 Lưu ý quan trọng
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
- 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
272
+ ## 🔒 Safety Features
274
273
 
275
- ## 📊 Monitoring Results
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
- 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
280
+ ## 🛠️ Configuration
282
281
 
283
- ```
284
- 📁 index.html:
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
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
- ## 🛠️ Troubleshooting
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
- ### Lỗi "Cannot find module"
297
- ```bash
298
- cd accessibility-package
299
- npm install
303
+ - name: Fix Accessibility Issues
304
+ run: npx gbu-accessibility-package --comprehensive
300
305
  ```
301
306
 
302
- ### Duplicate role attributes
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
- ### Performance với project lớn
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
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 - Tự do sử dụng cho mọi dự án.
317
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
325
318
 
326
- ## 🤝 Contributing
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
- 1. Fork repository
329
- 2. Tạo feature branch
330
- 3. Commit changes
331
- 4. Tạo Pull Request
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
- **Happy coding! 🚀**
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
 
@@ -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([^>]*)(?!.*role\s*=)([^>]*>)/gi,
649
- (match, attrs, end) => {
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 `<img${attrs} role="img"${end}`;
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[^>]*)(?!.*role\s*=)([^>]*>)/gi,
658
- (match, attrs, end) => {
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 `<button${attrs} role="button"${end}`;
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[^>]*)(?!.*role\s*=)([^>]*>)/gi,
667
- (match, attrs, end) => {
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 `<a${attrs} role="link"${end}`;
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[^>]*)(?!.*role\s*=)([^>]*>)/gi,
676
- (match, tag, attrs, end) => {
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 `<${tag}${attrs} role="button"${end}`;
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)[^"]*"[^>]*)(?!.*role\s*=)([^>]*>)/gi,
685
- (match, attrs, end) => {
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 `<div${attrs} role="button"${end}`;
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-]+[""']?[^>]*)(?!.*role\s*=)([^>]*>)/gi,
694
- (match, tag, attrs, end) => {
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 `<${tag}${attrs} role="button"${end}`;
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)[^"]*"[^>]*)(?!.*role\s*=)([^>]*>)/gi,
703
- (match, attrs, end) => {
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 `<ul${attrs} role="menubar"${end}`;
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)[^"]*"[^>]*)(?!.*role\s*=)([^>]*>)/gi,
712
- (match, attrs, end) => {
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 `<li${attrs} role="menuitem"${end}`;
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.1.0",
4
- "description": "Automated accessibility fixes for HTML files - Alt attributes, Lang attributes, Role attributes. Smart context-aware alt text generation and comprehensive role attribute management.",
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
- "test": "node example.js",
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 demo"
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
+ }