思源笔记 v3.1.0 技术解读:只读发布服务、剪藏管线增强与内核 API 的演进
【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间,让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan
本解读基于仓库内 v3.1.0 中文发布说明 撰写。该版本以"只读发布服务"为主线新特性,系统性改进了网页剪藏、编辑交互与导出能力,并为开发者新增了批量块属性内核 API 与 OCR 文本坐标能力。读完本文,你将掌握该版本引入的核心机制在源码层的落地形态(发布访问控制模型、块属性批量读取链路、Tesseract OCR 结果结构),并获得一份按主题整理的完整变更清单,便于对照验证与二次开发。
版本主线速览
v3.1.0 的整体定位是"发布可用性 + 细节打磨":一方面打通了只读发布服务这一关键能力,让知识库在只读场景下可以被安全地对外访问;另一方面围绕日常编辑、数据库、剪藏、导出等高频路径做了约 30 项体验改进,并修复了 15 个缺陷,同时完成三项工程重构(Mermaid v10.9.1、Electron v31.1.0、块树存储重构)。
按官方发布说明的分类,本版本变更构成如下:
| 变更类别 | 数量特征 | 代表内容 |
|---|---|---|
| 引入特性 | 1 项 | 支持只读发布服务 |
| 改进功能 | 约 36 项 | 编辑交互、数据库、剪藏、导出、渲染 |
| 修复缺陷 | 15 项 | 块移动、多窗口、播放、XSS 等 |
| 改进文档 | 1 项 | 用户指南类型过滤章节 |
| 开发重构 | 3 项 | Mermaid / Electron 升级、块树存储重构 |
| 开发者 | 2 项 | OCR 坐标返回、批量块属性 API |
引入特性:只读发布服务
本版本最重要的能力是支持只读发布服务(对应上游 PR 11367)。它意味着知识库内容可以以只读形态对特定访问者公开,而不再暴露可编辑入口,适合对外分享文档、搭建只读知识站点等场景。
发布访问控制的底层支撑
虽然发布说明只用一个条目概括了该特性,但从当前仓库源码中仍可看到这一机制完整、成体系的实现,可作为理解该版本引入能力的直接落地参照:
数据模型定义在 publish_access.go 中,每个发布访问控制项包含三个关键字段:
type PublishAccessItem struct { ID string `json:"id"` // 被控制的笔记本 / 文档 / 块 ID Visible bool `json:"visible"` // 是否发布可见 Password string `json:"password"` // 访问密码,为空表示无密码 Disable bool `json:"disable"` // 是否禁止发布 }控制状态持久化在数据目录下的
.siyuan/publishAccess.json(GetPublishAccess / SetPublishAccess),配合 30 秒内存缓存与互斥锁控制并发读写。请求侧在 serve.go 调用
GetPublishAccess()与CheckAbsPathAccessableByPublishAccess(),在对外服务层统一进行路径级放行判定。
只读语义如何落地
从源码结构可以推断,"只读 + 访问控制"由一组层次化规则共同组成:
- 密码保护:
Password非空时,通过GetPathPasswordByPublishAccess沿文档路径逐级向上查找最近一级密码;校验采用发布专用 Cookie(SetPublishAuthCookie/CheckPublishAuthCookie,见 publish_access.go),Cookie 名为publish-auth-{ID},值为 ID 与密码的 SHA-256 摘要,有效期一天。 - 禁止发布:
Disable为 true 的笔记本 / 文档将直接被过滤。内容层会替换为"禁止访问"占位块,资源、列表、搜索、标签、图、反链等所有可能泄漏路径的出口都有对应的Filter*ByPublishAccess/Filter*ByPublishIgnore过滤函数(集中在 publish_access.go)。 - 只读模式下禁用编辑入口:发布说明中另一条改进"只读模式下禁用一些菜单项"(PR 11733)与只读发布相辅相成,确保只读场景下编辑菜单不再暴露。
对于普通用户而言,使用只读发布服务的路径是:先在设置中开启对外发布 / 只读访问能力,再按需对笔记本或文档设置"可见、加密码、禁止发布",最后通过发布的访问地址即可只读浏览内容。
开发者能力升级:两个内核 API 级变更
本版本面向插件 / 集成开发者的两条变更,都能在当前仓库源码中直接定位到实现。
新增内核 API:/api/attr/batchGetBlockAttrs
此前获取块属性只能单块调用getBlockAttrs,批量场景下会产生大量往返请求。本版本新增了内部内核/api/attr/batchGetBlockAttrs(对应上游 issue 11786),一次请求读取多个块的属性。
路由注册位于 router.go:
ginServer.Handle("POST", "/api/attr/batchGetBlockAttrs", model.CheckAuth, batchGetBlockAttrs)处理函数在 attr.go,请求体示例:
{ "ids": ["20210808180117-6v0mkxr", "20230405172236-pg3l9eu"] }实现要点:
- 请求参数为
ids字符串数组,不做 ID 合法性(InvalidIDPattern)逐项校验——这与单块接口不同,说明它面向内部高频批量场景、追求吞吐; - 数据层调用 sql.BatchGetBlockAttrs:优先命中块 IAL 缓存(
cache.GetBlockIALWithBoxFallback,按 block ID 与所在笔记本 box 双键回退),未命中时经filesys.LoadTrees(ids)批量装载文档树后逐块解析属性; - 返回结构为
map[string]map[string]string,即"块 ID → 属性键值对"的映射,方便调用方直接索引,与配套的BatchGetBlockAttrsWitTrees(block.go,支持外部传入已加载树以复用)构成完整读写链路。
内核 API OCR 返回文本坐标信息
面向资产识别的/api/asset/ocr接口在本版本起会随结果返回 OCR 文本坐标信息(对应上游 PR 11738),让调用方可以拿到识别文本在图片上的几何位置,为框选高亮、图文定位等场景提供基础。
路由注册(router.go)带上了管理员与只读限制:
ginServer.Handle("POST", "/api/asset/ocr", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, ocr)接口处理函数见 asset.go,返回体中同时携带两个字段:
{ "text": "连接后的整段识别文本", "ocrJSON": [ { "left": "…", "top": "…", "width": "…", "height": "…", "conf": "…", "text": "…", "…": "…" } ] }其中
text是由所有词条text字段拼接的纯文本(便于直接建索引/搜索),ocrJSON是逐词条的完整明细。坐标信息来源于底层调用 Tesseract 时使用
tsv输出格式(ocr.go),随后按 TSV 表头逐行解析为map[string]any(ocr.go)。TSV 的left/top/width/height列即构成文本块在图片上的包围盒坐标,conf为置信度。识别任务侧由 model/ocr.go 中的
OCRAssetsJob等驱动:对尚未识别、可识别的图片资源排队执行 OCR,并限制单次任务处理数量(一次最多 7 张)以防长时间占用资源;加密笔记本内的资源会被显式跳过,避免密文图片产生无意义文本污染索引。
编辑器与交互体验改进
本版本在编辑器高频操作路径上投入了大量细节优化,相关条目按主题整理如下:
- 新建文档引导:创建空文档后提供交互指导,降低空文档的困惑感(issue 10528)。
- 行级元素:改进行级元素菜单交互(10577)、行级元素粘贴(11740);修复行级元素内
Shift+Enter失效(11766)、行级代码内粘贴转义文本异常(11778)等问题。 - 选择与光标:改进
Shift+↑/↓扩展选择(11671)、代码块内光标移动(11647)、表格内↑/↓移动(11694)、包含图片的块的多重选择(11763),以及图片居中后的选择操作(11757)。 - 标题与结构:改进展开标题的性能(10935)、优化文档标题中
↓的使用(11729);支持在开头粘贴块并将其插入上方(11677)。 - 查找与快捷键:改进
Ctrl+P与Ctrl+F(11637);转换列表支持配置快捷键(11634);修复"快捷键设置中按辅助键时无提示"(11720)。 - 超级块与嵌入块:修复移动超级块的子块异常(11609);改进嵌入块导出(11725);修复
Ctrl+X应剪切嵌入块本身而非其内容(11793)。
数据库与属性面板改进
围绕"数据库 / 属性视图"这一定位日益重要的能力,本版本进行了多项修正:
- 复制数据库表视图字段时保持字段宽度(11552);
- 改进带数据库的文档复制(11602);
- 属性面板中,数据库支持右键点击字段(11625);
- 改进"添加到数据库"搜索(11644),并修复移动端无法使用"添加到数据库"的问题(11651);
- 在书签面板中显示数据库标题(11666)。
网页剪藏与内容渲染优化
网页剪藏是本版本的另一个重点打磨方向,覆盖面从站点适配到 HTML 结构再到公式代码:
- HTML 结构化处理:改进 HTML 实体剪藏(11557)、HTML 代码剪藏(11642)、HTML 表格剪藏(11783)与 HTML 公式剪藏(11743);改进网页剪藏中转义代码块标记的处理(11643)。
- 站点适配:改进维基百科剪藏(11640)、知乎公式剪藏(11653)、StackExchange 公式剪藏(11646)。
- 渲染与内容显示:改进 Mermaid 的 Markdown 渲染(11670),本版本同步将 Mermaid 升级至 v10.9.1(11645);改进自定义表情搜索(PR 11768)与移动端自定义表情渲染(11690),自定义表情文件夹发生更改后也不再需要手动刷新(11749)。
导入、导出与文件资源
- 改进 PDF 导出(11258);改进导出 PDF 注释超链接的页码显示(11780);在 PDF 标签的右键菜单中添加"复制"(11758)。
- 导出
.sy.zip与data.zip时显示详情(11696)。 - 导出块引用
锚点哈希支持文档级别(11814)。 - Windows arm64 与 Linux arm64 不再打包 pandoc(11649),可显著减小对应平台安装包体积。
- 改进字体家族(11841);上传资源时从文件名中移除不可见字符(11683)。
- 修复:多窗口编辑时文档无法在新窗口正常打开(11610);移动文档后无法重命名(11661);启用自适应宽度时 IFrame 块不随动(11695);音频或视频偶尔无法播放(11810);图片标题转义内容重复(11681)。
- 附件相关补充:改进 IFrame、媒体资源健壮性之外,还修复了拖动和撤销 HTML 块时显示标签的问题(11656)。
其他细节与体验修复
- 文档树面板中显示"已关闭笔记本"数量(11648)。
- 笔记本配置变更后,数据同步将重新索引笔记本并重新加载界面(11850)。
- 若笔记本配置改变,同步后刷新相关状态,避免界面与磁盘配置不一致。
- 缺陷修复中较关键的安全项:搜索界面 XSS(11848)与代码块语言搜索 XSS(11869)均在本版本修复。
- 功能修复方面还包括:含有
%的行级备注无法显示(11709)、AI 自定义操作无法编辑(11791)等。
文档与工程重构
- 改进文档:改进用户指南中类型过滤章节的说明(PR 11692)。
- 依赖升级:Mermaid 升级至 v10.9.1(11645)、Electron 升级至 v31.1.0(11654)。
- 架构重构:重构块树存储(11773)。块树(BlockTree)是思源内核中"块 ID → 所在笔记本与路径"的核心索引,当前实现位于 kernel/treenode 包(如 blocktree.go、tree.go),其上承载了上述发布访问控制、批量属性读取、反链/引用过滤等大量查询路径,因此该重构的意义在于让这些高频只读索引更加稳定高效。
获取版本与继续阅读
- 完整中英日三语发布说明保存在仓库 app/changelogs 目录下,本版本目录为 v3.1.0,其余版本按 v3.x.y 分目录存放,便于横向对照相邻版本的演进脉络。
- 若希望基于源码继续验证本文提到的实现,可优先阅读 publish_access.go、attr.go、block.go 与 ocr.go 这几个核心文件。
- 内核内核 API 全量路由定义见 router.go,接入插件时可对照其中的认证、角色与只读中间件组合来评估接口的调用权限前提。
提示:本文所述发布访问控制、批量块属性与 OCR 坐标等机制在当前仓库源码中仍然可见;由于仓库持续演进,个别行为细节可能随后续版本迭代有所调整,落地时请以所使用版本的实际行为为准。
【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间,让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考