如何去除WordPress正文img标签外的p标签?
WordPress作为一款方便大众的CMS,内容编辑功能有很多防呆设计。
典型例子就是,如果你在“可视化”模式下编辑文章,那么每次回车会对应生成“文本模式”下的两个换行,而在生成正文的时候,两个换行会对应生成一个<p>标签。而大多数人都是用“可视化”模式编辑的,因此就会遇到这样的问题:
问题描述
在插入图片或者视频等媒体内容的时候,媒体内容会带上一个<p>标签。举例来说,如果要插入一个图片,那么在文章页的HTML代码中……
图片会是这样的:
<p><img src= "图片链接"></p>
视频可能是这样的:
<p><iframe src= "资源链接"></p>
而普通文字是这样的:
<p>正文文本</p>
而众所周知,中国人的阅读习惯是首行缩进,也就是每个段落的第一行会缩进两个字符。而在WordPress里面实现的方式无非以下几种:
1.通过修改格式按钮,添加首行缩进的样式。对每个需要首行缩进的段落进行设置。
2.编辑文字时,给每个需要首行缩进的段落添加两个全角空格(<p>标签最开始的所有半角空格会被程序删除,必须用全角)。
3.通过function或者CSS,对特定<p>标签进行设置,使得<p>标签自带text-indent:2em(首行缩进两个字符的样式)属性。
对于更新频率较高的网站来说,方法1和方法2显然过于麻烦,本站尽管每周只更新5篇左右的设计文章,但也不能接受这样的方法。因此我们就选择方法2或者方法3。
但是需要考虑到这样的问题:如果修改<p>标签,那么正文中的内容会变成这样(使用CSS的方法style属性不会出现在这里,但道理是一样的):
<p style="text-indent:2em"><img src= "图片链接"></p>
<p style="text-indent:2em"><iframe src= "资源链接"></p>
<p style="text-indent:2em">正文文本</p>
在这种情况下,<img>内的图片和<iframe>内的视频都会被首行缩进,而最佳观赏效果必然是图片和视频居中。然而,text-indent属性不可为负,因此无法通过给<img>等标签添加样式来抵消。
解决方案 
为此,我们可以通过想办法消除<img>标签周围的<p>标签来解决这个问题。在进行这个工作之前,我们先看看网上的一段代码,来自秋叶网络博客:
//去掉图片外围标签p
function img_unautop($pee) {
$pee = preg_replace('/<p.*?>\\s*?(<a .*?><img.*?><\\/a>|<img.*?>)?\\s*<\\/p>/s', '<div class="figure">$1</div>', $pee);
return $pee;
}
add_filter( 'the_content', 'img_unautop', 30 );
将这段代码加入function.php可发挥作用。方法为点击后台的外观→编辑,右侧找到functions.php,在最下方添加完整代码。
这段代码和笔者的意图相同,博主选择使用<div>标签替换掉<img>标签。这种做法有几个好处,主要在于<div>下的元素更好控制。然而这个方法中的正则表达式是有问题的,容易出现把正文内容直接换没的情况。
因此,这里给出升级版代码,同样写在function.php内,科直接去除<img>和<iframe>外的<p>标签:
//去除img和iframe外的p标签
function filter_ptags_on_images($content) {
$content = preg_replace('/<p>\s*(<a .*>)?\s*(<img .* \/>)\s*(<\/a>)?\s*<\/p>/iU', '\1\2\3', $content);
return preg_replace('/<p>\s*(<iframe .*>*.<\/iframe>)\s*<\/p>/iU', '\1', $content);
}
add_filter('acf_the_content', 'filter_ptags_on_images');
add_filter('the_content', 'filter_ptags_on_images');
注意,如果你使用了可以修改<img>标签的插件(比如自动加如标题到alt内),可能会导致本function无效,此时需要提升优先级,采用以下代码:
//去除img和iframe外的p标签
function filter_ptags_on_images($content) {
$content = preg_replace('/<p>\s*(<a .*>)?\s*(<img .* \/>)\s*(<\/a>)?\s*<\/p>/iU', '\1\2\3', $content);
return preg_replace('/<p>\s*(<iframe .*>*.<\/iframe>)\s*<\/p>/iU', '\1', $content);
}
add_filter('acf_the_content', 'filter_ptags_on_images', 9999);
add_filter('the_content', 'filter_ptags_on_images', 9999);
除了采用上述方式,还可以用javascript实现。你可以在对应的single.php或page.php内加入下述代码实现同样的效果:
<script type="text/javascript">
jQuery(document).ready(function($){
$('p > img').unwrap();
});
</script>
另外,如果你经常使用embed等标签插入媒体,可以在上述代码内相同位置加一行来实现替换。
首行缩进
在完成上述工作后,点开任何一篇带图文章刷新缓存,你应该发现<img>标签和<iframe>标签周围的<p>标签已经没有了,此时就可以针对正文内容来为每个<p>标签插入首行缩进的属性。
方法1:在function.php内插入代码:
//首行缩进
function kami_text_indent($text){
$return = str_replace('<p', '<p style="text-indent:2em;"',$text);
return $return;
}
add_filter('the_content',kami_text_indent');
这个方法的好处在于和上述的第一种方法可以共同使用,而且不需要找到对应的class即可快速实现。
方法2:CSS实现:
CSS实现首先要找到正文的class,你可以通过分析页面源代码查看。一般来说class是下者之一(根据主题可能不同):
.post .content p{}
.post .entry p{}
article p{}
你可以将上述的内容替换到下面的代码中,试试哪个对你的主题有效。注意,如果对正文有效,请注意其他地方的字体会不会受到影响。
笔者选择了直接修改single.php文件,为文章页增加了特殊的class(因为并不希望让“页面”类型的内页首行缩进),这样针对性更强。
确定好层级后,将下述代码增加到“自定义CSS”或者网站的stlye.css内(后者也可以直接找到对应的代码添加内容)。
.post .content p {
text-indent:2em;
}
以上完成后,我们就实现了单独对文字内容进行首行缩进而不影响图片。如果在操作中遇到问题,欢迎微信讨论。