Automattic / Automattic/blocks-engine

Resolve generated companion blocks from canonical content attributes

Open
#1,213 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

Generated companion blocks carry two copies of the same captured markup:

- the editable `content` block attribute, which the WordPress site-plan path canonicalizes and resolves
- `companion_plugin_payload.blocks[].render`, which remains the original static HTML

Static Site Importer scaffolds the second copy into `render.php`. The frontend therefore renders the uncanonicalized copy and bypasses the resolved editable attribute.

For local browser assets inside a generated custom block, this produces broken requests even though the assets were copied and the canonical page content is valid. For example, a captured gallery containing:

```html

Work
```

is copied into the theme and represented by canonical site-plan asset references, but the generated companion plugin still emits `/assets/css/gallery.css` and `/media/work.jpg` from its static `render.php`.

## Production evidence

Source: https://www.junedigann.com/

- 19/19 routes compile and materialize.
- The site plan has zero unresolved-local-browser-reference diagnostics after #1210.
- All 19 pages open in Gutenberg with zero invalid blocks or block-validation notices.
- The imported homepage requests nonexistent root-relative `/assets/css/capture-*.css` paths from a generated gallery renderer.
- The same CSS files exist under the generated theme and are also enqueued through `get_theme_file_uri()`.
- Playwright full-page comparison at 1440px reports 8.17% mismatched pixels on the homepage; gallery images render as empty boxes.
- The generated plugin's `blocks/gallery-*/render.php` contains the original root-relative `` and media markup.

## Root cause

`AssetReferenceCanonicalizer` processes canonical page block markup, but `CompanionPluginPayload::normalizeGeneratedBlock()` packages the independent raw `render` string. The consumer then treats that string as the authoritative frontend renderer instead of rendering the resolved `content` attribute.

This is a producer/consumer contract gap rather than another URL-parser case. Replacing URL strings in the static renderer would still leave two divergent content authorities and would not make frontend rendering reflect editor changes.

## Proposed contract

1. Blocks Engine emits an audited generic renderer identifier for generated sanitized-markup blocks instead of a static duplicate `render` payload.
2. The companion block declares a string `content` attribute as its single content authority.
3. Static Site Importer implements that renderer using the resolved `content` attribute with its existing executable-markup and URL safety policy.
4. Contract coverage proves local stylesheet, image, `srcset`, poster, and inline-style URL references render through destination theme URLs after materialization.
5. End-to-end coverage verifies a generated custom gallery has no root-relative artifact requests and that an editor content change affects frontend output.

Related parser fix: #1209 / #1210.

## AI assistance

OpenAI GPT-5.6-Sol via OpenCode helped inspect the materialized WordPress output, run Playwright visual and Gutenberg validation, trace the divergent site-plan and companion-render paths, and draft this issue. Chris Huber remains responsible for the report.

Contributor guide

Open the contributing guide

Research direction

Start by tracing AssetReferenceCanonicalizer and CompanionPluginPayload::normalizeGeneratedBlock(), then inspect the generated blocks/gallery-*/render.php output and the Static Site Importer consumer. Use the proposed renderer and content-attribute contract as the scope. Done means local stylesheet, image, srcset, poster, and inline-style references use destination theme URLs, editor content changes affect frontend output, and end-to-end checks show no root-relative artifact requests.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
backend-api-design, frontend, testing
Issue type
Bug
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.