首页
/ 思源笔记 v2.9.5 深度解析:面包屑交互重构、.sy 文件单行 JSON 存储与属性视图「表格化」

思源笔记 v2.9.5 深度解析:面包屑交互重构、.sy 文件单行 JSON 存储与属性视图「表格化」

2026-09-08 19:56:11作者:昌雅子Ethen

本篇文章基于思源笔记(Siyuan)v2.9.5 的官方发布说明(繁体中文版,另有简体中文版英文版),结合仓库当前源码,对这一版本在面包屑组件、编辑器细节、.sy 存储格式、属性视图(Attribute View)与内核网络 API 等方面的变化做逐项展开。读完你将理解:为什么该版本值得升级、云同步为何在 v2.9.4 处设下"版本门槛"、.sy 单行 JSON 配置项在前后端的完整生效链路,以及插件开发者可用的新事件总线与 /api/network/forwardProxy 内核 API 的调用方式。

版本概览:细节打磨 + 数据格式兼容的一版

官方概述将其定位为"改进了面包屑和一些细节"的版本,同时明确了两点升级诉求:

  1. 修复了工作空间文件夹名称含非 ASCII 字符时无法导出 Data 的问题,涉及所有使用非英文/非纯 ASCII 目录名的用户,例如中文用户名路径下的工作空间;
  2. 云同步兼容门槛收紧:由于旧版本存在可能导致云端数据损坏的问题,v2.9.5 发布之后,官方数据同步不再支持 v2.9.4 之前的旧版本。使用官方数据同步的用户必须升级到 v2.9.4 及以后版本。

这一"数据安全红线"式声明属于服务端兼容策略的常见做法——客户端版本过旧时会与新版服务端协议不兼容,强行同步可能引入脏数据,因此上游以版本下限作为兜底保护。

除上述两点外,本版本变更集中在三块:功能改进 15 项、缺陷修复 5 项、开发者能力 12 项,其中开发者侧的重头戏是属性视图(Attribute View)在 v2.9.5 首次支持"表格"形态及其配套列类型。下文按此脉络逐一展开。

面包屑(Breadcrumb)组件体验重塑

v2.9.5 的多项改动围绕"面包屑"展开,说明该版本在文档导航细节上做了集中打磨:

  • 改进移动端面包屑(issue #8623):针对窄屏下的面包屑交互与布局进行了适配优化;
  • 在面包屑右侧增加文档块标(issue #8654):用户可以直接从面包屑最右侧唤出文档级菜单,进而对整篇文档执行只读/全宽等属性操作,不必再回到文档树或编辑器顶部图标;
  • 改进面包屑转义文本(issue #8679):处理了特殊字符(如 <>、引号等)在面包屑中显示被错误转义的问题;
  • 动态计算面包屑高度(issue #8674):面包屑高度不再依赖固定值,而是随内容动态测量,避免文档标题过长时挤压/溢出编辑器区域。

从当前源码看,面包屑"更多菜单"的弹出逻辑集中在 app/src/protyle/breadcrumb/index.ts:点击文档块标后会先通过 fetchPost 拉取文档统计信息(response.data.stat 中包含 runeCountwordCountlinkCountimageCountrefCountblockCount 等),随后追加只读的文档统计菜单项,并向插件系统发出 open-menu-breadcrumbmore 事件(详见后文"开发者能力"章节)。这说明 v2.9.5 的面包屑并不是单纯的展示栏,而是文档级操作与插件扩展的入口。

编辑器与移动端的交互细节优化

除面包屑外,功能改进清单还覆盖了导出预览、移动端生命周期、集市、同步与关系图等模块:

变更点 issue 说明
导出预览模式下页签切换,大纲跟随切换 #8669 导出预览中切换页签时,右侧大纲不再滞留旧页签内容,而是跟随当前预览文档联动
移动端「退出应用」时保存文档浏览状态 #8670 记录退出前正在浏览的文档,下次启动恢复浏览位置
改进集市界面布局对齐 #8671 集市(Marketplace)卡片/列表的对齐细节修正
改进云端数据同步报错文案 #8675 同步失败时的提示信息更明确,便于判断是网络、账号还是版本原因
改进「关系图」设置界面 #8676 关系图(Graph View)的设置项布局与文案调整
停用账号前需输入用户名和密码进行校验 #8680 账号停用属于高风险操作,强制二次身份确认,防止误操作或越权
改进设置界面 #8685 通用设置界面布局细节优化
反链链接面板颜色不再受提及折叠状态影响 #8688 反链面板(Backlink)中链接高亮颜色与"提及/折叠"状态解耦,避免状态切换导致颜色跳变
更新移动端缩进/反向缩进图标 #8698 工具栏图标样式刷新
改进桌面端创建工作空间交互 #8700 首次启动/切换工作空间的创建流程更顺畅

其中"关系图"与"反链"分别对应内核中的 kernel/model/graph.gokernel/model/backlink.go 数据服务,这类纯前端 UI 改动在桌面端与移动端代码中各自维护实现,属于典型的"端侧体验收敛"型发布。

.sy 文件单行 JSON 存储

.sy 是思源文档在磁盘上的持久化格式,本质是一个 JSON 结构的文档树。历史上思源默认将其格式化(多行缩进)存储,便于人工阅读排查。v2.9.5 新增能力(issue #8712):支持以单行 JSON 格式保存 .sy 文件,同时覆盖属性视图的 .json 文件。这是文件系统层面的一个可配置行为,而非强制切换。

配置项与前后端生效链路

  • 前端设置项位于「设置 → 文件树」中,开关绑定的配置键为 fileTree.useSingleLineSave,见 app/src/config/tabs/fileTab.ts
  • 该键的类型声明在 app/src/types/config.d.ts,注释明确写着"Whether to save the content of the .sy file as a single-line JSON object";
  • 内核侧配置结构体字段定义于 kernel/conf/filetree.go,JSON 键同样为 useSingleLineSave("使用单行保存文档 .sy 和属性视图 .json");
  • 配置读取时,kernel/model/conf.go 会把该值同步到全局变量 util.UseSingleLineSave;用户在设置界面保存配置后,kernel/api/setting.go 同样会刷新该全局变量,保证无需重启立即生效
  • 实际写入时,kernel/model/export.go(文档树渲染落盘)与 kernel/model/import.go(导入/转存)都会判断 util.UseSingleLineSave:为 false 时对渲染结果做缩进美化,为 true 时直接以紧凑的单行 JSON 落盘。

关于 .sy 的文件级格式约定,可进一步参考仓库中的 SY-FORMAT 说明(中文见 SY-FORMAT.zh-CN.md)。

单行格式的价值与取舍

从工程角度看,单行 JSON 存储主要有三类收益:

  1. 显著减小文件体积:去掉换行与缩进空格后,包含大量子块的文档磁盘占用明显下降,云同步与本地备份的数据量随之减少;
  2. 利于版本控制与差异对比:单行格式下每个文档对应一条紧凑记录,配合 Git 等工具做内容级 diff 时更稳定,不会因缩进变动产生大量噪声差异;
  3. 便于脚本与程序化处理:对 JSON 解析器更友好,适合二次开发工具批量读取。

代价是人类直接阅读与手改 .sy 文件的体验下降。因此思源将其做成一个可开关的配置项而不是默认强制。若更看重可读性与调试便利,保持默认的多行缩进格式即可。顺带一提,与该配置相邻的 largeFileWarningSize(大文件警告阈值,默认 8MB,见 kernel/conf/filetree.go)用于在编辑超大文档/超大属性视图时给出性能提示,两者共同服务于大规模文档场景的存储与编辑体验。

行级元素合并策略调整

issue #8713 描述了一项编辑器底层行为变更:"不再自动合并相邻换行的行级元素"。

在思源的块级编辑器(基于 Protyle/WYSIWYG)中,同一段落内换行产生的相邻行级元素(行内节点)过去会被编辑器自动合并;v2.9.5 起这一自动合并被移除。其意义在于:当两行各自带有不同的行级属性(例如字体、颜色、行内公式/代码标记),或者用户通过换行有意分隔渲染内容时,编辑器将保留这两行元素的独立性,不再静默改写结构,从而保证复制、导出与排版结果符合用户原始输入。这属于"少干预、保原样"的编辑器策略调整,对追求精确排版的长文档用户更为友好。

缺陷修复盘点与实现位置

v2.9.5 修复的 5 个缺陷覆盖了导出、表格、复制与排版四大场景:

修复项 issue 影响面
工作空间文件夹名含非 ASCII 字符时无法导出 Data #8678 中文/日文等多字节路径下的「导出 Data」失败
表格单元格内三击全选后无法修改字体外观 #8703 表格中三击选中整格文本后,字号/字体颜色等外观修改失效
HTML 块相关复制问题 #8706 HTML 块在复制/粘贴场景下的内容异常
列表项带特定自定义属性值时复制内容不正确 #8707 列表项携带特定 custom-* 属性时复制结果错乱
标题块父级构造列表项后「优化排版」解析异常 #8709 将标题块转换为列表子项后执行"优化排版"出现解析错误

其中 #8678 是本次最重要的缺陷修复:导出 Data 的入口是内核 API /api/export/exportData(路由注册见 kernel/api/router.go,处理函数位于 kernel/api/export.go),该功能会把整个工作空间打包为数据备份。当工作空间绝对路径中混入非 ASCII 字符(如用户名含中文)时,打包/解包环节存在路径处理缺陷导致失败。该问题修复意味着以中文等非英文目录名创建工作空间的用户在 v2.9.5 之后可以正常执行「设置 → 导出 → 导出 Data」的完整数据备份流程。其余复制类缺陷集中在剪贴板与块属性序列化逻辑(内核侧可参考 kernel/util/clipboard.go 与块属性处理模块 kernel/treenode),"优化排版"则与 kernel/model/format.go 的排版重排逻辑相关。

开发者能力(一):属性视图(Attribute View)迈向表格化

v2.9.5 的开发者清单几乎全部围绕属性视图展开,标志着这一面向"结构化知识管理"的能力开始成熟:

  • 编辑器支持属性视图 - 表格(issue #7536):编辑器内首次原生支持以"表格"形态渲染属性视图;
  • 属性视图列排序(issue #8663):支持对列做自定义排序;
  • 属性视图添加数字类型列(issue #8690):新增 number 列类型,可存储并参与排序/计算;
  • 属性视图添加文本类型列(issue #8693):新增 text 列类型;
  • 属性视图添加选择类型列(issue #8694):新增 select 列类型,配合下拉选项完成枚举值录入;
  • 属性视图支持过滤、属性和排序面板中的项目排序(issue #8691):三个配置面板中的项目排列顺序可调;
  • 块数据同步至属性视图(issue #8696):块内容/块引用可向属性视图行同步,为"块 ↔ 数据库行"联动打下基础。

"块数据同步至属性视图"意味着属性视图不只是独立的二维表,它能够感知文档树中的真实块(block)——这是属性视图与普通表格的本质差异,也为后续基于属性视图构建看板、画廊等视图形态埋下伏笔。从仓库现状看,属性视图相关的内核实现非常庞大:数据层与表格/画廊/看板各视图布局实现在 kernel/av(如 av.golayout_table.golayout_gallery.golayout_kanban.go),模型层在 kernel/model/attribute_view.go 及同目录 attribute_view_*.go 系列,SQL 查询/缓存层在 kernel/sql 下的 av*.go 文件,内核 API 入口则在 kernel/api/av.go。可以说 v2.9.5 的表格列类型与排序只是起点,如今已成长为支持数字/文本/选择/日期/资源等多种列类型、多视图形态的大型子系统。

开发者能力(二):插件事件总线新增 open-menu-breadcrumbmore

插件系统在本版本获得了一个新事件类型:open-menu-breadcrumbmore(issue #8666)。事件类型名收录在事件总线类型联合中,见 app/src/types/index.d.ts。实际触发位置在面包屑"更多菜单"弹出处(app/src/protyle/breadcrumb/index.ts):

if (protyle?.app?.plugins) {
    emitOpenMenu({
        plugins: protyle.app.plugins,
        type: "open-menu-breadcrumbmore",
        detail: {
            protyle,
            data: response.data.stat, // 文档统计:字数、块数、引用数等
        },
        separatorPosition: "top",
    });
}

插件监听该事件后,即可在面包屑右侧的文档菜单中注入自己的菜单项,detail.data 携带了当前文档的统计信息(runeCountwordCountblockCountlinkCount 等),detail.protyle 则给出编辑器实例上下文。这使得插件无需再通过 DOM hack 就能扩展"文档级操作"入口。

同批还补充了 bind this 事件总线示例(issue #8668):当插件回调中需要访问插件实例(如调用 this.logthis.loadData)时,事件监听函数应使用箭头函数或显式绑定 this,避免在事件回调的独立作用域中丢失插件上下文——这属于典型的 JS this 绑定陷阱,官方通过示例帮助插件作者规避。

开发者能力(三):内核 API /api/network/forwardProxy

本版本新增了一个面向管理员的服务端网络转发 APIPOST /api/network/forwardProxy(issue #8724)。路由注册于 kernel/api/router.go,并挂载了 CheckAuth(登录校验)与 CheckAdminRole(管理员角色校验),实现位于 kernel/api/network.go 起的 forwardProxy 函数。

请求参数

参数 是否必填 默认值 说明
url 目标地址,仅允许 http/https 协议,非法地址返回错误码 1
method POST HTTP 方法,服务端会转为大写
timeout 7000(毫秒) 请求超时,小于 1 时回退到默认 7000ms
redirect true 是否跟随重定向,传 false 时使用不跟随重定向策略
headers 请求头,数组元素为键值对对象,逐项设置
contentType application/json 请求 Content-Type
payloadEncoding json 载荷编码:jsonbase64/base64-stdbase64-urlbase32/base32-stdbase32-hexhextext
payload 按需 请求体;二进制类编码(如 base64)会先解码再发送
responseEncoding text 响应体编码,取值同上,用于将响应内容回传为文本

实现细节(kernel/api/network.go):函数先解析并校验 urlschemehttp/https 时直接返回错误码 2;随后按 methodtimeoutredirect 构建带超时与重定向策略的客户端,根据 payloadEncoding 对载荷做对应解码(错误码 3~7 分别对应 base64-std、base64-url、base32-std、base32-hex、hex 解码失败),text 以外的编码分支通过 request.SetBody 写入解码后的二进制内容,最后 request.Send(method, destURL) 发起请求;请求失败返回错误码 8,读取响应失败返回错误码 9。responseEncoding 用于把响应字节编码回文本(含各 base32/base64/hex 变体),便于上层拿到可直接落库或展示的结果。

与其他代理 API 的定位差异

仓库中已存在 POST /api/network/proxy(HTTP 代理)与 GET /ws/network/proxy(WebSocket 代理,见 kernel/api/router.go)。相比之下,forwardProxy一次性的服务端请求转发:它不建立长连接,而是让内核作为一个受控 HTTP 客户端代为向第三方 URL 发请求并把响应回传。对于桌面端渲染进程或浏览器中受同源策略限制、需要绕过跨域约束的场景,插件与前端可以借助该 API 经由本地内核完成对第三方服务的调用。因为该接口需要管理员角色,实践中应仅将其暴露给可信调用方。

升级建议与延伸阅读

  • 务必升级:如果正在使用官方数据同步,请至少升级到 v2.9.4(含)以上版本,否则将因版本兼容策略无法继续同步;
  • 注意工作空间路径:如果你的数据目录/工作空间路径含中文等多字节字符,且此前导出 Data 失败,v2.9.5 已修复该问题,建议升级后完整执行一次「导出 Data」验证数据备份能力;
  • 关注 .sy 存储格式:启用"单行保存 .sy"后磁盘占用与同步体积会下降,但文件可读性降低,按需开启即可;该配置保存在设置中的"文件树"分组下(配置键 fileTree.useSingleLineSave)。

本版本三种语言的完整发布说明均可直接查阅:v2.9.5.md(英文)v2.9.5_zh_CN.md(简体中文)v2.9.5_zh_CHT.md(繁体中文);仓库根目录的 CHANGELOG.md 汇总了全部历史版本记录。若希望深入了解内核与编辑器实现,可从 AGENTS.md 入手概览工程结构,再按上文给出的文件路径逐模块深入。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.16 K
2.78 K
kernelkernel
deepin linux kernel
C
34
18
docsdocs
暂无描述
Markdown
904
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
932
1.86 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
862
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.95 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.38 K
1.47 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
535
606
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
549
398
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Markdown
77
23