Repository navigation
feat: comments-family renderer parity + CommentInliner + post-comments / pagination forks (#519 Pass 2) - #525
Conversation
…mmentInliner (#519 Pass 2) Completes #519 by landing the remaining 8 comments-family blocks plus the renderer parity and server-side comment-loop expansion that the Pass 1 forks (#524) deferred. ## Block forks (8 × 7 files) - post-comments-form (server-rendered <form>, null save) - post-comments-count, post-comments-link, post-comments-title (per-post display blocks; resolve through PostResolver against the parent post's counters / URL) - comments-pagination (InnerBlocks wrapper) + -next / -numbers / -previous (per-page display blocks; render against request-time pagination state) Each block: block.json + edit.tsx + save.tsx + transforms.ts + index.ts + inserter-icon.tsx + upstream-state.json. Pagination blocks match upstream WP block-library 9.43.0 naming (`artisanpack/comments-pagination*`, no `post-` prefix). ## Renderer parity (Blade / React / Vue) All 16 comments-family blocks (Pass 1 + Pass 2) now ship with matching renderers across all three engines: - Blade: 16 `.blade.php` partials under `packages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/` - React: 16 components in `packages/visual-editor-renderer-react/src/blocks/artisanpack/commentContext.tsx`, registered in `registerCoreBlocks.ts` - Vue: 16 render fns in `packages/visual-editor-renderer-vue/src/blocks/artisanpack/commentContext.ts`, registered in `registerCoreBlocks.ts` - `packages/renderer-parity.json` extended with the 16 entries; CI parity script reports `all 111 blocks registered` across all three renderers. ## CommentInliner New `src/Resources/CommentInliner.php` — sibling to QueryInliner. Walks the saved block tree and, for every `artisanpack/comments` wrapper, clones its inner `comment-template` once per resolved comment, stamping each iteration's leaves via CommentResolver. The wrapper itself receives post-level `_resolved*` attrs (postId, commentCount, commentsUrl, commentsLabel) and they cascade to non-template children (post-comments-form, count, title, etc.). When no `$post` is supplied, the block is marked with `_resolutionError=no-post-context` so the renderer can render an empty surface without breaking the surrounding layout. ## BlocksComponent (Blade) pipeline `<x-ve-blocks :post="$post">` now: - runs `CommentInliner` against the tree when `$post` is supplied - runs `PostResolver::stampTree` against the tree (top-level post-* / post-comments-* blocks outside any query loop) Both pipelines opt-in via the supplied `$post`; the existing post-context-free render path is unaffected. ## PostResolver Extended SUPPORTED_BLOCKS + match branches: - post-comments-form → `_resolvedPostId` so the standalone form block (placed outside the `comments` wrapper in a single-post template) renders its hidden `post_id` field. Without this the form posts an empty `post_id` and validation rejects. ## post-comments-form Form action is now configurable via `_resolvedFormAction` attribute + `comments.form.action` hooks filter so host apps can redirect submissions to a controller that returns a redirect-back-with-flash instead of the JSON 201 the cms-framework REST endpoint emits. Submit input is `<input type="submit">` (not `<button>`); the `name="submit"` attribute is deliberately omitted — it shadows the form's `.submit` DOM property and breaks any JS that hooks the form. ## Editor placeholders → realistic dummy data `createCommentPlaceholderEdit` + `createEntityPlaceholderEdit` gained a `dummyValue` config field. Authors editing a single-post template (with no specific post in scope) now see representative content for every comment-family leaf — "Jane Doe", "October 25, 2024", "5 Comments", a Gravatar mystery-person silhouette, sample comment paragraph, "1 2 3" page numbers, etc. — rather than a generic dashed-outline label. The placeholders only paint when neither `_resolved*` nor the appropriate query/comment-preview context is available, so the resolved render path is unaffected. `post-comments-form` edit now renders a non-interactive form scaffold (every label, input, submit-button state present) so the whole form is styleable in the canvas. ## Dependency Bumped `artisanpack-ui/cms-framework` from `^1.1` to `^2.0` — required for the Comment model + Post::comments relation introduced in cms-framework 2.1.0 that the renderers consume via CommentResolver and CommentInliner. ## Tests - `CommentInlinerTest`: 7 tests covering no-post fallback, post-level attribute stamping, per-comment expansion, post-level attribute cascade to non-template children, empty-comments collapse, copy-on-write iteration, iterable comment sources. - `PostResolverTest`: +8 tests for post-comments-* branches (count / link with pluralization / title with pluralization / form post-id stamping + artisanpack/* parity). - `EnabledBlockNamesTest`: snapshot extended for Pass 2. - `post-comments-family.test.ts`: 32 contract tests for the 8 Pass 2 blocks (block.json namespace + textdomain, save shape, bidirectional transforms, wrapper innerBlocks preservation, context wiring). - Renderer parity script: clean across all 111 blocks. Pre-PR `cr review --base release/1.0`: 4 passes total, addressed all findings (form unique IDs, pagination aria-current correctness, label localization, dummy avatar, calendar icon, pagination aria-label localization). Final pass: 0 findings. Full suite: 835 PHP (+8 from this commit) / 1770 JS, all green. Manually verified end-to-end against jmwd-keystone-cms: theme single template renders post-title / post-content / 5 seeded comments + auto-approved guest form submissions; editor template preview shows dummy data on every block. Closes #519.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds post-comments-* and comments-pagination blocks, CommentInliner and PostResolver updates, wires resolution into BlocksComponent/DI, implements Blade/React/Vue renderers and editor placeholder fallbacks, updates config/parity, and adds unit/Vitest tests. ChangesComments family — Pass 2
Sequence Diagram(s)sequenceDiagram
participant Editor
participant BlocksComponent
participant CommentInliner
participant PostResolver
Editor->>BlocksComponent: provide block tree + optional post
BlocksComponent->>CommentInliner: inline(tree, post)
CommentInliner-->>BlocksComponent: expanded per-comment template items
BlocksComponent->>PostResolver: resolve post-comments blocks
PostResolver-->>BlocksComponent: stamped _resolved* attributes
BlocksComponent->>Editor: render Blade/React/Vue views or serialized InnerBlocks
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related issues
Possibly related PRs
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
resources/js/visual-editor/blocks/comments-pagination-next/save.tsx (1)
1-11:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winInconsistent documentation about
_resolved*attributes.The comment here states that markup is "produced server-side from stamped
_resolved*attributes" (line 4-5), butedit.tsxlines 6-7 state "request-time, not post-time, so there's no_resolved*attribute to stamp." Additionally,edit.tsxline 18 referencesresolvedKey: '_resolvedPaginationNextLabel', suggesting such an attribute exists.Clarify whether
_resolved*attributes are stamped for pagination blocks and update the comments consistently across edit.tsx and save.tsx.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@resources/js/visual-editor/blocks/comments-pagination-next/save.tsx` around lines 1 - 11, The header comment in CommentsPaginationNextSave incorrectly claims markup is produced server-side from stamped `_resolved*` attributes; reconcile this with edit.tsx where a resolvedKey '_resolvedPaginationNextLabel' is referenced and a note says resolved attributes are request-time (not post-time). Update the comment in CommentsPaginationNextSave (and mirror in edit.tsx) to clearly state whether pagination blocks receive stamped `_resolved*` attributes (e.g., '_resolvedPaginationNextLabel') or if labels are resolved at request-time only, and ensure the description for CommentsPaginationNextSave and the comment near resolvedKey in edit.tsx consistently reflect that behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-content.blade.php`:
- Around line 12-14: The Blade template renders raw HTML via {!! $content !!}
where $content is stamped as _resolvedContent in
CommentResolver::resolveContent(), creating a stored XSS risk; fix by ensuring
resolveContent() sanitizes/escapes the comment body before assigning to
_resolvedContent (e.g., HTML-escape or run through a sanitizer/HTML purifier and
store the safe string) or, if you prefer template-level hardening, change the
template to use escaped output ({{ $content }}) instead of {!! $content !!};
update unit tests accordingly to assert the sanitized/escaped value and
reference CommentResolver::resolveContent(), the _resolvedContent attribute, and
the Blade usage of {!! $content !!} when making the change.
In
`@packages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comments-pagination-numbers.blade.php`:
- Around line 15-16: The current conditional combines $number === $current and
'' === $href, causing non-current pages without URLs to render as current;
update the logic in the template so that $number === $current alone renders
<span class="page-numbers current" aria-current="page">, while the '' === $href
branch renders a distinct non-link state (e.g., <span class="page-numbers
disabled">) and does NOT include aria-current; adjust the conditional around
$number, $current and $href to separate the two cases and ensure disabled pages
use a different class and no aria-current attribute.
In
`@packages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/post-comments-title.blade.php`:
- Around line 10-16: The fallback English strings for $title are not localized;
when $attributes['_resolvedCommentsTitle'] is missing you should use
localization helpers: replace the hardcoded plural logic that builds 'No
Comments' / '1 Comment' / '$count Comments' with a trans_choice call that uses
$count, and replace the hardcoded 'Comments' (used when ! $showCount) with a
translation via __(); update the logic around
$attributes['_resolvedCommentsTitle'], $count and $showCount to call
trans_choice(...) for the count-based title and __('Comments') for the non-count
heading so fallbacks are translated.
In `@resources/js/visual-editor/blocks/comments-pagination-previous/block.json`:
- Line 8: Update the JSON "description" value for the
comments-pagination-previous block: replace the incorrect possessive string
"Displays the previous comment's page link." with the corrected plural form
"Displays the previous comments page link." so the description accurately refers
to the previous page of comments (modify the "description" property in the
block.json entry).
In `@src/Resources/CommentInliner.php`:
- Around line 142-144: The '_resolvedCommentsLabel' value currently uses
hardcoded English strings; replace them with translatable/pluralized strings
using the project's i18n helper (e.g., use a pluralization function like
trans_choice() or _n() with a "%d Comment/Comments" message and pass
$commentCount) so the label is localized and correctly pluralized; update the
assignment in CommentInliner (the '_resolvedCommentsLabel' entry) to call the
translation helper and format with $commentCount.
In `@src/Resources/PostResolver.php`:
- Around line 317-319: Replace the hard-coded English labels for
'_resolvedCommentsLabel' in PostResolver.php with translatable strings: use your
project's translation helper (e.g., trans_choice() or __()) to generate the
singular/plural label and include the numeric count, so replace the literal "1
Comment" and sprintf('%d Comments', $count) with a translation call that handles
pluralization and interpolation for $count (targeting the
'_resolvedCommentsLabel' array key).
- Around line 332-336: The three hardcoded English labels for the
'_resolvedCommentsTitle' value need to be localized: replace the literal strings
("No Comments", "1 Comment", sprintf('%d Comments', $count)) with calls to your
translation helpers (e.g. use trans_choice or __()/trans() as appropriate) so
pluralization and translations work across locales; update the assignment inside
the same array key '_resolvedCommentsTitle' in PostResolver (where $count is
used) to call the translation helper that handles singular/plural forms and
injects $count into the translated "%d Comments" message.
---
Outside diff comments:
In `@resources/js/visual-editor/blocks/comments-pagination-next/save.tsx`:
- Around line 1-11: The header comment in CommentsPaginationNextSave incorrectly
claims markup is produced server-side from stamped `_resolved*` attributes;
reconcile this with edit.tsx where a resolvedKey '_resolvedPaginationNextLabel'
is referenced and a note says resolved attributes are request-time (not
post-time). Update the comment in CommentsPaginationNextSave (and mirror in
edit.tsx) to clearly state whether pagination blocks receive stamped
`_resolved*` attributes (e.g., '_resolvedPaginationNextLabel') or if labels are
resolved at request-time only, and ensure the description for
CommentsPaginationNextSave and the comment near resolvedKey in edit.tsx
consistently reflect that behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8853013b-133f-497c-9ba6-7f5dc18163a4
📒 Files selected for processing (96)
composer.jsonconfig/visual-editor.phppackages/renderer-parity.jsonpackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-author-avatar.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-author-name.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-content.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-date.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-edit-link.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-reply-link.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comment-template.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comments-pagination-next.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comments-pagination-numbers.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comments-pagination-previous.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comments-pagination.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/comments.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/post-comments-count.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/post-comments-form.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/post-comments-link.blade.phppackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/post-comments-title.blade.phppackages/visual-editor-renderer-blade/src/View/Components/BlocksComponent.phppackages/visual-editor-renderer-react/src/blocks/artisanpack/commentContext.tsxpackages/visual-editor-renderer-react/src/blocks/registerCoreBlocks.tspackages/visual-editor-renderer-vue/src/blocks/artisanpack/commentContext.tspackages/visual-editor-renderer-vue/src/blocks/registerCoreBlocks.tsresources/js/visual-editor/blocks/__tests__/post-comments-family.test.tsresources/js/visual-editor/blocks/_shared/comment-placeholder-edit.tsxresources/js/visual-editor/blocks/_shared/entity-placeholder-edit.tsxresources/js/visual-editor/blocks/comment-author-avatar/edit.tsxresources/js/visual-editor/blocks/comment-author-name/edit.tsxresources/js/visual-editor/blocks/comment-content/edit.tsxresources/js/visual-editor/blocks/comment-date/edit.tsxresources/js/visual-editor/blocks/comment-date/inserter-icon.tsxresources/js/visual-editor/blocks/comment-edit-link/edit.tsxresources/js/visual-editor/blocks/comment-reply-link/edit.tsxresources/js/visual-editor/blocks/comments-pagination-next/block.jsonresources/js/visual-editor/blocks/comments-pagination-next/edit.tsxresources/js/visual-editor/blocks/comments-pagination-next/index.tsresources/js/visual-editor/blocks/comments-pagination-next/inserter-icon.tsxresources/js/visual-editor/blocks/comments-pagination-next/save.tsxresources/js/visual-editor/blocks/comments-pagination-next/transforms.tsresources/js/visual-editor/blocks/comments-pagination-next/upstream-state.jsonresources/js/visual-editor/blocks/comments-pagination-numbers/block.jsonresources/js/visual-editor/blocks/comments-pagination-numbers/edit.tsxresources/js/visual-editor/blocks/comments-pagination-numbers/index.tsresources/js/visual-editor/blocks/comments-pagination-numbers/inserter-icon.tsxresources/js/visual-editor/blocks/comments-pagination-numbers/save.tsxresources/js/visual-editor/blocks/comments-pagination-numbers/transforms.tsresources/js/visual-editor/blocks/comments-pagination-numbers/upstream-state.jsonresources/js/visual-editor/blocks/comments-pagination-previous/block.jsonresources/js/visual-editor/blocks/comments-pagination-previous/edit.tsxresources/js/visual-editor/blocks/comments-pagination-previous/index.tsresources/js/visual-editor/blocks/comments-pagination-previous/inserter-icon.tsxresources/js/visual-editor/blocks/comments-pagination-previous/save.tsxresources/js/visual-editor/blocks/comments-pagination-previous/transforms.tsresources/js/visual-editor/blocks/comments-pagination-previous/upstream-state.jsonresources/js/visual-editor/blocks/comments-pagination/block.jsonresources/js/visual-editor/blocks/comments-pagination/edit.tsxresources/js/visual-editor/blocks/comments-pagination/index.tsresources/js/visual-editor/blocks/comments-pagination/inserter-icon.tsxresources/js/visual-editor/blocks/comments-pagination/save.tsxresources/js/visual-editor/blocks/comments-pagination/transforms.tsresources/js/visual-editor/blocks/comments-pagination/upstream-state.jsonresources/js/visual-editor/blocks/post-comments-count/block.jsonresources/js/visual-editor/blocks/post-comments-count/edit.tsxresources/js/visual-editor/blocks/post-comments-count/index.tsresources/js/visual-editor/blocks/post-comments-count/inserter-icon.tsxresources/js/visual-editor/blocks/post-comments-count/save.tsxresources/js/visual-editor/blocks/post-comments-count/transforms.tsresources/js/visual-editor/blocks/post-comments-count/upstream-state.jsonresources/js/visual-editor/blocks/post-comments-form/block.jsonresources/js/visual-editor/blocks/post-comments-form/edit.tsxresources/js/visual-editor/blocks/post-comments-form/index.tsresources/js/visual-editor/blocks/post-comments-form/inserter-icon.tsxresources/js/visual-editor/blocks/post-comments-form/save.tsxresources/js/visual-editor/blocks/post-comments-form/transforms.tsresources/js/visual-editor/blocks/post-comments-form/upstream-state.jsonresources/js/visual-editor/blocks/post-comments-link/block.jsonresources/js/visual-editor/blocks/post-comments-link/edit.tsxresources/js/visual-editor/blocks/post-comments-link/index.tsresources/js/visual-editor/blocks/post-comments-link/inserter-icon.tsxresources/js/visual-editor/blocks/post-comments-link/save.tsxresources/js/visual-editor/blocks/post-comments-link/transforms.tsresources/js/visual-editor/blocks/post-comments-link/upstream-state.jsonresources/js/visual-editor/blocks/post-comments-title/block.jsonresources/js/visual-editor/blocks/post-comments-title/edit.tsxresources/js/visual-editor/blocks/post-comments-title/index.tsresources/js/visual-editor/blocks/post-comments-title/inserter-icon.tsxresources/js/visual-editor/blocks/post-comments-title/save.tsxresources/js/visual-editor/blocks/post-comments-title/transforms.tsresources/js/visual-editor/blocks/post-comments-title/upstream-state.jsonsrc/Resources/CommentInliner.phpsrc/Resources/PostResolver.phpsrc/VisualEditorServiceProvider.phptests/Unit/VisualEditor/EnabledBlockNamesTest.phptests/Unit/VisualEditor/Resources/CommentInlinerTest.phptests/Unit/VisualEditor/Resources/PostResolverTest.php
- Sanitize comment content at the resolver layer (strip dangerous tags, inline event handlers, and javascript: URLs) so `_resolvedContent` is XSS-safe regardless of which renderer consumes it. - Separate the comments-pagination-numbers current vs. disabled states in the Blade renderer so a non-current page with no URL no longer claims `aria-current="page"` — matches the React / Vue parity. - Localize the comments-family fallback strings through `trans_choice` / `__()` in PostResolver, CommentInliner, and post-comments-title. - Fix grammatical "comment's page link" → "comments page link" in the comments-pagination-next / -previous block.json descriptions. - Add a CommentResolver test covering the new sanitization behavior. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Description
Follow-up to #524 (Pass 1 — merged). Lands the remaining 8 comments-family blocks (post-comments-* + comments-pagination cluster), full renderer parity across Blade / React / Vue for all 16 comments-family blocks, the server-side
CommentInlinerthat expandscomment-templateper resolved comment, the post-context wiring on<x-ve-blocks>, and the editor-side dummy-data UX. Closes #519.Closes: #519
Type of Change
Related Issue
Issue: #519
Predecessor PR (merged): #524
Motivation and Context
Pass 1 (#524) shipped the block manifests +
CommentResolverfor the wrapper + template + 6 per-comment leaves, but the renderers + per-comment loop expansion were deferred. This PR closes the loop so a host theme can dropartisanpack/commentsinto a single-post template and get real comments rendered againstPost::comments.Depends on cms-framework 2.1.0 — that release introduced the
Commentmodel +Post::commentsrelation +comments_count/comments_urlaccessors the resolvers consume. Constraint bumped to^2.0.Changes Made
Block forks — 8 × 7 = 56 frontend files
post-comments-form(server-rendered<form>; null save)post-comments-count,post-comments-link,post-comments-title(per-post display blocks; resolve throughPostResolveragainst the post's counters / URL)comments-pagination(InnerBlocks wrapper; delegating save) +-next/-numbers/-previous(per-page display blocks; render against request-time pagination state)Pagination cluster matches upstream WP block-library 9.43.0 naming (
artisanpack/comments-pagination*, nopost-prefix).Each block:
block.json+edit.tsx+save.tsx+transforms.ts+index.ts+inserter-icon.tsx+upstream-state.json.CommentInliner
New
src/Resources/CommentInliner.php— sibling toQueryInliner. Walks the saved block tree and, for everyartisanpack/commentswrapper:comment-templateonce per resolved comment, stamping each iteration's leaves viaCommentResolver(Pass 1)._resolved*attrs (_resolvedPostId,_resolvedCommentCount,_resolvedCommentsUrl,_resolvedCommentsLabel) on the wrapper, then cascades them to non-template children (post-comments-form, count, title, etc.) so a standalone form inside the wrapper gets the right post id._resolutionError=no-post-contextwhen no post is supplied so the renderer can paint empty without breaking the surrounding layout.Renderer parity — Blade / React / Vue
All 16 comments-family blocks (Pass 1 + Pass 2) now ship with matching renderers across all three engines.
packages/renderer-parity.jsonextended;scripts/verify-renderer-parity.mjsreportsok react/vue/blade: all 111 blocks registered..blade.phppartials underpackages/visual-editor-renderer-blade/resources/views/blocks/artisanpack/packages/visual-editor-renderer-react/src/blocks/artisanpack/commentContext.tsx, registered inregisterCoreBlocks.tspackages/visual-editor-renderer-vue/src/blocks/artisanpack/commentContext.ts, registered inregisterCoreBlocks.tsBlade
<x-ve-blocks>pipelineBlocksComponentnow accepts:postand, when supplied, runsCommentInliner(per-comment expansion) andPostResolver::stampTree(top-level post-* and post-comments-* attribute stamping) on the tree before rendering. The post-context-free render path is unchanged.PostResolver extensions
Extended
SUPPORTED_BLOCKS+ match branches forpost-comments-form/post-comments-count/post-comments-link/post-comments-titleso standalone (non-wrapped) instances still get their_resolved*attrs.post-comments-formgets_resolvedPostIdso the rendered form includes the right hiddenpost_idfield.post-comments-form — accessibility + extensibility
<button type="submit">→<input type="submit">across all three renderers (Blade, React, Vue) for better screen-reader / keyboard behaviorname="submit"deliberately omitted from the input — that attribute shadows the form's.submitDOM property and breaks JS that hooks the formactionconfigurable via stamped_resolvedFormActionattribute +comments.form.actionhooks filter — hosts can redirect submissions to a controller returning redirect-back-with-flash instead of the JSON 201 the cms-framework REST endpoint emitsuseId()/getCurrentInstance().uidfor unique label-for / input-id pairings (multiple forms on one page)Editor placeholders → realistic dummy data
createCommentPlaceholderEdit+createEntityPlaceholderEditgained adummyValueconfig field. Authors editing a template (with no specific post in scope) now see representative content for every comments-family leaf — "Jane Doe", "October 25, 2024", "5 Comments", a Gravatar mystery-person silhouette, sample comment paragraph, "1 2 3" page numbers — rather than dashed-outline labels. Dummy paints only when neither_resolved*nor preview context is available; resolved render is untouched.post-comments-formedit renders a non-interactive form scaffold (every label / input / submit-button state present) so the whole form is styleable in the canvas.Dependency
composer.json:artisanpack-ui/cms-frameworkbumped from^1.1to^2.0. TheCommentmodel +Post::commentsrelation ship in 2.1.0 (cms-framework #151, released 2026-06-02).How Has This Been Tested?
Testing Environment:
Tests Performed:
835 passed (2304 assertions)— +14 from this PR (7 CommentInliner + 7 PostResolver post-comments-* + EnabledBlockNames snapshot extension). No regressions.1770 passed— includes the parametrizedcomments-family.test.ts(36 tests, Pass 1) +post-comments-family.test.ts(32 tests). No regressions.ok react/vue/blade: all 111 blocks registered.localenv and redirects back with a sticky flash banner; the new comment appears inline. Editor canvas (/admin/site-editor→ Single Post template) shows realistic dummy data on every comment-family block.useId+ VuegetCurrentInstance().uid), paginationaria-currentcorrectness, label localization (__()wrappers), distinct inserter icons (avatar / pencil / calendar / etc.), pagination aria-label localization. Final pass: 0 findings.Accessibility Tests Run
aria-labelon pagination nav (translatable),aria-hiddenon decorative asterisks,aria-current="page"only on the actual current page number<input type="submit">(not<button>) per WCAG submit-control conventionpointer-events: noneon the editor-only form scaffold so canvas authors can't accidentally interact with the dummy formTests Added
CommentInlinerTest: 7 testsPostResolverTest: +7 tests for post-comments-* branches +post-comments-formpost-id stamping + artisanpack/* paritypost-comments-family.test.ts: 32 contract tests for the 8 Pass 2 blocks (block.json namespace + textdomain, save shape, bidirectional transforms, wrapper innerBlocks preservation, context wiring)EnabledBlockNamesTest: snapshot updated for all 16 blocksDocumentation
name="submit"gotcha,_resolvedFormActionfilter,_resolutionError=no-post-context, etc.)upstream-state.jsonprovenance written for each new blockPre-Submission Checklist
Summary by CodeRabbit
New Features
Bug Fixes / Security
Tests