fix(php-transformer): replace listing cards with a native Query Loop - #2247
Conversation
|
Verified on a fresh import (SSI dev package, BE
Root cause: each Post's Review by Claude (Anthropic) via Claude Code, orchestrated by @chubes4: AI imported the branch, measured the listing with Playwright, and drafted these notes. |
Listed dated articles already materialize as posts. The listing page kept frozen cards, so a newly published post never appeared. When repeated listing cards share one structure, replace that run with a core/query whose post-template reuses one captured card (title, date, comments, content) and keep non-card chrome. Convert a month list that matches the posts to core/archives. Refs #1245
…rome Weebly-style cards wrap title, date, and comments in a header group, so a direct-child rewrite never found a heading. Recurse into wrappers, replace leaf title/date/content, and drop share chrome. Refs #1245
Post-shaped routes kept title, date, share, and sidebar in post_content, so a listing Query Loop re-rendered that chrome once per card. Reuse ShellExtraction identity to find chrome shared across posts, put title/date in the single template as post-title/post-date, keep sidebar (and matching archives) on the template, and leave only the article body in post_content. Unmatched listing cards stay static before the loop. Refs #1245
A document that contains a comments form matched Leave a Reply at the root, so shared article chrome never split. Detect comment and share chrome from the current block, not descendant text. Refs #1245
1aecc40 to
41fd030
Compare
|
Re-verified the rework on a fresh import (BE
The card template needs to reproduce the listing's two-column row (article column + sidebar, the layout-table track widths from #2211/#2213) around the loop, and the source listing's per-card body (the source shows each post's intro + lead media, not the full article with every gallery). Converting this to draft until the listing reaches parity; the post/single split in this branch looks worth keeping as its own PR. Review by Claude (Anthropic) via Claude Code, orchestrated by @chubes4: AI imported the branch, measured the listing with Playwright, and drafted these notes. |
Problem
#2221 materialized listed dated articles as Posts with day-level dates and
/blog/<slug>/permalinks, but kept the listing page as captured static markup. A newly published post never appeared on/blog/.The first pass of this PR replaced listing cards with a Query Loop, but each Post's
post_contentwas still the full captured article page (title, date/comments, body, share, sidebar). The loop then re-rendered that chrome once per card: sidebar 9×, 17 titles, document height 41067 vs baseline 33931 / source 37609.Design
Post-shaped routes split into template-owned chrome and body.
singletemplate:core/post-titlecore/post-datein the source formatcore/archivesIdentity uses
ShellExtraction::identityMarkup()(the same nested-chrome identity as header/footer shells). Extraction runs only when two or more posts share a title plus a date or identity-shared subtree, and leaves a non-empty body. Comment/share chrome is detected on the current block, not descendant text.post_contentis the article body only, so the listing Query Loop'score/post-contentrenders that body once per post. The listing page keeps its own sidebar once.Query / post-template / post wrappers still use
display: contentsso captured card geometry participates in the parent layout.No importer change.
Fix
After shared shells and the navigation entity:
singletemplate and rewrite each post to body-only markup.core/query(postType: post,inherit: false,order: date desc,perPage= captured card count) whose post-template reuses one card (title, date, comments, post-content).core/archives.Tests
Contract fixture in
php-transformer/tests/contract/wordpress-site-plan.php(nested header chrome, comments form, share, sidebar, archives, orphan card):<!-- wp:queryabsent).Post content is the article body onlyassertion).core/archives; unmatched card stays static before the loop; "Leave a Reply" stays in the template, not inpost_content.composer testandphp tests/contract/production-acceptance-matrix.phppassed locally. Visual parity tool tests passed.Fresh import evidence
SSI dev package from
origin/main(c90b293a3e1e) with--blocks-engine-paththis branch.41fd0307cc34quality_pass: true,fallback_blocks: 0,invalid_blocks: 0serialize_blocks(parse_blocks(content))matches on/blog/and a postcore/navigationref(wp_navigation entity from fix(php-transformer): emit a shared navigation entity referenced by token #2248)n/j/Y), Author/Archives sidebar, and bodyPlaywright at 390/768/1440 (visible titles /
.blog-sidebarcount / document height):/blog//blog//blog/* Listing markup contains one Author/Archives sidebar; the article column fills the row so the column box itself can report height 0 while the inner sidebar still renders once (below the cards at 1440). Title count is 9 (8 loop posts + the unmatched static card), down from 17.
† Inner
.blog-sidebar-separatoris visible once.Single-post title, meta, body, and sidebar placement match the baseline. Listing is live; card height still exceeds the frozen-card baseline because loop bodies include full article media.
Remaining on #1245
core/categorieswhen the captured list matches WordPress terms (this source is only "All").core/post-comments-linkonce comments are imported.Refs #1245
AI assistance
Written by Claude (Anthropic) via Claude Code, orchestrated by chubes4. The model split post-shaped routes into template-owned chrome and body-only
post_contentusing ShellExtraction identity, kept unmatched listing cards static, added regression coverage (fails on trunk / listing-only HEAD, passes on this branch), rebuilt an SSI dev package, and verified a fresh import plus a newly published post. Chris Huber directed the work and remains responsible for the submitted change.