纯代码给wordpress文章添加一个文章目录

背景

很早之前就想写目录了,然后因为懒就一直拖,渐渐忘了,今天突然想起,于是就有了这篇文章

百度百科文章的右边有一个目录,可以快速跳到对应的文章位置

然后因为懒就想去网上copy一段代码,结果发现很多代码要么是无法执行,要么是太长了,逻辑混乱

好,那我就自己写一个

比如现在有下面这样一个目录:

  • h2
  • h3
  • h4
  • h5
  • h2

处理一下应该是这样的:

  • h2
    • h3
      • h4
        • h5
  • h2

换成html代码可能更直观

  • <li>h2</li>
    • <ul>
      • <li>h3</li>
        • <ul>
          • ……
        • </ul>
    • </ul>
  • </li>

有点像先进先出,于是我就想到用栈(stack)去解决

实现

首先,我们要先把h标签过滤出来

注:这里处理的是纯标签,如<h2>123</h2>这种情况,如果标签被设置过锚点之类的需要自己另外判断,这里不做考虑

preg_match_all( "/<h([1-6]).*?>(.*?)<\/h(\\1)>/", $content, $matches );

然后我们用stack来处理这些标签

$tot = 0;
		
$stack = array();
for($i = 0; $i < count( $matches[1] ); $i++) {
	while( count( $stack ) - 1 >= 0 && $stack[count( $stack ) - 1] >= $matches[1][$i] ) {
		array_pop( $stack );
		echo "</ul>\r\n";
	}
	echo "<li><a href=\"#h-" . $i . "\">" . $matches[2][$i] . "</a></li>\r\n";
	if( $i < count( $matches[1] ) - 1 && $matches[1][$i + 1] > $matches[1][$i] ) {
		array_push( $stack, $matches[1][$i] );
		echo "<ul>\r\n";
	}
}

最后再给h标签添加上id:(用在输出文章内容上)

echo preg_replace_callback(
			"/<h([1-6])(.*?)>(.*?)<\/h(\\1)>/", 
			function ( $matches ) {
				global $tot;
				return "<h" . $matches[1] ." id=\"h-". $tot++ ."\" " . $matches[2] .">" . $matches[3] ."</h" . $matches[1] .">";
			}, 
			$content
		);

所以最终的完整代码因该是这样的:

<?php
$content = get_the_content();
$tot = 0;

preg_match_all( "/<h([1-6]).*?>(.*?)<\/h(\\1)>/", $content, $matches );

$stack = array();
for($i = 0; $i < count( $matches[1] ); $i++) {
	while( count( $stack ) - 1 >= 0 && $stack[count( $stack ) - 1] >= $matches[1][$i] ) {
		array_pop( $stack );
		echo "</ul>\r\n";
	}
	echo "<li><a href=\"#h-" . $i . "\">" . $matches[2][$i] . "</a></li>\r\n";
	if( $i < count( $matches[1] ) - 1 && $matches[1][$i + 1] > $matches[1][$i] ) {
		array_push( $stack, $matches[1][$i] );
		echo "<ul>\r\n";
	}
}

......

echo preg_replace_callback(
	"/<h([1-6])(.*?)>(.*?)<\/h(\\1)>/", 
	function ( $matches ) {
		global $tot;
		return "<h" . $matches[1] ." id=\"h-". $tot++ ."\" " . $matches[2] .">" . $matches[3] ."</h" . $matches[1] .">";
	}, 
	$content
);

?>

最后再套到<ul></ul>里,添加一些css美化,目录就做好了

自己测下来没有问题,若有bug,欢迎在下方告诉我,我会去修改的

本站遵循「CC BY 4.0」创作共享协议,转载请注明出处