Post-merge-review: Fix template-no-nested-landmark: drop port-only section/region#2694
Merged
NullVoxPopuli merged 5 commits intoember-cli:masterfrom Apr 15, 2026
Conversation
Upstream excludes <section> from LANDMARK_ELEMENTS and 'region' from LANDMARK_ROLES. Restore parity — port was over-flagging legitimate nested sections.
e18dc6a to
958884b
Compare
| '<template><header><div role="navigation"></div></header></template>', | ||
| '<template><div role="banner"><div role="navigation"></div></div></template>', | ||
|
|
||
| // `<section>` is not a landmark element per upstream, so nested sections are allowed. |
Contributor
There was a problem hiding this comment.
upstream doesn't matter. what's MDN say?
Contributor
Author
There was a problem hiding this comment.
thanks, changed the comment now — cites https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/examples/HTML5.html directly: <section> only gets the region landmark role when it has an accessible name, otherwise it's generic.
| // `<section>` is not a landmark element per upstream, so nested sections are allowed. | ||
| // `<section>` only gets the `region` landmark role when it has an accessible name | ||
| // (aria-label/aria-labelledby/title). Without one it has the generic role — see | ||
| // https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/section. |
Contributor
There was a problem hiding this comment.
Contributor
Author
There was a problem hiding this comment.
MDN is inconsistent on this — checked the HTML-AAM spec directly: https://www.w3.org/TR/html-aam-1.0/#el-section — "region role if the section element has an accessible name. Otherwise, the generic role."
NullVoxPopuli
requested changes
Apr 14, 2026
NullVoxPopuli
approved these changes
Apr 15, 2026
This was referenced Apr 20, 2026
johanrd
added a commit
to johanrd/eslint-plugin-ember
that referenced
this pull request
Apr 21, 2026
… region exclusion) Adds `lib/utils/landmark-roles.js` deriving landmark roles from aria-query (non-abstract roles with 'landmark' in their superClass chain, filtering out DPub-ARIA doc-* roles). Exports two sets: - `ALL_LANDMARK_ROLES` — the 8 WAI-ARIA 1.2 §5.3.4 landmark roles (banner, complementary, contentinfo, form, main, navigation, region, search). - `LANDMARK_ROLES` — the 7-role subset excluding `region`, safe for static-linting rules that cannot verify accessible names at lint time. ## Why two sets `<section>` only gets the `region` landmark role when it has an accessible name (aria-label / aria-labelledby / title). Without one, `<section>` has role `generic` per the WAI-ARIA APG landmark examples: https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/examples/HTML5.html A static linter cannot verify that accessible names resolve to non-empty values at runtime, so rules that enumerate landmarks should use the 7-role subset (`LANDMARK_ROLES`) to avoid false-positive-flagging unnamed-section nesting/redundancy. Rules that DO verify accessible names can use `ALL_LANDMARK_ROLES`. This was the reasoning behind ember-cli#2694 (post-merge-review that dropped section/region from `template-no-nested-landmark`). An earlier draft of this PR reversed that fix by treating the exclusion as "drift"; this revision preserves the exclusion and codifies the reasoning in the shared util so future rule authors inherit the safe default. ## Rule migrations - `template-no-duplicate-landmark-elements` — imports `ALL_LANDMARK_ROLES` as `LANDMARK_ROLES`. This rule inspects aria-label / aria-labelledby before classifying a node as a landmark (see `getLabel` + dynamic-label skip in `GlimmerElementNode`), so it can safely include `region`. - `template-no-nested-landmark` — imports `LANDMARK_ROLES` (the safe subset). Preserves the ember-cli#2694 behavior. - `template-no-redundant-role` — imports `LANDMARK_ROLES` (the safe subset). Also removes the `region: ['section']` entry from `ROLE_TO_ELEMENTS` for the same reason — ember-cli#2694's reasoning applies here too: `<section role="region">` should not be flagged as redundant because we can't verify the section has a name. ## Tests - New util tests cover both sets, the DPub exclusion, and non-landmark role rejection. - `template-no-nested-landmark` tests preserve the original valid test for nested `role="region"` without accessible names. - `template-no-redundant-role` tests preserve the original `<div role="region">` as valid (div has no implicit role); the previously-regressed test for `<section role="region">` flagged-in-landmark-only is no longer present because the rule no longer flags that pattern (consistent with ember-cli#2694).
johanrd
added a commit
to johanrd/eslint-plugin-ember
that referenced
this pull request
Apr 26, 2026
… region exclusion) Adds `lib/utils/landmark-roles.js` deriving landmark roles from aria-query (non-abstract roles with 'landmark' in their superClass chain, filtering out DPub-ARIA doc-* roles). Exports two sets: - `ALL_LANDMARK_ROLES` — the 8 WAI-ARIA 1.2 §5.3.4 landmark roles (banner, complementary, contentinfo, form, main, navigation, region, search). - `LANDMARK_ROLES` — the 7-role subset excluding `region`, safe for static-linting rules that cannot verify accessible names at lint time. `<section>` only gets the `region` landmark role when it has an accessible name (aria-label / aria-labelledby / title). Without one, `<section>` has role `generic` per the WAI-ARIA APG landmark examples: https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/examples/HTML5.html A static linter cannot verify that accessible names resolve to non-empty values at runtime, so rules that enumerate landmarks should use the 7-role subset (`LANDMARK_ROLES`) to avoid false-positive-flagging unnamed-section nesting/redundancy. Rules that DO verify accessible names can use `ALL_LANDMARK_ROLES`. This was the reasoning behind ember-cli#2694 (post-merge-review that dropped section/region from `template-no-nested-landmark`). An earlier draft of this PR reversed that fix by treating the exclusion as "drift"; this revision preserves the exclusion and codifies the reasoning in the shared util so future rule authors inherit the safe default. - `template-no-duplicate-landmark-elements` — imports `ALL_LANDMARK_ROLES` as `LANDMARK_ROLES`. This rule inspects aria-label / aria-labelledby before classifying a node as a landmark (see `getLabel` + dynamic-label skip in `GlimmerElementNode`), so it can safely include `region`. - `template-no-nested-landmark` — imports `LANDMARK_ROLES` (the safe subset). Preserves the ember-cli#2694 behavior. - `template-no-redundant-role` — imports `LANDMARK_ROLES` (the safe subset). Also removes the `region: ['section']` entry from `ROLE_TO_ELEMENTS` for the same reason — ember-cli#2694's reasoning applies here too: `<section role="region">` should not be flagged as redundant because we can't verify the section has a name. - New util tests cover both sets, the DPub exclusion, and non-landmark role rejection. - `template-no-nested-landmark` tests preserve the original valid test for nested `role="region"` without accessible names. - `template-no-redundant-role` tests preserve the original `<div role="region">` as valid (div has no implicit role); the previously-regressed test for `<section role="region">` flagged-in-landmark-only is no longer present because the rule no longer flags that pattern (consistent with ember-cli#2694).
johanrd
added a commit
to johanrd/eslint-plugin-ember
that referenced
this pull request
Apr 27, 2026
… region exclusion) Adds `lib/utils/landmark-roles.js` deriving landmark roles from aria-query (non-abstract roles with 'landmark' in their superClass chain, filtering out DPub-ARIA doc-* roles). Exports two sets: - `ALL_LANDMARK_ROLES` — the 8 WAI-ARIA 1.2 §5.3.4 landmark roles (banner, complementary, contentinfo, form, main, navigation, region, search). - `LANDMARK_ROLES` — the 7-role subset excluding `region`, safe for static-linting rules that cannot verify accessible names at lint time. `<section>` only gets the `region` landmark role when it has an accessible name (aria-label / aria-labelledby / title). Without one, `<section>` has role `generic` per the WAI-ARIA APG landmark examples: https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/examples/HTML5.html A static linter cannot verify that accessible names resolve to non-empty values at runtime, so rules that enumerate landmarks should use the 7-role subset (`LANDMARK_ROLES`) to avoid false-positive-flagging unnamed-section nesting/redundancy. Rules that DO verify accessible names can use `ALL_LANDMARK_ROLES`. This was the reasoning behind ember-cli#2694 (post-merge-review that dropped section/region from `template-no-nested-landmark`). An earlier draft of this PR reversed that fix by treating the exclusion as "drift"; this revision preserves the exclusion and codifies the reasoning in the shared util so future rule authors inherit the safe default. - `template-no-duplicate-landmark-elements` — imports `ALL_LANDMARK_ROLES` as `LANDMARK_ROLES`. This rule inspects aria-label / aria-labelledby before classifying a node as a landmark (see `getLabel` + dynamic-label skip in `GlimmerElementNode`), so it can safely include `region`. - `template-no-nested-landmark` — imports `LANDMARK_ROLES` (the safe subset). Preserves the ember-cli#2694 behavior. - `template-no-redundant-role` — imports `LANDMARK_ROLES` (the safe subset). Also removes the `region: ['section']` entry from `ROLE_TO_ELEMENTS` for the same reason — ember-cli#2694's reasoning applies here too: `<section role="region">` should not be flagged as redundant because we can't verify the section has a name. - New util tests cover both sets, the DPub exclusion, and non-landmark role rejection. - `template-no-nested-landmark` tests preserve the original valid test for nested `role="region"` without accessible names. - `template-no-redundant-role` tests preserve the original `<div role="region">` as valid (div has no implicit role); the previously-regressed test for `<section role="region">` flagged-in-landmark-only is no longer present because the rule no longer flags that pattern (consistent with ember-cli#2694).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
<section>fromLANDMARK_ELEMENTSand'region'fromLANDMARK_ROLESto match upstream<section>elementsTest plan
<section><section>...</section></section>→ valid<div role="region"><div role="region">...</div></div>→ valid<main><nav>...</nav></main>→ still flagged