You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress:如何将基于H2标题的目录实现为Gutenberg自定义块?

适配Gutenberg块的目录生成方案

不需要完全重写现有代码,但要针对Gutenberg块的渲染逻辑做适配,同时修复原代码里的几个小问题,具体调整如下:

核心问题分析

原代码在模板里能正常运行,是因为模板处于文章循环的上下文里,get_the_ID()能稳定拿到当前文章ID;但Gutenberg块的渲染(尤其是编辑器预览场景)是独立执行的,上下文可能丢失,导致get_the_ID()拿不到正确值,另外原代码还有结构和语法bug,比如:

  • 错误的<div">标签(多了引号)
  • sprintf参数数量不匹配(格式串2个占位符,传了4个参数)
  • 没有正确生成列表结构(只有a标签,缺失ul/li)
  • DOM查询逻辑不准确(contains("h2", name())会匹配类似h20的无效标签)

修改后的Gutenberg块实现

1. 注册自定义块

先注册块的基本结构:

function register_custom_toc_block() {
    register_block_type( 'custom/table-of-contents', [
        'render_callback' => 'render_custom_toc_block',
        'attributes'      => [], // 可扩展添加显示标题、层级控制等属性
        'editor_style'    => 'wp-block-library', // 复用编辑器默认样式
    ] );
}
add_action( 'init', 'register_custom_toc_block' );

2. 编写块渲染函数

修复原代码并适配Gutenberg上下文:

function render_custom_toc_block( $attributes, $content, $block ) {
    // 优先从块上下文获取文章ID(编辑器预览场景), fallback到当前文章ID
    $post_id = isset( $block->context['postId'] ) ? $block->context['postId'] : get_the_ID();

    if ( ! $post_id || ! get_post( $post_id ) ) {
        return '<p class="toc-empty">请在文章编辑页面使用此块</p>';
    }

    // 获取并处理文章内容
    $post_content = apply_filters( 'the_content', get_post_field( 'post_content', $post_id ) );
    $post_content = str_replace( ']]>', ']]&gt;', $post_content );

    // DOM解析提取H2标题
    libxml_use_internal_errors( true );
    $dom = new DOMDocument();
    $dom->loadHTML( '<?xml encoding="utf-8" ?>' . $post_content );
    libxml_clear_errors();

    $xpath = new DOMXPath( $dom );
    $headings = $xpath->query( '//h2' ); // 准确匹配H2标签

    if ( ! $headings || $headings->length === 0 ) {
        return '<p class="toc-empty">本文暂无H2标题</p>';
    }

    // 构建目录HTML结构
    $toc_html = '<div class="custom-toc"><h3 class="toc-title">目录</h3><ul class="toc-list">';
    $current_level = 2; // 起始层级为H2

    foreach ( $headings as $heading ) {
        $heading_level = (int) $heading->tagName[1];
        $heading_id = $heading->getAttribute( 'id' );
        
        // 自动生成缺失的标题ID
        if ( empty( $heading_id ) ) {
            $heading_id = sanitize_title( $heading->nodeValue );
        }

        $heading_text = esc_html( $heading->nodeValue );

        // 处理层级嵌套(支持H3扩展)
        while ( $heading_level > $current_level ) {
            $toc_html .= '<ul class="toc-sub-list">';
            $current_level++;
        }
        while ( $heading_level < $current_level ) {
            $toc_html .= '</ul></li>';
            $current_level--;
        }

        $toc_html .= sprintf( '<li class="toc-item"><a href="#%s" class="toc-link">%s</a>', esc_attr( $heading_id ), $heading_text );
    }

    // 关闭剩余的嵌套列表标签
    while ( $current_level > 2 ) {
        $toc_html .= '</ul></li>';
        $current_level--;
    }

    $toc_html .= '</li></ul></div>';

    return $toc_html;
}

关键适配点

  • 上下文适配:通过$block->context['postId']获取编辑器内的当前文章ID,解决块渲染时的上下文丢失问题;
  • 输出方式调整:Gutenberg块的渲染函数需要返回HTML字符串,而非直接echo;
  • 结构修复:正确生成ul/li层级结构,修复原代码的标签错误;
  • 容错处理:添加文章不存在、无H2标题等场景的提示;
  • ID补全:自动为无ID的H2标题生成唯一ID,保证锚点跳转有效。

内容的提问来源于stack exchange,提问作者Cray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 13:55:16