gbu-accessibility-package 3.3.0 → 3.5.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/CHANGELOG.md +19 -0
- package/README-vi.md +12 -3
- package/README.md +12 -3
- package/cli.js +78 -11
- package/demo/heading-structure-test.html +60 -0
- package/demo/nested-controls-test.html +92 -0
- package/lib/fixer.js +995 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.5.0] - 2025-01-08
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Enhanced Heading Structure Auto-Fix**: Automatic fixing of heading hierarchy issues with `--auto-fix-headings` option
|
|
12
|
+
- **Improved Nested Controls Detection**: Better detection and fixing of nested interactive controls
|
|
13
|
+
- **Advanced Test Cases**: New comprehensive test files for heading structure and nested controls
|
|
14
|
+
- **Enhanced Alt Text Quality**: Improved context-aware alt text generation with better vocabulary support
|
|
15
|
+
|
|
16
|
+
### Enhanced
|
|
17
|
+
- **Heading Analysis**: More comprehensive detection of heading issues including empty headings, level skipping, and duplicates
|
|
18
|
+
- **Interactive Controls**: Better handling of complex nested control scenarios
|
|
19
|
+
- **Test Coverage**: Expanded demo files for better testing and validation
|
|
20
|
+
- **Performance**: Optimized processing for large files and complex HTML structures
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- **Heading Level Corrections**: Automatic correction of improper heading hierarchies
|
|
24
|
+
- **Empty Heading Detection**: Better identification and handling of empty headings
|
|
25
|
+
- **Control Nesting Issues**: Improved resolution of nested interactive control conflicts
|
|
26
|
+
|
|
8
27
|
## [3.2.0] - 2024-07-28
|
|
9
28
|
|
|
10
29
|
### Added
|
package/README-vi.md
CHANGED
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
- 🔘 **Button Names** - Sửa buttons rỗng và input buttons không có tên
|
|
19
19
|
- 🔗 **Link Names** - Sửa links rỗng và phát hiện text generic
|
|
20
20
|
- 🏛️ **Landmarks** - Thêm main và navigation landmarks thiếu
|
|
21
|
-
- 📑 **Phân tích Heading** - Phân tích cấu trúc heading với
|
|
21
|
+
- 📑 **Phân tích và Sửa Heading** - Phân tích cấu trúc heading với tùy chọn tự động sửa `--auto-fix-headings`
|
|
22
|
+
- 🎯 **Nested Controls Detection** - Phát hiện và sửa các control tương tác lồng nhau
|
|
22
23
|
- 🔍 **Broken Links Detection** - Phát hiện liên kết bị hỏng và tài nguyên 404
|
|
23
24
|
- 🧹 **Dọn dẹp Duplicate** - Loại bỏ role attributes trùng lặp
|
|
24
25
|
|
|
@@ -148,7 +149,8 @@ Chế độ sửa lỗi:
|
|
|
148
149
|
--buttons-only Sửa button names + dọn dẹp
|
|
149
150
|
--links-only Sửa link names + dọn dẹp
|
|
150
151
|
--landmarks-only Sửa landmarks + dọn dẹp
|
|
151
|
-
--headings-only Phân tích cấu trúc heading
|
|
152
|
+
--headings-only Phân tích cấu trúc heading với tùy chọn tự động sửa
|
|
153
|
+
--auto-fix-headings Bật tự động sửa lỗi heading structure
|
|
152
154
|
--links-check Kiểm tra liên kết bị hỏng và tài nguyên 404
|
|
153
155
|
--cleanup-only Chỉ dọn dẹp role attributes trùng lặp
|
|
154
156
|
|
|
@@ -178,6 +180,8 @@ gbu-a11y -l en ./public
|
|
|
178
180
|
gbu-a11y --alt-only # Sửa alt attributes + dọn dẹp
|
|
179
181
|
gbu-a11y --forms-only # Sửa form labels + dọn dẹp
|
|
180
182
|
gbu-a11y --buttons-only # Sửa button names + dọn dẹp
|
|
183
|
+
gbu-a11y --headings-only # Phân tích heading structure
|
|
184
|
+
gbu-a11y --headings-only --auto-fix-headings # Tự động sửa heading structure
|
|
181
185
|
gbu-a11y --links-check # Kiểm tra liên kết bị hỏng + dọn dẹp
|
|
182
186
|
|
|
183
187
|
# Tính năng enhanced alt attribute
|
|
@@ -308,7 +312,12 @@ console.log("Hoàn thành sửa lỗi với enhanced features:", results);
|
|
|
308
312
|
|
|
309
313
|
- **Lang attributes thiếu** → Phát hiện ngôn ngữ tự động
|
|
310
314
|
- **Landmark thiếu** → Main và navigation landmarks
|
|
311
|
-
- **Cấu trúc heading** → Phân tích và
|
|
315
|
+
- **Cấu trúc heading** → Phân tích và tự động sửa với `--auto-fix-headings`
|
|
316
|
+
- Sửa multiple h1 elements
|
|
317
|
+
- Sửa heading level skipping (h2 → h4)
|
|
318
|
+
- Thêm text cho empty headings
|
|
319
|
+
- Sửa duplicate headings
|
|
320
|
+
- **Nested interactive controls** → Phát hiện và sửa controls lồng nhau
|
|
312
321
|
- **Role attributes** → Gán role tuân thủ WCAG
|
|
313
322
|
|
|
314
323
|
### Kiểm tra liên kết
|
package/README.md
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
- 🔘 **Button Names** - Fix empty buttons and input buttons without names
|
|
18
18
|
- 🔗 **Link Names** - Fix empty links and detect generic link text
|
|
19
19
|
- 🏛️ **Landmarks** - Add missing main and navigation landmarks
|
|
20
|
-
- 📑 **Heading Analysis** - Analyze heading structure with
|
|
20
|
+
- 📑 **Heading Analysis & Auto-Fix** - Analyze heading structure with optional auto-fix using `--auto-fix-headings`
|
|
21
|
+
- 🎯 **Nested Controls Detection** - Detect and fix nested interactive controls
|
|
21
22
|
- 🔍 **Broken Links Detection** - Detect broken links and 404 resources
|
|
22
23
|
- 🧹 **Duplicate Cleanup** - Remove duplicate role attributes
|
|
23
24
|
|
|
@@ -145,7 +146,8 @@ Fix Modes:
|
|
|
145
146
|
--buttons-only Fix button names + cleanup
|
|
146
147
|
--links-only Fix link names + cleanup
|
|
147
148
|
--landmarks-only Fix landmarks + cleanup
|
|
148
|
-
--headings-only Analyze heading structure
|
|
149
|
+
--headings-only Analyze heading structure with optional auto-fix
|
|
150
|
+
--auto-fix-headings Enable automatic heading structure fixes
|
|
149
151
|
--links-check Check for broken links and 404 resources
|
|
150
152
|
--cleanup-only Only cleanup duplicate role attributes
|
|
151
153
|
|
|
@@ -175,6 +177,8 @@ gbu-a11y -l en ./public
|
|
|
175
177
|
gbu-a11y --alt-only # Fix alt attributes + cleanup
|
|
176
178
|
gbu-a11y --forms-only # Fix form labels + cleanup
|
|
177
179
|
gbu-a11y --buttons-only # Fix button names + cleanup
|
|
180
|
+
gbu-a11y --headings-only # Analyze heading structure
|
|
181
|
+
gbu-a11y --headings-only --auto-fix-headings # Auto-fix heading structure
|
|
178
182
|
gbu-a11y --links-check # Check broken links + cleanup
|
|
179
183
|
|
|
180
184
|
# Enhanced alt attribute features
|
|
@@ -298,7 +302,12 @@ console.log('Accessibility fixes completed with enhanced features:', results);
|
|
|
298
302
|
### Document Structure
|
|
299
303
|
- **Missing lang attributes** → Automatic language detection
|
|
300
304
|
- **Missing landmarks** → Main and navigation landmarks
|
|
301
|
-
- **Heading structure** → Analysis and
|
|
305
|
+
- **Heading structure** → Analysis and auto-fix with `--auto-fix-headings`
|
|
306
|
+
- Fix multiple h1 elements
|
|
307
|
+
- Fix heading level skipping (h2 → h4)
|
|
308
|
+
- Add text to empty headings
|
|
309
|
+
- Fix duplicate headings
|
|
310
|
+
- **Nested interactive controls** → Detect and fix nested controls
|
|
302
311
|
- **Role attributes** → WCAG-compliant role assignments
|
|
303
312
|
|
|
304
313
|
### Link Validation
|
package/cli.js
CHANGED
|
@@ -23,16 +23,21 @@ const options = {
|
|
|
23
23
|
langOnly: false,
|
|
24
24
|
roleOnly: false,
|
|
25
25
|
formsOnly: false,
|
|
26
|
+
nestedOnly: false,
|
|
26
27
|
buttonsOnly: false,
|
|
27
28
|
linksOnly: false,
|
|
28
29
|
landmarksOnly: false,
|
|
29
30
|
headingsOnly: false,
|
|
31
|
+
dlOnly: false,
|
|
30
32
|
brokenLinksOnly: false,
|
|
31
33
|
// Enhanced alt options
|
|
32
34
|
enhancedAlt: false,
|
|
33
35
|
altCreativity: 'balanced', // conservative, balanced, creative
|
|
34
36
|
includeEmotions: false,
|
|
35
|
-
strictAltChecking: false
|
|
37
|
+
strictAltChecking: false,
|
|
38
|
+
// Advanced features options
|
|
39
|
+
autoFixHeadings: false,
|
|
40
|
+
fixDescriptionLists: true
|
|
36
41
|
};
|
|
37
42
|
|
|
38
43
|
// Parse arguments
|
|
@@ -80,6 +85,9 @@ for (let i = 0; i < args.length; i++) {
|
|
|
80
85
|
case '--forms-only':
|
|
81
86
|
options.formsOnly = true;
|
|
82
87
|
break;
|
|
88
|
+
case '--nested-only':
|
|
89
|
+
options.nestedOnly = true;
|
|
90
|
+
break;
|
|
83
91
|
case '--buttons-only':
|
|
84
92
|
options.buttonsOnly = true;
|
|
85
93
|
break;
|
|
@@ -92,10 +100,19 @@ for (let i = 0; i < args.length; i++) {
|
|
|
92
100
|
case '--headings-only':
|
|
93
101
|
options.headingsOnly = true;
|
|
94
102
|
break;
|
|
103
|
+
case '--dl-only':
|
|
104
|
+
options.dlOnly = true;
|
|
105
|
+
break;
|
|
95
106
|
case '--links-check':
|
|
96
107
|
case '--broken-links':
|
|
97
108
|
options.brokenLinksOnly = true;
|
|
98
109
|
break;
|
|
110
|
+
case '--auto-fix-headings':
|
|
111
|
+
options.autoFixHeadings = true;
|
|
112
|
+
break;
|
|
113
|
+
case '--no-fix-dl':
|
|
114
|
+
options.fixDescriptionLists = false;
|
|
115
|
+
break;
|
|
99
116
|
case '--enhanced-alt':
|
|
100
117
|
options.enhancedAlt = true;
|
|
101
118
|
break;
|
|
@@ -221,14 +238,16 @@ async function main() {
|
|
|
221
238
|
enhancedAltMode: options.enhancedAlt,
|
|
222
239
|
altCreativity: options.altCreativity,
|
|
223
240
|
includeEmotions: options.includeEmotions,
|
|
224
|
-
strictAltChecking: options.strictAltChecking
|
|
241
|
+
strictAltChecking: options.strictAltChecking,
|
|
242
|
+
autoFixHeadings: options.autoFixHeadings,
|
|
243
|
+
fixDescriptionLists: options.fixDescriptionLists
|
|
225
244
|
});
|
|
226
245
|
|
|
227
246
|
try {
|
|
228
247
|
// Handle different modes - All modes now include cleanup
|
|
229
248
|
if (options.cleanupOnly || options.altOnly || options.langOnly || options.roleOnly ||
|
|
230
|
-
options.formsOnly || options.buttonsOnly || options.linksOnly || options.landmarksOnly ||
|
|
231
|
-
options.headingsOnly || options.brokenLinksOnly) {
|
|
249
|
+
options.formsOnly || options.nestedOnly || options.buttonsOnly || options.linksOnly || options.landmarksOnly ||
|
|
250
|
+
options.headingsOnly || options.dlOnly || options.brokenLinksOnly) {
|
|
232
251
|
// Individual modes - handle each separately, then run cleanup
|
|
233
252
|
} else {
|
|
234
253
|
// Default mode: Run comprehensive fix (all fixes including cleanup)
|
|
@@ -333,6 +352,24 @@ async function main() {
|
|
|
333
352
|
showCompletionMessage(options, 'Form label fixes + cleanup');
|
|
334
353
|
return;
|
|
335
354
|
|
|
355
|
+
} else if (options.nestedOnly) {
|
|
356
|
+
// Fix nested interactive controls + cleanup
|
|
357
|
+
console.log(chalk.blue('🎯 Running nested interactive controls fixes + cleanup...'));
|
|
358
|
+
const nestedResults = await fixer.fixNestedInteractiveControls(options.directory);
|
|
359
|
+
const nestedFixed = nestedResults.filter(r => r.status === 'fixed').length;
|
|
360
|
+
const totalNestedIssues = nestedResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
361
|
+
|
|
362
|
+
console.log(chalk.green(`\n✅ Fixed nested interactive controls in ${nestedFixed} files (${totalNestedIssues} issues)`));
|
|
363
|
+
|
|
364
|
+
// Run cleanup
|
|
365
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
366
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
367
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
368
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
369
|
+
|
|
370
|
+
showCompletionMessage(options, 'Nested interactive controls fixes + cleanup');
|
|
371
|
+
return;
|
|
372
|
+
|
|
336
373
|
} else if (options.buttonsOnly) {
|
|
337
374
|
// Fix button names + cleanup
|
|
338
375
|
console.log(chalk.blue('🔘 Running button name fixes + cleanup...'));
|
|
@@ -388,15 +425,45 @@ async function main() {
|
|
|
388
425
|
return;
|
|
389
426
|
|
|
390
427
|
} else if (options.headingsOnly) {
|
|
391
|
-
//
|
|
392
|
-
console.log(chalk.blue('📑 Running heading
|
|
393
|
-
const headingResults = await fixer.
|
|
394
|
-
const
|
|
428
|
+
// Fix heading structure + cleanup
|
|
429
|
+
console.log(chalk.blue('📑 Running heading structure fixes + cleanup...'));
|
|
430
|
+
const headingResults = await fixer.fixHeadingStructure(options.directory);
|
|
431
|
+
const headingFixed = headingResults.filter(r => r.status === 'fixed').length;
|
|
432
|
+
const totalHeadingIssues = headingResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
433
|
+
const totalHeadingFixes = headingResults.reduce((sum, r) => sum + (r.fixes || 0), 0);
|
|
434
|
+
|
|
435
|
+
console.log(chalk.green(`\n✅ Processed headings in ${headingResults.length} files (${totalHeadingIssues} issues found)`));
|
|
436
|
+
if (options.autoFixHeadings) {
|
|
437
|
+
console.log(chalk.green(`✅ Fixed ${totalHeadingFixes} heading issues automatically`));
|
|
438
|
+
} else {
|
|
439
|
+
console.log(chalk.gray('💡 Use --auto-fix-headings to enable automatic heading fixes'));
|
|
440
|
+
}
|
|
395
441
|
|
|
396
|
-
|
|
397
|
-
console.log(chalk.
|
|
442
|
+
// Run cleanup
|
|
443
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
444
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
445
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
446
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
447
|
+
|
|
448
|
+
showCompletionMessage(options, 'Heading structure fixes + cleanup');
|
|
449
|
+
return;
|
|
450
|
+
|
|
451
|
+
} else if (options.dlOnly) {
|
|
452
|
+
// Fix description lists + cleanup
|
|
453
|
+
console.log(chalk.blue('📋 Running description list fixes + cleanup...'));
|
|
454
|
+
const dlResults = await fixer.fixDescriptionLists(options.directory);
|
|
455
|
+
const dlFixed = dlResults.filter(r => r.status === 'fixed').length;
|
|
456
|
+
const totalDlIssues = dlResults.reduce((sum, r) => sum + (r.issues || 0), 0);
|
|
457
|
+
|
|
458
|
+
console.log(chalk.green(`\n✅ Fixed description lists in ${dlFixed} files (${totalDlIssues} issues)`));
|
|
459
|
+
|
|
460
|
+
// Run cleanup
|
|
461
|
+
console.log(chalk.blue('\n🧹 Running cleanup for duplicate role attributes...'));
|
|
462
|
+
const cleanupResults = await fixer.cleanupDuplicateRoles(options.directory);
|
|
463
|
+
const cleanupFixed = cleanupResults.filter(r => r.status === 'fixed').length;
|
|
464
|
+
console.log(chalk.green(`✅ Cleaned duplicate roles in ${cleanupFixed} files`));
|
|
398
465
|
|
|
399
|
-
showCompletionMessage(options, '
|
|
466
|
+
showCompletionMessage(options, 'Description list fixes + cleanup');
|
|
400
467
|
return;
|
|
401
468
|
|
|
402
469
|
} else if (options.brokenLinksOnly) {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="ja">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Heading Structure Test - Accessibility Issues</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>Heading Structure Test Cases</h1>
|
|
10
|
+
|
|
11
|
+
<!-- Test Case 1: Missing h1 (this will be converted from h2) -->
|
|
12
|
+
<h2>This should be h1</h2>
|
|
13
|
+
<p>Main content of the page</p>
|
|
14
|
+
|
|
15
|
+
<!-- Test Case 2: Multiple h1 elements -->
|
|
16
|
+
<h1>First h1 (should stay)</h1>
|
|
17
|
+
<h1>Second h1 (should become h2)</h1>
|
|
18
|
+
<h1>Third h1 (should become h2)</h1>
|
|
19
|
+
|
|
20
|
+
<!-- Test Case 3: Level skipping -->
|
|
21
|
+
<h2>Section heading</h2>
|
|
22
|
+
<h4>Subsection (skips h3 - should become h3)</h4>
|
|
23
|
+
<h6>Sub-subsection (skips h4, h5 - should become h4)</h6>
|
|
24
|
+
|
|
25
|
+
<!-- Test Case 4: Empty headings -->
|
|
26
|
+
<h3></h3>
|
|
27
|
+
<h4> </h4>
|
|
28
|
+
<h5><span></span></h5>
|
|
29
|
+
|
|
30
|
+
<!-- Test Case 5: Duplicate headings -->
|
|
31
|
+
<h2>Products</h2>
|
|
32
|
+
<p>Some content about products</p>
|
|
33
|
+
<h2>Products</h2>
|
|
34
|
+
<p>More content about products</p>
|
|
35
|
+
|
|
36
|
+
<!-- Test Case 6: Proper structure (should not be changed) -->
|
|
37
|
+
<h2>Proper Section</h2>
|
|
38
|
+
<h3>Proper Subsection</h3>
|
|
39
|
+
<h4>Proper Sub-subsection</h4>
|
|
40
|
+
<p>Content with proper heading hierarchy</p>
|
|
41
|
+
|
|
42
|
+
<!-- Test Case 7: Complex nesting with issues -->
|
|
43
|
+
<h2>Services</h2>
|
|
44
|
+
<h5>Service 1 (should be h3)</h5>
|
|
45
|
+
<h6>Details (should be h4)</h6>
|
|
46
|
+
<h3>Service 2 (correct)</h3>
|
|
47
|
+
<h5>More details (should be h4)</h5>
|
|
48
|
+
|
|
49
|
+
<!-- Test Case 8: Empty headings with context -->
|
|
50
|
+
<div class="section">
|
|
51
|
+
<h3></h3>
|
|
52
|
+
<p>This section talks about our company history and achievements.</p>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<div class="product-info">
|
|
56
|
+
<h4> </h4>
|
|
57
|
+
<p>Our flagship product offers innovative solutions for modern businesses.</p>
|
|
58
|
+
</div>
|
|
59
|
+
</body>
|
|
60
|
+
</html>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="ja">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Nested Interactive Controls Test - Accessibility Issues</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>Nested Interactive Controls Test Cases</h1>
|
|
10
|
+
|
|
11
|
+
<!-- Test Case 1: div[role="button"] containing links (like in the axe error) -->
|
|
12
|
+
<div class="card-buttons" role="button">
|
|
13
|
+
<a href="https://business.mobile.rakuten.co.jp/solution/service/rakuten-ai-for-business/?scid=we_solution09_2504" class="btn btn-secondary" target="_blank" role="link">詳細を見る</a>
|
|
14
|
+
<a href="https://business.mobile.rakuten.co.jp/solution/ai/inquiry/?l=id=solution_ai_inquiry1&scid=we_solution10_2504" class="btn btn-primary" target="_blank" role="link">お問い合わせ</a>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<!-- Test Case 2: Button containing links -->
|
|
18
|
+
<button type="button" onclick="handleClick()">
|
|
19
|
+
<a href="/page1">Link inside button</a>
|
|
20
|
+
<span>Click me</span>
|
|
21
|
+
</button>
|
|
22
|
+
|
|
23
|
+
<!-- Test Case 3: Link containing button -->
|
|
24
|
+
<a href="/page2">
|
|
25
|
+
<button type="button">Button inside link</button>
|
|
26
|
+
</a>
|
|
27
|
+
|
|
28
|
+
<!-- Test Case 4: div[role="button"] containing input -->
|
|
29
|
+
<div role="button" tabindex="0" onclick="submit()">
|
|
30
|
+
<input type="text" placeholder="Search...">
|
|
31
|
+
<span>Submit</span>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Test Case 5: Link containing select -->
|
|
35
|
+
<a href="/settings">
|
|
36
|
+
<select name="language">
|
|
37
|
+
<option value="ja">Japanese</option>
|
|
38
|
+
<option value="en">English</option>
|
|
39
|
+
</select>
|
|
40
|
+
Settings
|
|
41
|
+
</a>
|
|
42
|
+
|
|
43
|
+
<!-- Test Case 6: Button containing textarea -->
|
|
44
|
+
<button type="submit">
|
|
45
|
+
<textarea name="comment" placeholder="Enter comment"></textarea>
|
|
46
|
+
<span>Send</span>
|
|
47
|
+
</button>
|
|
48
|
+
|
|
49
|
+
<!-- Test Case 7: Multiple levels of nesting -->
|
|
50
|
+
<div role="button" tabindex="0">
|
|
51
|
+
<div class="container">
|
|
52
|
+
<a href="/nested">
|
|
53
|
+
<button type="button">Deeply nested</button>
|
|
54
|
+
</a>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!-- Test Case 8: div[role="button"] with tabindex containing interactive elements -->
|
|
59
|
+
<div role="button" tabindex="0" onclick="handleAction()">
|
|
60
|
+
<input type="checkbox" id="agree">
|
|
61
|
+
<label for="agree">I agree</label>
|
|
62
|
+
<a href="/terms">Terms</a>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<!-- Test Case 9: Link containing details/summary -->
|
|
66
|
+
<a href="/info">
|
|
67
|
+
<details>
|
|
68
|
+
<summary>More info</summary>
|
|
69
|
+
<p>Details content</p>
|
|
70
|
+
</details>
|
|
71
|
+
</a>
|
|
72
|
+
|
|
73
|
+
<!-- Test Case 10: Form elements nested in buttons -->
|
|
74
|
+
<button type="button" class="form-button">
|
|
75
|
+
<input type="radio" name="choice" value="1">
|
|
76
|
+
<input type="radio" name="choice" value="2">
|
|
77
|
+
<span>Choose option</span>
|
|
78
|
+
</button>
|
|
79
|
+
|
|
80
|
+
<!-- Test Case 11: Correct structure (should not be flagged) -->
|
|
81
|
+
<div class="card-buttons">
|
|
82
|
+
<a href="/page1" class="btn btn-secondary">詳細を見る</a>
|
|
83
|
+
<a href="/page2" class="btn btn-primary">お問い合わせ</a>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<!-- Test Case 12: Another correct structure -->
|
|
87
|
+
<button type="button" onclick="handleClick()">
|
|
88
|
+
<span>Click me</span>
|
|
89
|
+
<i class="icon"></i>
|
|
90
|
+
</button>
|
|
91
|
+
</body>
|
|
92
|
+
</html>
|