accessibility-hub 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/EXAMPLES.md CHANGED
@@ -7,6 +7,7 @@ Ejemplos concretos de inputs y outputs para cada herramienta MCP.
7
7
  - [analyze-with-axe](#analyze-with-axe)
8
8
  - [analyze-with-pa11y](#analyze-with-pa11y)
9
9
  - [analyze-with-eslint](#analyze-with-eslint)
10
+ - [analyze-contrast](#analyze-contrast)
10
11
  - [analyze-all](#analyze-all)
11
12
 
12
13
  ---
@@ -343,6 +344,215 @@ Ejemplos concretos de inputs y outputs para cada herramienta MCP.
343
344
 
344
345
  ---
345
346
 
347
+ ## analyze-contrast
348
+
349
+ ### Ejemplo 1: Análisis básico de contraste
350
+
351
+ **Input:**
352
+ ```json
353
+ {
354
+ "url": "https://example.com"
355
+ }
356
+ ```
357
+
358
+ **Output:**
359
+ ```json
360
+ {
361
+ "success": true,
362
+ "target": "https://example.com",
363
+ "wcagLevel": "AA",
364
+ "issueCount": 3,
365
+ "issues": [
366
+ {
367
+ "id": "contrast-0",
368
+ "ruleId": "color-contrast",
369
+ "tool": "contrast-analyzer",
370
+ "severity": "serious",
371
+ "wcag": {
372
+ "criterion": "1.4.3",
373
+ "level": "AA",
374
+ "principle": "perceivable",
375
+ "version": "2.1",
376
+ "title": "Contrast (Minimum)"
377
+ },
378
+ "location": {
379
+ "selector": "p.subtitle",
380
+ "snippet": "<p class=\"subtitle\">Light gray text on white</p>"
381
+ },
382
+ "message": "Contrast ratio 2.5:1 does not meet AA requirements (4.5:1 required for normal text)",
383
+ "humanContext": "Users with low vision or color blindness may have difficulty reading this text. The current contrast of 2.5:1 is below the AA threshold of 4.5:1.",
384
+ "suggestedActions": [
385
+ "Increase contrast ratio to at least 4.5:1",
386
+ "Consider using #767676 as the text color"
387
+ ],
388
+ "affectedUsers": ["low-vision", "color-blind"],
389
+ "contrastData": {
390
+ "foreground": "rgb(180, 180, 180)",
391
+ "background": "rgb(255, 255, 255)",
392
+ "currentRatio": 2.5,
393
+ "requiredRatio": 4.5,
394
+ "isLargeText": false,
395
+ "fontSize": 16,
396
+ "fontWeight": 400,
397
+ "suggestedFix": {
398
+ "foreground": "#767676",
399
+ "background": "#ffffff",
400
+ "newRatio": 4.54
401
+ }
402
+ }
403
+ }
404
+ ],
405
+ "summary": {
406
+ "total": 25,
407
+ "passing": 22,
408
+ "failing": 3,
409
+ "byTextSize": {
410
+ "normalText": { "passing": 18, "failing": 3 },
411
+ "largeText": { "passing": 4, "failing": 0 }
412
+ }
413
+ },
414
+ "duration": 1234
415
+ }
416
+ ```
417
+
418
+ ---
419
+
420
+ ### Ejemplo 2: Análisis con nivel AAA
421
+
422
+ **Input:**
423
+ ```json
424
+ {
425
+ "url": "https://example.com",
426
+ "options": {
427
+ "wcagLevel": "AAA"
428
+ }
429
+ }
430
+ ```
431
+
432
+ **Output:**
433
+ ```json
434
+ {
435
+ "success": true,
436
+ "target": "https://example.com",
437
+ "wcagLevel": "AAA",
438
+ "issueCount": 8,
439
+ "issues": [
440
+ {
441
+ "id": "contrast-0",
442
+ "ruleId": "color-contrast",
443
+ "tool": "contrast-analyzer",
444
+ "severity": "moderate",
445
+ "wcag": {
446
+ "criterion": "1.4.6",
447
+ "level": "AAA",
448
+ "principle": "perceivable",
449
+ "version": "2.1",
450
+ "title": "Contrast (Enhanced)"
451
+ },
452
+ "message": "Contrast ratio 5.2:1 does not meet AAA requirements (7:1 required for normal text)",
453
+ "contrastData": {
454
+ "foreground": "rgb(100, 100, 100)",
455
+ "background": "rgb(255, 255, 255)",
456
+ "currentRatio": 5.2,
457
+ "requiredRatio": 7,
458
+ "isLargeText": false
459
+ }
460
+ }
461
+ ],
462
+ "summary": {
463
+ "total": 25,
464
+ "passing": 17,
465
+ "failing": 8
466
+ },
467
+ "duration": 1456
468
+ }
469
+ ```
470
+
471
+ ---
472
+
473
+ ### Ejemplo 3: Análisis de sección específica
474
+
475
+ **Input:**
476
+ ```json
477
+ {
478
+ "url": "https://example.com",
479
+ "options": {
480
+ "selector": "#main-content",
481
+ "suggestFixes": true
482
+ }
483
+ }
484
+ ```
485
+
486
+ ---
487
+
488
+ ### Ejemplo 4: HTML con análisis de contraste
489
+
490
+ **Input:**
491
+ ```json
492
+ {
493
+ "html": "<div style='background: #fff'><p style='color: #999'>Low contrast text</p><h1 style='color: #333'>Good contrast heading</h1></div>",
494
+ "options": {
495
+ "wcagLevel": "AA",
496
+ "includePassingElements": true
497
+ }
498
+ }
499
+ ```
500
+
501
+ **Output:**
502
+ ```json
503
+ {
504
+ "success": true,
505
+ "target": "[html content]",
506
+ "wcagLevel": "AA",
507
+ "issueCount": 2,
508
+ "issues": [
509
+ {
510
+ "id": "contrast-0",
511
+ "ruleId": "color-contrast",
512
+ "severity": "serious",
513
+ "message": "Contrast ratio 2.85:1 does not meet AA requirements (4.5:1 required for normal text)",
514
+ "contrastData": {
515
+ "foreground": "rgb(153, 153, 153)",
516
+ "background": "rgb(255, 255, 255)",
517
+ "currentRatio": 2.85,
518
+ "requiredRatio": 4.5,
519
+ "isLargeText": false,
520
+ "suggestedFix": {
521
+ "foreground": "#767676",
522
+ "background": "#ffffff",
523
+ "newRatio": 4.54
524
+ }
525
+ }
526
+ },
527
+ {
528
+ "id": "contrast-1",
529
+ "ruleId": "color-contrast",
530
+ "severity": "minor",
531
+ "message": "Contrast ratio 12.63:1 meets AA requirements (3:1 required for large text)",
532
+ "contrastData": {
533
+ "foreground": "rgb(51, 51, 51)",
534
+ "background": "rgb(255, 255, 255)",
535
+ "currentRatio": 12.63,
536
+ "requiredRatio": 3,
537
+ "isLargeText": true
538
+ }
539
+ }
540
+ ],
541
+ "summary": {
542
+ "total": 2,
543
+ "passing": 1,
544
+ "failing": 1,
545
+ "byTextSize": {
546
+ "normalText": { "passing": 0, "failing": 1 },
547
+ "largeText": { "passing": 1, "failing": 0 }
548
+ }
549
+ },
550
+ "duration": 89
551
+ }
552
+ ```
553
+
554
+ ---
555
+
346
556
  ## analyze-all
347
557
 
348
558
  ### Ejemplo 1: Análisis combinado básico
@@ -550,16 +760,17 @@ Ejemplos concretos de inputs y outputs para cada herramienta MCP.
550
760
 
551
761
  ## Resumen de Diferencias
552
762
 
553
- | Característica | axe-core | Pa11y | ESLint |
554
- |----------------|----------|-------|--------|
555
- | **Target** | URL/HTML | URL/HTML | Archivos .vue |
556
- | **Selector** | CSS compacto | CSS completo | Línea/columna |
557
- | **Severidades** | 4 niveles | 3 tipos | 2 niveles (warn/error) |
558
- | **Snippet** | ✅ | ✅ | ✅ |
559
- | **Confidence** | ✅ | ✅ | Siempre 1 |
560
- | **Browser** | Puppeteer | Puppeteer | - |
561
- | **Velocidad** | ~2-3s | ~2s | <1s |
562
- | **Falsos positivos** | Pocos | Moderados | Muy pocos |
763
+ | Característica | axe-core | Pa11y | ESLint | Contrast |
764
+ |----------------|----------|-------|--------|----------|
765
+ | **Target** | URL/HTML | URL/HTML | Archivos .vue | URL/HTML |
766
+ | **Selector** | CSS compacto | CSS completo | Línea/columna | CSS compacto |
767
+ | **Severidades** | 4 niveles | 3 tipos | 2 niveles | 4 niveles |
768
+ | **Snippet** | ✅ | ✅ | ✅ | ✅ |
769
+ | **Confidence** | ✅ | ✅ | Siempre 1 | Siempre 1 |
770
+ | **Browser** | Puppeteer | Puppeteer | - | Puppeteer |
771
+ | **Velocidad** | ~2-3s | ~2s | <1s | ~1-2s |
772
+ | **Falsos positivos** | Pocos | Moderados | Muy pocos | Muy pocos |
773
+ | **Sugerencias de fix** | - | - | - | ✅ Colores |
563
774
 
564
775
  ---
565
776
 
package/README.md CHANGED
@@ -9,6 +9,7 @@ Servidor MCP para orquestación de herramientas de accesibilidad web (axe-core,
9
9
  - [analyze-with-axe](#analyze-with-axe)
10
10
  - [analyze-with-pa11y](#analyze-with-pa11y)
11
11
  - [analyze-with-eslint](#analyze-with-eslint)
12
+ - [analyze-contrast](#analyze-contrast)
12
13
  - [analyze-all ⭐](#analyze-all-)
13
14
  - [Contexto Humano Enriquecido ✨](#contexto-humano-enriquecido-)
14
15
  - [Estructura del Proyecto](#estructura-del-proyecto)
@@ -104,6 +105,82 @@ Analiza archivos Vue.js para problemas de accesibilidad mediante análisis está
104
105
  - `directory`: Directorio a analizar recursivamente
105
106
  - `code`: Código Vue inline a analizar
106
107
 
108
+ ### `analyze-contrast`
109
+
110
+ Analiza una página web o contenido HTML para detectar problemas de contraste de color según WCAG 2.1.
111
+
112
+ **Parámetros:**
113
+
114
+ | Parámetro | Tipo | Requerido | Descripción |
115
+ |-----------|------|-----------|-------------|
116
+ | `url` | string | url o html | URL de la página a analizar |
117
+ | `html` | string | url o html | Contenido HTML raw a analizar |
118
+ | `options.wcagLevel` | "AA" \| "AAA" | No | Nivel WCAG: AA (4.5:1 normal, 3:1 grande) o AAA (7:1 normal, 4.5:1 grande). Default: AA |
119
+ | `options.suggestFixes` | boolean | No | Sugerir correcciones de color (default: true) |
120
+ | `options.includePassingElements` | boolean | No | Incluir elementos que pasan en los resultados (default: false) |
121
+ | `options.selector` | string | No | Selector CSS para limitar el análisis a un elemento específico |
122
+ | `options.browser.waitForSelector` | string | No | Selector CSS a esperar antes del análisis |
123
+ | `options.browser.viewport` | object | No | Dimensiones del viewport |
124
+ | `options.browser.ignoreHTTPSErrors` | boolean | No | Ignorar errores de certificado SSL (default: false) |
125
+
126
+ **Ejemplo de respuesta:**
127
+
128
+ ```json
129
+ {
130
+ "success": true,
131
+ "target": "https://example.com",
132
+ "wcagLevel": "AA",
133
+ "issueCount": 2,
134
+ "issues": [
135
+ {
136
+ "id": "contrast-0",
137
+ "ruleId": "color-contrast",
138
+ "tool": "contrast-analyzer",
139
+ "severity": "serious",
140
+ "wcag": {
141
+ "criterion": "1.4.3",
142
+ "level": "AA",
143
+ "principle": "perceivable"
144
+ },
145
+ "location": {
146
+ "selector": "p.subtitle",
147
+ "snippet": "<p class=\"subtitle\">Texto de ejemplo</p>"
148
+ },
149
+ "message": "Contrast ratio 3.2:1 does not meet AA requirements (4.5:1 required for normal text)",
150
+ "contrastData": {
151
+ "foreground": "rgb(150, 150, 150)",
152
+ "background": "rgb(255, 255, 255)",
153
+ "currentRatio": 3.2,
154
+ "requiredRatio": 4.5,
155
+ "isLargeText": false,
156
+ "fontSize": 16,
157
+ "fontWeight": 400,
158
+ "suggestedFix": {
159
+ "foreground": "#767676",
160
+ "background": "#ffffff",
161
+ "newRatio": 4.54
162
+ }
163
+ },
164
+ "affectedUsers": ["low-vision", "color-blind"]
165
+ }
166
+ ],
167
+ "summary": {
168
+ "total": 15,
169
+ "passing": 13,
170
+ "failing": 2,
171
+ "byTextSize": {
172
+ "normalText": { "passing": 10, "failing": 2 },
173
+ "largeText": { "passing": 3, "failing": 0 }
174
+ }
175
+ },
176
+ "duration": 1543
177
+ }
178
+ ```
179
+
180
+ **Criterios WCAG:**
181
+ - 1.4.3 Contraste (Mínimo) - Nivel AA
182
+ - 1.4.6 Contraste (Mejorado) - Nivel AAA
183
+
107
184
  ### `analyze-all` ⭐
108
185
 
109
186
  **Tool de síntesis para análisis web** que ejecuta axe-core y Pa11y en paralelo y combina los resultados.
@@ -160,22 +237,34 @@ src/
160
237
  │ ├── base.ts # Clase base para adaptadores
161
238
  │ ├── axe.ts # Adaptador axe-core con Puppeteer
162
239
  │ ├── pa11y.ts # Adaptador Pa11y
163
- └── eslint.ts # Adaptador ESLint Vue a11y
240
+ ├── eslint.ts # Adaptador ESLint Vue a11y
241
+ │ └── contrast.ts # Adaptador de análisis de contraste
164
242
  ├── tools/
165
243
  │ ├── base.ts # Utilidades para tools MCP
166
244
  │ ├── axe.ts # Tool analyze-with-axe
167
245
  │ ├── pa11y.ts # Tool analyze-with-pa11y
168
246
  │ ├── eslint.ts # Tool analyze-with-eslint
247
+ │ ├── contrast.ts # Tool analyze-contrast
169
248
  │ └── analyze-all.ts # Tool de síntesis multi-herramienta
170
249
  ├── types/ # Schemas Zod (inputs, outputs, validación)
250
+ │ └── contrast.ts # Tipos para análisis de contraste
171
251
  ├── normalizers/ # Transformación a formato unificado
172
- └── utils/ # Logger, contexto WCAG
252
+ └── utils/
253
+ ├── logger.ts # Logging estructurado
254
+ ├── wcag-context.ts # Contexto WCAG
255
+ └── color-analysis/ # Utilidades de análisis de color
256
+ ├── contrast.ts # Cálculo de ratios de contraste
257
+ ├── converters.ts # Conversión entre formatos de color
258
+ └── parsers.ts # Parseo de colores CSS
173
259
 
174
260
  tests/
175
261
  ├── adapters/ # Tests unitarios de adaptadores
262
+ │ └── contrast.test.ts
176
263
  ├── tools/ # Tests de integración de tools
177
264
  ├── fixtures/ # HTML con problemas de accesibilidad conocidos
178
- └── helpers/ # Utilidades para tests (mock server, etc.)
265
+ ├── helpers/ # Utilidades para tests (mock server, etc.)
266
+ └── utils/
267
+ └── color-analysis/ # Tests de utilidades de color
179
268
  ```
180
269
 
181
270
  ## Scripts
@@ -315,6 +404,8 @@ Una vez configurado, puedes usar prompts como:
315
404
  - "Revisa este HTML para problemas de accesibilidad: `<img src='foto.jpg'>`"
316
405
  - "Analiza los archivos Vue en src/components/ para problemas de accesibilidad" (usa analyze-with-eslint)
317
406
  - "Compara los resultados de axe-core y Pa11y en mi landing page" (usa analyze-all)
407
+ - "Verifica el contraste de colores de mi página web" (usa analyze-contrast)
408
+ - "Analiza si los colores de texto cumplen con WCAG AAA" (usa analyze-contrast con wcagLevel: AAA)
318
409
 
319
410
  ### Desarrollo Local
320
411
 
package/USAGE.md CHANGED
@@ -101,6 +101,23 @@ Compara los resultados de axe-core y Pa11y en https://ejemplo.com
101
101
 
102
102
  ---
103
103
 
104
+ ### 6. Análisis de Contraste de Colores
105
+
106
+ **Prompt:**
107
+ ```
108
+ Verifica si los colores de texto de https://mi-sitio.com cumplen con WCAG AA
109
+ ```
110
+
111
+ **¿Qué herramienta se usará?**
112
+ → `analyze-contrast`
113
+
114
+ **Resultado esperado:**
115
+ - Ratio de contraste actual vs requerido
116
+ - Sugerencias de colores que cumplan WCAG
117
+ - Estadísticas por tipo de texto (normal/grande)
118
+
119
+ ---
120
+
104
121
  ## Ejemplos por Herramienta
105
122
 
106
123
  ### `analyze-with-axe`
@@ -187,6 +204,61 @@ Analiza todos los archivos Vue en src/components/ para problemas de accesibilida
187
204
 
188
205
  ---
189
206
 
207
+ ### `analyze-contrast`
208
+
209
+ #### Ejemplo 1: Análisis básico de contraste
210
+ ```
211
+ Verifica el contraste de colores de https://example.com
212
+ ```
213
+
214
+ #### Ejemplo 2: Análisis con nivel AAA
215
+ ```
216
+ Analiza el contraste de https://example.com con nivel WCAG AAA
217
+ ```
218
+
219
+ **Input equivalente:**
220
+ ```json
221
+ {
222
+ "url": "https://example.com",
223
+ "options": {
224
+ "wcagLevel": "AAA"
225
+ }
226
+ }
227
+ ```
228
+
229
+ #### Ejemplo 3: Análisis de sección específica
230
+ ```
231
+ Verifica el contraste solo del header de mi página
232
+ ```
233
+
234
+ **Input equivalente:**
235
+ ```json
236
+ {
237
+ "url": "https://example.com",
238
+ "options": {
239
+ "selector": "header",
240
+ "suggestFixes": true
241
+ }
242
+ }
243
+ ```
244
+
245
+ #### Ejemplo 4: Incluir elementos que pasan
246
+ ```
247
+ Muéstrame el contraste de todos los elementos, incluyendo los que pasan
248
+ ```
249
+
250
+ **Input equivalente:**
251
+ ```json
252
+ {
253
+ "url": "https://example.com",
254
+ "options": {
255
+ "includePassingElements": true
256
+ }
257
+ }
258
+ ```
259
+
260
+ ---
261
+
190
262
  ### `analyze-all`
191
263
 
192
264
  #### Ejemplo 1: Análisis completo
@@ -427,6 +499,38 @@ el issue WCAG 1.1.1 (Contenido no textual):
427
499
  }
428
500
  ```
429
501
 
502
+ ### 4. Análisis de Contraste con Nivel AAA
503
+
504
+ Para proyectos que requieren máxima accesibilidad:
505
+
506
+ ```json
507
+ {
508
+ "url": "https://example.com",
509
+ "options": {
510
+ "wcagLevel": "AAA",
511
+ "suggestFixes": true
512
+ }
513
+ }
514
+ ```
515
+
516
+ **Ratios requeridos:**
517
+ - **AA:** 4.5:1 (texto normal), 3:1 (texto grande)
518
+ - **AAA:** 7:1 (texto normal), 4.5:1 (texto grande)
519
+
520
+ ### 5. Contraste de Sección Específica
521
+
522
+ Analiza solo el contraste de una parte de la página:
523
+
524
+ ```json
525
+ {
526
+ "url": "https://example.com",
527
+ "options": {
528
+ "selector": ".hero-section",
529
+ "includePassingElements": false
530
+ }
531
+ }
532
+ ```
533
+
430
534
  ---
431
535
 
432
536
  ## Preguntas Frecuentes
@@ -435,6 +539,7 @@ el issue WCAG 1.1.1 (Contenido no textual):
435
539
 
436
540
  - **Para web deployada:** `analyze-all` (cobertura máxima)
437
541
  - **Para código Vue:** `analyze-with-eslint` (rápido, sin browser)
542
+ - **Para verificar colores:** `analyze-contrast` (con sugerencias de corrección)
438
543
 
439
544
  ### ¿Cómo manejar falsos positivos?
440
545