Mac 下手动安装 PicGo Gitee 上传插件解决方案
适用场景 :PicGo GUI 插件市场无法下载插件、
npm install超时或网络异常,需要手动离线安装picgo-plugin-gitee-uploader的 Mac 用户。
背景
PicGo 是一款优秀的图床管理工具,picgo-plugin-gitee-uploader 插件可以让你把图片上传到 Gitee(码云)仓库。
然而在国内网络环境下,通过 PicGo GUI 的插件市场或者 npm install 安装该插件时,经常遇到以下问题:
- GUI 界面点击安装无响应或报错
npm install picgo-plugin-gitee-uploader超时- 即使安装成功,插件也不出现在图床列表中
本文提供一套完整的离线手动安装方案,无需依赖网络即可完成安装。
原理说明
PicGo 插件本质上是一个 Node.js 模块,放在以下目录:
~/Library/Application Support/picgo/node_modules/
PicGo 通过读取同目录下的 data.json 文件中的 picgoPlugins 字段来识别已安装的插件。
该插件源码是 TypeScript,需要编译为 CommonJS 格式的 JavaScript 才能被 Node.js 加载。
前置准备
- 已安装 PicGo Mac 客户端
- 已安装 Node.js(推荐 v16+),可通过
node --version验证 - 已下载 picgo-plugin-gitee-uploader 源码包并解压到
~/Downloads/picgo-plugin-gitee-uploader-master
步骤一:确认目录结构
确保以下两个目录存在:
bash
# PicGo 数据目录
~/Library/Application\ Support/picgo/
# 插件源码目录
~/Downloads/picgo-plugin-gitee-uploader-master/
确认插件源码目录包含以下文件:
picgo-plugin-gitee-uploader-master/
├── index.ts
├── lib/
│ ├── helper.ts
│ ├── interface.ts
│ └── octokit.ts
├── package.json
└── tsconfig.json
步骤二:创建编译输出目录
插件的 package.json 中 "main": "dist/index.js",说明需要编译后的产物。
bash
mkdir -p ~/Downloads/picgo-plugin-gitee-uploader-master/dist/lib
步骤三:手动创建编译产物
由于网络问题无法安装 TypeScript 编译器,我们直接手写编译后的 JS 文件。
3.1 创建 dist/lib/interface.js
bash
cat > ~/Downloads/picgo-plugin-gitee-uploader-master/dist/lib/interface.js << 'EOF'
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
EOF
3.2 创建 dist/lib/helper.js
新建文件 ~/Downloads/picgo-plugin-gitee-uploader-master/dist/lib/helper.js,内容如下:
javascript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPath = exports.pathJoin = exports.unzip = exports.zip = exports.getNow = void 0;
const dayjs_1 = require("dayjs");
const normalize_path_1 = require("normalize-path");
const path_1 = require("path");
function getNow() {
return dayjs_1.default().format('YYYY-MM-DD hh:mm:ss');
}
exports.getNow = getNow;
function zip(img) {
return { f: img.fileName, s: img.sha };
}
exports.zip = zip;
function unzip(img) {
const { f: fileName, s } = img;
const extname = fileName.split('.').slice(-1)[0];
return { fileName, id: s, sha: s, extname, imgUrl: '', type: '' };
}
exports.unzip = unzip;
function pathJoin(...arg) {
return normalize_path_1.default(path_1.join.apply(null, arg));
}
exports.pathJoin = pathJoin;
function getPath(path, customPath) {
if (customPath === '') return path;
let date = new Date();
let year = date.getFullYear();
let month = (date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1);
if (customPath === 'year') return path.replace('$customPath', year + '');
if (customPath === 'yearQuarter') {
let quarter = 'spring';
if (month >= 4 && month <= 6) quarter = 'summer';
else if (month >= 7 && month <= 9) quarter = 'autumn';
else if (month >= 10 && month <= 12) quarter = 'winter';
return path.replace('$customPath', year + '/' + quarter);
}
if (customPath === 'yearMonth') return path.replace('$customPath', year + '/' + month);
return path;
}
exports.getPath = getPath;
3.3 创建 dist/lib/octokit.js
新建文件 ~/Downloads/picgo-plugin-gitee-uploader-master/dist/lib/octokit.js,完整内容参考本文附录 A,或直接从本仓库复制。
核心逻辑:将
Octo类从 TypeScript 转为 ES2017 CommonJS,移除所有类型注解。
3.4 创建 dist/index.js
新建文件 ~/Downloads/picgo-plugin-gitee-uploader-master/dist/index.js,完整内容参考本文附录 B。
核心逻辑:将
export =改为module.exports =,import 改为 require。
步骤四:手动安装运行时依赖
该插件依赖三个 npm 包:dayjs、normalize-path、url-join。
由于网络问题无法通过 npm 安装,我们在插件目录下手动创建这三个包的最小实现。
bash
mkdir -p ~/Downloads/picgo-plugin-gitee-uploader-master/node_modules/dayjs
mkdir -p ~/Downloads/picgo-plugin-gitee-uploader-master/node_modules/normalize-path
mkdir -p ~/Downloads/picgo-plugin-gitee-uploader-master/node_modules/url-join
dayjs shim
新建 node_modules/dayjs/index.js:
javascript
"use strict";
function dayjs(date) {
const d = date ? new Date(date) : new Date();
return {
format(fmt) {
const y = d.getFullYear();
const M = String(d.getMonth() + 1).padStart(2, '0');
const D = String(d.getDate()).padStart(2, '0');
const h = String(d.getHours()).padStart(2, '0');
const m = String(d.getMinutes()).padStart(2, '0');
const s = String(d.getSeconds()).padStart(2, '0');
return fmt
.replace('YYYY', y).replace('MM', M).replace('DD', D)
.replace('hh', h).replace('mm', m).replace('ss', s);
}
};
}
module.exports = dayjs;
module.exports.default = dayjs;
新建 node_modules/dayjs/package.json:
json
{"name":"dayjs","version":"1.11.0","main":"index.js"}
normalize-path shim
新建 node_modules/normalize-path/index.js:
javascript
"use strict";
module.exports = function normalizePath(path, stripTrailing) {
if (typeof path !== 'string') throw new TypeError('expected a string');
path = path.replace(/[\/\\]+/g, '/');
if (stripTrailing !== false) path = path.replace(/\/$/, '');
return path;
};
新建 node_modules/normalize-path/package.json:
json
{"name":"normalize-path","version":"3.0.0","main":"index.js"}
url-join shim
新建 node_modules/url-join/index.js:
javascript
"use strict";
function normalize(str) {
return str.replace(/([^:])(\/+)/g, '$1/');
}
function urlJoin() {
const parts = Array.from(arguments).reduce((acc, val) => {
if (Array.isArray(val)) return acc.concat(val);
acc.push(val); return acc;
}, []);
let joined = parts.map((part, i) => {
if (i === 0) return part.replace(/\/*$/, '');
return part.replace(/^\/*(.+?)\/*$/, '$1');
}).join('/');
return normalize(joined);
}
module.exports = urlJoin;
module.exports.default = urlJoin;
新建 node_modules/url-join/package.json:
json
{"name":"url-join","version":"4.0.1","main":"index.js"}
步骤五:验证插件是否可加载
bash
node -e "const p = require('$HOME/Library/Application Support/picgo/node_modules/picgo-plugin-gitee-uploader'); console.log(typeof p, 'loaded OK');"
输出 function loaded OK 说明插件加载成功。
步骤六:确认符号链接
PicGo 会在 node_modules 下创建指向插件目录的符号链接,检查是否存在:
bash
ls -la ~/Library/Application\ Support/picgo/node_modules/
应看到类似:
lrwxr-xr-x picgo-plugin-gitee-uploader -> ../../../../Downloads/picgo-plugin-gitee-uploader-master
如果没有,手动创建:
bash
ln -s ~/Downloads/picgo-plugin-gitee-uploader-master \
~/Library/Application\ Support/picgo/node_modules/picgo-plugin-gitee-uploader
步骤七:注册插件到 data.json
用文本编辑器(或直接在终端)修改 ~/Library/Application Support/picgo/data.json,找到 picgoPlugins 字段:
json
"picgoPlugins": {}
改为:
json
"picgoPlugins": {"picgo-plugin-gitee-uploader": true}
⚠️ 修改前先备份:
cp ~/Library/Application\ Support/picgo/data.json ~/Desktop/data.json.bak
步骤八:重启 PicGo 并配置
- 完全退出 PicGo(菜单栏右键 → 退出)
- 重新启动 PicGo
- 进入 图床设置 → 左侧列表应出现 gitee 选项
- 填写配置:
| 字段 | 说明 | 示例 |
|---|---|---|
repo |
仓库路径(用户名/仓库名) | yourname/picBed |
branch |
分支名 | master |
token |
Gitee 私人访问令牌 | 在 Gitee 设置 → 私人令牌 获取 |
path |
图片存储子目录(可选) | imgs/ |
customUrl |
自定义图片访问域名(可选) | 留空则使用 gitee.com |
- 点击 确定 并设为默认图床
- 测试上传图片 ✓
常见问题
Q: PicGo 重启后插件还是不显示?
A: 检查 data.json 是否保存成功,确认 picgoPlugins 字段值为 {"picgo-plugin-gitee-uploader": true} 而非 {}。
Q: 上传时报 Error in repo name?
A: repo 字段必须是 用户名/仓库名 格式,例如 zhangsan/myPicBed,不能只写仓库名。
Q: 上传时报 401/403 错误?
A: Gitee token 失效或权限不足。在 Gitee → 设置 → 私人令牌 中重新生成,勾选 projects 权限。
Q: 为什么不直接用 npm install 安装?
A: 国内网络访问 npm 官方源极慢,经常超时。本文方案完全离线,不依赖网络,更稳定可靠。如果你的网络正常,也可以直接运行:
bash
cd ~/Library/Application\ Support/picgo
npm install picgo-plugin-gitee-uploader --save
总结
整个手动安装流程分为三个核心步骤:
- 编译 :将 TypeScript 源码手动转为 CommonJS JS,生成
dist/目录 - 依赖 :为三个运行时依赖(
dayjs、normalize-path、url-join)创建最小实现 - 注册 :在
data.json的picgoPlugins中将插件标记为true
这套方法同样适用于其他 PicGo 插件的离线手动安装,举一反三即可。
参考链接
本文操作环境:macOS Sequoia 15、Node.js v16.20.2、PicGo 2.x