fix(php-transformer): carry menu chrome presentation core cannot save - #1606
Merged
Conversation
A navigation label is inlined into the core/navigation-link `label` attribute, so it never reaches the block tree and SourceBlockAttributeProjector never stamps its projected marker classes. The author rules for the label were already rewritten onto those markers, so the rewritten rule matched nothing and menu labels rendered at user-agent defaults on the front end while looking correct in the editor, which reads the separate editor-static-state projection. Carry the markers on the serialization clone so the rewritten rules match. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016W6gpfFTSwSok5vMvLnd5L
…not save core/details renders `<summary>` with no attributes, so a source toggle's own classes are dropped and every author rule addressing them is left with nothing to match. An overlay menu button loses its paint, its radius and its label type, and drops to the destination theme's defaults. Resolve the toggle's box once and restate it on a marker the details block carries, following the navigation link icon projection. The label's type rides along because it is inheritable and its own rules lost the same ancestor. Delivered as CSS, not markup: attributes on <summary> would diverge from core's save shape and invalidate the block. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016W6gpfFTSwSok5vMvLnd5L
core renders <summary> with no box, and the static-disclosure stylesheet only makes it inline-block, so a toggle sized by the source collapses to fit its label. Carry the box the source resolved on the toggle alongside its paint. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016W6gpfFTSwSok5vMvLnd5L
Fails on trunk for both surfaces: the navigation label carries no marker the frontend stylesheet addresses, and the disclosure toggle emits no summary rule. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016W6gpfFTSwSok5vMvLnd5L
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 #1605.
Problem
Two menu surfaces are rebuilt by core rather than emitted from the source, so the source element that carried the author classes stops existing and the author rule is left addressing nothing. Both look correct in the editor, which reads the separate
editor-static-stateprojection, and drop to the destination theme's defaults on the front end — which is why this survived four import runs unnoticed.1.
core/navigation-linkstores its label as a block attribute. The label markup never reaches the block tree, soSourceBlockAttributeProjectornever merges the projected marker classes into aclassName.AuthorStylesheetProjectorhas already rewritten the label's author rule onto those markers, so the rewritten rule matches nothing:2.
core/detailsrenders<summary>with no attributes.BlockFactoryemits a hardcoded<summary>andDetailsPatterncarries only the summary's inner HTML, so a disclosure toggle's own classes are dropped outright. On a hamburger site that toggle is the entire visible navigation affordance.Approach
Labels —
SourceDom::innerHtmlWithProjectedMarkers()stamps the projected markers while serializing markup destined for a block attribute. Markers are stamped on the serialization clone, never on the source DOM, so later selector matching still sees the authored classes. It falls back to the transformer's own serializer whenever no marker had to be carried, so rich-text lowering is unaffected.Toggles — resolve the toggle's box once, register it under a marker the details block carries, and restate it from
engine-supportCSS as.wp-block-details.<marker>>summary{…}, following the existingnavigation-link-iconprojection.Delivered as CSS rather than markup by necessity:
core/detailsdeclaressummaryas{"type":"rich-text","source":"rich-text","selector":"summary"}and saves a bare<summary>, so attributes there would diverge from core's save shape and invalidate the block. The emitted<summary>stays attribute-free, and the test asserts that.The label's type rides along on the same rule because it is inheritable and its own rules lost the same ancestor. Position and margin stay out — the details block core lays out already holds the slot.
Verification — two live sources
Imported through WordPress Studio PR Automattic/studio#3952
52755397+ Data Liberation Agent PR Automattic/data-liberation-agent#11916f32f4+ Static Site Importer881768a, on WordPress 7.1. Computed styles measured with Playwright, before and after on the same build.Horizontal menu —
https://www.wix.com/sgtemplates/e-ramirezcolorrgb(0, 0, 0)rgb(255, 153, 254)rgb(255, 153, 254)font-familyfont-sizeletter-spacingOverlay toggle —
https://www.wix.com/sgtemplates/sophja-j-piercebackgroundrgb(26, 26, 26)rgb(26, 26, 26)border-radiuscolorrgb(0, 0, 0)rgb(239, 254, 139)rgb(239, 254, 139)fontRe-importing the first source on the final build confirms no regression: labels and page height unchanged and still exact.
Editor: 0 block-validation warnings and 0
core/htmlfallback blocks on both sources, before and after.Known gaps, deliberately not in this PR
height:100%on the toggle; the<details>box core lays out does not fill its parent, so the pill is flatter than the source. Paint, radius, width and type are exact.-58/-59/-60while the labels that render carry-53–-56, i.e. the rule was projected onto source elements that never reach the output. That sits in the responsive-counterpart area, whose most recent change on Data Liberation Agent Preserve source button controls semantically #119 is a revert of "Preserve responsive counterpart provenance", so it wants a decision there rather than a patch here.Note for #1482
This adds one more marker vocabulary (
blocks-engine-disclosure-summary-*) to the surface #1482 wants to consolidate. It deliberately follows the existingnavigation-link-iconprojection rather than introducing a new mechanism, but it is additional surface for that refactor to absorb.Validation
composer test:canonical— 150 tests pass (149 before, plus the new one).composer test:parity— 300 fixtures pass.tests/unit/menu-chrome-presentation-carry.phpfails ontrunkfor both surfaces (2 of 5 assertions) and passes on this branch.php -lclean on every changed file.AI Assistance
Claude Opus 5 via Claude Code was used to diagnose both failures, reduce each to a minimal reproduction, implement the change, and run verification against two live sources. gmovr remains responsible for the submitted changes.
🤖 Generated with Claude Code
https://claude.ai/code/session_016W6gpfFTSwSok5vMvLnd5L