picgo-plugin-gitee 2.0.7 → 2.0.9
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 +138 -51
- 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.9",
|
|
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,101 @@ 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
|
+
// 兼容 string / object 两种响应形态,避免日志打 "[object Object]"
|
|
192
|
+
ctx.log.info(
|
|
193
|
+
"[删除操作]响应:" +
|
|
194
|
+
(typeof response === "string" ? response : JSON.stringify(response))
|
|
195
|
+
);
|
|
196
|
+
successNames.push(each.fileName || each.imgUrl);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
ctx.log.info(
|
|
199
|
+
"[删除操作]失败:" +
|
|
200
|
+
(each.fileName || each.imgUrl) +
|
|
201
|
+
" " +
|
|
202
|
+
err.message
|
|
203
|
+
);
|
|
204
|
+
fails.push(`${each.fileName || each.imgUrl}: ${err.message}`);
|
|
205
|
+
ctx.emit("notification", {
|
|
206
|
+
title: "删除失败",
|
|
207
|
+
body: `${each.fileName || each.imgUrl} ${err.message}`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
148
210
|
}
|
|
149
211
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
212
|
+
// 汇总通知,避免重复打扰。
|
|
213
|
+
if (successNames.length > 0) {
|
|
214
|
+
ctx.emit("notification", {
|
|
215
|
+
title: "删除完成",
|
|
216
|
+
body:
|
|
217
|
+
`成功同步删除 ${successNames.length} 个` +
|
|
218
|
+
(fails.length > 0 ? `,失败 ${fails.length} 个` : ""),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
if (fails.length > 0) {
|
|
222
|
+
ctx.log.info("[删除操作]失败明细:" + JSON.stringify(fails));
|
|
223
|
+
}
|
|
154
224
|
};
|
|
155
225
|
|
|
226
|
+
// 把预览 URL 转成删除用的 API URL。
|
|
227
|
+
// previewUrl 可能是默认域名、独立域名(raw.giteeusercontent.com)或用户自定义 customUrl,
|
|
228
|
+
// 但 Gitee API 始终在 gitee.com,所以这里统一映射到 gitee.com/api/v5/repos/...。
|
|
156
229
|
const getFilePath = function (url) {
|
|
157
|
-
let
|
|
158
|
-
|
|
159
|
-
let urlStr = url.replace(
|
|
160
|
-
|
|
230
|
+
let parsed = urlParser.parse(url);
|
|
231
|
+
// 去掉 raw/master,保留 owner/repo/path
|
|
232
|
+
let urlStr = url.replace("raw/master", "contents");
|
|
233
|
+
// 把 host 替换为 gitee.com,并插入 /api/v5/repos
|
|
234
|
+
return urlStr.replace(
|
|
235
|
+
`${parsed.protocol}//${parsed.host}`,
|
|
236
|
+
`${parsed.protocol}//gitee.com${apiPath}`
|
|
237
|
+
);
|
|
161
238
|
};
|
|
162
239
|
|
|
163
240
|
const getSha = async function (filepath) {
|
|
@@ -167,14 +244,15 @@ module.exports = (ctx) => {
|
|
|
167
244
|
|
|
168
245
|
const opts = {
|
|
169
246
|
method: "GET",
|
|
170
|
-
url:
|
|
247
|
+
url: url,
|
|
171
248
|
headers: headers,
|
|
172
249
|
};
|
|
173
250
|
|
|
174
251
|
let res = await ctx.Request.request(opts);
|
|
175
|
-
|
|
252
|
+
// 兼容 picgo-core(返回 JSON 字符串)和 picgo GUI(直接返回 parsed object)
|
|
253
|
+
let tmp = typeof res === "string" ? JSON.parse(res) : res;
|
|
176
254
|
|
|
177
|
-
return tmp.sha;
|
|
255
|
+
return tmp && tmp.sha;
|
|
178
256
|
};
|
|
179
257
|
|
|
180
258
|
const formatConfigPath = function (userConfig) {
|
|
@@ -187,21 +265,15 @@ module.exports = (ctx) => {
|
|
|
187
265
|
userConfig = {};
|
|
188
266
|
}
|
|
189
267
|
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
268
|
{
|
|
199
269
|
name: "owner",
|
|
200
270
|
type: "input",
|
|
201
271
|
default: userConfig.owner,
|
|
202
272
|
required: true,
|
|
203
273
|
message: "owner",
|
|
204
|
-
alias: "
|
|
274
|
+
alias: "仓库所属用户/组织",
|
|
275
|
+
tips:
|
|
276
|
+
"仓库 owner,例如仓库地址 https://gitee.com/zhanghuid/resources 中 owner 为 zhanghuid",
|
|
205
277
|
},
|
|
206
278
|
{
|
|
207
279
|
name: "repo",
|
|
@@ -209,23 +281,37 @@ module.exports = (ctx) => {
|
|
|
209
281
|
default: userConfig.repo,
|
|
210
282
|
required: true,
|
|
211
283
|
message: "repo",
|
|
212
|
-
alias: "
|
|
284
|
+
alias: "仓库名",
|
|
285
|
+
tips: "仓库名,例如 resources",
|
|
213
286
|
},
|
|
214
287
|
{
|
|
215
288
|
name: "path",
|
|
216
289
|
type: "input",
|
|
217
290
|
default: userConfig.path,
|
|
218
291
|
required: false,
|
|
219
|
-
message: "
|
|
220
|
-
alias: "
|
|
292
|
+
message: "根目录可留空,例如 img/2026",
|
|
293
|
+
alias: "存储路径",
|
|
294
|
+
tips: "图片在仓库内的存储子目录,根目录可不填",
|
|
221
295
|
},
|
|
222
296
|
{
|
|
223
297
|
name: "token",
|
|
224
|
-
type: "
|
|
298
|
+
type: "password",
|
|
225
299
|
default: userConfig.token,
|
|
226
300
|
required: true,
|
|
227
|
-
message: "
|
|
228
|
-
alias: "token",
|
|
301
|
+
message: "Gitee 私人令牌",
|
|
302
|
+
alias: "私人令牌 (token)",
|
|
303
|
+
tips:
|
|
304
|
+
"在 https://gitee.com/profile/personal_access_tokens 生成,需要 projects 和 pull_request 权限",
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: "customUrl",
|
|
308
|
+
type: "input",
|
|
309
|
+
default: userConfig.customUrl,
|
|
310
|
+
required: false,
|
|
311
|
+
message: "可留空,默认使用 raw.giteeusercontent.com",
|
|
312
|
+
alias: "自定义独立域名(可选)",
|
|
313
|
+
tips:
|
|
314
|
+
"如有自有独立域名(反代 raw.giteeusercontent.com 或 Gitee Page 绑定的域名),填这里;留空则默认使用 https://raw.giteeusercontent.com",
|
|
229
315
|
},
|
|
230
316
|
{
|
|
231
317
|
name: "message",
|
|
@@ -233,7 +319,8 @@ module.exports = (ctx) => {
|
|
|
233
319
|
default: userConfig.message,
|
|
234
320
|
required: false,
|
|
235
321
|
message: defaultMsg,
|
|
236
|
-
alias: "message",
|
|
322
|
+
alias: "提交信息 (commit message)",
|
|
323
|
+
tips: "上传/删除文件时使用的 commit message,留空使用默认 picgo commit",
|
|
237
324
|
},
|
|
238
325
|
];
|
|
239
326
|
};
|
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`的版本号
|