MarkdownPad2 自动生成目录原创
生成html时自动输出目录,完全离线,浏览时自动定位到当前目录并高亮显示:


点击查看代码
<style>
/* 目录容器样式 */
.folt_div {
max-height: 700px;
min-width: 250px;
overflow: auto;
border-radius: 8px;
z-index: 9999;
position: fixed;
right: 10px;
top: 10px;
padding: 10px;
background: #ffffff;
font-family: 'Arial', sans-serif;
font-size: 14px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border: 1px solid #ccc;
}
/* 目录标题样式 */
.catalog-title {
font-weight: bold;
margin-bottom: 15px;
font-size: 18px;
text-align: center;
color: #333;
background-color: #f0f0f0;
padding: 8px 0;
border-radius: 6px;
}
/* 目录项样式 */
.catalog {
cursor: pointer;
margin-left: 0;
padding: 3px 5px;
border-radius: 4px;
margin-bottom: 0px;
transition: background-color 0.2s ease;
}
.catalog a {
color: #333;
text-decoration: none;
font-weight: 600;
}
/* 鼠标悬停时 */
.catalog:hover {
background-color: #e0e0e0;
}
.catalog a:hover {
text-decoration: underline;
}
/* 高亮当前目录项 */
.catalog-active {
background-color: #f0f0f0;
color: white;
font-weight: bold;
border-radius: 4px;
}
/* 展开子目录时 */
.catalog-open > .catalog-children {
display: block;
}
/* 子目录样式 */
.catalog-children {
display: none;
margin-left: 0px;
}
/* 目录项折叠图标 */
.toggle-icon {
display: inline-block;
width: 1.2em;
cursor: pointer;
font-weight: bold;
margin-right: 0.0em;
text-align: center;
}
/* 不同层级的目录颜色 */
.catalog-h1 a { color: #333333; } /* 深灰 */
.catalog-h2 a { color: #666666; } /* 中灰 */
.catalog-h3 a { color: #999999; } /* 浅灰 */
.catalog-h4 a { color: #b3b3b3; } /* 更浅的灰 */
.catalog-h5 a { color: #cccccc; } /* 很浅的灰 */
.catalog-h6 a { color: #e0e0e0; } /* 非常浅的灰 */
/* 滚动到特定位置时的目录高亮 */
.catalog a.active {
color: #4CAF50;
font-weight: bold;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var container = document.createElement("div");
container.id = "catalogs";
container.className = "folt_div";
var title = document.createElement("div");
title.className = "catalog-title";
title.innerText = "📑 目录";
container.appendChild(title);
document.body.insertBefore(container, document.body.firstChild);
var headings = Array.from(document.querySelectorAll("h1,h2,h3,h4,h5,h6"));
if (headings.length === 0) return;
var idCount = 1;
function createNode(el) {
var tag = el.tagName.toLowerCase();
var level = parseInt(tag[1]);
var text = el.innerText.trim();
var id = "catalog" + (idCount++);
el.id = id;
return { level: level, id: id, text: text, children: [], element: el };
}
var tree = [], stack = [];
headings.forEach(el => {
var node = createNode(el);
while (stack.length > 0 && node.level <= stack[stack.length - 1].level) {
stack.pop();
}
if (stack.length === 0) {
tree.push(node);
} else {
stack[stack.length - 1].children.push(node);
}
stack.push(node);
});
function renderTree(nodes) {
var list = document.createElement("div");
nodes.forEach(node => {
var item = document.createElement("div");
item.className = "catalog catalog-h" + node.level;
if (node.children.length > 0) {
let toggle = document.createElement("span");
toggle.className = "toggle-icon";
toggle.innerText = "+";
toggle.onclick = function(e) {
e.stopPropagation();
item.classList.toggle("catalog-open");
toggle.innerText = item.classList.contains("catalog-open") ? "−" : "+";
};
item.appendChild(toggle);
} else {
let spacer = document.createElement("span");
spacer.className = "toggle-icon";
spacer.innerHTML = " ";
item.appendChild(spacer);
}
let link = document.createElement("a");
link.href = "javascript:void(0)";
link.innerText = node.text;
link.onclick = function(e) {
e.preventDefault();
node.element.scrollIntoView({ behavior: "smooth", block: "start" });
history.replaceState(null, '', '#' + node.id);
window.dispatchEvent(new Event("scroll")); // 更新高亮
};
item.appendChild(link);
if (node.children.length > 0) {
let childrenContainer = document.createElement("div");
childrenContainer.className = "catalog-children";
childrenContainer.appendChild(renderTree(node.children));
item.appendChild(childrenContainer);
}
list.appendChild(item);
});
return list;
}
container.appendChild(renderTree(tree));
var currentId = null;
window.addEventListener("scroll", function() {
let currentSection = null;
let currentOffset = Number.MAX_VALUE;
let currentLevel = -1;
headings.forEach(function(heading) {
let rect = heading.getBoundingClientRect();
let topDistance = rect.top + window.scrollY;
if (topDistance >= window.scrollY && topDistance < currentOffset) {
currentSection = heading.id;
currentOffset = topDistance;
currentLevel = parseInt(heading.tagName[1]);
}
});
if (currentSection && currentId !== currentSection) {
currentId = currentSection;
let allCatalogs = container.querySelectorAll(".catalog");
allCatalogs.forEach(c => {
let link = c.querySelector("a");
if (link && link.innerText && c.classList.contains("catalog-h" + currentLevel)) {
if (link.href.endsWith("#" + currentSection)) {
c.classList.add("catalog-active");
} else {
c.classList.remove("catalog-active");
}
} else {
c.classList.remove("catalog-active");
}
});
let activeLink = document.querySelector(`a[href*="#${currentSection}"]`);
if (activeLink) {
let parent = activeLink.closest(".catalog-children");
while (parent) {
parent.style.display = "block";
if (parent.previousElementSibling?.querySelector(".toggle-icon")) {
parent.previousElementSibling.querySelector(".toggle-icon").innerText = "−";
}
parent = parent.parentElement.closest(".catalog-children");
}
}
}
});
document.querySelectorAll('.toggle-icon').forEach(function(icon) {
icon.addEventListener('click', function(e) {
let parentCatalog = e.target.closest('.catalog');
let childrenContainer = parentCatalog.querySelector('.catalog-children');
if (childrenContainer) {
childrenContainer.style.display = childrenContainer.style.display === 'block' ? 'none' : 'block';
e.target.innerText = childrenContainer.style.display === 'block' ? '−' : '+';
}
e.stopPropagation();
});
});
window.dispatchEvent(new Event("scroll"));
});
</script>

浙公网安备 33010602011771号