artalk 2.8.0 → 2.8.2
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 +2 -2
- package/dist/Artalk.cjs.map +1 -1
- package/dist/Artalk.css +1 -1
- package/dist/Artalk.iife.js +2 -2
- package/dist/Artalk.iife.js.map +1 -1
- package/dist/Artalk.js +2 -2
- package/dist/Artalk.js.map +1 -1
- package/dist/Artalk.mjs +311 -269
- package/dist/Artalk.mjs.map +1 -1
- package/dist/ArtalkLite.cjs +2 -2
- package/dist/ArtalkLite.cjs.map +1 -1
- package/dist/ArtalkLite.css +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 +311 -269
- 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 +1 -1
- package/dist/i18n/zh-TW.cjs +1 -1
- package/dist/i18n/zh-TW.js +1 -1
- package/dist/i18n/zh-TW.mjs +3 -3
- package/dist/main.d.cts +109 -50
- package/dist/main.d.ts +109 -50
- package/package.json +1 -1
package/dist/ArtalkLite.mjs
CHANGED
|
@@ -368,6 +368,29 @@ let Api$1 = class Api extends HttpClient {
|
|
|
368
368
|
type: "application/json",
|
|
369
369
|
format: "json"
|
|
370
370
|
}, params)),
|
|
371
|
+
/**
|
|
372
|
+
* @description Get the detail of a comment by comment id
|
|
373
|
+
*
|
|
374
|
+
* @tags Comment
|
|
375
|
+
* @name GetComment
|
|
376
|
+
* @summary Get a comment
|
|
377
|
+
* @request GET:/comments/{id}
|
|
378
|
+
* @response `200` `HandlerResponseCommentGet` OK
|
|
379
|
+
* @response `404` `(HandlerMap & {
|
|
380
|
+
msg?: string,
|
|
381
|
+
|
|
382
|
+
})` Not Found
|
|
383
|
+
* @response `500` `(HandlerMap & {
|
|
384
|
+
msg?: string,
|
|
385
|
+
|
|
386
|
+
})` Internal Server Error
|
|
387
|
+
*/
|
|
388
|
+
getComment: (id, params = {}) => this.request(__spreadValues({
|
|
389
|
+
path: `/comments/${id}`,
|
|
390
|
+
method: "GET",
|
|
391
|
+
type: "application/json",
|
|
392
|
+
format: "json"
|
|
393
|
+
}, params)),
|
|
371
394
|
/**
|
|
372
395
|
* @description Update a specific comment
|
|
373
396
|
*
|
|
@@ -2449,7 +2472,7 @@ const en = {
|
|
|
2449
2472
|
link: "Website",
|
|
2450
2473
|
emoticon: "Emoji",
|
|
2451
2474
|
preview: "Preview",
|
|
2452
|
-
|
|
2475
|
+
uploadImage: "Upload Image",
|
|
2453
2476
|
uploadFail: "Upload Failed",
|
|
2454
2477
|
commentFail: "Failed to comment",
|
|
2455
2478
|
restoredMsg: "Content has been restored",
|
|
@@ -2522,14 +2545,14 @@ const zhCN = {
|
|
|
2522
2545
|
/* Editor */
|
|
2523
2546
|
placeholder: "键入内容...",
|
|
2524
2547
|
noComment: "「此时无声胜有声」",
|
|
2525
|
-
send: "
|
|
2526
|
-
save: "
|
|
2548
|
+
send: "发送",
|
|
2549
|
+
save: "保存",
|
|
2527
2550
|
nick: "昵称",
|
|
2528
2551
|
email: "邮箱",
|
|
2529
2552
|
link: "网址",
|
|
2530
2553
|
emoticon: "表情",
|
|
2531
2554
|
preview: "预览",
|
|
2532
|
-
|
|
2555
|
+
uploadImage: "上传图片",
|
|
2533
2556
|
uploadFail: "上传失败",
|
|
2534
2557
|
commentFail: "评论失败",
|
|
2535
2558
|
restoredMsg: "内容已自动恢复",
|
|
@@ -3131,7 +3154,7 @@ function showLoading(parentElem, conf) {
|
|
|
3131
3154
|
let $loading = parentElem.querySelector(":scope > .atk-loading");
|
|
3132
3155
|
if (!$loading) {
|
|
3133
3156
|
$loading = createElement(
|
|
3134
|
-
`<div class="atk-loading
|
|
3157
|
+
`<div class="atk-loading" style="display: none;">
|
|
3135
3158
|
<div class="atk-loading-spinner">
|
|
3136
3159
|
<svg viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"></circle></svg>
|
|
3137
3160
|
</div>
|
|
@@ -3146,7 +3169,8 @@ function showLoading(parentElem, conf) {
|
|
|
3146
3169
|
if ($spinner) {
|
|
3147
3170
|
$spinner.style.display = "none";
|
|
3148
3171
|
window.setTimeout(() => {
|
|
3149
|
-
$spinner.
|
|
3172
|
+
if ($spinner.isConnected)
|
|
3173
|
+
$spinner.style.display = "";
|
|
3150
3174
|
}, 500);
|
|
3151
3175
|
}
|
|
3152
3176
|
}
|
|
@@ -3166,8 +3190,7 @@ function scrollIntoView(elem, enableAnim = true, relativeTo) {
|
|
|
3166
3190
|
if (relativeTo) {
|
|
3167
3191
|
const containerRect = relativeTo.getBoundingClientRect();
|
|
3168
3192
|
const elementRect = elem.getBoundingClientRect();
|
|
3169
|
-
top = elementRect.top - containerRect.top + relativeTo.scrollTop;
|
|
3170
|
-
top += getHeight(relativeTo) / 2 - getHeight(elem) / 2;
|
|
3193
|
+
top = elementRect.top - containerRect.top + relativeTo.scrollTop - relativeTo.clientHeight / 2 + elem.clientHeight / 2;
|
|
3171
3194
|
} else {
|
|
3172
3195
|
const rect = elem.getBoundingClientRect();
|
|
3173
3196
|
const elemTop = rect.top + window.scrollY;
|
|
@@ -3501,8 +3524,11 @@ class Component {
|
|
|
3501
3524
|
get conf() {
|
|
3502
3525
|
return this.ctx.conf;
|
|
3503
3526
|
}
|
|
3527
|
+
getEl() {
|
|
3528
|
+
return this.$el;
|
|
3529
|
+
}
|
|
3504
3530
|
}
|
|
3505
|
-
const EditorHTML = '<div class="atk-main-editor">\n <div class="atk-header">\n <input name="nick" class="atk-nick" type="text" required="required">\n <input name="email" class="atk-email" type="email" required="required">\n <input name="link" class="atk-link" type="url">\n </div>\n <div class="atk-textarea-wrap">\n <textarea class="atk-textarea"></textarea>\n </div>\n <div class="atk-plug-panel-wrap" style="display: none;"></div>\n <div class="atk-bottom">\n <div class="atk-item atk-plug-btn-wrap"></div>\n <div class="atk-item">\n <button type="button" class="atk-send-btn"></button>\n </div>\n </div>\n <div class="atk-notify-wrap"></div>\n</div>\n';
|
|
3531
|
+
const EditorHTML = '<div class="atk-main-editor">\n <div class="atk-header">\n <input name="nick" class="atk-nick" type="text" required="required">\n <input name="email" class="atk-email" type="email" required="required">\n <input name="link" class="atk-link" type="url">\n </div>\n <div class="atk-textarea-wrap">\n <textarea class="atk-textarea"></textarea>\n </div>\n <div class="atk-plug-panel-wrap" style="display: none;"></div>\n <div class="atk-bottom">\n <div class="atk-item atk-bottom-left">\n <span class="atk-state-wrap"></span>\n <span class="atk-plug-btn-wrap"></span>\n </div>\n <div class="atk-item">\n <button type="button" class="atk-send-btn"></button>\n </div>\n </div>\n <div class="atk-notify-wrap"></div>\n</div>\n';
|
|
3506
3532
|
const Sel = {
|
|
3507
3533
|
$header: ".atk-header",
|
|
3508
3534
|
$nick: '.atk-header [name="nick"]',
|
|
@@ -3513,6 +3539,8 @@ const Sel = {
|
|
|
3513
3539
|
$bottom: ".atk-bottom",
|
|
3514
3540
|
$submitBtn: ".atk-send-btn",
|
|
3515
3541
|
$notifyWrap: ".atk-notify-wrap",
|
|
3542
|
+
$bottomLeft: ".atk-bottom-left",
|
|
3543
|
+
$stateWrap: ".atk-state-wrap",
|
|
3516
3544
|
$plugBtnWrap: ".atk-plug-btn-wrap",
|
|
3517
3545
|
$plugPanelWrap: ".atk-plug-panel-wrap"
|
|
3518
3546
|
};
|
|
@@ -3885,39 +3913,18 @@ function makeNestCommentNodeList(srcData, sortBy = "DATE_DESC", nestMax = 2) {
|
|
|
3885
3913
|
})(nodeList);
|
|
3886
3914
|
return nodeList;
|
|
3887
3915
|
}
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
}
|
|
3892
|
-
// TODO: refactor `if syntax` to strategy pattern
|
|
3893
|
-
import(comments) {
|
|
3894
|
-
if (this.options.flatMode) {
|
|
3895
|
-
comments.forEach((commentData) => {
|
|
3896
|
-
this.putCommentFlatMode(commentData, comments, "append");
|
|
3897
|
-
});
|
|
3898
|
-
} else {
|
|
3899
|
-
this.importCommentsNestMode(comments);
|
|
3900
|
-
}
|
|
3901
|
-
}
|
|
3902
|
-
insert(comment) {
|
|
3903
|
-
if (!this.options.flatMode) {
|
|
3904
|
-
this.insertCommentNest(comment);
|
|
3905
|
-
} else {
|
|
3906
|
-
this.insertCommentFlatMode(comment);
|
|
3907
|
-
}
|
|
3908
|
-
}
|
|
3909
|
-
// 导入评论 · 嵌套模式
|
|
3910
|
-
importCommentsNestMode(srcData) {
|
|
3911
|
-
const rootNodes = makeNestCommentNodeList(srcData, this.options.nestSortBy, this.options.nestMax);
|
|
3916
|
+
const createNestStrategy = (opts) => ({
|
|
3917
|
+
import: (comments) => {
|
|
3918
|
+
const rootNodes = makeNestCommentNodeList(comments, opts.nestSortBy, opts.nestMax);
|
|
3912
3919
|
rootNodes.forEach((rootNode) => {
|
|
3913
3920
|
var _a;
|
|
3914
|
-
const rootC =
|
|
3915
|
-
(_a =
|
|
3921
|
+
const rootC = opts.createCommentNode(rootNode.comment);
|
|
3922
|
+
(_a = opts.$commentsWrap) == null ? void 0 : _a.appendChild(rootC.getEl());
|
|
3916
3923
|
rootC.getRender().playFadeAnim();
|
|
3917
3924
|
const loadChildren = (parentC, parentNode) => {
|
|
3918
3925
|
parentNode.children.forEach((node) => {
|
|
3919
3926
|
const childD = node.comment;
|
|
3920
|
-
const childC =
|
|
3927
|
+
const childC = opts.createCommentNode(childD, parentC.getData());
|
|
3921
3928
|
parentC.putChild(childC);
|
|
3922
3929
|
loadChildren(childC, node);
|
|
3923
3930
|
});
|
|
@@ -3925,44 +3932,66 @@ class ListLayout {
|
|
|
3925
3932
|
loadChildren(rootC, rootNode);
|
|
3926
3933
|
rootC.getRender().checkHeightLimit();
|
|
3927
3934
|
});
|
|
3928
|
-
}
|
|
3929
|
-
|
|
3930
|
-
putCommentFlatMode(cData, ctxData, insertMode) {
|
|
3931
|
-
var _a, _b;
|
|
3932
|
-
if (cData.is_collapsed)
|
|
3933
|
-
cData.is_allow_reply = false;
|
|
3934
|
-
const comment = this.options.createCommentNode(cData, ctxData);
|
|
3935
|
-
if (cData.visible) {
|
|
3936
|
-
if (insertMode === "append")
|
|
3937
|
-
(_a = this.options.$commentsWrap) == null ? void 0 : _a.append(comment.getEl());
|
|
3938
|
-
if (insertMode === "prepend")
|
|
3939
|
-
(_b = this.options.$commentsWrap) == null ? void 0 : _b.prepend(comment.getEl());
|
|
3940
|
-
comment.getRender().playFadeAnim();
|
|
3941
|
-
}
|
|
3942
|
-
comment.getRender().checkHeightLimit();
|
|
3943
|
-
return comment;
|
|
3944
|
-
}
|
|
3945
|
-
insertCommentNest(commentData) {
|
|
3935
|
+
},
|
|
3936
|
+
insert: (comment, replyComment) => {
|
|
3946
3937
|
var _a;
|
|
3947
|
-
const
|
|
3948
|
-
if (
|
|
3949
|
-
(_a =
|
|
3938
|
+
const node = opts.createCommentNode(comment, replyComment);
|
|
3939
|
+
if (comment.rid === 0) {
|
|
3940
|
+
(_a = opts.$commentsWrap) == null ? void 0 : _a.prepend(node.getEl());
|
|
3950
3941
|
} else {
|
|
3951
|
-
const parent =
|
|
3942
|
+
const parent = opts.findCommentNode(comment.rid);
|
|
3952
3943
|
if (parent) {
|
|
3953
|
-
parent.putChild(
|
|
3954
|
-
|
|
3944
|
+
parent.putChild(node, opts.nestSortBy === "DATE_ASC" ? "append" : "prepend");
|
|
3945
|
+
node.getParents().forEach((p) => {
|
|
3955
3946
|
p.getRender().heightLimitRemoveForChildren();
|
|
3956
3947
|
});
|
|
3957
3948
|
}
|
|
3958
3949
|
}
|
|
3959
|
-
|
|
3960
|
-
scrollIntoView(
|
|
3961
|
-
|
|
3950
|
+
node.getRender().checkHeightLimit();
|
|
3951
|
+
node.scrollIntoView();
|
|
3952
|
+
node.getRender().playFadeAnim();
|
|
3953
|
+
}
|
|
3954
|
+
});
|
|
3955
|
+
const createFlatStrategy = (opts) => ({
|
|
3956
|
+
import: (comments) => {
|
|
3957
|
+
comments.forEach((comment) => {
|
|
3958
|
+
const replyComment = comment.rid === 0 ? void 0 : comments.find((c) => c.id === comment.rid);
|
|
3959
|
+
insertComment(opts, "append", comment, replyComment);
|
|
3960
|
+
});
|
|
3961
|
+
},
|
|
3962
|
+
insert: (comment, replyComment) => {
|
|
3963
|
+
const node = insertComment(opts, "prepend", comment, replyComment);
|
|
3964
|
+
node.scrollIntoView();
|
|
3965
|
+
}
|
|
3966
|
+
});
|
|
3967
|
+
function insertComment(opts, insertMode, comment, replyComment) {
|
|
3968
|
+
if (comment.is_collapsed)
|
|
3969
|
+
comment.is_allow_reply = false;
|
|
3970
|
+
const node = opts.createCommentNode(comment, replyComment);
|
|
3971
|
+
if (comment.visible) {
|
|
3972
|
+
const $comment = node.getEl();
|
|
3973
|
+
const $listCommentsWrap = opts.$commentsWrap;
|
|
3974
|
+
if (insertMode === "append")
|
|
3975
|
+
$listCommentsWrap == null ? void 0 : $listCommentsWrap.append($comment);
|
|
3976
|
+
if (insertMode === "prepend")
|
|
3977
|
+
$listCommentsWrap == null ? void 0 : $listCommentsWrap.prepend($comment);
|
|
3978
|
+
node.getRender().playFadeAnim();
|
|
3979
|
+
}
|
|
3980
|
+
node.getRender().checkHeightLimit();
|
|
3981
|
+
return node;
|
|
3982
|
+
}
|
|
3983
|
+
class ListLayout {
|
|
3984
|
+
constructor(options) {
|
|
3985
|
+
this.options = options;
|
|
3962
3986
|
}
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3987
|
+
getStrategy() {
|
|
3988
|
+
return this.options.flatMode ? createFlatStrategy(this.options) : createNestStrategy(this.options);
|
|
3989
|
+
}
|
|
3990
|
+
import(comments) {
|
|
3991
|
+
this.getStrategy().import(comments);
|
|
3992
|
+
}
|
|
3993
|
+
insert(comment, replyComment) {
|
|
3994
|
+
this.getStrategy().insert(comment, replyComment);
|
|
3966
3995
|
}
|
|
3967
3996
|
}
|
|
3968
3997
|
function Detect(userAgent) {
|
|
@@ -4225,7 +4254,7 @@ const CommentHTML = '<div class="atk-comment-wrap">\n <div class="atk-comment">
|
|
|
4225
4254
|
function renderAvatar(r) {
|
|
4226
4255
|
const $avatar = r.$el.querySelector(".atk-avatar");
|
|
4227
4256
|
const $avatarImg = createElement("<img />");
|
|
4228
|
-
const avatarURLBuilder = r.
|
|
4257
|
+
const avatarURLBuilder = r.opts.avatarURLBuilder;
|
|
4229
4258
|
$avatarImg.src = avatarURLBuilder ? avatarURLBuilder(r.data) : r.comment.getGravatarURL();
|
|
4230
4259
|
if (r.data.link) {
|
|
4231
4260
|
const $avatarA = createElement('<a target="_blank" rel="noreferrer noopener nofollow"></a>');
|
|
@@ -4264,12 +4293,12 @@ function renderVerifyBadge(ctx) {
|
|
|
4264
4293
|
const badgeColor = ctx.data.badge_color;
|
|
4265
4294
|
if (badgeText) {
|
|
4266
4295
|
const $badge = createElement(`<span class="atk-badge"></span>`);
|
|
4267
|
-
$badge.innerText = badgeText.replace("管理员",
|
|
4296
|
+
$badge.innerText = badgeText.replace("管理员", t("admin"));
|
|
4268
4297
|
$badge.style.backgroundColor = badgeColor || "";
|
|
4269
4298
|
ctx.$headerBadgeWrap.append($badge);
|
|
4270
4299
|
}
|
|
4271
4300
|
if (ctx.data.is_pinned) {
|
|
4272
|
-
const $pinnedBadge = createElement(`<span class="atk-pinned-badge">${
|
|
4301
|
+
const $pinnedBadge = createElement(`<span class="atk-pinned-badge">${t("pin")}</span>`);
|
|
4273
4302
|
ctx.$headerBadgeWrap.append($pinnedBadge);
|
|
4274
4303
|
}
|
|
4275
4304
|
}
|
|
@@ -4279,7 +4308,7 @@ function renderDate(ctx) {
|
|
|
4279
4308
|
$date.setAttribute("data-atk-comment-date", String(+new Date(ctx.data.date)));
|
|
4280
4309
|
}
|
|
4281
4310
|
function renderUABadge(ctx) {
|
|
4282
|
-
if (!ctx.
|
|
4311
|
+
if (!ctx.opts.uaBadge && !ctx.data.ip_region)
|
|
4283
4312
|
return;
|
|
4284
4313
|
let $uaWrap = ctx.$header.querySelector("atk-ua-wrap");
|
|
4285
4314
|
if (!$uaWrap) {
|
|
@@ -4292,7 +4321,7 @@ function renderUABadge(ctx) {
|
|
|
4292
4321
|
$regionBadge.innerText = ctx.data.ip_region;
|
|
4293
4322
|
$uaWrap.append($regionBadge);
|
|
4294
4323
|
}
|
|
4295
|
-
if (ctx.
|
|
4324
|
+
if (ctx.opts.uaBadge) {
|
|
4296
4325
|
const { browser, os } = ctx.comment.getUserUA();
|
|
4297
4326
|
if (String(browser).trim()) {
|
|
4298
4327
|
const $uaBrowser = createElement(`<span class="atk-ua ua-browser"></span>`);
|
|
@@ -4315,8 +4344,8 @@ function renderContent(r) {
|
|
|
4315
4344
|
r.$content.classList.add("atk-hide", "atk-type-collapsed");
|
|
4316
4345
|
const collapsedInfoEl = createElement(`
|
|
4317
4346
|
<div class="atk-collapsed">
|
|
4318
|
-
<span class="atk-text">${
|
|
4319
|
-
<span class="atk-show-btn">${
|
|
4347
|
+
<span class="atk-text">${t("collapsedMsg")}</span>
|
|
4348
|
+
<span class="atk-show-btn">${t("expand")}</span>
|
|
4320
4349
|
</div>`);
|
|
4321
4350
|
r.$body.insertAdjacentElement("beforeend", collapsedInfoEl);
|
|
4322
4351
|
const contentShowBtn = collapsedInfoEl.querySelector(".atk-show-btn");
|
|
@@ -4326,51 +4355,51 @@ function renderContent(r) {
|
|
|
4326
4355
|
r.$content.innerHTML = r.comment.getContentMarked();
|
|
4327
4356
|
r.$content.classList.remove("atk-hide");
|
|
4328
4357
|
playFadeInAnim(r.$content);
|
|
4329
|
-
contentShowBtn.innerText =
|
|
4358
|
+
contentShowBtn.innerText = t("collapse");
|
|
4330
4359
|
} else {
|
|
4331
4360
|
r.$content.innerHTML = "";
|
|
4332
4361
|
r.$content.classList.add("atk-hide");
|
|
4333
|
-
contentShowBtn.innerText =
|
|
4362
|
+
contentShowBtn.innerText = t("expand");
|
|
4334
4363
|
}
|
|
4335
4364
|
});
|
|
4336
4365
|
}
|
|
4337
4366
|
function renderReplyAt(r) {
|
|
4338
|
-
if (r.
|
|
4367
|
+
if (r.opts.flatMode || r.data.rid === 0)
|
|
4339
4368
|
return;
|
|
4340
|
-
if (!r.
|
|
4369
|
+
if (!r.opts.replyTo)
|
|
4341
4370
|
return;
|
|
4342
4371
|
r.$replyAt = createElement(`<span class="atk-item atk-reply-at"><span class="atk-arrow"></span><span class="atk-nick"></span></span>`);
|
|
4343
|
-
r.$replyAt.querySelector(".atk-nick").innerText = `${r.
|
|
4372
|
+
r.$replyAt.querySelector(".atk-nick").innerText = `${r.opts.replyTo.nick}`;
|
|
4344
4373
|
r.$replyAt.onclick = () => {
|
|
4345
4374
|
r.comment.getActions().goToReplyComment();
|
|
4346
4375
|
};
|
|
4347
4376
|
r.$headerBadgeWrap.insertAdjacentElement("afterend", r.$replyAt);
|
|
4348
4377
|
}
|
|
4349
4378
|
function renderReplyTo(r) {
|
|
4350
|
-
if (!r.
|
|
4379
|
+
if (!r.opts.flatMode)
|
|
4351
4380
|
return;
|
|
4352
|
-
if (!r.
|
|
4381
|
+
if (!r.opts.replyTo)
|
|
4353
4382
|
return;
|
|
4354
4383
|
r.$replyTo = createElement(`
|
|
4355
4384
|
<div class="atk-reply-to">
|
|
4356
|
-
<div class="atk-meta">${
|
|
4385
|
+
<div class="atk-meta">${t("reply")} <span class="atk-nick"></span>:</div>
|
|
4357
4386
|
<div class="atk-content"></div>
|
|
4358
4387
|
</div>`);
|
|
4359
4388
|
const $nick = r.$replyTo.querySelector(".atk-nick");
|
|
4360
|
-
$nick.innerText = `@${r.
|
|
4389
|
+
$nick.innerText = `@${r.opts.replyTo.nick}`;
|
|
4361
4390
|
$nick.onclick = () => {
|
|
4362
4391
|
r.comment.getActions().goToReplyComment();
|
|
4363
4392
|
};
|
|
4364
|
-
let replyContent = marked(r.
|
|
4365
|
-
if (r.
|
|
4366
|
-
replyContent = `[${
|
|
4393
|
+
let replyContent = marked(r.opts.replyTo.content);
|
|
4394
|
+
if (r.opts.replyTo.is_collapsed)
|
|
4395
|
+
replyContent = `[${t("collapsed")}]`;
|
|
4367
4396
|
r.$replyTo.querySelector(".atk-content").innerHTML = replyContent;
|
|
4368
4397
|
r.$body.prepend(r.$replyTo);
|
|
4369
4398
|
}
|
|
4370
4399
|
function renderPending(r) {
|
|
4371
4400
|
if (!r.data.is_pending)
|
|
4372
4401
|
return;
|
|
4373
|
-
const pendingEl = createElement(`<div class="atk-pending">${
|
|
4402
|
+
const pendingEl = createElement(`<div class="atk-pending">${t("pendingMsg")}</div>`);
|
|
4374
4403
|
r.$body.prepend(pendingEl);
|
|
4375
4404
|
}
|
|
4376
4405
|
class ActionBtn {
|
|
@@ -4523,14 +4552,14 @@ function renderActions(r) {
|
|
|
4523
4552
|
});
|
|
4524
4553
|
}
|
|
4525
4554
|
function renderVote(r) {
|
|
4526
|
-
if (!r.
|
|
4555
|
+
if (!r.opts.vote)
|
|
4527
4556
|
return;
|
|
4528
|
-
r.voteBtnUp = new ActionBtn(() => `${
|
|
4557
|
+
r.voteBtnUp = new ActionBtn(() => `${t("voteUp")} (${r.data.vote_up || 0})`).appendTo(r.$actions);
|
|
4529
4558
|
r.voteBtnUp.setClick(() => {
|
|
4530
4559
|
r.comment.getActions().vote("up");
|
|
4531
4560
|
});
|
|
4532
|
-
if (r.
|
|
4533
|
-
r.voteBtnDown = new ActionBtn(() => `${
|
|
4561
|
+
if (r.opts.voteDown) {
|
|
4562
|
+
r.voteBtnDown = new ActionBtn(() => `${t("voteDown")} (${r.data.vote_down || 0})`).appendTo(r.$actions);
|
|
4534
4563
|
r.voteBtnDown.setClick(() => {
|
|
4535
4564
|
r.comment.getActions().vote("down");
|
|
4536
4565
|
});
|
|
@@ -4539,20 +4568,16 @@ function renderVote(r) {
|
|
|
4539
4568
|
function renderReply(r) {
|
|
4540
4569
|
if (!r.data.is_allow_reply)
|
|
4541
4570
|
return;
|
|
4542
|
-
const replyBtn = createElement(`<span>${
|
|
4571
|
+
const replyBtn = createElement(`<span>${t("reply")}</span>`);
|
|
4543
4572
|
r.$actions.append(replyBtn);
|
|
4544
4573
|
replyBtn.addEventListener("click", (e) => {
|
|
4545
4574
|
e.stopPropagation();
|
|
4546
|
-
|
|
4547
|
-
r.ctx.replyComment(r.data, r.$el);
|
|
4548
|
-
} else {
|
|
4549
|
-
r.cConf.onReplyBtnClick();
|
|
4550
|
-
}
|
|
4575
|
+
r.opts.replyComment(r.data, r.$el);
|
|
4551
4576
|
});
|
|
4552
4577
|
}
|
|
4553
4578
|
function renderCollapse(r) {
|
|
4554
4579
|
const collapseBtn = new ActionBtn({
|
|
4555
|
-
text: () => r.data.is_collapsed ?
|
|
4580
|
+
text: () => r.data.is_collapsed ? t("expand") : t("collapse"),
|
|
4556
4581
|
adminOnly: true
|
|
4557
4582
|
});
|
|
4558
4583
|
collapseBtn.appendTo(r.$actions);
|
|
@@ -4562,7 +4587,7 @@ function renderCollapse(r) {
|
|
|
4562
4587
|
}
|
|
4563
4588
|
function renderModerator(r) {
|
|
4564
4589
|
const pendingBtn = new ActionBtn({
|
|
4565
|
-
text: () => r.data.is_pending ?
|
|
4590
|
+
text: () => r.data.is_pending ? t("pending") : t("approved"),
|
|
4566
4591
|
adminOnly: true
|
|
4567
4592
|
});
|
|
4568
4593
|
pendingBtn.appendTo(r.$actions);
|
|
@@ -4572,7 +4597,7 @@ function renderModerator(r) {
|
|
|
4572
4597
|
}
|
|
4573
4598
|
function renderPin(r) {
|
|
4574
4599
|
const pinnedBtn = new ActionBtn({
|
|
4575
|
-
text: () => r.data.is_pinned ?
|
|
4600
|
+
text: () => r.data.is_pinned ? t("unpin") : t("pin"),
|
|
4576
4601
|
adminOnly: true
|
|
4577
4602
|
});
|
|
4578
4603
|
pinnedBtn.appendTo(r.$actions);
|
|
@@ -4582,19 +4607,19 @@ function renderPin(r) {
|
|
|
4582
4607
|
}
|
|
4583
4608
|
function renderEdit(r) {
|
|
4584
4609
|
const editBtn = new ActionBtn({
|
|
4585
|
-
text:
|
|
4610
|
+
text: t("edit"),
|
|
4586
4611
|
adminOnly: true
|
|
4587
4612
|
});
|
|
4588
4613
|
editBtn.appendTo(r.$actions);
|
|
4589
4614
|
editBtn.setClick(() => {
|
|
4590
|
-
r.
|
|
4615
|
+
r.opts.editComment(r.data, r.$el);
|
|
4591
4616
|
});
|
|
4592
4617
|
}
|
|
4593
4618
|
function renderDel(r) {
|
|
4594
4619
|
const delBtn = new ActionBtn({
|
|
4595
|
-
text:
|
|
4620
|
+
text: t("delete"),
|
|
4596
4621
|
confirm: true,
|
|
4597
|
-
confirmText:
|
|
4622
|
+
confirmText: t("deleteConfirm"),
|
|
4598
4623
|
adminOnly: true
|
|
4599
4624
|
});
|
|
4600
4625
|
delBtn.appendTo(r.$actions);
|
|
@@ -4636,18 +4661,21 @@ class Render {
|
|
|
4636
4661
|
__publicField(this, "$replyAt");
|
|
4637
4662
|
this.comment = comment;
|
|
4638
4663
|
}
|
|
4639
|
-
get ctx() {
|
|
4640
|
-
return this.comment.ctx;
|
|
4641
|
-
}
|
|
4642
4664
|
get data() {
|
|
4643
4665
|
return this.comment.getData();
|
|
4644
4666
|
}
|
|
4645
|
-
get
|
|
4646
|
-
return this.comment.
|
|
4647
|
-
}
|
|
4648
|
-
get cConf() {
|
|
4649
|
-
return this.comment.getConf();
|
|
4667
|
+
get opts() {
|
|
4668
|
+
return this.comment.getOpts();
|
|
4650
4669
|
}
|
|
4670
|
+
/**
|
|
4671
|
+
* Render the comment ui
|
|
4672
|
+
*
|
|
4673
|
+
* If comment data is updated, call this method to re-render the comment ui.
|
|
4674
|
+
* The method will be called multiple times, so it should be idempotent.
|
|
4675
|
+
*
|
|
4676
|
+
* Renders may add event listeners to the comment ui, so it should be called only once or override the original.
|
|
4677
|
+
* Please be aware of the memory leak caused by the event listener.
|
|
4678
|
+
*/
|
|
4651
4679
|
render() {
|
|
4652
4680
|
this.$el = createElement(CommentHTML);
|
|
4653
4681
|
this.$main = this.$el.querySelector(".atk-main");
|
|
@@ -4657,12 +4685,14 @@ class Render {
|
|
|
4657
4685
|
this.$actions = this.$el.querySelector(".atk-actions");
|
|
4658
4686
|
this.$el.setAttribute("id", `atk-comment-${this.data.id}`);
|
|
4659
4687
|
loadRenders(this);
|
|
4660
|
-
this
|
|
4688
|
+
if (this.$childrenWrap) {
|
|
4689
|
+
this.$main.append(this.$childrenWrap);
|
|
4690
|
+
}
|
|
4661
4691
|
return this.$el;
|
|
4662
4692
|
}
|
|
4663
4693
|
/** 内容限高检测 */
|
|
4664
4694
|
checkHeightLimit() {
|
|
4665
|
-
const conf = this.
|
|
4695
|
+
const conf = this.opts.heightLimit;
|
|
4666
4696
|
if (!conf || !conf.content || !conf.children)
|
|
4667
4697
|
return;
|
|
4668
4698
|
const contentMaxH = conf.content;
|
|
@@ -4696,24 +4726,21 @@ class Render {
|
|
|
4696
4726
|
playFadeAnimForBody() {
|
|
4697
4727
|
playFadeInAnim(this.comment.getRender().$body);
|
|
4698
4728
|
}
|
|
4729
|
+
/** Perform the flash animation */
|
|
4730
|
+
playFlashAnim() {
|
|
4731
|
+
this.$el.classList.remove("atk-flash-once");
|
|
4732
|
+
window.setTimeout(() => {
|
|
4733
|
+
this.$el.classList.add("atk-flash-once");
|
|
4734
|
+
}, 150);
|
|
4735
|
+
}
|
|
4699
4736
|
/** 获取子评论 Wrap */
|
|
4700
4737
|
getChildrenWrap() {
|
|
4701
|
-
return this.$childrenWrap;
|
|
4702
|
-
}
|
|
4703
|
-
/** 初始化子评论区域 Wrap */
|
|
4704
|
-
renderChildrenWrap() {
|
|
4705
4738
|
if (!this.$childrenWrap) {
|
|
4706
4739
|
this.$childrenWrap = createElement('<div class="atk-comment-children"></div>');
|
|
4707
4740
|
this.$main.append(this.$childrenWrap);
|
|
4708
4741
|
}
|
|
4709
4742
|
return this.$childrenWrap;
|
|
4710
4743
|
}
|
|
4711
|
-
/** 恢复原有的子评论区域 Wrap */
|
|
4712
|
-
recoveryChildrenWrap() {
|
|
4713
|
-
if (this.$childrenWrap) {
|
|
4714
|
-
this.$main.append(this.$childrenWrap);
|
|
4715
|
-
}
|
|
4716
|
-
}
|
|
4717
4744
|
/** 设置已读 */
|
|
4718
4745
|
setUnread(val) {
|
|
4719
4746
|
if (val)
|
|
@@ -4732,17 +4759,15 @@ class Render {
|
|
|
4732
4759
|
setOpenURL(url) {
|
|
4733
4760
|
this.setOpenable(true);
|
|
4734
4761
|
this.$el.onclick = (evt) => {
|
|
4735
|
-
evt.
|
|
4762
|
+
evt.stopPropagation();
|
|
4736
4763
|
window.open(url);
|
|
4737
|
-
if (this.cConf.openEvt)
|
|
4738
|
-
this.cConf.openEvt();
|
|
4739
4764
|
};
|
|
4740
4765
|
}
|
|
4741
4766
|
/** 设置点击评论时的操作 */
|
|
4742
4767
|
setOpenAction(action) {
|
|
4743
4768
|
this.setOpenable(true);
|
|
4744
4769
|
this.$el.onclick = (evt) => {
|
|
4745
|
-
evt.
|
|
4770
|
+
evt.stopPropagation();
|
|
4746
4771
|
action();
|
|
4747
4772
|
};
|
|
4748
4773
|
}
|
|
@@ -4752,26 +4777,26 @@ class CommentActions {
|
|
|
4752
4777
|
__publicField(this, "comment");
|
|
4753
4778
|
this.comment = comment;
|
|
4754
4779
|
}
|
|
4755
|
-
get ctx() {
|
|
4756
|
-
return this.comment.ctx;
|
|
4757
|
-
}
|
|
4758
4780
|
get data() {
|
|
4759
4781
|
return this.comment.getData();
|
|
4760
4782
|
}
|
|
4761
|
-
get
|
|
4762
|
-
return this.comment.
|
|
4783
|
+
get opts() {
|
|
4784
|
+
return this.comment.getOpts();
|
|
4785
|
+
}
|
|
4786
|
+
getApi() {
|
|
4787
|
+
return this.comment.getOpts().getApi();
|
|
4763
4788
|
}
|
|
4764
4789
|
/** 投票操作 */
|
|
4765
4790
|
vote(type) {
|
|
4766
4791
|
const actionBtn = type === "up" ? this.comment.getRender().voteBtnUp : this.comment.getRender().voteBtnDown;
|
|
4767
|
-
this.
|
|
4792
|
+
this.getApi().votes.vote(`comment_${type}`, this.data.id, __spreadValues({}, this.getApi().getUserFields())).then((res) => {
|
|
4768
4793
|
var _a, _b;
|
|
4769
4794
|
this.data.vote_up = res.data.up;
|
|
4770
4795
|
this.data.vote_down = res.data.down;
|
|
4771
4796
|
(_a = this.comment.getRender().voteBtnUp) == null ? void 0 : _a.updateText();
|
|
4772
4797
|
(_b = this.comment.getRender().voteBtnDown) == null ? void 0 : _b.updateText();
|
|
4773
4798
|
}).catch((err) => {
|
|
4774
|
-
actionBtn == null ? void 0 : actionBtn.setError(
|
|
4799
|
+
actionBtn == null ? void 0 : actionBtn.setError(t("voteFail"));
|
|
4775
4800
|
console.log(err);
|
|
4776
4801
|
});
|
|
4777
4802
|
}
|
|
@@ -4779,7 +4804,7 @@ class CommentActions {
|
|
|
4779
4804
|
adminEdit(type, btnElem) {
|
|
4780
4805
|
if (btnElem.isLoading)
|
|
4781
4806
|
return;
|
|
4782
|
-
btnElem.setLoading(true, `${
|
|
4807
|
+
btnElem.setLoading(true, `${t("editing")}...`);
|
|
4783
4808
|
const modify = __spreadValues({}, this.data);
|
|
4784
4809
|
if (type === "collapsed") {
|
|
4785
4810
|
modify.is_collapsed = !modify.is_collapsed;
|
|
@@ -4788,26 +4813,26 @@ class CommentActions {
|
|
|
4788
4813
|
} else if (type === "pinned") {
|
|
4789
4814
|
modify.is_pinned = !modify.is_pinned;
|
|
4790
4815
|
}
|
|
4791
|
-
this.
|
|
4816
|
+
this.getApi().comments.updateComment(this.data.id, __spreadValues({}, modify)).then((res) => {
|
|
4792
4817
|
btnElem.setLoading(false);
|
|
4793
4818
|
this.comment.setData(res.data);
|
|
4794
4819
|
}).catch((err) => {
|
|
4795
4820
|
console.error(err);
|
|
4796
|
-
btnElem.setError(
|
|
4821
|
+
btnElem.setError(t("editFail"));
|
|
4797
4822
|
});
|
|
4798
4823
|
}
|
|
4799
4824
|
/** 管理员 - 评论删除 */
|
|
4800
4825
|
adminDelete(btnElem) {
|
|
4801
4826
|
if (btnElem.isLoading)
|
|
4802
4827
|
return;
|
|
4803
|
-
btnElem.setLoading(true, `${
|
|
4804
|
-
this.
|
|
4828
|
+
btnElem.setLoading(true, `${t("deleting")}...`);
|
|
4829
|
+
this.getApi().comments.deleteComment(this.data.id).then(() => {
|
|
4805
4830
|
btnElem.setLoading(false);
|
|
4806
|
-
if (this.
|
|
4807
|
-
this.
|
|
4831
|
+
if (this.opts.onDelete)
|
|
4832
|
+
this.opts.onDelete(this.comment);
|
|
4808
4833
|
}).catch((e) => {
|
|
4809
4834
|
console.error(e);
|
|
4810
|
-
btnElem.setError(
|
|
4835
|
+
btnElem.setError(t("deleteFail"));
|
|
4811
4836
|
});
|
|
4812
4837
|
}
|
|
4813
4838
|
/** 快速跳转到该评论 */
|
|
@@ -4819,21 +4844,18 @@ class CommentActions {
|
|
|
4819
4844
|
window.dispatchEvent(new Event("hashchange"));
|
|
4820
4845
|
}
|
|
4821
4846
|
}
|
|
4822
|
-
class CommentNode
|
|
4823
|
-
//
|
|
4824
|
-
constructor(
|
|
4825
|
-
|
|
4847
|
+
class CommentNode {
|
|
4848
|
+
// 当前嵌套层数
|
|
4849
|
+
constructor(data, opts) {
|
|
4850
|
+
__publicField(this, "$el");
|
|
4826
4851
|
__publicField(this, "renderInstance");
|
|
4827
4852
|
__publicField(this, "actionInstance");
|
|
4828
4853
|
__publicField(this, "data");
|
|
4829
|
-
__publicField(this, "
|
|
4854
|
+
__publicField(this, "opts");
|
|
4830
4855
|
__publicField(this, "parent");
|
|
4831
4856
|
__publicField(this, "children", []);
|
|
4832
4857
|
__publicField(this, "nestCurt");
|
|
4833
|
-
|
|
4834
|
-
__publicField(this, "nestMax");
|
|
4835
|
-
this.nestMax = ctx.conf.nestMax || 3;
|
|
4836
|
-
this.cConf = conf;
|
|
4858
|
+
this.opts = opts;
|
|
4837
4859
|
this.data = __spreadValues({}, data);
|
|
4838
4860
|
this.data.date = this.data.date.replace(/-/g, "/");
|
|
4839
4861
|
this.parent = null;
|
|
@@ -4847,8 +4869,8 @@ class CommentNode extends Component {
|
|
|
4847
4869
|
if (this.$el)
|
|
4848
4870
|
this.$el.replaceWith(newEl);
|
|
4849
4871
|
this.$el = newEl;
|
|
4850
|
-
if (this.
|
|
4851
|
-
this.
|
|
4872
|
+
if (this.opts.onAfterRender)
|
|
4873
|
+
this.opts.onAfterRender();
|
|
4852
4874
|
}
|
|
4853
4875
|
/** 获取评论操作实例对象 */
|
|
4854
4876
|
getActions() {
|
|
@@ -4889,51 +4911,76 @@ class CommentNode extends Component {
|
|
|
4889
4911
|
return this.data.id;
|
|
4890
4912
|
}
|
|
4891
4913
|
/** 置入子评论 */
|
|
4892
|
-
putChild(
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
this.children.push(
|
|
4896
|
-
const $
|
|
4914
|
+
putChild(childNode, insertMode = "append") {
|
|
4915
|
+
childNode.parent = this;
|
|
4916
|
+
childNode.nestCurt = this.nestCurt + 1;
|
|
4917
|
+
this.children.push(childNode);
|
|
4918
|
+
const $childrenWrap = this.getChildrenWrapEl();
|
|
4919
|
+
const $childComment = childNode.getEl();
|
|
4897
4920
|
if (insertMode === "append")
|
|
4898
|
-
$
|
|
4921
|
+
$childrenWrap.append($childComment);
|
|
4899
4922
|
else if (insertMode === "prepend")
|
|
4900
|
-
$
|
|
4901
|
-
|
|
4902
|
-
|
|
4923
|
+
$childrenWrap.prepend($childComment);
|
|
4924
|
+
childNode.getRender().playFadeAnim();
|
|
4925
|
+
childNode.getRender().checkHeightLimit();
|
|
4903
4926
|
}
|
|
4904
4927
|
/** 获取存放子评论的元素对象 */
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
if (this.nestCurt < this.nestMax) {
|
|
4909
|
-
$children = this.getRender().renderChildrenWrap();
|
|
4910
|
-
} else {
|
|
4911
|
-
$children = this.parent.getChildrenEl();
|
|
4912
|
-
}
|
|
4928
|
+
getChildrenWrapEl() {
|
|
4929
|
+
if (this.nestCurt >= this.opts.nestMax) {
|
|
4930
|
+
return this.parent.getChildrenWrapEl();
|
|
4913
4931
|
}
|
|
4914
|
-
return
|
|
4932
|
+
return this.getRender().getChildrenWrap();
|
|
4915
4933
|
}
|
|
4916
4934
|
/** 获取所有父评论 */
|
|
4917
4935
|
getParents() {
|
|
4918
|
-
const
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
once(this);
|
|
4926
|
-
return parents;
|
|
4936
|
+
const flattenParents = [];
|
|
4937
|
+
let parent = this.parent;
|
|
4938
|
+
while (parent) {
|
|
4939
|
+
flattenParents.push(parent);
|
|
4940
|
+
parent = parent.getParent();
|
|
4941
|
+
}
|
|
4942
|
+
return flattenParents;
|
|
4927
4943
|
}
|
|
4928
|
-
/**
|
|
4944
|
+
/**
|
|
4945
|
+
* Get the element of the comment
|
|
4946
|
+
*
|
|
4947
|
+
* The `getEl()` will always return the latest $el after calling `render()`.
|
|
4948
|
+
* Please be aware of the memory leak if you use the $el reference directly.
|
|
4949
|
+
*/
|
|
4929
4950
|
getEl() {
|
|
4951
|
+
if (!this.$el)
|
|
4952
|
+
throw new Error("comment element not initialized before `getEl()`");
|
|
4930
4953
|
return this.$el;
|
|
4931
4954
|
}
|
|
4955
|
+
/**
|
|
4956
|
+
* Focus on the comment
|
|
4957
|
+
*
|
|
4958
|
+
* Scroll to the comment and perform flash animation
|
|
4959
|
+
*/
|
|
4960
|
+
focus() {
|
|
4961
|
+
if (!this.$el)
|
|
4962
|
+
throw new Error("comment element not initialized before `focus()`");
|
|
4963
|
+
this.getParents().forEach((p) => {
|
|
4964
|
+
p.getRender().heightLimitRemoveForChildren();
|
|
4965
|
+
});
|
|
4966
|
+
this.scrollIntoView();
|
|
4967
|
+
this.getRender().playFlashAnim();
|
|
4968
|
+
}
|
|
4969
|
+
scrollIntoView() {
|
|
4970
|
+
this.$el && scrollIntoView(this.$el, false, this.opts.scrollRelativeTo && this.opts.scrollRelativeTo());
|
|
4971
|
+
}
|
|
4972
|
+
/**
|
|
4973
|
+
* Remove the comment node
|
|
4974
|
+
*/
|
|
4975
|
+
remove() {
|
|
4976
|
+
var _a;
|
|
4977
|
+
(_a = this.$el) == null ? void 0 : _a.remove();
|
|
4978
|
+
}
|
|
4932
4979
|
/** 获取 Gravatar 头像 URL */
|
|
4933
4980
|
getGravatarURL() {
|
|
4934
4981
|
return getGravatarURL({
|
|
4935
|
-
mirror: this.
|
|
4936
|
-
params: this.
|
|
4982
|
+
mirror: this.opts.gravatar.mirror,
|
|
4983
|
+
params: this.opts.gravatar.params,
|
|
4937
4984
|
emailMD5: this.data.email_encrypted
|
|
4938
4985
|
});
|
|
4939
4986
|
}
|
|
@@ -4943,7 +4990,7 @@ class CommentNode extends Component {
|
|
|
4943
4990
|
}
|
|
4944
4991
|
/** 获取格式化后的日期 */
|
|
4945
4992
|
getDateFormatted() {
|
|
4946
|
-
return timeAgo(new Date(this.data.date),
|
|
4993
|
+
return timeAgo(new Date(this.data.date), t);
|
|
4947
4994
|
}
|
|
4948
4995
|
/** 获取用户 UserAgent 信息 */
|
|
4949
4996
|
getUserUA() {
|
|
@@ -4954,21 +5001,33 @@ class CommentNode extends Component {
|
|
|
4954
5001
|
};
|
|
4955
5002
|
}
|
|
4956
5003
|
/** 获取配置 */
|
|
4957
|
-
|
|
4958
|
-
return this.
|
|
5004
|
+
getOpts() {
|
|
5005
|
+
return this.opts;
|
|
4959
5006
|
}
|
|
4960
5007
|
}
|
|
4961
|
-
function
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
isFlatMode: (_a = ctx.getData().getListLastFetch()) == null ? void 0 : _a.params.flatMode,
|
|
4965
|
-
afterRender: () => {
|
|
5008
|
+
function createCommentNode(ctx, comment, replyComment, opts) {
|
|
5009
|
+
const instance2 = new CommentNode(comment, {
|
|
5010
|
+
onAfterRender: () => {
|
|
4966
5011
|
ctx.trigger("comment-rendered", instance2);
|
|
4967
5012
|
},
|
|
4968
5013
|
onDelete: (c) => {
|
|
4969
5014
|
ctx.getData().deleteComment(c.getID());
|
|
4970
5015
|
},
|
|
4971
|
-
replyTo:
|
|
5016
|
+
replyTo: replyComment,
|
|
5017
|
+
// TODO simplify reference
|
|
5018
|
+
flatMode: typeof (opts == null ? void 0 : opts.forceFlatMode) === "boolean" ? opts == null ? void 0 : opts.forceFlatMode : ctx.conf.flatMode,
|
|
5019
|
+
gravatar: ctx.conf.gravatar,
|
|
5020
|
+
nestMax: ctx.conf.nestMax,
|
|
5021
|
+
heightLimit: ctx.conf.heightLimit,
|
|
5022
|
+
avatarURLBuilder: ctx.conf.avatarURLBuilder,
|
|
5023
|
+
scrollRelativeTo: ctx.conf.scrollRelativeTo,
|
|
5024
|
+
vote: ctx.conf.vote,
|
|
5025
|
+
voteDown: ctx.conf.voteDown,
|
|
5026
|
+
uaBadge: ctx.conf.uaBadge,
|
|
5027
|
+
// TODO: move to plugin folder and remove from core
|
|
5028
|
+
getApi: () => ctx.getApi(),
|
|
5029
|
+
replyComment: (c, $el) => ctx.replyComment(c, $el),
|
|
5030
|
+
editComment: (c, $el) => ctx.editComment(c, $el)
|
|
4972
5031
|
});
|
|
4973
5032
|
instance2.render();
|
|
4974
5033
|
return instance2;
|
|
@@ -5344,20 +5403,19 @@ class List extends Component {
|
|
|
5344
5403
|
getCommentNodes() {
|
|
5345
5404
|
return this.commentNodes;
|
|
5346
5405
|
}
|
|
5347
|
-
getListLayout() {
|
|
5406
|
+
getListLayout({ forceFlatMode } = {}) {
|
|
5348
5407
|
return new ListLayout({
|
|
5349
5408
|
$commentsWrap: this.$commentsWrap,
|
|
5350
5409
|
nestSortBy: this.ctx.conf.nestSort,
|
|
5351
5410
|
nestMax: this.ctx.conf.nestMax,
|
|
5352
|
-
flatMode: this.ctx.conf.flatMode,
|
|
5411
|
+
flatMode: typeof forceFlatMode === "boolean" ? forceFlatMode : this.ctx.conf.flatMode,
|
|
5353
5412
|
// flatMode must be boolean because it had been handled when Artalk.init
|
|
5354
|
-
createCommentNode: (d,
|
|
5355
|
-
const node =
|
|
5413
|
+
createCommentNode: (d, r) => {
|
|
5414
|
+
const node = createCommentNode(this.ctx, d, r, { forceFlatMode });
|
|
5356
5415
|
this.commentNodes.push(node);
|
|
5357
5416
|
return node;
|
|
5358
5417
|
},
|
|
5359
|
-
findCommentNode: (id) => this.commentNodes.find((c) => c.getID() === id)
|
|
5360
|
-
getCommentDataList: () => this.ctx.getData().getComments()
|
|
5418
|
+
findCommentNode: (id) => this.commentNodes.find((c) => c.getID() === id)
|
|
5361
5419
|
});
|
|
5362
5420
|
}
|
|
5363
5421
|
initCrudEvents() {
|
|
@@ -5365,8 +5423,10 @@ class List extends Component {
|
|
|
5365
5423
|
this.getListLayout().import(comments);
|
|
5366
5424
|
});
|
|
5367
5425
|
this.ctx.on("list-loaded", (comments) => {
|
|
5368
|
-
if (comments.length === 0)
|
|
5426
|
+
if (comments.length === 0) {
|
|
5427
|
+
this.commentNodes = [];
|
|
5369
5428
|
this.$commentsWrap.innerHTML = "";
|
|
5429
|
+
}
|
|
5370
5430
|
});
|
|
5371
5431
|
this.ctx.on("comment-inserted", (comment) => {
|
|
5372
5432
|
this.getListLayout().insert(comment);
|
|
@@ -5377,7 +5437,7 @@ class List extends Component {
|
|
|
5377
5437
|
console.error(`comment node id=${comment.id} not found`);
|
|
5378
5438
|
return;
|
|
5379
5439
|
}
|
|
5380
|
-
node.
|
|
5440
|
+
node.remove();
|
|
5381
5441
|
this.commentNodes = this.commentNodes.filter((c) => c.getID() !== comment.id);
|
|
5382
5442
|
});
|
|
5383
5443
|
this.ctx.on("comment-updated", (comment) => {
|
|
@@ -5894,15 +5954,16 @@ class StateReply extends EditorPlug {
|
|
|
5894
5954
|
}
|
|
5895
5955
|
setReply(commentData) {
|
|
5896
5956
|
const ui = this.kit.useUI();
|
|
5897
|
-
if (!ui.$
|
|
5898
|
-
|
|
5899
|
-
`<
|
|
5957
|
+
if (!ui.$sendReplyBtn) {
|
|
5958
|
+
const $btn = createElement(
|
|
5959
|
+
`<span class="atk-state-btn"><span class="atk-text-wrap">${t("reply")} <span class="atk-text"></span></span><span class="atk-cancel">×</span></span>`
|
|
5900
5960
|
);
|
|
5901
|
-
|
|
5902
|
-
|
|
5961
|
+
$btn.querySelector(".atk-text").innerText = `@${commentData.nick}`;
|
|
5962
|
+
$btn.addEventListener("click", () => {
|
|
5903
5963
|
this.kit.useEditor().resetState();
|
|
5904
5964
|
});
|
|
5905
|
-
ui.$
|
|
5965
|
+
ui.$stateWrap.append($btn);
|
|
5966
|
+
ui.$sendReplyBtn = $btn;
|
|
5906
5967
|
}
|
|
5907
5968
|
this.comment = commentData;
|
|
5908
5969
|
ui.$textarea.focus();
|
|
@@ -5911,9 +5972,9 @@ class StateReply extends EditorPlug {
|
|
|
5911
5972
|
if (!this.comment)
|
|
5912
5973
|
return;
|
|
5913
5974
|
const ui = this.kit.useUI();
|
|
5914
|
-
if (ui.$
|
|
5915
|
-
ui.$
|
|
5916
|
-
ui.$
|
|
5975
|
+
if (ui.$sendReplyBtn) {
|
|
5976
|
+
ui.$sendReplyBtn.remove();
|
|
5977
|
+
ui.$sendReplyBtn = void 0;
|
|
5917
5978
|
}
|
|
5918
5979
|
this.comment = void 0;
|
|
5919
5980
|
}
|
|
@@ -5960,12 +6021,12 @@ class StateEdit extends EditorPlug {
|
|
|
5960
6021
|
const ui = this.kit.useUI();
|
|
5961
6022
|
if (!ui.$editCancelBtn) {
|
|
5962
6023
|
const $btn = createElement(
|
|
5963
|
-
`<
|
|
6024
|
+
`<span class="atk-state-btn"><span class="atk-text-wrap">${t("editCancel")}</span><span class="atk-cancel">×</span></span>`
|
|
5964
6025
|
);
|
|
5965
6026
|
$btn.onclick = () => {
|
|
5966
6027
|
this.kit.useEditor().resetState();
|
|
5967
6028
|
};
|
|
5968
|
-
ui.$
|
|
6029
|
+
ui.$stateWrap.append($btn);
|
|
5969
6030
|
ui.$editCancelBtn = $btn;
|
|
5970
6031
|
}
|
|
5971
6032
|
this.comment = comment;
|
|
@@ -6162,7 +6223,7 @@ class Emoticons extends EditorPlug {
|
|
|
6162
6223
|
__publicField(this, "isImgLoaded", false);
|
|
6163
6224
|
this.kit.useMounted(() => {
|
|
6164
6225
|
this.usePanel(`<div class="atk-editor-plug-emoticons"></div>`);
|
|
6165
|
-
this.useBtn(t("emoticon"));
|
|
6226
|
+
this.useBtn(`<i aria-label="${t("emoticon")}"><svg fill="currentColor" aria-hidden="true" height="14" viewBox="0 0 14 14" width="14"><path d="m4.26829 5.29294c0-.94317.45893-1.7074 1.02439-1.7074.56547 0 1.02439.76423 1.02439 1.7074s-.45892 1.7074-1.02439 1.7074c-.56546 0-1.02439-.76423-1.02439-1.7074zm4.43903 1.7074c.56546 0 1.02439-.76423 1.02439-1.7074s-.45893-1.7074-1.02439-1.7074c-.56547 0-1.02439.76423-1.02439 1.7074s.45892 1.7074 1.02439 1.7074zm-1.70732 2.73184c-1.51883 0-2.06312-1.52095-2.08361-1.58173l-1.29551.43231c.03414.10244.868 2.51604 3.3798 2.51604 2.51181 0 3.34502-2.41291 3.37982-2.51604l-1.29484-.43573c-.02254.06488-.56683 1.58583-2.08498 1.58583zm7-2.73252c0 3.86004-3.1401 7.00034-7 7.00034s-7-3.1396-7-6.99966c0-3.86009 3.1401-7.00034 7-7.00034s7 3.14025 7 7.00034zm-1.3659 0c0-3.10679-2.5275-5.63442-5.6341-5.63442-3.10663 0-5.63415 2.52832-5.63415 5.6351 0 3.10676 2.52752 5.63446 5.63415 5.63446 3.1066 0 5.6341-2.5277 5.6341-5.63446z"/></svg></i>`);
|
|
6166
6227
|
});
|
|
6167
6228
|
this.kit.useUnmounted(() => {
|
|
6168
6229
|
});
|
|
@@ -6413,7 +6474,7 @@ class Upload extends EditorPlug {
|
|
|
6413
6474
|
this.$imgUploadInput.type = "file";
|
|
6414
6475
|
this.$imgUploadInput.style.display = "none";
|
|
6415
6476
|
this.$imgUploadInput.accept = AllowImgExts.map((o) => `.${o}`).join(",");
|
|
6416
|
-
const $btn = this.useBtn(
|
|
6477
|
+
const $btn = this.useBtn(`<i aria-label="${t("uploadImage")}"><svg fill="currentColor" aria-hidden="true" height="14" viewBox="0 0 14 14" width="14"><path d="m0 1.94444c0-1.074107.870333-1.94444 1.94444-1.94444h10.11116c1.0741 0 1.9444.870333 1.9444 1.94444v10.11116c0 1.0741-.8703 1.9444-1.9444 1.9444h-10.11116c-1.074107 0-1.94444-.8703-1.94444-1.9444zm1.94444-.38888c-.21466 0-.38888.17422-.38888.38888v7.06689l2.33333-2.33333 2.33333 2.33333 3.88888-3.88889 2.3333 2.33334v-5.51134c0-.21466-.1742-.38888-.3888-.38888zm10.49996 8.09977-2.3333-2.33333-3.88888 3.8889-2.33333-2.33334-2.33333 2.33334v.8447c0 .2146.17422.3888.38888.3888h10.11116c.2146 0 .3888-.1742.3888-.3888zm-7.1944-6.54422c-.75133 0-1.36111.60978-1.36111 1.36111 0 .75134.60978 1.36111 1.36111 1.36111s1.36111-.60977 1.36111-1.36111c0-.75133-.60978-1.36111-1.36111-1.36111z"/></svg></i>`);
|
|
6417
6478
|
$btn.after(this.$imgUploadInput);
|
|
6418
6479
|
$btn.onclick = () => {
|
|
6419
6480
|
const $input = this.$imgUploadInput;
|
|
@@ -6517,10 +6578,7 @@ class Preview extends EditorPlug {
|
|
|
6517
6578
|
__publicField(this, "isPlugPanelShow", false);
|
|
6518
6579
|
this.kit.useMounted(() => {
|
|
6519
6580
|
this.usePanel(`<div class="atk-editor-plug-preview"></div>`);
|
|
6520
|
-
|
|
6521
|
-
if (getInstance())
|
|
6522
|
-
btnText += ` <i title="Markdown is supported"><svg class="markdown" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path></svg></i>`;
|
|
6523
|
-
this.useBtn(btnText);
|
|
6581
|
+
this.useBtn(`<i aria-label="${t("preview")}"><svg fill="currentColor" aria-hidden="true" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M14.85 3H1.15C.52 3 0 3.52 0 4.15v7.69C0 12.48.52 13 1.15 13h13.69c.64 0 1.15-.52 1.15-1.15v-7.7C16 3.52 15.48 3 14.85 3zM9 11H7V8L5.5 9.92 4 8v3H2V5h2l1.5 2L7 5h2v6zm2.99.5L9.5 8H11V5h2v3h1.5l-2.51 3.5z"></path></svg></i>`);
|
|
6524
6582
|
});
|
|
6525
6583
|
this.kit.useUnmounted(() => {
|
|
6526
6584
|
});
|
|
@@ -6862,62 +6920,50 @@ const UnreadBadge = (ctx) => {
|
|
|
6862
6920
|
showUnreadBadge(notifies.length || 0);
|
|
6863
6921
|
});
|
|
6864
6922
|
};
|
|
6865
|
-
const
|
|
6866
|
-
let
|
|
6867
|
-
const check2 = () => {
|
|
6923
|
+
const GotoDispatcher = (ctx) => {
|
|
6924
|
+
let lastID = 0;
|
|
6925
|
+
const check2 = ({ locker }) => {
|
|
6868
6926
|
const commentID = extractCommentID();
|
|
6869
6927
|
if (!commentID)
|
|
6870
6928
|
return;
|
|
6929
|
+
if (locker && lastID === commentID)
|
|
6930
|
+
return;
|
|
6931
|
+
lastID = commentID;
|
|
6871
6932
|
ctx.trigger("list-goto", commentID);
|
|
6872
|
-
delayGoto = true;
|
|
6873
|
-
};
|
|
6874
|
-
const hashChangeHandler = () => {
|
|
6875
|
-
delayGoto = false;
|
|
6876
|
-
check2();
|
|
6877
6933
|
};
|
|
6934
|
+
const hashChangeHandler = () => check2({ locker: false });
|
|
6935
|
+
const listLoadedHandler = () => check2({ locker: true });
|
|
6878
6936
|
ctx.on("mounted", () => {
|
|
6879
6937
|
window.addEventListener("hashchange", hashChangeHandler);
|
|
6880
|
-
ctx.on("list-loaded",
|
|
6938
|
+
ctx.on("list-loaded", listLoadedHandler);
|
|
6881
6939
|
});
|
|
6882
6940
|
ctx.on("unmounted", () => {
|
|
6883
6941
|
window.removeEventListener("hashchange", hashChangeHandler);
|
|
6884
|
-
ctx.off("list-loaded",
|
|
6885
|
-
});
|
|
6886
|
-
let foundID = 0;
|
|
6887
|
-
ctx.on("list-goto", (commentID) => {
|
|
6888
|
-
if (foundID === commentID)
|
|
6889
|
-
return;
|
|
6890
|
-
const comment = ctx.get("list").getCommentNodes().find((c) => c.getID() === commentID);
|
|
6891
|
-
if (!comment)
|
|
6892
|
-
return;
|
|
6893
|
-
foundID = commentID;
|
|
6894
|
-
comment.getParents().forEach((p) => {
|
|
6895
|
-
p.getRender().heightLimitRemoveForChildren();
|
|
6896
|
-
});
|
|
6897
|
-
const goTo = () => {
|
|
6898
|
-
scrollIntoView(comment.getEl(), false);
|
|
6899
|
-
comment.getEl().classList.remove("atk-flash-once");
|
|
6900
|
-
window.setTimeout(() => {
|
|
6901
|
-
comment.getEl().classList.add("atk-flash-once");
|
|
6902
|
-
}, 150);
|
|
6903
|
-
};
|
|
6904
|
-
if (!delayGoto)
|
|
6905
|
-
goTo();
|
|
6906
|
-
else
|
|
6907
|
-
window.setTimeout(() => goTo(), 350);
|
|
6942
|
+
ctx.off("list-loaded", listLoadedHandler);
|
|
6908
6943
|
});
|
|
6909
6944
|
};
|
|
6910
6945
|
function extractCommentID() {
|
|
6911
|
-
|
|
6946
|
+
const match = window.location.hash.match(/#atk-comment-([0-9]+)/);
|
|
6947
|
+
let commentId = match && match[1] && !Number.isNaN(parseFloat(match[1])) ? parseFloat(match[1]) : null;
|
|
6912
6948
|
if (!commentId) {
|
|
6913
|
-
|
|
6914
|
-
if (!match || !match[1] || Number.isNaN(Number(match[1])))
|
|
6915
|
-
return null;
|
|
6916
|
-
commentId = Number(match[1]);
|
|
6949
|
+
commentId = Number(getQueryParam("atk_comment"));
|
|
6917
6950
|
}
|
|
6918
6951
|
return commentId || null;
|
|
6919
6952
|
}
|
|
6920
|
-
const
|
|
6953
|
+
const GotoFocus = (ctx) => {
|
|
6954
|
+
ctx.on("list-goto", (commentID) => __async(void 0, null, function* () {
|
|
6955
|
+
let comment = ctx.getCommentNodes().find((c) => c.getID() === commentID);
|
|
6956
|
+
if (!comment) {
|
|
6957
|
+
const data = (yield ctx.getApi().comments.getComment(commentID)).data;
|
|
6958
|
+
ctx.get("list").getListLayout({ forceFlatMode: true }).insert(data.comment, data.reply_comment);
|
|
6959
|
+
comment = ctx.getCommentNodes().find((c) => c.getID() === commentID);
|
|
6960
|
+
}
|
|
6961
|
+
if (!comment)
|
|
6962
|
+
return;
|
|
6963
|
+
comment.focus();
|
|
6964
|
+
}));
|
|
6965
|
+
};
|
|
6966
|
+
const version = "2.8.2";
|
|
6921
6967
|
const Copyright = (ctx) => {
|
|
6922
6968
|
ctx.on("mounted", () => {
|
|
6923
6969
|
const list = ctx.get("list");
|
|
@@ -6928,14 +6974,7 @@ const Copyright = (ctx) => {
|
|
|
6928
6974
|
});
|
|
6929
6975
|
};
|
|
6930
6976
|
const NoComment = (ctx) => {
|
|
6931
|
-
let isFetching = false;
|
|
6932
|
-
ctx.on("list-fetch", (params) => {
|
|
6933
|
-
isFetching = true;
|
|
6934
|
-
});
|
|
6935
6977
|
ctx.on("list-loaded", (comments) => {
|
|
6936
|
-
if (!isFetching)
|
|
6937
|
-
return;
|
|
6938
|
-
isFetching = false;
|
|
6939
6978
|
const list = ctx.get("list");
|
|
6940
6979
|
const isNoComment = comments.length <= 0;
|
|
6941
6980
|
let $noComment = list.getCommentsWrapEl().querySelector(".atk-list-no-comment");
|
|
@@ -7187,7 +7226,8 @@ const ListPlugins = [
|
|
|
7187
7226
|
SidebarBtn,
|
|
7188
7227
|
UnreadBadge,
|
|
7189
7228
|
Dropdown,
|
|
7190
|
-
|
|
7229
|
+
GotoDispatcher,
|
|
7230
|
+
GotoFocus,
|
|
7191
7231
|
NoComment,
|
|
7192
7232
|
Copyright,
|
|
7193
7233
|
TimeTicking,
|
|
@@ -7211,6 +7251,7 @@ const PvCountWidget = (ctx) => {
|
|
|
7211
7251
|
ctx.watchConf([
|
|
7212
7252
|
"site",
|
|
7213
7253
|
"pageKey",
|
|
7254
|
+
"pageTitle",
|
|
7214
7255
|
"countEl",
|
|
7215
7256
|
"pvEl"
|
|
7216
7257
|
], (conf) => {
|
|
@@ -7218,6 +7259,7 @@ const PvCountWidget = (ctx) => {
|
|
|
7218
7259
|
getApi: () => ctx.getApi(),
|
|
7219
7260
|
siteName: conf.site,
|
|
7220
7261
|
pageKey: conf.pageKey,
|
|
7262
|
+
pageTitle: conf.pageTitle,
|
|
7221
7263
|
countEl: conf.countEl,
|
|
7222
7264
|
pvEl: conf.pvEl,
|
|
7223
7265
|
pvAdd: typeof ctx.conf.pvAdd === "boolean" ? ctx.conf.pvAdd : true
|
|
@@ -7229,10 +7271,10 @@ function initCountWidget(opt) {
|
|
|
7229
7271
|
if (opt.countEl && document.querySelector(opt.countEl)) {
|
|
7230
7272
|
refreshStatCount(opt, { query: "page_comment", numEl: opt.countEl });
|
|
7231
7273
|
}
|
|
7232
|
-
const initialData = opt.pvAdd ? {
|
|
7274
|
+
const initialData = opt.pvAdd && opt.pageKey ? {
|
|
7233
7275
|
[opt.pageKey]: (yield opt.getApi().pages.logPv({
|
|
7234
7276
|
page_key: opt.pageKey,
|
|
7235
|
-
page_title: opt.
|
|
7277
|
+
page_title: opt.pageTitle,
|
|
7236
7278
|
site_name: opt.siteName
|
|
7237
7279
|
})).data.pv
|
|
7238
7280
|
// pv+1 and get pv count
|
|
@@ -7249,7 +7291,7 @@ function initCountWidget(opt) {
|
|
|
7249
7291
|
function refreshStatCount(opt, args) {
|
|
7250
7292
|
return __async(this, null, function* () {
|
|
7251
7293
|
let data = args.data || {};
|
|
7252
|
-
let queryPageKeys = Array.from(document.querySelectorAll(args.numEl)).map((e) => e.getAttribute("data-page-key") || opt.pageKey).filter((k) => typeof data[k] !== "number");
|
|
7294
|
+
let queryPageKeys = Array.from(document.querySelectorAll(args.numEl)).map((e) => e.getAttribute("data-page-key") || opt.pageKey).filter((k) => k && typeof data[k] !== "number");
|
|
7253
7295
|
queryPageKeys = [...new Set(queryPageKeys)];
|
|
7254
7296
|
if (queryPageKeys.length > 0) {
|
|
7255
7297
|
const res = (yield opt.getApi().stats.getStats(args.query, {
|
|
@@ -7258,7 +7300,8 @@ function refreshStatCount(opt, args) {
|
|
|
7258
7300
|
})).data.data;
|
|
7259
7301
|
data = __spreadValues(__spreadValues({}, data), res);
|
|
7260
7302
|
}
|
|
7261
|
-
|
|
7303
|
+
const defaultCount = opt.pageKey ? data[opt.pageKey] : 0;
|
|
7304
|
+
applyCountData(args.numEl, data, defaultCount);
|
|
7262
7305
|
});
|
|
7263
7306
|
}
|
|
7264
7307
|
function applyCountData(selector, data, defaultCount) {
|
|
@@ -7447,7 +7490,6 @@ class Artalk {
|
|
|
7447
7490
|
initCountWidget({
|
|
7448
7491
|
getApi: () => new Api2(convertApiOptions(conf)),
|
|
7449
7492
|
siteName: conf.site,
|
|
7450
|
-
pageKey: conf.pageKey,
|
|
7451
7493
|
countEl: conf.countEl,
|
|
7452
7494
|
pvEl: conf.pvEl,
|
|
7453
7495
|
pvAdd: false
|