artalk 2.8.5 → 2.8.7
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/dist/Artalk.cjs +1 -1
- package/dist/Artalk.cjs.map +1 -1
- package/dist/Artalk.iife.js +1 -1
- package/dist/Artalk.iife.js.map +1 -1
- package/dist/Artalk.js +1 -1
- package/dist/Artalk.js.map +1 -1
- package/dist/Artalk.mjs +592 -358
- package/dist/Artalk.mjs.map +1 -1
- package/dist/ArtalkLite.cjs +2 -2
- package/dist/ArtalkLite.cjs.map +1 -1
- package/dist/ArtalkLite.iife.js +2 -2
- package/dist/ArtalkLite.iife.js.map +1 -1
- package/dist/ArtalkLite.js +2 -2
- package/dist/ArtalkLite.js.map +1 -1
- package/dist/ArtalkLite.mjs +590 -357
- package/dist/ArtalkLite.mjs.map +1 -1
- package/dist/i18n/jp.cjs +1 -1
- package/dist/i18n/jp.js +1 -1
- package/dist/i18n/jp.mjs +21 -0
- package/dist/i18n/zh-TW.cjs +1 -1
- package/dist/i18n/zh-TW.js +1 -1
- package/dist/i18n/zh-TW.mjs +21 -4
- package/dist/main.d.cts +213 -12
- package/dist/main.d.ts +213 -12
- package/package.json +9 -11
package/dist/ArtalkLite.mjs
CHANGED
|
@@ -142,11 +142,14 @@ class HttpClient {
|
|
|
142
142
|
/* Json */
|
|
143
143
|
];
|
|
144
144
|
const responseFormat = format || requestParams.format;
|
|
145
|
-
return this.customFetch(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
return this.customFetch(
|
|
146
|
+
`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`,
|
|
147
|
+
__spreadProps(__spreadValues({}, requestParams), {
|
|
148
|
+
headers: __spreadValues(__spreadValues({}, requestParams.headers || {}), type && type !== "multipart/form-data" ? { "Content-Type": type } : {}),
|
|
149
|
+
signal: (cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal) || null,
|
|
150
|
+
body: typeof body === "undefined" || body === null ? null : payloadFormatter(body)
|
|
151
|
+
})
|
|
152
|
+
).then((response) => __async(this, null, function* () {
|
|
150
153
|
const r = response;
|
|
151
154
|
r.data = null;
|
|
152
155
|
r.error = null;
|
|
@@ -185,7 +188,9 @@ class HttpClient {
|
|
|
185
188
|
toQueryString(rawQuery) {
|
|
186
189
|
const query = rawQuery || {};
|
|
187
190
|
const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
|
|
188
|
-
return keys.map(
|
|
191
|
+
return keys.map(
|
|
192
|
+
(key) => Array.isArray(query[key]) ? this.addArrayQueryParam(query, key) : this.addQueryParam(query, key)
|
|
193
|
+
).join("&");
|
|
189
194
|
}
|
|
190
195
|
addQueryParams(rawQuery) {
|
|
191
196
|
const queryString = this.toQueryString(rawQuery);
|
|
@@ -209,6 +214,133 @@ class HttpClient {
|
|
|
209
214
|
let Api$1 = class Api extends HttpClient {
|
|
210
215
|
constructor() {
|
|
211
216
|
super(...arguments);
|
|
217
|
+
__publicField(this, "auth", {
|
|
218
|
+
/**
|
|
219
|
+
* @description Login by email with verify code (Need send email verify code first) or password
|
|
220
|
+
*
|
|
221
|
+
* @tags Auth
|
|
222
|
+
* @name LoginByEmail
|
|
223
|
+
* @summary Login by email
|
|
224
|
+
* @request POST:/auth/email/login
|
|
225
|
+
* @response `200` `HandlerResponseUserLogin` OK
|
|
226
|
+
* @response `400` `(HandlerMap & {
|
|
227
|
+
msg?: string,
|
|
228
|
+
|
|
229
|
+
})` Bad Request
|
|
230
|
+
* @response `500` `(HandlerMap & {
|
|
231
|
+
msg?: string,
|
|
232
|
+
|
|
233
|
+
})` Internal Server Error
|
|
234
|
+
*/
|
|
235
|
+
loginByEmail: (data, params = {}) => this.request(__spreadValues({
|
|
236
|
+
path: `/auth/email/login`,
|
|
237
|
+
method: "POST",
|
|
238
|
+
body: data,
|
|
239
|
+
type: "application/json",
|
|
240
|
+
format: "json"
|
|
241
|
+
}, params)),
|
|
242
|
+
/**
|
|
243
|
+
* @description Register by email and verify code (if user exists, will update user, like forget password. Need send email verify code first)
|
|
244
|
+
*
|
|
245
|
+
* @tags Auth
|
|
246
|
+
* @name RegisterByEmail
|
|
247
|
+
* @summary Register by email
|
|
248
|
+
* @request POST:/auth/email/register
|
|
249
|
+
* @response `200` `HandlerResponseUserLogin` OK
|
|
250
|
+
* @response `400` `(HandlerMap & {
|
|
251
|
+
msg?: string,
|
|
252
|
+
|
|
253
|
+
})` Bad Request
|
|
254
|
+
* @response `500` `(HandlerMap & {
|
|
255
|
+
msg?: string,
|
|
256
|
+
|
|
257
|
+
})` Internal Server Error
|
|
258
|
+
*/
|
|
259
|
+
registerByEmail: (data, params = {}) => this.request(__spreadValues({
|
|
260
|
+
path: `/auth/email/register`,
|
|
261
|
+
method: "POST",
|
|
262
|
+
body: data,
|
|
263
|
+
type: "application/json",
|
|
264
|
+
format: "json"
|
|
265
|
+
}, params)),
|
|
266
|
+
/**
|
|
267
|
+
* @description Send email including verify code to user
|
|
268
|
+
*
|
|
269
|
+
* @tags Auth
|
|
270
|
+
* @name SendVerifyEmail
|
|
271
|
+
* @summary Send verify email
|
|
272
|
+
* @request POST:/auth/email/send
|
|
273
|
+
* @response `200` `(HandlerMap & {
|
|
274
|
+
msg?: string,
|
|
275
|
+
|
|
276
|
+
})` OK
|
|
277
|
+
* @response `400` `(HandlerMap & {
|
|
278
|
+
msg?: string,
|
|
279
|
+
|
|
280
|
+
})` Bad Request
|
|
281
|
+
* @response `500` `(HandlerMap & {
|
|
282
|
+
msg?: string,
|
|
283
|
+
|
|
284
|
+
})` Internal Server Error
|
|
285
|
+
*/
|
|
286
|
+
sendVerifyEmail: (data, params = {}) => this.request(__spreadValues({
|
|
287
|
+
path: `/auth/email/send`,
|
|
288
|
+
method: "POST",
|
|
289
|
+
body: data,
|
|
290
|
+
type: "application/json",
|
|
291
|
+
format: "json"
|
|
292
|
+
}, params)),
|
|
293
|
+
/**
|
|
294
|
+
* @description Get all users with same email, if there are more than one user with same email, need merge
|
|
295
|
+
*
|
|
296
|
+
* @tags Auth
|
|
297
|
+
* @name CheckDataMerge
|
|
298
|
+
* @summary Check data merge
|
|
299
|
+
* @request GET:/auth/merge
|
|
300
|
+
* @secure
|
|
301
|
+
* @response `200` `HandlerResponseAuthDataMergeCheck` OK
|
|
302
|
+
* @response `400` `(HandlerMap & {
|
|
303
|
+
msg?: string,
|
|
304
|
+
|
|
305
|
+
})` Bad Request
|
|
306
|
+
* @response `500` `(HandlerMap & {
|
|
307
|
+
msg?: string,
|
|
308
|
+
|
|
309
|
+
})` Internal Server Error
|
|
310
|
+
*/
|
|
311
|
+
checkDataMerge: (params = {}) => this.request(__spreadValues({
|
|
312
|
+
path: `/auth/merge`,
|
|
313
|
+
method: "GET",
|
|
314
|
+
secure: true,
|
|
315
|
+
format: "json"
|
|
316
|
+
}, params)),
|
|
317
|
+
/**
|
|
318
|
+
* @description This function is to solve the problem of multiple users with the same email address, should be called after user login and then check, and perform data merge.
|
|
319
|
+
*
|
|
320
|
+
* @tags Auth
|
|
321
|
+
* @name ApplyDataMerge
|
|
322
|
+
* @summary Apply data merge
|
|
323
|
+
* @request POST:/auth/merge
|
|
324
|
+
* @secure
|
|
325
|
+
* @response `200` `HandlerResponseAuthDataMergeApply` OK
|
|
326
|
+
* @response `400` `(HandlerMap & {
|
|
327
|
+
msg?: string,
|
|
328
|
+
|
|
329
|
+
})` Bad Request
|
|
330
|
+
* @response `500` `(HandlerMap & {
|
|
331
|
+
msg?: string,
|
|
332
|
+
|
|
333
|
+
})` Internal Server Error
|
|
334
|
+
*/
|
|
335
|
+
applyDataMerge: (data, params = {}) => this.request(__spreadValues({
|
|
336
|
+
path: `/auth/merge`,
|
|
337
|
+
method: "POST",
|
|
338
|
+
body: data,
|
|
339
|
+
secure: true,
|
|
340
|
+
type: "application/json",
|
|
341
|
+
format: "json"
|
|
342
|
+
}, params))
|
|
343
|
+
});
|
|
212
344
|
__publicField(this, "cache", {
|
|
213
345
|
/**
|
|
214
346
|
* @description Flush all cache on the server
|
|
@@ -469,6 +601,24 @@ let Api$1 = class Api extends HttpClient {
|
|
|
469
601
|
method: "GET",
|
|
470
602
|
format: "json"
|
|
471
603
|
}, params)),
|
|
604
|
+
/**
|
|
605
|
+
* @description Get social login providers
|
|
606
|
+
*
|
|
607
|
+
* @tags System
|
|
608
|
+
* @name GetSocialLoginProviders
|
|
609
|
+
* @summary Get Social Login Providers
|
|
610
|
+
* @request GET:/conf/auth/providers
|
|
611
|
+
* @response `200` `HandlerResponseConfAuthProviders` OK
|
|
612
|
+
* @response `404` `(HandlerMap & {
|
|
613
|
+
msg?: string,
|
|
614
|
+
|
|
615
|
+
})` Not Found
|
|
616
|
+
*/
|
|
617
|
+
getSocialLoginProviders: (params = {}) => this.request(__spreadValues({
|
|
618
|
+
path: `/conf/auth/providers`,
|
|
619
|
+
method: "GET",
|
|
620
|
+
format: "json"
|
|
621
|
+
}, params)),
|
|
472
622
|
/**
|
|
473
623
|
* @description Get Domain Info
|
|
474
624
|
*
|
|
@@ -1328,8 +1478,6 @@ function getDefaultExportFromCjs(x) {
|
|
|
1328
1478
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
1329
1479
|
if (protoProps)
|
|
1330
1480
|
_defineProperties(Constructor.prototype, protoProps);
|
|
1331
|
-
if (staticProps)
|
|
1332
|
-
_defineProperties(Constructor, staticProps);
|
|
1333
1481
|
Object.defineProperty(Constructor, "prototype", {
|
|
1334
1482
|
writable: false
|
|
1335
1483
|
});
|
|
@@ -2228,7 +2376,7 @@ const insaneOptions = {
|
|
|
2228
2376
|
allowedAttributes: {
|
|
2229
2377
|
"*": ["title", "accesskey"],
|
|
2230
2378
|
a: ["href", "name", "target", "aria-label", "rel"],
|
|
2231
|
-
img: ["src", "alt", "title", "atk-emoticon", "aria-label"],
|
|
2379
|
+
img: ["src", "alt", "title", "atk-emoticon", "aria-label", "data-src", "class", "loading"],
|
|
2232
2380
|
// for code highlight
|
|
2233
2381
|
code: ["class"],
|
|
2234
2382
|
span: ["class", "style"]
|
|
@@ -2236,7 +2384,8 @@ const insaneOptions = {
|
|
|
2236
2384
|
filter: (node) => {
|
|
2237
2385
|
const allowed = [
|
|
2238
2386
|
["code", /^hljs\W+language-(.*)$/],
|
|
2239
|
-
["span", /^(hljs-.*)$/]
|
|
2387
|
+
["span", /^(hljs-.*)$/],
|
|
2388
|
+
["img", /^lazyload$/]
|
|
2240
2389
|
];
|
|
2241
2390
|
allowed.forEach(([tag, reg]) => {
|
|
2242
2391
|
if (node.tag === tag && !!node.attrs.class && !reg.test(node.attrs.class)) {
|
|
@@ -2313,18 +2462,26 @@ const hanabi = /* @__PURE__ */ getDefaultExportFromCjs(hanabiExports);
|
|
|
2313
2462
|
function renderCode(code) {
|
|
2314
2463
|
return hanabi(code);
|
|
2315
2464
|
}
|
|
2316
|
-
function getRenderer() {
|
|
2465
|
+
function getRenderer(options) {
|
|
2317
2466
|
const renderer = new marked$1.Renderer();
|
|
2318
2467
|
renderer.link = markedLinkRenderer(renderer, renderer.link);
|
|
2319
2468
|
renderer.code = markedCodeRenderer();
|
|
2469
|
+
renderer.image = markedImageRenderer(renderer, renderer.image, options);
|
|
2320
2470
|
return renderer;
|
|
2321
2471
|
}
|
|
2322
2472
|
const markedLinkRenderer = (renderer, orgLinkRenderer) => (href, title, text) => {
|
|
2323
|
-
const
|
|
2473
|
+
const getLinkOrigin = (link) => {
|
|
2474
|
+
try {
|
|
2475
|
+
return new URL(link).origin;
|
|
2476
|
+
} catch (e) {
|
|
2477
|
+
return "";
|
|
2478
|
+
}
|
|
2479
|
+
};
|
|
2480
|
+
const isSameOriginLink = getLinkOrigin(href) === window.location.origin;
|
|
2324
2481
|
const html = orgLinkRenderer.call(renderer, href, title, text);
|
|
2325
2482
|
return html.replace(
|
|
2326
2483
|
/^<a /,
|
|
2327
|
-
`<a target="_blank" ${!
|
|
2484
|
+
`<a target="_blank" ${!isSameOriginLink ? `rel="noreferrer noopener nofollow"` : ""} `
|
|
2328
2485
|
);
|
|
2329
2486
|
};
|
|
2330
2487
|
const markedCodeRenderer = () => (block, lang) => {
|
|
@@ -2341,6 +2498,16 @@ const markedCodeRenderer = () => (block, lang) => {
|
|
|
2341
2498
|
<code class="hljs language-${realLang}">${colorized.replace(/&/g, "&")}</code>
|
|
2342
2499
|
</pre>`;
|
|
2343
2500
|
};
|
|
2501
|
+
const markedImageRenderer = (renderer, orgImageRenderer, { imgLazyLoad }) => (href, title, text) => {
|
|
2502
|
+
const html = orgImageRenderer.call(renderer, href, title, text);
|
|
2503
|
+
if (!imgLazyLoad)
|
|
2504
|
+
return html;
|
|
2505
|
+
if (imgLazyLoad === "native" || imgLazyLoad === true)
|
|
2506
|
+
return html.replace(/^<img /, '<img class="lazyload" loading="lazy" ');
|
|
2507
|
+
if (imgLazyLoad === "data-src")
|
|
2508
|
+
return html.replace(/^<img /, '<img class="lazyload" ').replace("src=", "data-src=");
|
|
2509
|
+
return html;
|
|
2510
|
+
};
|
|
2344
2511
|
let instance;
|
|
2345
2512
|
let replacers = [];
|
|
2346
2513
|
const markedOptions = {
|
|
@@ -2354,16 +2521,18 @@ function getInstance() {
|
|
|
2354
2521
|
function setReplacers(arr) {
|
|
2355
2522
|
replacers = arr;
|
|
2356
2523
|
}
|
|
2357
|
-
function initMarked() {
|
|
2524
|
+
function initMarked(options) {
|
|
2358
2525
|
try {
|
|
2359
2526
|
if (!marked$1.name)
|
|
2360
2527
|
return;
|
|
2361
2528
|
} catch (e) {
|
|
2362
2529
|
return;
|
|
2363
2530
|
}
|
|
2364
|
-
marked$1.setOptions(__spreadValues({
|
|
2365
|
-
renderer: getRenderer(
|
|
2366
|
-
|
|
2531
|
+
marked$1.setOptions(__spreadValues(__spreadValues({
|
|
2532
|
+
renderer: getRenderer({
|
|
2533
|
+
imgLazyLoad: options.imgLazyLoad
|
|
2534
|
+
})
|
|
2535
|
+
}, markedOptions), options.markedOptions));
|
|
2367
2536
|
instance = marked$1;
|
|
2368
2537
|
}
|
|
2369
2538
|
function marked(src) {
|
|
@@ -2494,176 +2663,14 @@ class DataManager {
|
|
|
2494
2663
|
this.events.trigger("page-loaded", pageData);
|
|
2495
2664
|
}
|
|
2496
2665
|
}
|
|
2497
|
-
const en = {
|
|
2498
|
-
/* Editor */
|
|
2499
|
-
placeholder: "Leave a comment",
|
|
2500
|
-
noComment: "No Comment",
|
|
2501
|
-
send: "Send",
|
|
2502
|
-
save: "Save",
|
|
2503
|
-
nick: "Nickname",
|
|
2504
|
-
email: "Email",
|
|
2505
|
-
link: "Website",
|
|
2506
|
-
emoticon: "Emoji",
|
|
2507
|
-
preview: "Preview",
|
|
2508
|
-
uploadImage: "Upload Image",
|
|
2509
|
-
uploadFail: "Upload Failed",
|
|
2510
|
-
commentFail: "Failed to comment",
|
|
2511
|
-
restoredMsg: "Content has been restored",
|
|
2512
|
-
onlyAdminCanReply: "Only admin can reply",
|
|
2513
|
-
uploadLoginMsg: "Please fill in your name and email to upload",
|
|
2514
|
-
/* List */
|
|
2515
|
-
counter: "{count} Comments",
|
|
2516
|
-
sortLatest: "Latest",
|
|
2517
|
-
sortOldest: "Oldest",
|
|
2518
|
-
sortBest: "Best",
|
|
2519
|
-
sortAuthor: "Author",
|
|
2520
|
-
openComment: "Open Comment",
|
|
2521
|
-
closeComment: "Close Comment",
|
|
2522
|
-
listLoadFailMsg: "Failed to load comments",
|
|
2523
|
-
listRetry: "Retry",
|
|
2524
|
-
loadMore: "Load More",
|
|
2525
|
-
/* Comment */
|
|
2526
|
-
admin: "Admin",
|
|
2527
|
-
reply: "Reply",
|
|
2528
|
-
voteUp: "Up",
|
|
2529
|
-
voteDown: "Down",
|
|
2530
|
-
voteFail: "Vote Failed",
|
|
2531
|
-
readMore: "Read More",
|
|
2532
|
-
actionConfirm: "Confirm",
|
|
2533
|
-
collapse: "Collapse",
|
|
2534
|
-
collapsed: "Collapsed",
|
|
2535
|
-
collapsedMsg: "This comment has been collapsed",
|
|
2536
|
-
expand: "Expand",
|
|
2537
|
-
approved: "Approved",
|
|
2538
|
-
pending: "Pending",
|
|
2539
|
-
pendingMsg: "Pending, visible only to commenter.",
|
|
2540
|
-
edit: "Edit",
|
|
2541
|
-
editCancel: "Cancel Edit",
|
|
2542
|
-
delete: "Delete",
|
|
2543
|
-
deleteConfirm: "Confirm",
|
|
2544
|
-
pin: "Pin",
|
|
2545
|
-
unpin: "Unpin",
|
|
2546
|
-
/* Time */
|
|
2547
|
-
seconds: "seconds ago",
|
|
2548
|
-
minutes: "minutes ago",
|
|
2549
|
-
hours: "hours ago",
|
|
2550
|
-
days: "days ago",
|
|
2551
|
-
now: "just now",
|
|
2552
|
-
/* Checker */
|
|
2553
|
-
adminCheck: "Enter admin password:",
|
|
2554
|
-
captchaCheck: "Enter the CAPTCHA to continue:",
|
|
2555
|
-
confirm: "Confirm",
|
|
2556
|
-
cancel: "Cancel",
|
|
2557
|
-
/* Sidebar */
|
|
2558
|
-
msgCenter: "Messages",
|
|
2559
|
-
ctrlCenter: "Admin",
|
|
2560
|
-
emailVerified: "Email has been verified",
|
|
2561
|
-
/* General */
|
|
2562
|
-
frontend: "Frontend",
|
|
2563
|
-
backend: "Backend",
|
|
2564
|
-
loading: "Loading",
|
|
2565
|
-
loadFail: "Load Failed",
|
|
2566
|
-
editing: "Editing",
|
|
2567
|
-
editFail: "Edit Failed",
|
|
2568
|
-
deleting: "Deleting",
|
|
2569
|
-
deleteFail: "Delete Failed",
|
|
2570
|
-
reqGot: "Request got",
|
|
2571
|
-
reqAborted: "Request timed out or terminated unexpectedly",
|
|
2572
|
-
updateMsg: "Please update Artalk {name} to get the best experience!",
|
|
2573
|
-
currentVersion: "Current Version",
|
|
2574
|
-
ignore: "Ignore",
|
|
2575
|
-
open: "Open",
|
|
2576
|
-
openName: "Open {name}"
|
|
2577
|
-
};
|
|
2578
|
-
const zhCN = {
|
|
2579
|
-
/* Editor */
|
|
2580
|
-
placeholder: "键入内容...",
|
|
2581
|
-
noComment: "「此时无声胜有声」",
|
|
2582
|
-
send: "发送",
|
|
2583
|
-
save: "保存",
|
|
2584
|
-
nick: "昵称",
|
|
2585
|
-
email: "邮箱",
|
|
2586
|
-
link: "网址",
|
|
2587
|
-
emoticon: "表情",
|
|
2588
|
-
preview: "预览",
|
|
2589
|
-
uploadImage: "上传图片",
|
|
2590
|
-
uploadFail: "上传失败",
|
|
2591
|
-
commentFail: "评论失败",
|
|
2592
|
-
restoredMsg: "内容已自动恢复",
|
|
2593
|
-
onlyAdminCanReply: "仅管理员可评论",
|
|
2594
|
-
uploadLoginMsg: "填入你的名字邮箱才能上传哦",
|
|
2595
|
-
/* List */
|
|
2596
|
-
counter: "{count} 条评论",
|
|
2597
|
-
sortLatest: "最新",
|
|
2598
|
-
sortOldest: "最早",
|
|
2599
|
-
sortBest: "最热",
|
|
2600
|
-
sortAuthor: "作者",
|
|
2601
|
-
openComment: "打开评论",
|
|
2602
|
-
closeComment: "关闭评论",
|
|
2603
|
-
listLoadFailMsg: "无法获取评论列表数据",
|
|
2604
|
-
listRetry: "点击重新获取",
|
|
2605
|
-
loadMore: "加载更多",
|
|
2606
|
-
/* Comment */
|
|
2607
|
-
admin: "管理员",
|
|
2608
|
-
reply: "回复",
|
|
2609
|
-
voteUp: "赞同",
|
|
2610
|
-
voteDown: "反对",
|
|
2611
|
-
voteFail: "投票失败",
|
|
2612
|
-
readMore: "阅读更多",
|
|
2613
|
-
actionConfirm: "确认操作",
|
|
2614
|
-
collapse: "折叠",
|
|
2615
|
-
collapsed: "已折叠",
|
|
2616
|
-
collapsedMsg: "该评论已被系统或管理员折叠",
|
|
2617
|
-
expand: "展开",
|
|
2618
|
-
approved: "已审",
|
|
2619
|
-
pending: "待审",
|
|
2620
|
-
pendingMsg: "审核中,仅本人可见。",
|
|
2621
|
-
edit: "编辑",
|
|
2622
|
-
editCancel: "取消编辑",
|
|
2623
|
-
delete: "删除",
|
|
2624
|
-
deleteConfirm: "确认删除",
|
|
2625
|
-
pin: "置顶",
|
|
2626
|
-
unpin: "取消置顶",
|
|
2627
|
-
/* Time */
|
|
2628
|
-
seconds: "秒前",
|
|
2629
|
-
minutes: "分钟前",
|
|
2630
|
-
hours: "小时前",
|
|
2631
|
-
days: "天前",
|
|
2632
|
-
now: "刚刚",
|
|
2633
|
-
/* Checker */
|
|
2634
|
-
adminCheck: "键入密码来验证管理员身份:",
|
|
2635
|
-
captchaCheck: "键入验证码继续:",
|
|
2636
|
-
confirm: "确认",
|
|
2637
|
-
cancel: "取消",
|
|
2638
|
-
/* Sidebar */
|
|
2639
|
-
msgCenter: "通知中心",
|
|
2640
|
-
ctrlCenter: "控制中心",
|
|
2641
|
-
emailVerified: "邮箱已验证",
|
|
2642
|
-
/* General */
|
|
2643
|
-
frontend: "前端",
|
|
2644
|
-
backend: "后端",
|
|
2645
|
-
loading: "加载中",
|
|
2646
|
-
loadFail: "加载失败",
|
|
2647
|
-
editing: "修改中",
|
|
2648
|
-
editFail: "修改失败",
|
|
2649
|
-
deleting: "删除中",
|
|
2650
|
-
deleteFail: "删除失败",
|
|
2651
|
-
reqGot: "请求响应",
|
|
2652
|
-
reqAborted: "请求超时或意外终止",
|
|
2653
|
-
updateMsg: "请更新 Artalk {name} 以获得更好的体验!",
|
|
2654
|
-
currentVersion: "当前版本",
|
|
2655
|
-
ignore: "忽略",
|
|
2656
|
-
open: "打开",
|
|
2657
|
-
openName: "打开{name}"
|
|
2658
|
-
};
|
|
2659
|
-
const GLOBAL_LOCALES_KEY = "ArtalkI18n";
|
|
2660
2666
|
function createElement(htmlStr = "") {
|
|
2661
2667
|
const div = document.createElement("div");
|
|
2662
2668
|
div.innerHTML = htmlStr.trim();
|
|
2663
2669
|
return div.firstElementChild || div;
|
|
2664
2670
|
}
|
|
2665
2671
|
function getHeight(el) {
|
|
2666
|
-
|
|
2672
|
+
const num = parseFloat(getComputedStyle(el, null).height.replace("px", ""));
|
|
2673
|
+
return num || 0;
|
|
2667
2674
|
}
|
|
2668
2675
|
function htmlEncode(str) {
|
|
2669
2676
|
const temp = document.createElement("div");
|
|
@@ -2741,29 +2748,8 @@ function timeAgo(date, $t = (n) => n) {
|
|
|
2741
2748
|
return " - ";
|
|
2742
2749
|
}
|
|
2743
2750
|
}
|
|
2744
|
-
function onImagesLoaded($container, event) {
|
|
2745
|
-
if (!$container)
|
|
2746
|
-
return;
|
|
2747
|
-
const images = $container.getElementsByTagName("img");
|
|
2748
|
-
if (!images.length)
|
|
2749
|
-
return;
|
|
2750
|
-
let loaded = images.length;
|
|
2751
|
-
for (let i = 0; i < images.length; i++) {
|
|
2752
|
-
if (images[i].complete) {
|
|
2753
|
-
loaded--;
|
|
2754
|
-
} else {
|
|
2755
|
-
images[i].addEventListener("load", () => {
|
|
2756
|
-
loaded--;
|
|
2757
|
-
if (loaded === 0)
|
|
2758
|
-
event();
|
|
2759
|
-
});
|
|
2760
|
-
}
|
|
2761
|
-
if (loaded === 0)
|
|
2762
|
-
event();
|
|
2763
|
-
}
|
|
2764
|
-
}
|
|
2765
2751
|
function getGravatarURL(opts) {
|
|
2766
|
-
return `${opts.mirror.replace(/\/$/, "")}/${opts.
|
|
2752
|
+
return `${opts.mirror.replace(/\/$/, "")}/${opts.emailHash}?${opts.params.replace(/^\?/, "")}`;
|
|
2767
2753
|
}
|
|
2768
2754
|
function versionCompare(a, b) {
|
|
2769
2755
|
const pa = a.split(".");
|
|
@@ -2828,6 +2814,211 @@ function getURLBasedOnApi(opts) {
|
|
|
2828
2814
|
function getURLBasedOn(baseURL, path) {
|
|
2829
2815
|
return `${baseURL.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
|
|
2830
2816
|
}
|
|
2817
|
+
const en = {
|
|
2818
|
+
/* Editor */
|
|
2819
|
+
placeholder: "Leave a comment",
|
|
2820
|
+
noComment: "No Comment",
|
|
2821
|
+
send: "Send",
|
|
2822
|
+
signIn: "Sign in",
|
|
2823
|
+
signUp: "Sign up",
|
|
2824
|
+
save: "Save",
|
|
2825
|
+
nick: "Nickname",
|
|
2826
|
+
email: "Email",
|
|
2827
|
+
link: "Website",
|
|
2828
|
+
emoticon: "Emoji",
|
|
2829
|
+
preview: "Preview",
|
|
2830
|
+
uploadImage: "Upload Image",
|
|
2831
|
+
uploadFail: "Upload Failed",
|
|
2832
|
+
commentFail: "Failed to comment",
|
|
2833
|
+
restoredMsg: "Content has been restored",
|
|
2834
|
+
onlyAdminCanReply: "Only admin can reply",
|
|
2835
|
+
uploadLoginMsg: "Please fill in your name and email to upload",
|
|
2836
|
+
/* List */
|
|
2837
|
+
counter: "{count} Comments",
|
|
2838
|
+
sortLatest: "Latest",
|
|
2839
|
+
sortOldest: "Oldest",
|
|
2840
|
+
sortBest: "Best",
|
|
2841
|
+
sortAuthor: "Author",
|
|
2842
|
+
openComment: "Open Comment",
|
|
2843
|
+
closeComment: "Close Comment",
|
|
2844
|
+
listLoadFailMsg: "Failed to load comments",
|
|
2845
|
+
listRetry: "Retry",
|
|
2846
|
+
loadMore: "Load More",
|
|
2847
|
+
/* Comment */
|
|
2848
|
+
admin: "Admin",
|
|
2849
|
+
reply: "Reply",
|
|
2850
|
+
voteUp: "Up",
|
|
2851
|
+
voteDown: "Down",
|
|
2852
|
+
voteFail: "Vote Failed",
|
|
2853
|
+
readMore: "Read More",
|
|
2854
|
+
actionConfirm: "Confirm",
|
|
2855
|
+
collapse: "Collapse",
|
|
2856
|
+
collapsed: "Collapsed",
|
|
2857
|
+
collapsedMsg: "This comment has been collapsed",
|
|
2858
|
+
expand: "Expand",
|
|
2859
|
+
approved: "Approved",
|
|
2860
|
+
pending: "Pending",
|
|
2861
|
+
pendingMsg: "Pending, visible only to commenter.",
|
|
2862
|
+
edit: "Edit",
|
|
2863
|
+
editCancel: "Cancel Edit",
|
|
2864
|
+
delete: "Delete",
|
|
2865
|
+
deleteConfirm: "Confirm",
|
|
2866
|
+
pin: "Pin",
|
|
2867
|
+
unpin: "Unpin",
|
|
2868
|
+
/* Time */
|
|
2869
|
+
seconds: "seconds ago",
|
|
2870
|
+
minutes: "minutes ago",
|
|
2871
|
+
hours: "hours ago",
|
|
2872
|
+
days: "days ago",
|
|
2873
|
+
now: "just now",
|
|
2874
|
+
/* Checker */
|
|
2875
|
+
adminCheck: "Enter admin password:",
|
|
2876
|
+
captchaCheck: "Enter the CAPTCHA to continue:",
|
|
2877
|
+
confirm: "Confirm",
|
|
2878
|
+
cancel: "Cancel",
|
|
2879
|
+
/* Sidebar */
|
|
2880
|
+
msgCenter: "Messages",
|
|
2881
|
+
ctrlCenter: "Admin",
|
|
2882
|
+
/* Auth */
|
|
2883
|
+
noAccountPrompt: "Don't have an account?",
|
|
2884
|
+
haveAccountPrompt: "Already have an account?",
|
|
2885
|
+
forgetPassword: "Forget Password",
|
|
2886
|
+
resetPassword: "Reset Password",
|
|
2887
|
+
verificationCode: "Verification Code",
|
|
2888
|
+
verifySend: "Verify",
|
|
2889
|
+
verifyResend: "Resend",
|
|
2890
|
+
waitSeconds: "Wait {seconds}s",
|
|
2891
|
+
emailVerified: "Email has been verified",
|
|
2892
|
+
password: "Password",
|
|
2893
|
+
username: "Username",
|
|
2894
|
+
nextStep: "Next Step",
|
|
2895
|
+
skipNotVerify: "Skip, do not verify",
|
|
2896
|
+
logoutConfirm: "Are you sure to logout?",
|
|
2897
|
+
accountMergeNotice: "Your email has multiple accounts with different id.",
|
|
2898
|
+
accountMergeSelectOne: "Please select one you want to merge all the data into it.",
|
|
2899
|
+
accountMergeConfirm: "All data will be merged into one account, the id is {id}.",
|
|
2900
|
+
dismiss: "Dismiss",
|
|
2901
|
+
merge: "Merge",
|
|
2902
|
+
/* General */
|
|
2903
|
+
frontend: "Frontend",
|
|
2904
|
+
backend: "Backend",
|
|
2905
|
+
loading: "Loading",
|
|
2906
|
+
loadFail: "Load Failed",
|
|
2907
|
+
editing: "Editing",
|
|
2908
|
+
editFail: "Edit Failed",
|
|
2909
|
+
deleting: "Deleting",
|
|
2910
|
+
deleteFail: "Delete Failed",
|
|
2911
|
+
reqGot: "Request got",
|
|
2912
|
+
reqAborted: "Request timed out or terminated unexpectedly",
|
|
2913
|
+
updateMsg: "Please update Artalk {name} to get the best experience!",
|
|
2914
|
+
currentVersion: "Current Version",
|
|
2915
|
+
ignore: "Ignore",
|
|
2916
|
+
open: "Open",
|
|
2917
|
+
openName: "Open {name}"
|
|
2918
|
+
};
|
|
2919
|
+
const zhCN = {
|
|
2920
|
+
/* Editor */
|
|
2921
|
+
placeholder: "键入内容...",
|
|
2922
|
+
noComment: "「此时无声胜有声」",
|
|
2923
|
+
send: "发送",
|
|
2924
|
+
signIn: "登录",
|
|
2925
|
+
signUp: "注册",
|
|
2926
|
+
save: "保存",
|
|
2927
|
+
nick: "昵称",
|
|
2928
|
+
email: "邮箱",
|
|
2929
|
+
link: "网址",
|
|
2930
|
+
emoticon: "表情",
|
|
2931
|
+
preview: "预览",
|
|
2932
|
+
uploadImage: "上传图片",
|
|
2933
|
+
uploadFail: "上传失败",
|
|
2934
|
+
commentFail: "评论失败",
|
|
2935
|
+
restoredMsg: "内容已自动恢复",
|
|
2936
|
+
onlyAdminCanReply: "仅管理员可评论",
|
|
2937
|
+
uploadLoginMsg: "填入你的名字邮箱才能上传哦",
|
|
2938
|
+
/* List */
|
|
2939
|
+
counter: "{count} 条评论",
|
|
2940
|
+
sortLatest: "最新",
|
|
2941
|
+
sortOldest: "最早",
|
|
2942
|
+
sortBest: "最热",
|
|
2943
|
+
sortAuthor: "作者",
|
|
2944
|
+
openComment: "打开评论",
|
|
2945
|
+
closeComment: "关闭评论",
|
|
2946
|
+
listLoadFailMsg: "无法获取评论列表数据",
|
|
2947
|
+
listRetry: "点击重新获取",
|
|
2948
|
+
loadMore: "加载更多",
|
|
2949
|
+
/* Comment */
|
|
2950
|
+
admin: "管理员",
|
|
2951
|
+
reply: "回复",
|
|
2952
|
+
voteUp: "赞同",
|
|
2953
|
+
voteDown: "反对",
|
|
2954
|
+
voteFail: "投票失败",
|
|
2955
|
+
readMore: "阅读更多",
|
|
2956
|
+
actionConfirm: "确认操作",
|
|
2957
|
+
collapse: "折叠",
|
|
2958
|
+
collapsed: "已折叠",
|
|
2959
|
+
collapsedMsg: "该评论已被系统或管理员折叠",
|
|
2960
|
+
expand: "展开",
|
|
2961
|
+
approved: "已审",
|
|
2962
|
+
pending: "待审",
|
|
2963
|
+
pendingMsg: "审核中,仅本人可见。",
|
|
2964
|
+
edit: "编辑",
|
|
2965
|
+
editCancel: "取消编辑",
|
|
2966
|
+
delete: "删除",
|
|
2967
|
+
deleteConfirm: "确认删除",
|
|
2968
|
+
pin: "置顶",
|
|
2969
|
+
unpin: "取消置顶",
|
|
2970
|
+
/* Time */
|
|
2971
|
+
seconds: "秒前",
|
|
2972
|
+
minutes: "分钟前",
|
|
2973
|
+
hours: "小时前",
|
|
2974
|
+
days: "天前",
|
|
2975
|
+
now: "刚刚",
|
|
2976
|
+
/* Checker */
|
|
2977
|
+
adminCheck: "键入密码来验证管理员身份:",
|
|
2978
|
+
captchaCheck: "键入验证码继续:",
|
|
2979
|
+
confirm: "确认",
|
|
2980
|
+
cancel: "取消",
|
|
2981
|
+
/* Sidebar */
|
|
2982
|
+
msgCenter: "通知中心",
|
|
2983
|
+
ctrlCenter: "控制中心",
|
|
2984
|
+
/* Auth */
|
|
2985
|
+
noAccountPrompt: "没有账号?",
|
|
2986
|
+
haveAccountPrompt: "已有账号?",
|
|
2987
|
+
forgetPassword: "忘记密码",
|
|
2988
|
+
resetPassword: "重置密码",
|
|
2989
|
+
verificationCode: "验证码",
|
|
2990
|
+
verifySend: "发送验证码",
|
|
2991
|
+
verifyResend: "重新发送",
|
|
2992
|
+
waitSeconds: "等待 {seconds}秒",
|
|
2993
|
+
emailVerified: "邮箱已验证",
|
|
2994
|
+
password: "密码",
|
|
2995
|
+
username: "用户名",
|
|
2996
|
+
nextStep: "下一步",
|
|
2997
|
+
skipNotVerify: "跳过,不验证",
|
|
2998
|
+
logoutConfirm: "确定要退出登录吗?",
|
|
2999
|
+
accountMergeNotice: "您的电子邮件下有多个不同 ID 的账户。",
|
|
3000
|
+
accountMergeSelectOne: "请选择将所有数据合并到其中的一个。",
|
|
3001
|
+
accountMergeConfirm: "所有数据将合并到 ID 为 {id} 的账户中。",
|
|
3002
|
+
dismiss: "忽略",
|
|
3003
|
+
merge: "合并",
|
|
3004
|
+
/* General */
|
|
3005
|
+
frontend: "前端",
|
|
3006
|
+
backend: "后端",
|
|
3007
|
+
loading: "加载中",
|
|
3008
|
+
loadFail: "加载失败",
|
|
3009
|
+
editing: "修改中",
|
|
3010
|
+
editFail: "修改失败",
|
|
3011
|
+
deleting: "删除中",
|
|
3012
|
+
deleteFail: "删除失败",
|
|
3013
|
+
reqGot: "请求响应",
|
|
3014
|
+
reqAborted: "请求超时或意外终止",
|
|
3015
|
+
updateMsg: "请更新 Artalk {name} 以获得更好的体验!",
|
|
3016
|
+
currentVersion: "当前版本",
|
|
3017
|
+
ignore: "忽略",
|
|
3018
|
+
open: "打开",
|
|
3019
|
+
openName: "打开{name}"
|
|
3020
|
+
};
|
|
3021
|
+
const GLOBAL_LOCALES_KEY = "ArtalkI18n";
|
|
2831
3022
|
const internal = {
|
|
2832
3023
|
en,
|
|
2833
3024
|
"en-US": en,
|
|
@@ -2911,11 +3102,12 @@ const defaults = {
|
|
|
2911
3102
|
uaBadge: true,
|
|
2912
3103
|
listSort: true,
|
|
2913
3104
|
preview: true,
|
|
2914
|
-
countEl: "
|
|
2915
|
-
pvEl: "
|
|
3105
|
+
countEl: ".artalk-comment-count",
|
|
3106
|
+
pvEl: ".artalk-pv-count",
|
|
3107
|
+
statPageKeyAttr: "data-page-key",
|
|
2916
3108
|
gravatar: {
|
|
2917
|
-
mirror: "https://
|
|
2918
|
-
params: "d=mp&s=240"
|
|
3109
|
+
mirror: "https://www.gravatar.com/avatar/",
|
|
3110
|
+
params: "sha256=1&d=mp&s=240"
|
|
2919
3111
|
},
|
|
2920
3112
|
pagination: {
|
|
2921
3113
|
pageSize: 20,
|
|
@@ -2961,16 +3153,20 @@ function handelCustomConf(customConf, full = false) {
|
|
|
2961
3153
|
return conf;
|
|
2962
3154
|
}
|
|
2963
3155
|
function handleConfFormServer(conf) {
|
|
2964
|
-
const
|
|
3156
|
+
const ExcludedKeys = [
|
|
2965
3157
|
"el",
|
|
2966
3158
|
"pageKey",
|
|
2967
3159
|
"pageTitle",
|
|
2968
3160
|
"server",
|
|
2969
3161
|
"site",
|
|
2970
|
-
"
|
|
3162
|
+
"pvEl",
|
|
3163
|
+
"countEl",
|
|
3164
|
+
"statPageKeyAttr"
|
|
2971
3165
|
];
|
|
2972
3166
|
Object.keys(conf).forEach((k) => {
|
|
2973
|
-
if (
|
|
3167
|
+
if (ExcludedKeys.includes(k))
|
|
3168
|
+
delete conf[k];
|
|
3169
|
+
if (k === "darkMode" && conf[k] !== "auto")
|
|
2974
3170
|
delete conf[k];
|
|
2975
3171
|
});
|
|
2976
3172
|
if (conf.emoticons && typeof conf.emoticons === "string") {
|
|
@@ -3147,50 +3343,6 @@ class Context {
|
|
|
3147
3343
|
watchConf(this, keys, effect);
|
|
3148
3344
|
}
|
|
3149
3345
|
}
|
|
3150
|
-
class Dialog {
|
|
3151
|
-
constructor(contentEl) {
|
|
3152
|
-
__publicField(this, "$el");
|
|
3153
|
-
__publicField(this, "$content");
|
|
3154
|
-
__publicField(this, "$actions");
|
|
3155
|
-
this.$el = createElement(
|
|
3156
|
-
`<div class="atk-layer-dialog-wrap">
|
|
3157
|
-
<div class="atk-layer-dialog">
|
|
3158
|
-
<div class="atk-layer-dialog-content"></div>
|
|
3159
|
-
<div class="atk-layer-dialog-actions"></div>
|
|
3160
|
-
</div>
|
|
3161
|
-
</div>`
|
|
3162
|
-
);
|
|
3163
|
-
this.$actions = this.$el.querySelector(".atk-layer-dialog-actions");
|
|
3164
|
-
this.$content = this.$el.querySelector(".atk-layer-dialog-content");
|
|
3165
|
-
this.$content.appendChild(contentEl);
|
|
3166
|
-
}
|
|
3167
|
-
/** 按钮 · 确定 */
|
|
3168
|
-
setYes(handler) {
|
|
3169
|
-
const btn = createElement(
|
|
3170
|
-
`<button data-action="confirm">${t("confirm")}</button>`
|
|
3171
|
-
);
|
|
3172
|
-
btn.onclick = this.onBtnClick(handler);
|
|
3173
|
-
this.$actions.appendChild(btn);
|
|
3174
|
-
return this;
|
|
3175
|
-
}
|
|
3176
|
-
/** 按钮 · 取消 */
|
|
3177
|
-
setNo(handler) {
|
|
3178
|
-
const btn = createElement(
|
|
3179
|
-
`<button data-action="cancel">${t("cancel")}</button>`
|
|
3180
|
-
);
|
|
3181
|
-
btn.onclick = this.onBtnClick(handler);
|
|
3182
|
-
this.$actions.appendChild(btn);
|
|
3183
|
-
return this;
|
|
3184
|
-
}
|
|
3185
|
-
onBtnClick(handler) {
|
|
3186
|
-
return (evt) => {
|
|
3187
|
-
const re = handler(evt.currentTarget, this);
|
|
3188
|
-
if (re === void 0 || re === true) {
|
|
3189
|
-
this.$el.remove();
|
|
3190
|
-
}
|
|
3191
|
-
};
|
|
3192
|
-
}
|
|
3193
|
-
}
|
|
3194
3346
|
function showLoading(parentElem, conf) {
|
|
3195
3347
|
let $loading = parentElem.querySelector(":scope > .atk-loading");
|
|
3196
3348
|
if (!$loading) {
|
|
@@ -3279,8 +3431,6 @@ function playFadeAnim(elem, after, type = "in") {
|
|
|
3279
3431
|
const onAnimEnded = () => {
|
|
3280
3432
|
elem.classList.remove(`atk-fade-${type}`);
|
|
3281
3433
|
elem.removeEventListener("animationend", onAnimEnded);
|
|
3282
|
-
if (after)
|
|
3283
|
-
after();
|
|
3284
3434
|
};
|
|
3285
3435
|
elem.addEventListener("animationend", onAnimEnded);
|
|
3286
3436
|
}
|
|
@@ -3438,6 +3588,50 @@ const AdminChecker = {
|
|
|
3438
3588
|
onError(checker, err, inputVal, formEl) {
|
|
3439
3589
|
}
|
|
3440
3590
|
};
|
|
3591
|
+
class Dialog {
|
|
3592
|
+
constructor(contentEl) {
|
|
3593
|
+
__publicField(this, "$el");
|
|
3594
|
+
__publicField(this, "$content");
|
|
3595
|
+
__publicField(this, "$actions");
|
|
3596
|
+
this.$el = createElement(
|
|
3597
|
+
`<div class="atk-layer-dialog-wrap">
|
|
3598
|
+
<div class="atk-layer-dialog">
|
|
3599
|
+
<div class="atk-layer-dialog-content"></div>
|
|
3600
|
+
<div class="atk-layer-dialog-actions"></div>
|
|
3601
|
+
</div>
|
|
3602
|
+
</div>`
|
|
3603
|
+
);
|
|
3604
|
+
this.$actions = this.$el.querySelector(".atk-layer-dialog-actions");
|
|
3605
|
+
this.$content = this.$el.querySelector(".atk-layer-dialog-content");
|
|
3606
|
+
this.$content.appendChild(contentEl);
|
|
3607
|
+
}
|
|
3608
|
+
/** 按钮 · 确定 */
|
|
3609
|
+
setYes(handler) {
|
|
3610
|
+
const btn = createElement(
|
|
3611
|
+
`<button data-action="confirm">${t("confirm")}</button>`
|
|
3612
|
+
);
|
|
3613
|
+
btn.onclick = this.onBtnClick(handler);
|
|
3614
|
+
this.$actions.appendChild(btn);
|
|
3615
|
+
return this;
|
|
3616
|
+
}
|
|
3617
|
+
/** 按钮 · 取消 */
|
|
3618
|
+
setNo(handler) {
|
|
3619
|
+
const btn = createElement(
|
|
3620
|
+
`<button data-action="cancel">${t("cancel")}</button>`
|
|
3621
|
+
);
|
|
3622
|
+
btn.onclick = this.onBtnClick(handler);
|
|
3623
|
+
this.$actions.appendChild(btn);
|
|
3624
|
+
return this;
|
|
3625
|
+
}
|
|
3626
|
+
onBtnClick(handler) {
|
|
3627
|
+
return (evt) => {
|
|
3628
|
+
const re = handler(evt.currentTarget, this);
|
|
3629
|
+
if (re === void 0 || re === true) {
|
|
3630
|
+
this.$el.remove();
|
|
3631
|
+
}
|
|
3632
|
+
};
|
|
3633
|
+
}
|
|
3634
|
+
}
|
|
3441
3635
|
function wrapPromise(fn) {
|
|
3442
3636
|
return (payload) => new Promise((resolve, reject) => {
|
|
3443
3637
|
const cancelFn = payload.onCancel;
|
|
@@ -3831,10 +4025,10 @@ class SidebarLayer extends Component {
|
|
|
3831
4025
|
} else {
|
|
3832
4026
|
const $iframe = this.$iframe;
|
|
3833
4027
|
const iFrameSrc = $iframe.src;
|
|
3834
|
-
if (this.
|
|
4028
|
+
if (this.getDarkMode() !== iFrameSrc.includes("&darkMode=1")) {
|
|
3835
4029
|
this.iframeLoad(
|
|
3836
4030
|
$iframe,
|
|
3837
|
-
this.
|
|
4031
|
+
this.getDarkMode() ? iFrameSrc.concat("&darkMode=1") : iFrameSrc.replace("&darkMode=1", "")
|
|
3838
4032
|
);
|
|
3839
4033
|
}
|
|
3840
4034
|
}
|
|
@@ -3904,12 +4098,15 @@ class SidebarLayer extends Component {
|
|
|
3904
4098
|
};
|
|
3905
4099
|
if (view)
|
|
3906
4100
|
query.view = view;
|
|
3907
|
-
if (this.
|
|
4101
|
+
if (this.getDarkMode())
|
|
3908
4102
|
query.darkMode = "1";
|
|
3909
4103
|
const urlParams = new URLSearchParams(query);
|
|
3910
4104
|
this.iframeLoad($iframe, `${baseURL}?${urlParams.toString()}`);
|
|
3911
4105
|
return $iframe;
|
|
3912
4106
|
}
|
|
4107
|
+
getDarkMode() {
|
|
4108
|
+
return this.conf.darkMode === "auto" ? window.matchMedia("(prefers-color-scheme: dark)").matches : this.conf.darkMode;
|
|
4109
|
+
}
|
|
3913
4110
|
iframeLoad($iframe, src) {
|
|
3914
4111
|
$iframe.src = src;
|
|
3915
4112
|
showLoading(this.$iframeWrap);
|
|
@@ -4244,38 +4441,45 @@ function Detect(userAgent) {
|
|
|
4244
4441
|
return dest;
|
|
4245
4442
|
}
|
|
4246
4443
|
function check(conf, rules) {
|
|
4247
|
-
rules.forEach(({ el, max
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
el,
|
|
4254
|
-
maxHeight,
|
|
4255
|
-
postBtnClick: conf.postExpandBtnClick
|
|
4256
|
-
});
|
|
4257
|
-
else
|
|
4258
|
-
applyScrollableHeightLimit({ el, maxHeight });
|
|
4259
|
-
};
|
|
4444
|
+
rules.forEach(({ el, max, imgCheck }) => {
|
|
4445
|
+
if (!el)
|
|
4446
|
+
return;
|
|
4447
|
+
if (imgCheck)
|
|
4448
|
+
el.style.maxHeight = `${max + 1}px`;
|
|
4449
|
+
let lock = false;
|
|
4260
4450
|
const _check = () => {
|
|
4261
|
-
if (
|
|
4262
|
-
|
|
4451
|
+
if (lock)
|
|
4452
|
+
return;
|
|
4453
|
+
if (getHeight(el) <= max)
|
|
4454
|
+
return;
|
|
4455
|
+
const afterExpandBtnClick = () => {
|
|
4456
|
+
var _a;
|
|
4457
|
+
lock = true;
|
|
4458
|
+
(_a = conf.afterExpandBtnClick) == null ? void 0 : _a.call(conf);
|
|
4459
|
+
};
|
|
4460
|
+
!conf.scrollable ? applyHeightLimit({ el, max, afterExpandBtnClick }) : applyScrollableHeightLimit({ el, max });
|
|
4263
4461
|
};
|
|
4264
4462
|
_check();
|
|
4265
|
-
if (
|
|
4266
|
-
|
|
4463
|
+
if (imgCheck) {
|
|
4464
|
+
const imgs = el.querySelectorAll(".atk-content img");
|
|
4465
|
+
if (imgs.length === 0)
|
|
4466
|
+
el.style.maxHeight = "";
|
|
4467
|
+
imgs.forEach((img) => {
|
|
4468
|
+
img.onload = () => _check();
|
|
4469
|
+
});
|
|
4470
|
+
}
|
|
4267
4471
|
});
|
|
4268
4472
|
}
|
|
4269
4473
|
const HEIGHT_LIMIT_CSS = "atk-height-limit";
|
|
4270
4474
|
function applyHeightLimit(obj) {
|
|
4271
4475
|
if (!obj.el)
|
|
4272
4476
|
return;
|
|
4273
|
-
if (!obj.
|
|
4477
|
+
if (!obj.max)
|
|
4274
4478
|
return;
|
|
4275
4479
|
if (obj.el.classList.contains(HEIGHT_LIMIT_CSS))
|
|
4276
4480
|
return;
|
|
4277
4481
|
obj.el.classList.add(HEIGHT_LIMIT_CSS);
|
|
4278
|
-
obj.el.style.height = `${obj.
|
|
4482
|
+
obj.el.style.height = `${obj.max}px`;
|
|
4279
4483
|
obj.el.style.overflow = "hidden";
|
|
4280
4484
|
const $expandBtn = createElement(
|
|
4281
4485
|
`<div class="atk-height-limit-btn">${t("readMore")}</span>`
|
|
@@ -4283,8 +4487,8 @@ function applyHeightLimit(obj) {
|
|
|
4283
4487
|
$expandBtn.onclick = (e) => {
|
|
4284
4488
|
e.stopPropagation();
|
|
4285
4489
|
disposeHeightLimit(obj.el);
|
|
4286
|
-
if (obj.
|
|
4287
|
-
obj.
|
|
4490
|
+
if (obj.afterExpandBtnClick)
|
|
4491
|
+
obj.afterExpandBtnClick(e);
|
|
4288
4492
|
};
|
|
4289
4493
|
obj.el.append($expandBtn);
|
|
4290
4494
|
}
|
|
@@ -4299,16 +4503,17 @@ function disposeHeightLimit($el) {
|
|
|
4299
4503
|
e.remove();
|
|
4300
4504
|
});
|
|
4301
4505
|
$el.style.height = "";
|
|
4506
|
+
$el.style.maxHeight = "";
|
|
4302
4507
|
$el.style.overflow = "";
|
|
4303
4508
|
}
|
|
4304
4509
|
const HEIGHT_LIMIT_SCROLL_CSS = "atk-height-limit-scroll";
|
|
4305
|
-
function applyScrollableHeightLimit(
|
|
4306
|
-
if (!
|
|
4510
|
+
function applyScrollableHeightLimit(opt) {
|
|
4511
|
+
if (!opt.el)
|
|
4307
4512
|
return;
|
|
4308
|
-
if (
|
|
4513
|
+
if (opt.el.classList.contains(HEIGHT_LIMIT_SCROLL_CSS))
|
|
4309
4514
|
return;
|
|
4310
|
-
|
|
4311
|
-
|
|
4515
|
+
opt.el.classList.add(HEIGHT_LIMIT_SCROLL_CSS);
|
|
4516
|
+
opt.el.style.height = `${opt.max}px`;
|
|
4312
4517
|
}
|
|
4313
4518
|
const CommentHTML = '<div class="atk-comment-wrap">\n <div class="atk-comment">\n <div class="atk-avatar"></div>\n <div class="atk-main">\n <div class="atk-header">\n <span class="atk-item atk-nick"></span>\n <span class="atk-badge-wrap"></span>\n <span class="atk-item atk-date"></span>\n </div>\n <div class="atk-body">\n <div class="atk-content"></div>\n </div>\n <div class="atk-footer">\n <div class="atk-actions"></div>\n </div>\n </div>\n </div>\n</div>\n';
|
|
4314
4519
|
function renderAvatar(r) {
|
|
@@ -4772,7 +4977,7 @@ class Render {
|
|
|
4772
4977
|
const childrenMaxH = conf.children;
|
|
4773
4978
|
check(
|
|
4774
4979
|
{
|
|
4775
|
-
|
|
4980
|
+
afterExpandBtnClick: () => {
|
|
4776
4981
|
const children = this.comment.getChildren();
|
|
4777
4982
|
if (children.length === 1)
|
|
4778
4983
|
disposeHeightLimit(children[0].getRender().$content);
|
|
@@ -4781,10 +4986,10 @@ class Render {
|
|
|
4781
4986
|
},
|
|
4782
4987
|
[
|
|
4783
4988
|
// 评论内容限高
|
|
4784
|
-
{ el: this.$content, max: contentMaxH,
|
|
4785
|
-
{ el: this.$replyTo, max: contentMaxH,
|
|
4989
|
+
{ el: this.$content, max: contentMaxH, imgCheck: true },
|
|
4990
|
+
{ el: this.$replyTo, max: contentMaxH, imgCheck: true },
|
|
4786
4991
|
// 子评论区域限高(仅嵌套模式)
|
|
4787
|
-
{ el: this.$childrenWrap, max: childrenMaxH,
|
|
4992
|
+
{ el: this.$childrenWrap, max: childrenMaxH, imgCheck: false }
|
|
4788
4993
|
]
|
|
4789
4994
|
);
|
|
4790
4995
|
}
|
|
@@ -4873,7 +5078,7 @@ class CommentActions {
|
|
|
4873
5078
|
(_b = this.comment.getRender().voteBtnDown) == null ? void 0 : _b.updateText();
|
|
4874
5079
|
}).catch((err) => {
|
|
4875
5080
|
actionBtn == null ? void 0 : actionBtn.setError(t("voteFail"));
|
|
4876
|
-
console.
|
|
5081
|
+
console.error(err);
|
|
4877
5082
|
});
|
|
4878
5083
|
}
|
|
4879
5084
|
/** 管理员 - 评论状态修改 */
|
|
@@ -5057,7 +5262,7 @@ class CommentNode {
|
|
|
5057
5262
|
return getGravatarURL({
|
|
5058
5263
|
mirror: this.opts.gravatar.mirror,
|
|
5059
5264
|
params: this.opts.gravatar.params,
|
|
5060
|
-
|
|
5265
|
+
emailHash: this.data.email_encrypted
|
|
5061
5266
|
});
|
|
5062
5267
|
}
|
|
5063
5268
|
/** 获取评论 markdown 解析后的内容 */
|
|
@@ -5752,7 +5957,7 @@ const services = {
|
|
|
5752
5957
|
}
|
|
5753
5958
|
};
|
|
5754
5959
|
const PvCountWidget = (ctx) => {
|
|
5755
|
-
ctx.watchConf(["site", "pageKey", "pageTitle", "countEl", "pvEl"], (conf) => {
|
|
5960
|
+
ctx.watchConf(["site", "pageKey", "pageTitle", "countEl", "pvEl", "statPageKeyAttr"], (conf) => {
|
|
5756
5961
|
initCountWidget({
|
|
5757
5962
|
getApi: () => ctx.getApi(),
|
|
5758
5963
|
siteName: conf.site,
|
|
@@ -5760,78 +5965,85 @@ const PvCountWidget = (ctx) => {
|
|
|
5760
5965
|
pageTitle: conf.pageTitle,
|
|
5761
5966
|
countEl: conf.countEl,
|
|
5762
5967
|
pvEl: conf.pvEl,
|
|
5968
|
+
pageKeyAttr: conf.statPageKeyAttr,
|
|
5763
5969
|
pvAdd: typeof ctx.conf.pvAdd === "boolean" ? ctx.conf.pvAdd : true
|
|
5764
5970
|
});
|
|
5765
5971
|
});
|
|
5766
5972
|
};
|
|
5767
5973
|
function initCountWidget(opt) {
|
|
5768
5974
|
return __async(this, null, function* () {
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5975
|
+
yield loadCommentCount(opt);
|
|
5976
|
+
const cacheData = yield incrementPvCount(opt);
|
|
5977
|
+
yield loadPvCount(opt, cacheData);
|
|
5978
|
+
});
|
|
5979
|
+
}
|
|
5980
|
+
function incrementPvCount(opt) {
|
|
5981
|
+
return __async(this, null, function* () {
|
|
5982
|
+
if (!opt.pvAdd || !opt.pageKey)
|
|
5983
|
+
return void 0;
|
|
5984
|
+
const pvCount = (yield opt.getApi().pages.logPv({
|
|
5985
|
+
page_key: opt.pageKey,
|
|
5986
|
+
page_title: opt.pageTitle,
|
|
5987
|
+
site_name: opt.siteName
|
|
5988
|
+
})).data.pv;
|
|
5989
|
+
return {
|
|
5990
|
+
[opt.pageKey]: pvCount
|
|
5991
|
+
};
|
|
5992
|
+
});
|
|
5993
|
+
}
|
|
5994
|
+
function loadCommentCount(opt) {
|
|
5995
|
+
return __async(this, null, function* () {
|
|
5996
|
+
yield loadStatCount({ opt, query: "page_comment", containers: [opt.countEl, "#ArtalkCount"] });
|
|
5997
|
+
});
|
|
5998
|
+
}
|
|
5999
|
+
function loadPvCount(opt, cache) {
|
|
6000
|
+
return __async(this, null, function* () {
|
|
6001
|
+
yield loadStatCount({ opt, query: "page_pv", containers: [opt.pvEl, "#ArtalkPv"], cache });
|
|
5787
6002
|
});
|
|
5788
6003
|
}
|
|
5789
|
-
function
|
|
6004
|
+
function loadStatCount(args) {
|
|
5790
6005
|
return __async(this, null, function* () {
|
|
5791
|
-
|
|
5792
|
-
let
|
|
5793
|
-
|
|
5794
|
-
|
|
6006
|
+
const { opt } = args;
|
|
6007
|
+
let cache = args.cache || {};
|
|
6008
|
+
const els = retrieveElements(args.containers);
|
|
6009
|
+
const pageKeys = getPageKeys(els, opt.pageKeyAttr, opt.pageKey, cache);
|
|
6010
|
+
if (pageKeys.length > 0) {
|
|
5795
6011
|
const res = (yield opt.getApi().stats.getStats(args.query, {
|
|
5796
|
-
page_keys:
|
|
6012
|
+
page_keys: pageKeys.join(","),
|
|
5797
6013
|
site_name: opt.siteName
|
|
5798
6014
|
})).data.data;
|
|
5799
|
-
|
|
6015
|
+
cache = __spreadValues(__spreadValues({}, cache), res);
|
|
5800
6016
|
}
|
|
5801
|
-
|
|
5802
|
-
applyCountData(args.numEl, data, defaultCount);
|
|
6017
|
+
updateElementsText(els, cache, opt.pageKey);
|
|
5803
6018
|
});
|
|
5804
6019
|
}
|
|
5805
|
-
function
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
el.innerHTML = `${count}`;
|
|
6020
|
+
function retrieveElements(containers) {
|
|
6021
|
+
const els = /* @__PURE__ */ new Set();
|
|
6022
|
+
new Set(containers).forEach((selector) => {
|
|
6023
|
+
document.querySelectorAll(selector).forEach((el) => els.add(el));
|
|
5810
6024
|
});
|
|
6025
|
+
return els;
|
|
5811
6026
|
}
|
|
5812
|
-
function
|
|
5813
|
-
const
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
const $openSidebar = createElement(
|
|
5823
|
-
`<span atk-only-admin-show> | <span style="cursor:pointer;">${t("openName", { name: t("ctrlCenter") })}</span></span>`
|
|
5824
|
-
);
|
|
5825
|
-
errEl.appendChild($openSidebar);
|
|
5826
|
-
$openSidebar.onclick = () => opts.onOpenSidebar && opts.onOpenSidebar();
|
|
5827
|
-
}
|
|
5828
|
-
setError(opts.$err, errEl);
|
|
6027
|
+
function getPageKeys(els, pageKeyAttr, pageKey, cache) {
|
|
6028
|
+
const pageKeys = Array.from(els).map((el) => el.getAttribute(pageKeyAttr) || pageKey).filter((key) => key && typeof cache[key] !== "number");
|
|
6029
|
+
return [...new Set(pageKeys)];
|
|
6030
|
+
}
|
|
6031
|
+
function updateElementsText(els, data, defaultPageKey) {
|
|
6032
|
+
els.forEach((el) => {
|
|
6033
|
+
const pageKey = el.getAttribute("data-page-key");
|
|
6034
|
+
const count = pageKey && data[pageKey] || defaultPageKey && data[defaultPageKey] || 0;
|
|
6035
|
+
el.innerText = `${Number(count)}`;
|
|
6036
|
+
});
|
|
5829
6037
|
}
|
|
5830
6038
|
const Markdown = (ctx) => {
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
6039
|
+
ctx.watchConf(["imgLazyLoad", "markedOptions"], (conf) => {
|
|
6040
|
+
initMarked({
|
|
6041
|
+
markedOptions: ctx.getConf().markedOptions,
|
|
6042
|
+
imgLazyLoad: ctx.getConf().imgLazyLoad
|
|
6043
|
+
});
|
|
6044
|
+
});
|
|
6045
|
+
ctx.watchConf(["markedReplacers"], (conf) => {
|
|
6046
|
+
conf.markedReplacers && setReplacers(conf.markedReplacers);
|
|
5835
6047
|
});
|
|
5836
6048
|
};
|
|
5837
6049
|
const LocalStorageKey = "ArtalkContent";
|
|
@@ -7068,7 +7280,7 @@ const GotoFocus = (ctx) => {
|
|
|
7068
7280
|
comment.focus();
|
|
7069
7281
|
}));
|
|
7070
7282
|
};
|
|
7071
|
-
const version = "2.8.
|
|
7283
|
+
const version = "2.8.7";
|
|
7072
7284
|
const Copyright = (ctx) => {
|
|
7073
7285
|
ctx.on("mounted", () => {
|
|
7074
7286
|
const list = ctx.get("list");
|
|
@@ -7173,8 +7385,7 @@ function renderDropdown(conf) {
|
|
|
7173
7385
|
};
|
|
7174
7386
|
const $dropdown = createElement(`<ul class="atk-dropdown atk-fade-in"></ul>`);
|
|
7175
7387
|
dropdownList.forEach((item, i) => {
|
|
7176
|
-
const name = item
|
|
7177
|
-
const action = item[1];
|
|
7388
|
+
const [name, action] = item;
|
|
7178
7389
|
const $item = createElement(`<li class="atk-dropdown-item"><span></span></li>`);
|
|
7179
7390
|
const $link = $item.querySelector("span");
|
|
7180
7391
|
$link.innerText = name;
|
|
@@ -7209,6 +7420,24 @@ const TimeTicking = (ctx) => {
|
|
|
7209
7420
|
timer && window.clearInterval(timer);
|
|
7210
7421
|
});
|
|
7211
7422
|
};
|
|
7423
|
+
function showErrorDialog(opts) {
|
|
7424
|
+
const errEl = createElement(`<span><span class="error-message"></span><br/><br/></span>`);
|
|
7425
|
+
errEl.querySelector(".error-message").innerText = `${t("listLoadFailMsg")}
|
|
7426
|
+
${opts.errMsg}`;
|
|
7427
|
+
if (opts.retryFn) {
|
|
7428
|
+
const $retryBtn = createElement(`<span style="cursor:pointer;">${t("listRetry")}</span>`);
|
|
7429
|
+
$retryBtn.onclick = () => opts.retryFn && opts.retryFn();
|
|
7430
|
+
errEl.appendChild($retryBtn);
|
|
7431
|
+
}
|
|
7432
|
+
if (opts.onOpenSidebar) {
|
|
7433
|
+
const $openSidebar = createElement(
|
|
7434
|
+
`<span atk-only-admin-show> | <span style="cursor:pointer;">${t("openName", { name: t("ctrlCenter") })}</span></span>`
|
|
7435
|
+
);
|
|
7436
|
+
errEl.appendChild($openSidebar);
|
|
7437
|
+
$openSidebar.onclick = () => opts.onOpenSidebar && opts.onOpenSidebar();
|
|
7438
|
+
}
|
|
7439
|
+
setError(opts.$err, errEl);
|
|
7440
|
+
}
|
|
7212
7441
|
const ErrorDialog = (ctx) => {
|
|
7213
7442
|
ctx.on("list-fetch", () => {
|
|
7214
7443
|
const list = ctx.get("list");
|
|
@@ -7473,16 +7702,16 @@ const DefaultPlugins = [
|
|
|
7473
7702
|
VersionCheck,
|
|
7474
7703
|
DarkMode
|
|
7475
7704
|
];
|
|
7476
|
-
const GlobalPlugins = [...DefaultPlugins];
|
|
7705
|
+
const GlobalPlugins = /* @__PURE__ */ new Set([...DefaultPlugins]);
|
|
7477
7706
|
function load(ctx) {
|
|
7478
7707
|
return __async(this, null, function* () {
|
|
7479
7708
|
var _a;
|
|
7480
|
-
const loadedPlugins =
|
|
7709
|
+
const loadedPlugins = /* @__PURE__ */ new Set();
|
|
7481
7710
|
const loadPlugins = (plugins) => {
|
|
7482
7711
|
plugins.forEach((plugin) => {
|
|
7483
|
-
if (typeof plugin === "function" && !loadedPlugins.
|
|
7712
|
+
if (typeof plugin === "function" && !loadedPlugins.has(plugin)) {
|
|
7484
7713
|
plugin(ctx);
|
|
7485
|
-
loadedPlugins.
|
|
7714
|
+
loadedPlugins.add(plugin);
|
|
7486
7715
|
}
|
|
7487
7716
|
});
|
|
7488
7717
|
};
|
|
@@ -7518,8 +7747,9 @@ function load(ctx) {
|
|
|
7518
7747
|
}
|
|
7519
7748
|
function loadNetworkPlugins(scripts, apiBase) {
|
|
7520
7749
|
return __async(this, null, function* () {
|
|
7750
|
+
const networkPlugins = /* @__PURE__ */ new Set();
|
|
7521
7751
|
if (!scripts || !Array.isArray(scripts))
|
|
7522
|
-
return
|
|
7752
|
+
return networkPlugins;
|
|
7523
7753
|
const tasks = [];
|
|
7524
7754
|
scripts.forEach((url) => {
|
|
7525
7755
|
if (!/^(http|https):\/\//.test(url))
|
|
@@ -7539,7 +7769,11 @@ function loadNetworkPlugins(scripts, apiBase) {
|
|
|
7539
7769
|
);
|
|
7540
7770
|
});
|
|
7541
7771
|
yield Promise.all(tasks);
|
|
7542
|
-
|
|
7772
|
+
Object.values(window.ArtalkPlugins || {}).forEach((plugin) => {
|
|
7773
|
+
if (typeof plugin === "function")
|
|
7774
|
+
networkPlugins.add(plugin);
|
|
7775
|
+
});
|
|
7776
|
+
return networkPlugins;
|
|
7543
7777
|
});
|
|
7544
7778
|
}
|
|
7545
7779
|
function onLoadErr(ctx, err) {
|
|
@@ -7625,9 +7859,7 @@ class Artalk {
|
|
|
7625
7859
|
}
|
|
7626
7860
|
/** Use plugin, the plugin will be used when Artalk.init */
|
|
7627
7861
|
static use(plugin) {
|
|
7628
|
-
|
|
7629
|
-
return;
|
|
7630
|
-
GlobalPlugins.push(plugin);
|
|
7862
|
+
GlobalPlugins.add(plugin);
|
|
7631
7863
|
}
|
|
7632
7864
|
/** Load count widget */
|
|
7633
7865
|
static loadCountWidget(c) {
|
|
@@ -7637,6 +7869,7 @@ class Artalk {
|
|
|
7637
7869
|
siteName: conf.site,
|
|
7638
7870
|
countEl: conf.countEl,
|
|
7639
7871
|
pvEl: conf.pvEl,
|
|
7872
|
+
pageKeyAttr: conf.statPageKeyAttr,
|
|
7640
7873
|
pvAdd: false
|
|
7641
7874
|
});
|
|
7642
7875
|
}
|