Automattic / Automattic/blocks-engine

Derive editor presentation from containment, inert runtime, and block chrome

Open
#1,483 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
PHP
Stars
14
Forks
2
Avg merge
2h 10m
Merged PRs (30d)
561

Description

## Problem

Editor presentation is assembled as a chain of symptom patches rather than a model of how an editor canvas differs from the frontend. `NavigationStyleProjector::materializeEditorStaticStateStylesheet()` currently holds six unrelated concerns, each guarded by its own ad-hoc condition, and each written with `!important`:

```php
if ( '' !== $anchorProjectionCss ) { ... } // anchor projection
if ( preg_match('/animation.../', $authorCss) ) { ... } // freeze animations
if ( $runtimeBehavior->emptyRuntimeTargetGenerated() ) { ... } // dynamic-content placeholder
if ( $runtimeBehavior->emptyVisualGroupGenerated() ) { ... } // painted-layer placeholder
if ( preg_match('/\bbody\b[^{}]*\{[^}]*overflow.../', $authorCss) ) // body overflow repair
foreach ( $styleResolver->closedStateRepairCssRules() ... ) // closed-state repair
```

Two consequences:

1. **Coverage is limited to symptoms already discovered.** Anything not yet reported stays misplaced, because there is no model that would predict it.
2. **Decisions are made by sniffing author CSS with regular expressions** (for example matching `body { ... overflow ... }` as text) rather than by consulting the site plan. That is fragile against equivalent-but-differently-written source CSS.

The method also lives in a class named for navigation while owning none of these concerns.

## Expected contract

An editor canvas differs from the rendered frontend in exactly three ways. Derive the generated editor stylesheet from those, and have every emitted rule declare which one it addresses.

1. **Containment** — the canvas is a bounded, non-viewport container. Geometry expressed against the viewport does not track it. This is the same class of defect as viewport-anchored media geometry: a value that is correct only while its container happens to match the viewport.
2. **Inert runtime** — scripts are absent, so any runtime-driven state (entrance animation, open/closed disclosure, dynamically populated region) must resolve to a defined static state.
3. **Block chrome** — the editor injects wrappers, placeholders, and variation pickers that the source composition never contained, and which occupy layout the source did not allocate.

Inputs should come from the site plan and the transform's own recorded behaviour, so the emitter reasons about known facts instead of re-detecting them from stylesheet text.

## Acceptance

- Every generated editor rule is attributable to containment, inert runtime, or block chrome.
- Editor decisions read recorded transform/site-plan state rather than pattern-matching author CSS text.
- Editor projection lives in a class that owns editor presentation, not in the navigation projector.
- Rules stop relying on `!important` to defeat author CSS, except where a source declaration is itself `!important`.
- The 292 parity fixtures pass unchanged.
- A generated site opens in the editor with source composition intact: no injected picker occupying source layout, and no element positioned by a viewport-anchored value inside the bounded canvas.

## Related

- #1465 covers bounding editor presentation *delivery* for large sites; this issue covers what that delivered stylesheet should contain and why.
- #754 and #761 address editor-valid asset rewrites, a separate editor-correctness axis.

## AI assistance disclosure

This issue was researched and written with AI assistance: Claude Sonnet 4.5 running in the opencode CLI agent. The AI read the editor stylesheet assembly path, enumerated the six concerns and the regex-driven conditions quoted above, and drafted the proposed three-axis contract. A human reviewed and directed the simplification framing.

Contributor guide

Open the contributing guide

Research direction

Start with NavigationStyleProjector::materializeEditorStaticStateStylesheet() and trace the site-plan inputs and recorded transform behavior it can use. Review the six existing concerns and the 292 parity fixtures, then separate editor rules by containment, inert runtime, or block chrome. Done means the acceptance conditions hold and all parity fixtures pass unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
php, wordpress
Domain
frontend, web-dev
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.