- 桌面应用
- 开发工具
- 插件系统
【免费下载链接】PicGo
:rocket: The Ultimate Image Uploader for Efficient Creators. Supports Obsidian, Typora, VS Code etc. and 60+ image hosting services (S3, GitHub, Cloudflare R2, Imgur, Aliyun OSS...). Paste, upload, done.
本篇技术指南以 PicGo 官方贡献文档(CONTRIBUTING_EN.md)为骨架,结合当前仓库源码,系统讲解贡献者从零开始搭建开发环境、遵循目录边界编写代码、扩展多语言文件以及按规范提交代码的完整流程。读完本文,你将掌握 PicGo 主进程 / 渲染进程 / 共享层的代码放置规则、跨进程事件与全局类型的集中管理方式,以及一套可直接照做的 i18n 语言文件新增与更新步骤。
一、环境准备:安装依赖与启动项目
PicGo 的贡献流程第一步是搭建本地开发环境。官方文档指定的包管理器是 yarn,安装依赖后启动开发模式:
yarn install安装完成后,通过以下命令启动项目:
yarn dev从当前仓库 package.json 的 scripts 可以看到,dev脚本实际执行的是electron-vite dev,它由 Electron、Vite 与构建插件共同驱动,会同时监听主进程(src/main)、预加载(src/preload)与渲染进程(src/renderer)的代码变更。如果你使用的是 pnpm 工作区,也可以执行pnpm install与pnpm dev,两者等价地指向同一套 electron-vite 开发流程(AGENTS.md 中明确注明 npm install 不受支持)。
启动成功后,你就拥有了一个可实时热更新的 PicGo 桌面端开发环境,可以开始编写或修改代码。
二、代码目录边界:主进程、渲染进程与共享层的放置规则
PicGo 是一个 Electron + 前端框架构建的桌面应用,贡献文档对代码归属提出了严格的目录约束,这是理解整个项目组织方式的核心:
- 只与 Electron 主进程相关的代码:放入
src/main目录; - 只与渲染进程相关的代码:放入
src/renderer目录; - 两个进程都能使用的代码:放入
src/universal目录。
关键约束:渲染进程不具备 Node.js 能力。因此,任何渲染进程需要使用 Node.js 模块(文件系统、剪贴板、原生对话框等)的代码,都必须通过
src/main/events/picgoCoreIPC.ts中注册的 IPC 事件交由主进程处理,而不是在渲染进程里直接requireNode 模块。
这条规则的底层原因在于 Electron 的安全模型:渲染进程运行在浏览器环境(且 PicGo 启用了上下文隔离),只有主进程拥有完整的 Node.js 运行时。仓库里的 IPC 总线 src/main/events/picgoCoreIPC.ts 正是这一架构的落地实现——文件底部统一的listen()方法(picgoCoreIPC.ts#L319-L332)集中注册了所有事件处理器,例如:
- 配置读写:
PICGO_GET_CONFIG/PICGO_SAVE_CONFIG(内部调用picgo.getConfig(key)与picgo.saveConfig(data)); - 相册数据库操作:
PICGO_GET_DB、PICGO_INSERT_DB、PICGO_UPDATE_BY_ID_DB等,经由AlbumDB.getInstance()完成 lowdb 的增删改查; - 剪贴板写入:
PASTE_TEXT会根据settings.pasteStyle与settings.customLink配置,通过pasteTemplate生成 Markdown / HTML / URL 等格式的文本并写入剪贴板。
从源码结构看,这条约定已经渗透到仓库的方方面面:渲染进程侧的 IPC 适配器 全部通过useIPC等桥接层向主进程发起调用,而不是直接触碰 Node API。因此,新增功能时判断“代码放哪里”的第一标准就是:它需不需要访问 Node.js 能力?
三、跨进程事件名:统一收敛到 constants.ts
由于主进程与渲染进程之间通过 IPC 通信,事件名必须全局唯一、集中管理,否则极易出现拼写错误与命名冲突。贡献文档要求:
所有跨进程事件名请统一添加在
src/universal/events/constants.ts。
查看 src/universal/events/constants.ts,可以发现它就是一个纯常量导出模块,覆盖了窗口控制(MINIMIZE_WINDOW、MAXIMIZE_WINDOW、CLOSE_WINDOW)、剪贴板(CLIPBOARD_WRITE_TEXT)、i18n(GET_CURRENT_LANGUAGE、SET_CURRENT_LANGUAGE)、相册数据库(PICGO_GET_DB、PICGO_REMOVE_BY_ID_DB)等全部事件名(constants.ts#L1-L53)。
为什么放在src/universal而不是两处各写一份?因为事件名是主进程与渲染进程的“通信协议”,共享层的定位保证了主进程ipcMain.on(constant)与渲染进程ipcRenderer.send(constant)引用的是同一个常量值,从根本上杜绝了"两边字符串不一致导致静默失效"的经典 IPC 事故。这也是 picgoCoreIPC.ts 顶部通过import { ... } from '#/events/constants'引用这些常量的原因——事件注册方与触发方共用同一份定义。
四、全局类型定义:types 目录与 enum 的强制归位
TypeScript 是 PicGo 的核心语言,为了让主进程与渲染进程共享同一套数据结构,贡献文档要求:
所有全局类型定义放在
src/universal/types/下;如果是enum,必须放在src/universal/types/enum.ts。
打开 src/universal/types/enum.ts 可以看到项目里所有跨进程使用的枚举都被收敛在此处,例如:
IPicGoHelperType(enum.ts#L8-L14):定义了uploader、transformer、beforeUploadPlugins、beforeTransformPlugins、afterUploadPlugins五类 helper 类型,与 PicGo 核心的上传流水线一一对应;IPasteStyle(enum.ts#L16-L22):markdown、HTML、URL、UBB、Custom五种粘贴格式,直接驱动 picgoCoreIPC.ts 中PASTE_TEXT的模板生成逻辑;IWindowList(enum.ts#L24-L30):SETTING_WINDOW、TRAY_WINDOW、MINI_WINDOW等窗口枚举,被窗口管理器windowManager引用;IRPCActionType(enum.ts#L54-L122):渲染进程通过 RPC 触发主进程动作的完整清单,覆盖配置、插件、版本检查、工具箱、系统与 PicGo Cloud 等全部能力。
与事件名同理,把枚举和类型放进src/universal/types/是为了让两个进程引用同一份类型定义,保证 IPC 载荷的结构在编译期即可校验。新增跨进程数据结构时,请遵循这一约定,不要散落在各自的进程目录里。
五、i18n 多语言扩展:三步新增一种语言
PicGo 面向全球用户,多语言是贡献的高频场景。贡献文档给出了新增语言的完整流程,下面结合仓库源码逐条展开。
5.1 创建语言文件并声明显示名
在public/i18n/目录下创建对应语言的 YAML 文件,例如新增简体中文可命名为zh-Hans.yml。文件内容参考已存在的 zh-CN.yml 或 en.yml 编写。
语言文件的第一行必须是LANG_DISPLAY_LABEL,PicGo 会通过它在设置界面中向用户展示该语言的名称。以 en.yml 为例:
LANG_DISPLAY_LABEL: "English"而zh-CN.yml中对应的值是简体中文。语言文件采用扁平的KEY: 文案结构,文案中支持${变量}插值,例如CONFIG_THING: Config ${c}、ALBUM_CLOUD_IMPORT_SUCCESS: Successfully imported ${num} items to cloud album。在 src/main/i18n/index.ts 的I18nManager中,所有语言文件通过yaml.load被解析为ILocales类型对象,并依据getStaticPath('i18n')找到运行时路径;若目标语言文件缺失或解析失败,会自动回退到默认语言en(i18n/index.ts#L28-L53),这正是LANG_DISPLAY_LABEL与文件命名必须严格一致的原因。
5.2 在共享层注册默认语言
新建语言文件后,需要在src/universal/i18n/index.ts中将其注册为可选项。查看 src/universal/i18n/index.ts 可以看到内置语言列表builtinI18nList:
export const builtinI18nList: II18nItem[] = [{ label: '简体中文', value: 'zh-CN' }, { label: '繁體中文', value: 'zh-TW' }, { label: 'English', value: 'en' }, { label: '한국어', value: 'ko' }, { label: '日本語', value: 'ja' }]其中label必须与语言文件中的LANG_DISPLAY_LABEL值保持一致(例如新增zh-Hans.yml时 label 填简体中文),value是语言文件名(不含扩展名,例如zh-Hans)。注册后,I18nManager的addI18nFile(file, label)与languageListgetter(i18n/index.ts#L75-L77)就会把新语言纳入设置界面的语言下拉列表。
5.3 更新语言文件后生成语言类型定义
贡献文档特别强调:如果是对已有语言文件进行更新,更新后务必运行yarn gen-i18n,确保能生成正确的语言定义文件。
需要说明的是,当前仓库的实际情况是:类型定义文件的生成已经由 Vite 插件自动化完成。仓库根目录的 AGENTS.md 明确指出:"i18n type files are auto-generated by the Vitei18nTypesPluginwhenpublic/i18n/*.ymlchanges. Do not add or rely on a manualgen-i18nstep." 具体实现见 scripts/vite-plugin-i18n-types.ts:该插件在buildStart、文件热更新等时机读取public/i18n/en.yml的顶层键,自动生成两份类型声明:
src/universal/types/i18n.d.ts:生成ILocales接口(所有翻译键的联合类型);src/renderer/i18n/i18next.d.ts:为 i18next 声明CustomTypeOptions,让渲染进程拿到完整的键名类型提示。
因此,无论你执行文档中提到的yarn gen-i18n,还是依赖 Vite 插件的自动生成,最终效果都是让翻译键获得编译期检查——一旦在代码里写错键名,TypeScript 会直接报错。新增翻译键时,务必保证en.yml、zh-CN.yml、zh-TW.yml等所有语言文件同步补齐,避免出现某语言缺失键导致回退英文的情况。
六、提交代码:清理调试痕迹并使用规范提交工具
贡献文档对代码提交提出了两条硬性要求,这也是通过 CI 检查的前置条件。
6.1 提交前自检:无多余注释与调试代码
请检查代码没有多余的注释、
console.log等调试代码。
这一步与仓库的 ESLint 配置相呼应。package.json 中提供了yarn lint(eslint --ext .js,.jsx,.ts,.tsx,.vue src/)与yarn lint:fix脚本,仓库还配置了lint:dpdm用于在src/中检测循环依赖(--exit-code circular:1)。提交前建议执行yarn check(即tsc类型检查 + lint 修复),确保代码整洁且通过类型系统校验。
6.2 使用 PicGo 代码提交规范工具
提交代码前,请执行命令
git add . && yarn cz,唤起 PicGo 的代码提交规范工具(PicGo/bump-version),通过该工具提交代码。
从 package.json 可以看到,cz脚本映射到git-cz,底层由 Commitizen 驱动(config.commitizen.path指向cz-customizable,.cz-config.cjs来自@picgo/bump-version)。同时仓库通过commitlint校验提交信息格式,其规则集直接继承自@picgo/bump-version/commitlint-picgo(package.json#L162-L166),并由husky在prepare阶段注册为 Git 钩子。
实际提交时,按文档执行:
git add . yarn czgit-cz会以交互式问答引导你选择提交类型(feat / fix / refactor / docs 等)、填写影响范围与描述,最终生成符合 Conventional Commits 规范的提交信息,从而顺利通过 Commitlint 钩子与 CI。这套工具链保证了 PicGo 的 git 历史始终可读、可检索、可自动化生成 changelog(仓库根目录的 CHANGELOG.md 正是基于规范提交维护的)。
七、小结
综上,PicGo 的贡献流程可以浓缩为一条清晰的主线:用 yarn 启动环境 → 按“主进程 / 渲染进程 / 共享层”三目录边界放置代码 → 事件名与全局类型集中注册 → 用 i18n 三步流程扩展多语言 → 清理调试代码后用yarn cz规范提交。其中最关键的心智模型是"渲染进程没有 Node.js 能力",一切需要 Node 模块的操作都必须经由 src/main/events/picgoCoreIPC.ts 中注册的 IPC 事件转发给主进程执行。掌握这些约定后,无论是修复 bug、接入新的图床,还是贡献一门新的语言,你都能在遵守项目架构的前提下快速产出可合并的代码。中文版贡献文档见 CONTRIBUTING.md,更多工程规范(Zustand 状态管理、RPC 路由约定、测试要求等)可进一步阅读 AGENTS.md。
- 桌面应用
- 开发工具
- 插件系统
【免费下载链接】PicGo
:rocket: The Ultimate Image Uploader for Efficient Creators. Supports Obsidian, Typora, VS Code etc. and 60+ image hosting services (S3, GitHub, Cloudflare R2, Imgur, Aliyun OSS...). Paste, upload, done.
相关推荐
贡献Figma-Context-MCP前必须掌握的架构与规范:从开发到提交的全流程指南
贡献Figma Context MCP前必须掌握的架构与规范:从开发到提交的全流程指南 Figma Context MCP是为AI编码代理提供Figma布局信息
AI 应用MCP 服务Quivr贡献指南:代码提交规范和贡献流程
Quivr贡献指南:代码提交规范和贡献流程 引言:成为Quivr社区的一员 还在为如何为开源项目贡献代码而困惑吗?想要加入Quivr这个充满活力的AI助手项目却
人工智能AI 应用大模型RAG后端前端olmocr贡献指南:代码规范与提交流程
olmocr贡献指南:代码规范与提交流程 痛点:开源贡献的常见障碍 你是否有过这样的经历?想要为一个优秀的开源项目贡献代码,却因为不熟悉项目的代码规范、测试要求
人工智能大模型OCR计算机视觉微调模型评测强化学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考