Skip to content

Carry the source div marker on description-list rows - #5251

Merged
chubes4 merged 1 commit into
trunkfrom
fix/issue-5235-blocks-engine
Nov 9, 2026
Merged

chubes4 merged 1 commit into
trunkfrom
fix/issue-5235-blocks-engine

Conversation

@chubes4

@chubes4 chubes4 commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

What and why

The theme stylesheet rewrites the author rule .intro dl div{…} to .intro dl :where(.blocks-engine-source-div-<hash>-0):not(be-t-0){…}. This happens because the source div tag has a projection marker: converted divs become wp-block-group, paragraphs and similar blocks, and those blocks carry the marker class. The generated <theme>/description-list block was the exception. It rendered its row wrappers as plain <div>s, so the rewritten rule matched nothing and the rows lost their borders and padding.

Fix (option a): DescriptionListBlockGenerator::wrapper() now merges the session's source tag marker for the row element (tagMarker('div')) into the wrapper's className. The marker lives in the block's groups[].wrapper.className attribute. The JS save() already renders that attribute (via markupAttributes), so saved markup stays editor-valid. Other converted elements keep source identity the same way: SourceBlockAttributeProjector::sourceProjectionClassName, LayoutShellLowering, TableAttributesBuilder and SourceDom::safeFallbackHtml all add the tag marker to the rendered element.

I picked this over option (b), keeping div as a type selector when it sits under dl. Option (a) leaves the selector projector unchanged. Every div type selector is still rewritten the same way, including dl + div, dl ~ div and .x dl .y div. So no un-rewritten div selector can reach the wrapper divs WordPress adds, and the fix applies only to the rows this block actually renders. The marker is added only when the author CSS allocated one, so lists on pages without div type selectors render unchanged.

Evidence (reduced page dlist.html)

Theme CSS (unchanged): .intro dl :where(.blocks-engine-source-div-d5880a8e6d01-0):not(be-t-0){border-top:1px solid #ccc;padding:1.25rem 0}

Before (Studio import, released engine):

<!-- wp:ssi-dl5235/description-list {"groups":[{"wrapper":[],"items":[{"tagName":"dt","content":"Color story"},{"tagName":"dd","content":"Spring · Summer"}]},{"wrapper":[],"items":[…]}]} --><dl><div><dt>Color story</dt><dd>Spring · Summer</dd></div><div><dt>Forms</dt><dd>Plates · Bowls</dd></div></dl>

After (this branch):

<!-- wp:custom/description-list {"groups":[{"wrapper":{"className":"blocks-engine-source-div-d5880a8e6d01-0"},"items":[{"tagName":"dt","content":"Color story"},{"tagName":"dd","content":"Spring · Summer"}]},{"wrapper":{"className":"blocks-engine-source-div-d5880a8e6d01-0"},"items":[…]}]} --><dl><div class="blocks-engine-source-div-d5880a8e6d01-0"><dt>Color story</dt><dd>Spring · Summer</dd></div><div class="blocks-engine-source-div-d5880a8e6d01-0"><dt>Forms</dt><dd>Plates · Bowls</dd></div></dl>

Tests

  • New: tests/unit/description-list-source-tag-selector.php (added to test:unit). It runs a single table-driven case through HtmlTransformer, takes the emitted author CSS selectors and checks them with CssSelectorMatcher against the emitted block markup:
    • .intro dl div is rewritten to the marker and matches both rendered rows, but not the following sibling.
    • Negative case: dl + div is still rewritten (no bare div type selector). It matches the following sibling and neither row.
    • The block markup passes wp_block_validity.
    • Fails on trunk: descendant row selector: row match is true for .intro dl :where(.blocks-engine-source-div-…):not(be-t-0) on <div><dt>Color story</dt>…. Passes with the fix.
  • Neighbouring tests, all passing with the fix: description-list-block, functional-source-tag-identity, author-selector-semantics, richtext-type-selector-preservation, css-selector-matcher, list-element-converters, htmlcompilation-generator-builders, html-result-composer, companion-plugin-namespace, tests/contract/run.php, tests/contract/wordpress-site-plan.php, and the parity suite (351 fixtures).

AI disclosure: Claude (claude-fable-5-1) running in Pi wrote the fix, the test and this PR as a subagent of the Data Liberation import-loop orchestrator. Finalized outside Homeboy with Chris's authorization because Homeboy cook finalization is blocked (homeboy#16292).

Author type selectors such as `.intro dl div` are rewritten to the source
div tag marker, but the description-list block rendered its row wrappers
as plain divs, so the projected rule matched nothing. Persist the marker in
each row wrapper's className attribute, the same source identity other
converted elements carry, so saved markup stays editor-valid and the
rewritten selector matches.

Fixes #5235.
@chubes4
chubes4 force-pushed the fix/issue-5235-blocks-engine branch from 17792b0 to dc7b924 Compare November 9, 2026 18:06
@chubes4
chubes4 merged commit 549e534 into trunk Nov 9, 2026
13 checks passed
@chubes4
chubes4 deleted the fix/issue-5235-blocks-engine branch November 9, 2026 18:31
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