Self-hosted LiveSync 贡献指南:从环境搭建、代码验证到翻译与发布的全流程实战
2026/9/23 2:42:25 网站建设 项目流程
  • 数据同步

【免费下载链接】obsidian-livesync

项目地址:https://gitcode.com/gh_mirrors/ob/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。所有贡献都需要遵守以下三个基本要求:

  1. 提交 PR 前在本地跑通验证脚本;
  2. 文档与用户可见文案遵循统一的写作风格;
  3. 涉及共享同步逻辑的变更,必须通过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/browsersrc/apps/clisrc/apps/webappsrc/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)

当修改troubleshootingrecovery相关文档时,必须运行只读的检查器:

npm run inspect:troubleshooting

该命令对应 _tools/inspect-troubleshooting-docs.ts,它执行三类契约校验,并输出 JSON 结果(包含okcheckedFilescheckedLocalReferenceserrors四个字段),当契约过期时以非零退出码结束:

  1. current-label 检查:校验 docs/troubleshooting.md 是否仍包含 src/common/messagesJson/en.json 中定义的当前 UI 文案(如TweakMismatchResolve.Action.UseConfigured等键);
  2. retired-label 检查:确保文档中没有残留已退役的旧文案(如`Update with mine``Use configured`);
  3. local-reference 检查:对docs/troubleshooting.mddocs/recovery.mddocs/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:unitVitest,Node.js 环境
覆盖率npm run test:unit:coverage单元测试 + 覆盖率报告
集成测试npm run test:integration连接真实 CouchDB 实例的*.integration.spec.ts
自托管工具契约npm run test:setup-toolsDeno 校验 CouchDB / 对象存储 / P2P Setup URI 契约
CLI P2P E2Enpm run test:e2e:cli:p2pCompose 中的规范 P2P 验证
浏览器应用npm run test:browser-appsWebApp 与 WebPeer 的 Chromium 测试
跨应用互操作npm run test:e2e:browser-apps:interopWebApp → WebPeer → CLI 互操作
真实 Obsidian E2Enpm 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,核心流程如下。

为已有文案补充翻译

  1. 编辑src/common/messagesYAML/下人类可读的 YAML 文件(仓库提供deesfrhejakoruzhzh-tw九种语言及默认英文en);

  2. 执行烘焙命令,将 YAML 编译为 JSON 与 TypeScript 常量:

    npm run i18n:bake

    i18n:bake实际串联了三个子步骤(见 package.json):i18n:yaml2json(调用 _tools/yaml2json.ts)、i18n:bakejson(调用 _tools/bakei18n.ts 生成src/common/messages/combinedMessages.prod.ts)、i18n:format(Prettier 格式化产物);

  3. 以开发模式构建插件并安装到测试 Vault 中运行;

  4. 检查.obsidian/ls-debug目录下生成的missing-translation-yyyy-mm-dd.jsonl文件,把缺失的键补进 YAML 目录;

  5. 再次烘焙并构建,在相关流程中确认显示文本与占位符替换正确。

提交时必须把编辑过的 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-cnzh-hans归入zhzh-twzh-hant归入zh-tw),未匹配时回退到默认英文def。缺失翻译会通过__onMissingTranslations回调上报并写入ls-debug日志。

让一条消息变得可翻译

当新文案措辞还在打磨阶段时,可先加入 src/common/messages/LiveSyncProvisionalMessages.ts,获得类型化的英文回退,而无需立即更新所有语言。文案稳定后:

  1. 将英文条目从LiveSyncProvisionalMessages.ts移到src/common/messagesYAML/en.yaml,并在同一变更中删除临时条目;
  2. 把源码中的字面量替换为$msg()等翻译辅助函数;
  3. 运行npm run i18n:bake并验证受影响的工作流。

若新消息属于 Commonlib(共享同步逻辑库)而非应用本体,则应先在 Commonlib 中定义规范英文条目与键类型,再在 LiveSync 中补充翻译;未翻译的语言自动回退到 Commonlib 的规范英文。

Commonlib 变更:共享同步逻辑的边界

Shared synchronisation behaviour 由@vrtmrz/livesync-commonlib包提供(当前锁定版本见 package.json 中的@vrtmrz/livesync-commonlib依赖)。该包是平台无关的同步逻辑层,被 CLI、WebApp、WebPeer 与外部工具共享。

如果希望修改这个共享库,必须遵循独立流程:

  1. 向 livesync-commonlib 仓库提交单独的 PR
  2. 验证打包(packed)后的产物;
  3. 回到本仓库更新锁定的依赖版本。

两个仓库的边界规则是:npm ci只安装锁文件记录的精确产物,本仓库不编译 Commonlib 源码、也不提交回退声明(fallback declarations)。跨越两个仓库的变更,必须先产出通过独立包检查的 Commonlib 打包产物,在 LiveSync 中安装该精确产物并跑通类型检查、单元测试、应用构建、CLI E2E 及必要的真实 Obsidian E2E,发布前再替换为已评审的不可变包版本。

许可证声明

项目采用 MIT 许可证。根据 CONTRIBUTING.md 的约定,提交贡献即表示同意你的贡献以 MIT 许可证授权发布。若计划使用机器翻译引擎生成翻译资源,请先确认引擎的服务条款与项目许可证兼容(src/common/rosetta.ts 中有同样提醒)。

小结:贡献前检查清单

完成一篇贡献前,对照以下清单逐项确认:

  1. ✅ 环境:npm ci+npm run build通过;
  2. ✅ 质量门:npm run check零错误(类型、lint、Svelte、兼容性);
  3. ✅ 测试:npm run test:unit通过,涉及远程数据库行为时补充*.integration.spec.ts集成测试;
  4. ✅ 文档契约:改动 troubleshooting/recovery 文档后运行npm run inspect:troubleshooting
  5. ✅ 风格:文档与 UI 文案符合拼写、标点、术语规范(docs/terms.md);
  6. ✅ 翻译:新增文案按 YAML → 烘焙 → 验证流程处理,缺失翻译写入ls-debug检查;
  7. ✅ 边界:涉及共享逻辑时走 Commonlib 独立 PR,不在本仓库塞源码镜像或回退声明;
  8. ✅ 依赖:升级依赖后检查构建产物 diff,只保留预期变化。

遵循以上流程,你的 PR 就能顺畅通过 CI 与社区目录审查,成为 Self-hosted LiveSync 生态的一部分。

  • 数据同步

【免费下载链接】obsidian-livesync

项目地址:https://gitcode.com/gh_mirrors/ob/obsidian-livesync
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询