Skip to content

Extract Table of Contents heading utility class#80372

Open
getdave wants to merge 2 commits into
trunkfrom
toc-rendering-utility-class
Open

Extract Table of Contents heading utility class#80372
getdave wants to merge 2 commits into
trunkfrom
toc-rendering-utility-class

Conversation

@getdave

@getdave getdave commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What

Related: #42229

Extracts the PHP heading-building logic for the Table of Contents block into an internal WP_Table_Of_Contents utility class.

Why

This keeps the block render callback focused on markup rendering while separating the heading resolution algorithm into a smaller internal implementation detail. That should make later Table of Contents stabilization work easier to review and reduce ambiguity between implementation details and possible future extension points.

The public class method is named get_headings_from_post() rather than a more generic get_headings() so the input source is explicit. Today the front-end render callback resolves headings from the current saved post. In future work, the editor may need to call the same algorithm over REST to build its JSX-rendered preview from a block list, including unsaved editor state. Keeping the post-based entry point explicit leaves room for a future companion such as get_headings_from_blocks() that returns the same heading data shape without overloading one method with multiple input types.

How

The existing render callback remains the public callback for the block. It delegates post-based heading collection to the internal class, while list markup and aria-label handling stay in the block render file. The Gutenberg PHP build config is updated so the new class is suffixed correctly in plugin builds.

The class keeps the algorithm details private and exposes only the narrow post-based entry point needed by the current render callback.

Testing Instructions

  1. Enable experimental blocks.
  2. Add a Table of Contents block to a post with headings.
  3. Confirm the block behaves as it does on trunk, including heading updates, heading level limits, ordered/unordered list display, links, and front-end rendering.
  4. Confirm the block renders nothing when there are no headings.

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

Copy link
Copy Markdown

Size Change: 0 B

Total Size: 7.72 MB

compressed-size-action

@getdave
getdave requested a review from scruffian July 16, 2026 18:00
@getdave getdave added [Type] Task Issues or PRs that have been broken down into an individual action to take [Block] Table of contents (experimental) Affects the Table of contents Block labels Jul 16, 2026
@getdave
getdave requested a review from Copilot July 16, 2026 18:02
@getdave
getdave marked this pull request as ready for review July 16, 2026 18:02
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: getdave <get_dave@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

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 the Table of Contents block’s PHP heading-resolution logic into a dedicated internal WP_Table_Of_Contents utility class, keeping the render callback focused on markup output while preserving existing behavior (pagination-aware links, max heading level, etc.).

Changes:

  • Added WP_Table_Of_Contents internal class to encapsulate heading collection from a WP_Post.
  • Updated the Table of Contents block render callback to delegate heading extraction to the new class.
  • Updated the block-library build configuration to suffix the new class correctly in plugin builds.

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 Delegates heading collection to WP_Table_Of_Contents and adds a require_once for the new class file.
packages/block-library/src/table-of-contents/class-wp-table-of-contents.php Introduces WP_Table_Of_Contents with the extracted heading/pagination/link resolution logic.
packages/block-library/package.json Adds WP_Table_Of_Contents to suffixClasses for build-time class suffixing.

* The Heading block's default level when no `level` attribute is saved.
*/
const BLOCK_CORE_TABLE_OF_CONTENTS_DEFAULT_HEADING_LEVEL = 2;
require_once __DIR__ . '/table-of-contents/class-wp-table-of-contents.php';

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@copilot This is probably getting confused about the build process and how to maps files.

The real question is whether the class should be required here or in lib/. What's the precedent for the Navigation Fallback classes?

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.

This should stay with the block, not move into lib/. In Gutenberg the plugin loads one flattened PHP entry file per block from lib/blocks.php, and block-local helpers are expected to be pulled in from that entry point. The Navigation Fallback precedent is different because WP_Navigation_Fallback lives in Core wp-includes and is loaded centrally from wp-settings.php since it’s used outside the block render path too (for example the REST controller and filters).

@getdave
getdave force-pushed the toc-rendering-utility-class branch 2 times, most recently from df9b8a9 to 85a31ed Compare July 16, 2026 18:11
@getdave
getdave requested review from MaggieCabrera and jeryj July 16, 2026 18:44
@github-actions

Copy link
Copy Markdown

Flaky tests detected in 85a31ed.
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/29522954905
📝 Reported issues:

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

Labels

[Block] Table of contents (experimental) Affects the Table of contents Block [Package] Block library /packages/block-library [Type] Task Issues or PRs that have been broken down into an individual action to take

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants