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.

@CybotTM
CybotTM force-pushed the fix/menu-toctree-external-order branch from 80f7e7f to 6358e65 Compare June 16, 2026 19:43
@CybotTM
CybotTM force-pushed the fix/menu-toctree-external-order branch 2 times, most recently from c45ea55 to c4fba4f Compare June 24, 2026 15:26
…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 c4fba4f to 200f1ad Compare July 1, 2026 12:01
typo3-documentation-team pushed a commit to TYPO3-Documentation/t3docs-typo3-docs-theme that referenced this pull request Jul 26, 2026
…1291)

Fixes #1175

## Problem

When a `toctree` mixes internal pages and external links (e.g.
interlinks to other manuals), the **sidebar navigation** renders all
external entries grouped at the top, even though the on-page `toctree`
keeps the authored order. On the reported page (`reference-coreapi` →
Fluid) the sidebar shows `Fluid Syntax` and `ViewHelper reference` (both
external) above the internal pages.

## Root cause

The guides compiler attaches a document's menu entries via **separate
transformers for internal and external entries**
(`InternalMenuEntryNodeTransformer` /
`ExternalMenuEntryNodeTransformer`), and the compiler runs **one full
tree traversal per transformer** at each priority. So every external
entry is attached to the document's menu-entry list in one pass and
every internal entry in another — the list ends up grouped by type
instead of following the authored toctree. The on-page toctree renders
from the `TocNode` (authored order) and stays correct; the sidebar
renders from `DocumentEntryNode::getMenuEntries()` and does not.

This is an engine-level issue in `phpdocumentor/guides`. The proper fix
belongs upstream (phpDocumentor/guides#1344); this PR adds a
**downstream compiler pass** so docs.typo3.org is fixed now, and it can
be removed after a future `guides` bump.

## Fix

`SortMenuEntriesByToctreeTransformer` realigns each document's menu
entries with the authored order of its `toctree`s, 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. **Globbed toctrees are skipped**
(their order comes from the glob expansion, which the sitemap relies
on).

## Before / after

Sidebar of a subpage whose toctree mixes internal pages with two
external links:

**Before**


![before](https://raw.githubusercontent.com/CybotTM/render-guides/issue-1175-screenshots/before.png)

**After**


![after](https://raw.githubusercontent.com/CybotTM/render-guides/issue-1175-screenshots/after.png)

## Verification

- Two integration fixtures: `tests-full/menu-external-order` (one nested
mixed toctree) and `tests-full/menu-multiple-toctrees-order` (two mixed
toctrees on one page). Each **passes with the fix and fails without
it**.
- Full integration suite green (116 tests); the change touches only
mixed/explicit toctrees — `external-menu`, `two-toctrees`,
`menu-subpages`, `sitemap` (glob) and `main-menu-json` are unaffected.
- PHPStan (repo config) and php-cs-fixer clean on the changed files.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Co-authored-by: Lina Wolf <48202465+linawolf@users.noreply.github.com>
CybotTM added a commit to CybotTM/render-guides that referenced this pull request Jul 26, 2026
…YPO3-Documentation#1291)

Fixes TYPO3-Documentation#1175

## Problem

When a `toctree` mixes internal pages and external links (e.g.
interlinks to other manuals), the **sidebar navigation** renders all
external entries grouped at the top, even though the on-page `toctree`
keeps the authored order. On the reported page (`reference-coreapi` →
Fluid) the sidebar shows `Fluid Syntax` and `ViewHelper reference` (both
external) above the internal pages.

## Root cause

The guides compiler attaches a document's menu entries via **separate
transformers for internal and external entries**
(`InternalMenuEntryNodeTransformer` /
`ExternalMenuEntryNodeTransformer`), and the compiler runs **one full
tree traversal per transformer** at each priority. So every external
entry is attached to the document's menu-entry list in one pass and
every internal entry in another — the list ends up grouped by type
instead of following the authored toctree. The on-page toctree renders
from the `TocNode` (authored order) and stays correct; the sidebar
renders from `DocumentEntryNode::getMenuEntries()` and does not.

This is an engine-level issue in `phpdocumentor/guides`. The proper fix
belongs upstream (phpDocumentor/guides#1344); this PR adds a
**downstream compiler pass** so docs.typo3.org is fixed now, and it can
be removed after a future `guides` bump.

## Fix

`SortMenuEntriesByToctreeTransformer` realigns each document's menu
entries with the authored order of its `toctree`s, 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. **Globbed toctrees are skipped**
(their order comes from the glob expansion, which the sitemap relies
on).

## Before / after

Sidebar of a subpage whose toctree mixes internal pages with two
external links:

**Before**


![before](https://raw.githubusercontent.com/CybotTM/render-guides/issue-1175-screenshots/before.png)

**After**


![after](https://raw.githubusercontent.com/CybotTM/render-guides/issue-1175-screenshots/after.png)

## Verification

- Two integration fixtures: `tests-full/menu-external-order` (one nested
mixed toctree) and `tests-full/menu-multiple-toctrees-order` (two mixed
toctrees on one page). Each **passes with the fix and fails without
it**.
- Full integration suite green (116 tests); the change touches only
mixed/explicit toctrees — `external-menu`, `two-toctrees`,
`menu-subpages`, `sitemap` (glob) and `main-menu-json` are unaffected.
- PHPStan (repo config) and php-cs-fixer clean on the changed files.

Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Co-authored-by: Lina Wolf <48202465+linawolf@users.noreply.github.com>
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