gbu-accessibility-package 3.8.0 → 3.8.1
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 +13 -0
- package/bin/fix.js +140 -0
- package/bin/test.js +71 -0
- package/lib/fixer.js +35 -4
- package/package.json +2 -4
- package/ENHANCED_ALT_FEATURES.md +0 -230
- package/demo/1mb-jpg-example-file.jpg +0 -0
- package/demo/advanced-test.html +0 -44
- package/demo/aria-label-test.html +0 -32
- package/demo/broken-links-test.html +0 -41
- package/demo/comprehensive-test.html +0 -21
- package/demo/dead-code-test.css +0 -68
- package/demo/dead-code-test.html +0 -36
- package/demo/dead-code-test.js +0 -77
- package/demo/demo.js +0 -73
- package/demo/duplicate-roles.html +0 -45
- package/demo/enhanced-alt-test.html +0 -150
- package/demo/form-labels-test.html +0 -87
- package/demo/heading-structure-test.html +0 -60
- package/demo/heading-structure-test.html.backup +0 -60
- package/demo/large-file-demo.css +0 -213
- package/demo/nested-controls-test.html +0 -92
- package/demo/sample.html +0 -47
- package/demo/test-external-links.html +0 -26
- package/demo/unused-files-test.html +0 -31
- package/demo/unused-image.png +0 -1
- package/demo/unused-page.html +0 -11
- package/demo/unused-script.js +0 -12
- package/demo/unused-style.css +0 -10
- package/demo/very-large-file.js +0 -2
- package/example.js +0 -121
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ 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.8.1] - 2025-10-04
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Package Cleanup**: Removed unnecessary files and folders from npm package
|
|
12
|
+
- Excluded `demo/` folder from published package (development examples only)
|
|
13
|
+
- Excluded `ENHANCED_ALT_FEATURES.md` from published package (internal documentation)
|
|
14
|
+
- Excluded `example.js` and test files from published package
|
|
15
|
+
- Updated `.npmignore` and `package.json` files field to ensure clean deployments
|
|
16
|
+
- Reduced package size from ~3MB to ~330KB (unpacked) by removing demo assets
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- **Absolute Path Resolution**: Fixed bug in 404 resources checking where absolute paths (e.g., `/demo/image.png`) were incorrectly resolved from HTML file directory instead of project root
|
|
20
|
+
|
|
8
21
|
## [3.8.0] - 2025-10-03
|
|
9
22
|
|
|
10
23
|
### Added
|
package/bin/fix.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI tool for accessibility fixes
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { program } = require('commander');
|
|
8
|
+
const { AccessibilityFixer } = require('../index');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
|
|
11
|
+
program
|
|
12
|
+
.name('a11y-fix')
|
|
13
|
+
.description('Accessibility fixing CLI tool')
|
|
14
|
+
.version('1.0.0');
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.command('lang')
|
|
18
|
+
.description('Fix HTML lang attributes')
|
|
19
|
+
.option('-d, --directory <dir>', 'Directory to scan', '.')
|
|
20
|
+
.option('-l, --language <lang>', 'Language code', 'ja')
|
|
21
|
+
.option('--no-backup', 'Skip creating backup files')
|
|
22
|
+
.option('--dry-run', 'Show what would be changed without making changes')
|
|
23
|
+
.action(async (options) => {
|
|
24
|
+
try {
|
|
25
|
+
const fixer = new AccessibilityFixer({
|
|
26
|
+
language: options.language,
|
|
27
|
+
backupFiles: options.backup,
|
|
28
|
+
dryRun: options.dryRun
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const results = await fixer.fixHtmlLang(options.directory);
|
|
32
|
+
|
|
33
|
+
const fixed = results.filter(r => r.status === 'fixed').length;
|
|
34
|
+
const errors = results.filter(r => r.status === 'error').length;
|
|
35
|
+
|
|
36
|
+
console.log(chalk.green(`\n✅ Lang attribute fixes completed!`));
|
|
37
|
+
console.log(` Files fixed: ${fixed}`);
|
|
38
|
+
console.log(` Errors: ${errors}`);
|
|
39
|
+
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error(chalk.red(`❌ Error: ${error.message}`));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
program
|
|
47
|
+
.command('alt')
|
|
48
|
+
.description('Fix empty alt attributes')
|
|
49
|
+
.option('-d, --directory <dir>', 'Directory to scan', '.')
|
|
50
|
+
.option('--no-backup', 'Skip creating backup files')
|
|
51
|
+
.option('--dry-run', 'Show what would be changed without making changes')
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
try {
|
|
54
|
+
const fixer = new AccessibilityFixer({
|
|
55
|
+
backupFiles: options.backup,
|
|
56
|
+
dryRun: options.dryRun
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const results = await fixer.fixEmptyAltAttributes(options.directory);
|
|
60
|
+
|
|
61
|
+
const fixed = results.filter(r => r.status === 'fixed').length;
|
|
62
|
+
const errors = results.filter(r => r.status === 'error').length;
|
|
63
|
+
|
|
64
|
+
console.log(chalk.green(`\n✅ Alt attribute fixes completed!`));
|
|
65
|
+
console.log(` Files fixed: ${fixed}`);
|
|
66
|
+
console.log(` Errors: ${errors}`);
|
|
67
|
+
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error(chalk.red(`❌ Error: ${error.message}`));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
program
|
|
75
|
+
.command('role')
|
|
76
|
+
.description('Fix role attributes')
|
|
77
|
+
.option('-d, --directory <dir>', 'Directory to scan', '.')
|
|
78
|
+
.option('--no-backup', 'Skip creating backup files')
|
|
79
|
+
.option('--dry-run', 'Show what would be changed without making changes')
|
|
80
|
+
.action(async (options) => {
|
|
81
|
+
try {
|
|
82
|
+
const fixer = new AccessibilityFixer({
|
|
83
|
+
backupFiles: options.backup,
|
|
84
|
+
dryRun: options.dryRun
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const results = await fixer.fixRoleAttributes(options.directory);
|
|
88
|
+
|
|
89
|
+
const fixed = results.filter(r => r.status === 'fixed').length;
|
|
90
|
+
const errors = results.filter(r => r.status === 'error').length;
|
|
91
|
+
|
|
92
|
+
console.log(chalk.green(`\n✅ Role attribute fixes completed!`));
|
|
93
|
+
console.log(` Files fixed: ${fixed}`);
|
|
94
|
+
console.log(` Errors: ${errors}`);
|
|
95
|
+
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error(chalk.red(`❌ Error: ${error.message}`));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
program
|
|
103
|
+
.command('all')
|
|
104
|
+
.description('Run all automated fixes')
|
|
105
|
+
.option('-d, --directory <dir>', 'Directory to scan', '.')
|
|
106
|
+
.option('-l, --language <lang>', 'Language code', 'ja')
|
|
107
|
+
.option('--no-backup', 'Skip creating backup files')
|
|
108
|
+
.option('--dry-run', 'Show what would be changed without making changes')
|
|
109
|
+
.action(async (options) => {
|
|
110
|
+
try {
|
|
111
|
+
const fixer = new AccessibilityFixer({
|
|
112
|
+
language: options.language,
|
|
113
|
+
backupFiles: options.backup,
|
|
114
|
+
dryRun: options.dryRun
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
console.log(chalk.blue('🔧 Running all accessibility fixes...\n'));
|
|
118
|
+
|
|
119
|
+
await fixer.fixHtmlLang(options.directory);
|
|
120
|
+
await fixer.fixEmptyAltAttributes(options.directory);
|
|
121
|
+
await fixer.fixRoleAttributes(options.directory);
|
|
122
|
+
|
|
123
|
+
const suggestions = await fixer.addMainLandmarks(options.directory);
|
|
124
|
+
|
|
125
|
+
if (suggestions.length > 0) {
|
|
126
|
+
console.log(chalk.yellow('\n📋 Manual fixes needed:'));
|
|
127
|
+
suggestions.forEach(suggestion => {
|
|
128
|
+
console.log(` ${suggestion.file}: ${suggestion.recommendation}`);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log(chalk.green('\n✅ All automated fixes completed!'));
|
|
133
|
+
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error(chalk.red(`❌ Error: ${error.message}`));
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
program.parse();
|
package/bin/test.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI tool for accessibility testing
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { program } = require('commander');
|
|
8
|
+
const { AccessibilityTester } = require('../index');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
|
|
11
|
+
program
|
|
12
|
+
.name('a11y-test')
|
|
13
|
+
.description('Accessibility testing CLI tool')
|
|
14
|
+
.version('1.0.0');
|
|
15
|
+
|
|
16
|
+
program
|
|
17
|
+
.command('run')
|
|
18
|
+
.description('Run accessibility tests')
|
|
19
|
+
.option('-u, --base-url <url>', 'Base URL for testing', 'http://localhost:8080')
|
|
20
|
+
.option('-p, --port <port>', 'Server port', '8080')
|
|
21
|
+
.option('-o, --output <dir>', 'Output directory', 'accessibility-reports')
|
|
22
|
+
.option('-f, --files <files...>', 'HTML files to test')
|
|
23
|
+
.action(async (options) => {
|
|
24
|
+
try {
|
|
25
|
+
const tester = new AccessibilityTester({
|
|
26
|
+
baseUrl: options.baseUrl,
|
|
27
|
+
serverPort: parseInt(options.port),
|
|
28
|
+
outputDir: options.output,
|
|
29
|
+
pages: options.files || []
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Auto-discover pages if none specified
|
|
33
|
+
if (!options.files || options.files.length === 0) {
|
|
34
|
+
console.log(chalk.yellow('No files specified, auto-discovering HTML files...'));
|
|
35
|
+
const fs = require('fs').promises;
|
|
36
|
+
const files = await fs.readdir('.');
|
|
37
|
+
const htmlFiles = files.filter(f => f.endsWith('.html'));
|
|
38
|
+
tester.config.pages = htmlFiles;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const server = await tester.startServer();
|
|
42
|
+
const results = await tester.testPages();
|
|
43
|
+
|
|
44
|
+
// Kill server
|
|
45
|
+
server.kill();
|
|
46
|
+
|
|
47
|
+
const summary = await tester.generateSummary();
|
|
48
|
+
|
|
49
|
+
console.log(chalk.green('\n✅ Testing completed!'));
|
|
50
|
+
console.log(chalk.blue(`📊 Summary:`));
|
|
51
|
+
console.log(` Files tested: ${summary.totalFiles}`);
|
|
52
|
+
console.log(` Total violations: ${summary.totalViolations}`);
|
|
53
|
+
console.log(` Total passes: ${summary.totalPasses}`);
|
|
54
|
+
|
|
55
|
+
if (Object.keys(summary.violationsByType).length > 0) {
|
|
56
|
+
console.log(chalk.yellow('\n🔍 Common violations:'));
|
|
57
|
+
Object.entries(summary.violationsByType)
|
|
58
|
+
.sort(([,a], [,b]) => b - a)
|
|
59
|
+
.slice(0, 5)
|
|
60
|
+
.forEach(([type, count]) => {
|
|
61
|
+
console.log(` ${type}: ${count}`);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error(chalk.red(`❌ Error: ${error.message}`));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
program.parse();
|
package/lib/fixer.js
CHANGED
|
@@ -3106,13 +3106,14 @@ class AccessibilityFixer {
|
|
|
3106
3106
|
async checkLocalFile(url, baseDir, resourceType, elementType) {
|
|
3107
3107
|
const path = require('path');
|
|
3108
3108
|
|
|
3109
|
-
// Handle
|
|
3109
|
+
// Handle different URL types
|
|
3110
3110
|
let filePath;
|
|
3111
3111
|
if (url.startsWith('/')) {
|
|
3112
|
-
// Absolute path from web root -
|
|
3113
|
-
|
|
3112
|
+
// Absolute path from web root - find project root and resolve from there
|
|
3113
|
+
const projectRoot = this.findProjectRoot(baseDir);
|
|
3114
|
+
filePath = path.join(projectRoot, url.substring(1));
|
|
3114
3115
|
} else {
|
|
3115
|
-
// Relative path
|
|
3116
|
+
// Relative path - resolve relative to current HTML file directory
|
|
3116
3117
|
filePath = path.resolve(baseDir, url);
|
|
3117
3118
|
}
|
|
3118
3119
|
|
|
@@ -3126,11 +3127,41 @@ class AccessibilityFixer {
|
|
|
3126
3127
|
suggestion: `Create the missing file or update the ${resourceType.toLowerCase()} path`,
|
|
3127
3128
|
url: url,
|
|
3128
3129
|
filePath: filePath,
|
|
3130
|
+
resolvedPath: filePath,
|
|
3129
3131
|
resourceType: resourceType
|
|
3130
3132
|
};
|
|
3131
3133
|
}
|
|
3132
3134
|
}
|
|
3133
3135
|
|
|
3136
|
+
// Helper method to find project root directory
|
|
3137
|
+
findProjectRoot(startDir) {
|
|
3138
|
+
const path = require('path');
|
|
3139
|
+
const fs = require('fs');
|
|
3140
|
+
|
|
3141
|
+
let currentDir = startDir;
|
|
3142
|
+
const root = path.parse(currentDir).root;
|
|
3143
|
+
|
|
3144
|
+
// Look for common project root indicators
|
|
3145
|
+
while (currentDir !== root) {
|
|
3146
|
+
// Check for package.json, .git, or other project indicators
|
|
3147
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
3148
|
+
const gitPath = path.join(currentDir, '.git');
|
|
3149
|
+
const nodeModulesPath = path.join(currentDir, 'node_modules');
|
|
3150
|
+
|
|
3151
|
+
if (fs.existsSync(packageJsonPath) || fs.existsSync(gitPath) || fs.existsSync(nodeModulesPath)) {
|
|
3152
|
+
return currentDir;
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
// Move up one directory
|
|
3156
|
+
const parentDir = path.dirname(currentDir);
|
|
3157
|
+
if (parentDir === currentDir) break; // Reached filesystem root
|
|
3158
|
+
currentDir = parentDir;
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
// If no project root found, use the original baseDir (fallback)
|
|
3162
|
+
return startDir;
|
|
3163
|
+
}
|
|
3164
|
+
|
|
3134
3165
|
// Analyze headings (no auto-fix, only suggestions)
|
|
3135
3166
|
async analyzeHeadings(directory = '.') {
|
|
3136
3167
|
console.log(chalk.blue('📑 Analyzing heading structure...'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gbu-accessibility-package",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.1",
|
|
4
4
|
"description": "Comprehensive accessibility fixes and project optimization for HTML files. Smart context-aware alt text generation, form labels, button names, link names, landmarks, heading analysis, WCAG-compliant role attributes, unused files detection, dead code analysis, broken external links detection, and missing local resources detection. Covers major axe DevTools issues with individual fix modes.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -82,16 +82,14 @@
|
|
|
82
82
|
},
|
|
83
83
|
"files": [
|
|
84
84
|
"lib/",
|
|
85
|
+
"bin/",
|
|
85
86
|
"index.js",
|
|
86
87
|
"cli.js",
|
|
87
|
-
"example.js",
|
|
88
|
-
"demo/",
|
|
89
88
|
"README.md",
|
|
90
89
|
"README-vi.md",
|
|
91
90
|
"CHANGELOG.md",
|
|
92
91
|
"QUICK_START.md",
|
|
93
92
|
"PACKAGE_SUMMARY.md",
|
|
94
|
-
"ENHANCED_ALT_FEATURES.md",
|
|
95
93
|
"LICENSE"
|
|
96
94
|
],
|
|
97
95
|
"dependencies": {
|
package/ENHANCED_ALT_FEATURES.md
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
# Enhanced Alt Attribute Features
|
|
2
|
-
|
|
3
|
-
## Tổng quan
|
|
4
|
-
|
|
5
|
-
Enhanced Alt Attribute features là bộ tính năng cải tiến cho việc kiểm tra và tạo alt text đa dạng, thông minh hơn so với phiên bản cơ bản.
|
|
6
|
-
|
|
7
|
-
## Tính năng chính
|
|
8
|
-
|
|
9
|
-
### 🔍 **Phân tích toàn diện**
|
|
10
|
-
- **Phân loại hình ảnh**: Tự động phân loại hình ảnh theo mục đích (decorative, functional, complex, logo, data-visualization, etc.)
|
|
11
|
-
- **Kiểm tra chất lượng nội dung**: Phát hiện alt text quá dài/ngắn, từ thừa, generic text
|
|
12
|
-
- **Phân tích ngữ cảnh**: Hiểu context xung quanh hình ảnh để tạo alt text phù hợp
|
|
13
|
-
- **Kiểm tra tính nhất quán**: So sánh alt text với aria-label, title attributes
|
|
14
|
-
|
|
15
|
-
### 🎨 **Tạo alt text đa dạng**
|
|
16
|
-
- **Context-aware generation**: Dựa trên heading, paragraph, figcaption xung quanh
|
|
17
|
-
- **Semantic analysis**: Phân tích semantic từ src và context
|
|
18
|
-
- **Emotional context**: Thêm cảm xúc và tone phù hợp
|
|
19
|
-
- **Brand awareness**: Nhận diện và tích hợp thông tin thương hiệu
|
|
20
|
-
- **Technical descriptions**: Mô tả chuyên sâu cho biểu đồ, sơ đồ
|
|
21
|
-
|
|
22
|
-
### 🌐 **Đa ngôn ngữ**
|
|
23
|
-
- **Japanese (ja)**: Từ vựng phong phú, ngữ pháp chính xác
|
|
24
|
-
- **English (en)**: Vocabulary đa dạng, grammar tự nhiên
|
|
25
|
-
- **Vietnamese (vi)**: Hỗ trợ tiếng Việt với từ vựng phù hợp
|
|
26
|
-
|
|
27
|
-
## Cách sử dụng
|
|
28
|
-
|
|
29
|
-
### CLI Commands
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
# Bật enhanced alt mode
|
|
33
|
-
node cli.js --enhanced-alt
|
|
34
|
-
|
|
35
|
-
# Chọn mức độ creativity
|
|
36
|
-
node cli.js --enhanced-alt --alt-creativity conservative # Đơn giản, factual
|
|
37
|
-
node cli.js --enhanced-alt --alt-creativity balanced # Cân bằng (default)
|
|
38
|
-
node cli.js --enhanced-alt --alt-creativity creative # Phong phú, sáng tạo
|
|
39
|
-
|
|
40
|
-
# Thêm emotional context
|
|
41
|
-
node cli.js --enhanced-alt --include-emotions
|
|
42
|
-
|
|
43
|
-
# Kiểm tra strict quality
|
|
44
|
-
node cli.js --enhanced-alt --strict-alt
|
|
45
|
-
|
|
46
|
-
# Kết hợp các options
|
|
47
|
-
node cli.js --enhanced-alt --alt-creativity creative --include-emotions --strict-alt
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Programmatic Usage
|
|
51
|
-
|
|
52
|
-
```javascript
|
|
53
|
-
const { AccessibilityFixer, EnhancedAltChecker } = require('gbu-accessibility-package');
|
|
54
|
-
|
|
55
|
-
// Sử dụng AccessibilityFixer với enhanced mode
|
|
56
|
-
const fixer = new AccessibilityFixer({
|
|
57
|
-
language: 'ja',
|
|
58
|
-
enhancedAltMode: true,
|
|
59
|
-
altCreativity: 'creative',
|
|
60
|
-
includeEmotions: true,
|
|
61
|
-
strictAltChecking: true
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
await fixer.fixEmptyAltAttributes('./src');
|
|
65
|
-
|
|
66
|
-
// Sử dụng EnhancedAltChecker riêng biệt
|
|
67
|
-
const checker = new EnhancedAltChecker({
|
|
68
|
-
language: 'en',
|
|
69
|
-
strictMode: true
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const issues = checker.analyzeAltAttributes(htmlContent);
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Ví dụ cải tiến
|
|
76
|
-
|
|
77
|
-
### Before (Basic mode):
|
|
78
|
-
```html
|
|
79
|
-
<img src="company-logo.png">
|
|
80
|
-
<!-- Generates: alt="ロゴ" -->
|
|
81
|
-
|
|
82
|
-
<img src="sales-chart.png" alt="">
|
|
83
|
-
<!-- Generates: alt="グラフ" -->
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### After (Enhanced mode):
|
|
87
|
-
```html
|
|
88
|
-
<img src="company-logo.png">
|
|
89
|
-
<!-- Generates: alt="Technology company logo" -->
|
|
90
|
-
|
|
91
|
-
<img src="sales-chart.png" alt="">
|
|
92
|
-
<!-- Context: "Sales increased 25% this quarter" -->
|
|
93
|
-
<!-- Generates: alt="Sales performance chart showing 25% increase" -->
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Creativity Levels
|
|
97
|
-
|
|
98
|
-
### Conservative
|
|
99
|
-
- Mô tả đơn giản, factual
|
|
100
|
-
- Tập trung vào chức năng cơ bản
|
|
101
|
-
- Ít từ vựng đa dạng
|
|
102
|
-
|
|
103
|
-
**Example**: `alt="Chart"`, `alt="Logo"`
|
|
104
|
-
|
|
105
|
-
### Balanced (Default)
|
|
106
|
-
- Context-aware descriptions
|
|
107
|
-
- Vừa phải về creativity
|
|
108
|
-
- Cân bằng giữa đơn giản và chi tiết
|
|
109
|
-
|
|
110
|
-
**Example**: `alt="Sales performance chart"`, `alt="Company logo"`
|
|
111
|
-
|
|
112
|
-
### Creative
|
|
113
|
-
- Mô tả phong phú, chi tiết
|
|
114
|
-
- Tích hợp emotional context
|
|
115
|
-
- Brand và context awareness cao
|
|
116
|
-
|
|
117
|
-
**Example**: `alt="Dynamic sales performance chart showing impressive 25% quarterly growth"`, `alt="Innovative technology company logo representing digital transformation"`
|
|
118
|
-
|
|
119
|
-
## Image Type Classification
|
|
120
|
-
|
|
121
|
-
### Decorative Images
|
|
122
|
-
- **Detection**: Border, pattern, texture images
|
|
123
|
-
- **Recommendation**: `alt=""`
|
|
124
|
-
- **Rationale**: Không cần mô tả cho screen readers
|
|
125
|
-
|
|
126
|
-
### Functional Icons
|
|
127
|
-
- **Detection**: Icons trong buttons, links
|
|
128
|
-
- **Recommendation**: Mô tả chức năng
|
|
129
|
-
- **Example**: `alt="Open chat"`, `alt="Search"`
|
|
130
|
-
|
|
131
|
-
### Data Visualizations
|
|
132
|
-
- **Detection**: Charts, graphs, diagrams
|
|
133
|
-
- **Recommendation**: Mô tả loại + xu hướng + data
|
|
134
|
-
- **Example**: `alt="Bar chart showing 40% increase in user engagement"`
|
|
135
|
-
|
|
136
|
-
### Complex Images
|
|
137
|
-
- **Detection**: Flowcharts, maps, architectural diagrams
|
|
138
|
-
- **Recommendation**: Alt ngắn + longdesc hoặc mô tả chi tiết
|
|
139
|
-
- **Example**: `alt="System architecture diagram"` + detailed description
|
|
140
|
-
|
|
141
|
-
### Logos
|
|
142
|
-
- **Detection**: Logo keywords, brand context
|
|
143
|
-
- **Recommendation**: Brand name + "logo"
|
|
144
|
-
- **Example**: `alt="Microsoft logo"`, `alt="GBU company logo"`
|
|
145
|
-
|
|
146
|
-
## Quality Checks
|
|
147
|
-
|
|
148
|
-
### Error Level Issues
|
|
149
|
-
- ❌ **Missing alt attribute**
|
|
150
|
-
- ❌ **Empty alt for content images**
|
|
151
|
-
- ❌ **Generic alt text** ("click here", "read more")
|
|
152
|
-
- ❌ **Missing data description** (for charts without trend info)
|
|
153
|
-
|
|
154
|
-
### Warning Level Issues
|
|
155
|
-
- ⚠️ **Alt text too long** (>125 characters)
|
|
156
|
-
- ⚠️ **Alt text too short** (<3 characters for content)
|
|
157
|
-
- ⚠️ **Redundant words** ("image", "picture", "photo")
|
|
158
|
-
- ⚠️ **Filename in alt text**
|
|
159
|
-
- ⚠️ **Inconsistent labels** (alt ≠ aria-label)
|
|
160
|
-
|
|
161
|
-
### Info Level Issues
|
|
162
|
-
- ℹ️ **Redundant title attribute**
|
|
163
|
-
- ℹ️ **Optimization suggestions**
|
|
164
|
-
|
|
165
|
-
## Testing
|
|
166
|
-
|
|
167
|
-
```bash
|
|
168
|
-
# Test enhanced features
|
|
169
|
-
npm run test-enhanced-alt
|
|
170
|
-
|
|
171
|
-
# Demo enhanced mode
|
|
172
|
-
npm run demo-enhanced
|
|
173
|
-
|
|
174
|
-
# Demo creative mode
|
|
175
|
-
npm run demo-creative
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Configuration Options
|
|
179
|
-
|
|
180
|
-
```javascript
|
|
181
|
-
{
|
|
182
|
-
// Enhanced mode settings
|
|
183
|
-
enhancedAltMode: true, // Enable enhanced features
|
|
184
|
-
altCreativity: 'balanced', // conservative|balanced|creative
|
|
185
|
-
includeEmotions: false, // Add emotional descriptors
|
|
186
|
-
strictAltChecking: false, // Strict quality checking
|
|
187
|
-
|
|
188
|
-
// Alt generation settings
|
|
189
|
-
maxAltLength: 125, // Maximum alt text length
|
|
190
|
-
minAltLength: 3, // Minimum alt text length
|
|
191
|
-
checkDecorative: true, // Check decorative images
|
|
192
|
-
checkInformative: true, // Check informative images
|
|
193
|
-
checkComplex: true, // Check complex images
|
|
194
|
-
|
|
195
|
-
// Language and context
|
|
196
|
-
language: 'ja', // ja|en|vi
|
|
197
|
-
includeBrandContext: true, // Include brand information
|
|
198
|
-
}
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Performance Impact
|
|
202
|
-
|
|
203
|
-
- **Enhanced mode**: ~20-30% slower due to comprehensive analysis
|
|
204
|
-
- **Memory usage**: +15-20% for vocabulary and analysis
|
|
205
|
-
- **Accuracy**: 85-90% improvement in alt text quality
|
|
206
|
-
- **Coverage**: 95%+ detection of alt attribute issues
|
|
207
|
-
|
|
208
|
-
## Roadmap
|
|
209
|
-
|
|
210
|
-
### v3.2.0 (Planned)
|
|
211
|
-
- [ ] AI-powered image content analysis
|
|
212
|
-
- [ ] Custom vocabulary support
|
|
213
|
-
- [ ] Batch alt text review interface
|
|
214
|
-
- [ ] Integration with design systems
|
|
215
|
-
|
|
216
|
-
### v3.3.0 (Future)
|
|
217
|
-
- [ ] Real-time alt text suggestions
|
|
218
|
-
- [ ] Visual alt text editor
|
|
219
|
-
- [ ] Accessibility score calculation
|
|
220
|
-
- [ ] Team collaboration features
|
|
221
|
-
|
|
222
|
-
## Contributing
|
|
223
|
-
|
|
224
|
-
Enhanced alt features được phát triển với focus vào:
|
|
225
|
-
1. **Accuracy**: Alt text chính xác, phù hợp context
|
|
226
|
-
2. **Diversity**: Đa dạng trong cách mô tả
|
|
227
|
-
3. **Usability**: Dễ sử dụng, configuration linh hoạt
|
|
228
|
-
4. **Performance**: Tối ưu tốc độ xử lý
|
|
229
|
-
|
|
230
|
-
Contributions welcome! Please see main README for guidelines.
|
|
Binary file
|
package/demo/advanced-test.html
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ja">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<title>Advanced Accessibility Test</title>
|
|
6
|
-
</head>
|
|
7
|
-
<body>
|
|
8
|
-
<h1>Advanced Accessibility Test</h1>
|
|
9
|
-
|
|
10
|
-
<!-- Form issues -->
|
|
11
|
-
<form>
|
|
12
|
-
<input type="text" placeholder="Name" aria-label="Name" title="Name" id="text_019747">
|
|
13
|
-
<input type="email" id="email" aria-label="メールアドレス" title="メールアドレス">
|
|
14
|
-
<input type="password" aria-label="パスワード" title="パスワード" id="password_019747">
|
|
15
|
-
<input type="submit">
|
|
16
|
-
</form>
|
|
17
|
-
|
|
18
|
-
<!-- Button issues -->
|
|
19
|
-
<button aria-label="ボタン" title="ボタン"></button>
|
|
20
|
-
<button onclick="alert('test')" role="button" aria-label="ボタン" title="ボタン"></button>
|
|
21
|
-
<input type="button">
|
|
22
|
-
|
|
23
|
-
<!-- Link issues -->
|
|
24
|
-
<a href="/home" role="link" aria-label="リンク" title="リンク"></a>
|
|
25
|
-
<a href="/more" role="link">Click here</a>
|
|
26
|
-
<a href="/read" role="link">Read more</a>
|
|
27
|
-
<a href="/image" role="link" aria-label="リンク" title="リンク"><img src="icon.png" alt="Skipped h2" role="img" aria-label="Skipped h2"></a>
|
|
28
|
-
|
|
29
|
-
<!-- Heading issues -->
|
|
30
|
-
<h3>Skipped h2</h3>
|
|
31
|
-
<h1>Second h1</h1>
|
|
32
|
-
<h4></h4>
|
|
33
|
-
|
|
34
|
-
<!-- Landmark issues -->
|
|
35
|
-
<div class="content">
|
|
36
|
-
<p>Main content without landmark</p>
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<ul class="navigation" role="menubar">
|
|
40
|
-
<li><a href="/home" role="link">Home</a></li>
|
|
41
|
-
<li><a href="/about" role="link">About</a></li>
|
|
42
|
-
</ul>
|
|
43
|
-
</body>
|
|
44
|
-
</html>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ja">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Aria Label Test</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<h1>Aria Label Test Cases</h1>
|
|
10
|
-
|
|
11
|
-
<!-- Test case 1: Image with alt but no aria-label -->
|
|
12
|
-
<img src="test1.jpg" alt="Test image 1" role="img" aria-label="Test image 1">
|
|
13
|
-
|
|
14
|
-
<!-- Test case 2: Image with alt and existing aria-label (should not change) -->
|
|
15
|
-
<img src="test2.jpg" alt="Test image 2" aria-label="Custom label" role="img">
|
|
16
|
-
|
|
17
|
-
<!-- Test case 3: Image with empty alt (should not add aria-label) -->
|
|
18
|
-
<img src="test3.jpg" alt="Aria Label Test Cases" role="img" aria-label="Aria Label Test Cases">
|
|
19
|
-
|
|
20
|
-
<!-- Test case 4: Image without alt (should generate alt and aria-label) -->
|
|
21
|
-
<img src="logo.png" role="img" alt="ロゴ" aria-label="ロゴ">
|
|
22
|
-
|
|
23
|
-
<!-- Test case 5: Picture with role and img with alt -->
|
|
24
|
-
<picture>
|
|
25
|
-
<source srcset="responsive.webp" type="image/webp">
|
|
26
|
-
<img src="responsive.jpg" alt="Responsive image" role="img" aria-label="Responsive image">
|
|
27
|
-
</picture>
|
|
28
|
-
|
|
29
|
-
<!-- Test case 6: Image with role but no aria-label -->
|
|
30
|
-
<img src="test6.jpg" alt="Test image 6" role="img" aria-label="Test image 6">
|
|
31
|
-
</body>
|
|
32
|
-
</html>
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ja">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<title>Broken Links Test</title>
|
|
6
|
-
<!-- Broken CSS -->
|
|
7
|
-
<link rel="stylesheet" href="missing-style.css">
|
|
8
|
-
<!-- Working CSS (if exists) -->
|
|
9
|
-
<link rel="stylesheet" href="../package.json">
|
|
10
|
-
</head>
|
|
11
|
-
<body>
|
|
12
|
-
<h1>Broken Links Test</h1>
|
|
13
|
-
|
|
14
|
-
<!-- Working local link -->
|
|
15
|
-
<a href="advanced-test.html" role="link">Working local link</a>
|
|
16
|
-
|
|
17
|
-
<!-- Broken local link -->
|
|
18
|
-
<a href="non-existent-page.html" role="link">Broken local link</a>
|
|
19
|
-
|
|
20
|
-
<!-- Working external link -->
|
|
21
|
-
<a href="https://www.google.com" role="link">Working external link</a>
|
|
22
|
-
|
|
23
|
-
<!-- Broken external link -->
|
|
24
|
-
<a href="https://this-domain-does-not-exist-12345.com" role="link">Broken external link</a>
|
|
25
|
-
|
|
26
|
-
<!-- Working image -->
|
|
27
|
-
<img src="advanced-test.html" alt="Working image reference" role="img" aria-label="Working image reference">
|
|
28
|
-
|
|
29
|
-
<!-- Broken image -->
|
|
30
|
-
<img src="missing-image.jpg" alt="Broken image" role="img" aria-label="Broken image">
|
|
31
|
-
|
|
32
|
-
<!-- Broken script -->
|
|
33
|
-
<script src="missing-script.js"></script>
|
|
34
|
-
|
|
35
|
-
<!-- Skip patterns -->
|
|
36
|
-
<a href="#anchor" role="link">Anchor link (should skip)</a>
|
|
37
|
-
<a href="mailto:test@example.com" role="link">Email link (should skip)</a>
|
|
38
|
-
<a href="tel:+1234567890" role="link">Phone link (should skip)</a>
|
|
39
|
-
<a href="javascript:void(0)" role="link">JavaScript link (should skip)</a>
|
|
40
|
-
</body>
|
|
41
|
-
</html>
|