Skip to content

Post-merge-review: Fix template-no-nested-landmark: drop port-only section/region#2694

Merged
NullVoxPopuli merged 5 commits intoember-cli:masterfrom
johanrd:day_fix/template-no-nested-landmark
Apr 15, 2026
Merged

Post-merge-review: Fix template-no-nested-landmark: drop port-only section/region#2694
NullVoxPopuli merged 5 commits intoember-cli:masterfrom
johanrd:day_fix/template-no-nested-landmark

Conversation

@johanrd
Copy link
Copy Markdown
Contributor

@johanrd johanrd commented Apr 13, 2026

Summary

  • Removes <section> from LANDMARK_ELEMENTS and 'region' from LANDMARK_ROLES to match upstream
  • Port was over-flagging legitimate nested <section> elements

Test plan

  • <section><section>...</section></section> → valid
  • <div role="region"><div role="region">...</div></div> → valid
  • <main><nav>...</nav></main> → still flagged

Upstream excludes <section> from LANDMARK_ELEMENTS and 'region' from
LANDMARK_ROLES. Restore parity — port was over-flagging legitimate
nested sections.
@johanrd johanrd marked this pull request as ready for review April 13, 2026 16:23
@johanrd johanrd force-pushed the day_fix/template-no-nested-landmark branch from e18dc6a to 958884b Compare April 13, 2026 17:38
@johanrd johanrd changed the title Fix template-no-nested-landmark: drop port-only section/region Post-merge-review: Fix template-no-nested-landmark: drop port-only section/region Apr 13, 2026
'<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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upstream doesn't matter. what's MDN say?

Copy link
Copy Markdown
Contributor Author

@johanrd johanrd Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tyty

@johanrd johanrd requested a review from NullVoxPopuli April 15, 2026 13:46
@NullVoxPopuli NullVoxPopuli merged commit 623705b into ember-cli:master Apr 15, 2026
10 of 11 checks passed
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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants