当我们打开新的文章时,obsidian总是会回到最顶层,这时如果有一个大纲就可以很好的跳转到自己想要的位置,诚然obsidian在侧边栏提供了大纲功能,但是和hover这类悬浮插件无法相互配合,随后我就在obsidian论坛看到了MOY的文章(感谢),初步实现了自动生成大纲的功能,但是我发现功能过于鸡肋,层级一多就令人头昏眼花。
此时我想了想还是CSDN上的MOC最好用,随后对代码进行了重构,实现了几项功能
- 点击可跳转,并可悬浮预览
- 自动在前面增加.层级序号,使样式更加标准化
- 一级标题与其他行间隔最大,随后随着层级的减小逐级递减(可调整)
- 边距样式改为 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 = ' '.repeat((h.level-1) * 8); // 每个层级四个空格
output += `${indent}${chapterNumber} [[#${h.heading}]]\n`; // 添加编号和标题
// 输出并清空当前的输出
dv.paragraph(output.trim(), additionalAttr);
output = ''; // 清空
});
注意代码要放置dataviewjs代码框中