为了让文档层级导航插件能用于 MOC 笔记法,我写了一个对反链进行过滤的代码片段

使用 dailynote 笔记法的用户,会倾向于用 moc 来管理笔记,而不用文档树管理笔记,管理文档链接而不管理文档,这时候「文档层级导航插件」的显示父子文档功能就没有什么导航作用了,需要靠反链的文档来导航,显示相关文档。

由于使用 dailynote 积累笔记,反链有很多 dailynote,但这些 dailynote 和这篇文档的主题无关系只有补充信息。

我希望文档层级导航插件的反链展示可以只展示与本文档真正有关联的笔记(即真正的相关笔记),排除 dailynote 的干扰,因此希望是可以有一个选项可以过滤掉这些 dailynote 的

我给插件提了一个 issue:反链能支持排除 dailynote 笔记嘛 · Issue #64 · OpaqueGlass/syplugin-hierarchyNavigate (github.com)

暂时没得到回复,于是自己问 GPT 写了一个 js 代码片段,先用上了

具有如下功能

  1. 通过正则过滤 dailynote 笔记,此外我还有周总结、月总结的习惯,也希望反链不出现这些笔记。可以根据需要修改 filterPatterns 变量的正则表达式
  2. 对反链的文档进行排序
  3. 我习惯 moc 笔记添加前缀 @,所以额外处理,将 moc 笔记放在最前面



(async ()=>{function filterAndReorderLinks() {
    const filterPatterns = [
        /^\d{8} \w{3}$/, // Example: 20240728 Sun
        /^\d{6}$/,
        /^\d{8} ~ \d{8}$/,
        /^\d{8} \- \d{8}$/
        // Add more patterns here if needed
    ];

    const containers = document.querySelectorAll("div.og-hierachy-navigate-backlink-doc-container");
    if (containers.length === 0) {
        return;
    }

    containers.forEach(container => {
        const refLinks = container.querySelectorAll("span.refLinks.docLinksWrapper");
        if (refLinks.length === 0) {
            return;
        }

        // Hide elements that match any pattern in filterPatterns
        refLinks.forEach(link => {
            const docName = link.getAttribute("title");
            if (filterPatterns.some(pattern => pattern.test(docName))) {
                link.style.display = "none";
            } else {
                link.style.display = ""; // Reset display property if it doesn't match
            }
        });

        // Separate elements into two arrays: one for @-prefixed and one for otherItems
        const mocItems = [];
        const otherItems = [];

        refLinks.forEach(link => {
            const docName = link.getAttribute("title");
            if (docName.startsWith("@")) {
                mocItems.push(link);
            } else {
                otherItems.push(link);
            }
        });

        // Sort the 'otherItems' array based on the 'title' attribute in ascending order
        otherItems.sort((a, b) => {
            const titleA = a.getAttribute("title").toUpperCase(); // Ignore upper and lowercase
            const titleB = b.getAttribute("title").toUpperCase(); // Ignore upper and lowercase
            return titleA.localeCompare(titleB);
        });

        // Clear only the refLinks elements and append them in the desired order
        refLinks.forEach(link => link.remove());
        mocItems.concat(otherItems).forEach(link => {
            container.appendChild(link);
        });
    });
}
    // 监控dom变化
    function observeDomChange(targetNode, callback) {
        const config = { childList: true, subtree: true };
        const observer = new MutationObserver((mutationsList) => {
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    callback(mutation);
                }
            }
        });
        observer.observe(targetNode, config);
        // 返回observer,用于停止观察
        // observer.disconnect();
        return observer;
    }
// 等待元素渲染完成后执行的函数
function whenElementExist(selector) {
    return new Promise(resolve => {
        const checkForElement = () => {
            let element = null;
            if (typeof selector === 'function') {
                element = selector();
            } else {
                element = document.querySelector(selector);
            }
            if (element) {
                resolve(element);
            } else {
                // 如果元素不存在,等浏览器再次重绘,递归调用checkForElement,直到元素出现
                requestAnimationFrame(checkForElement);
            }
        };
        checkForElement();
    });
}

// 等待笔记区出现
whenElementExist(".layout__center").then((element)=>{
  
    const observer = observeDomChange(element, (mutation) => {
    // 监听弹窗代码列表
    if(mutation.target.classList.contains("protyle-top") || mutation.target.classList.contains("og-hn-heading-docs-container")) {
        setTimeout(filterAndReorderLinks, 100);
    }

});
});


})();

使用

Clip20240806194319.png

运行前Clip20240806194059.png

自定义 js 运行后Clip20240806194110.png

  • 思源笔记

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

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

    20511 引用 • 79971 回帖
2 操作
Achuan-2 在 2024-08-09 17:41:49 更新了该帖
Achuan-2 在 2024-08-09 16:37:24 更新了该帖

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...
  • 确实好用,在这基础上稍微修改一下自己就能用了,感谢。

    我在你这个基础上增加了隐藏链接末尾为*的文档,这样就可以手动标记来完成已经被整理过的反链的筛选,不过还是有点问题,就是这个筛选只针对于文档标题的引用,粒度有点大。

    1 回复
  • Achuan-2

    因为我还是喜欢文档来管理内容,也能更沉浸去创作。

    目前块引用也基本是文档引用,块粒度的引用对我而言,不如文档引用安全,容易失效

  • Achuan-2

    学习这篇帖子代码片段实现代码块最近使用的语言置顶 - 链滴 (ld246.com)

    放弃 setInterval 定时执行,用了 MutationObserver 来监控 DOM 变化

    
    
    (async ()=>{function filterAndReorderLinks() {
        const filterPatterns = [
            /^\d{8} \w{3}$/, // Example: 20240728 Sun
            /^\d{6}$/,
            /^\d{8} ~ \d{8}$/,
            /^\d{8} \- \d{8}$/
            // Add more patterns here if needed
        ];
    
        const containers = document.querySelectorAll("div.og-hierachy-navigate-backlink-doc-container");
        if (containers.length === 0) {
            return;
        }
    
        containers.forEach(container => {
            const refLinks = container.querySelectorAll("span.refLinks.docLinksWrapper");
            if (refLinks.length === 0) {
                return;
            }
    
            // Hide elements that match any pattern in filterPatterns
            refLinks.forEach(link => {
                const docName = link.getAttribute("title");
                if (filterPatterns.some(pattern => pattern.test(docName))) {
                    link.style.display = "none";
                } else {
                    link.style.display = ""; // Reset display property if it doesn't match
                }
            });
    
            // Separate elements into two arrays: one for @-prefixed and one for otherItems
            const mocItems = [];
            const otherItems = [];
    
            refLinks.forEach(link => {
                const docName = link.getAttribute("title");
                if (docName.startsWith("@")) {
                    mocItems.push(link);
                } else {
                    otherItems.push(link);
                }
            });
    
            // Sort the 'otherItems' array based on the 'title' attribute in ascending order
            otherItems.sort((a, b) => {
                const titleA = a.getAttribute("title").toUpperCase(); // Ignore upper and lowercase
                const titleB = b.getAttribute("title").toUpperCase(); // Ignore upper and lowercase
                return titleA.localeCompare(titleB);
            });
    
            // Clear only the refLinks elements and append them in the desired order
            refLinks.forEach(link => link.remove());
            mocItems.concat(otherItems).forEach(link => {
                container.appendChild(link);
            });
        });
    }
        // 监控dom变化
        function observeDomChange(targetNode, callback) {
            const config = { childList: true, subtree: true };
            const observer = new MutationObserver((mutationsList) => {
                for (const mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        callback(mutation);
                    }
                }
            });
            observer.observe(targetNode, config);
            // 返回observer,用于停止观察
            // observer.disconnect();
            return observer;
        }
    // 等待元素渲染完成后执行的函数
    function whenElementExist(selector) {
        return new Promise(resolve => {
            const checkForElement = () => {
                let element = null;
                if (typeof selector === 'function') {
                    element = selector();
                } else {
                    element = document.querySelector(selector);
                }
                if (element) {
                    resolve(element);
                } else {
                    // 如果元素不存在,等浏览器再次重绘,递归调用checkForElement,直到元素出现
                    requestAnimationFrame(checkForElement);
                }
            };
            checkForElement();
        });
    }
    
    // 等待笔记区出现
    whenElementExist(".layout__center").then((element)=>{
      
        const observer = observeDomChange(element, (mutation) => {
        // 监听弹窗代码列表
        if(mutation.target.classList.contains("protyle-top") || mutation.target.classList.contains("og-hn-heading-docs-container")) {
            setTimeout(filterAndReorderLinks, 100);
        }
    
    });
    });
    
    
    })();
    
    1 操作
    Achuan-2 在 2024-08-09 17:41:12 更新了该回帖
Achuan-2
给时间以生命而不是给生命以时间,给我买包辣条 https://www.yuque.com/achuan-2 上海

推荐标签 标签

  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 176 关注
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 190 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 144 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    146 引用 • 3767 回帖
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 6 关注
  • 学习

    “梦想从学习开始,事业从实践起步” —— 习近平

    163 引用 • 473 回帖
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 218 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 55 关注
  • 负能量

    上帝为你关上了一扇门,然后就去睡觉了....努力不一定能成功,但不努力一定很轻松 (° ー °〃)

    88 引用 • 1234 回帖 • 433 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    21 引用 • 140 回帖 • 6 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    106 引用 • 152 回帖 • 1 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 607 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    336 引用 • 1749 回帖 • 1 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 623 关注
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 25 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    540 引用 • 672 回帖 • 1 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    5 引用 • 102 回帖
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 2 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 444 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 618 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    123 引用 • 168 回帖
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    4 引用 • 16 回帖 • 1 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    485 引用 • 906 回帖
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    45 引用 • 113 回帖 • 274 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 462 关注