@waline/vercel 1.36.4 → 1.37.0

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.
Files changed (39) hide show
  1. package/__tests__/xss.spec.js +8 -19
  2. package/development.js +1 -0
  3. package/index.js +4 -3
  4. package/package.json +17 -18
  5. package/src/config/adapter.js +9 -11
  6. package/src/config/config.js +4 -12
  7. package/src/config/extend.js +0 -6
  8. package/src/config/middleware.js +2 -5
  9. package/src/controller/article.js +5 -12
  10. package/src/controller/comment.js +33 -53
  11. package/src/controller/db.js +3 -9
  12. package/src/controller/oauth.js +8 -8
  13. package/src/controller/rest.js +1 -1
  14. package/src/controller/user/password.js +3 -12
  15. package/src/controller/user.js +18 -45
  16. package/src/controller/verification.js +3 -2
  17. package/src/extend/think.js +33 -23
  18. package/src/logic/base.js +31 -47
  19. package/src/logic/comment.js +7 -4
  20. package/src/logic/db.js +1 -1
  21. package/src/logic/token.js +2 -2
  22. package/src/middleware/dashboard.js +1 -0
  23. package/src/middleware/plugin.js +1 -1
  24. package/src/service/akismet.js +10 -3
  25. package/src/service/avatar.js +2 -4
  26. package/src/service/markdown/highlight.js +1 -1
  27. package/src/service/markdown/mathCommon.js +2 -8
  28. package/src/service/markdown/mathjax.js +1 -2
  29. package/src/service/markdown/utils.js +5 -5
  30. package/src/service/markdown/xss.js +5 -10
  31. package/src/service/notify.js +111 -135
  32. package/src/service/storage/base.js +2 -7
  33. package/src/service/storage/cloudbase.js +9 -7
  34. package/src/service/storage/github.js +39 -42
  35. package/src/service/storage/leancloud.js +41 -54
  36. package/src/service/storage/mongodb.js +11 -8
  37. package/src/service/storage/mysql.js +7 -13
  38. package/src/service/storage/postgresql.js +7 -11
  39. package/src/service/storage/deta.js +0 -310
@@ -21,7 +21,7 @@ module.exports = class extends think.Controller {
21
21
  const filename = this.__filename || __filename;
22
22
  const last = filename.lastIndexOf(path.sep);
23
23
 
24
- return filename.substr(last + 1, filename.length - last - 4);
24
+ return filename.slice(last + 1, filename.length - last - 4);
25
25
  }
26
26
 
27
27
  getId() {
@@ -4,14 +4,8 @@ const BaseRest = require('../rest.js');
4
4
 
5
5
  module.exports = class extends BaseRest {
6
6
  async putAction() {
7
- const {
8
- SMTP_HOST,
9
- SMTP_SERVICE,
10
- SENDER_EMAIL,
11
- SENDER_NAME,
12
- SMTP_USER,
13
- SITE_NAME,
14
- } = process.env;
7
+ const { SMTP_HOST, SMTP_SERVICE, SENDER_EMAIL, SENDER_NAME, SMTP_USER, SITE_NAME } =
8
+ process.env;
15
9
  const hasMailService = SMTP_HOST || SMTP_SERVICE;
16
10
 
17
11
  if (!hasMailService) {
@@ -31,10 +25,7 @@ module.exports = class extends BaseRest {
31
25
  const profileUrl = `${this.ctx.serverURL}/ui/profile?token=${token}`;
32
26
 
33
27
  await notify.transporter.sendMail({
34
- from:
35
- SENDER_EMAIL && SENDER_NAME
36
- ? `"${SENDER_NAME}" <${SENDER_EMAIL}>`
37
- : SMTP_USER,
28
+ from: SENDER_EMAIL && SENDER_NAME ? `"${SENDER_NAME}" <${SENDER_EMAIL}>` : SMTP_USER,
38
29
  to: user[0].email,
39
30
  subject: this.locale('[{{name | safe}}] Reset Password', {
40
31
  name: SITE_NAME || 'Waline',
@@ -1,6 +1,6 @@
1
1
  const BaseRest = require('./rest.js');
2
2
 
3
- module.exports = class extends BaseRest {
3
+ module.exports = class UserController extends BaseRest {
4
4
  constructor(...args) {
5
5
  super(...args);
6
6
  this.modelInstance = this.getModel('Users');
@@ -50,28 +50,17 @@ module.exports = class extends BaseRest {
50
50
  email: data.email,
51
51
  });
52
52
 
53
- if (
54
- !think.isEmpty(resp) &&
55
- ['administrator', 'guest'].includes(resp[0].type)
56
- ) {
53
+ if (!think.isEmpty(resp) && ['administrator', 'guest'].includes(resp[0].type)) {
57
54
  return this.fail(this.locale('USER_EXIST'));
58
55
  }
59
56
 
60
57
  const count = await this.modelInstance.count();
61
58
 
62
- const {
63
- SMTP_HOST,
64
- SMTP_SERVICE,
65
- SENDER_EMAIL,
66
- SENDER_NAME,
67
- SMTP_USER,
68
- SITE_NAME,
69
- } = process.env;
59
+ const { SMTP_HOST, SMTP_SERVICE, SENDER_EMAIL, SENDER_NAME, SMTP_USER, SITE_NAME } =
60
+ process.env;
70
61
  const hasMailService = SMTP_HOST || SMTP_SERVICE;
71
62
 
72
- const token = Array.from({ length: 4 }, () =>
73
- Math.round(Math.random() * 9),
74
- ).join('');
63
+ const token = Array.from({ length: 4 }, () => Math.round(Math.random() * 9)).join('');
75
64
  const normalType = hasMailService
76
65
  ? `verify:${token}:${Date.now() + 1 * 60 * 60 * 1000}`
77
66
  : 'guest';
@@ -91,16 +80,13 @@ module.exports = class extends BaseRest {
91
80
 
92
81
  try {
93
82
  const notify = this.service('notify', this);
94
- const apiUrl = think.buildUrl(this.ctx.serverURL + '/verification', {
83
+ const apiUrl = think.buildUrl(`${this.ctx.serverURL}/verification`, {
95
84
  token,
96
85
  email: data.email,
97
86
  });
98
87
 
99
88
  await notify.transporter.sendMail({
100
- from:
101
- SENDER_EMAIL && SENDER_NAME
102
- ? `"${SENDER_NAME}" <${SENDER_EMAIL}>`
103
- : SMTP_USER,
89
+ from: SENDER_EMAIL && SENDER_NAME ? `"${SENDER_NAME}" <${SENDER_EMAIL}>` : SMTP_USER,
104
90
  to: data.email,
105
91
  subject: this.locale('[{{name | safe}}] Registration Confirm Mail', {
106
92
  name: SITE_NAME || 'Waline',
@@ -125,8 +111,7 @@ module.exports = class extends BaseRest {
125
111
  }
126
112
 
127
113
  async putAction() {
128
- const { display_name, url, avatar, password, type, label, email } =
129
- this.post();
114
+ const { display_name, url, avatar, password, type, label, email } = this.post();
130
115
  const { objectId } = this.ctx.state.userInfo;
131
116
  const twoFactorAuth = this.post('2fa');
132
117
 
@@ -194,6 +179,7 @@ module.exports = class extends BaseRest {
194
179
  return this.success();
195
180
  }
196
181
 
182
+ // oxlint-disable-next-line max-statements
197
183
  async getUsersListByCount() {
198
184
  const { pageSize } = this.get();
199
185
  const commentModel = this.getModel('Comment');
@@ -209,13 +195,11 @@ module.exports = class extends BaseRest {
209
195
  counts.sort((a, b) => b.count - a.count);
210
196
  counts.length = Math.min(pageSize, counts.length);
211
197
 
212
- const userIds = counts
213
- .filter(({ user_id }) => user_id)
214
- .map(({ user_id }) => user_id);
198
+ const userIds = counts.filter(({ user_id }) => user_id).map(({ user_id }) => user_id);
215
199
 
216
- let usersMap = {};
200
+ const usersMap = {};
217
201
 
218
- if (userIds.length) {
202
+ if (userIds.length > 0) {
219
203
  const users = await this.modelInstance.select({
220
204
  objectId: ['IN', userIds],
221
205
  });
@@ -237,10 +221,7 @@ module.exports = class extends BaseRest {
237
221
  let level = 0;
238
222
 
239
223
  if (user.count) {
240
- const _level = think.findLastIndex(
241
- this.config('levels'),
242
- (l) => l <= user.count,
243
- );
224
+ const _level = think.findLastIndex(this.config('levels'), (level) => level <= user.count);
244
225
 
245
226
  if (_level !== -1) {
246
227
  level = _level;
@@ -250,15 +231,10 @@ module.exports = class extends BaseRest {
250
231
  }
251
232
 
252
233
  if (count.user_id && users[count.user_id]) {
253
- const {
254
- display_name: nick,
255
- url: link,
256
- avatar: avatarUrl,
257
- label,
258
- } = users[count.user_id];
234
+ const { display_name: nick, url: link, avatar: avatarUrl, label } = users[count.user_id];
259
235
  const avatar =
260
236
  avatarProxy && !avatarUrl.includes(avatarProxy)
261
- ? avatarProxy + '?url=' + encodeURIComponent(avatarUrl)
237
+ ? `${avatarProxy}?url=${encodeURIComponent(avatarUrl)}`
262
238
  : avatarUrl;
263
239
 
264
240
  Object.assign(user, { nick, link, avatar, label });
@@ -266,15 +242,12 @@ module.exports = class extends BaseRest {
266
242
  continue;
267
243
  }
268
244
 
269
- const comments = await commentModel.select(
270
- { mail: count.mail },
271
- { limit: 1 },
272
- );
245
+ const comments = await commentModel.select({ mail: count.mail }, { limit: 1 });
273
246
 
274
247
  if (think.isEmpty(comments)) {
275
248
  continue;
276
249
  }
277
- const comment = comments[0];
250
+ const [comment] = comments;
278
251
 
279
252
  if (think.isEmpty(comment)) {
280
253
  continue;
@@ -283,7 +256,7 @@ module.exports = class extends BaseRest {
283
256
  const avatarUrl = await think.service('avatar').stringify(comment);
284
257
  const avatar =
285
258
  avatarProxy && !avatarUrl.includes(avatarProxy)
286
- ? avatarProxy + '?url=' + encodeURIComponent(avatarUrl)
259
+ ? `${avatarProxy}?url=${encodeURIComponent(avatarUrl)}`
287
260
  : avatarUrl;
288
261
 
289
262
  Object.assign(user, { nick, link, avatar });
@@ -21,10 +21,11 @@ module.exports = class extends BaseRest {
21
21
  return this.fail(this.locale('USER_REGISTERED'));
22
22
  }
23
23
 
24
- if (token === match[1] && Date.now() < parseInt(match[2])) {
24
+ if (token === match[1] && Date.now() < Number.parseInt(match[2])) {
25
25
  await this.modelInstance.update({ type: 'guest' }, { email });
26
26
 
27
- return this.redirect('/ui/login');
27
+ this.redirect('/ui/login');
28
+ return;
28
29
  }
29
30
 
30
31
  return this.fail(this.locale('TOKEN_EXPIRED'));
@@ -1,10 +1,24 @@
1
- const ip2region = require('dy-node-ip2region');
2
- const helper = require('think-helper');
1
+ const IP2Region = require('ip2region').default;
3
2
  const parser = require('ua-parser-js');
4
3
 
5
4
  const preventMessage = 'PREVENT_NEXT_PROCESS';
6
5
 
7
- const regionSearch = ip2region.create(process.env.IP2REGION_DB);
6
+ // Cached IP2Region instance using IIFE closure pattern
7
+ // Instance is created on first access and reused for all subsequent calls
8
+ const getIP2RegionInstance = (() => {
9
+ let instance = null;
10
+
11
+ return () => {
12
+ if (!instance) {
13
+ instance = new IP2Region({
14
+ ipv4db: process.env.IP2REGION_DB_V4 || process.env.IP2REGION_DB,
15
+ ipv6db: process.env.IP2REGION_DB_V6,
16
+ });
17
+ }
18
+
19
+ return instance;
20
+ };
21
+ })();
8
22
 
9
23
  const OS_VERSION_MAP = {
10
24
  Windows: {
@@ -34,15 +48,17 @@ module.exports = {
34
48
  },
35
49
  promiseAllQueue(promises, taskNum) {
36
50
  return new Promise((resolve, reject) => {
37
- if (!promises.length) {
38
- return resolve();
51
+ if (promises.length === 0) {
52
+ resolve();
53
+
54
+ return;
39
55
  }
40
56
 
41
57
  const ret = [];
42
58
  let index = 0;
43
59
  let count = 0;
44
60
 
45
- function runTask() {
61
+ const runTask = () => {
46
62
  const idx = index;
47
63
 
48
64
  index += 1;
@@ -59,7 +75,7 @@ module.exports = {
59
75
 
60
76
  return runTask();
61
77
  }, reject);
62
- }
78
+ };
63
79
 
64
80
  for (let i = 0; i < taskNum; i++) {
65
81
  runTask();
@@ -67,21 +83,17 @@ module.exports = {
67
83
  });
68
84
  },
69
85
  async ip2region(ip, { depth = 1 }) {
70
- if (!ip || ip.includes(':')) return '';
86
+ if (!ip) return '';
71
87
 
72
88
  try {
73
- const search = helper.promisify(regionSearch.btreeSearch, regionSearch);
74
- const result = await search(ip);
89
+ const res = getIP2RegionInstance().search(ip);
75
90
 
76
- if (!result) {
91
+ if (!res) {
77
92
  return '';
78
93
  }
79
- const { region } = result;
80
- const [, , province, city, isp] = region.split('|');
81
- const address = Array.from(
82
- new Set([province, city, isp].filter((v) => v)),
83
- );
84
94
 
95
+ const { province, city, isp } = res;
96
+ const address = [...new Set([province, city, isp].filter(Boolean))];
85
97
  return address.slice(0, depth).join(' ');
86
98
  } catch (err) {
87
99
  console.log(err);
@@ -106,7 +118,7 @@ module.exports = {
106
118
  return defaultLevel;
107
119
  }
108
120
 
109
- const level = think.findLastIndex(levels, (l) => l <= val);
121
+ const level = think.findLastIndex(levels, (level) => level <= val);
110
122
 
111
123
  return level === -1 ? defaultLevel : level;
112
124
  },
@@ -141,7 +153,7 @@ module.exports = {
141
153
  }
142
154
 
143
155
  if (think.isArray(middleware)) {
144
- return middleware.filter((m) => think.isFunction(m));
156
+ return middleware.filter((middleware) => think.isFunction(middleware));
145
157
  }
146
158
  });
147
159
 
@@ -149,10 +161,8 @@ module.exports = {
149
161
  },
150
162
  getPluginHook(hookName) {
151
163
  return think
152
- .pluginMap('hooks', (hook) =>
153
- think.isFunction(hook[hookName]) ? hook[hookName] : undefined,
154
- )
155
- .filter((v) => v);
164
+ .pluginMap('hooks', (hook) => (think.isFunction(hook[hookName]) ? hook[hookName] : null))
165
+ .filter(Boolean);
156
166
  },
157
167
  buildUrl(path, query = {}) {
158
168
  const notEmptyQuery = {};
@@ -169,7 +179,7 @@ module.exports = {
169
179
  let destUrl = path;
170
180
 
171
181
  if (destUrl && notEmptyQueryStr) {
172
- destUrl += destUrl.indexOf('?') !== -1 ? '&' : '?';
182
+ destUrl += destUrl.includes('?') ? '&' : '?';
173
183
  }
174
184
  if (notEmptyQueryStr) {
175
185
  destUrl += notEmptyQueryStr;
package/src/logic/base.js CHANGED
@@ -3,7 +3,7 @@ const qs = require('node:querystring');
3
3
 
4
4
  const jwt = require('jsonwebtoken');
5
5
 
6
- module.exports = class extends think.Logic {
6
+ module.exports = class BaseLogic extends think.Logic {
7
7
  constructor(...args) {
8
8
  super(...args);
9
9
  this.modelInstance = this.getModel('Users');
@@ -11,26 +11,25 @@ module.exports = class extends think.Logic {
11
11
  this.id = this.getId();
12
12
  }
13
13
 
14
+ // oxlint-disable-next-line max-statements
14
15
  async __before() {
15
16
  const referrer = this.ctx.referrer(true);
16
- let origin = this.ctx.origin;
17
+ let { origin } = this.ctx;
17
18
 
18
19
  if (origin) {
19
20
  try {
20
21
  const parsedOrigin = new URL(origin);
21
22
 
22
23
  origin = parsedOrigin.hostname;
23
- } catch (e) {
24
- console.error('Invalid origin format:', origin, e);
24
+ } catch (err) {
25
+ console.error('Invalid origin format:', origin, err);
25
26
  }
26
27
  }
27
28
 
28
29
  let { secureDomains } = this.config();
29
30
 
30
31
  if (secureDomains) {
31
- secureDomains = think.isArray(secureDomains)
32
- ? secureDomains
33
- : [secureDomains];
32
+ secureDomains = think.isArray(secureDomains) ? secureDomains : [secureDomains];
34
33
 
35
34
  secureDomains.push(
36
35
  'localhost',
@@ -41,27 +40,20 @@ module.exports = class extends think.Logic {
41
40
  // 'api.weibo.com',
42
41
  // 'graph.qq.com',
43
42
  );
44
- secureDomains = secureDomains.concat(
45
- this.ctx.state.oauthServices.map(({ origin }) => origin),
46
- );
43
+ secureDomains = [
44
+ ...secureDomains,
45
+ ...this.ctx.state.oauthServices.map(({ origin }) => origin),
46
+ ];
47
47
 
48
48
  // 转换可能的正则表达式字符串为正则表达式对象
49
49
  secureDomains = secureDomains
50
50
  .map((domain) => {
51
51
  // 如果是正则表达式字符串,创建一个 RegExp 对象
52
- if (
53
- typeof domain === 'string' &&
54
- domain.startsWith('/') &&
55
- domain.endsWith('/')
56
- ) {
52
+ if (typeof domain === 'string' && domain.startsWith('/') && domain.endsWith('/')) {
57
53
  try {
58
54
  return new RegExp(domain.slice(1, -1)); // 去掉斜杠并创建 RegExp 对象
59
- } catch (e) {
60
- console.error(
61
- 'Invalid regex pattern in secureDomains:',
62
- domain,
63
- e,
64
- );
55
+ } catch (err) {
56
+ console.error('Invalid regex pattern in secureDomains:', domain, err);
65
57
 
66
58
  return null;
67
59
  }
@@ -72,11 +64,9 @@ module.exports = class extends think.Logic {
72
64
  .filter(Boolean); // 过滤掉无效的正则表达式
73
65
 
74
66
  // 有 referrer 检查 referrer,没有则检查 origin
75
- const checking = referrer ? referrer : origin;
67
+ const checking = referrer || origin;
76
68
  const isSafe = secureDomains.some((domain) =>
77
- think.isFunction(domain.test)
78
- ? domain.test(checking)
79
- : domain === checking,
69
+ think.isFunction(domain.test) ? domain.test(checking) : domain === checking,
80
70
  );
81
71
 
82
72
  if (!isSafe) {
@@ -96,8 +86,8 @@ module.exports = class extends think.Logic {
96
86
 
97
87
  try {
98
88
  userId = jwt.verify(token, think.config('jwtKey'));
99
- } catch (e) {
100
- think.logger.debug(e);
89
+ } catch (err) {
90
+ think.logger.debug(err);
101
91
  }
102
92
 
103
93
  if (think.isEmpty(userId) || !think.isString(userId)) {
@@ -125,19 +115,19 @@ module.exports = class extends think.Logic {
125
115
  return;
126
116
  }
127
117
 
128
- const userInfo = user[0];
118
+ const [userInfo] = user;
129
119
 
130
- let avatarUrl = userInfo.avatar
131
- ? userInfo.avatar
132
- : await think.service('avatar').stringify({
133
- mail: userInfo.email,
134
- nick: userInfo.display_name,
135
- link: userInfo.url,
136
- });
120
+ let avatarUrl =
121
+ userInfo.avatar ||
122
+ (await think.service('avatar').stringify({
123
+ mail: userInfo.email,
124
+ nick: userInfo.display_name,
125
+ link: userInfo.url,
126
+ }));
137
127
  const { avatarProxy } = think.config();
138
128
 
139
129
  if (avatarProxy) {
140
- avatarUrl = avatarProxy + '?url=' + encodeURIComponent(avatarUrl);
130
+ avatarUrl = `${avatarProxy}?url=${encodeURIComponent(avatarUrl)}`;
141
131
  }
142
132
  userInfo.avatar = avatarUrl;
143
133
  this.ctx.state.userInfo = userInfo;
@@ -148,7 +138,7 @@ module.exports = class extends think.Logic {
148
138
  const filename = this.__filename || __filename;
149
139
  const last = filename.lastIndexOf(path.sep);
150
140
 
151
- return filename.substr(last + 1, filename.length - last - 4);
141
+ return filename.slice(last + 1, filename.length - last - 4);
152
142
  }
153
143
 
154
144
  getId() {
@@ -205,28 +195,22 @@ module.exports = class extends think.Logic {
205
195
  remoteip: this.ctx.ip,
206
196
  });
207
197
 
208
- const requestUrl = method === 'GET' ? api + '?' + query : api;
198
+ const requestUrl = method === 'GET' ? `${api}?${query}` : api;
209
199
  const options =
210
200
  method === 'GET'
211
201
  ? {}
212
202
  : {
213
203
  method,
214
204
  headers: {
215
- 'content-type':
216
- 'application/x-www-form-urlencoded; charset=UTF-8',
205
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
217
206
  },
218
207
  body: query,
219
208
  };
220
209
 
221
- const response = await fetch(requestUrl, options).then((resp) =>
222
- resp.json(),
223
- );
210
+ const response = await fetch(requestUrl, options).then((resp) => resp.json());
224
211
 
225
212
  if (!response.success) {
226
- think.logger.debug(
227
- 'RecaptchaV3 or Turnstile Result:',
228
- JSON.stringify(response, null, '\t'),
229
- );
213
+ think.logger.debug('RecaptchaV3 or Turnstile Result:', JSON.stringify(response, null, '\t'));
230
214
 
231
215
  return this.ctx.throw(403);
232
216
  }
@@ -1,6 +1,6 @@
1
1
  const Base = require('./base.js');
2
2
 
3
- module.exports = class extends Base {
3
+ module.exports = class CommentLogic extends Base {
4
4
  checkAdmin() {
5
5
  const { userInfo } = this.ctx.state;
6
6
 
@@ -117,7 +117,7 @@ module.exports = class extends Base {
117
117
  }
118
118
 
119
119
  switch (type) {
120
- case 'recent':
120
+ case 'recent': {
121
121
  this.rules = {
122
122
  count: {
123
123
  int: { max: 50 },
@@ -125,14 +125,16 @@ module.exports = class extends Base {
125
125
  },
126
126
  };
127
127
  break;
128
+ }
128
129
 
129
- case 'count':
130
+ case 'count': {
130
131
  this.rules = {
131
132
  url: {
132
133
  array: true,
133
134
  },
134
135
  };
135
136
  break;
137
+ }
136
138
 
137
139
  case 'list': {
138
140
  const { userInfo } = this.ctx.state;
@@ -153,7 +155,7 @@ module.exports = class extends Base {
153
155
  break;
154
156
  }
155
157
 
156
- default:
158
+ default: {
157
159
  this.rules = {
158
160
  path: {
159
161
  string: true,
@@ -173,6 +175,7 @@ module.exports = class extends Base {
173
175
  },
174
176
  };
175
177
  break;
178
+ }
176
179
  }
177
180
  }
178
181
 
package/src/logic/db.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const Base = require('./base.js');
2
2
 
3
- module.exports = class extends Base {
3
+ module.exports = class DatabaseLogic extends Base {
4
4
  async __before(...args) {
5
5
  await super.__before(...args);
6
6
 
@@ -34,8 +34,8 @@ module.exports = class extends Base {
34
34
  * @apiSuccess (200) {Number} errno 0
35
35
  * @apiSuccess (200) {String} errmsg return error message if error
36
36
  */
37
- postAction() {
38
- return this.useCaptchaCheck();
37
+ async postAction() {
38
+ await this.useCaptchaCheck();
39
39
  }
40
40
 
41
41
  /**
@@ -1,3 +1,4 @@
1
+ // oxlint-disable-next-line func-names
1
2
  module.exports = function () {
2
3
  return (ctx) => {
3
4
  ctx.type = 'html';
@@ -3,7 +3,7 @@ const compose = require('koa-compose');
3
3
  module.exports = () => async (ctx, next) => {
4
4
  const middlewares = think.getPluginMiddlewares();
5
5
 
6
- if (!think.isArray(middlewares) || !middlewares.length) {
6
+ if (!think.isArray(middlewares) || middlewares.length === 0) {
7
7
  return next();
8
8
  }
9
9
 
@@ -2,6 +2,7 @@ const Akismet = require('akismet');
2
2
 
3
3
  const DEFAULT_KEY = '70542d86693e';
4
4
 
5
+ // oxlint-disable-next-line func-names
5
6
  module.exports = function (comment, blog) {
6
7
  let { AKISMET_KEY, SITE_URL } = process.env;
7
8
 
@@ -13,14 +14,18 @@ module.exports = function (comment, blog) {
13
14
  return Promise.resolve(false);
14
15
  }
15
16
 
17
+ // oxlint-disable-next-line func-names
16
18
  return new Promise(function (resolve, reject) {
17
19
  const akismet = Akismet.client({ blog, apiKey: AKISMET_KEY });
18
20
 
21
+ // oxlint-disable-next-line func-names
19
22
  akismet.verifyKey(function (err, verifyKey) {
20
23
  if (err) {
21
- return reject(err);
24
+ reject(err);
25
+ return;
22
26
  } else if (!verifyKey) {
23
- return reject(new Error('Akismet API_KEY verify failed!'));
27
+ reject(new Error('Akismet API_KEY verify failed!'));
28
+ return;
24
29
  }
25
30
 
26
31
  akismet.checkComment(
@@ -30,9 +35,11 @@ module.exports = function (comment, blog) {
30
35
  comment_author: comment.nick,
31
36
  comment_content: comment.comment,
32
37
  },
38
+ // oxlint-disable-next-line func-names
33
39
  function (err, spam) {
34
40
  if (err) {
35
- return reject(err);
41
+ reject(err);
42
+ return;
36
43
  }
37
44
  resolve(spam);
38
45
  },
@@ -1,4 +1,4 @@
1
- const crypto = require('crypto');
1
+ const crypto = require('node:crypto');
2
2
 
3
3
  const nunjucks = require('nunjucks');
4
4
  const helper = require('think-helper');
@@ -8,9 +8,7 @@ const { GRAVATAR_STR } = process.env;
8
8
  const env = new nunjucks.Environment();
9
9
 
10
10
  env.addFilter('md5', (str) => helper.md5(str));
11
- env.addFilter('sha256', (str) =>
12
- crypto.createHash('sha256').update(str).digest('hex'),
13
- );
11
+ env.addFilter('sha256', (str) => crypto.createHash('sha256').update(str).digest('hex'));
14
12
 
15
13
  const DEFAULT_GRAVATAR_STR = `{%- set numExp = r/^[0-9]+$/g -%}
16
14
  {%- set qqMailExp = r/^[0-9]+@qq.com$/ig -%}
@@ -7,7 +7,7 @@ rawLoadLanguages.silent = true;
7
7
  const loadLanguages = (languages = []) => {
8
8
  const langsToLoad = languages.filter((item) => !prism.languages[item]);
9
9
 
10
- if (langsToLoad.length) {
10
+ if (langsToLoad.length > 0) {
11
11
  rawLoadLanguages(langsToLoad);
12
12
  }
13
13
  };
@@ -12,11 +12,7 @@ const isValidDelim = (state, pos) => {
12
12
  * Check non-whitespace conditions for opening and closing, and
13
13
  * check that closing delimiter isn’t followed by a number
14
14
  */
15
- canClose: !(
16
- prevChar === ' ' ||
17
- prevChar === '\t' ||
18
- /[0-9]/u.exec(nextChar)
19
- ),
15
+ canClose: !(prevChar === ' ' || prevChar === '\t' || /[0-9]/u.exec(nextChar)),
20
16
  };
21
17
  };
22
18
 
@@ -141,9 +137,7 @@ const blockTeX = (state, start, end, silent) => {
141
137
  ? `${firstLine}\n`
142
138
  : '') +
143
139
  state.getLines(start + 1, next, state.tShift[start], true) +
144
- ((lastLine === null || lastLine === void 0 ? void 0 : lastLine.trim())
145
- ? lastLine
146
- : '');
140
+ ((lastLine === null || lastLine === void 0 ? void 0 : lastLine.trim()) ? lastLine : '');
147
141
  token.map = [start, state.line];
148
142
  token.markup = '$$';
149
143