- 桌面应用
- 开发工具
- 插件系统
【免费下载链接】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.
导读
本文以 changelog/2.5.1.md 为骨架,系统拆解 PicGo 2.5.1 这一维护版本的三项变更:将核心依赖picgo升级至^2.0.1以适配 SM.MS 图床从旧域名sm.ms向s.ee的迁移;修复插件搜索在 npm 包描述为空时抛错的问题;以及刷新 GitHub 问题模板中的文档链接。读者阅读后,将理解 SM.MS 在 PicGo 中的配置模型与迁移影响面,掌握插件搜索从 npm registry 数据拉取到渲染层展示的完整调用链,以及"空描述崩溃"的根因与修复范式,并能据此完成升级验证与回归测试。
说明:本 changelog 记录的是 2.5.x 系列中的一个维护版本。当前仓库(package.json)已演进到 3.0.2,核心依赖
picgo也已升级至^3.0.1,本文所剖析的两条修复链路在此后持续迭代,但 2.5.1 引入的修复模式在现网代码中依然清晰可查。
一、版本概览:2.5.1 的三类更新
PicGo 的 changelog 采用中英双语结构,存放于仓库 changelog/ 目录,与 CHANGELOG.md 相互补充。2.5.1 的变更可归纳为三类:
| 分类 | 变更内容 | 关联编号 |
|---|---|---|
| Features | 将picgo依赖升级到^2.0.1,以支持旧版sm.ms迁移到s.ee | #1385 |
| Bug Fixes | 插件搜索在 npm 包描述为空时不再抛错 | #1383 |
| Other | 更新 GitHub bug 报告模板中的文档链接 | — |
其中,前两项属于有实际代码落点的技术变更,是本文分析的重点;第三项属于仓库元数据维护,仅作简述。
二、核心特性:picgo依赖升级至^2.0.1,为 sm.ms → s.ee 迁移铺路
2.1 变更背景
SM.MS 是 PicGo 长期内置的老牌图床服务(即smms上传器)。2.5.1 的 changelog 明确指出,此次升级核心库picgo至^2.0.1的目的,是"支持旧版sm.ms迁移到s.ee"——即 SM.MS 服务端将历史域名/接口从sm.ms迁移至s.ee,旧版本的核心库无法识别新域名下的上传与鉴权流程,因此需要随核心库一起升级。该修复由上游picgo核心库承担(参考 #1385),桌面端只需提升依赖版本即可继承能力。
2.2 SM.MS 在 PicGo 中的配置模型
虽然 2.5.1 的修复落在核心库,但桌面端的配置模型决定了迁移的影响面。从源码看,SM.MS 在 PicGo 中被视为默认图床之一:
- 类型定义 src/universal/types/types.d.ts#L389-L391 中,
ISMMSConfig仅包含一个必填字段:
interface ISMMSConfig { token: string }- 渲染层的上传器 schema 示例 src/renderer/components/main/providers/provider-mock.ts#L136-L168 给出了完整的配置项定义:
[ "smms", { summary: { id: "smms", name: "SM.MS", visible: true }, schema: [ { name: "token", type: "password", alias: "Set Token", message: "api token", default: "", required: true, }, { name: "backupDomain", type: "input", alias: "Set Backup Upload Domain", message: "Ex. smms.app", default: "", required: false, }, ], configState: { defaultId: "smms-1", configList: [ createConfigItem("smms-1", "Default", toTimestamp(84), { token: "smms_token_example", backupDomain: "smms.app", }), ], }, }, ]由此可梳理出 SM.MS 的两个核心配置参数:
- token(
password类型,必填):SM.MS 的 API Token,用于鉴权。迁移后旧 Token 是否需要更换由服务端策略决定,但配置入口不变。 - backupDomain(
input类型,可选):备份上传域名,示例值为smms.app。该字段允许用户配置备用域名以规避主域名的不可用——在sm.ms向s.ee迁移的背景下,这个"可配置备份域名"的字段设计恰好为用户提供了手动切换到新域名/备用域名的余地。
从配置结构可以推断,核心库升级后,迁移适配的主要受益点在于:使用旧sm.ms域名初始化或上传的存量用户,升级到 2.5.1(或更新版本)后,上传链路会按核心库新逻辑解析s.ee相关域名,无需在界面层改动配置结构。
2.3 SM.MS 作为默认图床的影响面
尽管本次修复在核心库,但 SM.MS 在 PicGo 桌面端代码中作为默认/兜底图床广泛存在,这也是其域名迁移牵动全局的原因:
- src/renderer/store/app-store.ts#L42:
defaultPicBed: 'smms',将smms作为默认图床。 - src/renderer/store/utils.ts#L187-L190:读取配置时以
smms作为uploader/current的兜底值。 - src/main/utils/dataReport.ts#L53(以及同文件的第 66、78、89 行):上报图床类型时同样以
'smms'作为缺省回退。
因此,任何依赖默认配置、或从未显式选择图床的用户,其上传请求在旧版本中都会走sm.ms域名的逻辑;升级到包含picgo@^2.0.1的版本后,这条链路才会识别新的s.ee域名。
三、Bug 修复:插件搜索遭遇空描述 npm 包不再抛错
3.1 问题根因
PicGo 的插件市场通过 npm registry 的搜索接口拉取候选插件。npm 上部分包未填写description字段,导致package.description为null或undefined。旧实现直接对 description 调用字符串方法(如.includes()),一旦遇到空描述就会抛出类似TypeError: Cannot read properties of undefined (reading 'includes')的异常,使整个搜索 Promise 被 reject,前端表现为插件搜索功能报错或不可用(参考 #1383)。
3.2 修复落点:适配层的字符串兜底
修复位于渲染层适配器 src/renderer/adapters/plugins.ts#L202-L225 的searchPlugins方法:
async searchPlugins (searchText: string, installedPlugins: IPicGoPlugin[]) { const response = await axios.get<{ objects: NpmSearchResultObject[] }>( `https://registry.npmjs.com/-/v1/search?text=${searchText}` ) const installedNames = new Set(installedPlugins.map((item) => item.fullName)) return response.data.objects .filter((item) => item.package.name.includes('picgo-plugin-')) .filter((item) => { // 关键修复点:先规约空值为空字符串,再调用 .includes() const description = item.package.description || '' return !description.includes('picgo.net') && !description.includes('PicGo官方') }) .map((item) => ({ name: streamlinePluginName(item.package.name), fullName: item.package.name, author: item.package.maintainers?.[0]?.username || '', description: item.package.description || '', // 输出侧同样兜底 logo: `https://cdn.jsdelivr.net/npm/${item.package.name}/logo.png`, config: {}, homepage: item.package.links?.homepage || '', hasInstall: installedNames.has(item.package.name), version: item.package.version, gui: Boolean(item.package.keywords?.includes('picgo-gui-plugin')), ing: false, } as IPicGoPlugin)) }修复包含两个层面的兜底:
- 过滤阶段:先执行
const description = item.package.description || '',将null/undefined规约为空字符串,再安全调用.includes()。同时该过滤还承担了"剔除picgo.net与PicGo官方相关描述的结果"这一业务规则,防止搜索结果混入非官方/无关条目。 - 映射阶段:输出对象中的
description: item.package.description || ''保证下游 UI 拿到的始终是字符串,避免其他组件重复踩坑。
可以推断,这一修复同时保证了maintainers?.[0]?.username(可选链)等相邻字段对缺失数据的容错,使适配层对整个 npm 数据结构的鲁棒性整体提升。
3.3 完整的插件搜索调用链
桌面端插件搜索的完整流程由 store 动作层驱动,见 src/renderer/store/plugins/actions.ts#L121-L179:
async searchPlugins (query: string) { const normalizedQuery = query.trim() if (!normalizedQuery) { pluginStoreActions.setSearchResults([]) // 空查询直接清空结果 return } const npmSearchText = buildPluginSearchKeyword(normalizedQuery) const exactMatch = usePluginStore.getState().exactMatch pluginStoreActions.setSearching(true) try { const installedPlugins = useAppStore.getState().pluginsInstalled const searchResults = await pluginsAdapter.searchPlugins( npmSearchText, installedPlugins.map((item) => ({ ... })) // 组装已安装插件信息 ) const normalizedResults = searchResults.map(mapPluginSearchResult) const filteredResults = exactMatch ? normalizedResults.filter((item) => item.fullName.includes(npmSearchText)) : normalizedResults usePluginStore.setState((state) => { state.rawSearchResults = normalizedResults state.searchResults = filteredResults state.isSearching = false }) } catch (error) { pluginStoreActions.setSearching(false) throw error } }整个链路依次为:
- 输入规整:对搜索词
trim(),空关键词直接清空结果,避免无意义的 registry 请求。 - 关键词构造:通过
buildPluginSearchKeyword生成 npm 搜索文本(含picgo-plugin-前缀语义)。 - 适配层请求:调用 src/renderer/adapters/plugins.ts 的
searchPlugins,请求https://registry.npmjs.com/-/v1/search,并按picgo-plugin-前缀、描述过滤规则筛选;这一层正是空描述兜底修复的所在地。 - 结果规范化:
mapPluginSearchResult将原始 npm 结果规整为统一的IPicGoPlugin结构。 - 精确匹配二次过滤:当用户开启"精确匹配"(
exactMatch)时,基于fullName(即 npm 包名,恒为字符串)再次过滤,该步骤不依赖 description,天然免疫空描述问题。 - 状态写入:分别保存原始结果与过滤结果,供插件市场列表 src/renderer/components/main/plugins/picgo-plugins.tsx 渲染。
UI 触发入口位于picgo-plugins.tsx的pluginStoreActions.searchPlugins(query)(src/renderer/components/main/plugins/picgo-plugins.tsx#L220)。
3.4 测试保障
适配层的行为由 src/tests/renderer/adapters/plugins.spec.ts 覆盖。该测试通过vi.mock('@/utils/dataSender')隔离 IPC 与数据收发依赖,验证了:
openPluginMenu通过SHOW_PLUGIN_PAGE_MENUIPC 事件向主进程发送菜单展示请求;installPlugin('picgo-plugin-demo')调用IRPCActionType.INSTALL_PLUGINRPC 并正确归并{ success, body, errMsg }返回结构;- 本地插件导入同样走 RPC 契约。
这类契约测试保证了适配层与主进程 src/main/events/rpc/routes/plugins.ts 之间的调用关系稳定,为后续新增搜索过滤逻辑提供了回归护栏。仓库根目录的 package.json 中定义了pnpm test(vitest run)可直接运行全部测试做回归验证。
四、其他更新:GitHub 问题模板文档链接刷新
2.5.1 的第三项变更是维护性更新:刷新 GitHub bug 报告模板中的文档链接。这类变更不涉及功能逻辑,目的是保证用户在新建 issue 时引导链接指向最新文档地址,减少因文档路径失效造成的无效反馈。它属于仓库元数据维护,与运行时功能无直接关联。
五、升级路径与验证建议
5.1 面向使用者
- 普通用户:直接下载并安装 2.5.1(或更新版本)的安装包即可。升级后进入"图床设置 → SM.MS",确认
token已正确配置;若旧域名上传失败,可尝试在backupDomain中填写新域名(如示例smms.app)或升级到含s.ee适配的核心版本。 - 开发者复现验证:在当前仓库中执行
pnpm install拉取依赖后,运行pnpm test执行 vitest 测试套件,重点观察src/__tests__/renderer/adapters/plugins.spec.ts是否通过;如需构建本地包可执行pnpm run build(见 package.json 的 scripts)。
5.2 回归验证清单
| 场景 | 验证点 |
|---|---|
| SM.MS 上传 | 配置 token 后上传图片,确认域名解析与返回 URL 符合新版s.ee逻辑 |
| 备份域名 | 在backupDomain填入新域名,验证上传回退链路 |
| 插件搜索(空描述) | 在插件市场搜索含无 description 包的关键词,确认不再抛错且列表正常渲染 |
| 精确匹配 | 开启精确匹配后,确认基于fullName的过滤行为符合预期 |
六、关键文件索引
- changelog/2.5.1.md:本文主体文档(中英双语 changelog)
- changelog/:2.4.x 至 2.5.x 的系列 changelog
- package.json:当前仓库版本与
picgo依赖(^3.0.1)、构建与测试脚本 - src/renderer/adapters/plugins.ts#L202-L225:插件搜索适配层(空描述兜底修复所在)
- src/renderer/store/plugins/actions.ts#L121-L179:插件搜索 store 动作层
- src/tests/renderer/adapters/plugins.spec.ts:适配层契约测试
- src/renderer/components/main/providers/provider-mock.ts#L136-L168:SM.MS 上传器 schema 与配置示例
- src/universal/types/types.d.ts#L389-L391:
ISMMSConfig类型定义 - src/renderer/store/app-store.ts#L42:默认图床
smms - src/main/utils/dataReport.ts#L53:图床类型上报的
smms兜底
- 桌面应用
- 开发工具
- 插件系统
【免费下载链接】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.
相关推荐
解决OBS Studio Linux崩溃:文件描述符耗尽深度排查与修复
解决OBS Studio Linux崩溃:文件描述符耗尽深度排查与修复 你是否遇到过OBS Studio在Linux系统直播到关键节点突然崩溃?日志中是否出现"
音视频直播屏幕录制桌面应用视频PicGo使用SM.MS图床上传失败的解决方案
PicGo使用SM.MS图床上传失败的解决方案 问题背景 在使用PicGo工具进行图片上传时,部分用户反馈在使用SM.MS图床服务时遇到了上传失败的问题。错误日
桌面应用开发工具插件系统如何快速上手Gemma-4-31B-it-assistant:3步安装与配置教程
如何快速上手Gemma 4 31B it assistant:3步安装与配置教程 Gemma 4 31B it assistant是Google DeepMin
大模型人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考