@chrissgon/light-site-auditor 0.1.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.
@@ -0,0 +1,619 @@
1
+ {
2
+ "language": "pt-BR",
3
+ "review": {
4
+ "status": "pending-human-review",
5
+ "automatedChecks": "tests/explanations.test.ts: frases de até vinte e cinco palavras, nenhum algarismo, todo termo técnico declarado e definido no glossário, um 'o que fazer' em cada problema, ids reais do axe-core e do Lighthouse.",
6
+ "humanReview": "Falta: leitura do texto por uma pessoa (tarefa T-aud-5 do backlog). Registre aqui quem revisou e quando."
7
+ },
8
+ "glossary": {
9
+ "HTML": "O código que monta o conteúdo da página, como textos, imagens e links.",
10
+ "CSS": "O código que define a aparência da página, como cores, tamanhos e posições.",
11
+ "JavaScript": "O código que faz a página reagir a cliques e mudar sem recarregar.",
12
+ "atributo": "Uma informação extra escrita dentro de uma marcação no código da página.",
13
+ "alt": "O texto alternativo de uma imagem. Ele descreve a imagem para quem não consegue vê-la.",
14
+ "contraste": "A diferença de claridade entre o texto e o fundo atrás dele.",
15
+ "leitor de tela": "Um programa que lê a página em voz alta para pessoas cegas ou com baixa visão.",
16
+ "navegador": "O programa usado para abrir sites, como Chrome, Safari ou Firefox.",
17
+ "servidor": "O computador que guarda o site e o envia para quem o visita.",
18
+ "cache": "Uma cópia que o navegador guarda para não baixar o mesmo arquivo de novo.",
19
+ "compressão": "Um jeito de encolher arquivos de texto antes de enviá-los, sem perder nada do conteúdo.",
20
+ "KB": "Quilobyte, a unidade usada para medir o tamanho de arquivos. Quanto maior o número, mais demora para baixar.",
21
+ "ARIA": "Um conjunto de marcações extras que explicam partes da página para leitores de tela.",
22
+ "foco": "A marca que mostra em que ponto da página o teclado está, ao navegar com a tecla Tab.",
23
+ "WebP": "Um formato de imagem moderno, que ocupa menos espaço com a mesma qualidade.",
24
+ "AVIF": "Outro formato de imagem moderno, que costuma ocupar ainda menos espaço que o WebP.",
25
+ "3G": "Um tipo de conexão de internet de celular antiga e lenta.",
26
+ "JSON": "Um arquivo de dados feito para programas lerem. Os números deste relatório saem dele.",
27
+ "Lighthouse": "Uma ferramenta gratuita do Google que mede a velocidade de páginas da web.",
28
+ "axe": "Uma ferramenta gratuita que procura barreiras de acessibilidade em páginas da web.",
29
+ "acessibilidade": "O quanto a página pode ser usada por todas as pessoas, inclusive pessoas com deficiência.",
30
+ "WCAG": "As diretrizes internacionais de acessibilidade para a web. Esta verificação usa os níveis A e AA.",
31
+ "kbit/s": "Quilobits por segundo, a medida da velocidade da internet. Quanto menor o número, mais lenta a conexão.",
32
+ "milissegundo": "A milésima parte de um segundo."
33
+ },
34
+ "jargon": [
35
+ "script",
36
+ "DOM",
37
+ "viewport",
38
+ "render",
39
+ "renderização",
40
+ "renderizar",
41
+ "minificar",
42
+ "minificado",
43
+ "minificação",
44
+ "preload",
45
+ "fetchpriority",
46
+ "lazy",
47
+ "HTTP",
48
+ "HTTPS",
49
+ "CDN",
50
+ "byte",
51
+ "bytes",
52
+ "pixel",
53
+ "pixels",
54
+ "tag",
55
+ "frame",
56
+ "iframe",
57
+ "SVG",
58
+ "protocolo",
59
+ "redirecionamento",
60
+ "framework",
61
+ "plugin",
62
+ "API",
63
+ "LCP",
64
+ "FCP",
65
+ "TBT",
66
+ "CLS",
67
+ "INP",
68
+ "UX",
69
+ "SEO",
70
+ "landmark",
71
+ "label",
72
+ "input",
73
+ "div",
74
+ "span",
75
+ "role",
76
+ "lang",
77
+ "title",
78
+ "bundle",
79
+ "polyfill",
80
+ "throttling",
81
+ "RTT",
82
+ "Kbps",
83
+ "CPU"
84
+ ],
85
+ "impact": {
86
+ "critical": "impede o uso",
87
+ "serious": "atrapalha muito",
88
+ "moderate": "atrapalha",
89
+ "minor": "incomoda"
90
+ },
91
+ "fileTypes": {
92
+ "html": "Página (HTML)",
93
+ "css": "Aparência (CSS)",
94
+ "js": "Código interativo (JavaScript)",
95
+ "image": "Imagens",
96
+ "font": "Fontes de letra",
97
+ "other": "Outros arquivos"
98
+ },
99
+ "report": {
100
+ "title": "Relatório do site",
101
+ "intro": "Este relatório mostra quanto a página pesa, quanto demora para aparecer num celular com internet fraca e o que impede algumas pessoas de usá-la.",
102
+ "introSources": "Os números vêm de duas ferramentas, o Lighthouse e o axe, e estão nos arquivos JSON salvos ao lado deste relatório.",
103
+ "introTerms": "As palavras técnicas estão explicadas no fim, na seção de palavras usadas.",
104
+ "page": "Página verificada",
105
+ "measuredAt": "Medida em",
106
+ "weightHeading": "Peso da página",
107
+ "weightIntro": "Cada visita baixa estes arquivos. No celular, cada arquivo gasta tempo e parte do plano de dados.",
108
+ "weightTotal": "Total baixado: {kb} KB em {files} arquivos.",
109
+ "weightType": "Tipo de arquivo",
110
+ "weightFiles": "Arquivos",
111
+ "weightSize": "Tamanho baixado (KB)",
112
+ "loadHeading": "Tempo para aparecer num celular com 3G",
113
+ "loadIntro": "O Lighthouse simula um celular comum numa conexão 3G e mede quanto tempo cada parte da página leva para aparecer.",
114
+ "loadProfile": "Conexão simulada: espera de ida e volta de {rtt} milissegundos, velocidade de {kbps} kbit/s e processador {cpu} vezes mais lento que o computador da medição.",
115
+ "loadMetric": "{title}: {seconds} segundos.",
116
+ "speedHeading": "O que deixa a página pesada ou lenta",
117
+ "speedNone": "O Lighthouse não apontou nenhum problema de peso ou velocidade nesta página.",
118
+ "speedGainLcp": "Corrigir isso pode fazer a parte principal aparecer até {seconds} segundos mais cedo.",
119
+ "speedGainFcp": "Corrigir isso pode fazer a primeira coisa aparecer até {seconds} segundos mais cedo.",
120
+ "a11yHeading": "Barreiras de acessibilidade",
121
+ "a11yIntro": "O axe procurou barreiras que as diretrizes WCAG pedem para remover. Cada uma impede ou atrapalha alguém de usar a página.",
122
+ "a11yCount": "O axe encontrou {rules} tipos de barreira, em {places} lugares da página.",
123
+ "a11yNone": "O axe não encontrou nenhuma barreira pelas regras WCAG nesta página.",
124
+ "a11yNote": "Ferramentas automáticas acham só parte das barreiras. Um teste com pessoas reais continua necessário.",
125
+ "a11yPlaces": "Aparece em {places} lugares da página.",
126
+ "a11yPlacesOne": "Aparece em um lugar da página.",
127
+ "a11yWhere": "Onde está",
128
+ "a11yMore": "Mais lugares estão no arquivo do axe.",
129
+ "severity": "Gravidade",
130
+ "whatItIs": "O que é",
131
+ "whatToDo": "O que fazer",
132
+ "noExplanation": "sem explicação ainda",
133
+ "noExplanationNote": "Este problema ainda não tem explicação em português simples. Abaixo está o texto original da ferramenta, em inglês.",
134
+ "original": "Texto original",
135
+ "termsHeading": "Palavras usadas neste relatório",
136
+ "sourcesHeading": "De onde vêm os números",
137
+ "sourcesIntro": "Cada número acima pode ser conferido nos arquivos JSON desta pasta, no lugar indicado abaixo.",
138
+ "sourcesWeight": "Peso por tipo: soma dos arquivos do mesmo tipo, no arquivo do Lighthouse",
139
+ "sourcesTotal": "Total baixado: soma de todos os arquivos, igual ao total do próprio Lighthouse",
140
+ "sourcesTime": "Tempos: valor medido de cada métrica, em milissegundos, no arquivo do Lighthouse",
141
+ "sourcesProfile": "Conexão simulada: configuração usada pelo Lighthouse",
142
+ "sourcesGain": "Ganhos possíveis: economia estimada de cada problema, em milissegundos, no arquivo do Lighthouse",
143
+ "sourcesA11y": "Barreiras e lugares: lista de barreiras do axe e os lugares de cada uma"
144
+ },
145
+ "metrics": {
146
+ "first-contentful-paint": {
147
+ "title": "Primeira coisa na tela",
148
+ "what": "Quanto tempo leva até aparecer o primeiro texto ou imagem. Antes disso, a pessoa vê a tela em branco."
149
+ },
150
+ "largest-contentful-paint": {
151
+ "title": "Parte principal na tela",
152
+ "what": "Quanto tempo leva até aparecer o maior texto ou imagem da tela. É quando a página parece pronta para quem visita."
153
+ }
154
+ },
155
+ "lighthouse": {
156
+ "total-byte-weight": {
157
+ "title": "A página é pesada",
158
+ "what": "A página inteira pesa muito para baixar. No celular com internet fraca, isso atrasa tudo e gasta o plano de dados.",
159
+ "fix": "Comece pelos arquivos maiores da tabela de peso. Imagens costumam ser as primeiras a reduzir.",
160
+ "terms": []
161
+ },
162
+ "image-delivery-insight": {
163
+ "title": "Imagens maiores do que precisam",
164
+ "what": "Há imagens com mais detalhe ou mais peso do que o tamanho em que aparecem na tela.",
165
+ "fix": "Salve cada imagem no tamanho em que ela aparece e use um formato moderno, como WebP ou AVIF.",
166
+ "terms": [
167
+ "WebP",
168
+ "AVIF"
169
+ ]
170
+ },
171
+ "render-blocking-insight": {
172
+ "title": "Arquivos que seguram a página em branco",
173
+ "what": "O navegador espera alguns arquivos de aparência ou de código terminarem de baixar antes de mostrar qualquer coisa.",
174
+ "fix": "Peça a quem cuida do site para carregar esses arquivos depois, ou para colocar o essencial dentro da própria página.",
175
+ "terms": [
176
+ "navegador"
177
+ ]
178
+ },
179
+ "lcp-discovery-insight": {
180
+ "title": "A imagem principal não tem prioridade",
181
+ "what": "O navegador não sabe que a imagem principal é a mais importante e não a baixa primeiro.",
182
+ "fix": "Peça a quem cuida do site para marcar a imagem principal como prioritária e nunca adiar o carregamento dela.",
183
+ "terms": [
184
+ "navegador"
185
+ ]
186
+ },
187
+ "network-dependency-tree-insight": {
188
+ "title": "Arquivos que esperam por outros",
189
+ "what": "Alguns arquivos só começam a baixar depois que outro termina. Na internet lenta, cada espera soma tempo.",
190
+ "fix": "Peça a quem cuida do site para encurtar essas esperas e avisar o navegador cedo sobre os arquivos importantes.",
191
+ "terms": [
192
+ "navegador"
193
+ ]
194
+ },
195
+ "cache-insight": {
196
+ "title": "Arquivos baixados de novo a cada visita",
197
+ "what": "O servidor não autoriza o navegador a guardar os arquivos. Quem volta ao site baixa tudo outra vez.",
198
+ "fix": "Configure o servidor para permitir cache longo em imagens e arquivos que mudam pouco.",
199
+ "terms": [
200
+ "servidor",
201
+ "navegador",
202
+ "cache"
203
+ ]
204
+ },
205
+ "document-latency-insight": {
206
+ "title": "A página demora a começar a chegar",
207
+ "what": "O servidor demora para responder, manda o visitante para outro endereço antes ou envia o texto sem compressão.",
208
+ "fix": "Verifique a hospedagem, evite desvios de endereço desnecessários e ative a compressão no servidor.",
209
+ "terms": [
210
+ "servidor",
211
+ "compressão"
212
+ ]
213
+ },
214
+ "font-display-insight": {
215
+ "title": "Texto invisível enquanto a fonte de letra chega",
216
+ "what": "O texto fica escondido até a fonte de letra própria do site terminar de baixar.",
217
+ "fix": "Peça a quem cuida do site para mostrar o texto com uma fonte comum enquanto a fonte própria chega.",
218
+ "terms": []
219
+ },
220
+ "unused-css-rules": {
221
+ "title": "Regras de aparência que a página não usa",
222
+ "what": "A página baixa regras de CSS que não usa. Elas pesam sem trazer nada para quem visita.",
223
+ "fix": "Remova as regras que nenhuma página usa, ou separe as regras de cada página.",
224
+ "terms": [
225
+ "CSS"
226
+ ]
227
+ },
228
+ "unused-javascript": {
229
+ "title": "Código interativo que a página não usa",
230
+ "what": "A página baixa código JavaScript que não roda nela.",
231
+ "fix": "Remova pacotes de código e trechos que não são usados, ou carregue cada parte só onde ela é necessária.",
232
+ "terms": [
233
+ "JavaScript"
234
+ ]
235
+ },
236
+ "unminified-css": {
237
+ "title": "Arquivos de aparência com espaços sobrando",
238
+ "what": "O arquivo de CSS vai com espaços, quebras de linha e comentários que só servem para quem escreve o código.",
239
+ "fix": "Ligue a opção de encolher arquivos da sua ferramenta de criação de sites ou da hospedagem antes de publicar.",
240
+ "terms": [
241
+ "CSS"
242
+ ]
243
+ },
244
+ "unminified-javascript": {
245
+ "title": "Código interativo com espaços sobrando",
246
+ "what": "O arquivo de JavaScript vai com espaços, quebras de linha e comentários que só servem para quem escreve o código.",
247
+ "fix": "Ligue a opção de encolher arquivos da sua ferramenta de criação de sites ou da hospedagem antes de publicar.",
248
+ "terms": [
249
+ "JavaScript"
250
+ ]
251
+ },
252
+ "legacy-javascript-insight": {
253
+ "title": "Código extra para navegadores antigos",
254
+ "what": "A página envia código a mais para funcionar em navegadores antigos. Os navegadores atuais não precisam dele.",
255
+ "fix": "Peça a quem cuida do site para gerar o código só para navegadores atuais.",
256
+ "terms": [
257
+ "navegador"
258
+ ]
259
+ },
260
+ "duplicated-javascript-insight": {
261
+ "title": "Código repetido",
262
+ "what": "O mesmo pacote de código aparece mais de uma vez, e o celular baixa todas as cópias.",
263
+ "fix": "Peça a quem cuida do site para manter uma só cópia de cada pacote de código.",
264
+ "terms": []
265
+ },
266
+ "third-parties-insight": {
267
+ "title": "Serviços de outras empresas pesando na página",
268
+ "what": "Ferramentas de outras empresas, como chats, anúncios e contadores de visitas, baixam arquivos e ocupam o celular.",
269
+ "fix": "Mantenha só os serviços que você realmente usa e remova os outros.",
270
+ "terms": []
271
+ },
272
+ "unsized-images": {
273
+ "title": "Imagens sem tamanho definido",
274
+ "what": "Algumas imagens não informam largura e altura. O conteúdo pula de lugar quando elas terminam de chegar.",
275
+ "fix": "Informe a largura e a altura de cada imagem no código da página.",
276
+ "terms": []
277
+ },
278
+ "dom-size-insight": {
279
+ "title": "Página com partes demais",
280
+ "what": "A página tem uma quantidade muito grande de blocos. O celular demora para montar e atualizar tudo.",
281
+ "fix": "Divida conteúdos longos em mais páginas e remova blocos escondidos que ninguém usa.",
282
+ "terms": []
283
+ },
284
+ "bootup-time": {
285
+ "title": "Código interativo demorando para rodar",
286
+ "what": "O celular gasta muito tempo processando o código JavaScript da página.",
287
+ "fix": "Remova códigos e serviços que não são essenciais, ou carregue-os depois que a página aparecer.",
288
+ "terms": [
289
+ "JavaScript"
290
+ ]
291
+ },
292
+ "mainthread-work-breakdown": {
293
+ "title": "O celular trabalha demais para montar a página",
294
+ "what": "O processador do celular fica ocupado por muito tempo com a aparência, o código e o desenho da página.",
295
+ "fix": "Reduza código interativo e efeitos visuais pesados, começando pelos que você não usa.",
296
+ "terms": []
297
+ },
298
+ "viewport-insight": {
299
+ "title": "Página não ajustada à tela do celular",
300
+ "what": "A página não avisa ao celular que deve caber na largura da tela, e o toque pode demorar a responder.",
301
+ "fix": "Peça a quem cuida do site para incluir a marcação de ajuste à tela do celular no começo da página.",
302
+ "terms": []
303
+ },
304
+ "modern-http-insight": {
305
+ "title": "Entrega de arquivos no modo antigo",
306
+ "what": "O servidor entrega os arquivos com uma versão antiga das regras da web, mais lenta quando há muitos arquivos.",
307
+ "fix": "Peça à hospedagem para ativar a versão atual de entrega de arquivos.",
308
+ "terms": [
309
+ "servidor"
310
+ ]
311
+ }
312
+ },
313
+ "axe": {
314
+ "color-contrast": {
315
+ "title": "Texto difícil de ler",
316
+ "what": "O texto tem pouco contraste com o fundo. Pessoas com baixa visão, ou lendo no sol, não conseguem ler.",
317
+ "fix": "Escureça o texto ou clareie o fundo até a leitura ficar fácil. Uma ferramenta de contraste mostra quando passa.",
318
+ "terms": [
319
+ "contraste"
320
+ ]
321
+ },
322
+ "image-alt": {
323
+ "title": "Imagem sem descrição",
324
+ "what": "A imagem não tem texto alternativo, o alt. Quem usa leitor de tela não sabe o que ela mostra.",
325
+ "fix": "Escreva no alt o que a imagem mostra, em poucas palavras. Se ela for só decoração, deixe o alt vazio.",
326
+ "terms": [
327
+ "alt",
328
+ "leitor de tela"
329
+ ]
330
+ },
331
+ "label": {
332
+ "title": "Campo de formulário sem nome",
333
+ "what": "Um campo de formulário não tem um nome ligado a ele. Quem usa leitor de tela não sabe o que preencher.",
334
+ "fix": "Coloque um texto visível ao lado de cada campo e ligue esse texto ao campo no código.",
335
+ "terms": [
336
+ "leitor de tela"
337
+ ]
338
+ },
339
+ "link-name": {
340
+ "title": "Link sem texto",
341
+ "what": "Um link não tem texto que diga para onde leva. Muitas vezes é um ícone sozinho.",
342
+ "fix": "Escreva um texto no link, ou dê ao ícone um nome que o leitor de tela possa ler.",
343
+ "terms": [
344
+ "leitor de tela"
345
+ ]
346
+ },
347
+ "button-name": {
348
+ "title": "Botão sem nome",
349
+ "what": "Um botão não tem texto que diga o que ele faz. Quem usa leitor de tela ouve só a palavra botão.",
350
+ "fix": "Escreva um texto no botão, ou dê ao ícone do botão um nome que o leitor de tela possa ler.",
351
+ "terms": [
352
+ "leitor de tela"
353
+ ]
354
+ },
355
+ "input-button-name": {
356
+ "title": "Botão de formulário sem nome",
357
+ "what": "Um botão de formulário não tem texto que diga o que ele faz.",
358
+ "fix": "Escreva no botão o que ele faz, como enviar ou buscar.",
359
+ "terms": []
360
+ },
361
+ "input-image-alt": {
362
+ "title": "Botão de imagem sem descrição",
363
+ "what": "Um botão feito com uma imagem não tem texto alternativo. Quem usa leitor de tela não sabe o que ele faz.",
364
+ "fix": "Escreva no alt da imagem o que o botão faz, como enviar ou buscar.",
365
+ "terms": [
366
+ "alt",
367
+ "leitor de tela"
368
+ ]
369
+ },
370
+ "html-has-lang": {
371
+ "title": "Página sem idioma informado",
372
+ "what": "A página não diz em que idioma está escrita. O leitor de tela pode ler o português com sotaque errado.",
373
+ "fix": "Informe o idioma da página no código, por exemplo português do Brasil.",
374
+ "terms": [
375
+ "leitor de tela"
376
+ ]
377
+ },
378
+ "html-lang-valid": {
379
+ "title": "Idioma da página escrito errado",
380
+ "what": "O idioma informado no código da página não existe na lista oficial de idiomas.",
381
+ "fix": "Corrija o código do idioma. Para português do Brasil, use o código oficial desse idioma.",
382
+ "terms": []
383
+ },
384
+ "valid-lang": {
385
+ "title": "Idioma de um trecho escrito errado",
386
+ "what": "Um trecho da página informa um idioma que não existe na lista oficial de idiomas.",
387
+ "fix": "Corrija o código do idioma desse trecho, ou apague a informação se o trecho estiver no idioma da página.",
388
+ "terms": []
389
+ },
390
+ "document-title": {
391
+ "title": "Página sem título",
392
+ "what": "A página não tem título. É ele que aparece na aba do navegador e que o leitor de tela lê primeiro.",
393
+ "fix": "Dê à página um título curto que diga o nome do site e o assunto da página.",
394
+ "terms": [
395
+ "navegador",
396
+ "leitor de tela"
397
+ ]
398
+ },
399
+ "select-name": {
400
+ "title": "Lista de opções sem nome",
401
+ "what": "Uma lista de escolha não tem nome. Quem usa leitor de tela não sabe o que está escolhendo.",
402
+ "fix": "Coloque um texto visível ao lado da lista e ligue esse texto à lista no código.",
403
+ "terms": [
404
+ "leitor de tela"
405
+ ]
406
+ },
407
+ "frame-title": {
408
+ "title": "Conteúdo embutido sem nome",
409
+ "what": "Um conteúdo de outro site dentro da página, como um mapa ou vídeo, não tem nome.",
410
+ "fix": "Dê a esse conteúdo um nome curto que diga o que ele é, como mapa da loja.",
411
+ "terms": []
412
+ },
413
+ "meta-viewport": {
414
+ "title": "Página impede o zoom",
415
+ "what": "A página não deixa a pessoa aumentar o texto com os dedos. Quem enxerga pouco precisa do zoom.",
416
+ "fix": "Remova do código da página a regra que bloqueia o zoom.",
417
+ "terms": []
418
+ },
419
+ "meta-refresh": {
420
+ "title": "Página que recarrega sozinha",
421
+ "what": "A página recarrega ou muda de endereço sozinha depois de um tempo. A pessoa perde o que estava lendo.",
422
+ "fix": "Remova a recarga automática, ou deixe a pessoa escolher quando atualizar.",
423
+ "terms": []
424
+ },
425
+ "list": {
426
+ "title": "Lista montada do jeito errado",
427
+ "what": "Uma lista tem, dentro dela, partes que não são itens. O leitor de tela conta os itens errado.",
428
+ "fix": "Deixe dentro da lista só os itens dela, e coloque o resto fora.",
429
+ "terms": [
430
+ "leitor de tela"
431
+ ]
432
+ },
433
+ "listitem": {
434
+ "title": "Item de lista fora de uma lista",
435
+ "what": "Um item de lista está solto, fora de uma lista. O leitor de tela não o anuncia como parte de uma lista.",
436
+ "fix": "Coloque o item dentro de uma lista, ou transforme-o em texto comum.",
437
+ "terms": [
438
+ "leitor de tela"
439
+ ]
440
+ },
441
+ "role-img-alt": {
442
+ "title": "Figura sem descrição",
443
+ "what": "Um elemento marcado como imagem não tem descrição. Quem usa leitor de tela não sabe o que ele mostra.",
444
+ "fix": "Dê a essa imagem um nome curto que diga o que ela mostra.",
445
+ "terms": [
446
+ "leitor de tela"
447
+ ]
448
+ },
449
+ "svg-img-alt": {
450
+ "title": "Desenho sem descrição",
451
+ "what": "Um desenho ou ícone marcado como imagem não tem descrição para quem usa leitor de tela.",
452
+ "fix": "Dê ao desenho um nome curto que diga o que ele mostra.",
453
+ "terms": [
454
+ "leitor de tela"
455
+ ]
456
+ },
457
+ "aria-required-attr": {
458
+ "title": "Marcação de acessibilidade incompleta",
459
+ "what": "Uma parte da página usa marcações ARIA, mas falta uma informação que elas exigem.",
460
+ "fix": "Peça a quem cuida do site para completar as marcações ARIA dessa parte, ou removê-las.",
461
+ "terms": [
462
+ "ARIA",
463
+ "acessibilidade"
464
+ ]
465
+ },
466
+ "aria-valid-attr-value": {
467
+ "title": "Marcação de acessibilidade com valor errado",
468
+ "what": "Uma marcação ARIA tem um valor que não existe. O leitor de tela pode anunciar algo falso.",
469
+ "fix": "Peça a quem cuida do site para corrigir o valor da marcação ARIA dessa parte.",
470
+ "terms": [
471
+ "leitor de tela",
472
+ "ARIA",
473
+ "acessibilidade"
474
+ ]
475
+ },
476
+ "aria-valid-attr": {
477
+ "title": "Marcação de acessibilidade com nome errado",
478
+ "what": "Uma marcação ARIA tem um nome que não existe, e o leitor de tela a ignora.",
479
+ "fix": "Peça a quem cuida do site para corrigir o nome da marcação ARIA dessa parte.",
480
+ "terms": [
481
+ "leitor de tela",
482
+ "ARIA",
483
+ "acessibilidade"
484
+ ]
485
+ },
486
+ "aria-allowed-attr": {
487
+ "title": "Marcação de acessibilidade no lugar errado",
488
+ "what": "Uma marcação ARIA foi usada numa parte da página que não aceita essa marcação.",
489
+ "fix": "Peça a quem cuida do site para remover essa marcação ARIA ou trocá-la por uma permitida.",
490
+ "terms": [
491
+ "ARIA",
492
+ "acessibilidade"
493
+ ]
494
+ },
495
+ "aria-hidden-focus": {
496
+ "title": "Parte escondida que o teclado alcança",
497
+ "what": "Uma parte está escondida do leitor de tela, mas o teclado ainda chega nela. A pessoa fica sem saber onde está.",
498
+ "fix": "Tire essa parte do caminho do teclado, ou deixe o leitor de tela enxergá-la.",
499
+ "terms": [
500
+ "leitor de tela"
501
+ ]
502
+ },
503
+ "aria-command-name": {
504
+ "title": "Comando sem nome",
505
+ "what": "Um botão ou link feito com marcações ARIA não tem nome. Quem usa leitor de tela não sabe o que ele faz.",
506
+ "fix": "Dê a esse comando um nome curto que diga o que ele faz.",
507
+ "terms": [
508
+ "ARIA",
509
+ "leitor de tela"
510
+ ]
511
+ },
512
+ "aria-input-field-name": {
513
+ "title": "Campo sem nome",
514
+ "what": "Um campo feito com marcações ARIA não tem nome. Quem usa leitor de tela não sabe o que preencher.",
515
+ "fix": "Dê a esse campo um nome visível que diga o que preencher.",
516
+ "terms": [
517
+ "ARIA",
518
+ "leitor de tela"
519
+ ]
520
+ },
521
+ "nested-interactive": {
522
+ "title": "Botão dentro de botão",
523
+ "what": "Um controle clicável está dentro de outro. O teclado e o leitor de tela não conseguem chegar no de dentro.",
524
+ "fix": "Separe os dois controles, um ao lado do outro.",
525
+ "terms": [
526
+ "leitor de tela"
527
+ ]
528
+ },
529
+ "link-in-text-block": {
530
+ "title": "Link que só se distingue pela cor",
531
+ "what": "Um link no meio do texto só se diferencia pela cor. Quem não distingue cores não o encontra.",
532
+ "fix": "Sublinhe os links que ficam no meio do texto.",
533
+ "terms": []
534
+ },
535
+ "autocomplete-valid": {
536
+ "title": "Preenchimento automático configurado errado",
537
+ "what": "Um campo pede um tipo de preenchimento automático que não existe. O navegador não consegue ajudar a preencher.",
538
+ "fix": "Peça a quem cuida do site para usar um dos tipos oficiais de preenchimento, como nome ou email.",
539
+ "terms": [
540
+ "navegador"
541
+ ]
542
+ },
543
+ "video-caption": {
544
+ "title": "Vídeo sem legenda",
545
+ "what": "Um vídeo não tem legendas. Pessoas surdas ou com o som desligado não entendem o que é falado.",
546
+ "fix": "Adicione legendas ao vídeo com o que é falado e os sons importantes.",
547
+ "terms": []
548
+ },
549
+ "object-alt": {
550
+ "title": "Conteúdo embutido sem descrição",
551
+ "what": "Um conteúdo embutido na página não tem texto alternativo para quem usa leitor de tela.",
552
+ "fix": "Dê a esse conteúdo um texto que diga o que ele mostra.",
553
+ "terms": [
554
+ "leitor de tela"
555
+ ]
556
+ },
557
+ "area-alt": {
558
+ "title": "Área clicável de imagem sem descrição",
559
+ "what": "Uma parte clicável de uma imagem não tem texto alternativo. Quem usa leitor de tela não sabe para onde ela leva.",
560
+ "fix": "Escreva no alt de cada área para onde ela leva.",
561
+ "terms": [
562
+ "alt",
563
+ "leitor de tela"
564
+ ]
565
+ },
566
+ "bypass": {
567
+ "title": "Sem atalho para o conteúdo",
568
+ "what": "Não há um jeito de pular o menu e ir direto ao conteúdo. Quem usa teclado passa pelo menu inteiro em cada página.",
569
+ "fix": "Adicione um link para pular ao conteúdo no começo da página, ou marque as regiões principais no código.",
570
+ "terms": []
571
+ },
572
+ "form-field-multiple-labels": {
573
+ "title": "Campo com mais de um nome",
574
+ "what": "Um campo de formulário tem dois ou mais nomes ligados a ele. O leitor de tela pode ler o nome errado.",
575
+ "fix": "Deixe um único nome ligado a cada campo.",
576
+ "terms": [
577
+ "leitor de tela"
578
+ ]
579
+ },
580
+ "scrollable-region-focusable": {
581
+ "title": "Área com rolagem que o teclado não alcança",
582
+ "what": "Uma área da página rola, mas quem usa só o teclado não consegue chegar nela para rolar.",
583
+ "fix": "Peça a quem cuida do site para deixar essa área alcançável pelo teclado.",
584
+ "terms": []
585
+ },
586
+ "duplicate-id-aria": {
587
+ "title": "Nomes internos repetidos",
588
+ "what": "Duas partes da página usam o mesmo nome interno, e o leitor de tela liga a descrição à parte errada.",
589
+ "fix": "Peça a quem cuida do site para dar um nome interno único a cada parte.",
590
+ "terms": [
591
+ "leitor de tela"
592
+ ]
593
+ },
594
+ "aria-roles": {
595
+ "title": "Marcação de papel que não existe",
596
+ "what": "Uma parte da página diz ser algo usando uma marcação ARIA que não existe.",
597
+ "fix": "Peça a quem cuida do site para corrigir ou remover essa marcação ARIA.",
598
+ "terms": [
599
+ "ARIA"
600
+ ]
601
+ },
602
+ "aria-required-children": {
603
+ "title": "Grupo sem as partes que deveria ter",
604
+ "what": "Uma parte marcada com ARIA como grupo, lista ou menu não contém os itens que esse tipo exige.",
605
+ "fix": "Peça a quem cuida do site para completar os itens do grupo ou corrigir a marcação ARIA.",
606
+ "terms": [
607
+ "ARIA"
608
+ ]
609
+ },
610
+ "aria-required-parent": {
611
+ "title": "Item fora do grupo certo",
612
+ "what": "Um item marcado com ARIA, como item de menu, está fora do grupo a que pertence.",
613
+ "fix": "Peça a quem cuida do site para colocar o item dentro do grupo certo.",
614
+ "terms": [
615
+ "ARIA"
616
+ ]
617
+ }
618
+ }
619
+ }
@@ -0,0 +1,47 @@
1
+ import { writeFileSync } from "node:fs";
2
+ import { pathToFileURL } from "node:url";
3
+ import * as chromeLauncher from "chrome-launcher";
4
+ import lighthouse from "lighthouse";
5
+ import { chromium } from "playwright";
6
+ import { REGULAR_3G, THROTTLING_METHOD } from "./profile.js";
7
+ /**
8
+ * Runs Lighthouse 13.5.0 through its Node API on one URL, mobile, with the 3G profile, and returns
9
+ * the raw result (the `lhr`). Only the performance category runs: it carries the network requests
10
+ * (weight) and the load metrics; accessibility comes from axe (src/a11y.ts).
11
+ */
12
+ export async function runLighthouse(url) {
13
+ const chrome = await chromeLauncher.launch({
14
+ chromePath: chromium.executablePath(),
15
+ chromeFlags: ["--headless=new", "--no-sandbox"],
16
+ });
17
+ try {
18
+ const result = await lighthouse(url, {
19
+ port: chrome.port,
20
+ output: "json",
21
+ logLevel: "error",
22
+ onlyCategories: ["performance"],
23
+ formFactor: "mobile",
24
+ throttlingMethod: THROTTLING_METHOD,
25
+ throttling: { ...REGULAR_3G },
26
+ });
27
+ if (!result)
28
+ throw new Error(`Lighthouse returned no result for ${url}`);
29
+ if (result.lhr.runtimeError)
30
+ throw new Error(`Lighthouse could not load ${url}: ${result.lhr.runtimeError.message}`);
31
+ return result.lhr;
32
+ }
33
+ finally {
34
+ await chrome.kill();
35
+ }
36
+ }
37
+ // Spike entry point (T-aud-2): `npx tsx src/lighthouse.ts <url> [out.json]` saves the raw JSON.
38
+ if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
39
+ const [url, out = "lighthouse.json"] = process.argv.slice(2);
40
+ if (!url || url === "--help") {
41
+ process.stdout.write("Usage: npx tsx src/lighthouse.ts <url> [out.json]\n");
42
+ process.exit(url ? 0 : 2);
43
+ }
44
+ const lhr = await runLighthouse(url);
45
+ writeFileSync(out, `${JSON.stringify(lhr, null, 2)}\n`);
46
+ process.stderr.write(`saved ${out}\n`);
47
+ }