artalk 2.2.7 → 2.2.10

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.es.js CHANGED
@@ -104,7 +104,7 @@ const defaults$3 = {
104
104
  listSort: true,
105
105
  pvEl: "#ArtalkPV",
106
106
  flatMode: "auto",
107
- maxNesting: 3,
107
+ nestMax: 2,
108
108
  gravatar: {
109
109
  default: "mp",
110
110
  mirror: "https://sdn.geekzu.org/avatar/"
@@ -120,7 +120,8 @@ const defaults$3 = {
120
120
  },
121
121
  imgUpload: true,
122
122
  reqTimeout: 15e3,
123
- versionCheck: true
123
+ versionCheck: true,
124
+ useBackendConf: false
124
125
  };
125
126
  class Component {
126
127
  constructor(ctx) {
@@ -2813,6 +2814,24 @@ function getURLBasedOnApi(ctx, path) {
2813
2814
  function getURLBasedOn(baseURL, path) {
2814
2815
  return `${baseURL.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
2815
2816
  }
2817
+ function mergeDeep(target, source) {
2818
+ const isObject = (obj) => obj && typeof obj === "object";
2819
+ if (!isObject(target) || !isObject(source)) {
2820
+ return source;
2821
+ }
2822
+ Object.keys(source).forEach((key) => {
2823
+ const targetValue = target[key];
2824
+ const sourceValue = source[key];
2825
+ if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
2826
+ target[key] = targetValue.concat(sourceValue);
2827
+ } else if (isObject(targetValue) && isObject(sourceValue)) {
2828
+ target[key] = mergeDeep(__spreadValues({}, targetValue), sourceValue);
2829
+ } else {
2830
+ target[key] = sourceValue;
2831
+ }
2832
+ });
2833
+ return target;
2834
+ }
2816
2835
  function showLoading(parentElem, conf) {
2817
2836
  if (parentElem instanceof Context)
2818
2837
  parentElem = parentElem.$root;
@@ -3434,6 +3453,19 @@ class Api {
3434
3453
  return json.data || {};
3435
3454
  });
3436
3455
  }
3456
+ conf() {
3457
+ return __async(this, null, function* () {
3458
+ const data = yield POST(this.ctx, `${this.baseURL}/conf`);
3459
+ const conf = data.frontend_conf || {};
3460
+ if (conf.emoticons && typeof conf.emoticons === "string") {
3461
+ conf.emoticons = conf.emoticons.trim();
3462
+ if (conf.emoticons.startsWith("[") || conf.emoticons.startsWith("{")) {
3463
+ conf.emoticons = JSON.parse(conf.emoticons);
3464
+ }
3465
+ }
3466
+ return conf;
3467
+ });
3468
+ }
3437
3469
  captchaGet() {
3438
3470
  return __async(this, null, function* () {
3439
3471
  const data = yield POST(this.ctx, `${this.baseURL}/captcha/refresh`);
@@ -4013,15 +4045,26 @@ class Editor extends Component {
4013
4045
  const inputEl = this.getInputEl(field);
4014
4046
  if (inputEl && inputEl instanceof HTMLInputElement) {
4015
4047
  inputEl.value = this.user.data[field] || "";
4016
- inputEl.addEventListener("input", () => this.onHeaderInputChanged(field, inputEl));
4048
+ inputEl.addEventListener("input", () => this.onHeaderInput(field, inputEl));
4017
4049
  }
4018
4050
  });
4051
+ const $linkInput = this.getInputEl("link");
4052
+ if ($linkInput) {
4053
+ $linkInput.addEventListener("change", () => {
4054
+ const link = $linkInput.value.trim();
4055
+ if (!!link && !/^(http|https):\/\//.test(link)) {
4056
+ $linkInput.value = `https://${link}`;
4057
+ this.user.data.link = $linkInput.value;
4058
+ this.saveUser();
4059
+ }
4060
+ });
4061
+ }
4019
4062
  }
4020
4063
  getInputEl(field) {
4021
4064
  const inputEl = this.$header.querySelector(`[name="${field}"]`);
4022
4065
  return inputEl;
4023
4066
  }
4024
- onHeaderInputChanged(field, inputEl) {
4067
+ onHeaderInput(field, inputEl) {
4025
4068
  this.user.data[field] = inputEl.value.trim();
4026
4069
  if (field === "nick" || field === "email") {
4027
4070
  this.user.data.token = "";
@@ -4715,6 +4758,8 @@ class Comment extends Component {
4715
4758
  __publicField(this, "data");
4716
4759
  __publicField(this, "$main");
4717
4760
  __publicField(this, "$header");
4761
+ __publicField(this, "$headerNick");
4762
+ __publicField(this, "$headerBadge");
4718
4763
  __publicField(this, "$body");
4719
4764
  __publicField(this, "$content");
4720
4765
  __publicField(this, "$children");
@@ -4722,11 +4767,13 @@ class Comment extends Component {
4722
4767
  __publicField(this, "voteBtnUp");
4723
4768
  __publicField(this, "voteBtnDown");
4724
4769
  __publicField(this, "parent");
4725
- __publicField(this, "nestedNum");
4726
- __publicField(this, "maxNestingNum");
4770
+ __publicField(this, "nestCurt");
4771
+ __publicField(this, "nestMax");
4727
4772
  __publicField(this, "children", []);
4773
+ __publicField(this, "flatMode", false);
4728
4774
  __publicField(this, "replyTo");
4729
4775
  __publicField(this, "$replyTo");
4776
+ __publicField(this, "$replyAt");
4730
4777
  __publicField(this, "afterRender");
4731
4778
  __publicField(this, "unread", false);
4732
4779
  __publicField(this, "openable", false);
@@ -4734,11 +4781,11 @@ class Comment extends Component {
4734
4781
  __publicField(this, "openEvt");
4735
4782
  __publicField(this, "onReplyBtnClick");
4736
4783
  __publicField(this, "onDelete");
4737
- this.maxNestingNum = ctx.conf.maxNesting || 3;
4784
+ this.nestMax = ctx.conf.nestMax || 3;
4738
4785
  this.data = __spreadValues({}, data);
4739
4786
  this.data.date = this.data.date.replace(/-/g, "/");
4740
4787
  this.parent = null;
4741
- this.nestedNum = 1;
4788
+ this.nestCurt = 1;
4742
4789
  }
4743
4790
  render() {
4744
4791
  this.$el = createElement(CommentHTML);
@@ -4754,6 +4801,7 @@ class Comment extends Component {
4754
4801
  this.renderAvatar();
4755
4802
  this.renderHeader();
4756
4803
  this.renderContent();
4804
+ this.renderReplyAt();
4757
4805
  this.renderReplyTo();
4758
4806
  this.renderPending();
4759
4807
  this.renderActionBtn();
@@ -4796,26 +4844,27 @@ class Comment extends Component {
4796
4844
  }
4797
4845
  }
4798
4846
  renderHeader() {
4799
- const $nick = this.$el.querySelector(".atk-nick");
4847
+ this.$headerNick = this.$el.querySelector(".atk-nick");
4800
4848
  if (this.data.link) {
4801
4849
  const $nickA = createElement('<a target="_blank" rel="noreferrer noopener nofollow"></a>');
4802
4850
  $nickA.innerText = this.data.nick;
4803
4851
  $nickA.href = this.data.link;
4804
- $nick.append($nickA);
4852
+ this.$headerNick.append($nickA);
4805
4853
  } else {
4806
- $nick.innerText = this.data.nick;
4854
+ this.$headerNick.innerText = this.data.nick;
4807
4855
  }
4808
- const $badge = this.$el.querySelector(".atk-badge");
4856
+ this.$headerBadge = this.$el.querySelector(".atk-badge");
4809
4857
  if (this.data.badge_name) {
4810
- $badge.innerText = this.data.badge_name;
4858
+ this.$headerBadge.innerText = this.data.badge_name;
4811
4859
  if (this.data.badge_color)
4812
- $badge.style.backgroundColor = this.data.badge_color;
4860
+ this.$headerBadge.style.backgroundColor = this.data.badge_color;
4813
4861
  } else {
4814
- $badge.remove();
4862
+ this.$headerBadge.remove();
4863
+ this.$headerBadge = void 0;
4815
4864
  }
4816
4865
  if (this.data.is_pinned) {
4817
4866
  const $pinnedBadge = createElement(`<span class="atk-item atk-pinned-badge">\u7F6E\u9876</span>`);
4818
- $nick.insertAdjacentElement("afterend", $pinnedBadge);
4867
+ this.$headerNick.insertAdjacentElement("afterend", $pinnedBadge);
4819
4868
  }
4820
4869
  const $date = this.$el.querySelector(".atk-date");
4821
4870
  $date.innerText = this.getDateFormatted();
@@ -4858,7 +4907,24 @@ class Comment extends Component {
4858
4907
  }
4859
4908
  });
4860
4909
  }
4910
+ renderReplyAt() {
4911
+ if (this.flatMode || this.data.rid === 0)
4912
+ return;
4913
+ if (this.$replyAt)
4914
+ return;
4915
+ if (!this.replyTo)
4916
+ return;
4917
+ this.$replyAt = createElement(`<span class="atk-item atk-reply-at"><span class="atk-arrow"></span><span class="atk-nick"></span></span>`);
4918
+ this.$replyAt.querySelector(".atk-nick").innerText = `${this.replyTo.nick}`;
4919
+ this.$replyAt.onclick = () => {
4920
+ this.goToReplyComment();
4921
+ };
4922
+ const $after = this.$headerBadge || this.$headerNick;
4923
+ $after.insertAdjacentElement("afterend", this.$replyAt);
4924
+ }
4861
4925
  renderReplyTo() {
4926
+ if (!this.flatMode)
4927
+ return;
4862
4928
  if (!this.replyTo)
4863
4929
  return;
4864
4930
  this.$replyTo = createElement(`
@@ -4866,13 +4932,24 @@ class Comment extends Component {
4866
4932
  <div class="atk-meta">\u56DE\u590D <span class="atk-nick"></span>:</div>
4867
4933
  <div class="atk-content"></div>
4868
4934
  </div>`);
4869
- this.$replyTo.querySelector(".atk-nick").innerText = `@${this.replyTo.nick}`;
4935
+ const $nick = this.$replyTo.querySelector(".atk-nick");
4936
+ $nick.innerText = `@${this.replyTo.nick}`;
4937
+ $nick.onclick = () => {
4938
+ this.goToReplyComment();
4939
+ };
4870
4940
  let replyContent = marked(this.ctx, this.replyTo.content);
4871
4941
  if (this.replyTo.is_collapsed)
4872
4942
  replyContent = "[\u5DF2\u6298\u53E0]";
4873
4943
  this.$replyTo.querySelector(".atk-content").innerHTML = replyContent;
4874
4944
  this.$body.prepend(this.$replyTo);
4875
4945
  }
4946
+ goToReplyComment() {
4947
+ const origHash = window.location.hash;
4948
+ const modifyHash = `#atk-comment-${this.data.rid}`;
4949
+ window.location.hash = modifyHash;
4950
+ if (modifyHash === origHash)
4951
+ window.dispatchEvent(new Event("hashchange"));
4952
+ }
4876
4953
  renderPending() {
4877
4954
  if (!this.data.is_pending)
4878
4955
  return;
@@ -4967,19 +5044,23 @@ class Comment extends Component {
4967
5044
  getChildren() {
4968
5045
  return this.children;
4969
5046
  }
4970
- putChild(childC) {
5047
+ putChild(childC, insertMode = "append") {
4971
5048
  childC.parent = this;
4972
- childC.nestedNum = this.nestedNum + 1;
5049
+ childC.nestCurt = this.nestCurt + 1;
4973
5050
  this.children.push(childC);
4974
- this.getChildrenEl().appendChild(childC.getEl());
5051
+ const $children = this.getChildrenEl();
5052
+ if (insertMode === "append")
5053
+ $children.append(childC.getEl());
5054
+ else if (insertMode === "prepend")
5055
+ $children.prepend(childC.getEl());
4975
5056
  childC.playFadeInAnim();
4976
5057
  childC.checkHeightLimitArea("content");
4977
5058
  }
4978
5059
  getChildrenEl() {
4979
- if (this.$children === null) {
4980
- if (this.nestedNum < this.maxNestingNum) {
5060
+ if (!this.$children) {
5061
+ if (this.nestCurt < this.nestMax) {
4981
5062
  this.$children = createElement('<div class="atk-comment-children"></div>');
4982
- this.$main.appendChild(this.$children);
5063
+ this.$main.append(this.$children);
4983
5064
  } else if (this.parent) {
4984
5065
  this.$children = this.parent.getChildrenEl();
4985
5066
  }
@@ -5178,7 +5259,7 @@ class Pagination {
5178
5259
  this.$el = createElement(`<div class="atk-pagination-wrap">
5179
5260
  <div class="atk-pagination">
5180
5261
  <div class="atk-btn atk-btn-prev">Prev</div>
5181
- <input type="text" class="atk-input" />
5262
+ <input type="text" class="atk-input" aria-label="Enter the number of page" />
5182
5263
  <div class="atk-btn atk-btn-next">Next</div>
5183
5264
  </div>
5184
5265
  </div>`);
@@ -5357,16 +5438,68 @@ class ReadMoreBtn {
5357
5438
  this.hide();
5358
5439
  }
5359
5440
  }
5360
- const backendMinVersion = "2.1.2";
5441
+ function makeNestCommentNodeList(srcData, sortBy = "DATE_DESC", nestMax = 2) {
5442
+ const nodeList = [];
5443
+ const roots = srcData.filter((o) => o.rid === 0);
5444
+ roots.forEach((root) => {
5445
+ const rootNode = {
5446
+ id: root.id,
5447
+ comment: root,
5448
+ children: [],
5449
+ level: 1
5450
+ };
5451
+ rootNode.parent = rootNode;
5452
+ nodeList.push(rootNode);
5453
+ (function loadChildren(parentNode) {
5454
+ const children = srcData.filter((o) => o.rid === parentNode.id);
5455
+ if (children.length === 0)
5456
+ return;
5457
+ if (parentNode.level >= nestMax)
5458
+ parentNode = parentNode.parent;
5459
+ children.forEach((child) => {
5460
+ const childNode = {
5461
+ id: child.id,
5462
+ comment: child,
5463
+ children: [],
5464
+ parent: parentNode,
5465
+ level: parentNode.level + 1
5466
+ };
5467
+ parentNode.children.push(childNode);
5468
+ loadChildren(childNode);
5469
+ });
5470
+ })(rootNode);
5471
+ });
5472
+ const sortFunc = (a, b) => {
5473
+ let v = a.id - b.id;
5474
+ if (sortBy === "DATE_ASC")
5475
+ v = +new Date(a.comment.date) - +new Date(b.comment.date);
5476
+ else if (sortBy === "DATE_DESC")
5477
+ v = +new Date(b.comment.date) - +new Date(a.comment.date);
5478
+ else if (sortBy === "SRC_INDEX")
5479
+ v = srcData.indexOf(a.comment) - srcData.indexOf(b.comment);
5480
+ else if (sortBy === "VOTE_UP_DESC")
5481
+ v = b.comment.vote_up - a.comment.vote_up;
5482
+ return v;
5483
+ };
5484
+ (function sortLevels(nodes) {
5485
+ nodes.forEach((node) => {
5486
+ node.children = node.children.sort(sortFunc);
5487
+ sortLevels(node.children);
5488
+ });
5489
+ })(nodeList);
5490
+ return nodeList;
5491
+ }
5492
+ const backendMinVersion = "2.1.4";
5361
5493
  class ListLite extends Component {
5362
5494
  constructor(ctx) {
5363
5495
  super(ctx);
5364
5496
  __publicField(this, "$commentsWrap");
5365
- __publicField(this, "comments", []);
5497
+ __publicField(this, "commentList", []);
5366
5498
  __publicField(this, "data");
5367
5499
  __publicField(this, "isLoading", false);
5368
5500
  __publicField(this, "noCommentText", "\u65E0\u5185\u5BB9");
5369
5501
  __publicField(this, "flatMode", false);
5502
+ __publicField(this, "nestSortBy", "DATE_DESC");
5370
5503
  __publicField(this, "pageMode", "pagination");
5371
5504
  __publicField(this, "pageSize", 20);
5372
5505
  __publicField(this, "scrollListenerAt");
@@ -5393,6 +5526,9 @@ class ListLite extends Component {
5393
5526
  }, 30 * 1e3);
5394
5527
  this.ctx.on("unread-update", (data) => this.updateUnread(data.notifies));
5395
5528
  }
5529
+ get commentDataList() {
5530
+ return this.commentList.map((c) => c.data);
5531
+ }
5396
5532
  fetchComments(offset) {
5397
5533
  return __async(this, null, function* () {
5398
5534
  if (this.isLoading)
@@ -5447,7 +5583,7 @@ class ListLite extends Component {
5447
5583
  }
5448
5584
  this.data = data;
5449
5585
  const feMinVersion = ((_a = data.api_version) == null ? void 0 : _a.fe_min_version) || "0.0.0";
5450
- if (this.ctx.conf.versionCheck && this.versionCheck("\u524D\u7AEF", feMinVersion, "2.2.7"))
5586
+ if (this.ctx.conf.versionCheck && this.versionCheck("\u524D\u7AEF", feMinVersion, "2.2.10"))
5451
5587
  return;
5452
5588
  if (this.ctx.conf.versionCheck && this.versionCheck("\u540E\u7AEF", backendMinVersion, (_b = data.api_version) == null ? void 0 : _b.version))
5453
5589
  return;
@@ -5558,7 +5694,7 @@ class ListLite extends Component {
5558
5694
  setError(this.$el, $err);
5559
5695
  }
5560
5696
  refreshUI() {
5561
- const isNoComment = this.comments.length <= 0;
5697
+ const isNoComment = this.commentList.length <= 0;
5562
5698
  let $noComment = this.$commentsWrap.querySelector(".atk-list-no-comment");
5563
5699
  if (isNoComment) {
5564
5700
  if (!$noComment) {
@@ -5571,8 +5707,11 @@ class ListLite extends Component {
5571
5707
  }
5572
5708
  this.ctx.trigger("check-admin-show-el");
5573
5709
  }
5574
- createComment(data) {
5575
- const comment2 = new Comment(this.ctx, data);
5710
+ createComment(cData, ctxData) {
5711
+ if (!ctxData)
5712
+ ctxData = this.commentDataList;
5713
+ const comment2 = new Comment(this.ctx, cData);
5714
+ comment2.flatMode = this.flatMode;
5576
5715
  comment2.afterRender = () => {
5577
5716
  if (this.renderComment)
5578
5717
  this.renderComment(comment2);
@@ -5581,6 +5720,7 @@ class ListLite extends Component {
5581
5720
  this.deleteComment(c);
5582
5721
  this.refreshUI();
5583
5722
  };
5723
+ comment2.replyTo = cData.rid ? ctxData.find((c) => c.id === cData.rid) : void 0;
5584
5724
  return comment2;
5585
5725
  }
5586
5726
  importComments(srcData) {
@@ -5589,44 +5729,37 @@ class ListLite extends Component {
5589
5729
  this.putCommentFlatMode(commentData, srcData, "append");
5590
5730
  });
5591
5731
  } else {
5592
- this.importCommentsNesting(srcData);
5732
+ this.importCommentsNest(srcData);
5593
5733
  }
5594
5734
  }
5595
- importCommentsNesting(srcData) {
5596
- const loadChildren = (parentC) => {
5597
- const children = srcData.filter((o) => o.rid === parentC.data.id);
5598
- children.forEach((childData) => {
5599
- const childC = this.createComment(childData);
5600
- childC.render();
5601
- parentC.putChild(childC);
5602
- loadChildren(childC);
5603
- });
5604
- };
5605
- const rootComments = srcData.filter((o) => o.rid === 0);
5606
- rootComments.forEach((rootData) => {
5607
- const rootC = this.createComment(rootData);
5735
+ importCommentsNest(srcData) {
5736
+ const rootNodes = makeNestCommentNodeList(srcData, this.nestSortBy, this.conf.nestMax);
5737
+ rootNodes.forEach((rootNode) => {
5738
+ const rootC = this.createComment(rootNode.comment, srcData);
5608
5739
  rootC.render();
5609
5740
  this.$commentsWrap.appendChild(rootC.getEl());
5610
5741
  rootC.playFadeInAnim();
5611
- this.comments.push(rootC);
5612
- loadChildren(rootC);
5742
+ this.commentList.push(rootC);
5743
+ const that = this;
5744
+ (function loadChildren(parentC, parentNode) {
5745
+ parentNode.children.forEach((node) => {
5746
+ const childD = node.comment;
5747
+ const childC = that.createComment(childD, srcData);
5748
+ childC.render();
5749
+ parentC.putChild(childC);
5750
+ that.commentList.push(childC);
5751
+ loadChildren(childC, node);
5752
+ });
5753
+ })(rootC, rootNode);
5613
5754
  rootC.checkHeightLimit();
5614
5755
  });
5615
5756
  }
5616
- putCommentFlatMode(cData, srcData, insertMode) {
5757
+ putCommentFlatMode(cData, ctxData, insertMode) {
5617
5758
  if (cData.is_collapsed)
5618
5759
  cData.is_allow_reply = false;
5619
- const comment2 = this.createComment(cData);
5620
- if (cData.rid !== 0) {
5621
- const rComment = srcData.find((o) => o.id === cData.rid);
5622
- if (rComment)
5623
- comment2.replyTo = rComment;
5624
- }
5760
+ const comment2 = this.createComment(cData, ctxData);
5625
5761
  comment2.render();
5626
- if (insertMode === "append")
5627
- this.comments.push(comment2);
5628
- if (insertMode === "prepend")
5629
- this.comments.unshift(comment2);
5762
+ this.commentList.push(comment2);
5630
5763
  if (cData.visible) {
5631
5764
  if (insertMode === "append")
5632
5765
  this.$commentsWrap.append(comment2.getEl());
@@ -5640,14 +5773,15 @@ class ListLite extends Component {
5640
5773
  insertComment(commentData) {
5641
5774
  if (!this.flatMode) {
5642
5775
  const comment2 = this.createComment(commentData);
5643
- comment2.render();
5644
5776
  if (commentData.rid === 0) {
5777
+ comment2.render();
5645
5778
  this.$commentsWrap.prepend(comment2.getEl());
5646
- this.comments.unshift(comment2);
5779
+ this.commentList.push(comment2);
5647
5780
  } else {
5648
5781
  const parent = this.findComment(commentData.rid);
5649
5782
  if (parent) {
5650
- parent.putChild(comment2);
5783
+ comment2.render();
5784
+ parent.putChild(comment2, this.nestSortBy === "DATE_ASC" ? "append" : "prepend");
5651
5785
  comment2.getParents().forEach((p) => {
5652
5786
  if (p.$children)
5653
5787
  p.heightLimitRemove(p.$children);
@@ -5658,7 +5792,7 @@ class ListLite extends Component {
5658
5792
  scrollIntoView(comment2.getEl());
5659
5793
  comment2.playFadeInAnim();
5660
5794
  } else {
5661
- const comment2 = this.putCommentFlatMode(commentData, this.comments.map((c) => c.data), "prepend");
5795
+ const comment2 = this.putCommentFlatMode(commentData, this.commentDataList, "prepend");
5662
5796
  scrollIntoView(comment2.getEl());
5663
5797
  }
5664
5798
  if (this.data)
@@ -5666,45 +5800,20 @@ class ListLite extends Component {
5666
5800
  this.refreshUI();
5667
5801
  this.ctx.trigger("comments-loaded");
5668
5802
  }
5669
- eachComment(commentList, action) {
5670
- if (commentList.length === 0)
5671
- return;
5672
- commentList.every((item) => {
5673
- if (action(item, commentList) === false)
5674
- return false;
5675
- this.eachComment(item.getChildren(), action);
5676
- return true;
5677
- });
5678
- }
5679
- findComment(id, src) {
5680
- if (!src)
5681
- src = this.comments;
5682
- let comment2 = null;
5683
- this.eachComment(src, (item) => {
5684
- if (item.data.id === id) {
5685
- comment2 = item;
5686
- return false;
5687
- }
5688
- return true;
5689
- });
5690
- return comment2;
5803
+ findComment(id) {
5804
+ return this.commentList.find((c) => c.data.id === id);
5691
5805
  }
5692
- deleteComment(comment2) {
5693
- let findComment;
5694
- if (typeof comment2 === "number") {
5695
- findComment = this.findComment(comment2);
5806
+ deleteComment(_comment) {
5807
+ let comment2;
5808
+ if (typeof _comment === "number") {
5809
+ const findComment = this.findComment(_comment);
5696
5810
  if (!findComment)
5697
- throw Error(`\u672A\u627E\u5230\u8BC4\u8BBA ${comment2}`);
5811
+ throw Error(`\u672A\u627E\u5230\u8BC4\u8BBA ${_comment}`);
5812
+ comment2 = findComment;
5698
5813
  } else
5699
- findComment = comment2;
5700
- findComment.getEl().remove();
5701
- this.eachComment(this.comments, (item, levelList) => {
5702
- if (item === findComment) {
5703
- levelList.splice(levelList.indexOf(item), 1);
5704
- return false;
5705
- }
5706
- return true;
5707
- });
5814
+ comment2 = _comment;
5815
+ comment2.getEl().remove();
5816
+ this.commentList.splice(this.commentList.indexOf(comment2), 1);
5708
5817
  if (this.data)
5709
5818
  this.data.total -= 1;
5710
5819
  this.refreshUI();
@@ -5712,12 +5821,12 @@ class ListLite extends Component {
5712
5821
  clearAllComments() {
5713
5822
  this.$commentsWrap.innerHTML = "";
5714
5823
  this.data = void 0;
5715
- this.comments = [];
5824
+ this.commentList = [];
5716
5825
  }
5717
5826
  updateUnread(notifies) {
5718
5827
  this.unread = notifies;
5719
5828
  if (this.unreadHighlight === true) {
5720
- this.eachComment(this.comments, (comment2) => {
5829
+ this.commentList.forEach((comment2) => {
5721
5830
  const notify = this.unread.find((o) => o.comment_id === comment2.data.id);
5722
5831
  if (notify) {
5723
5832
  comment2.setUnread(true);
@@ -5761,6 +5870,8 @@ class List extends ListLite {
5761
5870
  __publicField(this, "$unreadBadge");
5762
5871
  __publicField(this, "$commentCount");
5763
5872
  __publicField(this, "$dropdownWrap");
5873
+ __publicField(this, "goToCommentFounded", false);
5874
+ __publicField(this, "goToCommentDelay", true);
5764
5875
  el.querySelector(".atk-list-body").append(this.$el);
5765
5876
  this.$el = el;
5766
5877
  let flatMode = false;
@@ -5779,7 +5890,7 @@ class List extends ListLite {
5779
5890
  if (this.ctx.conf.listSort) {
5780
5891
  this.initDropdown();
5781
5892
  }
5782
- this.$el.querySelector(".atk-copyright").innerHTML = `Powered By <a href="https://artalk.js.org" target="_blank" title="Artalk v${"2.2.7"}">Artalk</a>`;
5893
+ this.$el.querySelector(".atk-copyright").innerHTML = `Powered By <a href="https://artalk.js.org" target="_blank" title="Artalk v${"2.2.10"}">Artalk</a>`;
5783
5894
  this.ctx.on("list-reload", () => this.fetchComments(0));
5784
5895
  this.ctx.on("list-refresh-ui", () => this.refreshUI());
5785
5896
  this.ctx.on("list-import", (data) => this.importComments(data));
@@ -5829,36 +5940,55 @@ class List extends ListLite {
5829
5940
  }
5830
5941
  onLoad(data, offset) {
5831
5942
  super.onLoad(data, offset);
5832
- this.checkGoToCommentByUrlHash();
5943
+ if (!this.goToCommentFounded)
5944
+ this.checkGoToCommentByUrlHash();
5945
+ if (this.ctx.conf.editorTravel === true) {
5946
+ this.ctx.trigger("editor-travel-back");
5947
+ }
5833
5948
  }
5834
5949
  checkGoToCommentByUrlHash() {
5835
- return __async(this, null, function* () {
5836
- let commentId = Number(getQueryParam("atk_comment"));
5837
- if (!commentId) {
5838
- const match = window.location.hash.match(/#atk-comment-([0-9]+)/);
5839
- if (!match || !match[1] || Number.isNaN(Number(match[1])))
5840
- return;
5841
- commentId = Number(match[1]);
5842
- }
5843
- if (!commentId)
5950
+ let commentId = Number(getQueryParam("atk_comment"));
5951
+ if (!commentId) {
5952
+ const match = window.location.hash.match(/#atk-comment-([0-9]+)/);
5953
+ if (!match || !match[1] || Number.isNaN(Number(match[1])))
5844
5954
  return;
5845
- const notifyKey = getQueryParam("atk_notify_key");
5846
- if (notifyKey) {
5847
- new Api(this.ctx).markRead(notifyKey).then(() => {
5848
- this.unread = this.unread.filter((o) => o.comment_id !== commentId);
5849
- this.ctx.trigger("unread-update", {
5850
- notifies: this.unread
5851
- });
5955
+ commentId = Number(match[1]);
5956
+ }
5957
+ if (!commentId)
5958
+ return;
5959
+ const comment2 = this.findComment(commentId);
5960
+ if (!comment2) {
5961
+ if (this.readMoreBtn)
5962
+ this.readMoreBtn.click();
5963
+ else if (this.pagination)
5964
+ this.pagination.next();
5965
+ return;
5966
+ }
5967
+ const notifyKey = getQueryParam("atk_notify_key");
5968
+ if (notifyKey) {
5969
+ new Api(this.ctx).markRead(notifyKey).then(() => {
5970
+ this.unread = this.unread.filter((o) => o.comment_id !== commentId);
5971
+ this.ctx.trigger("unread-update", {
5972
+ notifies: this.unread
5852
5973
  });
5853
- }
5854
- const comment2 = this.findComment(commentId);
5855
- if (!comment2)
5856
- return;
5974
+ });
5975
+ }
5976
+ comment2.getParents().forEach((p) => {
5977
+ if (p.$children)
5978
+ p.heightLimitRemove(p.$children);
5979
+ });
5980
+ const goTo = () => {
5857
5981
  scrollIntoView(comment2.getEl(), false);
5982
+ comment2.getEl().classList.remove("atk-flash-once");
5858
5983
  window.setTimeout(() => {
5859
5984
  comment2.getEl().classList.add("atk-flash-once");
5860
- }, 800);
5861
- });
5985
+ }, 150);
5986
+ };
5987
+ if (!this.goToCommentDelay)
5988
+ goTo();
5989
+ else
5990
+ window.setTimeout(() => goTo(), 350);
5991
+ this.goToCommentFounded = true;
5862
5992
  }
5863
5993
  adminPageEditSave() {
5864
5994
  if (!this.data || !this.data.page)
@@ -6077,7 +6207,7 @@ const _Artalk = class {
6077
6207
  __publicField(this, "editor");
6078
6208
  __publicField(this, "list");
6079
6209
  __publicField(this, "sidebarLayer");
6080
- this.conf = __spreadValues(__spreadValues({}, _Artalk.defaults), customConf);
6210
+ this.conf = mergeDeep(_Artalk.defaults, customConf);
6081
6211
  this.conf.server = this.conf.server.replace(/\/$/, "").replace(/\/api\/?$/, "");
6082
6212
  if (!this.conf.pageKey) {
6083
6213
  this.conf.pageKey = `${window.location.pathname}`;
@@ -6085,6 +6215,9 @@ const _Artalk = class {
6085
6215
  if (!this.conf.pageTitle) {
6086
6216
  this.conf.pageTitle = `${document.title}`;
6087
6217
  }
6218
+ if (this.conf.nestMax && this.conf.nestMax <= 1) {
6219
+ this.conf.flatMode = true;
6220
+ }
6088
6221
  if (!!this.conf.el && this.conf.el instanceof HTMLElement) {
6089
6222
  this.$root = this.conf.el;
6090
6223
  } else {
@@ -6101,6 +6234,16 @@ const _Artalk = class {
6101
6234
  this.ctx = new Context(this.$root, this.conf);
6102
6235
  this.$root.classList.add("artalk");
6103
6236
  this.$root.innerHTML = "";
6237
+ if (this.conf.useBackendConf) {
6238
+ return (() => __async(this, null, function* () {
6239
+ yield this.loadConfRemote();
6240
+ this.initCore();
6241
+ return this;
6242
+ }))();
6243
+ }
6244
+ this.initCore();
6245
+ }
6246
+ initCore() {
6104
6247
  this.initLayer();
6105
6248
  this.initDarkMode();
6106
6249
  this.checkerLauncher = new CheckerLauncher(this.ctx);
@@ -6120,8 +6263,22 @@ const _Artalk = class {
6120
6263
  }
6121
6264
  });
6122
6265
  }
6266
+ loadConfRemote() {
6267
+ return __async(this, null, function* () {
6268
+ showLoading(this.$root);
6269
+ let backendConf = {};
6270
+ try {
6271
+ backendConf = yield new Api(this.ctx).conf();
6272
+ } catch (err) {
6273
+ console.error("\u914D\u7F6E\u8FDC\u7A0B\u83B7\u53D6\u5931\u8D25", err);
6274
+ }
6275
+ this.ctx.conf = mergeDeep(this.ctx.conf, backendConf);
6276
+ hideLoading(this.$root);
6277
+ });
6278
+ }
6123
6279
  initEventBind() {
6124
6280
  window.addEventListener("hashchange", () => {
6281
+ this.list.goToCommentDelay = false;
6125
6282
  this.list.checkGoToCommentByUrlHash();
6126
6283
  });
6127
6284
  this.ctx.on("check-admin-show-el", () => {