- 数据同步
【免费下载链接】obsidian-livesync
本篇指南基于 obsidian-livesync 仓库的 CONTRIBUTING.md 与 devs.md 编写,系统讲解如何为 Self-hosted LiveSync(一个使用 CouchDB、MinIO/S3 或 WebRTC P2P 在设备间同步 Obsidian 库的插件)提交高质量贡献。读完本文,你将掌握完整的开发环境搭建流程、提交 PR 前必须通过的验证命令、仓库的文档与 UI 文本风格约定、翻译(i18n)贡献的完整工作流,以及涉及@vrtmrz/livesync-commonlib共享库时如何正确变更依赖边界。
项目与贡献概览
Self-hosted LiveSync 是一个 Obsidian 插件,核心能力是把 Vault(笔记库)的变更即时同步到其他设备,后端可选用自托管的 CouchDB、S3 兼容对象存储(如 MinIO),或无需中心存储的 WebRTC P2P 模式。代码库采用模块化架构,技术栈为 TypeScript、Svelte 与 PouchDB(详见 devs.md)。
项目欢迎各类贡献,包括:Bug 报告、功能请求、文档改进、翻译以及 Pull Request。所有贡献都需要遵守以下三个基本要求:
- 提交 PR 前在本地跑通验证脚本;
- 文档与用户可见文案遵循统一的写作风格;
- 涉及共享同步逻辑的变更,必须通过
livesync-commonlib仓库走独立的贡献流程。
开发环境搭建
首次搭建
按 CONTRIBUTING.md 给出的三个步骤即可完成从零到可构建的开发环境:
git clone https://github.com/vrtmrz/obsidian-livesync npm ci npm run build说明:
npm ci严格按照package-lock.json安装依赖,而不是像npm install那样可能改写锁文件;npm run build使用 esbuild 执行生产构建(对应 package.json 中的esbuild.config.mjs production);- 构建产物
main.js即插件本体,可以安装进 Obsidian 的 Vault 中进行调试。
切换分支时的注意事项
仓库存在补丁分支等历史分支。切换分支时如果锁文件发生变化,必须重新执行依赖安装,否则可能出现依赖与代码不匹配导致的诡异错误:
git checkout 0.25.70-patch1 # tag 或分支名 npm ci npm run build依赖安装的双路径验证
仓库同时面向「普通开发者」与「社区目录审查(Community Review)」两种安装路径,两者使用的 npm 版本不同。修改package.json、工作区清单或package-lock.json之后,需要同时验证两条安装路径(详见 devs.md):
npm ci --ignore-scripts npx --yes npm@10.9.2 ci --ignore-scripts其中npm@10.9.2是当前项目侧对 Community Review 安装路径的兼容性检查版本。如果 Community Review 报告大量外部包的类型错误,先确认依赖是否安装成功——安装失败会让所有未解析的外部类型都表现为下游不安全类型(unsafe-type)问题,此时不要急于修改源码导入或 lint 规则。
提交 PR 前的代码验证体系
CONTRIBUTING.md 明确要求:提交 Pull Request 之前,必须在本地运行验证脚本,确保没有语法、类型或 lint 错误。
类型检查与 lint
npm run check从 package.json 的check脚本定义可以看到,它实际串联了六项检查:
tsc-check:主工程 TypeScript 类型检查(tsc --noEmit);tsc-check:apps:对src/apps/browser、src/apps/cli、src/apps/webapp、src/apps/webpeer五个应用子工程分别做类型检查;lint:ESLint 检查src目录(使用--cache增量缓存);lint:community -- --quiet:应用社区目录阻塞规则,只输出错误级别问题;lint:community:tools:对_tools目录的工具脚本执行零警告上限的检查;svelte-check:Svelte 组件类型检查(--fail-on-warnings)。
此外还有check:compatibility(在precheck:compatibility中被调用),它通过 utils/check-compatibility.js 验证构建产物main.js是否兼容 iOS 15 级别的运行环境。
如果只想查看 Community Review 的非阻塞建议,可单独运行:
npm run lint:community单元测试
npm run test:unit单元测试使用 Vitest,配置见 vitest.config.unit.ts。仓库约定:单元测试文件命名为*.unit.spec.ts,与被测实现放在同一目录(例如ChunkFetcher.unit.spec.ts),在 Node.js 中运行,排除 harness 与集成测试。
文档契约检查(Inspect Troubleshooting)
当修改troubleshooting或recovery相关文档时,必须运行只读的检查器:
npm run inspect:troubleshooting该命令对应 _tools/inspect-troubleshooting-docs.ts,它执行三类契约校验,并输出 JSON 结果(包含ok、checkedFiles、checkedLocalReferences、errors四个字段),当契约过期时以非零退出码结束:
- current-label 检查:校验 docs/troubleshooting.md 是否仍包含 src/common/messagesJson/en.json 中定义的当前 UI 文案(如
TweakMismatchResolve.Action.UseConfigured等键); - retired-label 检查:确保文档中没有残留已退役的旧文案(如
`Update with mine`、`Use configured`); - local-reference 检查:对
docs/troubleshooting.md、docs/recovery.md、docs/tips/p2p-sync-tips.md三份指南中的所有本地 Markdown 链接做存在性校验,任何指向不存在文件的链接都会被记录为错误。
因此,更新故障排查文档时,务必同步核对它引用的 UI 文案与本地文件路径,保证文档契约持续有效。
E2E 测试与 CI
如果具备合适的 Linux + Docker 环境,强烈建议运行 CLI 端到端测试(详见 devs.md 与 src/apps/cli/testdeno)。若本地无法运行 E2E,请在 PR 描述中明确写明「Please run CI tests」,请求 CI 代为执行。
仓库的测试体系呈金字塔结构,可按变更范围选择最窄的测试命令:
| 测试类型 | 命令 | 说明 |
|---|---|---|
| 单元测试 | npm run test:unit | Vitest,Node.js 环境 |
| 覆盖率 | npm run test:unit:coverage | 单元测试 + 覆盖率报告 |
| 集成测试 | npm run test:integration | 连接真实 CouchDB 实例的*.integration.spec.ts |
| 自托管工具契约 | npm run test:setup-tools | Deno 校验 CouchDB / 对象存储 / P2P Setup URI 契约 |
| CLI P2P E2E | npm run test:e2e:cli:p2p | Compose 中的规范 P2P 验证 |
| 浏览器应用 | npm run test:browser-apps | WebApp 与 WebPeer 的 Chromium 测试 |
| 跨应用互操作 | npm run test:e2e:browser-apps:interop | WebApp → WebPeer → CLI 互操作 |
| 真实 Obsidian E2E | npm run test:e2e:obsidian:local-suite | 启动真实 Obsidian 的本地套件 |
其中真实 Obsidian E2E(test/e2e-obsidian/)用于验证启动序列、Vault 反射、RedFlag 流程、Fast Setup、设置对话框、对象存储回归等依赖 Obsidian 本身的行为。服务类测试通过 Docker 启动 CouchDB 与 MinIO(S3)作为测试基础设施:
npm run test:docker-all:start # 启动所有测试服务 npm run test:integration # 运行相关的服务支撑测试套件 npm run test:docker-all:stop # 停止服务注意:服务已在运行时启动脚本会失败,需要先停止再启动。
文档与 UI 文本的风格规范
为保证项目一致性,贡献文档或用户可见文案时必须遵循 docs/terms.md 与 docs/glossary.md 中确立的写作惯例。CONTRIBUTING.md 给出了六条核心规则:
- 拼写(Spelling):优先使用地区中立的拼写;若无中立词,则与代码库一致采用英式拼写(例如偏好
-ise/-isation后缀而非-ize/-ization)。但替代拼写不视为错误; - 牛津逗号(Oxford Comma):列表含三项及以上时使用序列逗号,例如
settings, snippets, and themes; - 逻辑标点(Logical Punctuation):标点放在引号之外,除非标点本身属于被引用文本,例如写
'dialogue'而不是'dialogue,'; - 禁止缩写(No Contractions):正文与文档避免缩写,写
do not而非don't,写cannot而非can't; - 肯定表述(Affirmative Phrasing):面向用户的对话中避免用否定形式提问,以降低翻译与解释歧义;
- 特定词汇(Specific Words):文档与用户文案用
dialogue(源码内才用dialog);用户可见文本用连字符形式plug-in(仅在配置项或技术语境中用plugin)。
项目术语的完整定义见 Project glossary,其中包含可能不出现在用户界面中的内部开发与设计术语。
翻译(i18n)贡献流程
Self-hosted LiveSync 拥有独立的多语言文案目录。详细教程见 docs/adding_translations.md,核心流程如下。
为已有文案补充翻译
编辑
src/common/messagesYAML/下人类可读的 YAML 文件(仓库提供de、es、fr、he、ja、ko、ru、zh、zh-tw九种语言及默认英文en);执行烘焙命令,将 YAML 编译为 JSON 与 TypeScript 常量:
npm run i18n:bakei18n:bake实际串联了三个子步骤(见 package.json):i18n:yaml2json(调用 _tools/yaml2json.ts)、i18n:bakejson(调用 _tools/bakei18n.ts 生成src/common/messages/combinedMessages.prod.ts)、i18n:format(Prettier 格式化产物);以开发模式构建插件并安装到测试 Vault 中运行;
检查
.obsidian/ls-debug目录下生成的missing-translation-yyyy-mm-dd.jsonl文件,把缺失的键补进 YAML 目录;再次烘焙并构建,在相关流程中确认显示文本与占位符替换正确。
提交时必须把编辑过的 YAML 与所有重新生成的 JSON、TypeScript 资源一起提交。
在代码中使用翻译
代码中通过三个翻译函数消费文案(实现在 src/common/translation.ts):
$msg("dialog.someKey"); // 带类型键的翻译,支持自动补全与参数替换 $t("Some message"); // 直接翻译 $f`Hello, ${userName}`; // Tagged Template Literal 形式的格式化消息其中$msg(key, params)支持${placeholder}形式的运行时参数替换。语言解析逻辑会把 Obsidian 的语言代码映射到目录键(例如zh-cn、zh-hans归入zh,zh-tw、zh-hant归入zh-tw),未匹配时回退到默认英文def。缺失翻译会通过__onMissingTranslations回调上报并写入ls-debug日志。
让一条消息变得可翻译
当新文案措辞还在打磨阶段时,可先加入 src/common/messages/LiveSyncProvisionalMessages.ts,获得类型化的英文回退,而无需立即更新所有语言。文案稳定后:
- 将英文条目从
LiveSyncProvisionalMessages.ts移到src/common/messagesYAML/en.yaml,并在同一变更中删除临时条目; - 把源码中的字面量替换为
$msg()等翻译辅助函数; - 运行
npm run i18n:bake并验证受影响的工作流。
若新消息属于 Commonlib(共享同步逻辑库)而非应用本体,则应先在 Commonlib 中定义规范英文条目与键类型,再在 LiveSync 中补充翻译;未翻译的语言自动回退到 Commonlib 的规范英文。
Commonlib 变更:共享同步逻辑的边界
Shared synchronisation behaviour 由@vrtmrz/livesync-commonlib包提供(当前锁定版本见 package.json 中的@vrtmrz/livesync-commonlib依赖)。该包是平台无关的同步逻辑层,被 CLI、WebApp、WebPeer 与外部工具共享。
如果希望修改这个共享库,必须遵循独立流程:
- 向 livesync-commonlib 仓库提交单独的 PR;
- 验证打包(packed)后的产物;
- 回到本仓库更新锁定的依赖版本。
两个仓库的边界规则是:npm ci只安装锁文件记录的精确产物,本仓库不编译 Commonlib 源码、也不提交回退声明(fallback declarations)。跨越两个仓库的变更,必须先产出通过独立包检查的 Commonlib 打包产物,在 LiveSync 中安装该精确产物并跑通类型检查、单元测试、应用构建、CLI E2E 及必要的真实 Obsidian E2E,发布前再替换为已评审的不可变包版本。
许可证声明
项目采用 MIT 许可证。根据 CONTRIBUTING.md 的约定,提交贡献即表示同意你的贡献以 MIT 许可证授权发布。若计划使用机器翻译引擎生成翻译资源,请先确认引擎的服务条款与项目许可证兼容(src/common/rosetta.ts 中有同样提醒)。
小结:贡献前检查清单
完成一篇贡献前,对照以下清单逐项确认:
- ✅ 环境:
npm ci+npm run build通过; - ✅ 质量门:
npm run check零错误(类型、lint、Svelte、兼容性); - ✅ 测试:
npm run test:unit通过,涉及远程数据库行为时补充*.integration.spec.ts集成测试; - ✅ 文档契约:改动 troubleshooting/recovery 文档后运行
npm run inspect:troubleshooting; - ✅ 风格:文档与 UI 文案符合拼写、标点、术语规范(docs/terms.md);
- ✅ 翻译:新增文案按 YAML → 烘焙 → 验证流程处理,缺失翻译写入
ls-debug检查; - ✅ 边界:涉及共享逻辑时走 Commonlib 独立 PR,不在本仓库塞源码镜像或回退声明;
- ✅ 依赖:升级依赖后检查构建产物 diff,只保留预期变化。
遵循以上流程,你的 PR 就能顺畅通过 CI 与社区目录审查,成为 Self-hosted LiveSync 生态的一部分。
- 数据同步
【免费下载链接】obsidian-livesync
相关推荐
cleanlab 开发环境搭建与代码贡献指南:从虚拟环境、测试到发布的全流程实战
cleanlab 开发环境搭建与代码贡献指南:从虚拟环境、测试到发布的全流程实战 导读 本文是面向 cleanlab 贡献者的开发者指南,完整梳理了从搭建本地开
人工智能机器学习数据清洗数据质检AppImageLauncher开发指南:从环境搭建到代码贡献全流程
AppImageLauncher开发指南:从环境搭建到代码贡献全流程 你是否曾为Linux下AppImage应用的集成管理感到困扰?作为开发者,你是否想为开源社
桌面应用CLICode-Graph-RAG 贡献指南:从开发环境搭建、代码规范到 CI/发布全流程实战
Code Graph RAG 贡献指南:从开发环境搭建、代码规范到 CI/发布全流程实战 本文是 Code Graph RAG 仓库 docs/contribu
人工智能RAG知识图谱MCP 服务开发者工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考