wcag-scanner 1.2.64 → 1.2.66

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/README.md CHANGED
@@ -22,13 +22,13 @@ WCAG Scanner is a powerful accessibility testing tool that helps developers iden
22
22
 
23
23
  ## ✨ Features
24
24
 
25
- - **Comprehensive Accessibility Testing**: Scans websites against WCAG 2.1 A, AA, and AAA compliance levels
26
- - **Detailed Reports**: Generates comprehensive reports highlighting issues with severity ratings
27
- - **Actionable Recommendations**: Provides specific guidance on how to fix identified issues
28
- - **Integration with Development Workflows**: CI/CD integration via GitHub Actions, GitLab CI, etc.
29
- - **Custom Rule Configuration**: Tailor scanning criteria to your project's specific needs
30
- - **Interactive Dashboard**: Visual representation of accessibility issues with filtering capabilities
31
- - **Performance Optimization**: Minimal impact on development and build processes
25
+ - **WCAG 2.1 Compliance Scanning**: Checks against A, AA, and AAA conformance levels
26
+ - **6 Built-in Rules**: Images, contrast, forms, ARIA, structure, and keyboard accessibility
27
+ - **React Dev Overlay**: Live in-browser inspector with element highlighting, pinning, and impact filtering
28
+ - **AI Fix Suggestions**: Paste your Gemini API key in the overlay settings to get instant fix suggestions per violation
29
+ - **Programmatic API**: Scan HTML strings or local files from Node.js
30
+ - **Express Middleware**: Auto-scan responses in your Express app
31
+ - **Multiple Report Formats**: JSON, HTML, and console output
32
32
 
33
33
  ## 📦 Installation
34
34
 
@@ -43,105 +43,82 @@ yarn add wcag-scanner
43
43
  pnpm add wcag-scanner
44
44
  ```
45
45
 
46
- > **React users:** React and React DOM are peer dependencies and are already installed in your project — no extra steps needed.
46
+ > **React users:** React and React DOM are peer dependencies already in your project — no extra install needed.
47
47
 
48
- ### For the React Dev Overlay
48
+ ## 🖥️ React Dev Overlay
49
49
 
50
- Add one line to your app entry point (`main.ts`, `index.js`, `App.tsx`, etc.):
50
+ The easiest way to use wcag-scanner in a React app. Add **one line** to your entry file and a live accessibility inspector appears in the corner of your browser during development.
51
51
 
52
52
  ```ts
53
+ // main.ts / main.jsx / index.tsx — works with any file type
53
54
  import { initWcagOverlay } from 'wcag-scanner/react';
54
- initWcagOverlay(); // shows a live WCAG inspector in the browser, dev only
55
+
56
+ initWcagOverlay(); // auto-disabled in production
57
+ ```
58
+
59
+ **Options:**
60
+ ```ts
61
+ initWcagOverlay({
62
+ level: 'AA', // 'A' | 'AA' | 'AAA' — default: 'AA'
63
+ position: 'bottom-right', // 'bottom-right' | 'bottom-left'
64
+ debounce: 750, // ms to wait after DOM change before rescanning
65
+ rules: ['images', 'contrast'], // run a subset of rules only
66
+ });
55
67
  ```
56
68
 
57
- The overlay is automatically disabled in production (`NODE_ENV=production`) and never ships to your users.
69
+ **Features:**
70
+ - Hover over a violation to highlight the element on the page
71
+ - Click to pin the highlight; click again to unpin
72
+ - Expand any violation card for the HTML snippet, element path, WCAG criteria, and fix hint
73
+ - Filter by impact level (critical / serious / moderate / minor)
74
+ - Drag the panel anywhere on screen
75
+ - Keyboard shortcut `Alt+Shift+W` to toggle open/close
76
+ - **⚙ Settings** — paste a free Google Gemini API key to get AI-powered fix suggestions per violation
58
77
 
59
- ## How to use
60
- ### CLI Usage Example:
78
+ > The overlay never runs in production (`NODE_ENV=production`) and is never included in your production bundle.
61
79
 
62
- ```bash
63
- # Scan a file
64
- npx wcag-scanner file index.html --level AA --format console
80
+ ## 🔧 Programmatic API
81
+
82
+ Scan HTML strings or local files from Node.js scripts, CI pipelines, or build tools.
83
+
84
+ ```js
85
+ import { scanHtml, scanFile, formatReport, saveReport } from 'wcag-scanner';
65
86
 
66
- # Scan a URL
67
- npx wcag-scanner url https://example.com --format html --output report.html
87
+ // Scan an HTML string
88
+ const results = await scanHtml('<img src="logo.png">', { level: 'AA' });
89
+ console.log(`${results.violations.length} violations found`);
90
+
91
+ // Scan a local HTML file
92
+ const results = await scanFile('./public/index.html', { level: 'AA' });
93
+
94
+ // Generate and save a report
95
+ const html = formatReport(results, 'html'); // 'html' | 'json' | 'console'
96
+ saveReport(html, 'accessibility-report.html');
68
97
  ```
69
98
 
70
- ### Express Middleware Usage Example:
99
+ ## 🌐 Express Middleware
71
100
 
72
- ```JavaScript
101
+ Automatically scan every HTML response in your Express app and inject a violation badge.
102
+
103
+ ```js
73
104
  import express from 'express';
74
105
  import { middleware } from 'wcag-scanner';
75
106
 
76
107
  const app = express();
77
108
 
78
- // Add the WCAG scanner middleware
79
109
  app.use(middleware.express.createMiddleware({
80
- enabled: true,
81
- level: 'AA',
82
- headerName: 'X-WCAG-Violations',
83
- inlineReport: true,
84
- onViolation: (results, req, res) => {
85
- console.log(`Found ${results.violations.length} accessibility issues in ${req.path}`);
86
- }
110
+ enabled: true,
111
+ level: 'AA',
112
+ headerName: 'X-WCAG-Violations', // violation count added to response headers
113
+ inlineReport: true, // inject a small widget into the HTML response
114
+ onViolation: (results, req) => {
115
+ console.log(`${results.violations.length} issues on ${req.path}`);
116
+ },
87
117
  }));
88
118
 
89
- // Your routes
90
119
  app.get('/', (req, res) => {
91
- res.send(`
92
- <!DOCTYPE html>
93
- <html>
94
- <head>
95
- <title>Test Page</title>
96
- </head>
97
- <body>
98
- <h1>Hello World</h1>
99
- <img src="logo.png"> <!-- Missing alt text will trigger violation -->
100
- </body>
101
- </html>
102
- `);
120
+ res.send(`<!DOCTYPE html><html><body><h1>Hello</h1></body></html>`);
103
121
  });
104
122
 
105
- app.listen(3000, () => {
106
- console.log('Server running on http://localhost:3000');
107
- });
108
- ```
109
-
110
- ### Programmatic API Usage Example:
111
- ```JavaScript
112
- import { scanHtml, scanUrl, formatReport } from 'wcag-scanner';
113
-
114
- async function checkMyWebsite() {
115
- try {
116
- // Scan a URL
117
- const results = await scanUrl('https://example.com', { level: 'AA' });
118
-
119
- console.log(`Found ${results.violations.length} accessibility issues`);
120
-
121
- // Generate a report
122
- const htmlReport = formatReport(results, 'html');
123
-
124
- // Save the report
125
- fs.writeFileSync('accessibility-report.html', htmlReport);
126
- } catch (error) {
127
- console.error('Error scanning website:', error);
128
- }
129
- }
130
-
131
- async function checkHtmlString() {
132
- const html = `
133
- <!DOCTYPE html>
134
- <html>
135
- <head>
136
- <title>Test</title>
137
- </head>
138
- <body>
139
- <img src="logo.png"> <!-- Missing alt text -->
140
- </body>
141
- </html>
142
- `;
143
-
144
- const results = await scanHtml(html);
145
- console.log(formatReport(results, 'console'));
146
- }
123
+ app.listen(3000);
147
124
  ```
package/dist/index.d.ts CHANGED
@@ -3,38 +3,19 @@ import { ScannerOptions, ScanResults } from './types';
3
3
  import { ReporterFormat } from './reporters';
4
4
  import middleware from './middleware';
5
5
  /**
6
- * Scan HTML string for WCAG violations
7
- * @param html HTML content to scan
8
- * @param options Scanner options
9
- * @returns Promise<ScanResults> Scan results
6
+ * Scan an HTML string for WCAG violations.
10
7
  */
11
8
  export declare function scanHtml(html: string, options?: ScannerOptions): Promise<ScanResults>;
12
9
  /**
13
- * Scan HTML file for WCAG violations
14
- * @param filePath Path to HTML file
15
- * @param options Scanner options
16
- * @returns Promise<ScanResults> Scan results
10
+ * Scan a local HTML file for WCAG violations.
17
11
  */
18
12
  export declare function scanFile(filePath: string, options?: ScannerOptions): Promise<ScanResults>;
19
13
  /**
20
- * Scan a URL for WCAG violations using Rust/WASM scraping
21
- * @param url URL to scan
22
- * @param options Scanner options
23
- * @returns Promise<ScanResults> Scan results
24
- */
25
- export declare function scanUrl(url: string, options?: ScannerOptions): Promise<ScanResults>;
26
- /**
27
- * Generate a report from scan results
28
- * @param results Scan results
29
- * @param format Report format
30
- * @param options Scanner options
31
- * @returns Report string
14
+ * Generate a report from scan results.
32
15
  */
33
16
  export declare function formatReport(results: ScanResults, format?: ReporterFormat, options?: ScannerOptions): string;
34
17
  /**
35
- * Save report to a file
36
- * @param report Report string
37
- * @param filePath Output file path
18
+ * Save a report string to a file.
38
19
  */
39
20
  export declare function saveReport(report: string, filePath: string): void;
40
21
  export { WCAGScanner };
@@ -44,7 +25,6 @@ export { middleware };
44
25
  declare const _default: {
45
26
  scanHtml: typeof scanHtml;
46
27
  scanFile: typeof scanFile;
47
- scanUrl: typeof scanUrl;
48
28
  formatReport: typeof formatReport;
49
29
  saveReport: typeof saveReport;
50
30
  middleware: {
package/dist/index.js CHANGED
@@ -10,28 +10,6 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
10
10
  if (k2 === undefined) k2 = k;
11
11
  o[k2] = m[k];
12
12
  }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
13
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
15
  };
@@ -42,7 +20,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
42
20
  exports.middleware = exports.WCAGScanner = void 0;
43
21
  exports.scanHtml = scanHtml;
44
22
  exports.scanFile = scanFile;
45
- exports.scanUrl = scanUrl;
46
23
  exports.formatReport = formatReport;
47
24
  exports.saveReport = saveReport;
48
25
  const scanner_1 = require("./scanner");
@@ -52,13 +29,8 @@ const middleware_1 = __importDefault(require("./middleware"));
52
29
  exports.middleware = middleware_1.default;
53
30
  const fs_1 = __importDefault(require("fs"));
54
31
  const path_1 = __importDefault(require("path"));
55
- const crypto_1 = __importDefault(require("crypto"));
56
- const os_1 = __importDefault(require("os"));
57
32
  /**
58
- * Scan HTML string for WCAG violations
59
- * @param html HTML content to scan
60
- * @param options Scanner options
61
- * @returns Promise<ScanResults> Scan results
33
+ * Scan an HTML string for WCAG violations.
62
34
  */
63
35
  async function scanHtml(html, options = {}) {
64
36
  const scanner = new scanner_1.WCAGScanner(options);
@@ -66,24 +38,7 @@ async function scanHtml(html, options = {}) {
66
38
  return scanner.scan();
67
39
  }
68
40
  /**
69
- * Get WASM scraper instance
70
- */
71
- async function getWasmScraper() {
72
- try {
73
- const { default: wasmModule } = await Promise.resolve().then(() => __importStar(require('./wasm')));
74
- await wasmModule.initialize();
75
- return wasmModule;
76
- }
77
- catch (error) {
78
- console.error('Failed to load WASM scraper, falling back to HTTP requests:', error);
79
- return null;
80
- }
81
- }
82
- /**
83
- * Scan HTML file for WCAG violations
84
- * @param filePath Path to HTML file
85
- * @param options Scanner options
86
- * @returns Promise<ScanResults> Scan results
41
+ * Scan a local HTML file for WCAG violations.
87
42
  */
88
43
  async function scanFile(filePath, options = {}) {
89
44
  const html = fs_1.default.readFileSync(path_1.default.resolve(filePath), 'utf8');
@@ -93,91 +48,16 @@ async function scanFile(filePath, options = {}) {
93
48
  return scanner.scan();
94
49
  }
95
50
  /**
96
- * Scan a URL for WCAG violations using Rust/WASM scraping
97
- * @param url URL to scan
98
- * @param options Scanner options
99
- * @returns Promise<ScanResults> Scan results
100
- */
101
- async function scanUrl(url, options = {}) {
102
- console.log(`Scanning URL: ${url}`);
103
- // Create temp directory for saving content
104
- const tempDir = path_1.default.join(os_1.default.tmpdir(), 'wcag-scanner-temp');
105
- if (!fs_1.default.existsSync(tempDir)) {
106
- fs_1.default.mkdirSync(tempDir, { recursive: true });
107
- }
108
- // Generate unique file name
109
- const fileId = crypto_1.default.createHash('md5').update(url + Date.now().toString()).digest('hex').substring(0, 10);
110
- const tempFile = path_1.default.join(tempDir, `${fileId}.html`);
111
- try {
112
- // Get the WASM scraper
113
- const wasmScraper = await getWasmScraper();
114
- let html;
115
- if (wasmScraper) {
116
- // Use WASM scraper
117
- html = await wasmScraper.scrapeUrl(url);
118
- }
119
- else {
120
- // Fallback to simple HTTP request
121
- const response = await fetch(url, {
122
- headers: {
123
- 'User-Agent': 'WCAG-Scanner/1.0-js'
124
- }
125
- });
126
- if (!response.ok) {
127
- throw new Error(`HTTP error: ${response.status}`);
128
- }
129
- html = await response.text();
130
- }
131
- if (!html || html.trim().length === 0) {
132
- throw new Error('Scraper returned empty HTML content');
133
- }
134
- console.log(`Successfully scraped ${html.length} bytes of HTML content`);
135
- // Save content to temp file
136
- fs_1.default.writeFileSync(tempFile, html);
137
- console.log(`Saved scraped content to ${tempFile}`);
138
- // If verbose logging is enabled, show a sample
139
- if (options.verbose) {
140
- console.log('First 200 characters of HTML:');
141
- console.log(html.substring(0, 200) + '...');
142
- }
143
- // Run the scanner on the HTML content
144
- const scanner = new scanner_1.WCAGScanner({
145
- ...options,
146
- baseUrl: url
147
- });
148
- await scanner.loadHTML(html, url);
149
- return scanner.scan();
150
- }
151
- catch (error) {
152
- console.error('Error scanning URL:', error);
153
- throw error;
154
- }
155
- }
156
- /**
157
- * Generate a report from scan results
158
- * @param results Scan results
159
- * @param format Report format
160
- * @param options Scanner options
161
- * @returns Report string
51
+ * Generate a report from scan results.
162
52
  */
163
53
  function formatReport(results, format = 'json', options = {}) {
164
54
  return (0, reporters_1.generateReport)(results, format, options);
165
55
  }
166
56
  /**
167
- * Save report to a file
168
- * @param report Report string
169
- * @param filePath Output file path
57
+ * Save a report string to a file.
170
58
  */
171
59
  function saveReport(report, filePath) {
172
60
  fs_1.default.writeFileSync(filePath, report);
173
61
  }
174
62
  __exportStar(require("./types"), exports);
175
- // Default export with all main functions
176
- exports.default = {
177
- scanHtml,
178
- scanFile,
179
- scanUrl,
180
- formatReport,
181
- saveReport,
182
- middleware: middleware_1.default
183
- };
63
+ exports.default = { scanHtml, scanFile, formatReport, saveReport, middleware: middleware_1.default };
@@ -1,12 +1,8 @@
1
1
  import React from 'react';
2
2
  export interface WcagDevOverlayProps {
3
- /** WCAG conformance level (default: 'AA') */
4
3
  level?: 'A' | 'AA' | 'AAA';
5
- /** Subset of rules to run. Omit to run all. */
6
4
  rules?: string[];
7
- /** Corner to anchor the overlay (default: 'bottom-right') */
8
5
  position?: 'bottom-right' | 'bottom-left';
9
- /** Delay in ms between DOM mutation and re-scan (default: 750) */
10
6
  debounce?: number;
11
7
  }
12
8
  export declare const WcagDevOverlay: React.FC<WcagDevOverlayProps>;