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/Artalk.mjs
CHANGED
|
@@ -381,6 +381,29 @@ let Api$1 = class Api extends HttpClient {
|
|
|
381
381
|
type: "application/json",
|
|
382
382
|
format: "json"
|
|
383
383
|
}, params)),
|
|
384
|
+
/**
|
|
385
|
+
* @description Get the detail of a comment by comment id
|
|
386
|
+
*
|
|
387
|
+
* @tags Comment
|
|
388
|
+
* @name GetComment
|
|
389
|
+
* @summary Get a comment
|
|
390
|
+
* @request GET:/comments/{id}
|
|
391
|
+
* @response `200` `HandlerResponseCommentGet` OK
|
|
392
|
+
* @response `404` `(HandlerMap & {
|
|
393
|
+
msg?: string,
|
|
394
|
+
|
|
395
|
+
})` Not Found
|
|
396
|
+
* @response `500` `(HandlerMap & {
|
|
397
|
+
msg?: string,
|
|
398
|
+
|
|
399
|
+
})` Internal Server Error
|
|
400
|
+
*/
|
|
401
|
+
getComment: (id, params = {}) => this.request(__spreadValues({
|
|
402
|
+
path: `/comments/${id}`,
|
|
403
|
+
method: "GET",
|
|
404
|
+
type: "application/json",
|
|
405
|
+
format: "json"
|
|
406
|
+
}, params)),
|
|
384
407
|
/**
|
|
385
408
|
* @description Update a specific comment
|
|
386
409
|
*
|
|
@@ -4470,7 +4493,7 @@ const en = {
|
|
|
4470
4493
|
link: "Website",
|
|
4471
4494
|
emoticon: "Emoji",
|
|
4472
4495
|
preview: "Preview",
|
|
4473
|
-
|
|
4496
|
+
uploadImage: "Upload Image",
|
|
4474
4497
|
uploadFail: "Upload Failed",
|
|
4475
4498
|
commentFail: "Failed to comment",
|
|
4476
4499
|
restoredMsg: "Content has been restored",
|
|
@@ -4543,14 +4566,14 @@ const zhCN = {
|
|
|
4543
4566
|
/* Editor */
|
|
4544
4567
|
placeholder: "键入内容...",
|
|
4545
4568
|
noComment: "「此时无声胜有声」",
|
|
4546
|
-
send: "
|
|
4547
|
-
save: "
|
|
4569
|
+
send: "发送",
|
|
4570
|
+
save: "保存",
|
|
4548
4571
|
nick: "昵称",
|
|
4549
4572
|
email: "邮箱",
|
|
4550
4573
|
link: "网址",
|
|
4551
4574
|
emoticon: "表情",
|
|
4552
4575
|
preview: "预览",
|
|
4553
|
-
|
|
4576
|
+
uploadImage: "上传图片",
|
|
4554
4577
|
uploadFail: "上传失败",
|
|
4555
4578
|
commentFail: "评论失败",
|
|
4556
4579
|
restoredMsg: "内容已自动恢复",
|
|
@@ -5152,7 +5175,7 @@ function showLoading(parentElem, conf) {
|
|
|
5152
5175
|
let $loading = parentElem.querySelector(":scope > .atk-loading");
|
|
5153
5176
|
if (!$loading) {
|
|
5154
5177
|
$loading = createElement(
|
|
5155
|
-
`<div class="atk-loading
|
|
5178
|
+
`<div class="atk-loading" style="display: none;">
|
|
5156
5179
|
<div class="atk-loading-spinner">
|
|
5157
5180
|
<svg viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"></circle></svg>
|
|
5158
5181
|
</div>
|
|
@@ -5167,7 +5190,8 @@ function showLoading(parentElem, conf) {
|
|
|
5167
5190
|
if ($spinner) {
|
|
5168
5191
|
$spinner.style.display = "none";
|
|
5169
5192
|
window.setTimeout(() => {
|
|
5170
|
-
$spinner.
|
|
5193
|
+
if ($spinner.isConnected)
|
|
5194
|
+
$spinner.style.display = "";
|
|
5171
5195
|
}, 500);
|
|
5172
5196
|
}
|
|
5173
5197
|
}
|
|
@@ -5187,8 +5211,7 @@ function scrollIntoView(elem, enableAnim = true, relativeTo) {
|
|
|
5187
5211
|
if (relativeTo) {
|
|
5188
5212
|
const containerRect = relativeTo.getBoundingClientRect();
|
|
5189
5213
|
const elementRect = elem.getBoundingClientRect();
|
|
5190
|
-
top = elementRect.top - containerRect.top + relativeTo.scrollTop;
|
|
5191
|
-
top += getHeight(relativeTo) / 2 - getHeight(elem) / 2;
|
|
5214
|
+
top = elementRect.top - containerRect.top + relativeTo.scrollTop - relativeTo.clientHeight / 2 + elem.clientHeight / 2;
|
|
5192
5215
|
} else {
|
|
5193
5216
|
const rect = elem.getBoundingClientRect();
|
|
5194
5217
|
const elemTop = rect.top + window.scrollY;
|
|
@@ -5522,8 +5545,11 @@ class Component {
|
|
|
5522
5545
|
get conf() {
|
|
5523
5546
|
return this.ctx.conf;
|
|
5524
5547
|
}
|
|
5548
|
+
getEl() {
|
|
5549
|
+
return this.$el;
|
|
5550
|
+
}
|
|
5525
5551
|
}
|
|
5526
|
-
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';
|
|
5552
|
+
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';
|
|
5527
5553
|
const Sel = {
|
|
5528
5554
|
$header: ".atk-header",
|
|
5529
5555
|
$nick: '.atk-header [name="nick"]',
|
|
@@ -5534,6 +5560,8 @@ const Sel = {
|
|
|
5534
5560
|
$bottom: ".atk-bottom",
|
|
5535
5561
|
$submitBtn: ".atk-send-btn",
|
|
5536
5562
|
$notifyWrap: ".atk-notify-wrap",
|
|
5563
|
+
$bottomLeft: ".atk-bottom-left",
|
|
5564
|
+
$stateWrap: ".atk-state-wrap",
|
|
5537
5565
|
$plugBtnWrap: ".atk-plug-btn-wrap",
|
|
5538
5566
|
$plugPanelWrap: ".atk-plug-panel-wrap"
|
|
5539
5567
|
};
|
|
@@ -5906,39 +5934,18 @@ function makeNestCommentNodeList(srcData, sortBy = "DATE_DESC", nestMax = 2) {
|
|
|
5906
5934
|
})(nodeList);
|
|
5907
5935
|
return nodeList;
|
|
5908
5936
|
}
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
}
|
|
5913
|
-
// TODO: refactor `if syntax` to strategy pattern
|
|
5914
|
-
import(comments) {
|
|
5915
|
-
if (this.options.flatMode) {
|
|
5916
|
-
comments.forEach((commentData) => {
|
|
5917
|
-
this.putCommentFlatMode(commentData, comments, "append");
|
|
5918
|
-
});
|
|
5919
|
-
} else {
|
|
5920
|
-
this.importCommentsNestMode(comments);
|
|
5921
|
-
}
|
|
5922
|
-
}
|
|
5923
|
-
insert(comment) {
|
|
5924
|
-
if (!this.options.flatMode) {
|
|
5925
|
-
this.insertCommentNest(comment);
|
|
5926
|
-
} else {
|
|
5927
|
-
this.insertCommentFlatMode(comment);
|
|
5928
|
-
}
|
|
5929
|
-
}
|
|
5930
|
-
// 导入评论 · 嵌套模式
|
|
5931
|
-
importCommentsNestMode(srcData) {
|
|
5932
|
-
const rootNodes = makeNestCommentNodeList(srcData, this.options.nestSortBy, this.options.nestMax);
|
|
5937
|
+
const createNestStrategy = (opts) => ({
|
|
5938
|
+
import: (comments) => {
|
|
5939
|
+
const rootNodes = makeNestCommentNodeList(comments, opts.nestSortBy, opts.nestMax);
|
|
5933
5940
|
rootNodes.forEach((rootNode) => {
|
|
5934
5941
|
var _a;
|
|
5935
|
-
const rootC =
|
|
5936
|
-
(_a =
|
|
5942
|
+
const rootC = opts.createCommentNode(rootNode.comment);
|
|
5943
|
+
(_a = opts.$commentsWrap) == null ? void 0 : _a.appendChild(rootC.getEl());
|
|
5937
5944
|
rootC.getRender().playFadeAnim();
|
|
5938
5945
|
const loadChildren = (parentC, parentNode) => {
|
|
5939
5946
|
parentNode.children.forEach((node) => {
|
|
5940
5947
|
const childD = node.comment;
|
|
5941
|
-
const childC =
|
|
5948
|
+
const childC = opts.createCommentNode(childD, parentC.getData());
|
|
5942
5949
|
parentC.putChild(childC);
|
|
5943
5950
|
loadChildren(childC, node);
|
|
5944
5951
|
});
|
|
@@ -5946,44 +5953,66 @@ class ListLayout {
|
|
|
5946
5953
|
loadChildren(rootC, rootNode);
|
|
5947
5954
|
rootC.getRender().checkHeightLimit();
|
|
5948
5955
|
});
|
|
5949
|
-
}
|
|
5950
|
-
|
|
5951
|
-
putCommentFlatMode(cData, ctxData, insertMode) {
|
|
5952
|
-
var _a, _b;
|
|
5953
|
-
if (cData.is_collapsed)
|
|
5954
|
-
cData.is_allow_reply = false;
|
|
5955
|
-
const comment = this.options.createCommentNode(cData, ctxData);
|
|
5956
|
-
if (cData.visible) {
|
|
5957
|
-
if (insertMode === "append")
|
|
5958
|
-
(_a = this.options.$commentsWrap) == null ? void 0 : _a.append(comment.getEl());
|
|
5959
|
-
if (insertMode === "prepend")
|
|
5960
|
-
(_b = this.options.$commentsWrap) == null ? void 0 : _b.prepend(comment.getEl());
|
|
5961
|
-
comment.getRender().playFadeAnim();
|
|
5962
|
-
}
|
|
5963
|
-
comment.getRender().checkHeightLimit();
|
|
5964
|
-
return comment;
|
|
5965
|
-
}
|
|
5966
|
-
insertCommentNest(commentData) {
|
|
5956
|
+
},
|
|
5957
|
+
insert: (comment, replyComment) => {
|
|
5967
5958
|
var _a;
|
|
5968
|
-
const
|
|
5969
|
-
if (
|
|
5970
|
-
(_a =
|
|
5959
|
+
const node = opts.createCommentNode(comment, replyComment);
|
|
5960
|
+
if (comment.rid === 0) {
|
|
5961
|
+
(_a = opts.$commentsWrap) == null ? void 0 : _a.prepend(node.getEl());
|
|
5971
5962
|
} else {
|
|
5972
|
-
const parent =
|
|
5963
|
+
const parent = opts.findCommentNode(comment.rid);
|
|
5973
5964
|
if (parent) {
|
|
5974
|
-
parent.putChild(
|
|
5975
|
-
|
|
5965
|
+
parent.putChild(node, opts.nestSortBy === "DATE_ASC" ? "append" : "prepend");
|
|
5966
|
+
node.getParents().forEach((p) => {
|
|
5976
5967
|
p.getRender().heightLimitRemoveForChildren();
|
|
5977
5968
|
});
|
|
5978
5969
|
}
|
|
5979
5970
|
}
|
|
5980
|
-
|
|
5981
|
-
scrollIntoView(
|
|
5982
|
-
|
|
5971
|
+
node.getRender().checkHeightLimit();
|
|
5972
|
+
node.scrollIntoView();
|
|
5973
|
+
node.getRender().playFadeAnim();
|
|
5974
|
+
}
|
|
5975
|
+
});
|
|
5976
|
+
const createFlatStrategy = (opts) => ({
|
|
5977
|
+
import: (comments) => {
|
|
5978
|
+
comments.forEach((comment) => {
|
|
5979
|
+
const replyComment = comment.rid === 0 ? void 0 : comments.find((c) => c.id === comment.rid);
|
|
5980
|
+
insertComment(opts, "append", comment, replyComment);
|
|
5981
|
+
});
|
|
5982
|
+
},
|
|
5983
|
+
insert: (comment, replyComment) => {
|
|
5984
|
+
const node = insertComment(opts, "prepend", comment, replyComment);
|
|
5985
|
+
node.scrollIntoView();
|
|
5986
|
+
}
|
|
5987
|
+
});
|
|
5988
|
+
function insertComment(opts, insertMode, comment, replyComment) {
|
|
5989
|
+
if (comment.is_collapsed)
|
|
5990
|
+
comment.is_allow_reply = false;
|
|
5991
|
+
const node = opts.createCommentNode(comment, replyComment);
|
|
5992
|
+
if (comment.visible) {
|
|
5993
|
+
const $comment = node.getEl();
|
|
5994
|
+
const $listCommentsWrap = opts.$commentsWrap;
|
|
5995
|
+
if (insertMode === "append")
|
|
5996
|
+
$listCommentsWrap == null ? void 0 : $listCommentsWrap.append($comment);
|
|
5997
|
+
if (insertMode === "prepend")
|
|
5998
|
+
$listCommentsWrap == null ? void 0 : $listCommentsWrap.prepend($comment);
|
|
5999
|
+
node.getRender().playFadeAnim();
|
|
6000
|
+
}
|
|
6001
|
+
node.getRender().checkHeightLimit();
|
|
6002
|
+
return node;
|
|
6003
|
+
}
|
|
6004
|
+
class ListLayout {
|
|
6005
|
+
constructor(options) {
|
|
6006
|
+
this.options = options;
|
|
6007
|
+
}
|
|
6008
|
+
getStrategy() {
|
|
6009
|
+
return this.options.flatMode ? createFlatStrategy(this.options) : createNestStrategy(this.options);
|
|
5983
6010
|
}
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
6011
|
+
import(comments) {
|
|
6012
|
+
this.getStrategy().import(comments);
|
|
6013
|
+
}
|
|
6014
|
+
insert(comment, replyComment) {
|
|
6015
|
+
this.getStrategy().insert(comment, replyComment);
|
|
5987
6016
|
}
|
|
5988
6017
|
}
|
|
5989
6018
|
function Detect(userAgent) {
|
|
@@ -6246,7 +6275,7 @@ const CommentHTML = '<div class="atk-comment-wrap">\n <div class="atk-comment">
|
|
|
6246
6275
|
function renderAvatar(r) {
|
|
6247
6276
|
const $avatar = r.$el.querySelector(".atk-avatar");
|
|
6248
6277
|
const $avatarImg = createElement("<img />");
|
|
6249
|
-
const avatarURLBuilder = r.
|
|
6278
|
+
const avatarURLBuilder = r.opts.avatarURLBuilder;
|
|
6250
6279
|
$avatarImg.src = avatarURLBuilder ? avatarURLBuilder(r.data) : r.comment.getGravatarURL();
|
|
6251
6280
|
if (r.data.link) {
|
|
6252
6281
|
const $avatarA = createElement('<a target="_blank" rel="noreferrer noopener nofollow"></a>');
|
|
@@ -6285,12 +6314,12 @@ function renderVerifyBadge(ctx) {
|
|
|
6285
6314
|
const badgeColor = ctx.data.badge_color;
|
|
6286
6315
|
if (badgeText) {
|
|
6287
6316
|
const $badge = createElement(`<span class="atk-badge"></span>`);
|
|
6288
|
-
$badge.innerText = badgeText.replace("管理员",
|
|
6317
|
+
$badge.innerText = badgeText.replace("管理员", t("admin"));
|
|
6289
6318
|
$badge.style.backgroundColor = badgeColor || "";
|
|
6290
6319
|
ctx.$headerBadgeWrap.append($badge);
|
|
6291
6320
|
}
|
|
6292
6321
|
if (ctx.data.is_pinned) {
|
|
6293
|
-
const $pinnedBadge = createElement(`<span class="atk-pinned-badge">${
|
|
6322
|
+
const $pinnedBadge = createElement(`<span class="atk-pinned-badge">${t("pin")}</span>`);
|
|
6294
6323
|
ctx.$headerBadgeWrap.append($pinnedBadge);
|
|
6295
6324
|
}
|
|
6296
6325
|
}
|
|
@@ -6300,7 +6329,7 @@ function renderDate(ctx) {
|
|
|
6300
6329
|
$date.setAttribute("data-atk-comment-date", String(+new Date(ctx.data.date)));
|
|
6301
6330
|
}
|
|
6302
6331
|
function renderUABadge(ctx) {
|
|
6303
|
-
if (!ctx.
|
|
6332
|
+
if (!ctx.opts.uaBadge && !ctx.data.ip_region)
|
|
6304
6333
|
return;
|
|
6305
6334
|
let $uaWrap = ctx.$header.querySelector("atk-ua-wrap");
|
|
6306
6335
|
if (!$uaWrap) {
|
|
@@ -6313,7 +6342,7 @@ function renderUABadge(ctx) {
|
|
|
6313
6342
|
$regionBadge.innerText = ctx.data.ip_region;
|
|
6314
6343
|
$uaWrap.append($regionBadge);
|
|
6315
6344
|
}
|
|
6316
|
-
if (ctx.
|
|
6345
|
+
if (ctx.opts.uaBadge) {
|
|
6317
6346
|
const { browser, os } = ctx.comment.getUserUA();
|
|
6318
6347
|
if (String(browser).trim()) {
|
|
6319
6348
|
const $uaBrowser = createElement(`<span class="atk-ua ua-browser"></span>`);
|
|
@@ -6336,8 +6365,8 @@ function renderContent(r) {
|
|
|
6336
6365
|
r.$content.classList.add("atk-hide", "atk-type-collapsed");
|
|
6337
6366
|
const collapsedInfoEl = createElement(`
|
|
6338
6367
|
<div class="atk-collapsed">
|
|
6339
|
-
<span class="atk-text">${
|
|
6340
|
-
<span class="atk-show-btn">${
|
|
6368
|
+
<span class="atk-text">${t("collapsedMsg")}</span>
|
|
6369
|
+
<span class="atk-show-btn">${t("expand")}</span>
|
|
6341
6370
|
</div>`);
|
|
6342
6371
|
r.$body.insertAdjacentElement("beforeend", collapsedInfoEl);
|
|
6343
6372
|
const contentShowBtn = collapsedInfoEl.querySelector(".atk-show-btn");
|
|
@@ -6347,51 +6376,51 @@ function renderContent(r) {
|
|
|
6347
6376
|
r.$content.innerHTML = r.comment.getContentMarked();
|
|
6348
6377
|
r.$content.classList.remove("atk-hide");
|
|
6349
6378
|
playFadeInAnim(r.$content);
|
|
6350
|
-
contentShowBtn.innerText =
|
|
6379
|
+
contentShowBtn.innerText = t("collapse");
|
|
6351
6380
|
} else {
|
|
6352
6381
|
r.$content.innerHTML = "";
|
|
6353
6382
|
r.$content.classList.add("atk-hide");
|
|
6354
|
-
contentShowBtn.innerText =
|
|
6383
|
+
contentShowBtn.innerText = t("expand");
|
|
6355
6384
|
}
|
|
6356
6385
|
});
|
|
6357
6386
|
}
|
|
6358
6387
|
function renderReplyAt(r) {
|
|
6359
|
-
if (r.
|
|
6388
|
+
if (r.opts.flatMode || r.data.rid === 0)
|
|
6360
6389
|
return;
|
|
6361
|
-
if (!r.
|
|
6390
|
+
if (!r.opts.replyTo)
|
|
6362
6391
|
return;
|
|
6363
6392
|
r.$replyAt = createElement(`<span class="atk-item atk-reply-at"><span class="atk-arrow"></span><span class="atk-nick"></span></span>`);
|
|
6364
|
-
r.$replyAt.querySelector(".atk-nick").innerText = `${r.
|
|
6393
|
+
r.$replyAt.querySelector(".atk-nick").innerText = `${r.opts.replyTo.nick}`;
|
|
6365
6394
|
r.$replyAt.onclick = () => {
|
|
6366
6395
|
r.comment.getActions().goToReplyComment();
|
|
6367
6396
|
};
|
|
6368
6397
|
r.$headerBadgeWrap.insertAdjacentElement("afterend", r.$replyAt);
|
|
6369
6398
|
}
|
|
6370
6399
|
function renderReplyTo(r) {
|
|
6371
|
-
if (!r.
|
|
6400
|
+
if (!r.opts.flatMode)
|
|
6372
6401
|
return;
|
|
6373
|
-
if (!r.
|
|
6402
|
+
if (!r.opts.replyTo)
|
|
6374
6403
|
return;
|
|
6375
6404
|
r.$replyTo = createElement(`
|
|
6376
6405
|
<div class="atk-reply-to">
|
|
6377
|
-
<div class="atk-meta">${
|
|
6406
|
+
<div class="atk-meta">${t("reply")} <span class="atk-nick"></span>:</div>
|
|
6378
6407
|
<div class="atk-content"></div>
|
|
6379
6408
|
</div>`);
|
|
6380
6409
|
const $nick = r.$replyTo.querySelector(".atk-nick");
|
|
6381
|
-
$nick.innerText = `@${r.
|
|
6410
|
+
$nick.innerText = `@${r.opts.replyTo.nick}`;
|
|
6382
6411
|
$nick.onclick = () => {
|
|
6383
6412
|
r.comment.getActions().goToReplyComment();
|
|
6384
6413
|
};
|
|
6385
|
-
let replyContent = marked(r.
|
|
6386
|
-
if (r.
|
|
6387
|
-
replyContent = `[${
|
|
6414
|
+
let replyContent = marked(r.opts.replyTo.content);
|
|
6415
|
+
if (r.opts.replyTo.is_collapsed)
|
|
6416
|
+
replyContent = `[${t("collapsed")}]`;
|
|
6388
6417
|
r.$replyTo.querySelector(".atk-content").innerHTML = replyContent;
|
|
6389
6418
|
r.$body.prepend(r.$replyTo);
|
|
6390
6419
|
}
|
|
6391
6420
|
function renderPending(r) {
|
|
6392
6421
|
if (!r.data.is_pending)
|
|
6393
6422
|
return;
|
|
6394
|
-
const pendingEl = createElement(`<div class="atk-pending">${
|
|
6423
|
+
const pendingEl = createElement(`<div class="atk-pending">${t("pendingMsg")}</div>`);
|
|
6395
6424
|
r.$body.prepend(pendingEl);
|
|
6396
6425
|
}
|
|
6397
6426
|
class ActionBtn {
|
|
@@ -6544,14 +6573,14 @@ function renderActions(r) {
|
|
|
6544
6573
|
});
|
|
6545
6574
|
}
|
|
6546
6575
|
function renderVote(r) {
|
|
6547
|
-
if (!r.
|
|
6576
|
+
if (!r.opts.vote)
|
|
6548
6577
|
return;
|
|
6549
|
-
r.voteBtnUp = new ActionBtn(() => `${
|
|
6578
|
+
r.voteBtnUp = new ActionBtn(() => `${t("voteUp")} (${r.data.vote_up || 0})`).appendTo(r.$actions);
|
|
6550
6579
|
r.voteBtnUp.setClick(() => {
|
|
6551
6580
|
r.comment.getActions().vote("up");
|
|
6552
6581
|
});
|
|
6553
|
-
if (r.
|
|
6554
|
-
r.voteBtnDown = new ActionBtn(() => `${
|
|
6582
|
+
if (r.opts.voteDown) {
|
|
6583
|
+
r.voteBtnDown = new ActionBtn(() => `${t("voteDown")} (${r.data.vote_down || 0})`).appendTo(r.$actions);
|
|
6555
6584
|
r.voteBtnDown.setClick(() => {
|
|
6556
6585
|
r.comment.getActions().vote("down");
|
|
6557
6586
|
});
|
|
@@ -6560,20 +6589,16 @@ function renderVote(r) {
|
|
|
6560
6589
|
function renderReply(r) {
|
|
6561
6590
|
if (!r.data.is_allow_reply)
|
|
6562
6591
|
return;
|
|
6563
|
-
const replyBtn = createElement(`<span>${
|
|
6592
|
+
const replyBtn = createElement(`<span>${t("reply")}</span>`);
|
|
6564
6593
|
r.$actions.append(replyBtn);
|
|
6565
6594
|
replyBtn.addEventListener("click", (e) => {
|
|
6566
6595
|
e.stopPropagation();
|
|
6567
|
-
|
|
6568
|
-
r.ctx.replyComment(r.data, r.$el);
|
|
6569
|
-
} else {
|
|
6570
|
-
r.cConf.onReplyBtnClick();
|
|
6571
|
-
}
|
|
6596
|
+
r.opts.replyComment(r.data, r.$el);
|
|
6572
6597
|
});
|
|
6573
6598
|
}
|
|
6574
6599
|
function renderCollapse(r) {
|
|
6575
6600
|
const collapseBtn = new ActionBtn({
|
|
6576
|
-
text: () => r.data.is_collapsed ?
|
|
6601
|
+
text: () => r.data.is_collapsed ? t("expand") : t("collapse"),
|
|
6577
6602
|
adminOnly: true
|
|
6578
6603
|
});
|
|
6579
6604
|
collapseBtn.appendTo(r.$actions);
|
|
@@ -6583,7 +6608,7 @@ function renderCollapse(r) {
|
|
|
6583
6608
|
}
|
|
6584
6609
|
function renderModerator(r) {
|
|
6585
6610
|
const pendingBtn = new ActionBtn({
|
|
6586
|
-
text: () => r.data.is_pending ?
|
|
6611
|
+
text: () => r.data.is_pending ? t("pending") : t("approved"),
|
|
6587
6612
|
adminOnly: true
|
|
6588
6613
|
});
|
|
6589
6614
|
pendingBtn.appendTo(r.$actions);
|
|
@@ -6593,7 +6618,7 @@ function renderModerator(r) {
|
|
|
6593
6618
|
}
|
|
6594
6619
|
function renderPin(r) {
|
|
6595
6620
|
const pinnedBtn = new ActionBtn({
|
|
6596
|
-
text: () => r.data.is_pinned ?
|
|
6621
|
+
text: () => r.data.is_pinned ? t("unpin") : t("pin"),
|
|
6597
6622
|
adminOnly: true
|
|
6598
6623
|
});
|
|
6599
6624
|
pinnedBtn.appendTo(r.$actions);
|
|
@@ -6603,19 +6628,19 @@ function renderPin(r) {
|
|
|
6603
6628
|
}
|
|
6604
6629
|
function renderEdit(r) {
|
|
6605
6630
|
const editBtn = new ActionBtn({
|
|
6606
|
-
text:
|
|
6631
|
+
text: t("edit"),
|
|
6607
6632
|
adminOnly: true
|
|
6608
6633
|
});
|
|
6609
6634
|
editBtn.appendTo(r.$actions);
|
|
6610
6635
|
editBtn.setClick(() => {
|
|
6611
|
-
r.
|
|
6636
|
+
r.opts.editComment(r.data, r.$el);
|
|
6612
6637
|
});
|
|
6613
6638
|
}
|
|
6614
6639
|
function renderDel(r) {
|
|
6615
6640
|
const delBtn = new ActionBtn({
|
|
6616
|
-
text:
|
|
6641
|
+
text: t("delete"),
|
|
6617
6642
|
confirm: true,
|
|
6618
|
-
confirmText:
|
|
6643
|
+
confirmText: t("deleteConfirm"),
|
|
6619
6644
|
adminOnly: true
|
|
6620
6645
|
});
|
|
6621
6646
|
delBtn.appendTo(r.$actions);
|
|
@@ -6657,18 +6682,21 @@ class Render {
|
|
|
6657
6682
|
__publicField(this, "$replyAt");
|
|
6658
6683
|
this.comment = comment;
|
|
6659
6684
|
}
|
|
6660
|
-
get ctx() {
|
|
6661
|
-
return this.comment.ctx;
|
|
6662
|
-
}
|
|
6663
6685
|
get data() {
|
|
6664
6686
|
return this.comment.getData();
|
|
6665
6687
|
}
|
|
6666
|
-
get
|
|
6667
|
-
return this.comment.
|
|
6668
|
-
}
|
|
6669
|
-
get cConf() {
|
|
6670
|
-
return this.comment.getConf();
|
|
6688
|
+
get opts() {
|
|
6689
|
+
return this.comment.getOpts();
|
|
6671
6690
|
}
|
|
6691
|
+
/**
|
|
6692
|
+
* Render the comment ui
|
|
6693
|
+
*
|
|
6694
|
+
* If comment data is updated, call this method to re-render the comment ui.
|
|
6695
|
+
* The method will be called multiple times, so it should be idempotent.
|
|
6696
|
+
*
|
|
6697
|
+
* Renders may add event listeners to the comment ui, so it should be called only once or override the original.
|
|
6698
|
+
* Please be aware of the memory leak caused by the event listener.
|
|
6699
|
+
*/
|
|
6672
6700
|
render() {
|
|
6673
6701
|
this.$el = createElement(CommentHTML);
|
|
6674
6702
|
this.$main = this.$el.querySelector(".atk-main");
|
|
@@ -6678,12 +6706,14 @@ class Render {
|
|
|
6678
6706
|
this.$actions = this.$el.querySelector(".atk-actions");
|
|
6679
6707
|
this.$el.setAttribute("id", `atk-comment-${this.data.id}`);
|
|
6680
6708
|
loadRenders(this);
|
|
6681
|
-
this
|
|
6709
|
+
if (this.$childrenWrap) {
|
|
6710
|
+
this.$main.append(this.$childrenWrap);
|
|
6711
|
+
}
|
|
6682
6712
|
return this.$el;
|
|
6683
6713
|
}
|
|
6684
6714
|
/** 内容限高检测 */
|
|
6685
6715
|
checkHeightLimit() {
|
|
6686
|
-
const conf = this.
|
|
6716
|
+
const conf = this.opts.heightLimit;
|
|
6687
6717
|
if (!conf || !conf.content || !conf.children)
|
|
6688
6718
|
return;
|
|
6689
6719
|
const contentMaxH = conf.content;
|
|
@@ -6717,24 +6747,21 @@ class Render {
|
|
|
6717
6747
|
playFadeAnimForBody() {
|
|
6718
6748
|
playFadeInAnim(this.comment.getRender().$body);
|
|
6719
6749
|
}
|
|
6750
|
+
/** Perform the flash animation */
|
|
6751
|
+
playFlashAnim() {
|
|
6752
|
+
this.$el.classList.remove("atk-flash-once");
|
|
6753
|
+
window.setTimeout(() => {
|
|
6754
|
+
this.$el.classList.add("atk-flash-once");
|
|
6755
|
+
}, 150);
|
|
6756
|
+
}
|
|
6720
6757
|
/** 获取子评论 Wrap */
|
|
6721
6758
|
getChildrenWrap() {
|
|
6722
|
-
return this.$childrenWrap;
|
|
6723
|
-
}
|
|
6724
|
-
/** 初始化子评论区域 Wrap */
|
|
6725
|
-
renderChildrenWrap() {
|
|
6726
6759
|
if (!this.$childrenWrap) {
|
|
6727
6760
|
this.$childrenWrap = createElement('<div class="atk-comment-children"></div>');
|
|
6728
6761
|
this.$main.append(this.$childrenWrap);
|
|
6729
6762
|
}
|
|
6730
6763
|
return this.$childrenWrap;
|
|
6731
6764
|
}
|
|
6732
|
-
/** 恢复原有的子评论区域 Wrap */
|
|
6733
|
-
recoveryChildrenWrap() {
|
|
6734
|
-
if (this.$childrenWrap) {
|
|
6735
|
-
this.$main.append(this.$childrenWrap);
|
|
6736
|
-
}
|
|
6737
|
-
}
|
|
6738
6765
|
/** 设置已读 */
|
|
6739
6766
|
setUnread(val) {
|
|
6740
6767
|
if (val)
|
|
@@ -6753,17 +6780,15 @@ class Render {
|
|
|
6753
6780
|
setOpenURL(url) {
|
|
6754
6781
|
this.setOpenable(true);
|
|
6755
6782
|
this.$el.onclick = (evt) => {
|
|
6756
|
-
evt.
|
|
6783
|
+
evt.stopPropagation();
|
|
6757
6784
|
window.open(url);
|
|
6758
|
-
if (this.cConf.openEvt)
|
|
6759
|
-
this.cConf.openEvt();
|
|
6760
6785
|
};
|
|
6761
6786
|
}
|
|
6762
6787
|
/** 设置点击评论时的操作 */
|
|
6763
6788
|
setOpenAction(action) {
|
|
6764
6789
|
this.setOpenable(true);
|
|
6765
6790
|
this.$el.onclick = (evt) => {
|
|
6766
|
-
evt.
|
|
6791
|
+
evt.stopPropagation();
|
|
6767
6792
|
action();
|
|
6768
6793
|
};
|
|
6769
6794
|
}
|
|
@@ -6773,26 +6798,26 @@ class CommentActions {
|
|
|
6773
6798
|
__publicField(this, "comment");
|
|
6774
6799
|
this.comment = comment;
|
|
6775
6800
|
}
|
|
6776
|
-
get ctx() {
|
|
6777
|
-
return this.comment.ctx;
|
|
6778
|
-
}
|
|
6779
6801
|
get data() {
|
|
6780
6802
|
return this.comment.getData();
|
|
6781
6803
|
}
|
|
6782
|
-
get
|
|
6783
|
-
return this.comment.
|
|
6804
|
+
get opts() {
|
|
6805
|
+
return this.comment.getOpts();
|
|
6806
|
+
}
|
|
6807
|
+
getApi() {
|
|
6808
|
+
return this.comment.getOpts().getApi();
|
|
6784
6809
|
}
|
|
6785
6810
|
/** 投票操作 */
|
|
6786
6811
|
vote(type) {
|
|
6787
6812
|
const actionBtn = type === "up" ? this.comment.getRender().voteBtnUp : this.comment.getRender().voteBtnDown;
|
|
6788
|
-
this.
|
|
6813
|
+
this.getApi().votes.vote(`comment_${type}`, this.data.id, __spreadValues({}, this.getApi().getUserFields())).then((res) => {
|
|
6789
6814
|
var _a, _b;
|
|
6790
6815
|
this.data.vote_up = res.data.up;
|
|
6791
6816
|
this.data.vote_down = res.data.down;
|
|
6792
6817
|
(_a = this.comment.getRender().voteBtnUp) == null ? void 0 : _a.updateText();
|
|
6793
6818
|
(_b = this.comment.getRender().voteBtnDown) == null ? void 0 : _b.updateText();
|
|
6794
6819
|
}).catch((err) => {
|
|
6795
|
-
actionBtn == null ? void 0 : actionBtn.setError(
|
|
6820
|
+
actionBtn == null ? void 0 : actionBtn.setError(t("voteFail"));
|
|
6796
6821
|
console.log(err);
|
|
6797
6822
|
});
|
|
6798
6823
|
}
|
|
@@ -6800,7 +6825,7 @@ class CommentActions {
|
|
|
6800
6825
|
adminEdit(type, btnElem) {
|
|
6801
6826
|
if (btnElem.isLoading)
|
|
6802
6827
|
return;
|
|
6803
|
-
btnElem.setLoading(true, `${
|
|
6828
|
+
btnElem.setLoading(true, `${t("editing")}...`);
|
|
6804
6829
|
const modify = __spreadValues({}, this.data);
|
|
6805
6830
|
if (type === "collapsed") {
|
|
6806
6831
|
modify.is_collapsed = !modify.is_collapsed;
|
|
@@ -6809,26 +6834,26 @@ class CommentActions {
|
|
|
6809
6834
|
} else if (type === "pinned") {
|
|
6810
6835
|
modify.is_pinned = !modify.is_pinned;
|
|
6811
6836
|
}
|
|
6812
|
-
this.
|
|
6837
|
+
this.getApi().comments.updateComment(this.data.id, __spreadValues({}, modify)).then((res) => {
|
|
6813
6838
|
btnElem.setLoading(false);
|
|
6814
6839
|
this.comment.setData(res.data);
|
|
6815
6840
|
}).catch((err) => {
|
|
6816
6841
|
console.error(err);
|
|
6817
|
-
btnElem.setError(
|
|
6842
|
+
btnElem.setError(t("editFail"));
|
|
6818
6843
|
});
|
|
6819
6844
|
}
|
|
6820
6845
|
/** 管理员 - 评论删除 */
|
|
6821
6846
|
adminDelete(btnElem) {
|
|
6822
6847
|
if (btnElem.isLoading)
|
|
6823
6848
|
return;
|
|
6824
|
-
btnElem.setLoading(true, `${
|
|
6825
|
-
this.
|
|
6849
|
+
btnElem.setLoading(true, `${t("deleting")}...`);
|
|
6850
|
+
this.getApi().comments.deleteComment(this.data.id).then(() => {
|
|
6826
6851
|
btnElem.setLoading(false);
|
|
6827
|
-
if (this.
|
|
6828
|
-
this.
|
|
6852
|
+
if (this.opts.onDelete)
|
|
6853
|
+
this.opts.onDelete(this.comment);
|
|
6829
6854
|
}).catch((e) => {
|
|
6830
6855
|
console.error(e);
|
|
6831
|
-
btnElem.setError(
|
|
6856
|
+
btnElem.setError(t("deleteFail"));
|
|
6832
6857
|
});
|
|
6833
6858
|
}
|
|
6834
6859
|
/** 快速跳转到该评论 */
|
|
@@ -6840,21 +6865,18 @@ class CommentActions {
|
|
|
6840
6865
|
window.dispatchEvent(new Event("hashchange"));
|
|
6841
6866
|
}
|
|
6842
6867
|
}
|
|
6843
|
-
class CommentNode
|
|
6844
|
-
//
|
|
6845
|
-
constructor(
|
|
6846
|
-
|
|
6868
|
+
class CommentNode {
|
|
6869
|
+
// 当前嵌套层数
|
|
6870
|
+
constructor(data, opts) {
|
|
6871
|
+
__publicField(this, "$el");
|
|
6847
6872
|
__publicField(this, "renderInstance");
|
|
6848
6873
|
__publicField(this, "actionInstance");
|
|
6849
6874
|
__publicField(this, "data");
|
|
6850
|
-
__publicField(this, "
|
|
6875
|
+
__publicField(this, "opts");
|
|
6851
6876
|
__publicField(this, "parent");
|
|
6852
6877
|
__publicField(this, "children", []);
|
|
6853
6878
|
__publicField(this, "nestCurt");
|
|
6854
|
-
|
|
6855
|
-
__publicField(this, "nestMax");
|
|
6856
|
-
this.nestMax = ctx.conf.nestMax || 3;
|
|
6857
|
-
this.cConf = conf;
|
|
6879
|
+
this.opts = opts;
|
|
6858
6880
|
this.data = __spreadValues({}, data);
|
|
6859
6881
|
this.data.date = this.data.date.replace(/-/g, "/");
|
|
6860
6882
|
this.parent = null;
|
|
@@ -6868,8 +6890,8 @@ class CommentNode extends Component {
|
|
|
6868
6890
|
if (this.$el)
|
|
6869
6891
|
this.$el.replaceWith(newEl);
|
|
6870
6892
|
this.$el = newEl;
|
|
6871
|
-
if (this.
|
|
6872
|
-
this.
|
|
6893
|
+
if (this.opts.onAfterRender)
|
|
6894
|
+
this.opts.onAfterRender();
|
|
6873
6895
|
}
|
|
6874
6896
|
/** 获取评论操作实例对象 */
|
|
6875
6897
|
getActions() {
|
|
@@ -6910,51 +6932,76 @@ class CommentNode extends Component {
|
|
|
6910
6932
|
return this.data.id;
|
|
6911
6933
|
}
|
|
6912
6934
|
/** 置入子评论 */
|
|
6913
|
-
putChild(
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
this.children.push(
|
|
6917
|
-
const $
|
|
6935
|
+
putChild(childNode, insertMode = "append") {
|
|
6936
|
+
childNode.parent = this;
|
|
6937
|
+
childNode.nestCurt = this.nestCurt + 1;
|
|
6938
|
+
this.children.push(childNode);
|
|
6939
|
+
const $childrenWrap = this.getChildrenWrapEl();
|
|
6940
|
+
const $childComment = childNode.getEl();
|
|
6918
6941
|
if (insertMode === "append")
|
|
6919
|
-
$
|
|
6942
|
+
$childrenWrap.append($childComment);
|
|
6920
6943
|
else if (insertMode === "prepend")
|
|
6921
|
-
$
|
|
6922
|
-
|
|
6923
|
-
|
|
6944
|
+
$childrenWrap.prepend($childComment);
|
|
6945
|
+
childNode.getRender().playFadeAnim();
|
|
6946
|
+
childNode.getRender().checkHeightLimit();
|
|
6924
6947
|
}
|
|
6925
6948
|
/** 获取存放子评论的元素对象 */
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
if (this.nestCurt < this.nestMax) {
|
|
6930
|
-
$children = this.getRender().renderChildrenWrap();
|
|
6931
|
-
} else {
|
|
6932
|
-
$children = this.parent.getChildrenEl();
|
|
6933
|
-
}
|
|
6949
|
+
getChildrenWrapEl() {
|
|
6950
|
+
if (this.nestCurt >= this.opts.nestMax) {
|
|
6951
|
+
return this.parent.getChildrenWrapEl();
|
|
6934
6952
|
}
|
|
6935
|
-
return
|
|
6953
|
+
return this.getRender().getChildrenWrap();
|
|
6936
6954
|
}
|
|
6937
6955
|
/** 获取所有父评论 */
|
|
6938
6956
|
getParents() {
|
|
6939
|
-
const
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
once(this);
|
|
6947
|
-
return parents;
|
|
6957
|
+
const flattenParents = [];
|
|
6958
|
+
let parent = this.parent;
|
|
6959
|
+
while (parent) {
|
|
6960
|
+
flattenParents.push(parent);
|
|
6961
|
+
parent = parent.getParent();
|
|
6962
|
+
}
|
|
6963
|
+
return flattenParents;
|
|
6948
6964
|
}
|
|
6949
|
-
/**
|
|
6965
|
+
/**
|
|
6966
|
+
* Get the element of the comment
|
|
6967
|
+
*
|
|
6968
|
+
* The `getEl()` will always return the latest $el after calling `render()`.
|
|
6969
|
+
* Please be aware of the memory leak if you use the $el reference directly.
|
|
6970
|
+
*/
|
|
6950
6971
|
getEl() {
|
|
6972
|
+
if (!this.$el)
|
|
6973
|
+
throw new Error("comment element not initialized before `getEl()`");
|
|
6951
6974
|
return this.$el;
|
|
6952
6975
|
}
|
|
6976
|
+
/**
|
|
6977
|
+
* Focus on the comment
|
|
6978
|
+
*
|
|
6979
|
+
* Scroll to the comment and perform flash animation
|
|
6980
|
+
*/
|
|
6981
|
+
focus() {
|
|
6982
|
+
if (!this.$el)
|
|
6983
|
+
throw new Error("comment element not initialized before `focus()`");
|
|
6984
|
+
this.getParents().forEach((p) => {
|
|
6985
|
+
p.getRender().heightLimitRemoveForChildren();
|
|
6986
|
+
});
|
|
6987
|
+
this.scrollIntoView();
|
|
6988
|
+
this.getRender().playFlashAnim();
|
|
6989
|
+
}
|
|
6990
|
+
scrollIntoView() {
|
|
6991
|
+
this.$el && scrollIntoView(this.$el, false, this.opts.scrollRelativeTo && this.opts.scrollRelativeTo());
|
|
6992
|
+
}
|
|
6993
|
+
/**
|
|
6994
|
+
* Remove the comment node
|
|
6995
|
+
*/
|
|
6996
|
+
remove() {
|
|
6997
|
+
var _a;
|
|
6998
|
+
(_a = this.$el) == null ? void 0 : _a.remove();
|
|
6999
|
+
}
|
|
6953
7000
|
/** 获取 Gravatar 头像 URL */
|
|
6954
7001
|
getGravatarURL() {
|
|
6955
7002
|
return getGravatarURL({
|
|
6956
|
-
mirror: this.
|
|
6957
|
-
params: this.
|
|
7003
|
+
mirror: this.opts.gravatar.mirror,
|
|
7004
|
+
params: this.opts.gravatar.params,
|
|
6958
7005
|
emailMD5: this.data.email_encrypted
|
|
6959
7006
|
});
|
|
6960
7007
|
}
|
|
@@ -6964,7 +7011,7 @@ class CommentNode extends Component {
|
|
|
6964
7011
|
}
|
|
6965
7012
|
/** 获取格式化后的日期 */
|
|
6966
7013
|
getDateFormatted() {
|
|
6967
|
-
return timeAgo(new Date(this.data.date),
|
|
7014
|
+
return timeAgo(new Date(this.data.date), t);
|
|
6968
7015
|
}
|
|
6969
7016
|
/** 获取用户 UserAgent 信息 */
|
|
6970
7017
|
getUserUA() {
|
|
@@ -6975,21 +7022,33 @@ class CommentNode extends Component {
|
|
|
6975
7022
|
};
|
|
6976
7023
|
}
|
|
6977
7024
|
/** 获取配置 */
|
|
6978
|
-
|
|
6979
|
-
return this.
|
|
7025
|
+
getOpts() {
|
|
7026
|
+
return this.opts;
|
|
6980
7027
|
}
|
|
6981
7028
|
}
|
|
6982
|
-
function
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
isFlatMode: (_a = ctx.getData().getListLastFetch()) == null ? void 0 : _a.params.flatMode,
|
|
6986
|
-
afterRender: () => {
|
|
7029
|
+
function createCommentNode(ctx, comment, replyComment, opts) {
|
|
7030
|
+
const instance2 = new CommentNode(comment, {
|
|
7031
|
+
onAfterRender: () => {
|
|
6987
7032
|
ctx.trigger("comment-rendered", instance2);
|
|
6988
7033
|
},
|
|
6989
7034
|
onDelete: (c) => {
|
|
6990
7035
|
ctx.getData().deleteComment(c.getID());
|
|
6991
7036
|
},
|
|
6992
|
-
replyTo:
|
|
7037
|
+
replyTo: replyComment,
|
|
7038
|
+
// TODO simplify reference
|
|
7039
|
+
flatMode: typeof (opts == null ? void 0 : opts.forceFlatMode) === "boolean" ? opts == null ? void 0 : opts.forceFlatMode : ctx.conf.flatMode,
|
|
7040
|
+
gravatar: ctx.conf.gravatar,
|
|
7041
|
+
nestMax: ctx.conf.nestMax,
|
|
7042
|
+
heightLimit: ctx.conf.heightLimit,
|
|
7043
|
+
avatarURLBuilder: ctx.conf.avatarURLBuilder,
|
|
7044
|
+
scrollRelativeTo: ctx.conf.scrollRelativeTo,
|
|
7045
|
+
vote: ctx.conf.vote,
|
|
7046
|
+
voteDown: ctx.conf.voteDown,
|
|
7047
|
+
uaBadge: ctx.conf.uaBadge,
|
|
7048
|
+
// TODO: move to plugin folder and remove from core
|
|
7049
|
+
getApi: () => ctx.getApi(),
|
|
7050
|
+
replyComment: (c, $el) => ctx.replyComment(c, $el),
|
|
7051
|
+
editComment: (c, $el) => ctx.editComment(c, $el)
|
|
6993
7052
|
});
|
|
6994
7053
|
instance2.render();
|
|
6995
7054
|
return instance2;
|
|
@@ -7365,20 +7424,19 @@ class List extends Component {
|
|
|
7365
7424
|
getCommentNodes() {
|
|
7366
7425
|
return this.commentNodes;
|
|
7367
7426
|
}
|
|
7368
|
-
getListLayout() {
|
|
7427
|
+
getListLayout({ forceFlatMode } = {}) {
|
|
7369
7428
|
return new ListLayout({
|
|
7370
7429
|
$commentsWrap: this.$commentsWrap,
|
|
7371
7430
|
nestSortBy: this.ctx.conf.nestSort,
|
|
7372
7431
|
nestMax: this.ctx.conf.nestMax,
|
|
7373
|
-
flatMode: this.ctx.conf.flatMode,
|
|
7432
|
+
flatMode: typeof forceFlatMode === "boolean" ? forceFlatMode : this.ctx.conf.flatMode,
|
|
7374
7433
|
// flatMode must be boolean because it had been handled when Artalk.init
|
|
7375
|
-
createCommentNode: (d,
|
|
7376
|
-
const node =
|
|
7434
|
+
createCommentNode: (d, r) => {
|
|
7435
|
+
const node = createCommentNode(this.ctx, d, r, { forceFlatMode });
|
|
7377
7436
|
this.commentNodes.push(node);
|
|
7378
7437
|
return node;
|
|
7379
7438
|
},
|
|
7380
|
-
findCommentNode: (id) => this.commentNodes.find((c) => c.getID() === id)
|
|
7381
|
-
getCommentDataList: () => this.ctx.getData().getComments()
|
|
7439
|
+
findCommentNode: (id) => this.commentNodes.find((c) => c.getID() === id)
|
|
7382
7440
|
});
|
|
7383
7441
|
}
|
|
7384
7442
|
initCrudEvents() {
|
|
@@ -7386,8 +7444,10 @@ class List extends Component {
|
|
|
7386
7444
|
this.getListLayout().import(comments);
|
|
7387
7445
|
});
|
|
7388
7446
|
this.ctx.on("list-loaded", (comments) => {
|
|
7389
|
-
if (comments.length === 0)
|
|
7447
|
+
if (comments.length === 0) {
|
|
7448
|
+
this.commentNodes = [];
|
|
7390
7449
|
this.$commentsWrap.innerHTML = "";
|
|
7450
|
+
}
|
|
7391
7451
|
});
|
|
7392
7452
|
this.ctx.on("comment-inserted", (comment) => {
|
|
7393
7453
|
this.getListLayout().insert(comment);
|
|
@@ -7398,7 +7458,7 @@ class List extends Component {
|
|
|
7398
7458
|
console.error(`comment node id=${comment.id} not found`);
|
|
7399
7459
|
return;
|
|
7400
7460
|
}
|
|
7401
|
-
node.
|
|
7461
|
+
node.remove();
|
|
7402
7462
|
this.commentNodes = this.commentNodes.filter((c) => c.getID() !== comment.id);
|
|
7403
7463
|
});
|
|
7404
7464
|
this.ctx.on("comment-updated", (comment) => {
|
|
@@ -7915,15 +7975,16 @@ class StateReply extends EditorPlug {
|
|
|
7915
7975
|
}
|
|
7916
7976
|
setReply(commentData) {
|
|
7917
7977
|
const ui = this.kit.useUI();
|
|
7918
|
-
if (!ui.$
|
|
7919
|
-
|
|
7920
|
-
`<
|
|
7978
|
+
if (!ui.$sendReplyBtn) {
|
|
7979
|
+
const $btn = createElement(
|
|
7980
|
+
`<span class="atk-state-btn"><span class="atk-text-wrap">${t("reply")} <span class="atk-text"></span></span><span class="atk-cancel">×</span></span>`
|
|
7921
7981
|
);
|
|
7922
|
-
|
|
7923
|
-
|
|
7982
|
+
$btn.querySelector(".atk-text").innerText = `@${commentData.nick}`;
|
|
7983
|
+
$btn.addEventListener("click", () => {
|
|
7924
7984
|
this.kit.useEditor().resetState();
|
|
7925
7985
|
});
|
|
7926
|
-
ui.$
|
|
7986
|
+
ui.$stateWrap.append($btn);
|
|
7987
|
+
ui.$sendReplyBtn = $btn;
|
|
7927
7988
|
}
|
|
7928
7989
|
this.comment = commentData;
|
|
7929
7990
|
ui.$textarea.focus();
|
|
@@ -7932,9 +7993,9 @@ class StateReply extends EditorPlug {
|
|
|
7932
7993
|
if (!this.comment)
|
|
7933
7994
|
return;
|
|
7934
7995
|
const ui = this.kit.useUI();
|
|
7935
|
-
if (ui.$
|
|
7936
|
-
ui.$
|
|
7937
|
-
ui.$
|
|
7996
|
+
if (ui.$sendReplyBtn) {
|
|
7997
|
+
ui.$sendReplyBtn.remove();
|
|
7998
|
+
ui.$sendReplyBtn = void 0;
|
|
7938
7999
|
}
|
|
7939
8000
|
this.comment = void 0;
|
|
7940
8001
|
}
|
|
@@ -7981,12 +8042,12 @@ class StateEdit extends EditorPlug {
|
|
|
7981
8042
|
const ui = this.kit.useUI();
|
|
7982
8043
|
if (!ui.$editCancelBtn) {
|
|
7983
8044
|
const $btn = createElement(
|
|
7984
|
-
`<
|
|
8045
|
+
`<span class="atk-state-btn"><span class="atk-text-wrap">${t("editCancel")}</span><span class="atk-cancel">×</span></span>`
|
|
7985
8046
|
);
|
|
7986
8047
|
$btn.onclick = () => {
|
|
7987
8048
|
this.kit.useEditor().resetState();
|
|
7988
8049
|
};
|
|
7989
|
-
ui.$
|
|
8050
|
+
ui.$stateWrap.append($btn);
|
|
7990
8051
|
ui.$editCancelBtn = $btn;
|
|
7991
8052
|
}
|
|
7992
8053
|
this.comment = comment;
|
|
@@ -8183,7 +8244,7 @@ class Emoticons extends EditorPlug {
|
|
|
8183
8244
|
__publicField(this, "isImgLoaded", false);
|
|
8184
8245
|
this.kit.useMounted(() => {
|
|
8185
8246
|
this.usePanel(`<div class="atk-editor-plug-emoticons"></div>`);
|
|
8186
|
-
this.useBtn(t("emoticon"));
|
|
8247
|
+
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>`);
|
|
8187
8248
|
});
|
|
8188
8249
|
this.kit.useUnmounted(() => {
|
|
8189
8250
|
});
|
|
@@ -8434,7 +8495,7 @@ class Upload extends EditorPlug {
|
|
|
8434
8495
|
this.$imgUploadInput.type = "file";
|
|
8435
8496
|
this.$imgUploadInput.style.display = "none";
|
|
8436
8497
|
this.$imgUploadInput.accept = AllowImgExts.map((o) => `.${o}`).join(",");
|
|
8437
|
-
const $btn = this.useBtn(
|
|
8498
|
+
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>`);
|
|
8438
8499
|
$btn.after(this.$imgUploadInput);
|
|
8439
8500
|
$btn.onclick = () => {
|
|
8440
8501
|
const $input = this.$imgUploadInput;
|
|
@@ -8538,10 +8599,7 @@ class Preview extends EditorPlug {
|
|
|
8538
8599
|
__publicField(this, "isPlugPanelShow", false);
|
|
8539
8600
|
this.kit.useMounted(() => {
|
|
8540
8601
|
this.usePanel(`<div class="atk-editor-plug-preview"></div>`);
|
|
8541
|
-
|
|
8542
|
-
if (getInstance())
|
|
8543
|
-
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>`;
|
|
8544
|
-
this.useBtn(btnText);
|
|
8602
|
+
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>`);
|
|
8545
8603
|
});
|
|
8546
8604
|
this.kit.useUnmounted(() => {
|
|
8547
8605
|
});
|
|
@@ -8883,62 +8941,50 @@ const UnreadBadge = (ctx) => {
|
|
|
8883
8941
|
showUnreadBadge(notifies.length || 0);
|
|
8884
8942
|
});
|
|
8885
8943
|
};
|
|
8886
|
-
const
|
|
8887
|
-
let
|
|
8888
|
-
const check2 = () => {
|
|
8944
|
+
const GotoDispatcher = (ctx) => {
|
|
8945
|
+
let lastID = 0;
|
|
8946
|
+
const check2 = ({ locker }) => {
|
|
8889
8947
|
const commentID = extractCommentID();
|
|
8890
8948
|
if (!commentID)
|
|
8891
8949
|
return;
|
|
8950
|
+
if (locker && lastID === commentID)
|
|
8951
|
+
return;
|
|
8952
|
+
lastID = commentID;
|
|
8892
8953
|
ctx.trigger("list-goto", commentID);
|
|
8893
|
-
delayGoto = true;
|
|
8894
|
-
};
|
|
8895
|
-
const hashChangeHandler = () => {
|
|
8896
|
-
delayGoto = false;
|
|
8897
|
-
check2();
|
|
8898
8954
|
};
|
|
8955
|
+
const hashChangeHandler = () => check2({ locker: false });
|
|
8956
|
+
const listLoadedHandler = () => check2({ locker: true });
|
|
8899
8957
|
ctx.on("mounted", () => {
|
|
8900
8958
|
window.addEventListener("hashchange", hashChangeHandler);
|
|
8901
|
-
ctx.on("list-loaded",
|
|
8959
|
+
ctx.on("list-loaded", listLoadedHandler);
|
|
8902
8960
|
});
|
|
8903
8961
|
ctx.on("unmounted", () => {
|
|
8904
8962
|
window.removeEventListener("hashchange", hashChangeHandler);
|
|
8905
|
-
ctx.off("list-loaded",
|
|
8906
|
-
});
|
|
8907
|
-
let foundID = 0;
|
|
8908
|
-
ctx.on("list-goto", (commentID) => {
|
|
8909
|
-
if (foundID === commentID)
|
|
8910
|
-
return;
|
|
8911
|
-
const comment = ctx.get("list").getCommentNodes().find((c) => c.getID() === commentID);
|
|
8912
|
-
if (!comment)
|
|
8913
|
-
return;
|
|
8914
|
-
foundID = commentID;
|
|
8915
|
-
comment.getParents().forEach((p) => {
|
|
8916
|
-
p.getRender().heightLimitRemoveForChildren();
|
|
8917
|
-
});
|
|
8918
|
-
const goTo = () => {
|
|
8919
|
-
scrollIntoView(comment.getEl(), false);
|
|
8920
|
-
comment.getEl().classList.remove("atk-flash-once");
|
|
8921
|
-
window.setTimeout(() => {
|
|
8922
|
-
comment.getEl().classList.add("atk-flash-once");
|
|
8923
|
-
}, 150);
|
|
8924
|
-
};
|
|
8925
|
-
if (!delayGoto)
|
|
8926
|
-
goTo();
|
|
8927
|
-
else
|
|
8928
|
-
window.setTimeout(() => goTo(), 350);
|
|
8963
|
+
ctx.off("list-loaded", listLoadedHandler);
|
|
8929
8964
|
});
|
|
8930
8965
|
};
|
|
8931
8966
|
function extractCommentID() {
|
|
8932
|
-
|
|
8967
|
+
const match = window.location.hash.match(/#atk-comment-([0-9]+)/);
|
|
8968
|
+
let commentId = match && match[1] && !Number.isNaN(parseFloat(match[1])) ? parseFloat(match[1]) : null;
|
|
8933
8969
|
if (!commentId) {
|
|
8934
|
-
|
|
8935
|
-
if (!match || !match[1] || Number.isNaN(Number(match[1])))
|
|
8936
|
-
return null;
|
|
8937
|
-
commentId = Number(match[1]);
|
|
8970
|
+
commentId = Number(getQueryParam("atk_comment"));
|
|
8938
8971
|
}
|
|
8939
8972
|
return commentId || null;
|
|
8940
8973
|
}
|
|
8941
|
-
const
|
|
8974
|
+
const GotoFocus = (ctx) => {
|
|
8975
|
+
ctx.on("list-goto", (commentID) => __async(void 0, null, function* () {
|
|
8976
|
+
let comment = ctx.getCommentNodes().find((c) => c.getID() === commentID);
|
|
8977
|
+
if (!comment) {
|
|
8978
|
+
const data = (yield ctx.getApi().comments.getComment(commentID)).data;
|
|
8979
|
+
ctx.get("list").getListLayout({ forceFlatMode: true }).insert(data.comment, data.reply_comment);
|
|
8980
|
+
comment = ctx.getCommentNodes().find((c) => c.getID() === commentID);
|
|
8981
|
+
}
|
|
8982
|
+
if (!comment)
|
|
8983
|
+
return;
|
|
8984
|
+
comment.focus();
|
|
8985
|
+
}));
|
|
8986
|
+
};
|
|
8987
|
+
const version = "2.8.2";
|
|
8942
8988
|
const Copyright = (ctx) => {
|
|
8943
8989
|
ctx.on("mounted", () => {
|
|
8944
8990
|
const list2 = ctx.get("list");
|
|
@@ -8949,14 +8995,7 @@ const Copyright = (ctx) => {
|
|
|
8949
8995
|
});
|
|
8950
8996
|
};
|
|
8951
8997
|
const NoComment = (ctx) => {
|
|
8952
|
-
let isFetching = false;
|
|
8953
|
-
ctx.on("list-fetch", (params) => {
|
|
8954
|
-
isFetching = true;
|
|
8955
|
-
});
|
|
8956
8998
|
ctx.on("list-loaded", (comments) => {
|
|
8957
|
-
if (!isFetching)
|
|
8958
|
-
return;
|
|
8959
|
-
isFetching = false;
|
|
8960
8999
|
const list2 = ctx.get("list");
|
|
8961
9000
|
const isNoComment = comments.length <= 0;
|
|
8962
9001
|
let $noComment = list2.getCommentsWrapEl().querySelector(".atk-list-no-comment");
|
|
@@ -9208,7 +9247,8 @@ const ListPlugins = [
|
|
|
9208
9247
|
SidebarBtn,
|
|
9209
9248
|
UnreadBadge,
|
|
9210
9249
|
Dropdown,
|
|
9211
|
-
|
|
9250
|
+
GotoDispatcher,
|
|
9251
|
+
GotoFocus,
|
|
9212
9252
|
NoComment,
|
|
9213
9253
|
Copyright,
|
|
9214
9254
|
TimeTicking,
|
|
@@ -9232,6 +9272,7 @@ const PvCountWidget = (ctx) => {
|
|
|
9232
9272
|
ctx.watchConf([
|
|
9233
9273
|
"site",
|
|
9234
9274
|
"pageKey",
|
|
9275
|
+
"pageTitle",
|
|
9235
9276
|
"countEl",
|
|
9236
9277
|
"pvEl"
|
|
9237
9278
|
], (conf) => {
|
|
@@ -9239,6 +9280,7 @@ const PvCountWidget = (ctx) => {
|
|
|
9239
9280
|
getApi: () => ctx.getApi(),
|
|
9240
9281
|
siteName: conf.site,
|
|
9241
9282
|
pageKey: conf.pageKey,
|
|
9283
|
+
pageTitle: conf.pageTitle,
|
|
9242
9284
|
countEl: conf.countEl,
|
|
9243
9285
|
pvEl: conf.pvEl,
|
|
9244
9286
|
pvAdd: typeof ctx.conf.pvAdd === "boolean" ? ctx.conf.pvAdd : true
|
|
@@ -9250,10 +9292,10 @@ function initCountWidget(opt) {
|
|
|
9250
9292
|
if (opt.countEl && document.querySelector(opt.countEl)) {
|
|
9251
9293
|
refreshStatCount(opt, { query: "page_comment", numEl: opt.countEl });
|
|
9252
9294
|
}
|
|
9253
|
-
const initialData = opt.pvAdd ? {
|
|
9295
|
+
const initialData = opt.pvAdd && opt.pageKey ? {
|
|
9254
9296
|
[opt.pageKey]: (yield opt.getApi().pages.logPv({
|
|
9255
9297
|
page_key: opt.pageKey,
|
|
9256
|
-
page_title: opt.
|
|
9298
|
+
page_title: opt.pageTitle,
|
|
9257
9299
|
site_name: opt.siteName
|
|
9258
9300
|
})).data.pv
|
|
9259
9301
|
// pv+1 and get pv count
|
|
@@ -9270,7 +9312,7 @@ function initCountWidget(opt) {
|
|
|
9270
9312
|
function refreshStatCount(opt, args) {
|
|
9271
9313
|
return __async(this, null, function* () {
|
|
9272
9314
|
let data = args.data || {};
|
|
9273
|
-
let queryPageKeys = Array.from(document.querySelectorAll(args.numEl)).map((e) => e.getAttribute("data-page-key") || opt.pageKey).filter((k) => typeof data[k] !== "number");
|
|
9315
|
+
let queryPageKeys = Array.from(document.querySelectorAll(args.numEl)).map((e) => e.getAttribute("data-page-key") || opt.pageKey).filter((k) => k && typeof data[k] !== "number");
|
|
9274
9316
|
queryPageKeys = [...new Set(queryPageKeys)];
|
|
9275
9317
|
if (queryPageKeys.length > 0) {
|
|
9276
9318
|
const res = (yield opt.getApi().stats.getStats(args.query, {
|
|
@@ -9279,7 +9321,8 @@ function refreshStatCount(opt, args) {
|
|
|
9279
9321
|
})).data.data;
|
|
9280
9322
|
data = __spreadValues(__spreadValues({}, data), res);
|
|
9281
9323
|
}
|
|
9282
|
-
|
|
9324
|
+
const defaultCount = opt.pageKey ? data[opt.pageKey] : 0;
|
|
9325
|
+
applyCountData(args.numEl, data, defaultCount);
|
|
9283
9326
|
});
|
|
9284
9327
|
}
|
|
9285
9328
|
function applyCountData(selector, data, defaultCount) {
|
|
@@ -9468,7 +9511,6 @@ class Artalk {
|
|
|
9468
9511
|
initCountWidget({
|
|
9469
9512
|
getApi: () => new Api2(convertApiOptions(conf)),
|
|
9470
9513
|
siteName: conf.site,
|
|
9471
|
-
pageKey: conf.pageKey,
|
|
9472
9514
|
countEl: conf.countEl,
|
|
9473
9515
|
pvEl: conf.pvEl,
|
|
9474
9516
|
pvAdd: false
|