@accesslint/core 0.8.4 → 0.8.6

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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const j = [
1
+ const W = [
2
2
  "a[href]",
3
3
  "button:not([disabled])",
4
4
  'input:not([disabled]):not([type="hidden"])',
@@ -133,7 +133,7 @@ function $e(e) {
133
133
  return null;
134
134
  }
135
135
  }
136
- function W(e) {
136
+ function j(e) {
137
137
  var n;
138
138
  const a = K.get(e);
139
139
  if (a !== void 0) return a;
@@ -1184,7 +1184,7 @@ function Ae(e) {
1184
1184
  return a.length > 0 ? a.join(`
1185
1185
  `) : void 0;
1186
1186
  }
1187
- const jt = {
1187
+ const Wt = {
1188
1188
  id: "text-alternatives/img-alt",
1189
1189
  category: "text-alternatives",
1190
1190
  actRuleIds: ["23a2a8"],
@@ -1229,7 +1229,7 @@ const jt = {
1229
1229
  return a;
1230
1230
  }
1231
1231
  };
1232
- function Wt(e) {
1232
+ function jt(e) {
1233
1233
  var i;
1234
1234
  const a = De(e);
1235
1235
  if (a) return a;
@@ -1250,7 +1250,7 @@ const Ut = {
1250
1250
  const a = [], t = 'svg[role="img"], [role="graphics-document"], [role="graphics-symbol"]';
1251
1251
  for (const i of e.querySelectorAll(t)) {
1252
1252
  if (h(i)) continue;
1253
- if (!Wt(i)) {
1253
+ if (!jt(i)) {
1254
1254
  const o = i.getAttribute("role");
1255
1255
  a.push({
1256
1256
  ruleId: "text-alternatives/svg-img-alt",
@@ -1321,7 +1321,7 @@ const Ut = {
1321
1321
  }
1322
1322
  return a;
1323
1323
  }
1324
- }, Bt = ["image", "picture", "photo", "graphic", "icon", "img"], _t = {
1324
+ }, Bt = /^(image|picture|photo|graphic|icon|img)(\s+of\b|\s*[:\u2013\u2014-]|\s*$)/i, _t = {
1325
1325
  id: "text-alternatives/image-alt-words",
1326
1326
  category: "text-alternatives",
1327
1327
  wcag: ["1.1.1"],
@@ -1329,23 +1329,26 @@ const Ut = {
1329
1329
  tags: ["best-practice"],
1330
1330
  fixability: "contextual",
1331
1331
  browserHint: "Screenshot the image to verify the alt text accurately describes it without filler words like 'image of'.",
1332
- description: "Image alt text should not contain words like 'image', 'photo', or 'picture' — screen readers already announce the element type.",
1332
+ description: "Image alt text should not start with words like 'image of', 'photo of', or 'picture of' — screen readers already announce the element type.",
1333
1333
  guidance: "Screen readers already announce 'image' or 'graphic' before reading alt text, so phrases like 'image of', 'photo of', or 'picture of' are redundant. Remove these words and describe what the image shows. For example, change 'image of a dog' to 'golden retriever playing fetch'.",
1334
1334
  run(e) {
1335
1335
  const a = [];
1336
1336
  for (const t of e.querySelectorAll("img[alt]")) {
1337
- const i = t.getAttribute("alt").toLowerCase();
1337
+ const i = t.getAttribute("alt").trim();
1338
1338
  if (!i) continue;
1339
- const n = Bt.filter((o) => i.split(/\s+/).includes(o));
1340
- n.length > 0 && a.push({
1341
- ruleId: "text-alternatives/image-alt-words",
1342
- selector: p(t),
1343
- html: m(t),
1344
- impact: "minor",
1345
- message: `Alt text "${t.getAttribute("alt")}" contains redundant word(s): ${n.join(", ")}.`,
1346
- context: `Current alt: "${t.getAttribute("alt")}", redundant word(s): ${n.join(", ")}`,
1347
- fix: { type: "suggest", suggestion: "Remove the redundant word(s) from the alt text; screen readers already announce the element as an image" }
1348
- });
1339
+ const n = i.match(Bt);
1340
+ if (n) {
1341
+ const o = n[1].toLowerCase();
1342
+ a.push({
1343
+ ruleId: "text-alternatives/image-alt-words",
1344
+ selector: p(t),
1345
+ html: m(t),
1346
+ impact: "minor",
1347
+ message: `Alt text "${i}" starts with redundant prefix "${o}".`,
1348
+ context: `Current alt: "${i}", redundant prefix: "${o}"`,
1349
+ fix: { type: "suggest", suggestion: "Remove the redundant prefix from the alt text; screen readers already announce the element as an image" }
1350
+ });
1351
+ }
1349
1352
  }
1350
1353
  return a;
1351
1354
  }
@@ -1885,7 +1888,7 @@ const sa = {
1885
1888
  fixability: "contextual",
1886
1889
  guidance: "Definition lists have strict content requirements. Only <dt> (terms), <dd> (definitions), and <div> (for grouping dt/dd pairs) are valid children. Other elements break the list structure for screen readers. Move invalid elements outside the <dl>, or if they represent a term change to <dt>, if a definition change to <dd>. Styling wrappers should be replaced with <div> elements containing <dt>/<dd> pairs."
1887
1890
  }, ma = N(ua);
1888
- function je(e, a) {
1891
+ function We(e, a) {
1889
1892
  switch (a.toLowerCase()) {
1890
1893
  case "deg":
1891
1894
  return e;
@@ -1907,7 +1910,7 @@ function pa(e) {
1907
1910
  /rotate[Z]?\(\s*(-?[\d.]+)(deg|rad|turn|grad)\s*\)/i
1908
1911
  );
1909
1912
  if (a) {
1910
- const n = je(parseFloat(a[1]), a[2]);
1913
+ const n = We(parseFloat(a[1]), a[2]);
1911
1914
  if (B(n)) return !0;
1912
1915
  }
1913
1916
  const t = e.match(
@@ -1929,7 +1932,7 @@ function pa(e) {
1929
1932
  function ba(e) {
1930
1933
  const a = e.match(/(-?[\d.]+)(deg|rad|turn|grad)/i);
1931
1934
  if (!a) return !1;
1932
- const t = je(parseFloat(a[1]), a[2]);
1935
+ const t = We(parseFloat(a[1]), a[2]);
1933
1936
  return B(t);
1934
1937
  }
1935
1938
  const ha = {
@@ -2007,14 +2010,14 @@ function fa(e, a) {
2007
2010
  for (const s of e.querySelectorAll("*")) {
2008
2011
  if (h(s)) continue;
2009
2012
  o = !0;
2010
- const l = W(s);
2013
+ const l = j(s);
2011
2014
  l && n.add(l);
2012
2015
  }
2013
2016
  for (const s of t) {
2014
2017
  const l = i.getElementById(s);
2015
2018
  if (l && !h(l)) {
2016
2019
  o = !0;
2017
- const d = W(l);
2020
+ const d = j(l);
2018
2021
  d && n.add(d);
2019
2022
  }
2020
2023
  }
@@ -2091,7 +2094,7 @@ const va = {
2091
2094
  const o = Se[n];
2092
2095
  let r = i.parentElement, s = !1;
2093
2096
  for (; r && r !== e.documentElement; ) {
2094
- const l = W(r);
2097
+ const l = j(r);
2095
2098
  if (l && o.includes(l)) {
2096
2099
  s = !0;
2097
2100
  break;
@@ -2340,7 +2343,7 @@ const ka = {
2340
2343
  function ce(e) {
2341
2344
  return e.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
2342
2345
  }
2343
- function We(e, a) {
2346
+ function je(e, a) {
2344
2347
  const t = e.getAttribute("style");
2345
2348
  if (!t) return null;
2346
2349
  const i = new RegExp(
@@ -2446,7 +2449,7 @@ function Be(e, a, t, i) {
2446
2449
  const n = [];
2447
2450
  for (const o of e.querySelectorAll("[style]")) {
2448
2451
  if (h(o) || !Oe(o) || Ve(o) || !de(o, t)) continue;
2449
- const r = We(o, t);
2452
+ const r = je(o, t);
2450
2453
  if (!r) continue;
2451
2454
  let s = !1;
2452
2455
  if (r.em !== null ? s = r.em < i : r.px !== null && (s = Ue(o, t, r.px, i)), s) {
@@ -2503,7 +2506,7 @@ const Ra = {
2503
2506
  const o = parseFloat(w(t).lineHeight);
2504
2507
  if (o > 0 && t.scrollHeight <= o * 1.5) continue;
2505
2508
  }
2506
- const i = We(t, "line-height");
2509
+ const i = je(t, "line-height");
2507
2510
  if (!i) continue;
2508
2511
  let n = !1;
2509
2512
  if (i.em !== null ? n = i.em < 1.5 : i.px !== null && (n = Ue(t, "line-height", i.px, 1.5)), n) {
@@ -2668,10 +2671,10 @@ function za(e) {
2668
2671
  }
2669
2672
  return !1;
2670
2673
  }
2671
- function ja(e) {
2674
+ function Wa(e) {
2672
2675
  return e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement || e instanceof HTMLSelectElement || e instanceof HTMLButtonElement ? e.disabled : !!(e.closest("fieldset[disabled]") || e.getAttribute("aria-disabled") === "true");
2673
2676
  }
2674
- function Wa(e, a) {
2677
+ function ja(e, a) {
2675
2678
  if (e.tagName !== "LABEL") return !1;
2676
2679
  const t = e, i = t.htmlFor;
2677
2680
  if (i) {
@@ -2787,7 +2790,7 @@ function _e(e, a, t) {
2787
2790
  const l = s.parentElement;
2788
2791
  if (!l || r.has(l) || (r.add(l), Da.has(l.tagName))) continue;
2789
2792
  const d = l.tagName;
2790
- if (d === "BODY" || d === "HTML" || Ua(l) || ja(l) || Wa(l, e) || Va(l) || za(l)) continue;
2793
+ if (d === "BODY" || d === "HTML" || Ua(l) || Wa(l) || ja(l, e) || Va(l) || za(l)) continue;
2791
2794
  const c = w(l);
2792
2795
  if (parseFloat(c.opacity) === 0) continue;
2793
2796
  const u = Mt(l);
@@ -3065,7 +3068,7 @@ const di = {
3065
3068
  } else
3066
3069
  continue;
3067
3070
  const u = i.getAttribute("tabindex");
3068
- u !== null && u !== "-1" || i.querySelector(j) || a.push({
3071
+ u !== null && u !== "-1" || i.querySelector(W) || a.push({
3069
3072
  ruleId: "keyboard-accessible/scrollable-region",
3070
3073
  selector: p(i),
3071
3074
  html: m(i),
@@ -3118,7 +3121,7 @@ const di = {
3118
3121
  guidance: "Keyboard users need to see which element has focus. Do not remove the default focus outline (outline: none) without providing an alternative visible indicator. Use :focus-visible or :focus styles to ensure focus is always perceivable.",
3119
3122
  run(e) {
3120
3123
  const a = [];
3121
- for (const t of e.querySelectorAll(j)) {
3124
+ for (const t of e.querySelectorAll(W)) {
3122
3125
  if (h(t) || !(t instanceof HTMLElement)) continue;
3123
3126
  const i = t.getAttribute("style") || "";
3124
3127
  if (/outline\s*:\s*(none|0)\s*(;|$|!)/i.test(i)) {
@@ -3759,15 +3762,15 @@ const Ei = {
3759
3762
  }
3760
3763
  return [];
3761
3764
  }
3762
- }, ji = new Set(
3765
+ }, Wi = new Set(
3763
3766
  "aa ab ae af ak am an ar as av ay az ba be bg bh bi bm bn bo br bs ca ce ch co cr cs cu cv cy da de dv dz ee el en eo es et eu fa ff fi fj fo fr fy ga gd gl gn gu gv ha he hi ho hr ht hu hy hz ia id ie ig ii ik io is it iu ja jv ka kg ki kj kk kl km kn ko kr ks ku kv kw ky la lb lg li ln lo lt lu lv mg mh mi mk ml mn mr ms mt my na nb nd ne ng nl nn no nr nv ny oc oj om or os pa pi pl ps pt qu rm rn ro ru rw sa sc sd se sg si sk sl sm sn so sq sr ss st su sv sw ta te tg th ti tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa wo xh yi yo za zh zu".split(" ")
3764
- ), Wi = new Set(
3767
+ ), ji = new Set(
3765
3768
  "aar abk afr aka amh ara arg asm ava ave aym aze bak bam bel ben bih bis bod bos bre bul cat ces cha che chu chv cor cos cre cym dan deu div dzo ell eng epo est eus ewe fao fas fij fin fra fry ful gla gle glg glv grn guj hat hau hbs heb her hin hmo hrv hun hye ibo iii iku ile ina ind ipk isl ita jav jpn kal kan kas kat kau kaz khm kik kin kir kom kon kor kua kur lao lat lav lim lin lit ltz lub lug mah mal mar mkd mlg mlt mon mri msa mya nau nav nbl nde ndo nep nld nno nob nor nya oci oji ori orm oss pan pli pol por pus que roh ron run rus sag san sin slk slv sme smo sna snd som sot spa sqi srd srp ssw sun swa swe tah tam tat tel tgk tgl tha tir ton tsn tso tuk tur twi uig ukr urd uzb ven vie vol wln wol xho yid yor zha zho zul".split(" ")
3766
3769
  ), Ui = /^[a-z]{2,8}(-[a-z0-9]{1,8})*$/i;
3767
3770
  function Ke(e) {
3768
3771
  if (!Ui.test(e)) return !1;
3769
3772
  const a = e.split("-")[0].toLowerCase();
3770
- return a.length === 2 ? ji.has(a) : a.length === 3 ? !Wi.has(a) : !1;
3773
+ return a.length === 2 ? Wi.has(a) : a.length === 3 ? !ji.has(a) : !1;
3771
3774
  }
3772
3775
  function Ce(e) {
3773
3776
  var i;
@@ -4703,7 +4706,7 @@ Referenced by: ${d}` : ""}`,
4703
4706
  }
4704
4707
  for (const o of t) {
4705
4708
  if (h(o)) continue;
4706
- const r = W(o);
4709
+ const r = j(o);
4707
4710
  if (!r) continue;
4708
4711
  const s = In[r];
4709
4712
  if (s)
@@ -4953,8 +4956,8 @@ const $n = {
4953
4956
  const a = [];
4954
4957
  for (const t of e.querySelectorAll('[aria-hidden="true"]')) {
4955
4958
  if (t === e.body) continue;
4956
- const i = [...t.querySelectorAll(j)];
4957
- t.matches(j) && i.push(t);
4959
+ const i = [...t.querySelectorAll(W)];
4960
+ t.matches(W) && i.push(t);
4958
4961
  for (const n of i)
4959
4962
  if (n instanceof HTMLElement) {
4960
4963
  const o = n.getAttribute("tabindex");
@@ -5077,7 +5080,7 @@ const Fn = {
5077
5080
  "spinbutton",
5078
5081
  "switch",
5079
5082
  "tab"
5080
- ]), jn = {
5083
+ ]), Wn = {
5081
5084
  id: "aria/presentational-children-focusable",
5082
5085
  category: "aria",
5083
5086
  actRuleIds: ["307n5z"],
@@ -5090,9 +5093,9 @@ const Fn = {
5090
5093
  const a = [];
5091
5094
  for (const t of e.querySelectorAll("*")) {
5092
5095
  if (h(t)) continue;
5093
- const i = W(t);
5096
+ const i = j(t);
5094
5097
  if (!(!i || !zn.has(i))) {
5095
- for (const n of t.querySelectorAll(j))
5098
+ for (const n of t.querySelectorAll(W))
5096
5099
  if (n !== t && !n.disabled && n.getAttribute("tabindex") !== "-1") {
5097
5100
  a.push({
5098
5101
  ruleId: "aria/presentational-children-focusable",
@@ -5109,7 +5112,7 @@ const Fn = {
5109
5112
  }
5110
5113
  }, Ze = [
5111
5114
  // Text Alternatives
5112
- jt,
5115
+ Wt,
5113
5116
  Ut,
5114
5117
  Ot,
5115
5118
  Vt,
@@ -5212,7 +5215,7 @@ const Fn = {
5212
5215
  $n,
5213
5216
  Hn,
5214
5217
  Fn,
5215
- jn
5218
+ Wn
5216
5219
  ];
5217
5220
  let me = [], et = /* @__PURE__ */ new Set(), tt = !1, at = !1, T, z;
5218
5221
  function Bn(e) {
@@ -5288,11 +5291,11 @@ function Yn(e, a) {
5288
5291
  n.has(l) || s.push(d);
5289
5292
  return { added: o, fixed: s, unchanged: r };
5290
5293
  }
5291
- const Wn = new Map(Ze.map((e) => [e.id, e]));
5294
+ const jn = new Map(Ze.map((e) => [e.id, e]));
5292
5295
  function Xn(e) {
5293
5296
  if (T)
5294
5297
  return pe().find((i) => i.id === e);
5295
- const a = Wn.get(e);
5298
+ const a = jn.get(e);
5296
5299
  return a || me.find((t) => t.id === e);
5297
5300
  }
5298
5301
  const Jn = {
@@ -5309,7 +5312,7 @@ const Jn = {
5309
5312
  "text-alternatives/svg-img-alt": { description: "SVG elements with an img, graphics-document, or graphics-symbol role must have an accessible name via a <title> element, aria-label, or aria-labelledby.", guidance: "Inline SVGs with role='img' need accessible names. Add a <title> element as the first child of the SVG (screen readers will announce it), or use aria-label on the SVG element. For complex SVGs, use aria-labelledby referencing both a <title> and <desc> element. Decorative SVGs should use aria-hidden='true' instead.", messages: { "{0} with role='{1}' has no accessible name.": "{0} with role='{1}' has no accessible name." } },
5310
5313
  "text-alternatives/input-image-alt": { description: 'Image inputs (<input type="image">) must have alternate text describing the button action.', guidance: "Image buttons (<input type='image'>) act as submit buttons with a custom image. Add alt text via alt, aria-label, or aria-labelledby that describes the action (e.g. alt='Search' or alt='Submit order'), not the image itself. Without it, screen readers announce only 'image' or the filename, giving no clue what the button does.", messages: { "Image input missing alt text.": "Image input missing alt text." } },
5311
5314
  "text-alternatives/image-redundant-alt": { description: "Image alt text should not duplicate adjacent link or button text. When alt text repeats surrounding text, screen reader users hear the same information twice.", guidance: "When an image is inside a link or button that also has text, make the alt text complementary rather than identical. If the image is purely decorative in that context, use alt='' to avoid repetition.", messages: { 'Alt text "{0}" duplicates surrounding {1} text.': 'Alt text "{0}" duplicates surrounding {1} text.' } },
5312
- "text-alternatives/image-alt-words": { description: "Image alt text should not contain words like 'image', 'photo', or 'picture' — screen readers already announce the element type.", guidance: "Screen readers already announce 'image' or 'graphic' before reading alt text, so phrases like 'image of', 'photo of', or 'picture of' are redundant. Remove these words and describe what the image shows. For example, change 'image of a dog' to 'golden retriever playing fetch'.", messages: { 'Alt text "{0}" contains redundant word(s): {1}.': 'Alt text "{0}" contains redundant word(s): {1}.' } },
5315
+ "text-alternatives/image-alt-words": { description: "Image alt text should not start with words like 'image of', 'photo of', or 'picture of' — screen readers already announce the element type.", guidance: "Screen readers already announce 'image' or 'graphic' before reading alt text, so phrases like 'image of', 'photo of', or 'picture of' are redundant. Remove these words and describe what the image shows. For example, change 'image of a dog' to 'golden retriever playing fetch'.", messages: { 'Alt text "{0}" contains redundant word(s): {1}.': 'Alt text "{0}" contains redundant word(s): {1}.' } },
5313
5316
  "text-alternatives/area-alt": { description: "Image map <area> elements must have alternative text.", guidance: "Each clickable region in an image map needs alternative text so screen reader users know what the region represents. Add an alt attribute to every <area> element describing its purpose. For complex image maps, consider using alternative approaches like SVG with embedded links, or a list of text links.", messages: { "Image map <area> element is missing alternative text.": "Image map <area> element is missing alternative text." } },
5314
5317
  "text-alternatives/object-alt": { description: "<object> elements must have alternative text.", guidance: "Object elements embed external content that may not be accessible to all users. Provide alternative text via aria-label, aria-labelledby, or a title attribute. The fallback content inside <object> is only shown when the object fails to load and does not serve as an accessible name.", messages: { "<object> element is missing alternative text. Add aria-label, aria-labelledby, or a title attribute.": "<object> element is missing alternative text. Add aria-label, aria-labelledby, or a title attribute." } },
5315
5318
  "text-alternatives/role-img-alt": { description: "Elements with role='img' must have an accessible name.", guidance: "When you assign role='img' to an element (like a div containing icon fonts or CSS backgrounds), you must provide an accessible name via aria-label or aria-labelledby. Without this, screen reader users have no way to understand what the image represents. If the image is decorative, use role='presentation' or role='none' instead.", messages: { "Element with role='img' has no accessible name. Add aria-label or aria-labelledby.": "Element with role='img' has no accessible name. Add aria-label or aria-labelledby." } },
@@ -5403,7 +5406,7 @@ const Jn = {
5403
5406
  "text-alternatives/svg-img-alt": { description: "Los elementos SVG con rol img, graphics-document o graphics-symbol deben tener un nombre accesible mediante un elemento <title>, aria-label o aria-labelledby.", guidance: "Los SVG en línea con role='img' necesitan nombres accesibles. Agregue un elemento <title> como primer hijo del SVG (los lectores de pantalla lo anunciarán), o use aria-label en el elemento SVG. Para SVGs complejos, use aria-labelledby haciendo referencia tanto a un elemento <title> como a un elemento <desc>. Los SVGs decorativos deben usar aria-hidden='true' en su lugar.", messages: { "{0} with role='{1}' has no accessible name.": "{0} con role='{1}' no tiene nombre accesible." } },
5404
5407
  "text-alternatives/input-image-alt": { description: 'Las entradas de imagen (<input type="image">) deben tener texto alternativo mediante alt, aria-label o aria-labelledby. El texto debe describir la acción del botón, no la imagen.', guidance: "Los botones de imagen (<input type='image'>) deben tener texto alternativo mediante alt, aria-label o aria-labelledby. El texto debe describir la acción del botón, no la imagen.", messages: { "Image input missing alt text.": "A la entrada de imagen le falta texto alt." } },
5405
5408
  "text-alternatives/image-redundant-alt": { description: "El texto alternativo de la imagen no debe duplicar el texto del enlace o botón adyacente. Cuando el texto alt repite el texto circundante, los usuarios de lectores de pantalla escuchan la misma información dos veces.", guidance: "Cuando una imagen está dentro de un enlace o botón que también tiene texto, haga que el texto alt sea complementario en lugar de idéntico. Si la imagen es puramente decorativa en ese contexto, use alt='' para evitar la repetición.", messages: { 'Alt text "{0}" duplicates surrounding {1} text.': 'El texto alt "{0}" duplica el texto del {1} circundante.' } },
5406
- "text-alternatives/image-alt-words": { description: "El texto alternativo de la imagen no debe contener palabras como 'imagen', 'foto' o 'fotografía': los lectores de pantalla ya anuncian el tipo de elemento.", guidance: "Los lectores de pantalla ya anuncian 'imagen' o 'gráfico' antes de leer el texto alt, por lo que frases como 'imagen de', 'foto de' o 'fotografía de' son redundantes. Elimine estas palabras y describa lo que muestra la imagen. Por ejemplo, cambie 'imagen de un perro' a 'golden retriever jugando a buscar'.", messages: { 'Alt text "{0}" contains redundant word(s): {1}.': 'El texto alt "{0}" contiene palabra(s) redundante(s): {1}.' } },
5409
+ "text-alternatives/image-alt-words": { description: "El texto alternativo de la imagen no debe comenzar con palabras como 'imagen de', 'foto de' o 'fotografía de': los lectores de pantalla ya anuncian el tipo de elemento.", guidance: "Los lectores de pantalla ya anuncian 'imagen' o 'gráfico' antes de leer el texto alt, por lo que frases como 'imagen de', 'foto de' o 'fotografía de' son redundantes. Elimine estas palabras y describa lo que muestra la imagen. Por ejemplo, cambie 'imagen de un perro' a 'golden retriever jugando a buscar'.", messages: { 'Alt text "{0}" contains redundant word(s): {1}.': 'El texto alt "{0}" contiene palabra(s) redundante(s): {1}.' } },
5407
5410
  "text-alternatives/area-alt": { description: "Los elementos <area> del mapa de imagen deben tener texto alternativo.", guidance: "Cada región clicable en un mapa de imagen necesita texto alternativo para que los usuarios de lectores de pantalla sepan qué representa la región. Agregue un atributo alt a cada elemento <area> describiendo su propósito. Para mapas de imagen complejos, considere usar enfoques alternativos como SVG con enlaces incrustados, o una lista de enlaces de texto.", messages: { "Image map <area> element is missing alternative text.": "Al elemento <area> del mapa de imagen le falta texto alternativo." } },
5408
5411
  "text-alternatives/object-alt": { description: "Los elementos <object> deben tener texto alternativo.", guidance: "Los elementos object incrustan contenido externo que puede no ser accesible para todos los usuarios. Proporcione texto alternativo mediante aria-label, aria-labelledby o un atributo title. El contenido de respaldo dentro de <object> solo se muestra cuando el objeto no se carga y no sirve como nombre accesible.", messages: { "<object> element is missing alternative text. Add aria-label, aria-labelledby, or a title attribute.": "Al elemento <object> le falta texto alternativo. Agregue aria-label, aria-labelledby o un atributo title." } },
5409
5412
  "text-alternatives/role-img-alt": { description: "Los elementos con role='img' deben tener un nombre accesible.", guidance: "Cuando asigna role='img' a un elemento (como un div que contiene fuentes de iconos o fondos CSS), debe proporcionar un nombre accesible mediante aria-label o aria-labelledby. Sin esto, los usuarios de lectores de pantalla no tienen forma de entender lo que representa la imagen. Si la imagen es decorativa, use role='presentation' o role='none' en su lugar.", messages: { "Element with role='img' has no accessible name. Add aria-label or aria-labelledby.": "El elemento con role='img' no tiene nombre accesible. Agregue aria-label o aria-labelledby." } },
@@ -5497,7 +5500,7 @@ export {
5497
5500
  x as getAccessibleName,
5498
5501
  k as getAccessibleTextContent,
5499
5502
  pe as getActiveRules,
5500
- W as getComputedRole,
5503
+ j as getComputedRole,
5501
5504
  m as getHtmlSnippet,
5502
5505
  $e as getImplicitRole,
5503
5506
  Xn as getRuleById,
@@ -1,9 +1,9 @@
1
1
  import type { Rule } from "../types";
2
2
  /**
3
- * Checks if alt text contains self-referential words like "image" or "photo".
4
- * Screen readers already announce "image"/"graphic" before alt text, so these
5
- * words are redundant. Separate from image-redundant-alt because axe-core
6
- * does not have an equivalent check.
3
+ * Checks if alt text starts with a self-referential prefix like "image of"
4
+ * or "photo:". Screen readers already announce "image"/"graphic" before alt
5
+ * text, so these prefixes are redundant. Separate from image-redundant-alt
6
+ * because axe-core does not have an equivalent check.
7
7
  */
8
8
  export declare const imageAltWords: Rule;
9
9
  //# sourceMappingURL=image-alt-words.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-alt-words.d.ts","sourceRoot":"","sources":["../../../src/rules/text-alternatives/image-alt-words.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAKrC;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,IAiC3B,CAAC"}
1
+ {"version":3,"file":"image-alt-words.d.ts","sourceRoot":"","sources":["../../../src/rules/text-alternatives/image-alt-words.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAerC;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,IAkC3B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@accesslint/core",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Pure accessibility rule engine — WCAG audit with zero browser dependencies",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",