Análisis de Componentes Personalizados con el Endpoint REST

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard

Una guía para usar Axe DevTools Linter para analizar componentes personalizados con el endpoint REST

Free Trial
Not for use with personal data

Este artículo muestra cómo usar el endpoint REST de Axe DevTools Linter para encontrar errores de accesibilidad en componentes personalizados.

important

Este artículo es para usuarios del endpoint REST de Axe DevTools Linter. Si utiliza la extensión Axe Accessibility Linter para VS Code o el plugin para JetBrains, consulte Análisis de Componentes Personalizados con la Extensión Axe Accessibility Linter para VS Code o el Plugin para JetBrains para más información.

Requisitos previos

Necesitará acceso a la versión SaaS o a una versión local de Axe DevTools Linter. Consulte Obtener una Clave API de SaaS de Axe DevTools Linter o Configurar la Edición Local de Axe DevTools Linter para más información.

También necesitará una herramienta REST que:

  • Pueda enviar solicitudes POST
  • Pueda añadir encabezados Authorization (para la versión SaaS de Axe DevTools Linter)
  • Permite crear cuerpos de solicitud JSON

Guía de Análisis de Componentes Personalizados

Cuando usa Axe DevTools Linter para analizar el código fuente, proporciona un cuerpo JSON que contiene el código fuente y la configuración en su solicitud HTTP. Por ejemplo, el siguiente HTML muestra el uso del elemento img:

<img src="path/to/image.jpg"/>

(Este es un ejemplo sumamente simplificado solo para demostrar el análisis en lugar de un ejemplo real.)

El cuerpo JSON de la solicitud a enviar a Axe DevTools Linter se vería así:

{ 
  "source": "<img src=\"path/to/image.jpg\"/>",
  "filename": "image-demo.html"
}
note

Envía este JSON a Axe DevTools Linter como una solicitud POST REST al endpoint /linter-source. Para más información, consulte El Endpoint de Análisis en la documentación de referencia.

Para seguir esta guía, puede usar cualquier herramienta REST que pueda enviar solicitudes POST con cuerpos de solicitud JSON. Los siguientes ejemplos muestran el cuerpo de la solicitud enviado a Axe DevTools Linter y el cuerpo de la respuesta JSON, que muestra los errores de accesibilidad encontrados por Axe DevTools Linter.

Debido a que este elemento img no tiene un atributo alt, obtendrá un error de accesibilidad de Axe DevTools Linter:

{
  "report": {
    "errors": [
      {
        "column": 1,
        "description": "Ensures <img> elements have alternate text or a role of none or presentation",
        "endColumn": 31,
        "helpURL": "https://dequeuniversity.com/rules/axe/4.4/image-alt?application=axe-linter",
        "lineContent": "<img src=\"path/to/image.jpg\"/>",
        "lineNumber": 1,
        "linterType": "html",
        "ruleId": "image-alt"
      }
    ]
  }
}

Un Componente de Imagen Personalizado

El siguiente ejemplo muestra un componente personalizado custom-image:

<custom-image src="path/to/image.jpg"></custom-image>

Para enviar el HTML a Axe DevTools Linter usando una solicitud POST, utilice lo siguiente como cuerpo JSON:

{
  "source": "<custom-image src=\"path/to/image.jpg\"></custom-image>",
  "filename": "custom-image.html"
}

El servidor responde sin errores de accesibilidad porque no hay mapeo entre custom-image y img, por lo que Axe DevTools Linter no puede señalar un atributo alt faltante:

{
  "report": {
    "errors": []
  }
}

Mapeando custom-image a img

Si proporciona un mapeo entre custom-image y img, Axe DevTools Linter puede mapear su componente personalizado como un elemento HTML estándar y localizar errores de accesibilidad. Puede especificar el mapeo usando la opción de configuración global-components (parte del objeto config):

{
  "config": {
    "global-components": {
      "custom-image": "img"
    }
  },
  "filename": "c-image.html",
  "source": "<custom-image src=\"path/to/image.jpg\"></custom-image>\n\n"
}

Axe DevTools Linter ahora responde con lo siguiente:

{
  "report": {
    "errors": [
      {
        "column": 1,
        "description": "Ensures <img> elements have alternate text or a role of none or presentation",
        "endColumn": 54,
        "helpURL": "https://dequeuniversity.com/rules/axe/4.4/image-alt?application=axe-linter",
        "lineContent": "<custom-image src=\"path/to/image.jpg\"></custom-image>",
        "lineNumber": 1,
        "linterType": "html",
        "ruleId": "image-alt"
      }
    ]
  }
}

También puede indicar el mismo mapeo que el anterior con cualquiera de estas sintaxis:

{
  "config": {
    "global-components": {
      "custom-image": {
        "element": "img"
      }
    }
  }
}

O, alternativamente, abreviando element como el:

{
  "config": {
    "global-components": {
      "custom-image": {
        "el": "img"
      }
    }
  }
}
important

Cuando usa un mapeo de elementos como se muestra arriba, todos los atributos del componente personalizado se copian al elemento emitido, y ese elemento emitido es analizado.

Solucionando el Problema de Accesibilidad

Puede agregar un atributo alt a su custom-image para solucionar el problema de accesibilidad (como se muestra a continuación con el cuerpo JSON de la solicitud):

{
  "config": {
    "global-components": {
      "custom-image": "img"
    }
  },
  "filename": "c-image.html",
  "source": "<custom-image src=\"path/to/image.jpg\" alt=\"alt text\"></custom-image>\n\n"
}

El servidor responde con el siguiente array vacío errors porque su componente personalizado tiene el atributo alt requerido (que fue copiado—junto con todo otros atributos en el componente custom-image—al elemento img emitido):

{
  "report": {
    "errors": []
  }
}

Mapeo del Atributo alternative-text

Si su componente de imagen personalizado usa en su lugar un atributo diferente para indicar texto alternativo, puede especificar ese atributo en la configuración. Por ejemplo, suponga que su componente custom-image usa un atributo alternative-text en lugar de alt, como se muestra a continuación:

<custom-image src="path/to/image.jpg" alternative-text="alt text"></custom-image>

En este caso, podría especificar un mapeo entre el atributo alternative-text y el atributo alt como se muestra con el array attributes en el cuerpo JSON de la solicitud que se muestra a continuación:

{
  "config": {
    "global-components": {
      "custom-image": {
        "element": "img",
        "attributes": [
          {
            "alternative-text": "alt"
          }
        ]
      }
    }
  },
  "filename": "c-image.html",
  "source": "<custom-image src=\"path/to/image.jpg\" alternative-text=\"alt text\"></custom-image>\n\n"
}
note

Tenga en cuenta que la configuración global-components difiere ligeramente del mapeo anterior de un componente personalizado a un elemento HTML. Con solo elementos, usa un mapeo de una cadena ("imagen-personalizada") a otra cadena ("img"). Con la inclusión del array attributes, ahora es necesario usar la propiedad element (o el) para especificar el elemento HTML emitido.

Axe DevTools Linter responde con lo siguiente porque la regla alt-text se ha satisfecho con su atributo alternative-text:

{
  "report": {
    "errors": []
  }
}
important

Debido a que especificó el array attributes en la configuración, cuando el servidor mapea de custom-image a img, solo los atributos especificados en el array attributes son copiados al elemento HTML emitido.

También puede abreviar attributes como attrs:

{
  "config": {
    "global-components": {
      "custom-image": {
        "attrs": [
          {
            "alternative-text": "alt"
          }
        ],
        "element": "img"
      }
    }
  }
}

Valores Especiales de Atributo: <text>, aria-* y <element>

Suponga que utiliza un componente custom-button de la siguiente manera:

<custom-button aria-controls="expand-region" aria-expanded="false" aria-colindex="1" message="Show Region"></custom-button>

(El botón personalizado, utilizando JavaScript y CSS que no se incluye aquí, ocultará y mostrará un div.)

Hay dos problemas con este uso:

  1. Si mapea este componente custom-button directamente a un elemento button, no habrá contenido de texto para mostrar en el botón. Sin embargo, la intención del autor del componente es que se use el atributo message como contenido de texto: <button> valor del atributo message </button>
  2. El elemento button emitido tiene un rol implícito de button, por lo que el atributo aria-colindex es incorrecto y debe eliminarse.

Si envías el código anterior a Axe DevTools Linter (sin ningún mapeo global-components), recibirás esta respuesta:

{
  "report": {
    "errors": []
  }
}

El valor especial de <text>

Para abordar el primer problema (el contenido de texto para el elemento button que proviene de un atributo message), puedes utilizar el valor especial <text>, que mapea un atributo al contenido de texto del elemento emitido. En este caso, el texto del atributo message debería copiarse en el contenido de texto del elemento emitido button.

Para configurar la solicitud y alertar a Axe DevTools Linter de que el atributo message debe considerarse como contenido de texto para el elemento HTML button, puedes utilizar el valor especial <text> y enviar la siguiente solicitud:

{
  "config": {
    "global-components": {
      "custom-button": {
        "attributes": [
          {
            "message": "<text>"
          }
        ],
        "element": "button"
      }
    }
  },
  "filename": "aria-button.html",
  "source": "<custom-button aria-controls=\"expand-region\" aria-expanded=\"false\" aria-colindex=\"1\" message=\"Show Region\"></custom-button>\n"
}

Debido a que definiste el atributo message como <text>, le dijiste a Axe DevTools Linter que considere ese atributo como un reemplazo del contenido textual del elemento HTML button con el valor del atributo message.

Desafortunadamente, al utilizar el arreglo attributes, el único atributo que se pasó al elemento emitido button fue solo el atributo message; cualquier atributo que no esté en el arreglo attributes no se pasa. Esto significa que el incorrecto aria-colindex no fue detectado por el servidor.

Usando aria-*

Puedes usar el valor especial aria-* para pasar todos los atributos ARIA, como se muestra a continuación:

{
  "config": {
    "global-components": {
      "custom-button": {
        "attributes": [
          {
            "message": "<text>"
          },
          "aria-*"
        ],
        "element": "button"
      }
    }
  },
  "filename": "aria-button.html",
  "source": "<custom-button aria-controls=\"expand-region\" aria-expanded=\"false\" aria-colindex=\"1\" message=\"Show Region\"></custom-button>\n"
}

El servidor responde con:

{
  "report": {
    "errors": [
      {
        "column": 1,
        "description": "Ensures ARIA attributes are allowed for an element's role",
        "endColumn": 124,
        "helpURL": "https://dequeuniversity.com/rules/axe/4.4/aria-allowed-attr?application=axe-linter",
        "lineContent": "<custom-button aria-controls=\"expand-region\" aria-expanded=\"false\" aria-colindex=\"1\" message=\"Show Region\"></custom-button>",
        "lineNumber": 1,
        "linterType": "html",
        "ruleId": "aria-allowed-attr"
      }
    ]
  }
}

Este error ocurre porque el elemento button tiene un role="button" implícito y usar aria-colindex no es válido con los botones. Con aria-*, todos los atributos ARIA se copian en el elemento emitido; esto incluye copiar el atributo aria-colindex no válido.

<element>

Con componentes complejos, es posible que desees emitir un elemento HTML diferente al elemento predeterminado en casos específicos. Por ejemplo, podrías tener un componente de botón que generalmente se comporta como un botón y, en otros estados, como una imagen de marcador de posición. El valor <element> te permite especificar un atributo en tu componente personalizado que determina el elemento emitido.

{  
  "config": {
    "global-components": {
      "my-button": {
        "element": "button",
        "attributes": [
         {
          "use": "<element>"
         },
         'src',
         'alt'
        ]
      } 
    }
  },

  "filename": "aria-button.html",
  "source": "<my-button use=\"img\" src=\"globe.jpg\"></my-button>"
}

En este caso, el atributo use en el componente my-button indica el elemento a emitir. Dado que el elemento emitido img no contiene un atributo alt, recibirás un error:

{
  "report": {
    "errors": [
      {
        "ruleId": "image-alt",
        "helpURL": "https://dequeuniversity.com/rules/axe/4.10/image-alt?application=axe-linter",
        "description": "Images must have alternative text",
        "lineNumber": 1,
        "column": 1,
        "linterType": "html",
        "lineContent": "<my-button use=\"img\" src=\"globe.jpg\"></my-button>",
        "endColumn": 50
      }
    ]
  }
}

Pasando todos los atributos implícitamente

Ten en cuenta que si solo hubieras usado el mapeo de elementos (donde el mapeo no usa el arreglo attributes), todos los atributos se copiarían, por defecto, en el elemento button como se muestra a continuación:

{
  "config": {
    "global-components": {
      "custom-button": "button"
    }
  },
  "filename": "aria-button.html",
  "source": "<custom-button aria-controls=\"expand-region\" aria-expanded=\"false\" aria-colindex=\"1\" message=\"Show Region\"></custom-button>\n"
}

Con esta respuesta del servidor, puedes ver que todos los atributos de custom-button se revisan en busca de problemas de accesibilidad, y se encuentran dos errores:

{
  "report": {
    "errors": [
      {
        "column": 1,
        "description": "Ensures ARIA attributes are allowed for an element's role",
        "endColumn": 124,
        "helpURL": "https://dequeuniversity.com/rules/axe/4.4/aria-allowed-attr?application=axe-linter",
        "lineContent": "<custom-button aria-controls=\"expand-region\" aria-expanded=\"false\" aria-colindex=\"1\" message=\"Show Region\"></custom-button>",
        "lineNumber": 1,
        "linterType": "html",
        "ruleId": "aria-allowed-attr"
      },
      {
        "column": 1,
        "description": "Ensures buttons have discernible text",
        "endColumn": 124,
        "helpURL": "https://dequeuniversity.com/rules/axe/4.4/button-name?application=axe-linter",
        "lineContent": "<custom-button aria-controls=\"expand-region\" aria-expanded=\"false\" aria-colindex=\"1\" message=\"Show Region\"></custom-button>",
        "lineNumber": 1,
        "linterType": "html",
        "ruleId": "button-name"
      }
    ]
  }
}

El ejemplo anterior muestra que un primer paso práctico al comenzar a analizar componentes personalizados sería comenzar con un mapeo de elementos (copiando así todos los atributos en el elemento HTML estándar emitido) y luego observar qué atributos necesitan agregarse a la configuración (ya sea que los atributos del componente personalizado deban mapease a diferentes atributos o si necesitas usar <text> o aria-*).

Atributos predeterminados

Los atributos predeterminados te permiten establecer valores para los atributos en tu archivo de configuración en lugar de mapear uno a otro. Por ejemplo, la siguiente configuración de muestra muestra un componente custom-menu mapeado a un elemento li con un role de menú:

{
  "config": {
    "global-components": {
      "custom-menu": {
        "element": "li",
        "attributes": [
          {
            "role": {
              "name": null,
              "default": "menu"
            }
          }
        ]
      }
    }
  }
}

Debido a que el atributo role tiene un valor predeterminado de menú, establecido en el archivo de configuración, los usuarios no necesitan especificar un atributo role cuando utilizan el componente custom-menu en su código. La implicación es que la implementación de tu componente personalizado crea estos atributos en el elemento de salida y establece sus valores en lugar de requerir que los usuarios los configuren al usar el componente.

Opcionalmente, el valor de name se establece en null en la configuración, lo que hace que Axe DevTools Linter ignore cualquier atributo role que los usuarios hayan especificado en custom-menu en el código analizado.

note

El valor especificado con default debe ser una cadena de texto.

Analizando violaciones de componentes personalizados

Cuando tienes configurados muchos componentes personalizados, puede ser difícil distinguir qué violaciones en la respuesta provienen de mapeos de componentes personalizados frente al HTML estándar. Agregar "properties": ["customName"] a tu cuerpo de solicitud hace que Axe DevTools Linter incluya una propiedad customName en cada error que se originó de un componente mapeado personalizado.

Sobre el ejemplo de custom-image mencionado anteriormente, agregar "properties": ["customName"] a la solicitud:

{
  "properties": ["customName"],
  "config": {
    "global-components": {
      "custom-image": "img"
    }
  },
  "filename": "c-image.html",
  "source": "<custom-image src=\"path/to/image.jpg\"></custom-image>\n\n"
}

La respuesta ahora incluye una propiedad customName en el error que muestra qué componente personalizado desencadenó la violación:

{
  "report": {
    "errors": [
      {
        "column": 1,
        "customName": "custom-image",
        "description": "Ensures <img> elements have alternate text or a role of none or presentation",
        "endColumn": 54,
        "helpURL": "https://dequeuniversity.com/rules/axe/4.4/image-alt?application=axe-linter",
        "lineContent": "<custom-image src=\"path/to/image.jpg\"></custom-image>",
        "lineNumber": 1,
        "linterType": "html",
        "ruleId": "image-alt"
      }
    ]
  }
}

Los errores de los componentes que no forman parte de un mapeo personalizado no tendrán una propiedad customName.

Ver también