Skip to content

fix(php-transformer): share fragment-equivalent variant menus - #2250

Merged
chubes4 merged 3 commits into
trunkfrom
fix/2246-shared-variant-menu
Sep 26, 2026
Merged

chubes4 merged 3 commits into
trunkfrom
fix/2246-shared-variant-menu

Conversation

@chubes4

@chubes4 chubes4 commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Desktop and mobile header menus with the same labels and paths stayed independent when one URL kept an in-page fragment. A rename in the Site Editor could not update both viewports. The shared navigation post also dropped the current item's geometry carrier, so the rendered item box no longer matched the source.

Depends on #2245 (paragraph-labelled menus become core/navigation) and #2248 (one menu entity per destination list). Those are already on trunk. #2248 and static-site-importer#1865 were merged before this follow-up; they do not set ref on hosts (inline children stay until SSI materializes) and they compared full URLs, fragment included.

After #2248, a responsive-variant capture that previously extracted shared header and footer parts produced no template parts. #2251.

Root cause

NavigationEntityProjection clustered on label + url, so /journal and /journal#section were different menus. ShellExtraction::withoutCurrentNavigationState() also stripped be-inline-geometry-* from the current item when building the entity that both viewports render. Shell identity still needs that strip; the rendered entity does not.

The missing parts are a separate ordering/identity failure. Navigation compilation makes the unlabeled shell candidate diverge, so sharedShells never reaches the viewport-partition hoist. Inline extraction then claims the pair as header-1/footer-1, or a document-wide landmark regex exhausts PCRE on a large page and rejects the whole area. Either way the template-bound header.html and footer.html parts are not emitted.

Fix

  • Compare navigation destinations with the fragment removed. Different paths stay separate entities. Hosts stay inline (no unresolved token ref) so WordPress can render before SSI binds an integer ref.
  • Keep the current item's geometry carrier on the entity. Shell-identity normalization still drops it.
  • Leave viewport-scoped landmarks to the shared partition instead of inline header-1/footer-1 parts. When shell candidates do not cluster, hoist a dominant desktop/mobile pair into one template-bound header and footer.
  • Scan block comments with a bounded walk so a large page cannot drop every landmark by exhausting PCRE.

Regression test

php php-transformer/tests/contract/shared-navigation-entity.php

Fails before (git stash of the projection / shell change):

PHP Fatal error: Uncaught RuntimeException: Variant menus that differ only by a URL fragment become one navigation entity.

and, for the geometry line:

PHP Fatal error: Uncaught RuntimeException: The shared navigation entity keeps a current item's geometry carrier.

Passes after:

shared-navigation-entity: ok

php php-transformer/tests/contract/shared-shell-plan.php

Fails before this commit (inline variants, no shared header/footer):

PHP Fatal error: Uncaught RuntimeException: Viewport-partitioned chrome still extracts one shared header and footer when both viewports contain navigation: ["header-1:inline_responsive_variant","header-2:inline_responsive_variant","footer-1:inline_responsive_variant","footer-2:inline_responsive_variant"]

Passes after:

shared-shell-plan contract passed

Also passed: php php-transformer/tests/unit/shell-landmark-policy.php, php php-transformer/tests/unit/route-current-navigation.php.

Verification

Paired SSI dev package imported the private capture (quality_pass, 0 fallbacks).

  • parts/header.html and parts/footer.html exist. Provenance reason responsive_variant_partition. Both header navigations are self-closing core/navigation blocks with the same ref (one wp_navigation).
  • One visible header at 1440 (second header 0×0) and one at 390, on /, /shop/, and /services-1/.
  • Desktop Home link at 1440: x=733, y=45 (within 2px of 733).
  • One rename of the shared menu label in the Site Editor header part updated the visible desktop menu and the opened 390 menu on /, /shop/, and /services-1/.

Static Site Importer main Homeboy Test is green after the later CI fix (run 36270107473). No SSI change in this pass.

Fixes #2246
Fixes #2251

AI disclosure: implemented by xAI Grok 4.7 via OpenCode (opencode run), orchestrated and reviewed by Claude (Anthropic).

…ragment

Desktop and mobile navigations with the same labels and paths were split
into two entities when one URL kept an in-page fragment. Compare destinations
without that fragment so both blocks can reference one navigation entity.
…tion entity

Shell identity still ignores a selected item's geometry carrier, but the
navigation post keeps it so both viewports render the source item box.
@chubes4

chubes4 commented Sep 26, 2026

Copy link
Copy Markdown
Contributor Author

Holding: verification on a fresh import found that trunk (with #2248) no longer extracts shared header/footer parts for this responsive-variant capture; bisected to #2248, tracked in the new regression issue. The shared-menu behaviour here can't be verified end to end until that is fixed.

AI disclosure: Claude (Anthropic) via OpenCode.

…s diverge

Navigation compilation can split the unlabeled shell candidate so a
responsive pair no longer clusters, and a document-wide landmark scan
drops large pages. Hoist a dominant desktop/mobile pair into one shared
header and footer instead.
@chubes4
chubes4 marked this pull request as ready for review September 26, 2026 22:15
@chubes4
chubes4 merged commit 55ca3af into trunk Sep 26, 2026
10 checks passed
@chubes4
chubes4 deleted the fix/2246-shared-variant-menu branch September 26, 2026 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant