-
[js] 简单实现 webdav 实时备份重要文件(密钥安全再无忧)
2025-09-12 05:44🔐 密钥铭刻昆仑石 ⛰️,
☁️ 云纹暗藏九重天 🌌。
🌊 纵使沧溟终覆灭 ⚡,
💫 一念重回太初前 🕰️。 -
思源笔记有没有比较浅显的插件开发教程?
2025-09-11 16:37从 0 到 1,别人只能给个大概流程,编程会涉及很多细节。
其实我推荐,把思源相关的架构,数据库结构,基本的文档整理成 md 文档,通过 ai 的知识库导入,然后根据这些知识库,再咨询你关心的问题,当看不明白时,你可以要求它用外行人听得懂的语言或新手容易理解的语言去讲解。
必要时,给出 html 源码,ai 回答的更精准,devtools 基础使用还是得了解的。
最后实践还是实践。先从简单的需求开始,边学边做进步最快。还成就感满满。
-
[rclone] 告别本地单点故障:思源笔记远程备份终极方案
2025-09-11 16:24注意:
第一次执行可能会耗时较长,根据文件大小和个数决定,以后就是增量备份了,速度很快。
rclone copy 和 rclone sync 的区别是:
rclone copy 只新增和修改,不删除。
rclone sync 严格与本地保持同步,会删除本地没有的文件。
-
[js] 简单实现 webdav 实时备份重要文件(密钥安全再无忧)
2025-09-10 00:24没看到,我用的是 3.3.2 没错啊
有的,你检查下版本或新空间看看

不过怎么还 at 了你自己?
哈哈,我做了一个一键 @ 工具,默认会把回帖,收藏,点赞,打赏,感谢等参与者全部 @ 忘了加过滤作者了。链滴默认 @ 参与者 仅支持回复者,不好用。
-
[js] 简单实现 webdav 实时备份重要文件(密钥安全再无忧)
2025-09-09 23:09 -
js 代码片段 | 悬赏请求:在编辑器的光标所在块按下快捷键 CTRL+R,为在该块的书签添加、删除一个图标
2025-09-09 20:44完整版
// 通过快捷键给块书签添加删除标签 // see https://ld246.com/article/1757393544265 (()=>{ // 按键字母,由于Ctrl+R是替换,建议改成别的比如Ctrl+T const pressLetter = 'R'; // 必须大写 // 添加的表情 const emojis = '😀'; // 表情位置,prefix 开头,suffix 结尾 const emojisPosition = 'prefix'; document.addEventListener('keydown', async (event) => { // 检查是否按下了 Ctrl+R // 这里推荐用 Ctrl + T,只需要把下行的 KeyR 改为 KeyT 即可 if ((event.ctrlKey || event.metaKey) && event.code === 'Key'+pressLetter && !event.shiftKey && !event.altKey) { const cursorElement = getCursorElement(); if(!cursorElement) return; const cursorBlock = cursorElement.closest('.protyle-wysiwyg [data-node-id][data-type]'); if(!cursorBlock) return; const blockId = cursorBlock?.dataset?.nodeId; if(!blockId) return; event.preventDefault(); event.stopPropagation(); // 获取书签 const data = await requestApi('/api/attr/getBlockAttrs', { "id": blockId }); let attr = data?.data['custom-riffCard-State-Fake'] || ''; // 添加删除表情 const hasEmojis = attr.includes(emojis); attr = attr.replace(emojis, ''); if(!hasEmojis) attr = emojisPosition === 'prefix' ? emojis + attr : attr + emojis; requestApi('/api/attr/setBlockAttrs', { "id": blockId, "attrs": { "custom-riffCard-State-Fake": attr } }); } }, true); function getCursorElement() { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); // 获取选择范围的起始位置所在的节点 const startContainer = range.startContainer; // 如果起始位置是文本节点,返回其父元素节点 const cursorElement = startContainer.nodeType === Node.TEXT_NODE ? startContainer.parentElement : startContainer; return cursorElement; } return null; } async function requestApi(url, data, method = 'POST') { return await (await fetch(url, {method: method, body: JSON.stringify(data||{})})).json(); } })(); -
js 代码片段 | 悬赏请求:在编辑器的光标所在块按下快捷键 CTRL+R,为在该块的书签添加、删除一个图标
2025-09-09 13:48试试这个是否想要的效果。
由于 Ctrl+R 是替换文本,建议改成 Ctrl+T 或其他,可通过参数配置修改,详情见参数说明。
// 通过快捷键给块书签添加删除标签 // see https://ld246.com/article/1757393544265 (()=>{ // 按键字母,由于Ctrl+R是替换,建议改成别的比如Ctrl+T const pressLetter = 'R'; // 必须大写 // 添加的表情 const emojis = '😀'; // 表情位置,prefix 开头,suffix 结尾 const emojisPosition = 'prefix'; document.addEventListener('keydown', async (event) => { // 检查是否按下了 Ctrl+R // 这里推荐用 Ctrl + T,只需要把下行的 KeyR 改为 KeyT 即可 if ((event.ctrlKey || event.metaKey) && event.code === 'Key'+pressLetter && !event.shiftKey && !event.altKey) { const cursorElement = getCursorElement(); if(!cursorElement) return; const cursorBlock = cursorElement.closest('.protyle-wysiwyg [data-node-id][data-type]'); if(!cursorBlock) return; const blockId = cursorBlock?.dataset?.nodeId; if(!blockId) return; event.preventDefault(); event.stopPropagation(); // 获取书签 const data = await requestApi('/api/attr/getBlockAttrs', { "id": blockId }); let bookmark = data?.data?.bookmark || ''; // 添加删除表情 const hasEmojis = bookmark.includes(emojis); bookmark = bookmark.replace(emojis, ''); if(!hasEmojis) bookmark = emojisPosition === 'prefix' ? emojis + bookmark : bookmark + emojis; requestApi('/api/attr/setBlockAttrs', { "id": blockId, "attrs": { "bookmark": bookmark } }); } }, true); function getCursorElement() { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); // 获取选择范围的起始位置所在的节点 const startContainer = range.startContainer; // 如果起始位置是文本节点,返回其父元素节点 const cursorElement = startContainer.nodeType === Node.TEXT_NODE ? startContainer.parentElement : startContainer; return cursorElement; } return null; } async function requestApi(url, data, method = 'POST') { return await (await fetch(url, {method: method, body: JSON.stringify(data||{})})).json(); } })();效果
-
[js] 简单实现 webdav 实时备份重要文件(密钥安全再无忧)
2025-09-09 12:34是的,也是好办法,不过最好多种方案结合,我觉得至少有一种方案是自动备份的,就像我之前帖子 你应当有个免费的 webdav(一场由浏览器升级引发的“数据灾难”) 中说的那样 重要数据绝不能仅依赖“手动备份” 时间久了总有忘的时候。
-
[js] 简单实现 webdav 实时备份重要文件(密钥安全再无忧)
2025-09-09 11:51好想法呀,这样的话,即使忘记,也可以一个个试出来,但这样会不会也可以被坏人试出来?
最好这些词自定义,这样坏人就没办法了。
-
[js] 简单实现 webdav 实时备份重要文件(密钥安全再无忧)
2025-09-09 11:300.0.3 更新内容
修改备份路径为/siyuan_backup
0.0.2 更新内容
对备份文件进行了简单的 base64 编码,并加了随机干扰码,因此解码时需要先去除前 10 位字符才行(可起到一定的安全作用)
-
SQL 问题请教
2025-09-08 11:20完整版
注意:最好把 % 文摘 之间的空格去掉(下面的示例已去掉空格),我不知道是否你故意添加的,请根据自己需要调整。
SELECT b.id, b.path, b.content FROM blocks b LEFT JOIN refs r ON b.id = r.def_block_id WHERE b.type = 'd' AND b.path LIKE '/20250304225728-0glbw2i/%' AND b.content not like '%文摘-' AND r.def_block_id IS NULL AND b.id NOT IN ( SELECT sub.parent_id FROM blocks sub JOIN refs r_sub ON sub.id = r_sub.def_block_id WHERE sub.type IN ('p', 'h', 'c', 't', 'm', 'i', 'b', 's') ); -
SQL 问题请教
2025-09-07 23:29AND b.path LIKE '/20250304225728-0glbw2i/%' 这句后面添加 and b.content like '% 文摘-' 就行了吧。
另外,你这里的 select ..., b.name 这个 b.name 应该改成 b.content 吧,或者 b.content as name
-
是否有办法指定笔记本发布?
2025-09-06 12:09其实可以用 nodejs 启动一个 web 服务,然后用思源前端代码 + 思源内核 api 实现一个简单的轻量级博客的。
然后想显示什么,怎么显示自己决定,完全后端过滤,安全可控。
缺点:不支持手机端发布,只能在 pc 端发布,不过一般博客用 pc 发布场景居多。
强烈建议,思源搞个博客功能,类似发布服务,只不过有选项可控制发布内容,博客模板等,轻量级。
还有一种方式,可以通过 思源 + pipe 最佳的笔记 / 博客方案 这个实现,对思源兼容性好,简单方便。
或者通过 solo 自建博客。
其他方式要么对思源兼容性不好,要么需要自己实现兼容。
-
请问想要深度使用思源笔记,甚至开发一些自用的小工具和插件应该学习哪些专业内容?
2025-09-05 10:33 -
现在有没有体验较好的把笔记当成知识库的 AI 插件?
2025-09-05 10:27如果对插件效果不满意 可以向作者 issue 或 github 搜 siyuan mcp 自行安装 mcp 服务
-
[css] 代码片段分享:将列表变成时间线笔记、日记
2025-09-05 10:04其实就是一个二级列表而已,一级是左侧时间线,二级是具体内容


如果操作不习惯,可以先取消样式编辑,编辑好后再恢复
或者直接用我下面这个代码
使用方法:
1 先安装 runjs 插件
2 随便新建个文档,把下面的代码放到 js 代码片段中
// 显示/隐藏时间线 // see https://ld246.com/article/1756998809429 async function main() { // css 代码 const styleContent = ` /****************************** 时间线图 ******************************/ [data-type="NodeList"][custom-setTimeLine] { overflow: hidden; >[data-type="NodeListItem"] { margin-top:0; margin-bottom:0; padding-top: 10px !important; padding-bottom: 20px !important; /* 图标 */ >.protyle-action { top: 12px; left: 105px; scale: 1.2; } /* 第一个内容块:时间 */ >.protyle-action+[data-type="NodeParagraph"] { position: absolute; margin-left: 10px; } /* 第二个内容块到最后一个内容块:内容 */ >[data-type]:not(.protyle-action+[data-type="NodeParagraph"]) { margin-left: 147px; } } /* 线条 */ >[data-type="NodeListItem"]::before { content: ""; top: 0; left: 121.4px; height: 100%; border: 1px solid var(--b3-theme-on-surface) !important; } } `; // 定义 style 的内容 const styleId = "ShowOrHideTimeLIne"; // 获取现有的 <style> 元素 let styleElement = document.getElementById(styleId); if (styleElement) { // 如果存在,则删除它 styleElement.remove(); await client.pushMsg({ msg: "已隐藏", timeout: 3000, }); } else { // 如果不存在,则创建并添加它 const newStyle = document.createElement("style"); newStyle.id = styleId; newStyle.textContent = styleContent; document.head.appendChild(newStyle); await client.pushMsg({ msg: "已显示", timeout: 3000, }); } } main(); plugin.saveAction(thisBlock.id, "显示/隐藏时间线");3 然后 js 代码块右键菜单中按下图运行下代码

4 然后在顶部工具栏 runjs 菜单中,可以动态显示和隐藏时间线

注意:
1 代码新增了 margin-top:0;margin-bottom:0; 不然在默认主题时间线之间有空隙
2 该方法显示和隐藏只是临时的,即使隐藏刷新页面仍旧是时间线,如果想记住,可以用这个代码进行调整 求隐藏已完成任务块的代码片段 - wilsons 的回帖
-
离开深圳,我在贵州山里写代码
2025-09-05 09:08可以成了自由工作公司,远程办公,唯一考核标准就是按时完成任务。
公司负责和用人单位接洽,员工只需要负责工作即可。
但相关细节还需要解决,比如社保缴纳问题,需要相关部门支持,目前国内系统不成熟。
-
思源笔记能否支持博客搭建, 笔记公有化分享
2025-09-04 13:10感觉 blossom 更像一个可部署本地的 b/s 应用。
但不知道,如果本地和远程都部署一份,如何二者同步?还是无法同步,直接连远程服务?
另外,这种部署方式,对普通用户(非开发)简直是地狱级难度。
其实,思源也是部署在本地的 b/s 应用,只不过,思源通过一键安装的方式自动部署了。
但其可取处,轻量级博客端,本地客户端可直接连接远程服务器,自带任务管理,便签等。
-
请问有插件实现 Obsidian 那样的幻灯片功能吗?
2025-09-03 22:04可以用全屏代码 [js] 全屏和宽屏 配合 pagedown pageup 按键简单实现
先 alt+y 伪全屏,再用全屏按钮真全屏,再 page down/up






