Habilidade de Verificador de Acessibilidade Markdown

De Wikiprompt, a enciclopédia livre de prompts

Fatih Kadir Akın
Contribuído porFatih Kadir AkınFonte

10 de out. de 2026

Habilidade de Verificador de Acessibilidade Markdown Uma definição completa de habilidade para um agente de IA que revisa documentos Markdown quanto à acessibilidade, escreve texto alternativo e retorna uma lista de correções ou um arquivo corrigido. Inclui fluxo de trabalho, guias de referência, modelos, um exemplo de revisão e um script verificador em Python.

Conteúdo do PromptSalvar

🌐
--- name: verificador-de-acessibilidade-markdown description: Revisa documentação em Markdown (READMEs, sites de documentação, wikis, posts de blog, changelogs) quanto à acessibilidade - texto alternativo ausente ou ruim para imagens, estrutura de títulos, texto de link vago ou duplicado, URLs expostas, cabeçalhos de tabela vazios, instruções apenas com cores, TUDO EM MAIÚSCULAS e marcadores com emoji - depois escreve um bom texto alternativo para cada imagem com base no contexto e retorna uma lista de correções ou um arquivo corrigido. Use quando um usuário pedir para "verificar a acessibilidade do meu README", "escrever texto alternativo para estas imagens", "tornar nossa documentação compatível com leitores de tela", ou quiser uma verificação de acessibilidade para Markdown em CI. --- # Verificador de Acessibilidade Markdown Você torna documentos Markdown utilizáveis por todos, incluindo pessoas que usam leitores de tela, navegação por teclado, ampliação ou auxílios de leitura. Você encontra os problemas que um script pode detectar e depois faz a parte que um script não consegue: escrever texto alternativo e texto de link significativos que se ajustem ao propósito do documento. ## Arquivos nesta habilidade - `scripts/check_md_a11y.py` - verifica arquivos ou pastas Markdown e relata problemas com números de linha e severidades (apenas biblioteca padrão do Python 3) - `references/alt-text-guide.md` - como escrever texto alternativo por tipo de imagem (capturas de tela, diagramas, gráficos, fotos, logotipos, selos, imagens decorativas) - `references/structure-and-links.md` - títulos, texto de link, tabelas, listas, ênfase e o que cada regra no script significa - `templates/a11y-review.md` - o relatório de revisão e a planilha de texto alternativo - `examples/example-readme-review.md` - uma revisão trabalhada do README de um projeto ## Fluxo de trabalho ### 1. Defina o escopo da revisão Pergunte quais arquivos ou pastas verificar, quem os lê (desenvolvedores, usuários finais, estudantes) e se o usuário quer um relatório, um arquivo corrigido ou ambos. Se os documentos forem renderizados por um gerador de site, pergunte se ele adiciona seu próprio título de página (então o Markdown pode não precisar de um H1). ### 2. Execute o verificador ```bash python3 scripts/check_md_a11y.py README.md docs/ python3 scripts/check_md_a11y.py docs/ --json python3 scripts/check_md_a11y.py docs/ --fail-on warn # para CI ``` Ele ignora blocos de código cercados e código inline. ALTO significa que o conteúdo é perdido para alguns leitores (alt ausente, link vazio, título vazio), AVISO deve ser corrigido, INFO precisa de uma análise humana. Se você não puder executar o script, verifique as mesmas regras lendo o arquivo e diga isso. ### 3. Escreva o texto alternativo Para cada imagem sinalizada e para cada imagem com texto alternativo existente, decida seu propósito usando `references/alt-text-guide.md`: - Leia o texto ao redor: para que serve a imagem neste ponto do documento? - Se você puder ver a imagem, descreva o que importa para esse propósito. Se não puder, pergunte ao usuário ou escreva um rascunho claramente marcado com base no nome do arquivo e no contexto (por exemplo, "RASCUNHO: verificar com a imagem"). - Imagens decorativas recebem texto alternativo vazio; em Markdown, prefira removê-las ou use HTML `<img alt="">`. Preencha a planilha de texto alternativo em `templates/a11y-review.md`. ### 4. Corrija estrutura e links Aplique `references/structure-and-links.md`: um H1, sem níveis pulados, títulos reais em vez de linhas em negrito, texto de link descritivo e único, tabelas com cabeçalhos, instruções que não dependam apenas de cores. ### 5. Entregue - Relatório: preencha `templates/a11y-review.md`, como em `examples/example-readme-review.md`, com as correções mais importantes primeiro. - Arquivo corrigido: retorne o Markdown completo com as correções aplicadas e uma breve lista de alterações. Não mude o significado, exemplos de código ou destinos de links. - Execute novamente o verificador no arquivo corrigido e inclua as contagens antes e depois. ## Regras - Nunca invente o que uma imagem mostra. Se você não a viu, marque o texto alternativo como rascunho. - Mantenha o texto alternativo curto (geralmente menos de 150 caracteres); coloque explicações longas (gráficos, diagramas) no texto ou em uma legenda e diga isso no alt. - Não comece o texto alternativo com "imagem de" ou "foto de". - Lembre-se de que as verificações automatizadas encontram apenas parte dos problemas; sempre mencione o que ainda precisa de uma verificação manual (contraste de cores em imagens, ordem de leitura, legendas de vídeo). - Respeite a voz do autor; corrija acessibilidade, não o estilo. FILE:references/alt-text-guide.md # Guia de texto alternativo O texto alternativo substitui a imagem para pessoas que não podem vê-la. Pergunte: "Se eu ler este documento em voz alta, o que eu diria neste ponto em vez de mostrar a imagem?" A resposta depende do motivo pelo qual a imagem está ali, não apenas do que está nela. ## Básico - Seja específico e curto: geralmente de 5 a 20 palavras, raramente mais de 150 caracteres. - Comece com a parte importante. Não comece com "imagem de", "foto de" ou "captura de tela de", a menos que o tipo em si importe ("Captura de tela" pode ajudar quando o leitor precisa encontrar a mesma tela). - Termine com um ponto final para que os leitores de tela façam uma pausa. - Não repita a legenda ou a frase ao lado da imagem palavra por palavra. - Inclua o texto que aparece na imagem se o leitor precisar dele (rótulos de botões, mensagens de erro). ## Por tipo de imagem ### Capturas de tela de um aplicativo ou site Declare a tela e a única coisa que o leitor deve notar. - Fraco: "captura de tela" - Melhor: "Tela de Configurações com o botão de alternância Unidades definido como Métrico." ### Imagens de herói e banners Se apenas define o clima, é decorativa. Se mostra o produto, descreva-o em uma frase. - "Trailhead Weather em um telefone, mostrando uma previsão de três dias para um passo de montanha." ### Diagramas e fluxogramas Dê a ideia principal no alt e a estrutura completa no texto ou em uma lista logo após a imagem. - Alt: "Diagrama de arquitetura: o aplicativo móvel chama a API, que lê de um cache de previsões e de um provedor de clima. Detalhes na lista abaixo." ### Gráficos e tabelas Dê o tipo, o assunto e a principal conclusão; coloque os dados em uma tabela se os leitores precisarem de números. - "Gráfico de linhas de usuários ativos diários, de janeiro a junho de 2026, subindo de 2.000 para 9.500 com uma queda em abril." ### Fotos Descreva o que importa para o propósito do documento: assunto, ação, ambiente. - "Trilha de crista coberta de neve com postes de marcação laranja levando a uma cabana." ### Logotipos Use o nome da organização ou produto, mais "logotipo" apenas se ajudar: "Logotipo do Trailhead Weather." Quando o logotipo for um link, descreva o destino: "Página inicial do Trailhead Weather." ### Selos (status de build, versão, licença) Escreva a informação que o selo mostra: "Build: passando", "Licença: MIT", "Versão 2.4.1". ### Ícones dentro de texto ou links Se o ícone tem uma função, descreva a função ("Baixar"); se repete o texto próximo, é decorativo. ### GIFs animados e vídeos curtos Descreva o que acontece: "Animação: arrastar um pino para o mapa adiciona um novo ponto de partida de trilha à lista." Vídeos também precisam de legendas e, para conteúdo importante, uma alternativa em texto. ### Imagens decorativas Divisores, texturas de fundo e floreios puramente visuais. Em HTML, use `alt=""` para que os leitores de tela os ignorem. Em Markdown, `![](divider.png)` é ambíguo (muitas vezes um erro), então prefira remover a imagem ou usar `<img src="divider.png" alt="">`. ## Erros comuns - Nomes de arquivo como texto alternativo: "IMG_2041.jpg", "hero-final-v3". - Uma palavra: "imagem", "logotipo", "gráfico". - Excesso de palavras-chave para mecanismos de busca. - Texto alternativo diferente para a mesma imagem usada em vários lugares. - Descrever cores ou layout quando o leitor precisa da informação, não da aparência. FILE:references/structure-and-links.md # Estrutura, links e o que cada regra significa Usuários de leitores de tela frequentemente navegam por um documento por títulos ou por links. Uma boa estrutura é o que torna isso possível. ## Títulos | Regra | Severidade | Porquê | Correção | |---|---|---|---| | título-vazio | ALTO | Um título vazio é anunciado como "título nível 2" sem nada depois. | Adicione texto ou remova o #. | | sem-h1 | AVISO | A página não tem título no contorno de títulos. | Comece com um `# Título`. Ignore se o gerador de site adicionar o H1 a partir do front matter. | | múltiplos-h1 | AVISO | Vários títulos confundem o contorno. | Mantenha um H1; use `##` para seções. | | pulo-de-título | AVISO | Pular de H2 para H4 sugere uma seção ausente. | Use o próximo nível abaixo (H3). Escolha níveis para estrutura, não para tamanho de fonte. | | título-falso | INFO | Uma linha em negrito parece um título, mas não está no contorno. | Use um título real se iniciar uma seção; mantenha negrito se for apenas ênfase. | | sem-títulos | INFO | Texto longo sem títulos é difícil de escanear. | Adicione títulos de seção a cada poucos parágrafos. | ## Links | Regra | Severidade | Porquê | Correção | |---|---|---|---| | link-vazio | ALTO | O link não tem nome acessível. | Adicione texto descritivo. | | link-vago | AVISO | "Clique aqui" ou "leia mais" não significa nada em uma lista de links. | Nomeie o destino: "baixe a versão mais recente", "guia de configuração". | | mesmo-texto-url-diferente | AVISO | Dois links chamados "docs" que vão para lugares diferentes são indistinguíveis. | Torne cada texto único: "referência da API", "guia de configuração". | | url-como-texto-de-link | INFO | URLs longas são lidas caractere por caractere. | Use uma descrição curta; mantenha a URL apenas se os leitores precisarem copiá-la. | | url-exposta | INFO | Igual ao acima e nem sempre clicável. | Envolva em um link descritivo. | Dicas para texto de link: coloque as palavras importantes primeiro, mantenha-o curto, diga quando um link abre um arquivo ("planilha de preços (PDF, 2 MB)") e não use "link" no texto. ## Imagens | Regra | Severidade | Porquê | |---|---|---| | img-alt-ausente | ALTO | `![](arquivo.png)` não fornece alternativa; alguns leitores anunciam o nome do arquivo. | | img-sem-alt | ALTO | `<img>` sem atributo alt; leitores de tela recorrem ao nome do arquivo. | | img-alt-genérico | AVISO | "imagem", "captura de tela", "logotipo" sozinhos não carregam informação. | | img-alt-nome-de-arquivo | AVISO | "IMG_2041.jpg" não é uma descrição. | | img-alt-longo | AVISO | Texto alternativo muito longo não pode ser navegado; mova os detalhes para o texto. | | img-alt-redundante | INFO | "Imagem de" é redundante; leitores de tela já dizem "imagem". | | img-decorativa | INFO | `alt=""` oculta a imagem; confirme que é verdadeiramente decorativa. | Veja `alt-text-guide.md` para saber como escrever o texto. ## Tabelas - tabela-cabeçalho-vazio (AVISO): toda coluna precisa de um cabeçalho para que os leitores de tela possam anunciar "Pro, Dias de previsão, 10". Adicione um cabeçalho como "Recurso" à primeira coluna. - Use tabelas para dados, não para layout. Mantenha-as pequenas; divida tabelas muito largas. ## Outras regras - apenas-cor (AVISO): "Pressione o botão verde" falha para leitores daltônicos e usuários de leitores de tela. Nomeie o botão: "Selecione Salvar (o botão verde)". - tudo-maiúsculas (INFO): texto longo TUDO EM MAIÚSCULAS é mais difícil de ler, e alguns leitores de tela soletram palavras curtas em maiúsculas letra por letra. Use maiúsculas e minúsculas normais e negrito para ênfase. - marcador-emoji (INFO): emojis são lidos em voz alta pelo nome ("marca de verificação branca pesada Previsões por hora"). Use marcadores de lista normais e mantenha emojis raros e significativos. ## Não verificado pelo script (verifique manualmente) - Se o texto alternativo é preciso e útil. - Contraste de cores e texto dentro de imagens (capturas de tela com texto minúsculo, gráficos com baixo contraste). - Ordem de leitura de layouts complexos e blocos HTML incorporados em Markdown. - Legendas e transcrições para vídeos e áudio. - Linguagem simples: frases curtas, jargão definido e nomes de seção descritivos. FILE:templates/a11y-review.md # Revisão de Acessibilidade: <documento ou pasta> Data: <AAAA-MM-DD> Arquivos verificados: <n> (<lista ou pasta>) Público: <quem lê estes documentos> Execução do verificador: `python3 scripts/check_md_a11y.py <caminhos>` -> ALTO <n>, AVISO <n>, INFO <n> ## Principais correções (maior impacto primeiro) 1. <correção> (<arquivo:linha>) 2. <correção> 3. <correção> ## Planilha de texto alternativo | Arquivo:linha | Imagem | Propósito no documento | Alt atual | Novo alt | Viu a imagem? | |---|---|---|---|---|---| | | | informativa / funcional / decorativa / complexa | | | sim / rascunho | ## Títulos - Contorno atual: <H1 ... / H2 ... / H4 ...> - Contorno proposto: <H1 ... / H2 ... / H3 ...> ## Links | Arquivo:linha | Texto atual | Novo texto | Destino | |---|---|---|---| | | | | | ## Outras descobertas | Arquivo:linha | Regra | Alteração | |---|---|---| | | | | ## Após as correções Verificador executado novamente: ALTO <n>, AVISO <n>, INFO <n> (itens INFO restantes explicados abaixo). - <item INFO: motivo pelo qual é aceitável> ## Verificações manuais ainda necessárias - <por exemplo: contraste do texto dentro de capturas de tela, legendas de vídeo> FILE:examples/example-readme-review.md # Exemplo: revisão de acessibilidade do README de um projeto ## A solicitação "O README do nosso aplicativo de código aberto recebe muito tráfego. Um usuário que depende de um leitor de tela disse que é difícil de seguir. Você pode verificar e corrigir? A imagem de herói é o aplicativo em um telefone com a previsão de 3 dias; app-main.png é a tela principal com temperatura horária, vento e linha de neve; o selo é nosso status de build." ## Execução do verificador (antes) ``` $ python3 scripts/check_md_a11y.py README.md Verificação de acessibilidade Markdown: 1 arquivo(s), 3 imagem(ns) ALTO 2 AVISO 8 INFO 5 README.md (3 imagens, 4 títulos): 15 descoberta(s) 3 ALTO img-alt-ausente A imagem hero.png tem texto alternativo vazio; descreva-a ou confirme que é puramente decorativa. 5 INFO tudo-maiúsculas Texto longo TUDO EM MAIÚSCULAS é difícil de ler e alguns leitores de tela o soletram letra por letra. 9 AVISO link-vago O texto do link "aqui" não diz para onde vai; descreva o destino. 9 AVISO link-vago O texto do link "clique aqui" não diz para onde vai; descreva o destino. 11 AVISO img-alt-genérico O texto alternativo "captura de tela" para app-main.png é genérico; diga o que a imagem mostra ou por que está ali. 13 ALTO img-sem-alt <img src="docs/img/badge.svg"> não tem atributo alt. 15 AVISO pulo-de-título O nível do título pula de H2 para H4 ("Configuração"); use H3. 17 AVISO apenas-cor A instrução depende de cor; adicione também o rótulo, forma ou posição. 19 INFO título-falso A linha em negrito "Recursos" parece um título; use um título # real se iniciar uma seção. 21 INFO marcador-emoji Emoji usado como marcador é lido em voz alta pelo nome; use um marcador de lista e coloque o significado em palavras. 22 INFO marcador-emoji Emoji usado como marcador é lido em voz alta pelo nome; use um marcador de lista e coloque o significado em palavras. 24 AVISO tabela-cabeçalho-vazio O cabeçalho da tabela tem 1 célula(s) vazia(s); toda coluna precisa de um cabeçalho. 28 AVISO mesmo-texto-url-diferente O texto do link "docs" aponta para 2 URLs diferentes; torne cada texto único. 28 INFO url-exposta URL exposta https://example.org/docs; leitores de tela a soletram. Use [texto descritivo](https://example.org/docs). 35 AVISO múltiplos-h1 2 títulos H1 (linhas 1, 35); mantenha um título e use ## para seções. ``` O `![](not-an-image.png)` dentro do bloco de código bash e o exemplo de código inline na última linha foram corretamente ignorados. ## A revisão (modelo preenchido, abreviado) # Revisão de Acessibilidade: README.md Público: caminhantes e colaboradores, muitos vindos de busca. Execução do verificador: ALTO 2, AVISO 8, INFO 5. ### Principais correções 1. Dê à imagem de herói e ao selo de build um texto alternativo real (linhas 3 e 13). 2. Substitua "aqui" e "clique aqui" por texto de link que nomeie o destino (linha 9). 3. Corrija o contorno: "Configuração" torna-se H3, "Recursos" torna-se um H3 real e o segundo H1 "Contribuindo" torna-se H2. 4. Nomeie o botão Salvar em vez de apenas sua cor (linha 17). 5. Dê um cabeçalho à primeira coluna da tabela (linha 24). ### Planilha de texto alternativo | Arquivo:linha | Imagem | Propósito | Alt atual | Novo alt | Viu? | |---|---|---|---|---|---| | README.md:3 | hero.png | informativa: mostra o produto | (vazio) | Trailhead Weather em um telefone, mostrando uma previsão de três dias para um passo de montanha. | descrita pelo usuário | | README.md:11 | app-main.png | informativa: o que a tela principal mostra | captura de tela | Tela principal com temperatura horária, vento e linha de neve para o ponto de partida de trilha selecionado. | descrita pelo usuário | | README.md:13 | badge.svg | informativa: status de build | (sem alt) | Build: passando | descrita pelo usuário | ### Títulos - Antes: H1 Trailhead Weather / H2 Instalar / H4 Configuração / H1 Contribuindo (mais uma linha em negrito "Recursos"). - Depois: H1 Trailhead Weather / H2 Instalar / H3 Configuração / H3 Recursos / H2 Contribuindo. ### Links | Linha | Texto atual | Novo texto | Destino | |---|---|---|---| | 9 | aqui | Baixe a versão mais recente | https://example.org/releases | | 9 | clique aqui | guia de configuração | docs/guides/setup.md | | 28 | docs (URL exposta + "docs") | referência da API | https://example.org/docs | | 28 | docs | guia de configuração | docs/guides/setup.md | ### Outras descobertas | Linha | Regra | Alteração | |---|---|---| | 5 | tudo-maiúsculas | Maiúsculas e minúsculas normais dentro da nota em negrito. | | 17 | apenas-cor | "Selecione Salvar (o botão verde na parte inferior de Configurações)". | | 21-22 | marcador-emoji | Itens de lista "-" normais. | | 24 | tabela-cabeçalho-vazio | Cabeçalho da primeira coluna "Recurso". | ### README corrigido (trecho) ```markdown # Trailhead Weather ![Trailhead Weather em um telefone, mostrando uma previsão de três dias para um passo de montanha.](docs/img/hero.png) Trailhead Weather mostra previsões de montanha para caminhantes. **Nota: este projeto ainda está em beta e as coisas quebrarão com frequência.** ## Instalar [Baixe a versão mais recente](https://example.org/releases) ou siga o [guia de configuração](docs/guides/setup.md). <img src="docs/img/badge.svg" width="90" alt="Build: passando"> ### Configuração Selecione Salvar (o botão verde na parte inferior de Configurações) para salvar suas configurações. ### Recursos - Previsões por hora - Boletins de avalanche | Recurso | Grátis | Pro | |---|---|---| | Dias de previsão | 3 | 10 | ``` ### Após as correções ``` $ python3 scripts/check_md_a11y.py README-corrigido.md Verificação de acessibilidade Markdown: 1 arquivo(s), 3 imagem(ns) ALTO 0 AVISO 0 INFO 0 ``` ### Verificações manuais ainda necessárias - A imagem de herói tem texto pequeno na tela do telefone; o texto alternativo carrega a mensagem principal, então está tudo bem aqui. - Se o README for transformado em uma página de site de documentação, confirme que o site não adiciona um segundo H1. ## Por que esta é uma boa resposta - O texto alternativo descreve o propósito de cada imagem, usando o que o usuário disse que as imagens mostram em vez de adivinhar. - Links e títulos são corrigidos para como usuários de leitores de tela navegam: por lista de links e por contorno de títulos. - A correção é verificada executando novamente o verificador, e as verificações manuais restantes são listadas honestamente. FILE:scripts/check_md_a11y.py #!/usr/bin/env python3 """Verifica arquivos Markdown quanto a problemas comuns de acessibilidade. Uso: python3 check_md_a11y.py README.md docs/ # arquivos e pastas (*.md, *.markdown) python3 check_md_a11y.py docs/ --json cat page.md | python3 check_md_a11y.py - python3 check_md_a11y.py docs/ --fail-on warn # sai com 1 em AVISO também (para CI) Verificações (blocos de código e código inline são ignorados): imagens texto alternativo ausente, alt genérico ou nome de arquivo ("imagem", "captura de tela"), aberturas redundantes "imagem de ...", alt muito longo, <img> HTML sem alt, alt vazio (ok apenas para imagens decorativas) títulos sem H1 ou mais de um H1, níveis pulados (H2 -> H4), títulos vazios, linhas em negrito usadas como títulos falsos links texto de link vazio, texto vago ("clique aqui", "leia mais", "aqui"), URLs expostas, o mesmo texto apontando para URLs diferentes tabelas células de cabeçalho vazias outros frases TUDO EM MAIÚSCULAS, emoji usados como marcadores, instruções apenas com cores Severidades: ALTO (bloqueia a compreensão), AVISO (deve corrigir), INFO (verificar manualmente). Código de saída: 0 sem ALTO, 1 ALTO encontrado (ou AVISO com --fail-on warn), 2 erro de uso. Apenas biblioteca padrão. """ import argparse import json import os import re import sys GENERIC_ALT = {"image", "img", "picture", "pic", "photo", "screenshot", "screen shot", "graphic", "icon", "logo", "diagram", "chart", "figure", "untitled", "alt", "alt text", "banner", "placeholder"} VAGUE_LINK = {"click here", "here", "click", "read more", "more", "learn more", "link", "this", "this link", "this page", "go", "details", "more info", "info", "see here", "check it out"} REDUNDANT_START = re.compile(r"^(an? )?(image|picture|photo|screenshot|graphic) (of|showing)\b", re.I) FILE_ALT = re.compile(r"^[\w\-. ]+\.(png|jpe?g|gif|svg|webp|bmp|tiff?)$|^(img|image|dsc|screenshot)[_\- ]?\d+", re.I) IMG_MD = re.compile(r"!\[([^\]]*)\]\(\s*<?([^)\s>]*)>?(?:\s+\"[^\"]*\")?\s*\)") IMG_REF = re.compile(r"!\[([^\]]*)\]\[[^\]]*\]") LINK_MD = re.compile(r"(?<!!)\[([^\]]*)\]\(\s*<?([^)\s>]*)>?(?:\s+\"[^\"]*\")?\s*\)") HTML_IMG = re.compile(r"<img\b[^>]*>", re.I) BARE_URL = re.compile(r"(?<![(<\"'=\[])\bhttps?://[^\s)>\]]+") COLOR_ONLY = re.compile(r"\b(click|press|tap|select|choose|use)\b[^.]{0,30}\b(red|green|blue|yellow|orange|purple)\b(?! *\()", re.I) EMOJI_BULLET = re.compile(r"^\s*[\u2705\u274c\u2b50\u27a1\u2714\u2716\U0001F300-\U0001FAFF]\ufe0f?\s+\S") def strip_inline_code(line): return re.sub(r"`+[^`]*`+", lambda m: " " * len(m.group(0)), line) def check_text(text, name): findings = [] def add(sev, line, rule, msg): findings.append({"file": name, "line": line, "severity": sev, "rule": rule, "message": msg}) lines = text.replace("\r\n", "\n").split("\n") in_fence, fence = False, "" headings, link_targets = [], {} images = 0 prev_blank = True for no, raw in enumerate(lines, 1): stripped = raw.strip() m = re.match(r"^\s{0,3}(`{3,}|~{3,})", raw) if m: if not in_fence: in_fence, fence = True, m.group(1)[0] * 3 elif stripped.startswith(fence): in_fence = False continue if in_fence or raw.startswith(" ") and prev_blank and not stripped.startswith(("-", "*", "+")): prev_blank = not stripped if not in_fence else prev_blank continue line = strip_inline_code(raw) hm = re.match(r"^\s{0,3}(#{1,6})(\s+|$)(.*?)\s*#*\s*$", line) if hm: level, title = len(hm.group(1)), hm.group(3).strip() headings.append((no, level, title)) if not title: add("ALTO", no, "título-vazio", f"Título H{level} vazio; usuários de leitores de tela navegam por títulos.") elif re.fullmatch(r"\s*(\*\*|__)[^*_]{2,80}(\*\*|__):?\s*", line) and prev_blank: add("INFO", no, "título-falso", f"A linha em negrito \"{stripped.strip('*_:')}\" parece um título; use um título # real se iniciar uma seção.") images += len(IMG_MD.findall(line)) + len(IMG_REF.findall(line)) + len(HTML_IMG.findall(line)) for alt, src in IMG_MD.findall(line): check_alt(add, no, alt, src) for alt in IMG_REF.findall(line): check_alt(add, no, alt, "(referência)") for tag in HTML_IMG.findall(line): am = re.search(r"\balt\s*=\s*(\"([^\"]*)\"|'([^']*)'|(\S+))", tag, re.I) src = re.search(r"\bsrc\s*=\s*[\"']?([^\"'\s>]+)", tag, re.I) src = src.group(1) if src else "?" if not am: add("ALTO", no, "img-sem-alt", f"<img src=\"{src}\"> não tem atributo alt.") else: check_alt(add, no, am.group(2) if am.group(2) is not None else (am.group(3) if am.group(3) is not None else am.group(4)), src, html=True) no_images = IMG_MD.sub(" ", line) for text_, url in LINK_MD.findall(no_images): label = re.sub(r"[*_`]", "", text_).strip() if not label: add("ALTO", no, "link-vazio", f"Link para {url or '(sem url)'} não tem texto; leitores de tela lerão a URL ou nada.") elif label.lower().rstrip(".!:") in VAGUE_LINK: add("AVISO", no, "link-vago", f"O texto do link \"{label}\" não diz para onde vai; descreva o destino.") elif re.fullmatch(r"https?://\S+", label): add("INFO", no, "url-como-texto-de-link", f"O texto do link é uma URL bruta ({label[:60]}); use uma descrição curta.") if label: link_targets.setdefault(label.lower(), {}).setdefault(url, no) for url in BARE_URL.findall(LINK_MD.sub(" ", no_images)): add("INFO", no, "url-exposta", f"URL exposta {url[:60]}; leitores de tela a soletram. Use [texto descritivo]({url[:40]}).") if "|" in line and re.match(r"^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$", line) and no > 1: header = lines[no - 2].strip().strip("|") cells = [c.strip() for c in header.split("|")] if any(not c for c in cells): add("AVISO", no - 1, "tabela-cabeçalho-vazio", f"O cabeçalho da tabela tem {sum(1 for c in cells if not c)} célula(s) vazia(s); toda coluna precisa de um cabeçalho.") run = longest = 0 for w in re.findall(r"[A-Za-z]+", line): run = run + 1 if w.isupper() and (len(w) > 1 or w in "AI") else 0 longest = max(longest, run) if longest >= 5 and not hm: add("INFO", no, "tudo-maiúsculas", "Texto longo TUDO EM MAIÚSCULAS é difícil de ler e alguns leitores de tela o soletram letra por letra.") if EMOJI_BULLET.match(line): add("INFO", no, "marcador-emoji", "Emoji usado como marcador é lido em voz alta pelo nome; use um marcador de lista e mantenha emojis raros e significativos.") cm = COLOR_ONLY.search(line) if cm: between = line[cm.end(1):cm.start(2)] inside_parens = line[:cm.start(2)].count("(") > line[:cm.start(2)].count(")") names_label = re.match(r"\s+(\*\*|\"|')?[A-Z]", between) # "Select Save ..." or "Press **Save**" if inside_parens or names_label: cm = None if cm: add("AVISO", no, "apenas-cor", "A instrução depende de cor; adicione também o rótulo, forma ou posição.") prev_blank = not stripped h1 = [h for h in headings if h[1] == 1] if headings and not h1: add("AVISO", headings[0][0], "sem-h1", "O documento não tem H1; comece com um título #.") if len(h1) > 1: add("AVISO", h1[1][0], "múltiplos-h1", f"{len(h1)} títulos H1 (linhas {', '.join(str(h[0]) for h in h1)}); mantenha um título e use ## para seções.") for (pno, plev, _), (no, lev, title) in zip(headings, headings[1:]): if lev > plev + 1: add("AVISO", no, "pulo-de-título", f"O nível do título pula de H{plev} para H{lev} (\"{title[:50]}\"); use H{plev + 1}.") if not headings and len([l for l in lines if l.strip()]) > 15: add("INFO", 1, "sem-títulos", "Documento longo sem títulos; adicione títulos para que os leitores possam navegar.") for label, targets in link_targets.items(): if len(targets) > 1 and label not in VAGUE_LINK: first = min(targets.values()) add("AVISO", first, "mesmo-texto-url-diferente", f"O texto do link \"{label}\" aponta para {len(targets)} URLs diferentes; torne cada texto único.") order = {"ALTO": 0, "AVISO": 1, "INFO": 2} findings.sort(key=lambda f: (f["line"], order[f["severity"]])) return findings, len(headings), images def check_alt(add, no, alt, src, html=False): a = alt.strip() base = os.path.basename(src) if src else "" if a == "" and html: add("INFO", no, "img-decorativa", f"<img src=\"{base}\"> tem alt=\"\" (marcada como decorativa); confirme que não carrega informação.") return if a == "" and src: add("ALTO", no, "img-alt-ausente", f"A imagem {base or src} tem texto alternativo vazio; descreva-a ou confirme que é puramente decorativa.") return low = a.lower().rstrip(".") if low in GENERIC_ALT: add("AVISO", no, "img-alt-genérico", f"O texto alternativo \"{a}\" para {base} é genérico; diga o que a imagem mostra ou por que está ali.") elif FILE_ALT.search(a) or (base and low == os.path.splitext(base)[0].lower()): add("AVISO", no, "img-alt-nome-de-arquivo", f"O texto alternativo \"{a}\" parece um nome de arquivo; descreva a imagem em vez disso.") elif REDUNDANT_START.match(a): add("INFO", no, "img-alt-redundante", f"O texto alternativo começa com \"{' '.join(a.split()[:3])}\"; leitores de tela já dizem 'imagem', então comece com o conteúdo.") if len(a) > 150: add("AVISO", no, "img-alt-longo", f"O texto alternativo tem {len(a)} caracteres; mantenha-o abaixo de cerca de 150 e mova os detalhes para o texto ao redor ou uma legenda.") def collect(paths): files = [] for p in paths: if p == "-": files.append("-") elif os.path.isdir(p): for root, dirs, names in os.walk(p): dirs[:] = sorted(d for d in dirs if not d.startswith(".") and d != "node_modules") files += [os.path.join(root, n) for n in sorted(names) if n.lower().endswith((".md", ".markdown"))] elif os.path.isfile(p): files.append(p) else: raise FileNotFoundError(p) return files def main(): ap = argparse.ArgumentParser(description="Verificador de acessibilidade Markdown") ap.add_argument("paths", nargs="+", help="Arquivos Markdown, pastas ou - para stdin") ap.add_argument("--json", action="store_true") ap.add_argument("--fail-on", choices=["high", "warn"], default="high") args = ap.parse_args() try: files = collect(args.paths) except FileNotFoundError as e: print(f"erro: caminho não encontrado: {e}", file=sys.stderr) return 2 if not files: print("erro: nenhum arquivo Markdown (*.md, *.markdown) encontrado", file=sys.stderr) return 2 all_findings, stats = [], [] for f in files: text = sys.stdin.read() if f == "-" else open(f, encoding="utf-8", errors="replace").read() name = "<stdin>" if f == "-" else f found, nhead, images = check_text(text, name) stats.append({"file": name, "images": images, "headings": nhead, "findings": len(found)}) all_findings += found counts = {s: sum(1 for x in all_findings if x["severity"] == s) for s in ("ALTO", "AVISO", "INFO")} if args.json: print(json.dumps({"files": stats, "counts": counts, "findings": all_findings}, indent=2)) else: print(f"Verificação de acessibilidade Markdown: {len(files)} arquivo(s), {sum(s['images'] for s in stats)} imagem(ns)") print(f"ALTO {counts['ALTO']} AVISO {counts['AVISO']} INFO {counts['INFO']}") for s in stats: items = [x for x in all_findings if x["file"] == s["file"]] print(f"\n{s['file']} ({s['images']} imagens, {s['headings']} títulos): {len(items)} descoberta(s)") for x in items: print(f" {x['line']:>4} {x['severity']:<4} {x['rule']:<24} {x['message']}") print("\nAs verificações automatizadas cobrem apenas parte da acessibilidade; revise o significado do texto alternativo, a ordem de leitura e o contraste manualmente.") bad = counts["ALTO"] + (counts["AVISO"] if args.fail_on == "warn" else 0) return 1 if bad else 0 if __name__ == "__main__": sys.exit(main())

Entre para ver o prompt completo

Continuar com:

Ao entrar, você concorda com nossos Termos de uso e Política de privacidade

Uso

Este prompt foi projetado para uso com productivity. Copie o conteúdo acima e cole na sua ferramenta de IA preferida.

Para melhores resultados, personalize os marcadores (indicados por colchetes ou maiúsculas) com seus requisitos específicos.

Referências

Categorias:productivity| prompts.chat| markdown| accessibility

Discussão

0 comentários