Skip to content

Keep navigation menu in toctree order when mixing internal and external entries#1344

Open
CybotTM wants to merge 1 commit into
phpDocumentor:mainfrom
netresearch:fix/menu-toctree-external-order
Open

Keep navigation menu in toctree order when mixing internal and external entries#1344
CybotTM wants to merge 1 commit into
phpDocumentor:mainfrom
netresearch:fix/menu-toctree-external-order

Conversation

@CybotTM

@CybotTM CybotTM commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Problem

A toctree that mixes internal pages and external links builds the navigation menu (the document entry's menu entries, used for the sidebar/navbar) with all external entries grouped first, even though the on-page toctree keeps the authored order. The navigation therefore disagrees with the page. It shows up for nested toctrees.

Root cause

Internal and external menu entries are attached to the document entry by two separate transformers — InternalMenuEntryNodeTransformer and ExternalMenuEntryNodeTransformer — and the compiler runs one full tree traversal per transformer at a given priority (both attach at 4500). So every external entry is appended to DocumentEntryNode::getMenuEntries() in one pass and every internal entry in another, and the list ends up grouped by type instead of following the toctree. The on-page toctree renders from the TocNode value (authored order) and stays correct.

Fix

ToctreeSortingTransformer (priority 3200, after the attach passes) now realigns the document entry's menu entries with the authored toctree order, matching entries by file/URL. It emits each toctree's entries as one contiguous block at the position of its first entry, so a document with several mixed toctrees is ordered correctly too. It already ran at the right point to handle the reversed option, and globbed toctrees are skipped — their order comes from the glob expansion, not an authored sequence.

Before / after

Sidebar of a nested subpage whose toctree interleaves internal pages and external links (Bootstrap theme):

Before

before

After

after

Tests

Two integration fixtures: tests-full/bootstrap/bootstrap-menu-nested-external-order (one nested mixed toctree) and tests-full/bootstrap/bootstrap-menu-multiple-toctrees-order (two mixed toctrees on one page). Each passes with the fix and fails without it.

Verified locally: integration (229), unit (481) and functional (117) suites pass; PHPStan (level max + baseline), PHPCS (Doctrine standard) and deptrac all clean.

Context

Reported downstream at TYPO3-Documentation/render-guides#1175.

…al entries

A toctree that mixes internal pages and external links built the
navigation menu (the document entry's menu entries) with all external
entries grouped first, even though the on-page toctree kept the authored
order. The sidebar/navbar therefore disagreed with the page; this was
visible for nested toctrees.

Internal and external menu entries are attached to the document entry by
two separate transformers (InternalMenuEntryNodeTransformer and
ExternalMenuEntryNodeTransformer), and the compiler runs one full tree
traversal per transformer, so every external entry is appended in one
pass and every internal entry in another. The result is grouped by type
instead of following the toctree.

ToctreeSortingTransformer now realigns the document entry's menu entries
with the authored toctree order, emitting each toctree's entries as a
contiguous block at the position of its first entry. Applied per toctree
in document order, this also yields the correct order when a document has
several mixed toctrees. It already ran at the right point to handle the
reversed option; globbed toctrees are skipped, since their order comes
from the glob expansion rather than an authored sequence.

Reported downstream at TYPO3-Documentation/render-guides#1175
@CybotTM CybotTM force-pushed the fix/menu-toctree-external-order branch from c45ea55 to c4fba4f Compare June 24, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant