这两天在研究 Typecho 文章内容部分展示问题(后续可能会运用到 ArmxMod for Typecho 主题),由于在进行根据字数裁切时,PHP 并不会去判断到底裁的位置有没有问题,很有可能就把 HTML 标签裁了,还裁的不完全,就造成页面在展示的时候,布局混乱(目前这个问题在大家开发主题时做文章摘要比较容易出现),故在完成裁切后,应当对输出进行修复,补齐标签缺失的部分。
问题
比如正常的 HTML 代码如下:
<p>这两天在研究 Typecho 文章内容部分展示问题(后续可能会运用到<a href="https://vircloud.net/default/change-theme.html">ArmxMod for Typecho</a> 主题</p>
经过裁切后,输出的 HTML 如下:
<p>这两天在研究 Typecho 文章内容部分展示问题(后续可能会运用到<a href="https://vircloud.net/default/change-theme.html">
显然裁切后的 HTML 是不完整的,浏览器在显示时输出的页面完全变样了。
修复
function fixPost($post){
$post = preg_replace('/<[^>]*$/','',$post);
preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $post, $result);
if($result){
$opentags = $result[1];
preg_match_all('#</([a-z]+)>#iU', $post, $result);
if($result){
$closetags = $result[1];
$len_opened = count($opentags);
if (count($closetags) == $len_opened) {
return $post; //没有未关闭标签
}
$opentags = array_reverse($opentags);
$sc = array('br','input','img','hr','meta','link'); //跳过这些标签
for ($i=0; $i < $len_opened; $i++) {
$ot = strtolower($opentags[$i]);
if (!in_array($opentags[$i], $closetags) && !in_array($ot,$sc)) {
$post .= '</'.$opentags[$i].'>'; //补齐标签
}
else {
unset($closetags[array_search($opentags[$i], $closetags)]);
}
}
}
}
return $post;
}
$post='<p>这两天在研究 Typecho 文章内容部分展示问题(后续可能会运用到<a href="https://vircloud.net/default/change-theme.html">';
echo fixPost($post);
结果
经过修复后,输出为:
<p>这两天在研究 Typecho 文章内容部分展示问题(后续可能会运用到<a href="https://vircloud.net/default/change-theme.html"></a></p>
可以看到标签已经都成功补全闭合了。
需要注意的是,文字缺失部分不会补齐,只会补齐标签,而且如果本身标签就是不完整的(无法判断到底是不是标签),那么也会被忽略,比如如果裁切后输出是:
<p>这两天在研究 Typecho 文章内容部分展示问题(后续可能会运用到<a href="