Skip to content

Refactor Table of Contents server rendering#80098

Draft
getdave wants to merge 7 commits into
trunkfrom
toc-server-render-refactor
Draft

Refactor Table of Contents server rendering#80098
getdave wants to merge 7 commits into
trunkfrom
toc-server-render-refactor

Conversation

@getdave

@getdave getdave commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What

Refactors the front-end/server rendering for the Table of Contents block so it builds its entries from the current post content at render time.

The renderer now uses the core/post-content boundary to decide which headings are eligible when the block is placed in a template, and it supports headings from core Heading blocks, synced patterns, and template parts within that boundary.

Why

The saved Table of Contents markup can become stale when post headings change. Server rendering should reflect the current front-end post content without relying on editor-side heading observation or changing the editor implementation.

The block also needs predictable template behavior: when placed in a template, it should render from the current post’s content only if that template contains a core/post-content block. It should not scan unrelated template headings or arbitrary site template content.

How

  • Rebuild the Table of Contents markup in PHP from the current post content.
  • Use WP_Block_Processor to walk block content and resolve supported nested content sources.
  • Use WP_HTML_Tag_Processor to read heading text and existing heading anchors from rendered Heading block HTML.
  • Preserve existing block attributes such as ariaLabel, ordered, maxLevel, and onlyIncludeCurrentPage.
  • Keep editor implementation files unchanged.
  • Add focused PHPUnit and e2e coverage for server-rendered behavior, including template placement and post-content boundary cases.

Testing Instructions

  1. Start the test environment:

    npm run wp-env-test start
  2. Run the focused e2e coverage:

    npm run test:e2e -- test/e2e/specs/editor/blocks/table-of-contents-server-rendering.spec.js
  3. Run the focused PHPUnit coverage:

    npm run wp-env-test -- run cli --env-cwd=wp-content/plugins/gutenberg -- vendor/bin/phpunit --filter Tests_Blocks_Render_Table_Of_Contents
  4. Optional manual check:

    • Create a post with a Table of Contents block and multiple Heading blocks.
    • Confirm the front end renders current headings, not stale saved TOC entries.
    • Add the Table of Contents block to a Single template that contains core/post-content.
    • Confirm the front end renders the current post headings and does not include headings outside core/post-content.
    • Add the block to a template without core/post-content.
    • Confirm no Table of Contents is rendered.

@getdave getdave self-assigned this Jul 10, 2026
@github-actions github-actions Bot added the [Package] Block library /packages/block-library label Jul 10, 2026
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

Size Change: -9 B (0%)

Total Size: 7.69 MB

📦 View Changed
Filename Size Change
build/scripts/block-library/index.min.js 347 kB -9 B (0%)

compressed-size-action

@getdave getdave requested a review from Copilot July 10, 2026 11:17
@github-actions

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Block library.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors core/table-of-contents so its front-end output is rebuilt on the server from the current post content at render time, avoiding stale saved TOC markup and enforcing predictable behavior when the block is used in templates.

Changes:

  • Rebuild TOC entries in PHP by scanning the current post’s block content (including synced patterns and template parts) and extracting heading text/anchors from rendered heading HTML.
  • Gate template rendering so TOC only renders for singular views when the active template contains a core/post-content block (including via nested template parts).
  • Add dedicated PHPUnit and Playwright e2e coverage for server-rendered behavior, including pagination and template boundary rules.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/block-library/src/table-of-contents/index.php Implements server-side heading resolution and TOC HTML generation with template/post-content boundary checks.
phpunit/blocks/render-block-table-of-contents-test.php Adds PHPUnit coverage for synced patterns, template parts, pagination, and template boundary detection.
test/e2e/specs/editor/blocks/table-of-contents-server-rendering.spec.js Adds e2e coverage for server-rendered TOC behavior across post content and template scenarios.

Comment on lines +17 to +21
public function tear_down() {
unset( $GLOBALS['_wp_current_template_content'] );
wp_reset_postdata();
parent::tear_down();
}
@github-actions

Copy link
Copy Markdown

Flaky tests detected in 8d00c0d.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/29088974141
📝 Reported issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Block library /packages/block-library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants