[js] 标签文档自动加入数据库(转载)

本文只是转载,大佬在评论区分享的 js 代码,我觉得非常好用,于是搬运过来

代码作者:wilsons - 链滴

创意作者及其 quicker 动作:qiancang - 链滴[Quicker] 思源笔记 SuperTag - 链滴

// 思源通过标签插入当前块到数据库(SuperTag) // 功能:给块设置标签,将块添加到标签同名的数据库。 // 说明; // 1、数据库名称需要与标签同名,名称需含前后#,如 #笔记软件# // 2、如果有多个同名数据库,只会将块添加到其中一个,所以不要建立同名数据库 // 3、需要提前建立数据库才能添加成功 // version:0.0.4 // 更新记录 // 0.0.2 增加数据库同名文档标签即可把文档添加到标签同名数据库中(文档标签这里指文档头部的添加标签)。 // 0.0.3 增加可删除数据库引用文本中的标签名选项isShowTagNameInAvCell // 0.0.4 改进当标签在列表中时数据库插入列表项 // 根据qiancang大佬的帖子实现 https://ld246.com/article/1731945645865 (()=>{ // 添加tag后多少毫秒添加当前块到数据库 // 不宜设置过小,过小可能导致标签被插入一半 const delay = 500; // 是否开启文档标签插入同名数据库(文档标签这里指文档头部的添加标签),true开启,false不开启 const enableDocTagToAv = true; // 是否在数据库列表中显示标签名(数据库名),true显示,false不显示(注意,文档块引用不会添加标签名,实现较麻烦暂不支持) const isShowTagNameInAvCell = true; // 发布服务立即返回 if(siyuan.config.readonly) return; // 监听tag输入 observeTagSpans(async (tagEl, tagType) => { // 如果未开启文档标签插入同名数据库,当为文档标签时返回 if(!enableDocTagToAv && tagType === 'doc-tag') return; // 去掉零宽度字符&ZeroWithSpace; const tag = tagEl?.textContent?.replace(/[\u200B-\u200D\uFEFF]/g, '')?.trim(); if(!tag) return; // 获取数据库信息 const av = await getAvByName(tag); if(!av) return; const avId = av.avID; if(!avId) return; const avBlockID = av.blockID; if(!avBlockID) return; // 获取文档块信息 let block; if(tagType === 'doc-tag') { // 如果头部标签,返回文档id const blockParent = tagEl.closest('div.protyle-top'); if(!blockParent) return; block = blockParent.querySelector('.protyle-title'); } else { // 如果块标签,返回块id(监听元素的临时块) block = tagEl.closest('div[data-node-id][data-type]'); if(!block) return; // 获取文档中的block结点 block = document.querySelector('div[data-node-id="'+(block?.dataset?.nodeId||'')+'"]'); if(!block) return; // 判断是否在列表元素内,数据库插入列表项 const listItemNode = block.closest('div[data-node-id][data-type="NodeListItem"]'); if(listItemNode) block = listItemNode; } const blockId = block?.dataset?.nodeId; if(!blockId) return; // 添加块到数据库 await sleep(delay || 500); addBlocksToAv(blockId, avId, avBlockID); }); // 如果不在数据库中显示标签名则删除标签名(注意,文档块引用不会添加标签名,实现较麻烦暂不支持) if(!isShowTagNameInAvCell) { observeElementCreation( document.body, '.av__row:not(.av__row--header) [data-dtype="block"] [data-type="block-ref"]', async ref => { if(!/\s?#.*?#/i.test(ref.textContent)) return; ref.textContent = ref.textContent.replace(/\s?#.*?#/ig, ''); } ); } // 插入块到数据库 async function addBlocksToAv(blockIds, avId, avBlockID) { blockIds = typeof blockIds === 'string' ? [blockIds] : blockIds; const srcs = blockIds.map(blockId => ({ "id": blockId, "isDetached": false, })); const input = { "avID": avId, "blockID": avBlockID, 'srcs': srcs } const result = await fetchSyncPost('/api/av/addAttributeViewBlocks', input); if(!result || result.code !== 0) console.error(result); } // 通过该tag查询数据库 async function getAvByName(name) { const result = await fetchSyncPost('/api/av/searchAttributeView', { "keyword": name }); if(!result || result.code !== 0 || !result?.data?.results || result?.data?.results?.length === 0) return null; for (const av of result.data.results) { if (av.avName === name || av.avName === `#${name}#`) { return av; } } return null; } // 请求api // returnType json返回json格式,text返回文本格式 async function fetchSyncPost(url, data, returnType = 'json') { const init = { method: "POST", }; if (data) { if (data instanceof FormData) { init.body = data; } else { init.body = JSON.stringify(data); } } try { const res = await fetch(url, init); const res2 = returnType === 'json' ? await res.json() : await res.text(); return res2; } catch(e) { console.log(e); return returnType === 'json' ? {code:e.code||1, msg: e.message||"", data: null} : ""; } } // 延迟执行 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 监听tag被添加 function observeTagSpans(callback) { // 创建一个观察者实例并传入回调函数 const observer = new MutationObserver((mutationsList, observer) => { for (const mutation of mutationsList) { if (mutation.type === 'childList') { // 检查新增的节点 for (const node of mutation.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() === 'span' && node.getAttribute('data-type') === 'tag') { // 块标签调用回调函数 callback(node, 'block-tag'); } else if(node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() === 'div' && node.classList?.contains('b3-chip') && node.getAttribute('data-type') === 'open-search') { // 文档头部标签调用回调函数 callback(node, 'doc-tag'); } } } } }); // 配置观察选项: const config = { childList: true, // 观察子节点的变化(添加/删除) subtree: true // 观察所有后代节点 }; // 选择需要观察变动的节点 const targetNode = document.body; // 或者选择更具体的父节点以减少性能消耗 // 开始观察目标节点 observer.observe(targetNode, config); // 返回一个取消观察的方法 return () => observer.disconnect(); } // 监听元素被创建 function observeElementCreation(parentNode, selector, onElementCreated) { // 配置观察器选项 const config = { childList: true, // 观察直接子节点的添加和移除 subtree: true // 观察所有后代节点 }; // 当检测到变动时执行的回调函数 const callback = function(mutationsList, observer) { for (let mutation of mutationsList) { if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { // 使用 querySelectorAll 查找所有符合条件的新元素 const elements = node.querySelectorAll(selector); elements.forEach(element => { onElementCreated(element); // 调用外部提供的回调函数 }); } }); } } }; // 创建一个观察器实例并传入回调函数 const observer = new MutationObserver(callback); // 开始观察目标节点 observer.observe(parentNode, config); // 返回一个函数来停止观察 return () => observer.disconnect(); } })();
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    140 引用 • 946 回帖 • 1 关注
  • 思源笔记

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

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

    25091 引用 • 103444 回帖
1 操作
TangQi 在 2024-11-26 17:38:35 更新了该帖

相关帖子

欢迎来到这里!

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

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    31 引用 • 97 回帖
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 109 关注
  • 反馈

    Communication channel for makers and users.

    126 引用 • 930 回帖 • 274 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖 • 2 关注
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 86 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    31 引用 • 108 回帖
  • GraphQL

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

    4 引用 • 3 回帖 • 5 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 32 关注
  • V2Ray
    1 引用 • 15 回帖
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖 • 2 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    432 引用 • 1250 回帖 • 597 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖 • 1 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 30 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3196 引用 • 8215 回帖
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 724 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    88 引用 • 139 回帖 • 1 关注
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 2 关注
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    42 引用 • 130 回帖 • 252 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    124 引用 • 74 回帖 • 1 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    298 引用 • 762 回帖
  • abitmean

    有点意思就行了

    38 关注
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    79 引用 • 431 回帖
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    133 引用 • 1124 回帖 • 117 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    315 引用 • 547 回帖