【dataview】建立仿CSND样式的大纲可点击跳转,并自动添加.序号(类似论文)

当我们打开新的文章时,obsidian总是会回到最顶层,这时如果有一个大纲就可以很好的跳转到自己想要的位置,诚然obsidian在侧边栏提供了大纲功能,但是和hover这类悬浮插件无法相互配合,随后我就在obsidian论坛看到了MOY的文章(感谢),初步实现了自动生成大纲的功能,但是我发现功能过于鸡肋,层级一多就令人头昏眼花。

此时我想了想还是CSDN上的MOC最好用,随后对代码进行了重构,实现了几项功能

  1. 点击可跳转,并可悬浮预览
  2. 自动在前面增加.层级序号,使样式更加标准化
  3. 一级标题与其他行间隔最大,随后随着层级的减小逐级递减(可调整)
  4. 边距样式改为 2em 与正文内容保持距离,防止误触(可调整)

代码如下:

const file = app.workspace.getActiveFile();
const { headings } = app.metadataCache.getFileCache(file);

let output = '';
const maxMargin = 1;  // 第一级标题的最大间距(单位:em)
const minMargin = 0;  // 最小的间距(单位:em),现在设为 0
const marginStep = 0.2;  // 每增加一个层级,间距递减的量

// 整个 dv 容器的样式调整
dv.container.style.marginBlockStart = "2em";//标题框体与正文的距离

// 初始化编号
let currentChapter = new Array(6).fill(0); // 支持六个层级,obsidian最高支持6级

headings.forEach(h => {
    // 更新当前章节的编号
    currentChapter[h.level - 1] += 1; // 更新当前层级的编号

    // 重置更深层级的编号
    for (let i = h.level; i < 6; i++) {
        currentChapter[i] = 0;
    }

    // 计算当前标题的间距,确保间距不小于 minMargin
    const margin = Math.max(maxMargin - (h.level - 1) * marginStep, minMargin); // 每个层级减少一定的间距,最小为 minMargin

    // 动态设置标题的上下间距
    const additionalAttr = {
        attr: {
            style: `margin-block-start: ${margin}em !important; margin-block-end: ${margin}em !important;`
        }
    };

    // 生成章节编号
    let chapterNumber = currentChapter.slice(0, h.level).join('.');

    // 拼接缩进和编号
    const indent = '&nbsp;'.repeat((h.level-1) * 8); // 每个层级四个空格
    output += `${indent}${chapterNumber} [[#${h.heading}]]\n`; // 添加编号和标题

    // 输出并清空当前的输出
    dv.paragraph(output.trim(), additionalAttr);
    output = ''; // 清空
});

注意代码要放置dataviewjs代码框中

1 个赞