更新!看有回复说应用到Joe主题是目录内容为空白,已解决!!!
这是一款文章目录的插件,Typecho的 默认主题,jasmine主题和Joe主题均适用,其他主题没试过。。。
用法:将文件解压放在/usr/plugins目录下,后台点击启用 在你的主题文件中的post.php中添加以下代码:针对默认主题,jasmine主题,对于Joe主题有个修改 往下读可见
代码: 全选
<!-- 目录按钮和容器 -->
<div class="directory-container">
<div class="directory-toggle">
<span class="iconify" id="toggle-icon" data-icon="lets-icons:expand-left-double-light" data-inline="false"></span>
</div>
<div class="article-directory">
<!-- 目录将由 JavaScript 动态生成 -->
</div>
</div>
可以前往:https://github.com/devilchendk/OwODirectoryPlugin 下载
Jasmine主题效果图:
针对Joe主题
在post.php中插入:
代码: 全选
<!-- 目录按钮和容器 -->
<div class="directory-container">
<div class="directory-toggle">
<span class="iconify" id="toggle-icon" data-icon="lets-icons:expand-left-double-light" data-inline="false"></span>
</div>
<div class="article-directory">
<!-- 目录将由 JavaScript 动态生成 -->
</div>
</div>
更改插件的script.js代码或直接用以下代码替换(如果是github上下载的,只需要进入插件中的script.js中将该文件中下方注释掉的代码恢复,注释掉上方代码即可):
代码: 全选
document.addEventListener('DOMContentLoaded', function () {
const directoryToggle = document.querySelector('.directory-toggle');
const directoryContainer = document.querySelector('.directory-container');
const toggleIcon = document.querySelector('#toggle-icon');
const articleDirectory = document.querySelector('.article-directory');
const contentSelector = '.joe_detail .joe_detail__article'; // 更加精确地选择文章正文部分
let isExpanded = false;
// 初始状态,鼠标悬停提示为 "点击展开目录"
directoryToggle.setAttribute('title', '点击展开目录');
// 目录展开/收起动画
directoryToggle.addEventListener('click', function () {
isExpanded = !isExpanded;
if (isExpanded) {
directoryContainer.classList.add('directory-expanded');
toggleIcon.setAttribute('data-icon', 'lets-icons:collapse-right-double-light');
directoryToggle.classList.add('moved-left');
directoryToggle.setAttribute('title', '点击收起目录');
} else {
directoryContainer.classList.remove('directory-expanded');
toggleIcon.setAttribute('data-icon', 'lets-icons:expand-left-double-light');
directoryToggle.classList.remove('moved-left');
directoryToggle.setAttribute('title', '点击展开目录');
}
});
// 查找文章内容容器,只查找 .joe_detail__article 内的标题
let content = document.querySelector(contentSelector);
if (!content) {
console.error("未能找到文章内容容器。");
return;
}
// 生成目录
const headings = content.querySelectorAll('h1, h2, h3, h4, h5, h6');
if (headings.length === 0) {
console.error("没有找到标题");
return;
}
let tocHtml = '<ul>';
let minLevel = 7;
// 计算最小的标题层级
headings.forEach((heading) => {
const level = parseInt(heading.tagName.substring(1));
if (level < minLevel) minLevel = level;
});
// 生成目录结构
headings.forEach((heading, index) => {
const level = parseInt(heading.tagName.substring(1));
const indent = (level - minLevel) * 20;
const anchor = `heading-${index}`;
heading.id = anchor;
tocHtml += `<li style="margin-left: ${indent}px;"><a href="#${anchor}" data-anchor="${anchor}">${heading.textContent}</a></li>`;
});
tocHtml += '</ul>';
articleDirectory.innerHTML = tocHtml;
// 点击目录跳转
const tocLinks = document.querySelectorAll('.article-directory a');
tocLinks.forEach(link => {
link.addEventListener('click', function (event) {
event.preventDefault();
const targetId = event.target.getAttribute('data-anchor');
const targetElement = document.getElementById(targetId);
if (targetElement) {
window.scrollTo({
top: targetElement.offsetTop - 10,
behavior: 'smooth'
});
history.pushState(null, null, `#${targetId}`);
}
});
});
// 监听滚动并高亮当前标题
window.addEventListener('scroll', function () {
let currentHeadingId = null;
const offset = window.innerHeight * 0.25;
headings.forEach(function (heading) {
const rect = heading.getBoundingClientRect();
if (rect.top < offset && rect.bottom > 0) {
currentHeadingId = heading.id;
}
});
tocLinks.forEach(function (link) {
if (link.getAttribute('data-anchor') === currentHeadingId) {
link.classList.add('active'); // 高亮当前项
} else {
link.classList.remove('active'); // 移除高亮
}
});
});
});