本站当前使用主题(2026-8-28)为Blowfish-修改侧边TOC标题树:支持正文H1 + 仅H1可折叠(默认全部折叠)

Bludit Blowfish主题改造|侧边TOC标题树:支持正文H1 + 仅H1可折叠(默认全部折叠)

适配Blowfish原生JS体系,不改动文章渲染逻辑,仅修改目录生成JS与配套CSS,实现类似Obsidian大纲折叠效果。

改造目标

  1. 正文Markdown支持多个# H1一级标题,可正常进入侧边TOC目录树;
  2. 层级缩进:H1顶格加粗,H2/H3/H4逐级缩进;
  3. 仅H1章节支持折叠展开,H2/H3/H4不可单独折叠;
  4. 页面加载时所有H1默认折叠;点击H1前方+/-按钮切换子条目显隐;
  5. 保留原有全部能力:锚点#悬浮标记、点击目录跳转、scroll-spy滚动高亮、移动端兼容。

修改清单

1. JS两处选择器修改(标题采集)

文件:主题内TOC相关JS
blowfish.js
两处原代码:

var headings = content.querySelectorAll('h2, h3, h4');

全部替换为:

var headings = content.querySelectorAll('h1,h2, h3, h4');

一处是TOC目录生成,一处是标题hover锚点#生成,两处必须同步修改,否则H1无悬浮锚点。

2. TOC目录构建循环代码(核心折叠逻辑,完整替换)

Array.prototype.forEach.call(headings, function (h) {
    const tag = h.tagName.toLowerCase();
    var li = document.createElement('li');
    li.className = 'toc-item toc-' + tag;

    var a = document.createElement('a');
    a.href = '#' + h.id;
    a.textContent = h.textContent;
    a.className = 'toc-link';

    if(tag === 'h1'){
        const toggleBtn = document.createElement('button');
        toggleBtn.className = 'toc-h1-toggle';
        toggleBtn.textContent = '+'; // 默认折叠显示加号
        toggleBtn.title = '折叠/展开章节';

        li.prepend(toggleBtn);
        li.appendChild(a);

        const subUl = document.createElement('ul');
        subUl.className = 'toc-subgroup';
        subUl.hidden = true; // 默认全部折叠
        li._subUl = subUl;
        li.appendChild(subUl);

        toggleBtn.onclick = function(e){
            e.preventDefault();
            const targetUl = li._subUl;
            const isHidden = targetUl.hidden;
            targetUl.hidden = !isHidden;
            toggleBtn.textContent = isHidden ? '−' : '+';
        };
        ul.appendChild(li);
    }else{
        li.appendChild(a);
        let lastH1li = null;
        const siblings = Array.from(ul.children);
        for(let i = siblings.length -1; i >=0; i--){
            const item = siblings[i];
            if(item.classList.contains('toc-h1')){
                lastH1li = item;
                break;
            }
        }
        if(lastH1li && lastH1li._subUl){
            lastH1li._subUl.appendChild(li);
        }else{
            ul.appendChild(li);
        }
    }
});

3. TOC完整CSS(替换原有TOC样式,包含层级缩进+折叠按钮)

style.css

/* ========================================
   TABLE OF CONTENTS (left sidebar, article view)
   ======================================== */
.toc-sidebar {
    margin-top: var(--space-xl);
    position: sticky;
    /* 56px = fixed navbar height; extra gap so the ToC doesn't hug it */
    top: calc(56px + var(--space-sm));
    max-height: calc(100vh - 56px - var(--space-md));
    overflow-y: auto;
    font-size: var(--font-size-sm);
}
.toc-title {
    font-size: var(--font-size-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin-bottom: 0.75rem;
}
.toc-list {
    list-style: none;
    padding: 0;
    margin: 0;
}
.toc-item {
    padding: 0.15rem 0;
}
.toc-h1 {
    padding-left: 0;
    font-weight: 700;
    margin-top: 0.4rem;
}
.toc-h2 {
    padding-left: 0.75rem;
}
.toc-h3 {
    padding-left: 1.5rem;
}
.toc-h4 {
    padding-left: 2.25rem;
}
.toc-link {
    color: var(--text-muted);
    text-decoration: none;
    line-height: 1.5;
    display: block;
    transition: color 0.15s ease;
}
.toc-link:hover {
    color: var(--text-primary);
    text-decoration: none;
}
.toc-link.active {
    color: var(--accent);
    font-weight: 600;
    text-decoration: none;
}
/* 折叠按钮样式 */
.toc-h1-toggle {
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0 0.2rem 0 0;
    font-size: 1em;
    color: var(--text-muted);
    width:1.2rem;
}
.toc-subgroup {
    list-style: none;
    padding-left: 0.75rem;
    margin: 0.2rem 0;
}
.toc-subgroup .toc-item {
    padding:0.15rem 0;
}

行为说明

  1. 页面载入:所有H1子目录默认折叠,H1前面显示+;
  2. 点击H1前+ → 展开下属H2/H3/H4,符号变为−;
  3. 点击− → 收起子条目,变回+;
  4. 多个H1互相独立,单独控制,互不干扰;
  5. 点击H1文字链接,直接跳转到文章内对应H1锚点;
  6. 滚动页面,scroll-spy依旧自动高亮当前所在目录条目,折叠状态不影响高亮。

回滚方案

  1. JS:还原目录循环代码,并且把两处h1,h2,h3,h4改回原始h2,h3,h4;
  2. CSS:删除新增的折叠按钮、toc-h1/toc-h2缩进规则,恢复原始TOC样式。

注意事项

  • SEO:页面会出现多个<h1>,搜索引擎规范不推荐,仅适配个人书写习惯;
  • 缓存:每次修改后,需要清空Bludit缓存 + 浏览器Ctrl+F5硬刷新;
  • 边界:文章无H1时,所有标题直接渲染在根目录,JS不会报错。

测试样例Markdown

# 第一章 测试H1(默认折叠)
## 1.1 二级标题
### 1.1.1 三级标题
#### 1.1.1.1 四级标题
# 第二章 第二个H1(独立折叠)
## 2.1 二级内容

已解决历史问题

  • ✅ 原版JS只读取h2-h4,正文H1无法进入目录树;
  • ✅ 最初折叠逻辑全局变量覆盖,仅最后一个H1按钮生效;
  • ✅ 层级无缩进,目录视觉层次混乱;
  • ✅ 新增H1后,hover标题缺少#锚点链接。

后续可扩展:记住页面折叠状态(localStorage),刷新页面保留上次展开/折叠状态。

如果你需要,我可以把这份改造记录合并进之前Blowfish主题优化的复盘MD文档里统一归档。

general Bluditcms Blowfish
Share X (Twitter) Reddit LinkedIn