Typecho Joe主题自定义目录树
1、修改主题模版
编辑Joe主题文件夹public/aside.php
文件
<section id="toc" class="joe_aside__item" style="display:none;">
<div class="joe_aside__item-title menu_title">
<svg t="1642997936013" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2169" width="128" height="128"><path d="M838.3 895.9H197.9c-53.9 0-97.7-43.8-97.7-97.7V236.7c0-53.9 43.8-97.7 97.7-97.7h640.3c53.9 0 97.7 43.8 97.7 97.7v561.4c0.1 53.9-43.7 97.8-97.6 97.8zM197.9 203.8c-18.1 0-32.9 14.8-32.9 32.9v561.4c0 18.1 14.8 32.9 32.9 32.9h640.3c18.1 0 32.9-14.8 32.9-32.9V236.7c0-18.1-14.8-32.9-32.9-32.9H197.9z" fill="#666666" p-id="2170"></path><path d="M695.1 455.2H341.2c-17.9 0-32.4-14.5-32.4-32.4s14.5-32.4 32.4-32.4h353.9c17.9 0 32.4 14.5 32.4 32.4s-14.5 32.4-32.4 32.4zM695.1 578.2H341.2c-17.9 0-32.4-14.5-32.4-32.4s14.5-32.4 32.4-32.4h353.9c17.9 0 32.4 14.5 32.4 32.4s-14.5 32.4-32.4 32.4zM695.1 701.2H341.2c-17.9 0-32.4-14.5-32.4-32.4s14.5-32.4 32.4-32.4h353.9c17.9 0 32.4 14.5 32.4 32.4s-14.5 32.4-32.4 32.4zM379.1 281.1c-17.9 0-32.4-14.5-32.4-32.4V115.4c0-17.9 14.5-32.4 32.4-32.4s32.4 14.5 32.4 32.4v133.2c0 17.9-14.5 32.5-32.4 32.5zM657.1 281.1c-17.9 0-32.4-14.5-32.4-32.4V115.4c0-17.9 14.5-32.4 32.4-32.4s32.4 14.5 32.4 32.4v133.2c0 17.9-14.5 32.5-32.4 32.5z" fill="#666666" p-id="2171"></path></svg>
<span class="text">目录</span>
</div>
</section>
2、编写目录生成脚本
toc-nav.js
脚本动态生成目录树,并将目录插入到元素ID是toc
的标签内
// 获取文章页面h1~h6标签
const article = document.querySelector('.joe_detail__article');
const list = article.querySelectorAll('h1, h2, h3, h4, h5, h6');
// 为标题标签添加动态ID
list.forEach(element => {
let id = element.id || ('toc-index-' + Math.random()).replace('0.', '');
element.id = id;
});
// 生成TOC目录
const container = document.createElement('ul');
container.classList.add('toc-container');
list.forEach(item => {
let li = document.createElement('li');
li.classList.add('nav-item');
li.classList.add('nav-item-' + item.tagName.toLowerCase());
let a = document.createElement('a');
a.setAttribute('data', '#' + item.id);
a.innerText = item.innerText;
li.append(a);
container.append(li);
});
document.querySelector('#toc').append(container);
// 目录点击跳转
const tocContainer = document.querySelector('.toc-container');
tocContainer.addEventListener('click', function(event) {
event.preventDefault();
let id = event.target.getAttribute('data')
document.querySelector(id).scrollIntoView({
behavior: 'smooth',
block: 'center',
});
});
function removeHighLight() {
document.querySelectorAll('#toc .active').forEach(item => {
item.classList.remove('active');
});
}
// 为标题添加交叉观察器
let observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 删除已经高亮的元素
removeHighLight();
let targetId = entry.target.id;
let anchor = document.querySelector(`a[data="#${targetId}"]`);
anchor.classList.add('active');
}
});
});
list.forEach(item => {
observer.observe(item);
});
编写样式
编辑Joe主题文件夹assets/css/toc-nav.css
文件
#toc {
background: var(--background);
padding: 15px 15px;
top: 50px;
position: sticky;
}
.toc-container {
max-height: 500px;
overflow-y: auto;
overflow-x: hidden;
}
.nav-item a {
text-decoration: none;
color: var(--main);
line-height: 30px;
}
.nav-item a:hover {
color: var(--theme);
text-shadow: var(--text-shadow);
cursor: pointer;
}
.toc-container .active {
color: var(--theme);
text-shadow: var(--text-shadow);
}
.nav-item-h3 {
margin-left: 10px;
}
.nav-item-h4 {
margin-left: 20px;
}
.nav-item-h5 {
margin-left: 30px;
}
.nav-item-h6 {
margin-left: 40px;
}
/*,侧边栏目录导航只在文章页面生效*/
.joe_post + .joe_aside > section {
display: none;
}
.joe_post + .joe_aside > .author {
display: block;
}
.joe_post + .joe_aside > #toc {
display: block !important;
}
4、应用样式和脚本
编辑Joe主题文件夹post.php
文件,在<head>
标签中添加以下代码
<link rel="stylesheet" href="<?php $this->options->themeUrl('assets/css/toc-nav.css'); ?>">
编辑Joe主题文件夹post.php
文件,在<body>
标签中尾部添加以下代码
<script src="<?php _getAssets('assets/js/toc-nav.js'); ?>"></script>