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
@@ -42,7 +42,6 @@ var __async = (__this, __arguments, generator) => {
42
42
  });
43
43
  };
44
44
  import { marked as marked$1 } from "marked";
45
- const main = "";
46
45
  function createElement(htmlStr = "") {
47
46
  const div = document.createElement("div");
48
47
  div.innerHTML = htmlStr.trim();
@@ -629,48 +628,6 @@ function getDefaultExportFromCjs(x) {
629
628
  });
630
629
  })(typeof self !== "undefined" ? self : commonjsGlobal);
631
630
  });
632
- const LOCAL_USER_KEY = "ArtalkUser";
633
- class User {
634
- constructor() {
635
- __publicField(this, "data");
636
- __publicField(this, "onUserChanged", null);
637
- const localUser = JSON.parse(window.localStorage.getItem(LOCAL_USER_KEY) || "{}");
638
- this.data = {
639
- nick: localUser.nick || "",
640
- email: localUser.email || "",
641
- link: localUser.link || "",
642
- token: localUser.token || "",
643
- isAdmin: localUser.isAdmin || false
644
- };
645
- }
646
- /** 保存用户到 localStorage 中 */
647
- update(obj = {}) {
648
- Object.entries(obj).forEach(([key, value]) => {
649
- this.data[key] = value;
650
- });
651
- window.localStorage.setItem(LOCAL_USER_KEY, JSON.stringify(this.data));
652
- this.onUserChanged && this.onUserChanged(this.data);
653
- }
654
- setOnUserChanged(fn) {
655
- this.onUserChanged = fn;
656
- }
657
- /**
658
- * Logout
659
- *
660
- * @description Logout will clear login status, but not clear user data (nick, email, link)
661
- */
662
- logout() {
663
- this.update({
664
- token: "",
665
- isAdmin: false
666
- });
667
- }
668
- /** 是否已填写基本用户信息 */
669
- checkHasBasicUserInfo() {
670
- return !!this.data.nick && !!this.data.email;
671
- }
672
- }
673
- const UserInstance = new User();
674
631
  const en = {
675
632
  /* Editor */
676
633
  placeholder: "Leave a comment",
@@ -747,7 +704,8 @@ const en = {
747
704
  reqAborted: "Request timed out or terminated unexpectedly",
748
705
  updateMsg: "Please update Artalk {name} to get the full experience",
749
706
  currentVersion: "Current Version",
750
- ignore: "Ignore"
707
+ ignore: "Ignore",
708
+ open: "Open"
751
709
  };
752
710
  const zhCN = {
753
711
  /* Editor */
@@ -825,7 +783,8 @@ const zhCN = {
825
783
  reqAborted: "请求超时或意外终止",
826
784
  updateMsg: "请更新 Artalk {name} 以获得完整体验",
827
785
  currentVersion: "当前版本",
828
- ignore: "忽略"
786
+ ignore: "忽略",
787
+ open: "打开"
829
788
  };
830
789
  const GLOBAL_LOCALES_KEY = "ArtalkI18n";
831
790
  const internal = {
@@ -862,9 +821,9 @@ function t(key, args = {}) {
862
821
  function Fetch$1(opts, input, init2, timeout) {
863
822
  return __async(this, null, function* () {
864
823
  var _a, _b;
865
- if (UserInstance.data.token) {
824
+ if (opts.apiToken) {
866
825
  const headers = new Headers(init2.headers);
867
- headers.set("Authorization", `Bearer ${UserInstance.data.token}`);
826
+ headers.set("Authorization", `Bearer ${opts.apiToken}`);
868
827
  init2.headers = headers;
869
828
  }
870
829
  const resp = yield timeoutFetch(input, timeout || opts.timeout || 15e3, init2);
@@ -956,6 +915,20 @@ class ApiBase {
956
915
  return Fetch$1(this.options, this.options.baseURL + path, init2, timeout);
957
916
  });
958
917
  }
918
+ /**
919
+ * Carry user info to request params
920
+ *
921
+ * @param params Request params
922
+ * @returns Request params with user info
923
+ */
924
+ withUserInfo(params) {
925
+ const user = this.options.userInfo;
926
+ if (user == null ? void 0 : user.name)
927
+ params.name = user.name;
928
+ if (user == null ? void 0 : user.email)
929
+ params.email = user.email;
930
+ return params;
931
+ }
959
932
  }
960
933
  class CommentApi extends ApiBase {
961
934
  /** 评论 · 获取 */
@@ -968,10 +941,7 @@ class CommentApi extends ApiBase {
968
941
  };
969
942
  if (flatMode)
970
943
  params.flat_mode = flatMode;
971
- if (UserInstance.checkHasBasicUserInfo()) {
972
- params.name = UserInstance.data.nick;
973
- params.email = UserInstance.data.email;
974
- }
944
+ this.withUserInfo(params);
975
945
  if (paramsEditor)
976
946
  paramsEditor(params);
977
947
  return this.POST("/get", params);
@@ -1020,10 +990,7 @@ class CommentApi extends ApiBase {
1020
990
  target_id: targetID,
1021
991
  type
1022
992
  };
1023
- if (UserInstance.checkHasBasicUserInfo()) {
1024
- params.name = UserInstance.data.nick;
1025
- params.email = UserInstance.data.email;
1026
- }
993
+ this.withUserInfo(params);
1027
994
  const data = yield this.POST("/vote", params);
1028
995
  return data;
1029
996
  });
@@ -1192,10 +1159,7 @@ class UserApi extends ApiBase {
1192
1159
  /** 用户 · 登录状态 */
1193
1160
  loginStatus() {
1194
1161
  return __async(this, null, function* () {
1195
- const data = yield this.POST("/login-status", {
1196
- name: UserInstance.data.nick,
1197
- email: UserInstance.data.email
1198
- });
1162
+ const data = yield this.POST("/login-status", this.withUserInfo({}));
1199
1163
  return data || { is_login: false, is_admin: false };
1200
1164
  });
1201
1165
  }
@@ -1215,8 +1179,7 @@ class UserApi extends ApiBase {
1215
1179
  delete params.comment_id;
1216
1180
  delete params.notify_key;
1217
1181
  params.read_all = true;
1218
- params.name = UserInstance.data.nick;
1219
- params.email = UserInstance.data.email;
1182
+ this.withUserInfo(params);
1220
1183
  }
1221
1184
  return this.POST(`/mark-read`, params);
1222
1185
  }
@@ -1353,10 +1316,9 @@ class UploadApi extends ApiBase {
1353
1316
  imgUpload(file) {
1354
1317
  return __async(this, null, function* () {
1355
1318
  const params = {
1356
- name: UserInstance.data.nick,
1357
- email: UserInstance.data.email,
1358
1319
  page_key: this.options.pageKey
1359
1320
  };
1321
+ this.withUserInfo(params);
1360
1322
  const form = ToFormData(params);
1361
1323
  form.set("file", file);
1362
1324
  const init2 = {
@@ -2216,6 +2178,11 @@ function convertApiOptions(conf, ctx) {
2216
2178
  pageKey: conf.pageKey || "",
2217
2179
  pageTitle: conf.pageTitle || "",
2218
2180
  timeout: conf.reqTimeout,
2181
+ apiToken: ctx == null ? void 0 : ctx.get("user").getData().token,
2182
+ userInfo: (ctx == null ? void 0 : ctx.get("user").checkHasBasicUserInfo()) ? {
2183
+ name: ctx == null ? void 0 : ctx.get("user").getData().nick,
2184
+ email: ctx == null ? void 0 : ctx.get("user").getData().email
2185
+ } : void 0,
2219
2186
  onNeedCheckAdmin(payload) {
2220
2187
  ctx == null ? void 0 : ctx.checkAdmin({
2221
2188
  onSuccess: () => {
@@ -2279,7 +2246,7 @@ class Context {
2279
2246
  this.data.fetchComments({ offset: 0 });
2280
2247
  }
2281
2248
  listGotoFirst() {
2282
- this.trigger("list-goto-first");
2249
+ this.events.trigger("list-goto-first");
2283
2250
  }
2284
2251
  /* 编辑器 */
2285
2252
  editorShowLoading() {
@@ -2324,11 +2291,11 @@ class Context {
2324
2291
  }
2325
2292
  setDarkMode(darkMode) {
2326
2293
  this.conf.darkMode = darkMode;
2327
- this.trigger("dark-mode-changed", darkMode);
2294
+ this.events.trigger("dark-mode-changed", darkMode);
2328
2295
  }
2329
2296
  updateConf(nConf) {
2330
2297
  this.conf = mergeDeep(this.conf, handelCustomConf(nConf));
2331
- this.trigger("conf-loaded", this.conf);
2298
+ this.events.trigger("conf-loaded", this.conf);
2332
2299
  }
2333
2300
  getMarked() {
2334
2301
  return getInstance();
@@ -2535,7 +2502,7 @@ function imgBody(checker) {
2535
2502
  }
2536
2503
  function iframeBody(checker) {
2537
2504
  const $iframeWrap = createElement(`<div class="atk-checker-iframe-wrap"></div>`);
2538
- const $iframe = createElement(`<iframe class="atk-fade-in"></iframe>`);
2505
+ const $iframe = createElement(`<iframe class="atk-fade-in" referrerpolicy="strict-origin-when-cross-origin"></iframe>`);
2539
2506
  $iframe.style.display = "none";
2540
2507
  showLoading($iframeWrap, { transparentBg: true });
2541
2508
  $iframe.src = `${checker.getOpts().getIframeURLBase() || ""}/api/captcha/get?t=${+/* @__PURE__ */ new Date()}`;
@@ -2599,8 +2566,8 @@ const AdminChecker = {
2599
2566
  inputType: "password",
2600
2567
  request(checker, inputVal) {
2601
2568
  const data = {
2602
- name: UserInstance.data.nick,
2603
- email: UserInstance.data.email,
2569
+ name: checker.getUser().getData().nick,
2570
+ email: checker.getUser().getData().email,
2604
2571
  password: inputVal
2605
2572
  };
2606
2573
  return (() => __async(this, null, function* () {
@@ -2612,7 +2579,7 @@ const AdminChecker = {
2612
2579
  return createElement(`<span>${t("adminCheck")}</span>`);
2613
2580
  },
2614
2581
  onSuccess(checker, userToken, inputVal, formEl) {
2615
- UserInstance.update({
2582
+ checker.getUser().update({
2616
2583
  isAdmin: true,
2617
2584
  token: userToken
2618
2585
  });
@@ -2645,6 +2612,7 @@ class CheckerLauncher {
2645
2612
  },
2646
2613
  get: (key) => checkerStore[key],
2647
2614
  getOpts: () => this.opts,
2615
+ getUser: () => this.opts.getCtx().get("user"),
2648
2616
  getApi: () => this.opts.getApi(),
2649
2617
  hideInteractInput: () => {
2650
2618
  hideInteractInput = true;
@@ -3036,7 +3004,7 @@ class SidebarLayer extends Component {
3036
3004
  });
3037
3005
  }
3038
3006
  createIframe(view) {
3039
- const $iframe = createElement("<iframe></iframe>");
3007
+ const $iframe = createElement('<iframe referrerpolicy="strict-origin-when-cross-origin"></iframe>');
3040
3008
  const baseURL = getURLBasedOnApi({
3041
3009
  base: this.ctx.conf.server,
3042
3010
  path: "/sidebar/"
@@ -3044,7 +3012,7 @@ class SidebarLayer extends Component {
3044
3012
  const query = {
3045
3013
  pageKey: this.conf.pageKey,
3046
3014
  site: this.conf.site || "",
3047
- user: JSON.stringify(UserInstance.data),
3015
+ user: JSON.stringify(this.ctx.get("user").getData()),
3048
3016
  time: +/* @__PURE__ */ new Date()
3049
3017
  };
3050
3018
  if (view)
@@ -3121,7 +3089,7 @@ class ListLayout {
3121
3089
  constructor(options) {
3122
3090
  this.options = options;
3123
3091
  }
3124
- // TODO refactor `if syntax` to strategy pattern
3092
+ // TODO: refactor `if syntax` to strategy pattern
3125
3093
  import(comments) {
3126
3094
  if (this.options.flatMode) {
3127
3095
  comments.forEach((commentData) => {
@@ -3197,9 +3165,9 @@ class ListLayout {
3197
3165
  scrollIntoView(comment.getEl());
3198
3166
  }
3199
3167
  }
3200
- const win = window || {};
3201
- const nav = navigator || {};
3202
3168
  function Detect(userAgent) {
3169
+ const win = window || {};
3170
+ const nav = navigator || {};
3203
3171
  const u = String(userAgent || nav.userAgent);
3204
3172
  const dest = {
3205
3173
  os: "",
@@ -4548,20 +4516,6 @@ const initListPaginatorFunc = (ctx) => {
4548
4516
  var _a;
4549
4517
  (_a = paginator == null ? void 0 : paginator.showErr) == null ? void 0 : _a.call(paginator, t("loadFail"));
4550
4518
  });
4551
- const autoSwitchPageForFindComment = (commentID) => {
4552
- const comment = ctx.getData().findComment(commentID);
4553
- if (!!comment || !(paginator == null ? void 0 : paginator.getHasMore()))
4554
- return;
4555
- ctx.on("list-loaded", () => {
4556
- autoSwitchPageForFindComment(commentID);
4557
- }, { once: true });
4558
- setTimeout(() => {
4559
- paginator == null ? void 0 : paginator.next();
4560
- }, 80);
4561
- };
4562
- ctx.on("list-goto", (commentID) => {
4563
- autoSwitchPageForFindComment(commentID);
4564
- });
4565
4519
  ctx.on("list-fetch", (params) => {
4566
4520
  paginator == null ? void 0 : paginator.setLoading(true);
4567
4521
  });
@@ -4759,6 +4713,47 @@ class LayerManager {
4759
4713
  return layer;
4760
4714
  }
4761
4715
  }
4716
+ const LOCAL_USER_KEY = "ArtalkUser";
4717
+ class User {
4718
+ constructor(opts) {
4719
+ __publicField(this, "data");
4720
+ this.opts = opts;
4721
+ const localUser = JSON.parse(window.localStorage.getItem(LOCAL_USER_KEY) || "{}");
4722
+ this.data = {
4723
+ nick: localUser.nick || "",
4724
+ email: localUser.email || "",
4725
+ link: localUser.link || "",
4726
+ token: localUser.token || "",
4727
+ isAdmin: localUser.isAdmin || false
4728
+ };
4729
+ }
4730
+ getData() {
4731
+ return this.data;
4732
+ }
4733
+ /** 保存用户到 localStorage 中 */
4734
+ update(obj = {}) {
4735
+ Object.entries(obj).forEach(([key, value]) => {
4736
+ this.data[key] = value;
4737
+ });
4738
+ window.localStorage.setItem(LOCAL_USER_KEY, JSON.stringify(this.data));
4739
+ this.opts.onUserChanged && this.opts.onUserChanged(this.data);
4740
+ }
4741
+ /**
4742
+ * Logout
4743
+ *
4744
+ * @description Logout will clear login status, but not clear user data (nick, email, link)
4745
+ */
4746
+ logout() {
4747
+ this.update({
4748
+ token: "",
4749
+ isAdmin: false
4750
+ });
4751
+ }
4752
+ /** 是否已填写基本用户信息 */
4753
+ checkHasBasicUserInfo() {
4754
+ return !!this.data.nick && !!this.data.email;
4755
+ }
4756
+ }
4762
4757
  const services = {
4763
4758
  // I18n
4764
4759
  i18n(ctx) {
@@ -4769,10 +4764,12 @@ const services = {
4769
4764
  },
4770
4765
  // User Store
4771
4766
  user(ctx) {
4772
- UserInstance.setOnUserChanged((user) => {
4773
- ctx == null ? void 0 : ctx.trigger("user-changed", user);
4767
+ const user = new User({
4768
+ onUserChanged: (data) => {
4769
+ ctx.trigger("user-changed", data);
4770
+ }
4774
4771
  });
4775
- return UserInstance;
4772
+ return user;
4776
4773
  },
4777
4774
  // 弹出层
4778
4775
  layerManager(ctx) {
@@ -4822,11 +4819,8 @@ function showErrorDialog(opts) {
4822
4819
  errEl.appendChild($retryBtn);
4823
4820
  }
4824
4821
  if (opts.onOpenSidebar) {
4825
- const $openSidebar = createElement('<span atk-only-admin-show> | <span style="cursor:pointer;">打开控制台</span></span>');
4822
+ const $openSidebar = createElement(`<span atk-only-admin-show> | <span style="cursor:pointer;">${t("open") + t("ctrlCenter")}</span></span>`);
4826
4823
  errEl.appendChild($openSidebar);
4827
- if (!UserInstance.data.isAdmin) {
4828
- $openSidebar.classList.add("atk-hide");
4829
- }
4830
4824
  $openSidebar.onclick = () => opts.onOpenSidebar && opts.onOpenSidebar();
4831
4825
  }
4832
4826
  setError(opts.$err, errEl);
@@ -4862,9 +4856,10 @@ function loadConf(ctx) {
4862
4856
  errMsg: err.msg || String(err),
4863
4857
  errData: err.data,
4864
4858
  retryFn: () => loadConf(ctx),
4865
- onOpenSidebar: () => ctx.showSidebar({
4859
+ onOpenSidebar: ctx.get("user").getData().isAdmin ? () => ctx.showSidebar({
4866
4860
  view: sidebarOpenView
4867
- })
4861
+ }) : void 0
4862
+ // only show open sidebar button when user is admin
4868
4863
  });
4869
4864
  throw err;
4870
4865
  }).then(() => {
@@ -4969,7 +4964,7 @@ class SubmitAddPreset {
4969
4964
  });
4970
4965
  }
4971
4966
  getSubmitAddParams() {
4972
- const { nick, email, link } = UserInstance.data;
4967
+ const { nick, email, link } = this.kit.useUser().getData();
4973
4968
  const conf = this.kit.useConf();
4974
4969
  return {
4975
4970
  content: this.kit.useEditor().getContentFinal(),
@@ -5167,7 +5162,7 @@ class StateEdit extends EditorPlug {
5167
5162
  ui.$editCancelBtn = void 0;
5168
5163
  }
5169
5164
  this.comment = void 0;
5170
- const { nick, email, link } = UserInstance.data;
5165
+ const { nick, email, link } = this.kit.useUser().getData();
5171
5166
  ui.$nick.value = nick;
5172
5167
  ui.$email.value = email;
5173
5168
  ui.$link.value = link;
@@ -5206,7 +5201,7 @@ class Closable extends EditorPlug {
5206
5201
  close() {
5207
5202
  if (!this.kit.useUI().$textareaWrap.querySelector(".atk-comment-closed"))
5208
5203
  this.kit.useUI().$textareaWrap.prepend(createElement(`<div class="atk-comment-closed">${t("onlyAdminCanReply")}</div>`));
5209
- if (!UserInstance.data.isAdmin) {
5204
+ if (!this.kit.useUser().getData().isAdmin) {
5210
5205
  this.kit.useUI().$textarea.style.display = "none";
5211
5206
  this.kit.useEvents().trigger("panel-close");
5212
5207
  this.kit.useUI().$bottom.style.display = "none";
@@ -5251,14 +5246,14 @@ class HeaderUser extends EditorPlug {
5251
5246
  const onInput = ({ $input, field }) => {
5252
5247
  if (this.kit.useEditor().getState() === "edit")
5253
5248
  return;
5254
- UserInstance.update({ [field]: $input.value.trim() });
5249
+ this.kit.useUser().update({ [field]: $input.value.trim() });
5255
5250
  if (field === "nick" || field === "email")
5256
5251
  this.fetchUserInfo();
5257
5252
  };
5258
5253
  this.kit.useMounted(() => {
5259
5254
  Object.entries(this.kit.useEditor().getHeaderInputEls()).forEach(([key, $input]) => {
5260
5255
  $input.placeholder = `${t(key)}`;
5261
- $input.value = UserInstance.data[key] || "";
5256
+ $input.value = this.kit.useUser().getData()[key] || "";
5262
5257
  });
5263
5258
  this.kit.useEvents().on("header-input", onInput);
5264
5259
  });
@@ -5270,7 +5265,7 @@ class HeaderUser extends EditorPlug {
5270
5265
  * Fetch user info from server
5271
5266
  */
5272
5267
  fetchUserInfo() {
5273
- UserInstance.logout();
5268
+ this.kit.useUser().logout();
5274
5269
  if (this.query.timer)
5275
5270
  window.clearTimeout(this.query.timer);
5276
5271
  if (this.query.abortFn)
@@ -5278,8 +5273,8 @@ class HeaderUser extends EditorPlug {
5278
5273
  this.query.timer = window.setTimeout(() => {
5279
5274
  this.query.timer = null;
5280
5275
  const { req, abort } = this.kit.useApi().user.userGet(
5281
- UserInstance.data.nick,
5282
- UserInstance.data.email
5276
+ this.kit.useUser().getData().nick,
5277
+ this.kit.useUser().getData().email
5283
5278
  );
5284
5279
  this.query.abortFn = abort;
5285
5280
  req.then((data) => this.onUserInfoFetched(data)).catch((err) => {
@@ -5296,9 +5291,9 @@ class HeaderUser extends EditorPlug {
5296
5291
  onUserInfoFetched(data) {
5297
5292
  var _a;
5298
5293
  if (!data.is_login)
5299
- UserInstance.logout();
5294
+ this.kit.useUser().logout();
5300
5295
  this.kit.useGlobalCtx().getData().updateUnreads(data.unread);
5301
- if (UserInstance.checkHasBasicUserInfo() && !data.is_login && ((_a = data.user) == null ? void 0 : _a.is_admin)) {
5296
+ if (this.kit.useUser().checkHasBasicUserInfo() && !data.is_login && ((_a = data.user) == null ? void 0 : _a.is_admin)) {
5302
5297
  this.kit.useGlobalCtx().checkAdmin({
5303
5298
  onSuccess: () => {
5304
5299
  }
@@ -5306,7 +5301,7 @@ class HeaderUser extends EditorPlug {
5306
5301
  }
5307
5302
  if (data.user && data.user.link) {
5308
5303
  this.kit.useUI().$link.value = data.user.link;
5309
- UserInstance.update({ link: data.user.link });
5304
+ this.kit.useUser().update({ link: data.user.link });
5310
5305
  }
5311
5306
  }
5312
5307
  }
@@ -5328,11 +5323,10 @@ class HeaderLink extends EditorPlug {
5328
5323
  const link = this.kit.useUI().$link.value.trim();
5329
5324
  if (!!link && !/^(http|https):\/\//.test(link)) {
5330
5325
  this.kit.useUI().$link.value = `https://${link}`;
5331
- UserInstance.update({ link: this.kit.useUI().$link.value });
5326
+ this.kit.useUser().update({ link: this.kit.useUI().$link.value });
5332
5327
  }
5333
5328
  }
5334
5329
  }
5335
- const emoticons = "";
5336
5330
  class Emoticons extends EditorPlug {
5337
5331
  constructor(kit) {
5338
5332
  super(kit);
@@ -5448,7 +5442,8 @@ class Emoticons extends EditorPlug {
5448
5442
  return json;
5449
5443
  } catch (err) {
5450
5444
  hideLoading(this.$panel);
5451
- setError(this.$panel, `表情加载失败 ${String(err)}`);
5445
+ console.error("[Emoticons] Load Failed:", err);
5446
+ setError(this.$panel, `${t("emoticon")}${t("loadFail")} ${String(err)}`);
5452
5447
  return [];
5453
5448
  }
5454
5449
  });
@@ -5657,7 +5652,7 @@ class Upload extends EditorPlug {
5657
5652
  const fileExt = /[^.]+$/.exec(file.name);
5658
5653
  if (!fileExt || !AllowImgExts.includes(fileExt[0]))
5659
5654
  return;
5660
- if (!UserInstance.checkHasBasicUserInfo()) {
5655
+ if (!this.kit.useUser().checkHasBasicUserInfo()) {
5661
5656
  this.kit.useEditor().showNotify(t("uploadLoginMsg"), "w");
5662
5657
  return;
5663
5658
  }
@@ -5692,7 +5687,6 @@ class Upload extends EditorPlug {
5692
5687
  });
5693
5688
  }
5694
5689
  }
5695
- const preview = "";
5696
5690
  class Preview extends EditorPlug {
5697
5691
  constructor(kit) {
5698
5692
  super(kit);
@@ -5755,7 +5749,11 @@ class PlugKit {
5755
5749
  useEditor() {
5756
5750
  return this.plugs.editor;
5757
5751
  }
5758
- /** Use the context of global */
5752
+ /**
5753
+ * Use the context of global
5754
+ *
5755
+ * @deprecated The calls to this function should be reduced as much as possible
5756
+ */
5759
5757
  useGlobalCtx() {
5760
5758
  return this.plugs.editor.ctx;
5761
5759
  }
@@ -5767,6 +5765,10 @@ class PlugKit {
5767
5765
  useApi() {
5768
5766
  return this.plugs.editor.ctx.getApi();
5769
5767
  }
5768
+ /** Use the user manager */
5769
+ useUser() {
5770
+ return this.plugs.editor.ctx.get("user");
5771
+ }
5770
5772
  /** Use the ui of editor */
5771
5773
  useUI() {
5772
5774
  return this.plugs.editor.getUI();
@@ -5984,7 +5986,7 @@ const SidebarBtn = (ctx) => {
5984
5986
  const syncByUser = () => {
5985
5987
  if (!$openSidebarBtn)
5986
5988
  return;
5987
- const user = ctx.get("user").data;
5989
+ const user = ctx.get("user").getData();
5988
5990
  if (!!user.nick && !!user.email) {
5989
5991
  $openSidebarBtn.classList.remove("atk-hide");
5990
5992
  const $btnText = $openSidebarBtn.querySelector(".atk-text");
@@ -6083,7 +6085,7 @@ function extractCommentID() {
6083
6085
  }
6084
6086
  return commentId || null;
6085
6087
  }
6086
- const version = "2.7.1";
6088
+ const version = "2.7.2";
6087
6089
  const Copyright = (ctx) => {
6088
6090
  ctx.on("conf-loaded", () => {
6089
6091
  const list = ctx.get("list");
@@ -6416,7 +6418,7 @@ function versionCheck(list, feVer, beVer) {
6416
6418
  }
6417
6419
  const AdminOnlyElem = (ctx) => {
6418
6420
  const scanApply = () => {
6419
- applyAdminOnlyEls(ctx.get("user").data.isAdmin, getAdminOnlyEls({
6421
+ applyAdminOnlyEls(ctx.get("user").getData().isAdmin, getAdminOnlyEls({
6420
6422
  $root: ctx.$root
6421
6423
  }));
6422
6424
  };
@@ -6443,38 +6445,44 @@ function applyAdminOnlyEls(isAdmin, els) {
6443
6445
  $item.classList.add("atk-hide");
6444
6446
  });
6445
6447
  }
6446
- const darkModeMedia = window.matchMedia("(prefers-color-scheme: dark)");
6447
- let darkModeAutoFunc;
6448
- function applyDarkMode($els, darkMode) {
6449
- const apply = (d) => {
6450
- $els.forEach(($el) => updateClassName($el, d));
6451
- };
6452
- if (darkMode === "auto") {
6453
- if (!darkModeAutoFunc) {
6454
- darkModeAutoFunc = (evt) => apply(evt.matches);
6455
- darkModeMedia.addEventListener("change", darkModeAutoFunc);
6456
- }
6457
- apply(darkModeMedia.matches);
6458
- } else {
6459
- if (darkModeAutoFunc)
6460
- darkModeMedia.removeEventListener("change", darkModeAutoFunc);
6461
- apply(darkMode);
6462
- }
6463
- }
6464
- const DarkModeClassName = "atk-dark-mode";
6465
- function updateClassName($el, darkMode) {
6466
- if (darkMode)
6467
- $el.classList.add(DarkModeClassName);
6468
- else
6469
- $el.classList.remove(DarkModeClassName);
6448
+ let darkModeMedia;
6449
+ function updateClassnames($els, darkMode) {
6450
+ const DarkModeClassName = "atk-dark-mode";
6451
+ $els.forEach(($el) => {
6452
+ if (darkMode)
6453
+ $el.classList.add(DarkModeClassName);
6454
+ else
6455
+ $el.classList.remove(DarkModeClassName);
6456
+ });
6470
6457
  }
6471
6458
  const DarkMode = (ctx) => {
6472
- const sync = () => {
6473
- applyDarkMode([ctx.$root, ctx.get("layerManager").getEl()], ctx.conf.darkMode);
6459
+ let darkModeAutoHandler;
6460
+ const sync = (darkMode) => {
6461
+ const $els = [ctx.$root, ctx.get("layerManager").getEl()];
6462
+ if (!darkModeMedia) {
6463
+ darkModeMedia = window.matchMedia("(prefers-color-scheme: dark)");
6464
+ }
6465
+ if (darkMode === "auto") {
6466
+ if (!darkModeAutoHandler) {
6467
+ darkModeAutoHandler = (evt) => updateClassnames($els, evt.matches);
6468
+ darkModeMedia.addEventListener("change", darkModeAutoHandler);
6469
+ }
6470
+ updateClassnames($els, darkModeMedia.matches);
6471
+ } else {
6472
+ if (darkModeAutoHandler) {
6473
+ darkModeMedia.removeEventListener("change", darkModeAutoHandler);
6474
+ darkModeAutoHandler = void 0;
6475
+ }
6476
+ updateClassnames($els, darkMode);
6477
+ }
6474
6478
  };
6475
- ctx.on("inited", () => sync());
6476
- ctx.on("conf-loaded", () => sync());
6477
- ctx.on("dark-mode-changed", () => sync());
6479
+ ctx.on("inited", () => sync(ctx.conf.darkMode));
6480
+ ctx.on("conf-loaded", (conf) => sync(conf.darkMode));
6481
+ ctx.on("dark-mode-changed", (darkMode) => sync(darkMode));
6482
+ ctx.on("destroy", () => {
6483
+ darkModeAutoHandler && (darkModeMedia == null ? void 0 : darkModeMedia.removeEventListener("change", darkModeAutoHandler));
6484
+ darkModeAutoHandler = void 0;
6485
+ });
6478
6486
  };
6479
6487
  const DefaultPlugins = [
6480
6488
  ConfRemoter,