From 3c054db01fec5f227982bb05150080daf7707429 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 2 Oct 2026 07:37:54 +0200 Subject: [PATCH 1/2] Name links from hidden aria-labelledby targets Per AccName 2.A, nodes directly referenced by aria-labelledby contribute to the name even when hidden. Adds fixtures for hidden and aria-hidden labels. --- guided-navigation/fixtures/ROLES_COVERAGE.md | 3 +- .../gnd.json | 31 +++++++++++++++++++ .../input.html | 3 ++ .../meta.json | 10 ++++++ .../gnd.json | 31 +++++++++++++++++++ .../input.html | 3 ++ .../meta.json | 10 ++++++ guided-navigation/fixtures/manifest.json | 20 ++++++++++++ guided-navigation/src/a11y.ts | 2 +- 9 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/gnd.json create mode 100644 guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/input.html create mode 100644 guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/meta.json create mode 100644 guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/gnd.json create mode 100644 guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/input.html create mode 100644 guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/meta.json diff --git a/guided-navigation/fixtures/ROLES_COVERAGE.md b/guided-navigation/fixtures/ROLES_COVERAGE.md index d3a3a547..d209b143 100644 --- a/guided-navigation/fixtures/ROLES_COVERAGE.md +++ b/guided-navigation/fixtures/ROLES_COVERAGE.md @@ -8,6 +8,7 @@ renaming, or removing a fixture. | Role | Fixtures | | --- | --- | | `abstract` | `abstract-epub-type`, `abstract-role-aria` | +| `accessible-name` | `accessible-name-labelledby-aria-hidden`, `accessible-name-labelledby-hidden-attribute` | | `acknowledgments` | `acknowledgments-epub-type`, `acknowledgments-role-aria` | | `afterword` | `afterword-epub-type`, `afterword-role-aria` | | `appendix` | `appendix-epub-type`, `appendix-role-aria` | @@ -77,4 +78,4 @@ renaming, or removing a fixture. | `toc` | `toc-epub-type`, `toc-role-aria` | | `video` | `video-html-native`, `video-no-description` | -178 fixtures across 69 roles. +180 fixtures across 70 roles. diff --git a/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/gnd.json b/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/gnd.json new file mode 100644 index 00000000..b608c4c3 --- /dev/null +++ b/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/gnd.json @@ -0,0 +1,31 @@ +{ + "children": [ + { + "role": [ + "paragraph" + ], + "text": { + "language": "en", + "plain": "Into speech.", + "ssml": "Into speech. " + }, + "children": [ + { + "id": "link1", + "textref": "#gloss", + "text": { + "plain": "see glossary entry" + } + } + ] + }, + { + "role": [ + "paragraph" + ], + "text": { + "plain": "synthesized speech can be created." + } + } + ] +} diff --git a/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/input.html b/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/input.html new file mode 100644 index 00000000..17e48109 --- /dev/null +++ b/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/input.html @@ -0,0 +1,3 @@ +

Into speech. *

+

synthesized speech can be created.

+ diff --git a/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/meta.json b/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/meta.json new file mode 100644 index 00000000..5f1f21a9 --- /dev/null +++ b/guided-navigation/fixtures/accessible-name-labelledby-aria-hidden/meta.json @@ -0,0 +1,10 @@ +{ + "id": "accessible-name-labelledby-aria-hidden", + "description": "A link named via aria-labelledby pointing at an element marked aria-hidden=\"true\": the hidden label still names the link, and is not emitted on its own", + "role": "accessible-name", + "rolesCovered": [ + "paragraph" + ], + "sourceRef": "https://www.w3.org/TR/accname/#computation-steps", + "inputKind": "fragment" +} diff --git a/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/gnd.json b/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/gnd.json new file mode 100644 index 00000000..b608c4c3 --- /dev/null +++ b/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/gnd.json @@ -0,0 +1,31 @@ +{ + "children": [ + { + "role": [ + "paragraph" + ], + "text": { + "language": "en", + "plain": "Into speech.", + "ssml": "Into speech. " + }, + "children": [ + { + "id": "link1", + "textref": "#gloss", + "text": { + "plain": "see glossary entry" + } + } + ] + }, + { + "role": [ + "paragraph" + ], + "text": { + "plain": "synthesized speech can be created." + } + } + ] +} diff --git a/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/input.html b/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/input.html new file mode 100644 index 00000000..dce1b4ef --- /dev/null +++ b/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/input.html @@ -0,0 +1,3 @@ +

Into speech. *

+

synthesized speech can be created.

+ diff --git a/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/meta.json b/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/meta.json new file mode 100644 index 00000000..83de2c82 --- /dev/null +++ b/guided-navigation/fixtures/accessible-name-labelledby-hidden-attribute/meta.json @@ -0,0 +1,10 @@ +{ + "id": "accessible-name-labelledby-hidden-attribute", + "description": "A link named via aria-labelledby pointing at an element hidden with the native hidden attribute: the hidden label still names the link, and is not emitted on its own", + "role": "accessible-name", + "rolesCovered": [ + "paragraph" + ], + "sourceRef": "https://www.w3.org/TR/accname/#computation-steps", + "inputKind": "fragment" +} diff --git a/guided-navigation/fixtures/manifest.json b/guided-navigation/fixtures/manifest.json index c7bbe9c9..4994e71a 100644 --- a/guided-navigation/fixtures/manifest.json +++ b/guided-navigation/fixtures/manifest.json @@ -19,6 +19,26 @@ "gnd": "gnd.json" } }, + { + "id": "accessible-name-labelledby-aria-hidden", + "dir": "accessible-name-labelledby-aria-hidden", + "role": "accessible-name", + "description": "A link named via aria-labelledby pointing at an element marked aria-hidden=\"true\": the hidden label still names the link, and is not emitted on its own", + "files": { + "input": "input.html", + "gnd": "gnd.json" + } + }, + { + "id": "accessible-name-labelledby-hidden-attribute", + "dir": "accessible-name-labelledby-hidden-attribute", + "role": "accessible-name", + "description": "A link named via aria-labelledby pointing at an element hidden with the native hidden attribute: the hidden label still names the link, and is not emitted on its own", + "files": { + "input": "input.html", + "gnd": "gnd.json" + } + }, { "id": "acknowledgments-epub-type", "dir": "acknowledgments-epub-type", diff --git a/guided-navigation/src/a11y.ts b/guided-navigation/src/a11y.ts index 376476d8..25222646 100644 --- a/guided-navigation/src/a11y.ts +++ b/guided-navigation/src/a11y.ts @@ -69,8 +69,8 @@ export function extractNodeAria(el: Element): [string | null, boolean] { if (labelNodes.length > 0) { let text = ""; + // Directly-referenced label nodes count even when hidden (AccName 2.A). labelNodes.forEach((n, i) => { - if (nodeIsHidden(n)) return; const label = n.getAttribute("aria-label"); text += label ? label : nodeTextExcludingExplicitRoles(n); if (i < labelNodes.length - 1) text += " "; From c7c00547ca230e38d9362043d91b07160092bc79 Mon Sep 17 00:00:00 2001 From: Jiminy Panoz Date: Fri, 2 Oct 2026 07:39:19 +0200 Subject: [PATCH 2/2] Bump version --- guided-navigation/CHANGELOG.MD | 10 ++++++++++ guided-navigation/package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/guided-navigation/CHANGELOG.MD b/guided-navigation/CHANGELOG.MD index 68424624..afec84db 100644 --- a/guided-navigation/CHANGELOG.MD +++ b/guided-navigation/CHANGELOG.MD @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.1] – 2026-10-02 + +### Added + +- Fixtures for `aria-labelledby` pointing to `hidden` and `aria-hidden` elements + +### Fixed + +- `aria-labelledby` now uses the elements it references even when they are hidden (`hidden` or `aria-hidden="true"`), as AccName requires, instead of ignoring them + ## [1.0.0] – 2026-10-01 ### Added diff --git a/guided-navigation/package.json b/guided-navigation/package.json index 83ca1ed9..0a2abe01 100644 --- a/guided-navigation/package.json +++ b/guided-navigation/package.json @@ -1,6 +1,6 @@ { "name": "@readium/guided-navigation", - "version": "1.0.0", + "version": "1.0.1", "type": "module", "description": "Guided Navigation document generation from HTML and XHTML content", "author": "readium",