Skip to content

feat: 支持导入思源 .sy.zip 笔记 - #1166

Open
jibwf wants to merge 1 commit into
codexu:devfrom
jibwf:feature/siyuan-import
Open

feat: 支持导入思源 .sy.zip 笔记#1166
jibwf wants to merge 1 commit into
codexu:devfrom
jibwf:feature/siyuan-import

Conversation

@jibwf

@jibwf jibwf commented Jul 25, 2026

Copy link
Copy Markdown

概述

本 PR 为 NoteGen 桌面端新增思源笔记导出包(.sy.zip)导入能力。用户通过现有「导入笔记」按钮选择文件:若为 .sy.zip 则走思源导入流程,否则保持原有 Markdown 文件夹导入逻辑不变。

导入结果写入当前工作区,.sy 文档转为 Markdown,资源文件按 NoteGen 既有习惯放置在各笔记同级 {assetsPath}/ 目录(默认 assets/),Markdown 内使用相对路径引用(如 assets/image.png)。有子目录的文档会生成 {文件夹名}/{文件夹名}.md,与点击文件夹时打开同名首页文档的现有行为一致。


架构说明

用户选择 .sy.zip
  → Rust: import_siyuan_archive(解压 ZIP、校验路径、维护锁)
  → 子进程: bundled Node + siyuan-import-worker.bundle.mjs
  → TypeScript: importSiYuanData(规划 → 索引 → 转换 → 写文件)
  → 进度通过 siyuan-import-progress 事件推送到前端
  • Rust 层:负责 ZIP 安全解压、临时目录管理、worker 进程生命周期、取消/回滚
  • Worker 层:bundled Node 运行时 + 预打包 import 逻辑(避免依赖用户本机 Node)
  • TS 层.sy JSON 解析、块树转 Markdown、块引用/数据库(AV)/资源路径处理

新增文件(主要模块)

模块 路径 说明
导入核心 src/lib/import/siyuan/* converter、importer、block-index、av-loader/renderer 等
安全写文件 src/lib/fs/exclusive-file.ts 导入时禁止覆盖已有文件
Rust 导入 src-tauri/src/siyuan_import.rs Tauri command + worker IPC
共享 ZIP src-tauri/src/zip_extract.rs 路径规范化、Zip Slip 防护、大小/条目限制
进程管理 src-tauri/src/process_util.rs 进程组配置与树形终止(供 MCP/Skill/导入 worker 共用)
维护锁 src-tauri/src/maintenance_lock.rs 导入/备份互斥,避免并发写 workspace
Worker 脚本 scripts/siyuan-import-worker*.mjs 开发/打包/验证工具链
Node 运行时 src-tauri/resources/node-runtime/ 打包用占位 + LICENSE/SBOM(CI 拉取实际二进制)
测试 tests/siyuan-*.spec.mjs + fixtures 59 项 import 相关测试

对原有代码的改动(请重点审核)

1. 文件管理 / 导入入口

use-markdown-import.ts

  • 原逻辑:仅支持选择 Markdown 文件夹导入
  • 现逻辑:文件选择器同时接受 .sy.zip 和普通目录;根据扩展名分发到思源导入或原 Markdown 导入
  • 新增 import-lock.ts:Markdown 导入与思源导入互斥,避免并发

file-more-menu.tsx / file-actions.tsx / file-manager.tsx

  • 移除单独的「导入思源」菜单项,统一为「导入笔记」
  • 集成 use-siyuan-import.ts 与进度对话框 siyuan-import-dialog.tsx

folder-item/index.tsx

  • 无行为变更;已有逻辑:点击文件夹时若存在 {文件夹名}/{文件夹名}.md 则打开该文档

2. 编辑器 / 图片路径(兼容导入后的 Markdown)

tiptap-editor.tsx

  • 图片 src 转换 effect 增加对 activeFilePath 的依赖,切换文件时重新解析相对路径
  • 改进 data-relative-src 与已转换 asset:// URL 的保留逻辑,避免重复转换导致图片丢失
  • 加载内容时剥离思源零宽字符(\u200b

markdown-paragraph.ts

  • 新增 stripSiYuanInvisibleMarkdownChars,加载时清理不可见字符

utils.ts / markdown-image-path.ts

  • 新增 decodeWorkspaceImagePath,处理 URL 编码的图片路径(如 %20

以上改动对非思源笔记的影响:仅增强图片路径解析鲁棒性,不改变正常写作流程。

3. Rust 后端

backup.rs(较大改动)

  • 将原有内联 ZIP 解压替换为共享模块 zip_extract::extract_zip_safely
  • 新增路径去重策略(大小写敏感/ insensitive 探测),修复 macOS/Windows 上备份恢复可能覆盖的问题
  • 导入/导出/从文件恢复均加 MaintenanceGuard,与思源导入互斥
  • 抽取 restore_app_data_from_temp,消除重复逻辑
  • 新增单元测试(路径 dedup、大小写保留)

mcp_runtime.rs / skill_runtime.rs

  • 删除重复的进程组配置/终止代码,统一使用 process_util.rs
  • 行为等价,仅为重构 dedup

lib.rs / main.rs

  • 注册新 commands:import_siyuan_archivecancel_siyuan_import
  • 注册新模块:siyuan_importzip_extractprocess_utilmaintenance_lock
  • 应用退出时调用 shutdown_active_import

printing.rs / app_setup.rs

  • 小改动,适配模块结构或维护锁(无功能变化)

tauri.conf.json

  • 将 worker bundle 与 node-runtime 纳入打包资源

4. CI / 构建

.github/workflows/release.yml

  • 新增 Node 运行时拉取步骤(fetch-node-runtime.mjs
  • 新增 worker bundle 构建与校验(build-siyuan-worker + verify:siyuan-worker
  • 确保发布包内含完整导入能力

package.json

  • 新增脚本:test:importbuild:siyuan-workerverify:siyuan-workerverifysmoke:desktop-siyuan

5. 国际化

messages/*.json

  • 新增思源导入相关文案(进度阶段、成功/部分成功/取消/错误提示等)

安全考量

  • ZIP 解压:路径 canonicalization、拒绝 .. traversal、条目数/uncompressed 大小上限
  • 导入目标目录:限定在 app_data/article 或用户自定义 workspace 根下
  • 写入策略:writeTextFileExclusive / copyFileExclusive,不覆盖已有笔记或资源
  • 取消导入:回滚已写 Markdown 与已复制资源
  • Worker IPC:stdout NDJSON 行长度限制、stderr 截断

已知限制 / 降级行为

  • 部分思源块类型(widget、embed_block 等)转为 degraded 占位,计入导入报告
  • 属性数据库(AV)行/列过多时会截断并报告
  • 未知块类型不会静默丢弃,会标记为 degraded
  • 移动端不支持思源导入(与原 Markdown 导入策略一致)
  • 发布签名(TAURI_SIGNING_PRIVATE_KEY)缺失时 updater 签名步骤仍会失败,不影响 .app 构建

测试

自动化测试

pnpm verify
# 包含 typecheck + lint + test:import(59项) + verify:siyuan-worker

macOS 构建与实测

已在 macOS(Apple Silicon / arm64) 本地完成桌面端构建与手动验证:

  • 构建命令:pnpm tauri build
  • 产物:NoteGen.app(v0.32.1,arm64),已安装至 /Applications/NoteGen.app 进行实测
  • 构建结果:应用本体与 .dmg 打包成功;末尾 updater 签名因缺少 TAURI_SIGNING_PRIVATE_KEY 报错,不影响 .app 本地安装与功能验证

实测内容(思源 .sy.zip 导入):

  1. 使用真实导出包(Security 笔记本)完成完整导入
  2. 统一「导入笔记」入口:选择 .sy.zip 走思源导入,选择文件夹仍走原 Markdown 导入
  3. 笔记本顶层结构正确(仅 Security,无多余 assets 笔记本或 .siyuan-import 隐藏目录)
  4. 文件夹首页文档符合 NoteGen 习惯(如 VPN/VPN.md,点击文件夹可打开同名首页)
  5. 资源文件按 NoteGen 习惯写入各笔记同级 assets/ 目录,Markdown 引用为 assets/...,Cryptography 等章节图片可正常显示
  6. 导入进度对话框、部分成功/降级报告、取消后文件树刷新均正常

手动验证建议(其他平台/Reviewer)

  1. 准备思源「导出 .sy.zip」测试包
  2. 桌面端 → 导入笔记 → 选择 .sy.zip
  3. 确认笔记本结构、文件夹首页文档(VPN/VPN.md)、图片显示
  4. 确认导入过程中取消可回滚
  5. 确认与普通 Markdown 文件夹导入不冲突

变更规模

  • 80 files changed, +15082 / -304 lines
  • 新增代码为主;对原有代码的侵入集中在:导入入口、编辑器图片路径、backup ZIP 解压重构、进程管理 dedup

在桌面端新增思源笔记导出包(.sy.zip)导入能力,复用现有「导入笔记」入口,
将 .sy 文档转换为 Markdown 并按 NoteGen 习惯放置资源文件。同时抽取安全的
ZIP 解压与进程管理模块,供备份恢复与导入 worker 共用,并补充完整测试与 CI 校验。

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants