受益于 shortcode 短代码插件和泽泽短代码中目录树的显示样式,形成了自己实现添加文章目录的思路:
一、文章目录树的结构
<div id="toc"><div class="toc-left"><div class="toc-btn" type="button" onclick="changetoc()">></div></div><div class="TOC">目录树区域</div>
</div>
上面用到点击显示目录树的js代码为:
// 推拉toc
function changetoc() {var e = document.getElementById("toc");if (e.classList.contains("tocwidth")) {e.classList.remove("tocwidth");} else {e.classList.add("tocwidth");}
}
二、给文章目录树创建CSS样式
/* -----------------------------------
## 目录树
------------------------------------*/
#toc {--toc-width: 260px;position: fixed;top: 0;/* right: 0px; */right: calc(-1 * var(--toc-width));height: 100vh;width: var(--toc-width);display: flex;flex-wrap: nowrap;justify-content: center;align-items: stretch;z-index: 5;transition: 0.5s;-webkit-transition: 0.5s; /* Safari */
}
.tocwidth {right: 0px !important;
}.toc-left {flex: 1 0 auto;display: flex;align-items: center;margin-left: -25px;margin-right: -25px;z-index: 6;
}
.toc-left .toc-btn {display: flex;justify-content: center;align-items: center;width: 50px;height: 50px;border-radius: 50%;background-color: var(--bd-main);cursor: pointer;box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.15);
}.toc {display: flex;flex-wrap: nowrap;height: auto;width: 100%;flex-direction: column;justify-content: center;background-color: var(--bd-main);box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.15);
}.toc > span {background-color: var(--bd-main);/*自定义背景色*/display: flex;justify-content: left;flex-wrap: wrap;font-size: larger;font-weight: bolder;text-align: left;padding: 10px;margin-bottom: 2px;margin-left: 20px;
}.toc ol {list-style-type: none;margin-left: 20px;padding: 0;display: -webkit-flex;display: flex;flex-direction: column;flex-wrap: nowrap;
}.toc ol li {flex: 0 0 auto;width: 100%;padding-left: 0px;
}.toc ol ol {padding-left: 5px;
}.toc li li {padding-left: 5px;
}.toc ol li a {display: block;padding: 5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;
}.toc ol li a:hover {background-color: var(--bd-main);color: white;
}
三、在 function.php 中建立目录树实现函数
//生成目录树
function toc($content)
{$html = '';$dom = new DOMDocument();libxml_use_internal_errors(true);$dom->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><body>' . $content . '</body>');libxml_use_internal_errors(false);$xpath = new DOMXPath($dom);$objs = $xpath->query('//h1|//h2|//h3|//h4|//h5|//h6');if ($objs->length) {$arr = [];$html = '<div class="toc"><span>目录</span>';foreach ($objs as $n => $obj) {$obj->setAttribute('id', 'TOC' . $n);handleToc($obj, $n, $arr, $html);}foreach ($arr as $n)$html .= '</li></ol>';$html .= '</div>';$html = '<div id="toc"><div class="toc-left"><div class="toc-btn" type="button" οnclick="changetoc()">></div></div>' . $html .'</div>';}return $html;
}//处理目录树
function handleToc($obj, $n, &$arr, &$html)
{$i = str_replace('h', '', $obj->tagName);$j = end($arr);if ($i > $j) {$arr[] = $i;$html .= '<ol>';} else if ($i == $j)$html .= '</li>';else if (in_array($i, $arr)) {$html .= '</li></ol>';array_pop($arr);handleToc($obj, $n, $arr, $html);return;} else {$arr = [$i];$html .= '</li>';}$html .= '<li><a href="#TOC' . $n . '">' . $obj->textContent . '</a>';
}
四、在 post.php 中调用目录树函数
<!-- 输出文章目录 -->
<?php echo toc($this->content); ?>