You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WordPress自定义折叠面板短代码:HTML禁自动换行但内容需换行

解决WordPress短代码空格导致的自动换行/段落标签问题

我太懂这种困扰了——WordPress自带的wpautop函数虽然方便处理普通内容的排版,但碰到短代码尤其是嵌套短代码时,只要标签之间有空格或换行,就会自动套上<p><br>,直接把布局搞崩。而且咱们还不能全局关掉它,不然正常内容的排版就废了。别慌,咱们只针对你的折叠面板插件来解决这个问题,完全不影响其他功能。

问题根源拆解

WordPress默认是先运行wpautop处理所有内容的换行/空格,再解析短代码。这就导致短代码标签(比如[os_accordion])前后的空格会被转换成<p>[os_accordion]</p>或者<br>[os_accordion],等短代码解析成HTML后,这些多余的标签就留在页面里破坏布局了。

分步解决方案

咱们从三个方面调整代码,精准控制自动排版的范围:

1. 调整短代码解析优先级,让它跑在wpautop前面

先让WordPress先解析你的短代码,再处理自动排版,这样wpautop就只会处理短代码内部的内容,不会碰短代码标签本身。在你的插件代码里添加以下内容:

// 调整短代码优先级,确保在wpautop之前执行
remove_shortcode('os_accordion');
add_shortcode('os_accordion', 'function_accordion', 9);

remove_shortcode('os_spoiler');
add_shortcode('os_spoiler', 'function_spoiler', 9);

// 确保wpautop在短代码解析后运行
add_filter('the_content', 'wpautop', 10);
add_filter('the_content', 'shortcode_unautop', 11);

2. 让短代码内部内容保留自动排版

现在短代码内部的内容(比如os_spoiler里的文字)需要正常生成段落,所以在function_spoiler里主动对内容应用wpautop

function function_spoiler($atts, $content = null){
    // 设置默认属性
    $values = shortcode_atts(
        array(
            'title' => '',
        ), $atts );
    
    // 对内部内容应用自动排版,生成正确的<p>和<br>
    $content = wpautop(trim($content));
    
    // 输出缓冲生成HTML
    ob_start(); ?>
    <div class="toggle"><?php echo esc_attr($values['title']); ?></div>
    <div class="content"><?php echo $content; ?></div>
    <?php return ob_get_clean();
}

这里加了trim($content)是为了去掉内容前后的多余空格,避免生成不必要的空段落。

3. 精准清理残留的多余标签(保险措施)

万一还有漏网的<p><br>套在短代码标签外面,咱们加一个专门针对你的短代码的清理函数,只处理os_accordionos_spoiler相关的标签:

function os_accordion_cleanup($content) {
    // 清理短代码周围的<p>标签
    $content = preg_replace('/<p>\s*\[os_accordion\]\s*<\/p>/', '[os_accordion]', $content);
    $content = preg_replace('/<p>\s*\[\/os_accordion\]\s*<\/p>/', '[/os_accordion]', $content);
    $content = preg_replace('/<p>\s*\[os_spoiler(.*?)\]\s*<\/p>/', '[os_spoiler$1]', $content);
    $content = preg_replace('/<p>\s*\[\/os_spoiler\]\s*<\/p>/', '[/os_spoiler]', $content);
    
    // 清理短代码前后的<br>标签
    $content = preg_replace('/<br\s*\/?>\s*\[os_accordion\]/', '[os_accordion]', $content);
    $content = preg_replace('/\[\/os_accordion\]\s*<br\s*\/?>/', '[/os_accordion]', $content);
    $content = preg_replace('/<br\s*\/?>\s*\[os_spoiler(.*?)\]/', '[os_spoiler$1]', $content);
    $content = preg_replace('/\[\/os_spoiler\]\s*<br\s*\/?>/', '[/os_spoiler]', $content);
    
    return $content;
}
add_filter('the_content', 'os_accordion_cleanup', 12);

替换后的完整代码

把你原来的插件代码替换成下面的版本就行:

// 调整短代码优先级,确保在wpautop之前执行
remove_shortcode('os_accordion');
add_shortcode('os_accordion', 'function_accordion', 9);

remove_shortcode('os_spoiler');
add_shortcode('os_spoiler', 'function_spoiler', 9);

// 确保wpautop在短代码解析后运行
add_filter('the_content', 'wpautop', 10);
add_filter('the_content', 'shortcode_unautop', 11);

// 清理短代码周围的多余标签
function os_accordion_cleanup($content) {
    // 清理短代码周围的<p>标签
    $content = preg_replace('/<p>\s*\[os_accordion\]\s*<\/p>/', '[os_accordion]', $content);
    $content = preg_replace('/<p>\s*\[\/os_accordion\]\s*<\/p>/', '[/os_accordion]', $content);
    $content = preg_replace('/<p>\s*\[os_spoiler(.*?)\]\s*<\/p>/', '[os_spoiler$1]', $content);
    $content = preg_replace('/<p>\s*\[\/os_spoiler\]\s*<\/p>/', '[/os_spoiler]', $content);
    
    // 清理短代码前后的<br>标签
    $content = preg_replace('/<br\s*\/?>\s*\[os_accordion\]/', '[os_accordion]', $content);
    $content = preg_replace('/\[\/os_accordion\]\s*<br\s*\/?>/', '[/os_accordion]', $content);
    $content = preg_replace('/<br\s*\/?>\s*\[os_spoiler(.*?)\]/', '[os_spoiler$1]', $content);
    $content = preg_replace('/\[\/os_spoiler\]\s*<br\s*\/?>/', '[/os_spoiler]', $content);
    
    return $content;
}
add_filter('the_content', 'os_accordion_cleanup', 12);

// 外层折叠面板短代码
function function_accordion($atts, $content = null){
    $html = '<div class="accordion">'.do_shortcode($content).'</div>';
    return $html;
}

// 内层折叠项短代码
function function_spoiler($atts, $content = null){
    // 设置默认属性
    $values = shortcode_atts(
        array(
            'title' => '',
        ), $atts );
    
    // 对内部内容应用自动排版,生成正确的<p>和<br>
    $content = wpautop(trim($content));
    
    // 输出缓冲生成HTML
    ob_start(); ?>
    <div class="toggle"><?php echo esc_attr($values['title']); ?></div>
    <div class="content"><?php echo $content; ?></div>
    <?php return ob_get_clean();
}

测试效果

现在不管你用哪种写法:

  • 紧凑版:[os_accordion][os_spoiler title="Title"]Content with some breaks.[/os_spoiler][/os_accordion]
  • 带空格/换行版:
[os_accordion] 
[os_spoiler title="Title"] 
Content with some breaks. 
[/os_spoiler] 
[/os_accordion]

都会生成干净的HTML,折叠面板布局正常,同时内部内容会自动生成正确的段落标签,不用手动加<p>

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

火山引擎 最新活动