[QueryView] 目录章节跳转体系

这个东西的原型在 Achuan 佬的视频 BV1PEi6YSERC 中,他在每篇笔记末尾通过引用链接快速跳转到目录、本章开头、上下章。有人很喜欢这个功能:

所以尝试用 Query View 插件制作了一个类似功能。简单来说,考虑到成体系的笔记会把各篇文档汇总到一个 MOC 里,那么基于这个 MOC 引用列表就能知道一篇笔记的目录和上下章,从而在各章节笔记末尾插入的查询块中自动生成类似川佬原视频的目录章节跳转体系。

功能使用

  1. 建立一篇文档作为笔记 MOC,用列表放置对各章节的引用构成目录,形如:

  1. 在各章节末尾插入 QV 查询块,代码位于后文,并将代码第一行的块 ID 换成上一步的目录列表块的 ID。所得查询块会渲染为以下样式,支持点击跳转到目录、本章开头、上一章、下一章。

除了改目录块 ID 以外,可以将查询块复制粘贴、设为模板、复制为嵌入块使用。但与原视频手搓的跳转链接相比,这个渲染结果只会在笔记内显示,导出无效

效果演示

查询代码

安装 Query & View 插件后,在嵌入块中输入以下代码,并将代码第一行的块 ID 换成目录列表块的 ID。

//!js
const contents_id = '20250502231118-wlnx75o';   // 目录列表块ID

const get_chapter_id_list = (markdown) => {
    // 正则表达式匹配以 (( 开头,后跟14位数字、-、7位随机字母数字、空格
    const regex = /\(\((\d{14}-[a-zA-Z0-9]{7}) /g;

    // 使用 matchAll 来找到所有匹配项
    const matches = [...markdown.matchAll(regex)];

    // 提取内容并返回
    return matches.map(match => match[1]);
}

const get_block_from_id = async (id) => {
    return await Query.sql(`select * from blocks where id = '${id}'`)
}


const query = async () => {
    let dv = Query.DataView(protyle, item, top);

    // 目录块
    const contents_block = await get_block_from_id(contents_id);

    // 文档子块
    let child_blocks = await Query.request('/api/block/getChildBlocks', {
        id: Query.root_id(protyle)
    });
    child_blocks = Query.wrapit(child_blocks);

    // 章节上下章
    let previous_chapter = null;
    let next_chapter = null;

    const chapter_id_list = get_chapter_id_list(contents_block[0].markdown);
    for (let i = 0; i < chapter_id_list.length; i++) {
        let chapter_id = chapter_id_list[i];
        if (chapter_id === Query.root_id(protyle)) {
            if (i > 0) {
                const previous_id = chapter_id_list[i - 1];
                previous_chapter = await get_block_from_id(previous_id);
            }
            if (i < chapter_id_list.length - 1) {
                const next_id = chapter_id_list[i + 1];
                next_chapter = await get_block_from_id(next_id);
            }
            break;
        }

    }


    // dv.addmd(`---`);
    if (previous_chapter === null) {
        dv.addmd(`[📖目录](${contents_block[0].asurl}) | [⬆️回到本章开头](${child_blocks[0].asurl}) | [➡️后一章](${next_chapter[0].asurl})`);
    }
    else if (next_chapter === null) {
        dv.addmd(`[📖目录](${contents_block[0].asurl}) | [⬅️前一章](${previous_chapter[0].asurl}) | [⬆️回到本章开头](${child_blocks[0].asurl})`);
    }
    else {
        dv.addmd(`[📖目录](${contents_block[0].asurl}) | [⬅️前一章](${previous_chapter[0].asurl}) | [⬆️回到本章开头](${child_blocks[0].asurl}) | [➡️后一章](${next_chapter[0].asurl})`);
    }
    dv.render();
}

return query();

代码不复杂,水平有限只会用 SQL 从块 ID 查出 block。

感谢 Frostime 佬,QV 插件为笔记的结构呈现提供了无限可能。

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    26401 引用 • 109793 回帖 • 2 关注
  • QueryView
    14 引用 • 69 回帖
  • 双向链接
    6 引用 • 18 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 👌 新技巧 get

  • MasterYS

    我就是喜欢川大那个之一,如果能导出 PDF 生效就更好了

    1 回复
  • F 门 🙏🙏🙏🙏🙏

  • SyTlr

    小声问一句,这个 QV 插件,是建立在嵌入块上的,每次打开文档都会刷新一次,不会占用资源造成软件卡顿吗。。。

    我用嵌入块写个每日随机文案,都感觉有点害怕占用资源。。。

    1 回复
  • wilsons 2 评论

    这个是动态生成的,所以导出没效果,如果是直接插入到文档中应该就没问题了。

    如果想达到这种效果,可以尝试在文档外部写个代码片段,然后,刷新页面时或定时生成导航到文档中,这样就应该可以导出了。

    求实现,这样做的 PDF 电子书,阅读性一下子就起来了
    MasterYS
    @MasterYS 模仿 J 佬风格 先记录了 😄
    wilsons 1 1 赞同
  • 每次打开文档都会刷新一次

    这种问题不大,不会阻塞页面不会卡

请输入回帖内容 ...