Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions plugin/scripts/lib/md-checks.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
// ref-undefined full/collapsed reference [text][label] with no
// definition (renders as literal brackets on GitHub)
// def-orphan a [label]: definition no reference ever uses
// image-alt-missing image with empty or absent alt text — screen readers
// announce "image" with no description, search engines
// cannot index content (MD045 class, WCAG 1.1.1)
// bare-url a raw http(s)/www URL in prose text (GFM auto-links
// it, CommonMark does not; MD034 class — style signal)
// doc-too-large pre-parse short-circuit: input over MAX_DOC_BYTES is
Expand Down Expand Up @@ -246,6 +249,19 @@ export function checkDocument(src, opts = {}) {
if (node.type === 'link' || node.type === 'image' || node.type === 'definition') checkTarget(node, node.url);
});

// ---- images: alt text -------------------------------------------------------
// MD045 / WCAG 1.1.1: every image needs a non-empty alt. Without it a screen
// reader says "image" with no description, and search engines cannot index the
// content. Both inline images (![alt](url)) and reference images (![alt][ref])
// are checked — the AST carries the alt field on both node types.
walk(root, (node) => {
if (node.type !== 'image' && node.type !== 'imageReference') return;
const alt = (node.alt || '').trim();
if (!alt) {
add('image-alt-missing', node, `image has no alt text — screen readers and search engines cannot describe it (MD045)`);
}
});

// ---- tables ----------------------------------------------------------------
walk(root, (node) => {
if (node.type !== 'table' || !node.children.length) return;
Expand Down
1 change: 1 addition & 0 deletions plugin/skills/doc-structure/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Scan markdown docs for structural breakage. Report CONFIRMED findings. Fix on re
| table-ragged | row with MORE cells than the header (GitHub silently drops them) |
| ref-undefined | \[text]\[label] with no definition (renders as literal brackets) |
| def-orphan | definition never referenced |
| image-alt-missing | image with empty or absent alt text — inaccessible to screen readers, invisible to search engines (MD045 / WCAG 1.1.1) |
| bare-url | raw URL in prose (MD034 class) |
| doc-unreadable | binary/corrupted input (NUL byte sniffed) — refused before parsing, never a false "0 findings" clean bill |

Expand Down
16 changes: 16 additions & 0 deletions plugin/skills/doc-structure/lib/md-checks.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
// ref-undefined full/collapsed reference [text][label] with no
// definition (renders as literal brackets on GitHub)
// def-orphan a [label]: definition no reference ever uses
// image-alt-missing image with empty or absent alt text — screen readers
// announce "image" with no description, search engines
// cannot index content (MD045 class, WCAG 1.1.1)
// bare-url a raw http(s)/www URL in prose text (GFM auto-links
// it, CommonMark does not; MD034 class — style signal)
// doc-too-large pre-parse short-circuit: input over MAX_DOC_BYTES is
Expand Down Expand Up @@ -246,6 +249,19 @@ export function checkDocument(src, opts = {}) {
if (node.type === 'link' || node.type === 'image' || node.type === 'definition') checkTarget(node, node.url);
});

// ---- images: alt text -------------------------------------------------------
// MD045 / WCAG 1.1.1: every image needs a non-empty alt. Without it a screen
// reader says "image" with no description, and search engines cannot index the
// content. Both inline images (![alt](url)) and reference images (![alt][ref])
// are checked — the AST carries the alt field on both node types.
walk(root, (node) => {
if (node.type !== 'image' && node.type !== 'imageReference') return;
const alt = (node.alt || '').trim();
if (!alt) {
add('image-alt-missing', node, `image has no alt text — screen readers and search engines cannot describe it (MD045)`);
}
});

// ---- tables ----------------------------------------------------------------
walk(root, (node) => {
if (node.type !== 'table' || !node.children.length) return;
Expand Down
2 changes: 2 additions & 0 deletions scripts/fixtures/defects-structure.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Defects fixture

### Skipped level (h1 to h3)

Check failure on line 3 in scripts/fixtures/defects-structure.md

View workflow job for this annotation

GitHub Actions / lint

Heading levels should only increment by one level at a time

scripts/fixtures/defects-structure.md:3 MD001/heading-increment Heading levels should only increment by one level at a time [Expected: h2; Actual: h3] https://github.com/DavidAnson/markdownlint/blob/v0.41.1/doc/md001.md

# Second top-level title

Check failure on line 5 in scripts/fixtures/defects-structure.md

View workflow job for this annotation

GitHub Actions / lint

Multiple top-level headings in the same document

scripts/fixtures/defects-structure.md:5 MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "Second top-level title"] https://github.com/DavidAnson/markdownlint/blob/v0.41.1/doc/md025.md

Link to [a missing anchor](#no-such-heading) here.

Check failure on line 7 in scripts/fixtures/defects-structure.md

View workflow job for this annotation

GitHub Actions / lint

Link fragments should be valid

scripts/fixtures/defects-structure.md:7:9 MD051/link-fragments Link fragments should be valid [Context: "[a missing anchor](#no-such-heading)"] https://github.com/DavidAnson/markdownlint/blob/v0.41.1/doc/md051.md

Link to [a case mismatch](#Skipped-level-h1-to-h3) here.

Check failure on line 9 in scripts/fixtures/defects-structure.md

View workflow job for this annotation

GitHub Actions / lint

Link fragments should be valid

scripts/fixtures/defects-structure.md:9:9 MD051/link-fragments Link fragments should be valid [Expected: #skipped-level-h1-to-h3; Actual: #Skipped-level-h1-to-h3] [Context: "[a case mismatch](#Skipped-level-h1-to-h3)"] https://github.com/DavidAnson/markdownlint/blob/v0.41.1/doc/md051.md

Link to [a dead file](./no-such-file.md) here.

Expand All @@ -18,11 +18,11 @@

| a | b |
| --- | --- |
| 1 | 2 | 3 |

Check failure on line 21 in scripts/fixtures/defects-structure.md

View workflow job for this annotation

GitHub Actions / lint

Table column count

scripts/fixtures/defects-structure.md:21:9 MD056/table-column-count Table column count [Expected: 2; Actual: 3; Too many cells, extra data will be missing] https://github.com/DavidAnson/markdownlint/blob/v0.41.1/doc/md056.md

See [broken ref][no-def] for details.

Check failure on line 23 in scripts/fixtures/defects-structure.md

View workflow job for this annotation

GitHub Actions / lint

Reference links and images should use a label that is defined

scripts/fixtures/defects-structure.md:23:5 MD052/reference-links-images Reference links and images should use a label that is defined [Missing link or image reference definition: "no-def"] [Context: "[broken ref][no-def]"] https://github.com/DavidAnson/markdownlint/blob/v0.41.1/doc/md052.md

Bare URL: https://example.com/dangling in prose.

Check failure on line 25 in scripts/fixtures/defects-structure.md

View workflow job for this annotation

GitHub Actions / lint

Bare URL used

scripts/fixtures/defects-structure.md:25:11 MD034/no-bare-urls Bare URL used [Context: "https://example.com/dangling"] https://github.com/DavidAnson/markdownlint/blob/v0.41.1/doc/md034.md

[orphan-def]: https://example.com/orphan

Expand All @@ -31,3 +31,5 @@
Some instructions.

## Setup

![](./img/no-alt.png)
16 changes: 16 additions & 0 deletions scripts/lib/md-checks.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
// ref-undefined full/collapsed reference [text][label] with no
// definition (renders as literal brackets on GitHub)
// def-orphan a [label]: definition no reference ever uses
// image-alt-missing image with empty or absent alt text — screen readers
// announce "image" with no description, search engines
// cannot index content (MD045 class, WCAG 1.1.1)
// bare-url a raw http(s)/www URL in prose text (GFM auto-links
// it, CommonMark does not; MD034 class — style signal)
// doc-too-large pre-parse short-circuit: input over MAX_DOC_BYTES is
Expand Down Expand Up @@ -246,6 +249,19 @@ export function checkDocument(src, opts = {}) {
if (node.type === 'link' || node.type === 'image' || node.type === 'definition') checkTarget(node, node.url);
});

// ---- images: alt text -------------------------------------------------------
// MD045 / WCAG 1.1.1: every image needs a non-empty alt. Without it a screen
// reader says "image" with no description, and search engines cannot index the
// content. Both inline images (![alt](url)) and reference images (![alt][ref])
// are checked — the AST carries the alt field on both node types.
walk(root, (node) => {
if (node.type !== 'image' && node.type !== 'imageReference') return;
const alt = (node.alt || '').trim();
if (!alt) {
add('image-alt-missing', node, `image has no alt text — screen readers and search engines cannot describe it (MD045)`);
}
});

// ---- tables ----------------------------------------------------------------
walk(root, (node) => {
if (node.type !== 'table' || !node.children.length) return;
Expand Down
2 changes: 2 additions & 0 deletions scripts/lib/md-checks.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ test('defects-structure.md: every planted defect found — exact check ids and l
'def-orphan@27',
'file-missing@11', // ./no-such-file.md
'file-missing@13', // dead image
'file-missing@35', // no-alt image target also missing
'heading-duplicate@33', // second "## Setup" — anchor silently points to first
'image-alt-missing@35', // ![](./img/no-alt.png) — no alt text
'heading-multiple-h1@5',
'heading-skip@3',
'ref-undefined@23',
Expand Down
1 change: 1 addition & 0 deletions skills/doc-structure/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Scan markdown docs for structural breakage. Report CONFIRMED findings. Fix on re
| table-ragged | row with MORE cells than the header (GitHub silently drops them) |
| ref-undefined | \[text]\[label] with no definition (renders as literal brackets) |
| def-orphan | definition never referenced |
| image-alt-missing | image with empty or absent alt text — inaccessible to screen readers, invisible to search engines (MD045 / WCAG 1.1.1) |
| bare-url | raw URL in prose (MD034 class) |
| doc-unreadable | binary/corrupted input (NUL byte sniffed) — refused before parsing, never a false "0 findings" clean bill |

Expand Down
Loading