如何快速统计并汇总子页面的链接

如何快速统计并汇总子页面的链接

以前用 Notion 的时候,留下一个习惯:

把子级页面都集中放在父级页面中。

在 Obsidian 这边,基本上就是:把同文件夹里的其他笔记的链接都汇总起来。

(配合 FolderNotes 插件可以获得相当好的嵌套笔记体验)

为了便于排查尚未链接的笔记,写了这个 DV 脚本,可以直接呈现出当前文件夹内还没链接的子笔记

如何快速统计并汇总子页面的链接--

提供了链接格式和纯文本两种格式:

  • 上半部分的链接可以用鼠标拖动直接放进笔记里
  • 纯文本则可以用右上角的复制按钮来批量复制,适合笔记数量较多的情况

DV 脚本

关于使用的说明,可以看这篇指导:【占位符,还没发布】


```dataviewjs
// 统计当前笔记所在的文件夹下,有哪些笔记还没出现在当前笔记内
// 可以通过修改 folderDepth 参数来设置搜索的目录层级
const input = {};
// 设置参数
const folderDepth = 1; // 设置搜索的目录层级,1表示只搜索当前目录,2表示搜索当前目录及其子目录,以此类推
const ignoreRules = input?.ignore || []; // 忽略规则,可以是正则表达式或字符串

// 获取当前文件
const currentFile = dv.current();
// 获取当前文件的路径
const currentFilePath = currentFile.file.path;
// 获取当前文件所在的文件夹路径
const folderPath = currentFilePath.substring(0, currentFilePath.lastIndexOf('/'));
// 如果路径中没有'/',说明文件在根目录下
const currentFolder = folderPath === currentFilePath ? '' : folderPath;

// 获取当前文件的内容
const content = await dv.io.load(currentFilePath);

// 获取指定文件夹下的所有笔记
let notesInFolder = [];
if (folderDepth === 1) {
    // 只搜索当前目录
    notesInFolder = dv.pages()
        .where(p => p.file.path.startsWith(currentFolder) && 
                  p.file.path !== currentFilePath && 
                  p.file.path.substring(currentFolder.length + 1).indexOf('/') === -1);
} else {
    // 搜索多级目录
    notesInFolder = dv.pages()
        .where(p => {
            if (!p.file.path.startsWith(currentFolder) || p.file.path === currentFilePath) {
                return false;
            }
            
            // 计算路径中的目录层级
            const relativePath = p.file.path.substring(currentFolder.length + 1);
            const slashCount = (relativePath.match(/\//g) || []).length;
            return slashCount < folderDepth;
        });
}

// 应用忽略规则,过滤掉需要忽略的笔记
let ignoredCount = 0;
const filteredNotes = notesInFolder.filter(note => {
    // 检查是否符合忽略规则
    for (const rule of ignoreRules) {
        if (rule instanceof RegExp) {
            // 正则表达式规则
            if (rule.test(note.file.name) || rule.test(note.file.path)) {
                ignoredCount++;
                return false;
            }
        } else if (typeof rule === 'string') {
            // 字符串规则
            if (note.file.name.includes(rule) || note.file.path.includes(rule)) {
                ignoredCount++;
                return false;
            }
        }
    }
    return true;
});

// 检查每个笔记是否在当前文件中被引用
const unreferencedNotes = filteredNotes.filter(note => {
    // 构建链接格式,检查是否在内容中出现
    const linkFormats = [
        `[[${note.file.name}]]`, // 标准链接格式
        `undefined`, // 嵌入格式
        `[[${note.file.path}]]`, // 完整路径链接格式
        `undefined`, // 完整路径嵌入格式
        new RegExp( `\\[\\[${escapeRegExp(note.file.name)}\\|.*?\\]\\]` ), // 带别名的链接格式 [[文件名|别名]]
        new RegExp( `\\[\\[${escapeRegExp(note.file.path)}\\|.*?\\]\\]` ) // 带别名的完整路径链接格式 [[路径|别名]]
    ];
    
    // 如果笔记有别名,也检查别名链接
    if (note.aliases) {
        note.aliases.forEach(alias => {
            linkFormats.push( `[[${alias}]]` );
            linkFormats.push( `undefined` );
        });
    }
    
    // 检查所有可能的链接格式
    return !linkFormats.some(format => {
        if (format instanceof RegExp) {
            return format.test(content);
        }
        return content.includes(format);
    });
});

// 用于转义正则表达式中的特殊字符
function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& 表示整个匹配的字符串
}

// 显示结果
if (unreferencedNotes.length > 0) {
    // dv.header(3, "未引用的笔记列表");
    
    dv.paragraph(`共计 ${unreferencedNotes.length} 个未引用的笔记${ignoredCount > 0 ? ` *(${ignoredCount} 个笔记被忽略规则过滤)*` : ''}`)

    dv.paragraph("#### 链接格式")
    dv.paragraph(
        unreferencedNotes.map(note => 
            dv.fileLink(note.file.path, false, note.file.name)
        )
    );

    
    dv.paragraph("\n#### 纯文本")
    
    // 拼接成一个纯文本,包在 > 中
    const pureText = "```txt\n" + unreferencedNotes.map(note => `[[${note.file.name}]]`).join('\n') + "\n```";

    dv.paragraph(pureText);
} else {
    dv.paragraph(`✅ 所有笔记都已被引用${ignoredCount > 0 ? `,${ignoredCount} 个笔记被忽略规则过滤` : ''}`);
}
```

单独的脚本文件:showUnlinkedSubNotes.js · GitHub

过滤笔记

有时候不是所有的笔记都想要链接,这个时候可以用下面这样的方式来过滤:

```dataviewjs
dv.view("showUnlinkedSubNotes", {ignore: [/2[34]\d{4}.*/, "特定文本"]})
```

ignore: [] 是个列表,把需要忽略的文本或者正则表达式放进去即可。

讨论

若阁下有独到的见解或新颖的想法,诚邀您在文章下方留言,与大家共同探讨。



反馈交流

其他渠道

版权声明