remove: image heavy description warning

This commit is contained in:
tdgao
2026-08-28 12:28:11 -06:00
parent 0d90c205bf
commit d3146a6acb
34 changed files with 12 additions and 230 deletions
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "تنظيف الروابط المتطابقة"
},
"nags.image-heavy-description.description": {
"defaultMessage": "وصفك يجب أن يحتوي على نص عادي أو نص بديل للصورة، لتكون متاحة لمستخدمي قارئ الشاشة أو من لا توجد عنده اتصال إنترنت جيد."
},
"nags.image-heavy-description.title": {
"defaultMessage": "يرجى التأكد من إمكانية الوصول في وصفك"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "رابط الرخصة غير صالح."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Odstraňte duplicitní odkazy"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Popis by měl obsahovat dostatečné množství prostého textu nebo popisků u obrázku, aby byl přístupný i těm, kteří používají čtečky obrazovky nebo mají pomalé připojení k internetu."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Zajistěte přístupnost"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "URL licence je neplatná."
},
@@ -71,9 +71,6 @@
"nags.identical-links.description": {
"defaultMessage": "Nogle af dine eksterne links ser ud til at være identiske. Hvert link skal kun indtastes en gang og med den korrekte linktype."
},
"nags.image-heavy-description.description": {
"defaultMessage": "Din Beskrivelse burde indeholde tilstrækkelig almindelig tekst eller billedtekst, så den er tilgængelig for personer som bruger skærmlæsere eller med langsom internet forbindelse."
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Licens-URL'en er ugyldig."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Identische Links bereinigen"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Deine Beschreibung sollte genügend normalen Text und Alt-Text für Bilder enthalten, damit es für Benutzer mit Bildschirmleseprogrammen oder langsamem Internet verfügbar ist."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Barrierefreiheit sicherstellen"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Lizenz-URL ist ungültig."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Doppelte Links löschen"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Deine Beschreibung sollte ausreichend Klartext oder Alt-Text für Bilder enthalten, damit sie für Nutzer mit Bildschirmleseprogrammen oder langsamer Internetverbindung zugänglich bleibt."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Barrierefreiheit sicherstellen"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Lizenz-URL ist ungültig."
},
@@ -113,12 +113,6 @@
"nags.identical-links.title": {
"defaultMessage": "Clean up identical links"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Your Description should contain sufficient plain text or image alt-text, keeping it accessible to those using screen readers or with slow internet connections."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Ensure accessibility"
},
"nags.invalid-gallery-text.title": {
"defaultMessage": "Fix gallery text"
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Limpiar links idénticos"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Tu descripción debe incluir suficiente texto plano o texto alternativo para imágenes, de modo que sea accesible para quienes usan lectores de pantalla o tienen conexiones lentas a Internet."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Asegura la accesibilidad"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "La URL de la licencia no es válida."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Limpiar links idénticos"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Tu Descripción debe contener suficiente texto sin formato o texto alternativo para imágenes, de modo que sea accesible para quienes utilizan lectores de pantalla o tienen conexiones lentas a Internet."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Garantizar la accesibilidad"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "La URL de la licencia no es válida."
},
@@ -59,9 +59,6 @@
"nags.gpl-license-source-required.title": {
"defaultMessage": "Anna lähdekoodi"
},
"nags.image-heavy-description.title": {
"defaultMessage": "Varmista esteettömyys"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Lisenssin URL-osoite on virheellinen."
},
@@ -77,12 +77,6 @@
"nags.identical-links.title": {
"defaultMessage": "Ipaglinis ang mga magkaparehong link"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Ang iyong Paglalarawan ay dapat maglalaman ng simpleng teksto o image alt-text, panatilihing accessible sa mga gumamagamit ng screen reader o mahihina ang koneksiyon sa internet."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Siguraduhin ang aksesibilidad"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Di-wasto ang URL ng lisensiya."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Nettoyer des liens identiques"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Votre description doit contenir suffisamment de texte clair ou de texte alternatif pour les images, afin de rester accessible aux personnes utilisant des lecteurs d’écran ou disposant dune connexion Internet lente."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Garantir laccessibilité"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "LURL de la licence est invalide."
},
@@ -89,12 +89,6 @@
"nags.identical-links.title": {
"defaultMessage": "תמחק קישורים זהים"
},
"nags.image-heavy-description.description": {
"defaultMessage": "התיאור שלך צריך להכיל מספיק טקסט פשוט או טקסט חלופי לתמונה, כדי שיישאר נגיש למשתמשים עם הקראות מסך או חיבורי אינטרנט איטיים."
},
"nags.image-heavy-description.title": {
"defaultMessage": "הבטח נגישות"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "כתובת ה-URL של הרישיון אינה חוקית."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Töröld az azonos linkeket"
},
"nags.image-heavy-description.description": {
"defaultMessage": "A leírásnak elegendő mennyiségű egyszerű szöveget vagy képhelyettesítő szöveget kell tartalmaznia, hogy a képernyőolvasókat használók vagy lassú internetkapcsolattal rendelkezők számára is hozzáférhető legyen."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Biztosítsa az akadálymentességet"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "A licensz linkje érvénytelen."
},
@@ -89,12 +89,6 @@
"nags.identical-links.title": {
"defaultMessage": "Bersihkan tautan identik"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Keterangan Anda seharusnya berisi teks biasa atau teks alt gambar yang cukup, agar memastikan aksesibilitas terhadap pengguna pembaca layar atau pengguna dengan koneksi internet yang lambat."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Pastikan aksesibilitas"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "URL lisensi tidak sah."
},
@@ -89,12 +89,6 @@
"nags.identical-links.title": {
"defaultMessage": "Rimuovi i link identici"
},
"nags.image-heavy-description.description": {
"defaultMessage": "La descrizione dovrebbe essere minuta e avere delle descrizioni testuali alle immagini per chi usa lettori dello schermo o abbia connessioni a Internet lente."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Garantisci l'accessibilità"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "L'URL della licenza non è valido."
},
@@ -92,12 +92,6 @@
"nags.identical-links.title": {
"defaultMessage": "リンクの重複を整理"
},
"nags.image-heavy-description.description": {
"defaultMessage": "視覚障害のある方やインターネット回線速度の遅い方への配慮のため、十分で分かりやすい説明または画像の代替テキストが必要です。"
},
"nags.image-heavy-description.title": {
"defaultMessage": "アクセシビリティを確保する"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "ライセンスのURLが無効です。"
},
@@ -89,12 +89,6 @@
"nags.identical-links.title": {
"defaultMessage": "중복 링크 정리"
},
"nags.image-heavy-description.description": {
"defaultMessage": "설명에는 충분한 일반 텍스트 또는 이미지 대체 텍스트를 포함하여, 화면 읽기 도구를 사용하는 사용자나 인터넷 속도가 느린 사용자도 접근할 수 있도록 해야 합니다."
},
"nags.image-heavy-description.title": {
"defaultMessage": "접근성 보장"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "라이선스 URL이 잘못되었습니다."
},
@@ -77,12 +77,6 @@
"nags.identical-links.title": {
"defaultMessage": "Bersihkan pautan yang serupa"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Keterangan anda harus mengandungi teks biasa atau teks alt gambar yang mencukupi, memastikan ia boleh diakses oleh mereka yang menggunakan pembaca skrin atau dengan sambungan internet yang perlahan."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Pastikan kebolehcapaian"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "URL lesen tidak sah."
},
@@ -89,12 +89,6 @@
"nags.identical-links.title": {
"defaultMessage": "Identieke links opschonen"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Je beschrijving moet voldoende normale tekst of alternatieve tekst bij afbeeldingen bevatten, zodat deze toegankelijk blijft voor mensen die een schermlezer gebruiken of een trage internetverbinding hebben."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Zorg voor toegankelijkheid"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Licentie URL is ongeldig."
},
@@ -83,12 +83,6 @@
"nags.identical-links.title": {
"defaultMessage": "Fjern identiske lenker"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Beskrivelsen din bør inneholde tilstrekkelig med ren tekst eller alternativ tekst til bilder, slik at den er tilgjengelig for personer som bruker skjermlesere eller har langsomme internettforbindelser."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Sikre tilgjengelighet"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Lisens-URL er ugyldig."
},
@@ -89,12 +89,6 @@
"nags.identical-links.title": {
"defaultMessage": "Usuń identyczne linki"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Twój opis powinien zawierać wystarczająco zwykłego tekstu lub tekstu alternatywnego obrazów, aby był przystępny dla osób korzystających z czytników ekranu lub mających wolne połączenie z internetem."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Zapewnij dostępność"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Adres URL licencji jest nieprawidłowy."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Limpar links idênticos"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Sua descrição deve conter texto simples ou imagem com texto alternativo, permanecendo acessível para usuários que usam leitores de tela ou têm conexão lenta."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Garanta a acessibilidade"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "O URL de licença é inválido."
},
@@ -83,12 +83,6 @@
"nags.identical-links.title": {
"defaultMessage": "Limpar links idênticos"
},
"nags.image-heavy-description.description": {
"defaultMessage": "A tua Descrição deve conter texto simples ou texto alternativo para imagens suficiente, mantendo-a acessível aos que utilizam leitores de ecrã ou que têm ligações lentas à internet."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Garante acessibilidade"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "O URL da licença é inválido."
},
@@ -71,12 +71,6 @@
"nags.identical-links.description": {
"defaultMessage": "Unele dintre linkurile dvs. externe par a fi identice. Fiecare link trebuie introdus o singură dată și cu tipul de link corespunzător."
},
"nags.image-heavy-description.description": {
"defaultMessage": "Descrierea ta ar trebui să conțină suficient text simplu sau text alternativ pentru imagini, pentru a o face accesibilă persoanelor care folosesc cititoare de ecran sau care au o conexiune lentă la internet."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Asigură accesibilitatea"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "URL-ul licenței este invalid."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Уберите повторения"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Укажите в описании обычный и альтернативный текст для изображений, чтобы сделать его доступным для средств чтения с экрана и при медленном интернете."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Обеспечьте доступность"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Ссылка на лицензию недействительна."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Počisti identične linkove"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Tvoj opis treba da sadrži dovoljno običnog teksta ili alternativnog teksta slike, kako bi bio pristupačan onima koji koriste čitače ekrana ili imaju spore internet veze."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Obezbedi pristupačnost"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "URL adresa licence je nevažeća."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Städa upp identiska länkar"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Din beskrivning ska ha tillräckligt med vanlig text eller bild-alternativtext, för att hålla det tillgängligt till de som använder skärmavläsare eller de med långsamma internetkopplingar."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Säkerställ tillgänglighet"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Licens-URL är ogiltig."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Özdeş bağlantıları temizle"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Açıklaman yeterli düz yazı veya resim açıklamalı içermeli ki ekran okuyucu veya patates internet kullananlar için erişilebilir olsun."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Erişilebilirlikte emin ol"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Lisans URL'i geçersiz."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "Приберіть однакові посилання"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Ваш опис повинен містити достатню кількість простого тексту або альтернативного тексту зображень, щоби він був зрозумілим для тих, хто використовує читачі екрану або має повільне з’єднання з інтернетом."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Забезпечте доступність"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "Посилання на ліцензію неправильне."
},
@@ -89,12 +89,6 @@
"nags.identical-links.title": {
"defaultMessage": "Xóa các đường link giống nhau"
},
"nags.image-heavy-description.description": {
"defaultMessage": "Phần mô tả của bạn nên chứa đủ văn bản thuần hoặc văn bản thay thế cho hình ảnh (alt-text), nhằm đảm bảo khả năng truy cập cho người dùng trình đọc màn hình hoặc có kết nối internet chậm."
},
"nags.image-heavy-description.title": {
"defaultMessage": "Đảm bảo khả năng truy cập"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "URL giấy phép không hợp lệ."
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "清除重复的链接"
},
"nags.image-heavy-description.description": {
"defaultMessage": "你的介绍描述应包含足够的纯文本或图片替代文本,确保使用屏幕阅读器的用户或网速较慢的用户也能正常访问。"
},
"nags.image-heavy-description.title": {
"defaultMessage": "确保无障碍体验"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "许可证 URL 不可用。"
},
@@ -95,12 +95,6 @@
"nags.identical-links.title": {
"defaultMessage": "清理重複連結"
},
"nags.image-heavy-description.description": {
"defaultMessage": "請在描述中提供充足的純文字或圖片替代文字,讓螢幕閱讀器使用者與網路速度較慢的使用者也能順利閱讀。"
},
"nags.image-heavy-description.title": {
"defaultMessage": "確保無障礙體驗"
},
"nags.invalid-license-url.description.default": {
"defaultMessage": "授權條款網址無效。"
},
@@ -37,10 +37,6 @@ const messages = defineMessages({
id: 'nags.long-headers.title',
defaultMessage: 'Shorten headers',
},
ensureAccessibility: {
id: 'nags.image-heavy-description.title',
defaultMessage: 'Ensure accessibility',
},
addImageAltText: {
id: 'nags.missing-alt-text.title',
defaultMessage: 'Add image alt text',
@@ -80,11 +76,6 @@ const messages = defineMessages({
defaultMessage:
'{count, plural, one {# header} other {# headers}} in your description {count, plural, one {is} other {are}} too long. Headers should be concise and act as section titles, not full sentences.',
},
imageHeavy: {
id: 'nags.image-heavy-description.description',
defaultMessage:
'Your Description should contain sufficient plain text or image alt-text, keeping it accessible to those using screen readers or with slow internet connections.',
},
missingAltText: {
id: 'nags.missing-alt-text.description',
defaultMessage:
@@ -96,7 +87,6 @@ export const DESCRIPTION_MAX_PROFANITY_COUNT = 2
export const DESCRIPTION_NON_STANDARD_TEXT_FAILURE_THRESHOLD = 0.05
export const MIN_DESCRIPTION_CHARS = 200
export const MAX_HEADER_LENGTH = 80
export const MIN_CHARS_PER_IMAGE = 60
export const BANNED_DESCRIPTION_LINK_DOMAINS = [...URL_SHORTENERS] as const
const descriptionLinkify = new LinkifyIt({
@@ -169,21 +159,13 @@ export function countText(markdown: string): number {
}
export function analyzeImageContent(markdown: string): {
imageHeavy: boolean
hasEmptyAltText: boolean
} {
if (!markdown) return { imageHeavy: false, hasEmptyAltText: false }
if (!markdown) return { hasEmptyAltText: false }
const withoutCodeBlocks = markdown.replace(/```[\s\S]*?```/g, '').replace(/`[^`]*`/g, '')
const images = [...withoutCodeBlocks.matchAll(/!\[([^\]]*)\]\([^)]+\)/g)]
const htmlImages = [...withoutCodeBlocks.matchAll(/<img[^>]*>/gi)]
const totalImages = images.length + htmlImages.length
if (totalImages === 0) return { imageHeavy: false, hasEmptyAltText: false }
const textLength = countText(withoutCodeBlocks)
const recommendedTextLength = MIN_CHARS_PER_IMAGE * totalImages
const imageHeavy =
recommendedTextLength > MIN_DESCRIPTION_CHARS && textLength < recommendedTextLength
const hasEmptyAltText =
images.some((match) => !match[1]?.trim()) ||
htmlImages.some((match) => {
@@ -191,7 +173,7 @@ export function analyzeImageContent(markdown: string): {
return !altMatch || !altMatch[1]?.trim()
})
return { imageHeavy, hasEmptyAltText }
return { hasEmptyAltText }
}
type DescriptionInput = string | null | undefined
@@ -285,16 +267,6 @@ export const projectDescriptionValidationRules = {
nag: { title: messages.shortenHeaders, ...commonNagPresentation },
},
},
'image-heavy-description': {
severity: 'warning',
evaluate: (description) => ({
valid: !analyzeImageContent(description ?? '').imageHeavy,
}),
presentation: {
message: messages.imageHeavy,
nag: { title: messages.ensureAccessibility, ...commonNagPresentation },
},
},
'missing-alt-text': {
severity: 'warning',
evaluate: (description) => ({
@@ -3,11 +3,11 @@ import test from 'node:test'
import { evaluateRules } from './evaluate-rules.ts'
import {
analyzeImageContent,
BANNED_DESCRIPTION_LINK_DOMAINS,
countText,
extractDescriptionLinks,
findBannedDescriptionLink,
MIN_CHARS_PER_IMAGE,
MIN_DESCRIPTION_CHARS,
validateProjectDescription,
} from './rules/description.ts'
@@ -178,10 +178,18 @@ test('validates description requirements and simultaneous recommendations', () =
const description = `${'# '.concat('A'.repeat(81))}\n![](one.png)\n![](two.png)\n![](three.png)\n![](four.png)`
assert.deepEqual(
validateProjectDescription(description).map(({ code }) => code),
['description-too-short', 'long-headers', 'image-heavy-description', 'missing-alt-text'],
['description-too-short', 'long-headers', 'missing-alt-text'],
)
})
test('requires alt text for description images', () => {
assert.deepEqual(analyzeImageContent('![Screenshot](screenshot.png)'), {
hasEmptyAltText: false,
})
assert.deepEqual(analyzeImageContent('![](screenshot.png)'), { hasEmptyAltText: true })
assert.deepEqual(analyzeImageContent('<img src="screenshot.png">'), { hasEmptyAltText: true })
})
test('counts blockquote content as readable description text', () => {
assert.equal(countText('> Quoted text'), 'Quoted text'.length)
@@ -192,18 +200,6 @@ test('counts blockquote content as readable description text', () => {
),
false,
)
const images = ['![One](one.png)', '![Two](two.png)', '![Three](three.png)', '![Four](four.png)']
const quotedImageDescription = [
`> ${'A'.repeat(MIN_CHARS_PER_IMAGE * images.length)}`,
...images,
].join('\n')
assert.equal(
validateProjectDescription(quotedImageDescription).some(
({ code }) => code === 'image-heavy-description',
),
false,
)
})
test('uses the gallery text rules for names and descriptions', () => {