artalk 2.7.1 → 2.7.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.
Files changed (173) hide show
  1. package/README.md +1 -1
  2. package/dist/Artalk.css +1 -1
  3. package/dist/Artalk.es.js +155 -147
  4. package/dist/Artalk.es.js.map +1 -1
  5. package/dist/Artalk.iife.js +1 -1
  6. package/dist/Artalk.iife.js.map +1 -1
  7. package/dist/Artalk.js +1 -1
  8. package/dist/Artalk.js.map +1 -1
  9. package/dist/ArtalkLite.css +1 -1
  10. package/dist/ArtalkLite.es.js +155 -147
  11. package/dist/ArtalkLite.es.js.map +1 -1
  12. package/dist/ArtalkLite.iife.js +1 -1
  13. package/dist/ArtalkLite.iife.js.map +1 -1
  14. package/dist/ArtalkLite.js +1 -1
  15. package/dist/ArtalkLite.js.map +1 -1
  16. package/dist/i18n/jp.js +1 -1
  17. package/dist/i18n/zh-TW.js +1 -1
  18. package/dist/src/api/_base.d.ts +7 -0
  19. package/dist/src/api/_options.d.ts +5 -0
  20. package/dist/src/components/checker/index.d.ts +2 -0
  21. package/dist/src/i18n/en.d.ts +1 -0
  22. package/dist/src/i18n/external.d.ts +1 -0
  23. package/dist/src/i18n/index.d.ts +3 -0
  24. package/dist/src/i18n/jp.d.ts +1 -0
  25. package/dist/src/i18n/zh-TW.d.ts +1 -0
  26. package/dist/src/lib/user.d.ts +8 -6
  27. package/dist/src/plugins/editor/_kit.d.ts +7 -1
  28. package/dist/src/service.d.ts +2 -8
  29. package/dist/types/event.d.ts +1 -1
  30. package/package.json +43 -17
  31. package/dist/src/components/dark-mode.d.ts +0 -2
  32. package/src/api/_base.ts +0 -18
  33. package/src/api/_options.ts +0 -25
  34. package/src/api/_request.ts +0 -104
  35. package/src/api/admin.ts +0 -18
  36. package/src/api/captcha.ts +0 -24
  37. package/src/api/comment.ts +0 -84
  38. package/src/api/index.ts +0 -29
  39. package/src/api/page.ts +0 -83
  40. package/src/api/site.ts +0 -51
  41. package/src/api/system.ts +0 -49
  42. package/src/api/upload.ts +0 -28
  43. package/src/api/user.ts +0 -132
  44. package/src/artalk.ts +0 -115
  45. package/src/comment/actions.ts +0 -83
  46. package/src/comment/comment.html +0 -18
  47. package/src/comment/comment.ts +0 -192
  48. package/src/comment/height-limit.ts +0 -100
  49. package/src/comment/index.ts +0 -3
  50. package/src/comment/render.ts +0 -150
  51. package/src/comment/renders/actions.ts +0 -114
  52. package/src/comment/renders/avatar.ts +0 -22
  53. package/src/comment/renders/content.ts +0 -39
  54. package/src/comment/renders/header.ts +0 -84
  55. package/src/comment/renders/index.ts +0 -19
  56. package/src/comment/renders/pending.ts +0 -12
  57. package/src/comment/renders/reply-at.ts +0 -16
  58. package/src/comment/renders/reply-to.ts +0 -24
  59. package/src/components/action-btn.ts +0 -170
  60. package/src/components/checker/admin.ts +0 -37
  61. package/src/components/checker/captcha-renders.ts +0 -69
  62. package/src/components/checker/captcha.ts +0 -26
  63. package/src/components/checker/index.ts +0 -192
  64. package/src/components/dark-mode.ts +0 -30
  65. package/src/components/dialog.ts +0 -62
  66. package/src/components/error-dialog.ts +0 -35
  67. package/src/components/pagination.ts +0 -153
  68. package/src/components/read-more-btn.ts +0 -92
  69. package/src/config.ts +0 -119
  70. package/src/context.ts +0 -146
  71. package/src/data.ts +0 -110
  72. package/src/defaults.ts +0 -61
  73. package/src/editor/editor.html +0 -18
  74. package/src/editor/editor.ts +0 -114
  75. package/src/editor/state.ts +0 -52
  76. package/src/editor/ui.ts +0 -36
  77. package/src/i18n/en.ts +0 -84
  78. package/src/i18n/external.ts +0 -10
  79. package/src/i18n/index.ts +0 -67
  80. package/src/i18n/jp.ts +0 -86
  81. package/src/i18n/zh-CN.ts +0 -88
  82. package/src/i18n/zh-TW.ts +0 -86
  83. package/src/layer/index.ts +0 -4
  84. package/src/layer/layer-manager.ts +0 -32
  85. package/src/layer/layer.ts +0 -39
  86. package/src/layer/scrollbar-helper.ts +0 -24
  87. package/src/layer/sidebar-layer.html +0 -8
  88. package/src/layer/sidebar-layer.ts +0 -155
  89. package/src/layer/wrap.ts +0 -77
  90. package/src/lib/component.ts +0 -12
  91. package/src/lib/detect.ts +0 -222
  92. package/src/lib/event-manager.ts +0 -47
  93. package/src/lib/highlight.ts +0 -5
  94. package/src/lib/marked-renderer.ts +0 -32
  95. package/src/lib/marked.ts +0 -72
  96. package/src/lib/sanitizer.ts +0 -57
  97. package/src/lib/ui.ts +0 -193
  98. package/src/lib/user.ts +0 -55
  99. package/src/lib/utils.ts +0 -236
  100. package/src/list/comment.ts +0 -20
  101. package/src/list/layout.ts +0 -120
  102. package/src/list/list.html +0 -20
  103. package/src/list/list.ts +0 -79
  104. package/src/list/nest.ts +0 -66
  105. package/src/list/page.ts +0 -97
  106. package/src/list/paginator/index.ts +0 -25
  107. package/src/list/paginator/read-more.ts +0 -67
  108. package/src/list/paginator/up-down.ts +0 -51
  109. package/src/main.ts +0 -14
  110. package/src/plugins/admin-only-elem.ts +0 -40
  111. package/src/plugins/conf-remoter.ts +0 -54
  112. package/src/plugins/dark-mode.ts +0 -12
  113. package/src/plugins/editor/_kit.ts +0 -57
  114. package/src/plugins/editor/_plug.ts +0 -60
  115. package/src/plugins/editor/_sample.ts +0 -8
  116. package/src/plugins/editor/closable.ts +0 -44
  117. package/src/plugins/editor/emoticons.scss +0 -72
  118. package/src/plugins/editor/emoticons.ts +0 -293
  119. package/src/plugins/editor/header-event.ts +0 -35
  120. package/src/plugins/editor/header-link.ts +0 -31
  121. package/src/plugins/editor/header-user.ts +0 -98
  122. package/src/plugins/editor/index.ts +0 -40
  123. package/src/plugins/editor/local-storage.ts +0 -36
  124. package/src/plugins/editor/mover.ts +0 -29
  125. package/src/plugins/editor/preview.scss +0 -7
  126. package/src/plugins/editor/preview.ts +0 -41
  127. package/src/plugins/editor/state-edit.ts +0 -116
  128. package/src/plugins/editor/state-reply.ts +0 -91
  129. package/src/plugins/editor/submit-add.ts +0 -33
  130. package/src/plugins/editor/submit-btn.ts +0 -25
  131. package/src/plugins/editor/submit.ts +0 -73
  132. package/src/plugins/editor/textarea.ts +0 -55
  133. package/src/plugins/editor/upload.ts +0 -145
  134. package/src/plugins/editor-kit.ts +0 -161
  135. package/src/plugins/index.ts +0 -16
  136. package/src/plugins/list/copyright.ts +0 -16
  137. package/src/plugins/list/count.ts +0 -31
  138. package/src/plugins/list/dropdown.ts +0 -95
  139. package/src/plugins/list/error-dialog.ts +0 -22
  140. package/src/plugins/list/fetch.ts +0 -64
  141. package/src/plugins/list/goto-first.ts +0 -23
  142. package/src/plugins/list/goto.ts +0 -72
  143. package/src/plugins/list/index.ts +0 -25
  144. package/src/plugins/list/loading.ts +0 -17
  145. package/src/plugins/list/no-comment.ts +0 -25
  146. package/src/plugins/list/reach-bottom.ts +0 -46
  147. package/src/plugins/list/sidebar-btn.ts +0 -39
  148. package/src/plugins/list/time-ticking.ts +0 -22
  149. package/src/plugins/list/unread-badge.ts +0 -26
  150. package/src/plugins/list/unread.ts +0 -38
  151. package/src/plugins/list/with-editor.ts +0 -59
  152. package/src/plugins/markdown.ts +0 -10
  153. package/src/plugins/stat.ts +0 -82
  154. package/src/plugins/version-check.ts +0 -36
  155. package/src/service.ts +0 -91
  156. package/src/style/_color.scss +0 -41
  157. package/src/style/_extend.scss +0 -20
  158. package/src/style/_variables.scss +0 -3
  159. package/src/style/comment.scss +0 -360
  160. package/src/style/editor.scss +0 -194
  161. package/src/style/list.scss +0 -212
  162. package/src/style/main.scss +0 -486
  163. package/src/style/pagination.scss +0 -58
  164. package/src/style/sidebar-layer.scss +0 -92
  165. package/types/config.ts +0 -153
  166. package/types/context.ts +0 -84
  167. package/types/data.ts +0 -271
  168. package/types/editor.ts +0 -95
  169. package/types/event.ts +0 -40
  170. package/types/global.d.ts +0 -1
  171. package/types/index.ts +0 -7
  172. package/types/plugin.ts +0 -3
  173. package/types/sidebar.ts +0 -3
package/dist/Artalk.es.js CHANGED
@@ -55,7 +55,6 @@ var __async = (__this, __arguments, generator) => {
55
55
  });
56
56
  };
57
57
  var _parseMarkdown, parseMarkdown_fn, _onError, onError_fn;
58
- const main = "";
59
58
  function createElement(htmlStr = "") {
60
59
  const div = document.createElement("div");
61
60
  div.innerHTML = htmlStr.trim();
@@ -642,48 +641,6 @@ function getDefaultExportFromCjs(x) {
642
641
  });
643
642
  })(typeof self !== "undefined" ? self : commonjsGlobal);
644
643
  });
645
- const LOCAL_USER_KEY = "ArtalkUser";
646
- class User {
647
- constructor() {
648
- __publicField(this, "data");
649
- __publicField(this, "onUserChanged", null);
650
- const localUser = JSON.parse(window.localStorage.getItem(LOCAL_USER_KEY) || "{}");
651
- this.data = {
652
- nick: localUser.nick || "",
653
- email: localUser.email || "",
654
- link: localUser.link || "",
655
- token: localUser.token || "",
656
- isAdmin: localUser.isAdmin || false
657
- };
658
- }
659
- /** 保存用户到 localStorage 中 */
660
- update(obj = {}) {
661
- Object.entries(obj).forEach(([key, value]) => {
662
- this.data[key] = value;
663
- });
664
- window.localStorage.setItem(LOCAL_USER_KEY, JSON.stringify(this.data));
665
- this.onUserChanged && this.onUserChanged(this.data);
666
- }
667
- setOnUserChanged(fn) {
668
- this.onUserChanged = fn;
669
- }
670
- /**
671
- * Logout
672
- *
673
- * @description Logout will clear login status, but not clear user data (nick, email, link)
674
- */
675
- logout() {
676
- this.update({
677
- token: "",
678
- isAdmin: false
679
- });
680
- }
681
- /** 是否已填写基本用户信息 */
682
- checkHasBasicUserInfo() {
683
- return !!this.data.nick && !!this.data.email;
684
- }
685
- }
686
- const UserInstance = new User();
687
644
  const en = {
688
645
  /* Editor */
689
646
  placeholder: "Leave a comment",
@@ -760,7 +717,8 @@ const en = {
760
717
  reqAborted: "Request timed out or terminated unexpectedly",
761
718
  updateMsg: "Please update Artalk {name} to get the full experience",
762
719
  currentVersion: "Current Version",
763
- ignore: "Ignore"
720
+ ignore: "Ignore",
721
+ open: "Open"
764
722
  };
765
723
  const zhCN = {
766
724
  /* Editor */
@@ -838,7 +796,8 @@ const zhCN = {
838
796
  reqAborted: "请求超时或意外终止",
839
797
  updateMsg: "请更新 Artalk {name} 以获得完整体验",
840
798
  currentVersion: "当前版本",
841
- ignore: "忽略"
799
+ ignore: "忽略",
800
+ open: "打开"
842
801
  };
843
802
  const GLOBAL_LOCALES_KEY = "ArtalkI18n";
844
803
  const internal = {
@@ -875,9 +834,9 @@ function t(key, args = {}) {
875
834
  function Fetch$1(opts, input, init2, timeout) {
876
835
  return __async(this, null, function* () {
877
836
  var _a, _b;
878
- if (UserInstance.data.token) {
837
+ if (opts.apiToken) {
879
838
  const headers = new Headers(init2.headers);
880
- headers.set("Authorization", `Bearer ${UserInstance.data.token}`);
839
+ headers.set("Authorization", `Bearer ${opts.apiToken}`);
881
840
  init2.headers = headers;
882
841
  }
883
842
  const resp = yield timeoutFetch(input, timeout || opts.timeout || 15e3, init2);
@@ -969,6 +928,20 @@ class ApiBase {
969
928
  return Fetch$1(this.options, this.options.baseURL + path, init2, timeout);
970
929
  });
971
930
  }
931
+ /**
932
+ * Carry user info to request params
933
+ *
934
+ * @param params Request params
935
+ * @returns Request params with user info
936
+ */
937
+ withUserInfo(params) {
938
+ const user = this.options.userInfo;
939
+ if (user == null ? void 0 : user.name)
940
+ params.name = user.name;
941
+ if (user == null ? void 0 : user.email)
942
+ params.email = user.email;
943
+ return params;
944
+ }
972
945
  }
973
946
  class CommentApi extends ApiBase {
974
947
  /** 评论 · 获取 */
@@ -981,10 +954,7 @@ class CommentApi extends ApiBase {
981
954
  };
982
955
  if (flatMode)
983
956
  params.flat_mode = flatMode;
984
- if (UserInstance.checkHasBasicUserInfo()) {
985
- params.name = UserInstance.data.nick;
986
- params.email = UserInstance.data.email;
987
- }
957
+ this.withUserInfo(params);
988
958
  if (paramsEditor)
989
959
  paramsEditor(params);
990
960
  return this.POST("/get", params);
@@ -1033,10 +1003,7 @@ class CommentApi extends ApiBase {
1033
1003
  target_id: targetID,
1034
1004
  type
1035
1005
  };
1036
- if (UserInstance.checkHasBasicUserInfo()) {
1037
- params.name = UserInstance.data.nick;
1038
- params.email = UserInstance.data.email;
1039
- }
1006
+ this.withUserInfo(params);
1040
1007
  const data = yield this.POST("/vote", params);
1041
1008
  return data;
1042
1009
  });
@@ -1205,10 +1172,7 @@ class UserApi extends ApiBase {
1205
1172
  /** 用户 · 登录状态 */
1206
1173
  loginStatus() {
1207
1174
  return __async(this, null, function* () {
1208
- const data = yield this.POST("/login-status", {
1209
- name: UserInstance.data.nick,
1210
- email: UserInstance.data.email
1211
- });
1175
+ const data = yield this.POST("/login-status", this.withUserInfo({}));
1212
1176
  return data || { is_login: false, is_admin: false };
1213
1177
  });
1214
1178
  }
@@ -1228,8 +1192,7 @@ class UserApi extends ApiBase {
1228
1192
  delete params.comment_id;
1229
1193
  delete params.notify_key;
1230
1194
  params.read_all = true;
1231
- params.name = UserInstance.data.nick;
1232
- params.email = UserInstance.data.email;
1195
+ this.withUserInfo(params);
1233
1196
  }
1234
1197
  return this.POST(`/mark-read`, params);
1235
1198
  }
@@ -1366,10 +1329,9 @@ class UploadApi extends ApiBase {
1366
1329
  imgUpload(file) {
1367
1330
  return __async(this, null, function* () {
1368
1331
  const params = {
1369
- name: UserInstance.data.nick,
1370
- email: UserInstance.data.email,
1371
1332
  page_key: this.options.pageKey
1372
1333
  };
1334
+ this.withUserInfo(params);
1373
1335
  const form = ToFormData(params);
1374
1336
  form.set("file", file);
1375
1337
  const init2 = {
@@ -4431,6 +4393,11 @@ function convertApiOptions(conf, ctx) {
4431
4393
  pageKey: conf.pageKey || "",
4432
4394
  pageTitle: conf.pageTitle || "",
4433
4395
  timeout: conf.reqTimeout,
4396
+ apiToken: ctx == null ? void 0 : ctx.get("user").getData().token,
4397
+ userInfo: (ctx == null ? void 0 : ctx.get("user").checkHasBasicUserInfo()) ? {
4398
+ name: ctx == null ? void 0 : ctx.get("user").getData().nick,
4399
+ email: ctx == null ? void 0 : ctx.get("user").getData().email
4400
+ } : void 0,
4434
4401
  onNeedCheckAdmin(payload) {
4435
4402
  ctx == null ? void 0 : ctx.checkAdmin({
4436
4403
  onSuccess: () => {
@@ -4494,7 +4461,7 @@ class Context {
4494
4461
  this.data.fetchComments({ offset: 0 });
4495
4462
  }
4496
4463
  listGotoFirst() {
4497
- this.trigger("list-goto-first");
4464
+ this.events.trigger("list-goto-first");
4498
4465
  }
4499
4466
  /* 编辑器 */
4500
4467
  editorShowLoading() {
@@ -4539,11 +4506,11 @@ class Context {
4539
4506
  }
4540
4507
  setDarkMode(darkMode) {
4541
4508
  this.conf.darkMode = darkMode;
4542
- this.trigger("dark-mode-changed", darkMode);
4509
+ this.events.trigger("dark-mode-changed", darkMode);
4543
4510
  }
4544
4511
  updateConf(nConf) {
4545
4512
  this.conf = mergeDeep(this.conf, handelCustomConf(nConf));
4546
- this.trigger("conf-loaded", this.conf);
4513
+ this.events.trigger("conf-loaded", this.conf);
4547
4514
  }
4548
4515
  getMarked() {
4549
4516
  return getInstance();
@@ -4750,7 +4717,7 @@ function imgBody(checker) {
4750
4717
  }
4751
4718
  function iframeBody(checker) {
4752
4719
  const $iframeWrap = createElement(`<div class="atk-checker-iframe-wrap"></div>`);
4753
- const $iframe = createElement(`<iframe class="atk-fade-in"></iframe>`);
4720
+ const $iframe = createElement(`<iframe class="atk-fade-in" referrerpolicy="strict-origin-when-cross-origin"></iframe>`);
4754
4721
  $iframe.style.display = "none";
4755
4722
  showLoading($iframeWrap, { transparentBg: true });
4756
4723
  $iframe.src = `${checker.getOpts().getIframeURLBase() || ""}/api/captcha/get?t=${+/* @__PURE__ */ new Date()}`;
@@ -4814,8 +4781,8 @@ const AdminChecker = {
4814
4781
  inputType: "password",
4815
4782
  request(checker, inputVal) {
4816
4783
  const data = {
4817
- name: UserInstance.data.nick,
4818
- email: UserInstance.data.email,
4784
+ name: checker.getUser().getData().nick,
4785
+ email: checker.getUser().getData().email,
4819
4786
  password: inputVal
4820
4787
  };
4821
4788
  return (() => __async(this, null, function* () {
@@ -4827,7 +4794,7 @@ const AdminChecker = {
4827
4794
  return createElement(`<span>${t("adminCheck")}</span>`);
4828
4795
  },
4829
4796
  onSuccess(checker, userToken, inputVal, formEl) {
4830
- UserInstance.update({
4797
+ checker.getUser().update({
4831
4798
  isAdmin: true,
4832
4799
  token: userToken
4833
4800
  });
@@ -4860,6 +4827,7 @@ class CheckerLauncher {
4860
4827
  },
4861
4828
  get: (key) => checkerStore[key],
4862
4829
  getOpts: () => this.opts,
4830
+ getUser: () => this.opts.getCtx().get("user"),
4863
4831
  getApi: () => this.opts.getApi(),
4864
4832
  hideInteractInput: () => {
4865
4833
  hideInteractInput = true;
@@ -5251,7 +5219,7 @@ class SidebarLayer extends Component {
5251
5219
  });
5252
5220
  }
5253
5221
  createIframe(view) {
5254
- const $iframe = createElement("<iframe></iframe>");
5222
+ const $iframe = createElement('<iframe referrerpolicy="strict-origin-when-cross-origin"></iframe>');
5255
5223
  const baseURL = getURLBasedOnApi({
5256
5224
  base: this.ctx.conf.server,
5257
5225
  path: "/sidebar/"
@@ -5259,7 +5227,7 @@ class SidebarLayer extends Component {
5259
5227
  const query = {
5260
5228
  pageKey: this.conf.pageKey,
5261
5229
  site: this.conf.site || "",
5262
- user: JSON.stringify(UserInstance.data),
5230
+ user: JSON.stringify(this.ctx.get("user").getData()),
5263
5231
  time: +/* @__PURE__ */ new Date()
5264
5232
  };
5265
5233
  if (view)
@@ -5336,7 +5304,7 @@ class ListLayout {
5336
5304
  constructor(options) {
5337
5305
  this.options = options;
5338
5306
  }
5339
- // TODO refactor `if syntax` to strategy pattern
5307
+ // TODO: refactor `if syntax` to strategy pattern
5340
5308
  import(comments) {
5341
5309
  if (this.options.flatMode) {
5342
5310
  comments.forEach((commentData) => {
@@ -5412,9 +5380,9 @@ class ListLayout {
5412
5380
  scrollIntoView(comment.getEl());
5413
5381
  }
5414
5382
  }
5415
- const win = window || {};
5416
- const nav = navigator || {};
5417
5383
  function Detect(userAgent) {
5384
+ const win = window || {};
5385
+ const nav = navigator || {};
5418
5386
  const u = String(userAgent || nav.userAgent);
5419
5387
  const dest = {
5420
5388
  os: "",
@@ -6763,20 +6731,6 @@ const initListPaginatorFunc = (ctx) => {
6763
6731
  var _a;
6764
6732
  (_a = paginator == null ? void 0 : paginator.showErr) == null ? void 0 : _a.call(paginator, t("loadFail"));
6765
6733
  });
6766
- const autoSwitchPageForFindComment = (commentID) => {
6767
- const comment = ctx.getData().findComment(commentID);
6768
- if (!!comment || !(paginator == null ? void 0 : paginator.getHasMore()))
6769
- return;
6770
- ctx.on("list-loaded", () => {
6771
- autoSwitchPageForFindComment(commentID);
6772
- }, { once: true });
6773
- setTimeout(() => {
6774
- paginator == null ? void 0 : paginator.next();
6775
- }, 80);
6776
- };
6777
- ctx.on("list-goto", (commentID) => {
6778
- autoSwitchPageForFindComment(commentID);
6779
- });
6780
6734
  ctx.on("list-fetch", (params) => {
6781
6735
  paginator == null ? void 0 : paginator.setLoading(true);
6782
6736
  });
@@ -6974,6 +6928,47 @@ class LayerManager {
6974
6928
  return layer;
6975
6929
  }
6976
6930
  }
6931
+ const LOCAL_USER_KEY = "ArtalkUser";
6932
+ class User {
6933
+ constructor(opts) {
6934
+ __publicField(this, "data");
6935
+ this.opts = opts;
6936
+ const localUser = JSON.parse(window.localStorage.getItem(LOCAL_USER_KEY) || "{}");
6937
+ this.data = {
6938
+ nick: localUser.nick || "",
6939
+ email: localUser.email || "",
6940
+ link: localUser.link || "",
6941
+ token: localUser.token || "",
6942
+ isAdmin: localUser.isAdmin || false
6943
+ };
6944
+ }
6945
+ getData() {
6946
+ return this.data;
6947
+ }
6948
+ /** 保存用户到 localStorage 中 */
6949
+ update(obj = {}) {
6950
+ Object.entries(obj).forEach(([key, value]) => {
6951
+ this.data[key] = value;
6952
+ });
6953
+ window.localStorage.setItem(LOCAL_USER_KEY, JSON.stringify(this.data));
6954
+ this.opts.onUserChanged && this.opts.onUserChanged(this.data);
6955
+ }
6956
+ /**
6957
+ * Logout
6958
+ *
6959
+ * @description Logout will clear login status, but not clear user data (nick, email, link)
6960
+ */
6961
+ logout() {
6962
+ this.update({
6963
+ token: "",
6964
+ isAdmin: false
6965
+ });
6966
+ }
6967
+ /** 是否已填写基本用户信息 */
6968
+ checkHasBasicUserInfo() {
6969
+ return !!this.data.nick && !!this.data.email;
6970
+ }
6971
+ }
6977
6972
  const services = {
6978
6973
  // I18n
6979
6974
  i18n(ctx) {
@@ -6984,10 +6979,12 @@ const services = {
6984
6979
  },
6985
6980
  // User Store
6986
6981
  user(ctx) {
6987
- UserInstance.setOnUserChanged((user) => {
6988
- ctx == null ? void 0 : ctx.trigger("user-changed", user);
6982
+ const user = new User({
6983
+ onUserChanged: (data) => {
6984
+ ctx.trigger("user-changed", data);
6985
+ }
6989
6986
  });
6990
- return UserInstance;
6987
+ return user;
6991
6988
  },
6992
6989
  // 弹出层
6993
6990
  layerManager(ctx) {
@@ -7037,11 +7034,8 @@ function showErrorDialog(opts) {
7037
7034
  errEl.appendChild($retryBtn);
7038
7035
  }
7039
7036
  if (opts.onOpenSidebar) {
7040
- const $openSidebar = createElement('<span atk-only-admin-show> | <span style="cursor:pointer;">打开控制台</span></span>');
7037
+ const $openSidebar = createElement(`<span atk-only-admin-show> | <span style="cursor:pointer;">${t("open") + t("ctrlCenter")}</span></span>`);
7041
7038
  errEl.appendChild($openSidebar);
7042
- if (!UserInstance.data.isAdmin) {
7043
- $openSidebar.classList.add("atk-hide");
7044
- }
7045
7039
  $openSidebar.onclick = () => opts.onOpenSidebar && opts.onOpenSidebar();
7046
7040
  }
7047
7041
  setError(opts.$err, errEl);
@@ -7077,9 +7071,10 @@ function loadConf(ctx) {
7077
7071
  errMsg: err.msg || String(err),
7078
7072
  errData: err.data,
7079
7073
  retryFn: () => loadConf(ctx),
7080
- onOpenSidebar: () => ctx.showSidebar({
7074
+ onOpenSidebar: ctx.get("user").getData().isAdmin ? () => ctx.showSidebar({
7081
7075
  view: sidebarOpenView
7082
- })
7076
+ }) : void 0
7077
+ // only show open sidebar button when user is admin
7083
7078
  });
7084
7079
  throw err;
7085
7080
  }).then(() => {
@@ -7184,7 +7179,7 @@ class SubmitAddPreset {
7184
7179
  });
7185
7180
  }
7186
7181
  getSubmitAddParams() {
7187
- const { nick, email, link } = UserInstance.data;
7182
+ const { nick, email, link } = this.kit.useUser().getData();
7188
7183
  const conf = this.kit.useConf();
7189
7184
  return {
7190
7185
  content: this.kit.useEditor().getContentFinal(),
@@ -7382,7 +7377,7 @@ class StateEdit extends EditorPlug {
7382
7377
  ui.$editCancelBtn = void 0;
7383
7378
  }
7384
7379
  this.comment = void 0;
7385
- const { nick, email, link } = UserInstance.data;
7380
+ const { nick, email, link } = this.kit.useUser().getData();
7386
7381
  ui.$nick.value = nick;
7387
7382
  ui.$email.value = email;
7388
7383
  ui.$link.value = link;
@@ -7421,7 +7416,7 @@ class Closable extends EditorPlug {
7421
7416
  close() {
7422
7417
  if (!this.kit.useUI().$textareaWrap.querySelector(".atk-comment-closed"))
7423
7418
  this.kit.useUI().$textareaWrap.prepend(createElement(`<div class="atk-comment-closed">${t("onlyAdminCanReply")}</div>`));
7424
- if (!UserInstance.data.isAdmin) {
7419
+ if (!this.kit.useUser().getData().isAdmin) {
7425
7420
  this.kit.useUI().$textarea.style.display = "none";
7426
7421
  this.kit.useEvents().trigger("panel-close");
7427
7422
  this.kit.useUI().$bottom.style.display = "none";
@@ -7466,14 +7461,14 @@ class HeaderUser extends EditorPlug {
7466
7461
  const onInput = ({ $input, field }) => {
7467
7462
  if (this.kit.useEditor().getState() === "edit")
7468
7463
  return;
7469
- UserInstance.update({ [field]: $input.value.trim() });
7464
+ this.kit.useUser().update({ [field]: $input.value.trim() });
7470
7465
  if (field === "nick" || field === "email")
7471
7466
  this.fetchUserInfo();
7472
7467
  };
7473
7468
  this.kit.useMounted(() => {
7474
7469
  Object.entries(this.kit.useEditor().getHeaderInputEls()).forEach(([key, $input]) => {
7475
7470
  $input.placeholder = `${t(key)}`;
7476
- $input.value = UserInstance.data[key] || "";
7471
+ $input.value = this.kit.useUser().getData()[key] || "";
7477
7472
  });
7478
7473
  this.kit.useEvents().on("header-input", onInput);
7479
7474
  });
@@ -7485,7 +7480,7 @@ class HeaderUser extends EditorPlug {
7485
7480
  * Fetch user info from server
7486
7481
  */
7487
7482
  fetchUserInfo() {
7488
- UserInstance.logout();
7483
+ this.kit.useUser().logout();
7489
7484
  if (this.query.timer)
7490
7485
  window.clearTimeout(this.query.timer);
7491
7486
  if (this.query.abortFn)
@@ -7493,8 +7488,8 @@ class HeaderUser extends EditorPlug {
7493
7488
  this.query.timer = window.setTimeout(() => {
7494
7489
  this.query.timer = null;
7495
7490
  const { req, abort } = this.kit.useApi().user.userGet(
7496
- UserInstance.data.nick,
7497
- UserInstance.data.email
7491
+ this.kit.useUser().getData().nick,
7492
+ this.kit.useUser().getData().email
7498
7493
  );
7499
7494
  this.query.abortFn = abort;
7500
7495
  req.then((data) => this.onUserInfoFetched(data)).catch((err) => {
@@ -7511,9 +7506,9 @@ class HeaderUser extends EditorPlug {
7511
7506
  onUserInfoFetched(data) {
7512
7507
  var _a;
7513
7508
  if (!data.is_login)
7514
- UserInstance.logout();
7509
+ this.kit.useUser().logout();
7515
7510
  this.kit.useGlobalCtx().getData().updateUnreads(data.unread);
7516
- if (UserInstance.checkHasBasicUserInfo() && !data.is_login && ((_a = data.user) == null ? void 0 : _a.is_admin)) {
7511
+ if (this.kit.useUser().checkHasBasicUserInfo() && !data.is_login && ((_a = data.user) == null ? void 0 : _a.is_admin)) {
7517
7512
  this.kit.useGlobalCtx().checkAdmin({
7518
7513
  onSuccess: () => {
7519
7514
  }
@@ -7521,7 +7516,7 @@ class HeaderUser extends EditorPlug {
7521
7516
  }
7522
7517
  if (data.user && data.user.link) {
7523
7518
  this.kit.useUI().$link.value = data.user.link;
7524
- UserInstance.update({ link: data.user.link });
7519
+ this.kit.useUser().update({ link: data.user.link });
7525
7520
  }
7526
7521
  }
7527
7522
  }
@@ -7543,11 +7538,10 @@ class HeaderLink extends EditorPlug {
7543
7538
  const link = this.kit.useUI().$link.value.trim();
7544
7539
  if (!!link && !/^(http|https):\/\//.test(link)) {
7545
7540
  this.kit.useUI().$link.value = `https://${link}`;
7546
- UserInstance.update({ link: this.kit.useUI().$link.value });
7541
+ this.kit.useUser().update({ link: this.kit.useUI().$link.value });
7547
7542
  }
7548
7543
  }
7549
7544
  }
7550
- const emoticons = "";
7551
7545
  class Emoticons extends EditorPlug {
7552
7546
  constructor(kit) {
7553
7547
  super(kit);
@@ -7663,7 +7657,8 @@ class Emoticons extends EditorPlug {
7663
7657
  return json;
7664
7658
  } catch (err) {
7665
7659
  hideLoading(this.$panel);
7666
- setError(this.$panel, `表情加载失败 ${String(err)}`);
7660
+ console.error("[Emoticons] Load Failed:", err);
7661
+ setError(this.$panel, `${t("emoticon")}${t("loadFail")} ${String(err)}`);
7667
7662
  return [];
7668
7663
  }
7669
7664
  });
@@ -7872,7 +7867,7 @@ class Upload extends EditorPlug {
7872
7867
  const fileExt = /[^.]+$/.exec(file.name);
7873
7868
  if (!fileExt || !AllowImgExts.includes(fileExt[0]))
7874
7869
  return;
7875
- if (!UserInstance.checkHasBasicUserInfo()) {
7870
+ if (!this.kit.useUser().checkHasBasicUserInfo()) {
7876
7871
  this.kit.useEditor().showNotify(t("uploadLoginMsg"), "w");
7877
7872
  return;
7878
7873
  }
@@ -7907,7 +7902,6 @@ class Upload extends EditorPlug {
7907
7902
  });
7908
7903
  }
7909
7904
  }
7910
- const preview = "";
7911
7905
  class Preview extends EditorPlug {
7912
7906
  constructor(kit) {
7913
7907
  super(kit);
@@ -7970,7 +7964,11 @@ class PlugKit {
7970
7964
  useEditor() {
7971
7965
  return this.plugs.editor;
7972
7966
  }
7973
- /** Use the context of global */
7967
+ /**
7968
+ * Use the context of global
7969
+ *
7970
+ * @deprecated The calls to this function should be reduced as much as possible
7971
+ */
7974
7972
  useGlobalCtx() {
7975
7973
  return this.plugs.editor.ctx;
7976
7974
  }
@@ -7982,6 +7980,10 @@ class PlugKit {
7982
7980
  useApi() {
7983
7981
  return this.plugs.editor.ctx.getApi();
7984
7982
  }
7983
+ /** Use the user manager */
7984
+ useUser() {
7985
+ return this.plugs.editor.ctx.get("user");
7986
+ }
7985
7987
  /** Use the ui of editor */
7986
7988
  useUI() {
7987
7989
  return this.plugs.editor.getUI();
@@ -8199,7 +8201,7 @@ const SidebarBtn = (ctx) => {
8199
8201
  const syncByUser = () => {
8200
8202
  if (!$openSidebarBtn)
8201
8203
  return;
8202
- const user = ctx.get("user").data;
8204
+ const user = ctx.get("user").getData();
8203
8205
  if (!!user.nick && !!user.email) {
8204
8206
  $openSidebarBtn.classList.remove("atk-hide");
8205
8207
  const $btnText = $openSidebarBtn.querySelector(".atk-text");
@@ -8298,7 +8300,7 @@ function extractCommentID() {
8298
8300
  }
8299
8301
  return commentId || null;
8300
8302
  }
8301
- const version = "2.7.1";
8303
+ const version = "2.7.2";
8302
8304
  const Copyright = (ctx) => {
8303
8305
  ctx.on("conf-loaded", () => {
8304
8306
  const list = ctx.get("list");
@@ -8631,7 +8633,7 @@ function versionCheck(list, feVer, beVer) {
8631
8633
  }
8632
8634
  const AdminOnlyElem = (ctx) => {
8633
8635
  const scanApply = () => {
8634
- applyAdminOnlyEls(ctx.get("user").data.isAdmin, getAdminOnlyEls({
8636
+ applyAdminOnlyEls(ctx.get("user").getData().isAdmin, getAdminOnlyEls({
8635
8637
  $root: ctx.$root
8636
8638
  }));
8637
8639
  };
@@ -8658,38 +8660,44 @@ function applyAdminOnlyEls(isAdmin, els) {
8658
8660
  $item.classList.add("atk-hide");
8659
8661
  });
8660
8662
  }
8661
- const darkModeMedia = window.matchMedia("(prefers-color-scheme: dark)");
8662
- let darkModeAutoFunc;
8663
- function applyDarkMode($els, darkMode) {
8664
- const apply = (d) => {
8665
- $els.forEach(($el) => updateClassName($el, d));
8666
- };
8667
- if (darkMode === "auto") {
8668
- if (!darkModeAutoFunc) {
8669
- darkModeAutoFunc = (evt) => apply(evt.matches);
8670
- darkModeMedia.addEventListener("change", darkModeAutoFunc);
8671
- }
8672
- apply(darkModeMedia.matches);
8673
- } else {
8674
- if (darkModeAutoFunc)
8675
- darkModeMedia.removeEventListener("change", darkModeAutoFunc);
8676
- apply(darkMode);
8677
- }
8678
- }
8679
- const DarkModeClassName = "atk-dark-mode";
8680
- function updateClassName($el, darkMode) {
8681
- if (darkMode)
8682
- $el.classList.add(DarkModeClassName);
8683
- else
8684
- $el.classList.remove(DarkModeClassName);
8663
+ let darkModeMedia;
8664
+ function updateClassnames($els, darkMode) {
8665
+ const DarkModeClassName = "atk-dark-mode";
8666
+ $els.forEach(($el) => {
8667
+ if (darkMode)
8668
+ $el.classList.add(DarkModeClassName);
8669
+ else
8670
+ $el.classList.remove(DarkModeClassName);
8671
+ });
8685
8672
  }
8686
8673
  const DarkMode = (ctx) => {
8687
- const sync = () => {
8688
- applyDarkMode([ctx.$root, ctx.get("layerManager").getEl()], ctx.conf.darkMode);
8674
+ let darkModeAutoHandler;
8675
+ const sync = (darkMode) => {
8676
+ const $els = [ctx.$root, ctx.get("layerManager").getEl()];
8677
+ if (!darkModeMedia) {
8678
+ darkModeMedia = window.matchMedia("(prefers-color-scheme: dark)");
8679
+ }
8680
+ if (darkMode === "auto") {
8681
+ if (!darkModeAutoHandler) {
8682
+ darkModeAutoHandler = (evt) => updateClassnames($els, evt.matches);
8683
+ darkModeMedia.addEventListener("change", darkModeAutoHandler);
8684
+ }
8685
+ updateClassnames($els, darkModeMedia.matches);
8686
+ } else {
8687
+ if (darkModeAutoHandler) {
8688
+ darkModeMedia.removeEventListener("change", darkModeAutoHandler);
8689
+ darkModeAutoHandler = void 0;
8690
+ }
8691
+ updateClassnames($els, darkMode);
8692
+ }
8689
8693
  };
8690
- ctx.on("inited", () => sync());
8691
- ctx.on("conf-loaded", () => sync());
8692
- ctx.on("dark-mode-changed", () => sync());
8694
+ ctx.on("inited", () => sync(ctx.conf.darkMode));
8695
+ ctx.on("conf-loaded", (conf) => sync(conf.darkMode));
8696
+ ctx.on("dark-mode-changed", (darkMode) => sync(darkMode));
8697
+ ctx.on("destroy", () => {
8698
+ darkModeAutoHandler && (darkModeMedia == null ? void 0 : darkModeMedia.removeEventListener("change", darkModeAutoHandler));
8699
+ darkModeAutoHandler = void 0;
8700
+ });
8693
8701
  };
8694
8702
  const DefaultPlugins = [
8695
8703
  ConfRemoter,