picgo-plugin-gitee 2.0.7 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +30 -10
- package/readme.md +7 -3
- package/src/index.js +131 -49
- package/.eslintrc +0 -3
- package/CONTRIBUTING.md +0 -14
package/package.json
CHANGED
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "picgo-plugin-gitee",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "picgo uploader for gitee",
|
|
5
5
|
"main": "src/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/**/*",
|
|
8
|
+
"readme.md",
|
|
9
|
+
"LICENSE"
|
|
10
|
+
],
|
|
6
11
|
"publishConfig": {
|
|
7
|
-
"access": "public"
|
|
12
|
+
"access": "public",
|
|
13
|
+
"registry": "https://registry.npmjs.org/"
|
|
8
14
|
},
|
|
9
15
|
"homepage": "https://github.com/zhanghuid/picgo-plugin-gitee",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/zhanghuid/picgo-plugin-gitee.git"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/zhanghuid/picgo-plugin-gitee/issues"
|
|
22
|
+
},
|
|
10
23
|
"scripts": {
|
|
24
|
+
"lint": "eslint src/index.js",
|
|
11
25
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
26
|
+
"bump": "bumpp --commit \"chore(release): v%s\"",
|
|
27
|
+
"bump:patch": "bumpp patch --commit \"chore(release): v%s\"",
|
|
28
|
+
"bump:minor": "bumpp minor --commit \"chore(release): v%s\"",
|
|
29
|
+
"bump:major": "bumpp major --commit \"chore(release): v%s\"",
|
|
30
|
+
"release": "npm run bump && npm publish",
|
|
31
|
+
"release:patch": "npm run bump:patch && npm publish",
|
|
32
|
+
"release:minor": "npm run bump:minor && npm publish",
|
|
33
|
+
"release:major": "npm run bump:major && npm publish",
|
|
34
|
+
"prepublishOnly": "node --check src/index.js"
|
|
15
35
|
},
|
|
16
36
|
"keywords": [
|
|
17
37
|
"picgo",
|
|
@@ -21,13 +41,13 @@
|
|
|
21
41
|
"author": "zhanghuid",
|
|
22
42
|
"license": "MIT",
|
|
23
43
|
"devDependencies": {
|
|
44
|
+
"@varnxy/logger": "^1.1.2",
|
|
45
|
+
"bumpp": "^12.3.0",
|
|
24
46
|
"eslint": "^5.0.1",
|
|
25
47
|
"eslint-config-standard": "^11.0.0",
|
|
26
48
|
"eslint-plugin-import": "^2.13.0",
|
|
27
49
|
"eslint-plugin-node": "^6.0.1",
|
|
28
50
|
"eslint-plugin-promise": "^3.8.0",
|
|
29
|
-
"eslint-plugin-standard": "^3.1.0"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"dependencies": {}
|
|
33
|
-
}
|
|
51
|
+
"eslint-plugin-standard": "^3.1.0"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/readme.md
CHANGED
|
@@ -17,9 +17,12 @@ npm i picgo-plugin-gitee
|
|
|
17
17
|
#### input your config
|
|
18
18
|
- owner: gitee project's owner name
|
|
19
19
|
- repo: gitee project repo
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
20
|
+
- path: img path in response json (eg:url or data.url), 根目录可留空
|
|
21
|
+
- token: gitee's api token(在 https://gitee.com/profile/personal_access_tokens 生成)
|
|
22
|
+
- customUrl: 自定义独立域名(可选),留空默认使用 `https://raw.giteeusercontent.com`,避免默认域名被 302 重定向
|
|
23
|
+
- message: gitee commit,默认 `picgo commit`
|
|
24
|
+
|
|
25
|
+
> 默认预览地址使用 [Gitee 独立域名 `raw.giteeusercontent.com`](https://help.gitee.com/repository/file-operate/raw#%E7%8B%AC%E7%AB%8B%E5%9F%9F%E5%90%8D),不再走 `gitee.com` 的 302。
|
|
23
26
|
|
|
24
27
|
#### init your remote repo
|
|
25
28
|
- create git repo?
|
|
@@ -42,6 +45,7 @@ git push -u origin master
|
|
|
42
45
|
|
|
43
46
|
### Feature
|
|
44
47
|
- support sync gitee file delete
|
|
48
|
+
- 上传/删除结束均会弹出系统通知(PicGo 消息中心)
|
|
45
49
|
|
|
46
50
|
### Todo
|
|
47
51
|
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
const uploadedName = "gitee";
|
|
2
2
|
const domain = "https://gitee.com";
|
|
3
|
+
// 独立域名:直接命中,避免走默认域名的 302 重定向。
|
|
4
|
+
// 参考:https://help.gitee.com/repository/file-operate/raw#%E7%8B%AC%E7%AB%8B%E5%9F%9F%E5%90%8D
|
|
5
|
+
const previewDomain = "https://raw.giteeusercontent.com";
|
|
6
|
+
const apiPath = "/api/v5/repos";
|
|
3
7
|
const urlParser = require("url");
|
|
4
8
|
const defaultMsg = "picgo commit";
|
|
5
9
|
|
|
@@ -28,9 +32,9 @@ module.exports = (ctx) => {
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
userConfig["baseUrl"] =
|
|
31
|
-
domain + "/
|
|
35
|
+
domain + apiPath + "/" + userConfig.owner + "/" + userConfig.repo;
|
|
32
36
|
userConfig["previewUrl"] =
|
|
33
|
-
|
|
37
|
+
(userConfig.customUrl || previewDomain) +
|
|
34
38
|
"/" +
|
|
35
39
|
userConfig.owner +
|
|
36
40
|
"/" +
|
|
@@ -51,6 +55,10 @@ module.exports = (ctx) => {
|
|
|
51
55
|
userConfig.baseUrl + "/contents" + formatConfigPath(userConfig);
|
|
52
56
|
|
|
53
57
|
let imgList = ctx.output;
|
|
58
|
+
let successCount = 0;
|
|
59
|
+
let failCount = 0;
|
|
60
|
+
const fails = [];
|
|
61
|
+
|
|
54
62
|
for (let i in imgList) {
|
|
55
63
|
let image = imgList[i].buffer;
|
|
56
64
|
if (!image && imgList[i].base64Image) {
|
|
@@ -64,32 +72,53 @@ module.exports = (ctx) => {
|
|
|
64
72
|
await ctx.Request.request(postConfig);
|
|
65
73
|
imgList[i]["imgUrl"] =
|
|
66
74
|
userConfig.previewUrl + "/" + imgList[i].fileName;
|
|
75
|
+
successCount += 1;
|
|
76
|
+
ctx.log.info(
|
|
77
|
+
"[上传操作]成功:" + imgList[i].fileName + " -> " + imgList[i].imgUrl
|
|
78
|
+
);
|
|
67
79
|
} catch (err) {
|
|
68
|
-
ctx.log.info("[上传操作]异常:" + err.message);
|
|
69
80
|
// duplicate file, so continue
|
|
70
81
|
if (checkIsDuplicateFile(err.message)) {
|
|
82
|
+
ctx.log.info("[上传操作]文件已存在:" + imgList[i].fileName);
|
|
71
83
|
ctx.emit("notification", {
|
|
72
84
|
title: "上传失败",
|
|
73
|
-
body:
|
|
85
|
+
body: `${imgList[i].fileName} 文件已经存在了`,
|
|
74
86
|
});
|
|
87
|
+
failCount += 1;
|
|
75
88
|
continue;
|
|
76
|
-
} else {
|
|
77
|
-
ctx.emit("notification", {
|
|
78
|
-
title: "上传失败",
|
|
79
|
-
body: JSON.stringify(err),
|
|
80
|
-
});
|
|
81
89
|
}
|
|
90
|
+
failCount += 1;
|
|
91
|
+
fails.push(`${imgList[i].fileName}: ${err.message}`);
|
|
92
|
+
ctx.log.info("[上传操作]异常:" + err.message);
|
|
93
|
+
ctx.emit("notification", {
|
|
94
|
+
title: "上传失败",
|
|
95
|
+
body: `${imgList[i].fileName} ${err.message}`,
|
|
96
|
+
});
|
|
82
97
|
}
|
|
83
98
|
|
|
84
99
|
delete imgList[i].base64Image;
|
|
85
100
|
delete imgList[i].buffer;
|
|
86
101
|
}
|
|
87
102
|
|
|
103
|
+
// 上传结束后统一给一条汇总通知,避免每次上传都点弹窗打扰用户。
|
|
104
|
+
if (successCount > 0) {
|
|
105
|
+
ctx.emit("notification", {
|
|
106
|
+
title: "上传完成",
|
|
107
|
+
body: `成功 ${successCount} 张${failCount > 0 ? `,失败 ${failCount} 张` : ""}`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (fails.length > 0) {
|
|
111
|
+
ctx.log.info("[上传操作]失败明细:" + JSON.stringify(fails));
|
|
112
|
+
}
|
|
113
|
+
|
|
88
114
|
return ctx;
|
|
89
115
|
};
|
|
90
116
|
|
|
91
117
|
const checkIsDuplicateFile = (message) => {
|
|
92
|
-
return
|
|
118
|
+
return (
|
|
119
|
+
message.indexOf("A file with this name already exists") != -1 ||
|
|
120
|
+
message.indexOf("文件已经存在") != -1
|
|
121
|
+
);
|
|
93
122
|
};
|
|
94
123
|
|
|
95
124
|
const postOptions = (url, image) => {
|
|
@@ -111,53 +140,97 @@ module.exports = (ctx) => {
|
|
|
111
140
|
|
|
112
141
|
// trigger delete file
|
|
113
142
|
const onRemove = async function (files) {
|
|
114
|
-
// log request params
|
|
115
143
|
const rms = files.filter((each) => each.type === uploadedName);
|
|
116
144
|
if (rms.length === 0) {
|
|
117
145
|
return;
|
|
118
146
|
}
|
|
119
147
|
|
|
120
148
|
ctx.log.info("删除个数:" + rms.length);
|
|
121
|
-
ctx.log.info("uploaded 信息:");
|
|
122
149
|
let headers = getHeaders();
|
|
123
150
|
let config = getUserConfig();
|
|
124
|
-
const
|
|
151
|
+
const fails = [];
|
|
152
|
+
const successNames = [];
|
|
125
153
|
|
|
126
154
|
for (let i = 0; i < rms.length; i++) {
|
|
127
155
|
const each = rms[i];
|
|
128
156
|
let filepath = getFilePath(each.imgUrl);
|
|
129
|
-
let sha
|
|
130
|
-
|
|
131
|
-
|
|
157
|
+
let sha;
|
|
158
|
+
try {
|
|
159
|
+
sha = await getSha(filepath);
|
|
160
|
+
} catch (err) {
|
|
161
|
+
ctx.log.info(
|
|
162
|
+
"[删除操作]获取 sha 失败,跳过:" + each.imgUrl + " " + err.message
|
|
163
|
+
);
|
|
164
|
+
fails.push(`${each.fileName || each.imgUrl}: 获取 sha 失败`);
|
|
165
|
+
ctx.emit("notification", {
|
|
166
|
+
title: "删除失败",
|
|
167
|
+
body: `${each.fileName || each.imgUrl} 获取 sha 失败`,
|
|
168
|
+
});
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
132
171
|
|
|
133
|
-
|
|
172
|
+
if (!sha) {
|
|
173
|
+
ctx.log.info("[删除操作]sha 为空,文件可能已被删除:" + each.imgUrl);
|
|
174
|
+
fails.push(`${each.fileName || each.imgUrl}: 文件不存在`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const url =
|
|
134
179
|
`${filepath}` +
|
|
135
180
|
`?access_token=${config.token}` +
|
|
136
|
-
`&message=${config.message}` +
|
|
181
|
+
`&message=${encodeURIComponent(config.message || defaultMsg)}` +
|
|
137
182
|
`&sha=${sha}`;
|
|
138
183
|
ctx.log.info("[删除操作]当前删除地址:" + url);
|
|
139
|
-
|
|
184
|
+
const opts = {
|
|
140
185
|
method: "DELETE",
|
|
141
|
-
url:
|
|
186
|
+
url: url,
|
|
142
187
|
headers: headers,
|
|
143
188
|
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
189
|
+
try {
|
|
190
|
+
const response = await ctx.Request.request(opts);
|
|
191
|
+
ctx.log.info("[删除操作]响应:" + response);
|
|
192
|
+
successNames.push(each.fileName || each.imgUrl);
|
|
193
|
+
} catch (err) {
|
|
194
|
+
ctx.log.info(
|
|
195
|
+
"[删除操作]失败:" +
|
|
196
|
+
(each.fileName || each.imgUrl) +
|
|
197
|
+
" " +
|
|
198
|
+
err.message
|
|
199
|
+
);
|
|
200
|
+
fails.push(`${each.fileName || each.imgUrl}: ${err.message}`);
|
|
201
|
+
ctx.emit("notification", {
|
|
202
|
+
title: "删除失败",
|
|
203
|
+
body: `${each.fileName || each.imgUrl} ${err.message}`,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
148
206
|
}
|
|
149
207
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
208
|
+
// 汇总通知,避免重复打扰。
|
|
209
|
+
if (successNames.length > 0) {
|
|
210
|
+
ctx.emit("notification", {
|
|
211
|
+
title: "删除完成",
|
|
212
|
+
body:
|
|
213
|
+
`成功同步删除 ${successNames.length} 个` +
|
|
214
|
+
(fails.length > 0 ? `,失败 ${fails.length} 个` : ""),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
if (fails.length > 0) {
|
|
218
|
+
ctx.log.info("[删除操作]失败明细:" + JSON.stringify(fails));
|
|
219
|
+
}
|
|
154
220
|
};
|
|
155
221
|
|
|
222
|
+
// 把预览 URL 转成删除用的 API URL。
|
|
223
|
+
// previewUrl 可能是默认域名、独立域名(raw.giteeusercontent.com)或用户自定义 customUrl,
|
|
224
|
+
// 但 Gitee API 始终在 gitee.com,所以这里统一映射到 gitee.com/api/v5/repos/...。
|
|
156
225
|
const getFilePath = function (url) {
|
|
157
|
-
let
|
|
158
|
-
|
|
159
|
-
let urlStr = url.replace(
|
|
160
|
-
|
|
226
|
+
let parsed = urlParser.parse(url);
|
|
227
|
+
// 去掉 raw/master,保留 owner/repo/path
|
|
228
|
+
let urlStr = url.replace("raw/master", "contents");
|
|
229
|
+
// 把 host 替换为 gitee.com,并插入 /api/v5/repos
|
|
230
|
+
return urlStr.replace(
|
|
231
|
+
`${parsed.protocol}//${parsed.host}`,
|
|
232
|
+
`${parsed.protocol}//gitee.com${apiPath}`
|
|
233
|
+
);
|
|
161
234
|
};
|
|
162
235
|
|
|
163
236
|
const getSha = async function (filepath) {
|
|
@@ -167,7 +240,7 @@ module.exports = (ctx) => {
|
|
|
167
240
|
|
|
168
241
|
const opts = {
|
|
169
242
|
method: "GET",
|
|
170
|
-
url:
|
|
243
|
+
url: url,
|
|
171
244
|
headers: headers,
|
|
172
245
|
};
|
|
173
246
|
|
|
@@ -187,21 +260,15 @@ module.exports = (ctx) => {
|
|
|
187
260
|
userConfig = {};
|
|
188
261
|
}
|
|
189
262
|
return [
|
|
190
|
-
// {
|
|
191
|
-
// name: 'url',
|
|
192
|
-
// type: 'input',
|
|
193
|
-
// default: userConfig.url,
|
|
194
|
-
// required: true,
|
|
195
|
-
// message: 'https://gitee.com',
|
|
196
|
-
// alias: 'url'
|
|
197
|
-
// },
|
|
198
263
|
{
|
|
199
264
|
name: "owner",
|
|
200
265
|
type: "input",
|
|
201
266
|
default: userConfig.owner,
|
|
202
267
|
required: true,
|
|
203
268
|
message: "owner",
|
|
204
|
-
alias: "
|
|
269
|
+
alias: "仓库所属用户/组织",
|
|
270
|
+
tips:
|
|
271
|
+
"仓库 owner,例如仓库地址 https://gitee.com/zhanghuid/resources 中 owner 为 zhanghuid",
|
|
205
272
|
},
|
|
206
273
|
{
|
|
207
274
|
name: "repo",
|
|
@@ -209,23 +276,37 @@ module.exports = (ctx) => {
|
|
|
209
276
|
default: userConfig.repo,
|
|
210
277
|
required: true,
|
|
211
278
|
message: "repo",
|
|
212
|
-
alias: "
|
|
279
|
+
alias: "仓库名",
|
|
280
|
+
tips: "仓库名,例如 resources",
|
|
213
281
|
},
|
|
214
282
|
{
|
|
215
283
|
name: "path",
|
|
216
284
|
type: "input",
|
|
217
285
|
default: userConfig.path,
|
|
218
286
|
required: false,
|
|
219
|
-
message: "
|
|
220
|
-
alias: "
|
|
287
|
+
message: "根目录可留空,例如 img/2026",
|
|
288
|
+
alias: "存储路径",
|
|
289
|
+
tips: "图片在仓库内的存储子目录,根目录可不填",
|
|
221
290
|
},
|
|
222
291
|
{
|
|
223
292
|
name: "token",
|
|
224
|
-
type: "
|
|
293
|
+
type: "password",
|
|
225
294
|
default: userConfig.token,
|
|
226
295
|
required: true,
|
|
227
|
-
message: "
|
|
228
|
-
alias: "token",
|
|
296
|
+
message: "Gitee 私人令牌",
|
|
297
|
+
alias: "私人令牌 (token)",
|
|
298
|
+
tips:
|
|
299
|
+
"在 https://gitee.com/profile/personal_access_tokens 生成,需要 projects 和 pull_request 权限",
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: "customUrl",
|
|
303
|
+
type: "input",
|
|
304
|
+
default: userConfig.customUrl,
|
|
305
|
+
required: false,
|
|
306
|
+
message: "可留空,默认使用 raw.giteeusercontent.com",
|
|
307
|
+
alias: "自定义独立域名(可选)",
|
|
308
|
+
tips:
|
|
309
|
+
"如有自有独立域名(反代 raw.giteeusercontent.com 或 Gitee Page 绑定的域名),填这里;留空则默认使用 https://raw.giteeusercontent.com",
|
|
229
310
|
},
|
|
230
311
|
{
|
|
231
312
|
name: "message",
|
|
@@ -233,7 +314,8 @@ module.exports = (ctx) => {
|
|
|
233
314
|
default: userConfig.message,
|
|
234
315
|
required: false,
|
|
235
316
|
message: defaultMsg,
|
|
236
|
-
alias: "message",
|
|
317
|
+
alias: "提交信息 (commit message)",
|
|
318
|
+
tips: "上传/删除文件时使用的 commit message,留空使用默认 picgo commit",
|
|
237
319
|
},
|
|
238
320
|
];
|
|
239
321
|
};
|
package/.eslintrc
DELETED
package/CONTRIBUTING.md
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# 开发者说明
|
|
2
|
-
|
|
3
|
-
## 开发环境搭建
|
|
4
|
-
[插件测试与发布](https://picgo.github.io/PicGo-Core-Doc/zh/dev-guide/deploy.html#%E6%99%AE%E9%80%9A%E6%8F%92%E4%BB%B6)
|
|
5
|
-
[图片转base64工具](https://tool.chinaz.com/tools/imgtobase)
|
|
6
|
-
|
|
7
|
-
## 相关 API
|
|
8
|
-
- [新建文件](https://gitee.com/api/v5/swagger#/postV5ReposOwnerRepoContentsPath)
|
|
9
|
-
- [删除文件](https://gitee.com/api/v5/swagger#/deleteV5ReposOwnerRepoContentsPath)
|
|
10
|
-
|
|
11
|
-
## 步骤
|
|
12
|
-
1. 按照 **开发环境搭建 > 插件测试与发布** 的教程,直接使用本地安装
|
|
13
|
-
2. 安装完后,重启应用生效
|
|
14
|
-
3. 更改 `package.json`的版本号
|