Linting de Componentes Personalizados com o 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

Um guia para usar Axe DevTools Linter na verificação de componentes personalizados com o endpoint REST

Free Trial
Not for use with personal data

Este artigo mostra como usar o endpoint REST do Axe DevTools Linter para encontrar erros de acessibilidade em componentes personalizados.

important

Este artigo é para usuários do endpoint REST do Axe DevTools Linter. Se você usa a extensão Axe Accessibility Linter para VS Code ou o plugin para JetBrains, veja Linting de Componentes Personalizados com a Extensão Axe Accessibility Linter para VS Code ou o Plugin para JetBrains para mais informações.

Pré-requisitos

Você precisará de acesso à versão SaaS ou a uma versão local do Axe DevTools Linter. Veja Obtendo uma Chave de API SaaS do Axe DevTools Linter ou Configurando a Edição Local do Axe DevTools Linter para mais informações.

Você também precisará de uma ferramenta REST que:

  • Possa enviar solicitações POST
  • Possa adicionar Authorization cabeçalhos (para a versão SaaS do Axe DevTools Linter)
  • Permita a criação de corpos de solicitação JSON

Um Tutorial de Linting de Componentes Personalizados

Quando você usa o Axe DevTools Linter para verificar o código-fonte, você fornece um corpo JSON contendo o código-fonte e a configuração na sua solicitação HTTP. Por exemplo, o seguinte HTML mostra o uso do img elemento:

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

(Este é um exemplo altamente simplificado apenas para demonstrar o linting, e não um exemplo real do mundo.)

O corpo JSON da solicitação a ser enviada para o Axe DevTools Linter seria assim:

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

Você envia este JSON para o Axe DevTools Linter como uma solicitação POST REST para o /linter-source endpoint. Para mais informações, veja O Endpoint de Lint na documentação de referência.

Para acompanhar este tutorial, você pode usar qualquer ferramenta REST que possa enviar solicitações POST com corpos de solicitação JSON. Os exemplos a seguir mostram o corpo da solicitação enviado para o Axe DevTools Linter e o corpo da resposta JSON, que mostra os erros de acessibilidade encontrados pelo Axe DevTools Linter.

Porque este img elemento não tem um alt atributo, você receberá um erro de acessibilidade do 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"
      }
    ]
  }
}

Um Componente de Imagem Personalizado

O exemplo a seguir mostra um exemplo de um custom-image componente personalizado:

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

Para enviar o HTML para o Axe DevTools Linter usando uma solicitação POST, use o seguinte como corpo JSON:

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

O servidor responde sem erros de acessibilidade porque não há mapeamento entre custom-image e img, portanto, o Axe DevTools Linter não pode sinalizar a ausência de um alt atributo:

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

Mapeamento de custom-image para img

Se você fornecer um mapeamento entre custom-image para img, o Axe DevTools Linter pode mapear seu componente personalizado como um elemento HTML padrão e localizar erros de acessibilidade. Você pode especificar o mapeamento usando a opção de configuração global-components (parte do objeto config ):

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

O Axe DevTools Linter agora responde o seguinte:

{
  "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"
      }
    ]
  }
}

Você também pode indicar o mesmo mapeamento acima com qualquer uma destas sintaxes:

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

Ou, alternativamente, abreviando element como el:

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

Quando você usa um mapeamento de elemento como mostrado acima, todos os atributos do componente personalizado são copiados para o elemento emitido, e esse elemento emitido é verificado.

Corrigindo o Problema de Acessibilidade

Você pode adicionar um alt atributo ao seu custom-image para corrigir o problema de acessibilidade (como mostrado abaixo com o corpo JSON da solicitação):

{
  "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"
}

O servidor responde com o seguinte errors array vazio porque o seu componente personalizado possui o alt atributo necessário (que foi copiado — com *todos* os outros atributos no custom-image componente — para o img elemento emitido):

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

Mapeando o alternative-text Atributo

Se o seu componente de imagem personalizado usar outro atributo para indicar texto alternativo, você pode especificar esse atributo na configuração. Por exemplo, suponha que seu custom-image componente use um alternative-text atributo em vez de alt, como mostrado abaixo:

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

Nesse caso, você poderia especificar um mapeamento entre o alternative-text atributo e o alt atributo como mostrado com o attributes array no corpo da solicitação JSON mostrado abaixo:

{
  "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

Observe que a global-components configuração difere ligeiramente do mapeamento anterior de um componente personalizado para um elemento HTML. Com apenas elementos, você usa um mapeamento de uma string ("custom-image") para outra string ("img"). Com a inclusão do attributes array, agora é necessário usar a element propriedade (ou el) para especificar o elemento HTML emitido.

A Linter Axe DevTools responde com o seguinte porque a alt-text regra foi satisfeita pelo seu alternative-text atributo:

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

Porque você especificou o attributes array na configuração, quando o servidor mapeia de custom-image para img, *apenas* os atributos especificados no attributes array são copiados para o elemento HTML emitido.

Você também pode abreviar attributes como attrs:

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

Valores Especiais de Atributos: <text>, aria-* e <element>

Suponha que você use um custom-button componente da seguinte forma:

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

(O botão personalizado, usando JavaScript e CSS que não estão incluídos aqui, irá ocultar e mostrar um div.)

Há dois problemas com esse uso:

  1. Se você mapear este custom-button componente diretamente para um button elemento, não haverá nenhum conteúdo de texto a ser exibido no botão. No entanto, a intenção do autor do componente é que o message atributo seja usado como conteúdo do texto: <button> valor do message atributo </button>
  2. O elemento emitido button tem um papel implícito de button, portanto o aria-colindex atributo está incorreto e deve ser removido.

Se você enviar o código acima para o Axe DevTools Linter (sem global-components mapeamento), você receberá esta resposta:

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

O valor especial <text>

Para resolver o primeiro problema (conteúdo de texto para o button elemento vindo de um message atributo), você pode usar o valor especial <text> que mapeia um atributo para o conteúdo de texto do elemento emitido. Nesse caso, o message texto do atributo deve ser copiado para o button conteúdo de texto do elemento emitido.

Para configurar a solicitação para alertar o Axe DevTools Linter que o message atributo deve ser considerado como conteúdo de texto para o button elemento HTML, você pode usar o valor especial <text> e enviar a seguinte solicitação:

{
  "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"
}

Como você definiu o message atributo como <text>, você informou ao Axe DevTools Linter para considerar esse atributo como substituindo o conteúdo textual do button elemento HTML pelo valor do message atributo.

Infelizmente, ao usar o attributes array, o único atributo que foi passado para o button elemento emitido foi apenas o message atributo; quaisquer atributos não presentes no attributes array não são repassados. Isso significa que o aria-colindex incorreto não foi detectado pelo servidor.

Usando aria-*

Você pode usar o valor especial aria-* para passar todos os atributos ARIA, conforme mostrado abaixo:

{
  "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"
}

O servidor responde com:

{
  "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 erro ocorre porque o button elemento tem um role="button" implícito e usar o aria-colindex é inválido com botões. Com aria-*, todos os atributos ARIA são copiados para o elemento emitido; isso inclui a cópia do aria-colindex atributo inválido.

<element>

Com componentes complexos, pode ser necessário emitir um elemento HTML diferente do elemento padrão em casos específicos. Por exemplo, você pode ter um componente de botão que normalmente se comporta como um botão e, em outros estados, como uma imagem de espaço reservado. O <element> valor permite que você especifique um atributo em seu componente personalizado que determina o 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>"
}

Nesse caso, o use atributo no my-button componente indica o elemento a ser emitido. Como o img elemento emitido não contém um alt atributo, você receberá um erro:

{
  "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
      }
    ]
  }
}

Passando Todos os Atributos Implicitamente

Observe que se você tivesse usado apenas o mapeamento de elementos (onde o mapeamento não usa o attributes array), todos os atributos seriam, por padrão, copiados para o button elemento, como mostrado abaixo:

{
  "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"
}

Com essa resposta do servidor, você pode ver que todos os atributos de custom-button são verificados quanto a problemas de acessibilidade, e dois erros são encontrados:

{
  "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"
      }
    ]
  }
}

O exemplo acima mostra que um primeiro passo prático ao começar a analisar componentes personalizados seria começar com um mapeamento de elementos (copiando assim todos os atributos para o elemento HTML padrão emitido) e depois ver quais atributos precisam ser adicionados à configuração (se os atributos do componente personalizado devem ser mapeados para diferentes atributos ou se você precisa usar <text> ou aria-*).

Atributos Padrão

Os atributos padrão permitem definir valores para atributos no seu arquivo de configuração em vez de mapear um atributo para outro. Por exemplo, a configuração de amostra a seguir mostra um componente custom-menu mapeado para um elemento li com um role de *menu*:

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

Como o atributo role tem um valor padrão de *menu*, definido no arquivo de configuração, os usuários não precisam especificar um atributo role quando usam o componente custom-menu em seu código. A implicação é que a implementação do seu componente personalizado cria esses atributos no elemento de saída e define seus valores em vez de exigir que os usuários os configurem ao usarem seu componente.

Opcionalmente, o valor de name é definido como null na configuração, o que faz com que o Axe DevTools Linter ignore quaisquer atributos role que os usuários tenham especificado em custom-menu no código analisado.

note

O valor especificado com default deve ser uma string.

Analisando Violações de Componentes Personalizados

Quando você tem muitos componentes personalizados configurados, pode ser difícil saber quais violações na resposta vieram de mapeamentos de componentes personalizados versus HTML padrão. Adicionar "properties": ["customName"] ao corpo da sua solicitação faz com que o Axe DevTools Linter inclua uma propriedade customName em cada erro que originou de um componente mapeado personalizado.

Com base no exemplo custom-image acima, adicionar "properties": ["customName"] à solicitação:

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

A resposta agora inclui uma propriedade customName no erro, mostrando qual componente personalizado acionou a violação:

{
  "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"
      }
    ]
  }
}

Erros de componentes que não fazem parte de um mapeamento personalizado não terão uma propriedade customName .

Veja Também