which-heading-do-i-need: nested sections are not heading context; heading-less boundaries are transparent#776
Merged
NullVoxPopuli merged 2 commits intoJul 13, 2026
Conversation
…xt; empty boundaries are transparent
Fixes two ways getSectionHeadingLevel disagreed with its own documented
algorithm ("We'll need to check the subtrees between these elements,
stopping if we encounter other boundary elements"):
1. findHeadingIn's fallback child-traversal recursed into every child,
including sectioning content. Headings inside a nested/sibling
<section> belong to that section and are not context for ours, but
the fallback would find them anyway. This made sibling headings
resolve one level deeper than the first through non-boundary
wrappers, and made sibling <section>s cascade one level per section
(h3, h4, h5, ...) instead of staying at equal levels.
The fallback now skips sectioning content (section, article, aside,
nav) like the previous-sibling traversal already did. header,
footer, and main are still traversed: a <header> in particular
typically contains its section's heading (covered by the existing
"wrapped headings" rendering tests).
2. levelOf returned 1 as soon as the walk reached the next boundary,
even if that boundary had no heading of its own. A heading-less
wrapper <section> therefore isolated everything inside it, pinning
headings to <h1> mid-document. Such a boundary has no heading level
to nest under, so it is now transparent: the walk keeps searching
outward for context.
Both fixes come out of universal-ember/kolay#318, where api-docs
headings rendered inside a heading-less <section> came out as <h1>
(failing axe's heading-order audit in consuming docs pages), and
union-signature variants cascaded one level per variant.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Contributor
|
NullVoxPopuli-ai-agent
pushed a commit
to NullVoxPopuli-ai-agent/kolay
that referenced
this pull request
Jul 13, 2026
The behaviors the previous comments described working around are bugs in which-heading-do-i-need, now fixed in universal-ember/ember-primitives#776 (fallback traversal no longer treats nested sectioning content as heading context; heading-less boundaries are transparent). The comments now just state the intent: these headings are siblings within <Load>'s <section>. With that fix, all signature headings resolve to the same level, one below the heading that precedes the api-docs block (verified against nvp.ui with both fixes packed: timeline renders h3 Timeline -> h4 Element / h4 Arguments / h4 Blocks, union variants at equal levels, 83/83 with axe-core 4.12.1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
NullVoxPopuli
approved these changes
Jul 13, 2026
… even pinned to 2 CPUs) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
NullVoxPopuli-ai-agent
pushed a commit
to NullVoxPopuli-ai-agent/kolay
that referenced
this pull request
Jul 13, 2026
The behaviors the previous comments described working around are bugs in which-heading-do-i-need, now fixed in universal-ember/ember-primitives#776 (fallback traversal no longer treats nested sectioning content as heading context; heading-less boundaries are transparent). The comments now just state the intent: these headings are siblings within <Load>'s <section>. With that fix, all signature headings resolve to the same level, one below the heading that precedes the api-docs block (verified against nvp.ui with both fixes packed: timeline renders h3 Timeline -> h4 Element / h4 Arguments / h4 Blocks, union variants at equal levels, 83/83 with axe-core 4.12.1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Author
|
Re: the Docs' Tests timeout on the first run (86843900699) — investigated as a possible traversal hang; it isn't one:
The retriggered run confirms: Docs' Tests passed in 2m15s, and every other job is green. |
NullVoxPopuli
approved these changes
Jul 13, 2026
Merged
NullVoxPopuli-ai-agent
pushed a commit
to NullVoxPopuli-ai-agent/kolay
that referenced
this pull request
Jul 13, 2026
0.60.1 ships which-heading-do-i-need 0.4.1, which contains the traversal fixes from universal-ember/ember-primitives#776 (fallback does not treat nested sectioning content as heading context; heading-less boundaries are transparent). Together with the markup change in this PR, all api-docs signature headings now resolve to the same level, one below the heading that precedes the block (e.g. "## API Reference" -> h3 Element / h3 Arguments / h3 Blocks). Bumped in the addon package, docs-app, and both test apps that pin it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Fixes two ways
getSectionHeadingLevel(which-heading-do-i-need) disagreed with its own documented algorithm — "We'll need to check the subtrees between these elements, stopping if we encounter other boundary elements" — surfaced while fixing an axeheading-orderfailure via universal-ember/kolay#318 (see the review discussion there).1. Fallback traversal recursed into sectioning content
findHeadingIn's previous-sibling scan skips boundary siblings, but its fallback child-traversal recursed into every child, including nested<section>s. Headings inside a nested/sibling section belong to that section and are not context for ours, but the fallback found them anyway. Consequences:<section>s cascaded one level per section (h3, h4, h5, ...).The fallback now skips sectioning content (
section,article,aside,nav) — consistent with the sibling scan.header/footer/mainare still traversed: a<header>in particular typically contains its section's heading, which the existing "wrapped headings" rendering tests cover (a blanket boundary skip fails 4 of them; this split keeps them green).2. Heading-less boundaries isolated their contents to
<h1>levelOfreturned 1 as soon as the upward walk reached the next boundary, even when that boundary had no heading of its own. A heading-less wrapper<section>therefore cut everything inside it off from the document — kolay's api-docs signatures rendered<h1>s mid-page (a 2+ level heading-order jump on consuming docs pages, flagged by axe-core ≥ 4.12). A boundary without a heading has no level to nest under, so it is now transparent: the walk keeps searching outward for context.Verification
wrapped headings,extraneous sections, shadow-root, and mixed section/aside/article cases (4<InViewport />failures in my local run are pre-existing: identical on an unmodified checkout, IntersectionObserver-timing related, untouched by this change)h2 API Reference → h3 Element / h3 Arguments / h3 Blocks), union variants no longer cascade, and nvp.ui's full suite passes 83/83🤖 Generated with Claude Code