给WordPress文章添加自动目录(免插件)

在写文章的时候咱为了结构更清晰,通常会添加h2-h6标签来展示段落标题,同时也提醒网络蜘蛛这些是内文小标题,是文章的重点。特别是当WordPress文章较长时,有一个自动索引的目录能有效帮助访客快速了解内容结构,会大大提高读者的阅读体验。

给WordPress文章添加自动目录的方法非常多,官方库里边也有很多相关的目录插件,比如知名的LuckyWP Table of Contents、Heroic Table of Contents、Rich Table of Contents等,它们主体功能差不多,文件越大的越贵的自然是功能更完善,小细节更好,但副作用也很明显,它们配置麻烦且会加重主机负担影响页面加载速度。

此前有段时间我特想给WordPress添加一个文章目录,后来因为更新较少就放下了。正好最近在瞎折腾,也看了不少教程,最后发现微言微语这一篇相当良心,该方案代码结构清晰注释多,操作步骤明了,作为技术小白的我一下就折腾成功了。为了给更多的人看到,特地把这篇纯代码实现WordPress多级文章目录索引转载过来,也算作是我的一个备忘录吧。

本方案代码量少,可自定义程度也比较高,我在原基础上稍微调整了下CSS,具体的实现效果看本页,根据喜好你也可以修改CSS把目录嵌入进正文中展示,后面本站可能会那样做,届时再把CSS贴出来。其实,我的理想方案是把文章目录嵌入到边栏小工具中,并能在文章编辑时开关控制…这是后话了。

WordPress构建文章多级目录索引

将以下这段代码加载进function.php循环中,通过代码中注释可以知道文章目录是获取h2-h6的标题,同时h标签的个数大于2才生效,也就是文章中要有3个及以上才展示,该数量可以自定义修改。

这段使用了两个函数:buildDirectory 和 article_index。article_index 函数是一个 WordPress 的过滤器函数,用于在文章内容中自动生成目录。buildDirectory 函数则是用来构建目录的核心逻辑。

根据代码,article_index 函数首先使用正则表达式匹配文章内容中的标题,然后根据匹配到的标题内容和标题级别调用 buildDirectory 函数来构建目录。最后,将生成的目录插入到文章内容中,并返回处理后的内容。这段代码有个小Bug,即当第一个H标签比后面的小时,目录可能无法正常加载…当然这也提醒我们:写作要规范~

// 构建文章多级目录索引
function buildDirectory($titleIndexArr, $titleContentArr, &$index, &$html)
{
    $size = sizeof($titleIndexArr);
    $flag = $index == 0;
    $html .= $flag ? '<ol id="index-ol">' : '<ul id="index-ul">';
    while ($index < $size) {
        $title = trim(strip_tags($titleContentArr[$index])); // 标题内容
        $h = $titleIndexArr[$index]; // 几级标题
        $html .= '<li><a href="#title-' . $index . '" title="' . $title . '">' . $title . "</a></li>";
        if ($index == $size - 1) { //最后一个
            $index++;
            break;
        }
        $next_h = $titleIndexArr[++$index]; // 下个标题是几级标题
        if ($h < $next_h) { // 子标题递归
            buildDirectory($titleIndexArr, $titleContentArr, $index, $html);
            if ($index >= $size || $h > $titleIndexArr[$index]) {
                break;
            }
        } else if ($h > $next_h) {
            break;
        }
    }
    $html .= $flag ? '</ol>' : '</ul>';
}
function article_index($content)
{
    $html="";
    $matches = array();
    // 当前设置 [2-6]即 h2 到 h6 可以自己修改下面正则
    $r="/<h([2-6])(.*?)>(.*?)<\/h[2-6]>/is";
    // preg_match_all 函数用于执行一个全局正则表达式匹配。$r=正则,$content=文章内容,$matches=作为输出参数输出所有匹配结果
    preg_match_all($r, $content, $matches);
    $num_match = count($matches[0]);
    // 用于文章页,同时h标签个数大于2个才生效
    if ( is_single() && ($num_match > 2) ) {
        foreach ($matches[1] as $key => $value) {
            // strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签
            $title = trim(strip_tags($matches[3][$key])); //文章标题
            // 文章原标题添加锚点
            $content = str_replace($matches[0][$key], '<h' . $value . ' id="title-' . $key . '"' . $matches[2][$key] . '>' . $title . '</h' . $value . '>', $content);
        }
        $titleIndexArr = $matches[1];
        $titleContentArr = $matches[3];
        $index = 0;
        $html .= "\n".'<div id="article-index-show">目 录</div><div id="article-index"><div id="article-index-top"><strong>文章目录</strong><span id="article-index-hide">隐藏</span></div>';
        buildDirectory($titleIndexArr, $titleContentArr, $index, $html);
        $html .= '</div>'."\n";
    }
    return $html. $content;
}
add_filter('the_content', 'article_index');

WordPress文章目录的CSS样式表

以下这段样式代码中包含了上述WordPress文章自动目录的一些样式定义,如索引框的位置、大小、背景颜色等。同时还包括了显示和隐藏文章目录的按钮样式。另外,这是我第一次用box-shadow: 0 0 5px rgba(0,0,0,.4);这个参数,它能让内容产生阴影,可以给予页面更多灵活性,还挺好玩的~

#article-index {
	position: fixed;
	top: 50%;
	transform: translateY(-50%);
	left: 0;
	width: auto;
	max-height: 76%;
	padding: 0 10px;
	font-size: 14px;
	border-radius: 0 6px 6px 0;
	background-color: #fff;
	box-shadow: 0 0 5px rgba(0, 0, 0, .4);
	overflow: auto;
	z-index: 99;
	display: none;
}

#article-index-top {
	position: sticky;
	top: 0;
	z-index: 92;
	background: #fff;
}

#article-index strong {
	display: block;
	font-size: 16px;
	padding: 10px 0 12px 5px;
}

#index-ol {
	list-style: none;
	font-size: 18px;
}

#index-ol ul {
	font-size: 15px;
}

#index-ol li {
	padding: 0;
	margin-left: 18px;
	line-height: 24px;
	position: relative;
	list-style-position: inherit;
	word-break: break-all;
}

#index-ul {
	list-style: revert-layer;
	margin: 0;
	padding: 4px 0px 6px 36px;
}

#index-ul li:before {
	display: none;
}

#article-index-show {
	position: fixed;
	top: 50%;
	transform: translateY(-50%);
	left: 0;
	display: block;
	width: 50px;
	height: 36px;
	line-height: 36px;
	text-align: center;
	font-size: 14px;
	/* border-radius: 0 36px 36px 0; */
	color: #fff;
	background-color: #cc3333;
	cursor: pointer;
}

#article-index-hide {
	position: absolute;
	right: 0;
	top: 5px;
	display: block;
	width: 32px;
	height: 32px;
	line-height: 32px;
	text-align: center;
	font-size: 12px;
	border-radius: 100%;
	background-color: #eeeeee;
	cursor: pointer;
}

#article-index-hide:hover {
	color: #fff;
	background-color: #cc3333;
}

以上这个样式是我这里正在使用的效果,以下这段CSS是上面这段的变体,它让代码默认展开悬浮在正文旁边(细节还需要自己改一些),如图所示:

给WordPress文章添加自动目录(免插件)
给WordPress文章添加自动目录(免插件)
#article-index {
    position: fixed;
    top: 30%;
    transform: translateY(-20%);
    margin-left: -240px;
    width: 224px;
    max-height: 100%;
    padding: 0 10px;
    font-size: 14px;
    border-radius: 6px;
    background-color: #fff;
    box-shadow: 0 0 5px rgba(0, 0, 0, .4);
    overflow: auto;
    z-index: 99;
    display: block;
}

#article-index strong {
    display: block;
    font-size: 16px;
    padding: 10px 0 16px 0;
}

#index-ol {
    list-style: square;
    text-wrap: 
wrap;
}

#index-ol a {
    color: #555;
}

#index-ol li {
    list-style: none;
    padding: 0;
    margin-left: -50px;
    line-height: 24px;
    position: relative;
    list-style-position: inherit;
    word-break: break-all;
}

#index-ul {
    list-style: circle;
    margin: 0;
    padding: 5px 0 5px 8px;
}

#index-ul li:before {
    display: none;
}

#article-index-show {
    position: fixed;
    top: 31%;
    transform: translateY(-50%);
    margin-left: -240px;
    display: block;
    width: 200px;
    height: 36px;
    line-height: 36px;
    text-align: center;
    font-size: 14px;
    border-radius: 36px 36px 36px 36px;
    color: #fff;
    background-color: #59f;
    cursor: pointer;
}

#article-index-hide {
    position: absolute;
    right: 5px;
    top: 5px;
    display: block;
    color: #fff;
    width: 32px;
    height: 32px;
    line-height: 32px;
    text-align: center;
    font-size: 12px;
    border-radius: 100%;
    background-color: #59f;
    cursor: pointer;
}

#article-index-hide:hover {
    color: #fff;
    background-color: #0088dd;
}

WordPress文章自动目录所需要的JS代码

根据上面的主函数和CSS,这里还需要一些JavaScript代码来实现点击显示和隐藏文章目录的功能。以下是一个简单的示例JavaScript代码,由Devv AI自动生成,用于显示和隐藏文章目录索引:

// 获取显示和隐藏按钮元素
const showButton = document.getElementById('article-index-show');
const hideButton = document.getElementById('article-index-hide');
const indexElement = document.getElementById('article-index');

// 点击显示按钮显示文章目录索引
showButton.addEventListener('click', function() {
    indexElement.style.display = 'block';
});

// 点击隐藏按钮隐藏文章目录索引
hideButton.addEventListener('click', function() {
    indexElement.style.display = 'none';
});

这段代码尚未经过测试,建议使用后面一段!请确保将此JavaScript代码添加到您的页面中,并根据需要调整元素ID以匹配您的实际代码。这样,您就可以实现点击按钮显示和隐藏文章目录索引的功能。

以下这段代码是本站正在使用的JS效果,把它加载到jQuery库后边就行,它能控制文章目录的开关和平滑滚动,可根据需要自行设定数值控制打开速度(毫秒)。

//文章目录展示切换
jQuery(document).ready(function(){
	jQuery("#article-index-hide").click(function(){
		jQuery("#article-index").hide(100);
		jQuery("#article-index-show").show(200);
	});
	jQuery("#article-index-show").click(function(){
		jQuery("#article-index").show(200);
		jQuery("#article-index-show").hide(100);
	});
});

//文章目录锚点点击平滑滚动
jQuery(document).on('click', '#article-index a[href^="#"]', function(e) {
	var id = jQuery(this).attr('href');
	var $id = jQuery(id);
	if ($id.length === 0) {
		return;
	}
	e.preventDefault();
	var pos = $id.offset().top;
	jQuery('body, html').animate({scrollTop: pos});
});

本文收录于{牧羊人}

© 版权声明

相关文章

暂无评论

暂无评论...