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_accordion和os_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




