artalk 2.7.2 → 2.8.0

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 (161) hide show
  1. package/LICENSE +21 -0
  2. package/dist/Artalk.cjs +11 -0
  3. package/dist/Artalk.cjs.map +1 -0
  4. package/dist/Artalk.css +1 -1
  5. package/dist/Artalk.iife.js +10 -1
  6. package/dist/Artalk.iife.js.map +1 -1
  7. package/dist/Artalk.js +10 -1
  8. package/dist/Artalk.js.map +1 -1
  9. package/dist/{Artalk.es.js → Artalk.mjs} +2552 -1857
  10. package/dist/Artalk.mjs.map +1 -0
  11. package/dist/ArtalkLite.cjs +11 -0
  12. package/dist/ArtalkLite.cjs.map +1 -0
  13. package/dist/ArtalkLite.css +1 -1
  14. package/dist/ArtalkLite.iife.js +10 -1
  15. package/dist/ArtalkLite.iife.js.map +1 -1
  16. package/dist/ArtalkLite.js +10 -1
  17. package/dist/ArtalkLite.js.map +1 -1
  18. package/dist/{ArtalkLite.es.js → ArtalkLite.mjs} +2150 -1261
  19. package/dist/ArtalkLite.mjs.map +1 -0
  20. package/dist/i18n/jp.cjs +1 -0
  21. package/dist/i18n/jp.d.cts +3 -0
  22. package/dist/i18n/jp.d.ts +3 -0
  23. package/dist/i18n/jp.js +1 -1
  24. package/dist/i18n/jp.mjs +94 -0
  25. package/dist/i18n/zh-TW.cjs +1 -0
  26. package/dist/i18n/zh-TW.d.cts +3 -0
  27. package/dist/i18n/zh-TW.d.ts +3 -0
  28. package/dist/i18n/zh-TW.js +1 -1
  29. package/dist/i18n/zh-TW.mjs +94 -0
  30. package/dist/main.d.cts +2812 -0
  31. package/dist/main.d.ts +2812 -0
  32. package/package.json +62 -30
  33. package/dist/Artalk.es.js.map +0 -1
  34. package/dist/ArtalkLite.es.js.map +0 -1
  35. package/dist/src/api/_base.d.ts +0 -17
  36. package/dist/src/api/_options.d.ts +0 -24
  37. package/dist/src/api/_request.d.ts +0 -12
  38. package/dist/src/api/admin.d.ts +0 -10
  39. package/dist/src/api/captcha.d.ts +0 -14
  40. package/dist/src/api/comment.d.ts +0 -29
  41. package/dist/src/api/index.d.ts +0 -29
  42. package/dist/src/api/page.d.ts +0 -22
  43. package/dist/src/api/site.d.ts +0 -17
  44. package/dist/src/api/system.d.ts +0 -33
  45. package/dist/src/api/upload.d.ts +0 -11
  46. package/dist/src/api/user.d.ts +0 -42
  47. package/dist/src/artalk.d.ts +0 -35
  48. package/dist/src/comment/actions.d.ts +0 -17
  49. package/dist/src/comment/comment.d.ts +0 -66
  50. package/dist/src/comment/height-limit.d.ts +0 -30
  51. package/dist/src/comment/index.d.ts +0 -2
  52. package/dist/src/comment/render.d.ts +0 -46
  53. package/dist/src/comment/renders/actions.d.ts +0 -5
  54. package/dist/src/comment/renders/avatar.d.ts +0 -5
  55. package/dist/src/comment/renders/content.d.ts +0 -5
  56. package/dist/src/comment/renders/header.d.ts +0 -5
  57. package/dist/src/comment/renders/index.d.ts +0 -2
  58. package/dist/src/comment/renders/pending.d.ts +0 -5
  59. package/dist/src/comment/renders/reply-at.d.ts +0 -5
  60. package/dist/src/comment/renders/reply-to.d.ts +0 -5
  61. package/dist/src/components/action-btn.d.ts +0 -50
  62. package/dist/src/components/checker/admin.d.ts +0 -3
  63. package/dist/src/components/checker/captcha-renders.d.ts +0 -5
  64. package/dist/src/components/checker/captcha.d.ts +0 -3
  65. package/dist/src/components/checker/index.d.ts +0 -53
  66. package/dist/src/components/dialog.d.ts +0 -16
  67. package/dist/src/components/error-dialog.d.ts +0 -8
  68. package/dist/src/components/pagination.d.ts +0 -31
  69. package/dist/src/components/read-more-btn.d.ts +0 -33
  70. package/dist/src/config.d.ts +0 -24
  71. package/dist/src/context.d.ts +0 -45
  72. package/dist/src/data.d.ts +0 -27
  73. package/dist/src/defaults.d.ts +0 -3
  74. package/dist/src/editor/editor.d.ts +0 -31
  75. package/dist/src/editor/state.d.ts +0 -20
  76. package/dist/src/editor/ui.d.ts +0 -25
  77. package/dist/src/i18n/en.d.ts +0 -73
  78. package/dist/src/i18n/external.d.ts +0 -74
  79. package/dist/src/i18n/index.d.ts +0 -236
  80. package/dist/src/i18n/jp.d.ts +0 -73
  81. package/dist/src/i18n/zh-CN.d.ts +0 -3
  82. package/dist/src/i18n/zh-TW.d.ts +0 -73
  83. package/dist/src/layer/index.d.ts +0 -4
  84. package/dist/src/layer/layer-manager.d.ts +0 -9
  85. package/dist/src/layer/layer.d.ts +0 -12
  86. package/dist/src/layer/scrollbar-helper.d.ts +0 -5
  87. package/dist/src/layer/sidebar-layer.d.ts +0 -20
  88. package/dist/src/layer/wrap.d.ts +0 -13
  89. package/dist/src/lib/component.d.ts +0 -7
  90. package/dist/src/lib/detect.d.ts +0 -10
  91. package/dist/src/lib/event-manager.d.ts +0 -28
  92. package/dist/src/lib/highlight.d.ts +0 -1
  93. package/dist/src/lib/marked-renderer.d.ts +0 -4
  94. package/dist/src/lib/marked.d.ts +0 -11
  95. package/dist/src/lib/sanitizer.d.ts +0 -1
  96. package/dist/src/lib/ui.d.ts +0 -24
  97. package/dist/src/lib/user.d.ts +0 -21
  98. package/dist/src/lib/utils.d.ts +0 -41
  99. package/dist/src/list/comment.d.ts +0 -3
  100. package/dist/src/list/layout.d.ts +0 -23
  101. package/dist/src/list/list.d.ts +0 -14
  102. package/dist/src/list/nest.d.ts +0 -10
  103. package/dist/src/list/page.d.ts +0 -2
  104. package/dist/src/list/paginator/index.d.ts +0 -25
  105. package/dist/src/list/paginator/read-more.d.ts +0 -18
  106. package/dist/src/list/paginator/up-down.d.ts +0 -14
  107. package/dist/src/main.d.ts +0 -7
  108. package/dist/src/plugins/admin-only-elem.d.ts +0 -2
  109. package/dist/src/plugins/conf-remoter.d.ts +0 -2
  110. package/dist/src/plugins/dark-mode.d.ts +0 -2
  111. package/dist/src/plugins/editor/_kit.d.ts +0 -33
  112. package/dist/src/plugins/editor/_plug.d.ts +0 -29
  113. package/dist/src/plugins/editor/_sample.d.ts +0 -5
  114. package/dist/src/plugins/editor/closable.d.ts +0 -7
  115. package/dist/src/plugins/editor/emoticons.d.ts +0 -30
  116. package/dist/src/plugins/editor/header-event.d.ts +0 -6
  117. package/dist/src/plugins/editor/header-link.d.ts +0 -6
  118. package/dist/src/plugins/editor/header-user.d.ts +0 -16
  119. package/dist/src/plugins/editor/index.d.ts +0 -6
  120. package/dist/src/plugins/editor/local-storage.d.ts +0 -6
  121. package/dist/src/plugins/editor/mover.d.ts +0 -6
  122. package/dist/src/plugins/editor/preview.d.ts +0 -7
  123. package/dist/src/plugins/editor/state-edit.d.ts +0 -11
  124. package/dist/src/plugins/editor/state-reply.d.ts +0 -8
  125. package/dist/src/plugins/editor/submit-add.d.ts +0 -18
  126. package/dist/src/plugins/editor/submit-btn.d.ts +0 -5
  127. package/dist/src/plugins/editor/submit.d.ts +0 -17
  128. package/dist/src/plugins/editor/textarea.d.ts +0 -8
  129. package/dist/src/plugins/editor/upload.d.ts +0 -9
  130. package/dist/src/plugins/editor-kit.d.ts +0 -42
  131. package/dist/src/plugins/index.d.ts +0 -2
  132. package/dist/src/plugins/list/copyright.d.ts +0 -2
  133. package/dist/src/plugins/list/count.d.ts +0 -2
  134. package/dist/src/plugins/list/dropdown.d.ts +0 -2
  135. package/dist/src/plugins/list/error-dialog.d.ts +0 -2
  136. package/dist/src/plugins/list/fetch.d.ts +0 -2
  137. package/dist/src/plugins/list/goto-first.d.ts +0 -3
  138. package/dist/src/plugins/list/goto.d.ts +0 -2
  139. package/dist/src/plugins/list/index.d.ts +0 -3
  140. package/dist/src/plugins/list/loading.d.ts +0 -2
  141. package/dist/src/plugins/list/no-comment.d.ts +0 -2
  142. package/dist/src/plugins/list/reach-bottom.d.ts +0 -2
  143. package/dist/src/plugins/list/sidebar-btn.d.ts +0 -2
  144. package/dist/src/plugins/list/time-ticking.d.ts +0 -3
  145. package/dist/src/plugins/list/unread-badge.d.ts +0 -2
  146. package/dist/src/plugins/list/unread.d.ts +0 -2
  147. package/dist/src/plugins/list/with-editor.d.ts +0 -2
  148. package/dist/src/plugins/markdown.d.ts +0 -2
  149. package/dist/src/plugins/stat.d.ts +0 -13
  150. package/dist/src/plugins/version-check.d.ts +0 -2
  151. package/dist/src/service.d.ts +0 -36
  152. package/dist/tests/e2e/comment-add.spec.d.ts +0 -1
  153. package/dist/types/config.d.ts +0 -110
  154. package/dist/types/context.d.ts +0 -62
  155. package/dist/types/data.d.ts +0 -194
  156. package/dist/types/editor.d.ts +0 -76
  157. package/dist/types/event.d.ts +0 -39
  158. package/dist/types/global.d.ts +0 -1
  159. package/dist/types/index.d.ts +0 -7
  160. package/dist/types/plugin.d.ts +0 -2
  161. package/dist/types/sidebar.d.ts +0 -3
@@ -17,6 +17,18 @@ var __spreadValues = (a, b) => {
17
17
  return a;
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
20
32
  var __publicField = (obj, key, value) => {
21
33
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
22
34
  return value;
@@ -42,192 +54,1217 @@ var __async = (__this, __arguments, generator) => {
42
54
  });
43
55
  };
44
56
  import { marked as marked$1 } from "marked";
45
- function createElement(htmlStr = "") {
46
- const div = document.createElement("div");
47
- div.innerHTML = htmlStr.trim();
48
- return div.firstElementChild || div;
49
- }
50
- function getHeight(el) {
51
- return parseFloat(getComputedStyle(el, null).height.replace("px", ""));
52
- }
53
- function htmlEncode(str) {
54
- const temp = document.createElement("div");
55
- temp.innerText = str;
56
- const output = temp.innerHTML;
57
- return output;
58
- }
59
- function getQueryParam(name) {
60
- const match = RegExp(`[?&]${name}=([^&]*)`).exec(window.location.search);
61
- return match && decodeURIComponent(match[1].replace(/\+/g, " "));
62
- }
63
- function getOffset(el, relativeTo) {
64
- const getOffsetRecursive = (element) => {
65
- const rect = element.getBoundingClientRect();
66
- const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
67
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
68
- return {
69
- top: rect.top + scrollTop,
70
- left: rect.left + scrollLeft
71
- };
72
- };
73
- const elOffset = getOffsetRecursive(el);
74
- if (!relativeTo)
75
- return elOffset;
76
- const relativeToOffset = getOffsetRecursive(relativeTo);
77
- return {
78
- top: elOffset.top - relativeToOffset.top,
79
- left: elOffset.left - relativeToOffset.left
80
- };
81
- }
82
- function padWithZeros(vNumber, width) {
83
- let numAsString = vNumber.toString();
84
- while (numAsString.length < width) {
85
- numAsString = `0${numAsString}`;
86
- }
87
- return numAsString;
88
- }
89
- function dateFormat(date) {
90
- const vDay = padWithZeros(date.getDate(), 2);
91
- const vMonth = padWithZeros(date.getMonth() + 1, 2);
92
- const vYear = padWithZeros(date.getFullYear(), 2);
93
- return `${vYear}-${vMonth}-${vDay}`;
94
- }
95
- function timeAgo(date, $t = (n) => n) {
96
- try {
97
- const oldTime = date.getTime();
98
- const currTime = (/* @__PURE__ */ new Date()).getTime();
99
- const diffValue = currTime - oldTime;
100
- const days = Math.floor(diffValue / (24 * 3600 * 1e3));
101
- if (days === 0) {
102
- const leave1 = diffValue % (24 * 3600 * 1e3);
103
- const hours = Math.floor(leave1 / (3600 * 1e3));
104
- if (hours === 0) {
105
- const leave2 = leave1 % (3600 * 1e3);
106
- const minutes = Math.floor(leave2 / (60 * 1e3));
107
- if (minutes === 0) {
108
- const leave3 = leave2 % (60 * 1e3);
109
- const seconds = Math.round(leave3 / 1e3);
110
- if (seconds < 10)
111
- return $t("now");
112
- return `${seconds} ${$t("seconds")}`;
57
+ class HttpClient {
58
+ constructor(apiConfig = {}) {
59
+ __publicField(this, "baseUrl", "/api/v2");
60
+ __publicField(this, "securityData", null);
61
+ __publicField(this, "securityWorker");
62
+ __publicField(this, "abortControllers", /* @__PURE__ */ new Map());
63
+ __publicField(this, "customFetch", (...fetchParams) => fetch(...fetchParams));
64
+ __publicField(this, "baseApiParams", {
65
+ credentials: "same-origin",
66
+ headers: {},
67
+ redirect: "follow",
68
+ referrerPolicy: "no-referrer"
69
+ });
70
+ __publicField(this, "setSecurityData", (data) => {
71
+ this.securityData = data;
72
+ });
73
+ __publicField(this, "contentFormatters", {
74
+ [
75
+ "application/json"
76
+ /* Json */
77
+ ]: (input) => input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
78
+ [
79
+ "text/plain"
80
+ /* Text */
81
+ ]: (input) => input !== null && typeof input !== "string" ? JSON.stringify(input) : input,
82
+ [
83
+ "multipart/form-data"
84
+ /* FormData */
85
+ ]: (input) => Object.keys(input || {}).reduce((formData, key) => {
86
+ const property = input[key];
87
+ formData.append(
88
+ key,
89
+ property instanceof Blob ? property : typeof property === "object" && property !== null ? JSON.stringify(property) : `${property}`
90
+ );
91
+ return formData;
92
+ }, new FormData()),
93
+ [
94
+ "application/x-www-form-urlencoded"
95
+ /* UrlEncoded */
96
+ ]: (input) => this.toQueryString(input)
97
+ });
98
+ __publicField(this, "createAbortSignal", (cancelToken) => {
99
+ if (this.abortControllers.has(cancelToken)) {
100
+ const abortController2 = this.abortControllers.get(cancelToken);
101
+ if (abortController2) {
102
+ return abortController2.signal;
113
103
  }
114
- return `${minutes} ${$t("minutes")}`;
104
+ return void 0;
115
105
  }
116
- return `${hours} ${$t("hours")}`;
117
- }
118
- if (days < 0)
119
- return $t("now");
120
- if (days < 8) {
121
- return `${days} ${$t("days")}`;
122
- }
123
- return dateFormat(date);
124
- } catch (error) {
125
- console.error(error);
126
- return " - ";
106
+ const abortController = new AbortController();
107
+ this.abortControllers.set(cancelToken, abortController);
108
+ return abortController.signal;
109
+ });
110
+ __publicField(this, "abortRequest", (cancelToken) => {
111
+ const abortController = this.abortControllers.get(cancelToken);
112
+ if (abortController) {
113
+ abortController.abort();
114
+ this.abortControllers.delete(cancelToken);
115
+ }
116
+ });
117
+ __publicField(this, "request", (_a) => __async(this, null, function* () {
118
+ var _b = _a, {
119
+ body,
120
+ secure,
121
+ path,
122
+ type,
123
+ query,
124
+ format,
125
+ baseUrl,
126
+ cancelToken
127
+ } = _b, params = __objRest(_b, [
128
+ "body",
129
+ "secure",
130
+ "path",
131
+ "type",
132
+ "query",
133
+ "format",
134
+ "baseUrl",
135
+ "cancelToken"
136
+ ]);
137
+ const secureParams = (typeof secure === "boolean" ? secure : this.baseApiParams.secure) && this.securityWorker && (yield this.securityWorker(this.securityData)) || {};
138
+ const requestParams = this.mergeRequestParams(params, secureParams);
139
+ const queryString = query && this.toQueryString(query);
140
+ const payloadFormatter = this.contentFormatters[
141
+ type || "application/json"
142
+ /* Json */
143
+ ];
144
+ const responseFormat = format || requestParams.format;
145
+ return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, __spreadProps(__spreadValues({}, requestParams), {
146
+ headers: __spreadValues(__spreadValues({}, requestParams.headers || {}), type && type !== "multipart/form-data" ? { "Content-Type": type } : {}),
147
+ signal: (cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal) || null,
148
+ body: typeof body === "undefined" || body === null ? null : payloadFormatter(body)
149
+ })).then((response) => __async(this, null, function* () {
150
+ const r = response;
151
+ r.data = null;
152
+ r.error = null;
153
+ const data = !responseFormat ? r : yield response[responseFormat]().then((data2) => {
154
+ if (r.ok) {
155
+ r.data = data2;
156
+ } else {
157
+ r.error = data2;
158
+ }
159
+ return r;
160
+ }).catch((e) => {
161
+ r.error = e;
162
+ return r;
163
+ });
164
+ if (cancelToken) {
165
+ this.abortControllers.delete(cancelToken);
166
+ }
167
+ if (!response.ok)
168
+ throw data;
169
+ return data;
170
+ }));
171
+ }));
172
+ Object.assign(this, apiConfig);
127
173
  }
128
- }
129
- function onImagesLoaded($container, event) {
130
- if (!$container)
131
- return;
132
- const images = $container.getElementsByTagName("img");
133
- if (!images.length)
134
- return;
135
- let loaded = images.length;
136
- for (let i = 0; i < images.length; i++) {
137
- if (images[i].complete) {
138
- loaded--;
139
- } else {
140
- images[i].addEventListener("load", () => {
141
- loaded--;
142
- if (loaded === 0)
143
- event();
144
- });
145
- }
146
- if (loaded === 0)
147
- event();
174
+ encodeQueryParam(key, value) {
175
+ const encodedKey = encodeURIComponent(key);
176
+ return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`;
148
177
  }
149
- }
150
- function getGravatarURL(opts) {
151
- return `${opts.mirror.replace(/\/$/, "")}/${opts.emailMD5}?${opts.params.replace(/^\?/, "")}`;
152
- }
153
- function versionCompare(a, b) {
154
- const pa = a.split(".");
155
- const pb = b.split(".");
156
- for (let i = 0; i < 3; i++) {
157
- const na = Number(pa[i]);
158
- const nb = Number(pb[i]);
159
- if (na > nb)
160
- return 1;
161
- if (nb > na)
162
- return -1;
163
- if (!Number.isNaN(na) && Number.isNaN(nb))
164
- return 1;
165
- if (Number.isNaN(na) && !Number.isNaN(nb))
166
- return -1;
178
+ addQueryParam(query, key) {
179
+ return this.encodeQueryParam(key, query[key]);
167
180
  }
168
- return 0;
169
- }
170
- function getCorrectUserAgent() {
171
- return __async(this, null, function* () {
172
- const uaRaw = navigator.userAgent;
173
- if (!navigator.userAgentData || !navigator.userAgentData.getHighEntropyValues) {
174
- return uaRaw;
175
- }
176
- const uaData = navigator.userAgentData;
177
- let uaGot = null;
178
- try {
179
- uaGot = yield uaData.getHighEntropyValues(["platformVersion"]);
180
- } catch (err) {
181
- console.error(err);
182
- return uaRaw;
183
- }
184
- const majorPlatformVersion = Number(uaGot.platformVersion.split(".")[0]);
185
- if (uaData.platform === "Windows") {
186
- if (majorPlatformVersion >= 13) {
187
- return uaRaw.replace(/Windows NT 10.0/, "Windows NT 11.0");
188
- }
189
- }
190
- if (uaData.platform === "macOS") {
191
- if (majorPlatformVersion >= 11) {
192
- return uaRaw.replace(/(Mac OS X \d+_\d+_\d+|Mac OS X)/, `Mac OS X ${uaGot.platformVersion.replace(/\./g, "_")}`);
193
- }
194
- }
195
- return uaRaw;
196
- });
197
- }
198
- function isValidURL(urlRaw) {
199
- let url;
200
- try {
201
- url = new URL(urlRaw);
202
- } catch (_) {
203
- return false;
181
+ addArrayQueryParam(query, key) {
182
+ const value = query[key];
183
+ return value.map((v) => this.encodeQueryParam(key, v)).join("&");
184
+ }
185
+ toQueryString(rawQuery) {
186
+ const query = rawQuery || {};
187
+ const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
188
+ return keys.map((key) => Array.isArray(query[key]) ? this.addArrayQueryParam(query, key) : this.addQueryParam(query, key)).join("&");
189
+ }
190
+ addQueryParams(rawQuery) {
191
+ const queryString = this.toQueryString(rawQuery);
192
+ return queryString ? `?${queryString}` : "";
193
+ }
194
+ mergeRequestParams(params1, params2) {
195
+ return __spreadProps(__spreadValues(__spreadValues(__spreadValues({}, this.baseApiParams), params1), params2 || {}), {
196
+ headers: __spreadValues(__spreadValues(__spreadValues({}, this.baseApiParams.headers || {}), params1.headers || {}), params2 && params2.headers || {})
197
+ });
204
198
  }
205
- return url.protocol === "http:" || url.protocol === "https:";
206
- }
207
- function getURLBasedOnApi(opts) {
208
- return getURLBasedOn(opts.base, opts.path);
209
- }
210
- function getURLBasedOn(baseURL, path) {
211
- return `${baseURL.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
212
- }
213
- function mergeDeep(target, source) {
214
- const isObject = (obj) => obj && typeof obj === "object";
215
- if (!isObject(target) || !isObject(source)) {
216
- return source;
217
- }
218
- Object.keys(source).forEach((key) => {
219
- const targetValue = target[key];
220
- const sourceValue = source[key];
221
- if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
222
- target[key] = targetValue.concat(sourceValue);
223
- } else if (isObject(targetValue) && isObject(sourceValue)) {
224
- target[key] = mergeDeep(__spreadValues({}, targetValue), sourceValue);
225
- } else {
226
- target[key] = sourceValue;
227
- }
228
- });
229
- return target;
230
199
  }
200
+ /**
201
+ * @title Artalk API
202
+ * @version 2.0
203
+ * @license MIT (https://github.com/ArtalkJS/Artalk/blob/master/LICENSE)
204
+ * @baseUrl /api/v2
205
+ * @contact API Support <artalkjs@gmail.com> (https://artalk.js.org)
206
+ *
207
+ * Artalk is a modern comment system based on Golang.
208
+ */
209
+ let Api$1 = class Api extends HttpClient {
210
+ constructor() {
211
+ super(...arguments);
212
+ __publicField(this, "cache", {
213
+ /**
214
+ * @description Flush all cache on the server
215
+ *
216
+ * @tags Cache
217
+ * @name FlushCache
218
+ * @summary Flush Cache
219
+ * @request POST:/cache/flush
220
+ * @secure
221
+ * @response `200` `(HandlerMap & {
222
+ msg?: string,
223
+
224
+ })` OK
225
+ * @response `400` `(HandlerMap & {
226
+ msg?: string,
227
+
228
+ })` Bad Request
229
+ * @response `403` `(HandlerMap & {
230
+ msg?: string,
231
+
232
+ })` Forbidden
233
+ */
234
+ flushCache: (params = {}) => this.request(__spreadValues({
235
+ path: `/cache/flush`,
236
+ method: "POST",
237
+ secure: true,
238
+ format: "json"
239
+ }, params)),
240
+ /**
241
+ * @description Cache warming helps you to pre-load the cache to improve the performance of the first request
242
+ *
243
+ * @tags Cache
244
+ * @name WarmUpCache
245
+ * @summary Warm-Up Cache
246
+ * @request POST:/cache/warm_up
247
+ * @secure
248
+ * @response `200` `(HandlerMap & {
249
+ msg?: string,
250
+
251
+ })` OK
252
+ * @response `400` `(HandlerMap & {
253
+ msg?: string,
254
+
255
+ })` Bad Request
256
+ * @response `403` `(HandlerMap & {
257
+ msg?: string,
258
+
259
+ })` Forbidden
260
+ */
261
+ warmUpCache: (params = {}) => this.request(__spreadValues({
262
+ path: `/cache/warm_up`,
263
+ method: "POST",
264
+ secure: true,
265
+ format: "json"
266
+ }, params))
267
+ });
268
+ __publicField(this, "captcha", {
269
+ /**
270
+ * @description Get a base64 encoded captcha image or a HTML page to verify for user
271
+ *
272
+ * @tags Captcha
273
+ * @name GetCaptcha
274
+ * @summary Get Captcha
275
+ * @request GET:/captcha
276
+ * @response `200` `HandlerResponseCaptchaGet` OK
277
+ * @response `500` `(HandlerMap & {
278
+ msg?: string,
279
+
280
+ })` Internal Server Error
281
+ */
282
+ getCaptcha: (params = {}) => this.request(__spreadValues({
283
+ path: `/captcha`,
284
+ method: "GET",
285
+ format: "json"
286
+ }, params)),
287
+ /**
288
+ * @description Get the status of the user's captcha verification
289
+ *
290
+ * @tags Captcha
291
+ * @name GetCaptchaStatus
292
+ * @summary Get Captcha Status
293
+ * @request GET:/captcha/status
294
+ * @response `200` `HandlerResponseCaptchaStatus` OK
295
+ */
296
+ getCaptchaStatus: (params = {}) => this.request(__spreadValues({
297
+ path: `/captcha/status`,
298
+ method: "GET",
299
+ format: "json"
300
+ }, params)),
301
+ /**
302
+ * @description Verify user enters correct captcha code
303
+ *
304
+ * @tags Captcha
305
+ * @name VerifyCaptcha
306
+ * @summary Verify Captcha
307
+ * @request POST:/captcha/verify
308
+ * @response `200` `HandlerMap` OK
309
+ * @response `403` `(HandlerMap & {
310
+ img_data?: string,
311
+
312
+ })` Forbidden
313
+ */
314
+ verifyCaptcha: (data, params = {}) => this.request(__spreadValues({
315
+ path: `/captcha/verify`,
316
+ method: "POST",
317
+ body: data,
318
+ type: "application/json",
319
+ format: "json"
320
+ }, params))
321
+ });
322
+ __publicField(this, "comments", {
323
+ /**
324
+ * @description Get a list of comments by some conditions
325
+ *
326
+ * @tags Comment
327
+ * @name GetComments
328
+ * @summary Get Comment List
329
+ * @request GET:/comments
330
+ * @secure
331
+ * @response `200` `HandlerResponseCommentList` OK
332
+ * @response `500` `(HandlerMap & {
333
+ msg?: string,
334
+
335
+ })` Internal Server Error
336
+ */
337
+ getComments: (query, params = {}) => this.request(__spreadValues({
338
+ path: `/comments`,
339
+ method: "GET",
340
+ query,
341
+ secure: true,
342
+ type: "application/json",
343
+ format: "json"
344
+ }, params)),
345
+ /**
346
+ * @description Create a new comment
347
+ *
348
+ * @tags Comment
349
+ * @name CreateComment
350
+ * @summary Create Comment
351
+ * @request POST:/comments
352
+ * @secure
353
+ * @response `200` `HandlerResponseCommentCreate` OK
354
+ * @response `400` `(HandlerMap & {
355
+ msg?: string,
356
+
357
+ })` Bad Request
358
+ * @response `500` `(HandlerMap & {
359
+ msg?: string,
360
+
361
+ })` Internal Server Error
362
+ */
363
+ createComment: (comment, params = {}) => this.request(__spreadValues({
364
+ path: `/comments`,
365
+ method: "POST",
366
+ body: comment,
367
+ secure: true,
368
+ type: "application/json",
369
+ format: "json"
370
+ }, params)),
371
+ /**
372
+ * @description Update a specific comment
373
+ *
374
+ * @tags Comment
375
+ * @name UpdateComment
376
+ * @summary Update Comment
377
+ * @request PUT:/comments/{id}
378
+ * @secure
379
+ * @response `200` `HandlerResponseCommentUpdate` OK
380
+ * @response `400` `(HandlerMap & {
381
+ msg?: string,
382
+
383
+ })` Bad Request
384
+ * @response `403` `(HandlerMap & {
385
+ msg?: string,
386
+
387
+ })` Forbidden
388
+ * @response `404` `(HandlerMap & {
389
+ msg?: string,
390
+
391
+ })` Not Found
392
+ * @response `500` `(HandlerMap & {
393
+ msg?: string,
394
+
395
+ })` Internal Server Error
396
+ */
397
+ updateComment: (id, comment, params = {}) => this.request(__spreadValues({
398
+ path: `/comments/${id}`,
399
+ method: "PUT",
400
+ body: comment,
401
+ secure: true,
402
+ type: "application/json",
403
+ format: "json"
404
+ }, params)),
405
+ /**
406
+ * @description Delete a specific comment
407
+ *
408
+ * @tags Comment
409
+ * @name DeleteComment
410
+ * @summary Delete Comment
411
+ * @request DELETE:/comments/{id}
412
+ * @secure
413
+ * @response `200` `HandlerMap` OK
414
+ * @response `403` `(HandlerMap & {
415
+ msg?: string,
416
+
417
+ })` Forbidden
418
+ * @response `404` `(HandlerMap & {
419
+ msg?: string,
420
+
421
+ })` Not Found
422
+ * @response `500` `(HandlerMap & {
423
+ msg?: string,
424
+
425
+ })` Internal Server Error
426
+ */
427
+ deleteComment: (id, params = {}) => this.request(__spreadValues({
428
+ path: `/comments/${id}`,
429
+ method: "DELETE",
430
+ secure: true,
431
+ format: "json"
432
+ }, params))
433
+ });
434
+ __publicField(this, "conf", {
435
+ /**
436
+ * @description Get System Configs for UI
437
+ *
438
+ * @tags System
439
+ * @name Conf
440
+ * @summary Get System Configs
441
+ * @request GET:/conf
442
+ * @response `200` `CommonConfData` OK
443
+ */
444
+ conf: (params = {}) => this.request(__spreadValues({
445
+ path: `/conf`,
446
+ method: "GET",
447
+ format: "json"
448
+ }, params))
449
+ });
450
+ __publicField(this, "notifies", {
451
+ /**
452
+ * @description Get a list of notifies for user
453
+ *
454
+ * @tags Notify
455
+ * @name GetNotifies
456
+ * @summary Get Notifies
457
+ * @request GET:/notifies
458
+ * @response `200` `HandlerResponseNotifyList` OK
459
+ * @response `400` `(HandlerMap & {
460
+ msg?: string,
461
+
462
+ })` Bad Request
463
+ * @response `500` `(HandlerMap & {
464
+ msg?: string,
465
+
466
+ })` Internal Server Error
467
+ */
468
+ getNotifies: (query, params = {}) => this.request(__spreadValues({
469
+ path: `/notifies`,
470
+ method: "GET",
471
+ query,
472
+ type: "application/json",
473
+ format: "json"
474
+ }, params)),
475
+ /**
476
+ * @description Mark all notifies as read for user
477
+ *
478
+ * @tags Notify
479
+ * @name MarkAllNotifyRead
480
+ * @summary Mark All Notifies as Read
481
+ * @request POST:/notifies/read
482
+ * @response `200` `HandlerMap` OK
483
+ * @response `400` `(HandlerMap & {
484
+ msg?: string,
485
+
486
+ })` Bad Request
487
+ * @response `500` `(HandlerMap & {
488
+ msg?: string,
489
+
490
+ })` Internal Server Error
491
+ */
492
+ markAllNotifyRead: (options, params = {}) => this.request(__spreadValues({
493
+ path: `/notifies/read`,
494
+ method: "POST",
495
+ body: options,
496
+ type: "application/json",
497
+ format: "json"
498
+ }, params)),
499
+ /**
500
+ * @description Mark specific notification as read for user
501
+ *
502
+ * @tags Notify
503
+ * @name MarkNotifyRead
504
+ * @summary Mark Notify as Read
505
+ * @request POST:/notifies/{comment_id}/{notify_key}
506
+ * @response `200` `HandlerMap` OK
507
+ * @response `400` `(HandlerMap & {
508
+ msg?: string,
509
+
510
+ })` Bad Request
511
+ * @response `404` `(HandlerMap & {
512
+ msg?: string,
513
+
514
+ })` Not Found
515
+ * @response `500` `(HandlerMap & {
516
+ msg?: string,
517
+
518
+ })` Internal Server Error
519
+ */
520
+ markNotifyRead: (commentId, notifyKey, params = {}) => this.request(__spreadValues({
521
+ path: `/notifies/${commentId}/${notifyKey}`,
522
+ method: "POST",
523
+ format: "json"
524
+ }, params))
525
+ });
526
+ __publicField(this, "pages", {
527
+ /**
528
+ * @description Get a list of pages by some conditions
529
+ *
530
+ * @tags Page
531
+ * @name GetPages
532
+ * @summary Get Page List
533
+ * @request GET:/pages
534
+ * @secure
535
+ * @response `200` `HandlerResponsePageList` OK
536
+ * @response `403` `(HandlerMap & {
537
+ msg?: string,
538
+
539
+ })` Forbidden
540
+ */
541
+ getPages: (query, params = {}) => this.request(__spreadValues({
542
+ path: `/pages`,
543
+ method: "GET",
544
+ query,
545
+ secure: true,
546
+ type: "application/json",
547
+ format: "json"
548
+ }, params)),
549
+ /**
550
+ * @description Fetch the data of all pages
551
+ *
552
+ * @tags Page
553
+ * @name FetchAllPages
554
+ * @summary Fetch All Pages Data
555
+ * @request POST:/pages/fetch
556
+ * @secure
557
+ * @response `200` `HandlerMap` OK
558
+ * @response `400` `(HandlerMap & {
559
+ msg?: string,
560
+
561
+ })` Bad Request
562
+ * @response `500` `(HandlerMap & {
563
+ msg?: string,
564
+
565
+ })` Internal Server Error
566
+ */
567
+ fetchAllPages: (options, params = {}) => this.request(__spreadValues({
568
+ path: `/pages/fetch`,
569
+ method: "POST",
570
+ body: options,
571
+ secure: true,
572
+ type: "application/json",
573
+ format: "json"
574
+ }, params)),
575
+ /**
576
+ * @description Get the status of the task of fetching all pages
577
+ *
578
+ * @tags Page
579
+ * @name GetPageFetchStatus
580
+ * @summary Get Pages Fetch Status
581
+ * @request GET:/pages/fetch/status
582
+ * @secure
583
+ * @response `200` `HandlerResponsePageFetchStatus` OK
584
+ */
585
+ getPageFetchStatus: (params = {}) => this.request(__spreadValues({
586
+ path: `/pages/fetch/status`,
587
+ method: "GET",
588
+ secure: true,
589
+ format: "json"
590
+ }, params)),
591
+ /**
592
+ * @description Increase and get the number of page views
593
+ *
594
+ * @tags Page
595
+ * @name LogPv
596
+ * @summary Increase Page Views (PV)
597
+ * @request POST:/pages/pv
598
+ * @response `200` `HandlerResponsePagePV` OK
599
+ */
600
+ logPv: (page, params = {}) => this.request(__spreadValues({
601
+ path: `/pages/pv`,
602
+ method: "POST",
603
+ body: page,
604
+ type: "application/json",
605
+ format: "json"
606
+ }, params)),
607
+ /**
608
+ * @description Update a specific page
609
+ *
610
+ * @tags Page
611
+ * @name UpdatePage
612
+ * @summary Update Page
613
+ * @request PUT:/pages/{id}
614
+ * @secure
615
+ * @response `200` `HandlerResponsePageUpdate` OK
616
+ * @response `400` `(HandlerMap & {
617
+ msg?: string,
618
+
619
+ })` Bad Request
620
+ * @response `403` `(HandlerMap & {
621
+ msg?: string,
622
+
623
+ })` Forbidden
624
+ * @response `404` `(HandlerMap & {
625
+ msg?: string,
626
+
627
+ })` Not Found
628
+ * @response `500` `(HandlerMap & {
629
+ msg?: string,
630
+
631
+ })` Internal Server Error
632
+ */
633
+ updatePage: (id, page, params = {}) => this.request(__spreadValues({
634
+ path: `/pages/${id}`,
635
+ method: "PUT",
636
+ body: page,
637
+ secure: true,
638
+ type: "application/json",
639
+ format: "json"
640
+ }, params)),
641
+ /**
642
+ * @description Delete a specific page
643
+ *
644
+ * @tags Page
645
+ * @name DeletePage
646
+ * @summary Delete Page
647
+ * @request DELETE:/pages/{id}
648
+ * @secure
649
+ * @response `200` `HandlerMap` OK
650
+ * @response `403` `(HandlerMap & {
651
+ msg?: string,
652
+
653
+ })` Forbidden
654
+ * @response `404` `(HandlerMap & {
655
+ msg?: string,
656
+
657
+ })` Not Found
658
+ * @response `500` `(HandlerMap & {
659
+ msg?: string,
660
+
661
+ })` Internal Server Error
662
+ */
663
+ deletePage: (id, params = {}) => this.request(__spreadValues({
664
+ path: `/pages/${id}`,
665
+ method: "DELETE",
666
+ secure: true,
667
+ format: "json"
668
+ }, params)),
669
+ /**
670
+ * @description Fetch the data of a specific page
671
+ *
672
+ * @tags Page
673
+ * @name FetchPage
674
+ * @summary Fetch Page Data
675
+ * @request POST:/pages/{id}/fetch
676
+ * @secure
677
+ * @response `200` `HandlerResponsePageFetch` OK
678
+ * @response `404` `(HandlerMap & {
679
+ msg?: string,
680
+
681
+ })` Not Found
682
+ * @response `500` `(HandlerMap & {
683
+ msg?: string,
684
+
685
+ })` Internal Server Error
686
+ */
687
+ fetchPage: (id, params = {}) => this.request(__spreadValues({
688
+ path: `/pages/${id}/fetch`,
689
+ method: "POST",
690
+ secure: true,
691
+ type: "application/json",
692
+ format: "json"
693
+ }, params))
694
+ });
695
+ __publicField(this, "sendEmail", {
696
+ /**
697
+ * @description Send an email to test the email sender
698
+ *
699
+ * @tags System
700
+ * @name SendEmail
701
+ * @summary Send Email
702
+ * @request POST:/send_email
703
+ * @secure
704
+ * @response `200` `HandlerMap` OK
705
+ * @response `403` `(HandlerMap & {
706
+ msg?: string,
707
+
708
+ })` Forbidden
709
+ * @response `500` `HandlerMap` Internal Server Error
710
+ */
711
+ sendEmail: (email, params = {}) => this.request(__spreadValues({
712
+ path: `/send_email`,
713
+ method: "POST",
714
+ body: email,
715
+ secure: true,
716
+ type: "application/json",
717
+ format: "json"
718
+ }, params))
719
+ });
720
+ __publicField(this, "settings", {
721
+ /**
722
+ * @description Get settings from app config file
723
+ *
724
+ * @tags System
725
+ * @name GetSettings
726
+ * @summary Get Settings
727
+ * @request GET:/settings
728
+ * @secure
729
+ * @response `200` `HandlerResponseSettingGet` OK
730
+ * @response `403` `(HandlerMap & {
731
+ msg?: string,
732
+
733
+ })` Forbidden
734
+ * @response `500` `(HandlerMap & {
735
+ msg?: string,
736
+
737
+ })` Internal Server Error
738
+ */
739
+ getSettings: (params = {}) => this.request(__spreadValues({
740
+ path: `/settings`,
741
+ method: "GET",
742
+ secure: true,
743
+ format: "json"
744
+ }, params)),
745
+ /**
746
+ * @description Apply settings and restart the server
747
+ *
748
+ * @tags System
749
+ * @name ApplySettings
750
+ * @summary Save and apply Settings
751
+ * @request PUT:/settings
752
+ * @secure
753
+ * @response `200` `HandlerMap` OK
754
+ * @response `403` `(HandlerMap & {
755
+ msg?: string,
756
+
757
+ })` Forbidden
758
+ * @response `500` `(HandlerMap & {
759
+ msg?: string,
760
+
761
+ })` Internal Server Error
762
+ */
763
+ applySettings: (settings, params = {}) => this.request(__spreadValues({
764
+ path: `/settings`,
765
+ method: "PUT",
766
+ body: settings,
767
+ secure: true,
768
+ type: "application/json",
769
+ format: "json"
770
+ }, params)),
771
+ /**
772
+ * @description Get config templates in different languages for rendering the settings page in the frontend
773
+ *
774
+ * @tags System
775
+ * @name GetSettingsTemplate
776
+ * @summary Get Settings Template
777
+ * @request GET:/settings/template/{locale}
778
+ * @secure
779
+ * @response `200` `HandlerResponseSettingTemplate` OK
780
+ */
781
+ getSettingsTemplate: (locale, params = {}) => this.request(__spreadValues({
782
+ path: `/settings/template/${locale}`,
783
+ method: "GET",
784
+ secure: true,
785
+ format: "json"
786
+ }, params))
787
+ });
788
+ __publicField(this, "sites", {
789
+ /**
790
+ * @description Get a list of sites by some conditions
791
+ *
792
+ * @tags Site
793
+ * @name GetSites
794
+ * @summary Get Site List
795
+ * @request GET:/sites
796
+ * @secure
797
+ * @response `200` `HandlerResponseSiteList` OK
798
+ */
799
+ getSites: (params = {}) => this.request(__spreadValues({
800
+ path: `/sites`,
801
+ method: "GET",
802
+ secure: true,
803
+ format: "json"
804
+ }, params)),
805
+ /**
806
+ * @description Create a new site
807
+ *
808
+ * @tags Site
809
+ * @name CreateSite
810
+ * @summary Create Site
811
+ * @request POST:/sites
812
+ * @secure
813
+ * @response `200` `HandlerResponseSiteCreate` OK
814
+ * @response `400` `(HandlerMap & {
815
+ msg?: string,
816
+
817
+ })` Bad Request
818
+ * @response `403` `(HandlerMap & {
819
+ msg?: string,
820
+
821
+ })` Forbidden
822
+ * @response `500` `(HandlerMap & {
823
+ msg?: string,
824
+
825
+ })` Internal Server Error
826
+ */
827
+ createSite: (site, params = {}) => this.request(__spreadValues({
828
+ path: `/sites`,
829
+ method: "POST",
830
+ body: site,
831
+ secure: true,
832
+ type: "application/json",
833
+ format: "json"
834
+ }, params)),
835
+ /**
836
+ * @description Update a specific site
837
+ *
838
+ * @tags Site
839
+ * @name UpdateSite
840
+ * @summary Update Site
841
+ * @request PUT:/sites/{id}
842
+ * @secure
843
+ * @response `200` `HandlerResponseSiteUpdate` OK
844
+ */
845
+ updateSite: (id, site, params = {}) => this.request(__spreadValues({
846
+ path: `/sites/${id}`,
847
+ method: "PUT",
848
+ body: site,
849
+ secure: true,
850
+ type: "application/json",
851
+ format: "json"
852
+ }, params)),
853
+ /**
854
+ * @description Delete a specific site
855
+ *
856
+ * @tags Site
857
+ * @name DeleteSite
858
+ * @summary Site Delete
859
+ * @request DELETE:/sites/{id}
860
+ * @secure
861
+ * @response `200` `HandlerMap` OK
862
+ * @response `403` `(HandlerMap & {
863
+ msg?: string,
864
+
865
+ })` Forbidden
866
+ * @response `404` `(HandlerMap & {
867
+ msg?: string,
868
+
869
+ })` Not Found
870
+ * @response `500` `(HandlerMap & {
871
+ msg?: string,
872
+
873
+ })` Internal Server Error
874
+ */
875
+ deleteSite: (id, params = {}) => this.request(__spreadValues({
876
+ path: `/sites/${id}`,
877
+ method: "DELETE",
878
+ secure: true,
879
+ format: "json"
880
+ }, params))
881
+ });
882
+ __publicField(this, "stats", {
883
+ /**
884
+ * @description Get the statistics of various data analysis
885
+ *
886
+ * @tags Statistic
887
+ * @name GetStats
888
+ * @summary Statistic
889
+ * @request GET:/stats/{type}
890
+ * @response `200` `CommonJSONResult` OK
891
+ * @response `400` `(HandlerMap & {
892
+ msg?: string,
893
+
894
+ })` Bad Request
895
+ * @response `403` `(HandlerMap & {
896
+ msg?: string,
897
+
898
+ })` Forbidden
899
+ * @response `404` `(HandlerMap & {
900
+ msg?: string,
901
+
902
+ })` Not Found
903
+ * @response `500` `(HandlerMap & {
904
+ msg?: string,
905
+
906
+ })` Internal Server Error
907
+ */
908
+ getStats: (type, query, params = {}) => this.request(__spreadValues({
909
+ path: `/stats/${type}`,
910
+ method: "GET",
911
+ query,
912
+ type: "application/json",
913
+ format: "json"
914
+ }, params))
915
+ });
916
+ __publicField(this, "transfer", {
917
+ /**
918
+ * @description Export data from Artalk
919
+ *
920
+ * @tags Transfer
921
+ * @name ExportArtrans
922
+ * @summary Export Artrans
923
+ * @request GET:/transfer/export
924
+ * @secure
925
+ * @response `200` `HandlerResponseTransferExport` OK
926
+ * @response `500` `(HandlerMap & {
927
+ msg?: string,
928
+
929
+ })` Internal Server Error
930
+ */
931
+ exportArtrans: (params = {}) => this.request(__spreadValues({
932
+ path: `/transfer/export`,
933
+ method: "GET",
934
+ secure: true,
935
+ format: "json"
936
+ }, params)),
937
+ /**
938
+ * @description Import data to Artalk
939
+ *
940
+ * @tags Transfer
941
+ * @name ImportArtrans
942
+ * @summary Import Artrans
943
+ * @request POST:/transfer/import
944
+ * @secure
945
+ * @response `200` `string` OK
946
+ */
947
+ importArtrans: (data, params = {}) => this.request(__spreadValues({
948
+ path: `/transfer/import`,
949
+ method: "POST",
950
+ body: data,
951
+ secure: true,
952
+ type: "application/json"
953
+ }, params)),
954
+ /**
955
+ * @description Upload a file to prepare to import
956
+ *
957
+ * @tags Transfer
958
+ * @name UploadArtrans
959
+ * @summary Upload Artrans
960
+ * @request POST:/transfer/upload
961
+ * @secure
962
+ * @response `200` `(HandlerResponseTransferUpload & {
963
+ filename?: string,
964
+
965
+ })` OK
966
+ * @response `500` `(HandlerMap & {
967
+ msg?: string,
968
+
969
+ })` Internal Server Error
970
+ */
971
+ uploadArtrans: (data, params = {}) => this.request(__spreadValues({
972
+ path: `/transfer/upload`,
973
+ method: "POST",
974
+ body: data,
975
+ secure: true,
976
+ type: "multipart/form-data",
977
+ format: "json"
978
+ }, params))
979
+ });
980
+ __publicField(this, "upload", {
981
+ /**
982
+ * @description Upload file from this endpoint
983
+ *
984
+ * @tags Upload
985
+ * @name Upload
986
+ * @summary Upload
987
+ * @request POST:/upload
988
+ * @secure
989
+ * @response `200` `HandlerResponseUpload` OK
990
+ * @response `400` `(HandlerMap & {
991
+ msg?: string,
992
+
993
+ })` Bad Request
994
+ * @response `403` `(HandlerMap & {
995
+ msg?: string,
996
+
997
+ })` Forbidden
998
+ * @response `500` `(HandlerMap & {
999
+ msg?: string,
1000
+
1001
+ })` Internal Server Error
1002
+ */
1003
+ upload: (data, params = {}) => this.request(__spreadValues({
1004
+ path: `/upload`,
1005
+ method: "POST",
1006
+ body: data,
1007
+ secure: true,
1008
+ type: "multipart/form-data",
1009
+ format: "json"
1010
+ }, params))
1011
+ });
1012
+ __publicField(this, "user", {
1013
+ /**
1014
+ * @description Get user info to prepare for login or check current user status
1015
+ *
1016
+ * @tags Account
1017
+ * @name GetUser
1018
+ * @summary Get User Info
1019
+ * @request GET:/user
1020
+ * @secure
1021
+ * @response `200` `HandlerResponseUserInfo` OK
1022
+ * @response `400` `(HandlerMap & {
1023
+ msg?: string,
1024
+
1025
+ })` Bad Request
1026
+ */
1027
+ getUser: (query, params = {}) => this.request(__spreadValues({
1028
+ path: `/user`,
1029
+ method: "GET",
1030
+ query,
1031
+ secure: true,
1032
+ format: "json"
1033
+ }, params)),
1034
+ /**
1035
+ * @description Login user by name or email
1036
+ *
1037
+ * @tags Account
1038
+ * @name Login
1039
+ * @summary Get Access Token
1040
+ * @request POST:/user/access_token
1041
+ * @response `200` `HandlerResponseUserLogin` OK
1042
+ * @response `400` `(HandlerMap & {
1043
+ " data"?: {
1044
+ need_name_select?: (string)[],
1045
+
1046
+ },
1047
+ msg?: string,
1048
+
1049
+ })` Multiple users with the same email address are matched
1050
+ * @response `403` `(HandlerMap & {
1051
+ msg?: string,
1052
+
1053
+ })` Forbidden
1054
+ * @response `500` `(HandlerMap & {
1055
+ msg?: string,
1056
+
1057
+ })` Internal Server Error
1058
+ */
1059
+ login: (user, params = {}) => this.request(__spreadValues({
1060
+ path: `/user/access_token`,
1061
+ method: "POST",
1062
+ body: user,
1063
+ type: "application/json",
1064
+ format: "json"
1065
+ }, params)),
1066
+ /**
1067
+ * @description Get user login status by header Authorization
1068
+ *
1069
+ * @tags Account
1070
+ * @name GetUserStatus
1071
+ * @summary Get Login Status
1072
+ * @request GET:/user/status
1073
+ * @secure
1074
+ * @response `200` `HandlerResponseUserStatus` OK
1075
+ */
1076
+ getUserStatus: (query, params = {}) => this.request(__spreadValues({
1077
+ path: `/user/status`,
1078
+ method: "GET",
1079
+ query,
1080
+ secure: true,
1081
+ format: "json"
1082
+ }, params))
1083
+ });
1084
+ __publicField(this, "users", {
1085
+ /**
1086
+ * @description Create a new user
1087
+ *
1088
+ * @tags User
1089
+ * @name CreateUser
1090
+ * @summary Create User
1091
+ * @request POST:/users
1092
+ * @secure
1093
+ * @response `200` `HandlerResponseUserCreate` OK
1094
+ * @response `400` `(HandlerMap & {
1095
+ msg?: string,
1096
+
1097
+ })` Bad Request
1098
+ * @response `403` `(HandlerMap & {
1099
+ msg?: string,
1100
+
1101
+ })` Forbidden
1102
+ * @response `500` `(HandlerMap & {
1103
+ msg?: string,
1104
+
1105
+ })` Internal Server Error
1106
+ */
1107
+ createUser: (user, params = {}) => this.request(__spreadValues({
1108
+ path: `/users`,
1109
+ method: "POST",
1110
+ body: user,
1111
+ secure: true,
1112
+ type: "application/json",
1113
+ format: "json"
1114
+ }, params)),
1115
+ /**
1116
+ * @description Update a specific user
1117
+ *
1118
+ * @tags User
1119
+ * @name UpdateUser
1120
+ * @summary Update User
1121
+ * @request PUT:/users/{id}
1122
+ * @secure
1123
+ * @response `200` `HandlerResponseUserUpdate` OK
1124
+ * @response `400` `(HandlerMap & {
1125
+ msg?: string,
1126
+
1127
+ })` Bad Request
1128
+ * @response `403` `(HandlerMap & {
1129
+ msg?: string,
1130
+
1131
+ })` Forbidden
1132
+ * @response `404` `(HandlerMap & {
1133
+ msg?: string,
1134
+
1135
+ })` Not Found
1136
+ * @response `500` `(HandlerMap & {
1137
+ msg?: string,
1138
+
1139
+ })` Internal Server Error
1140
+ */
1141
+ updateUser: (id, user, params = {}) => this.request(__spreadValues({
1142
+ path: `/users/${id}`,
1143
+ method: "PUT",
1144
+ body: user,
1145
+ secure: true,
1146
+ type: "application/json",
1147
+ format: "json"
1148
+ }, params)),
1149
+ /**
1150
+ * @description Delete a specific user
1151
+ *
1152
+ * @tags User
1153
+ * @name DeleteUser
1154
+ * @summary Delete User
1155
+ * @request DELETE:/users/{id}
1156
+ * @secure
1157
+ * @response `200` `HandlerMap` OK
1158
+ * @response `403` `(HandlerMap & {
1159
+ msg?: string,
1160
+
1161
+ })` Forbidden
1162
+ * @response `404` `(HandlerMap & {
1163
+ msg?: string,
1164
+
1165
+ })` Not Found
1166
+ * @response `500` `(HandlerMap & {
1167
+ msg?: string,
1168
+
1169
+ })` Internal Server Error
1170
+ */
1171
+ deleteUser: (id, params = {}) => this.request(__spreadValues({
1172
+ path: `/users/${id}`,
1173
+ method: "DELETE",
1174
+ secure: true,
1175
+ format: "json"
1176
+ }, params)),
1177
+ /**
1178
+ * @description Get a list of users by some conditions
1179
+ *
1180
+ * @tags User
1181
+ * @name GetUsers
1182
+ * @summary Get User List
1183
+ * @request GET:/users/{type}
1184
+ * @secure
1185
+ * @response `200` `HandlerResponseAdminUserList` OK
1186
+ * @response `403` `(HandlerMap & {
1187
+ msg?: string,
1188
+
1189
+ })` Forbidden
1190
+ */
1191
+ getUsers: (type, query, params = {}) => this.request(__spreadValues({
1192
+ path: `/users/${type}`,
1193
+ method: "GET",
1194
+ query,
1195
+ secure: true,
1196
+ type: "application/json",
1197
+ format: "json"
1198
+ }, params))
1199
+ });
1200
+ __publicField(this, "version", {
1201
+ /**
1202
+ * @description Get the version of Artalk
1203
+ *
1204
+ * @tags System
1205
+ * @name GetVersion
1206
+ * @summary Get Version Info
1207
+ * @request GET:/version
1208
+ * @response `200` `CommonApiVersionData` OK
1209
+ */
1210
+ getVersion: (params = {}) => this.request(__spreadValues({
1211
+ path: `/version`,
1212
+ method: "GET",
1213
+ format: "json"
1214
+ }, params))
1215
+ });
1216
+ __publicField(this, "votes", {
1217
+ /**
1218
+ * @description Sync the number of votes in the `comments` or `pages` data tables to keep them the same as the `votes` table
1219
+ *
1220
+ * @tags Vote
1221
+ * @name SyncVotes
1222
+ * @summary Sync Vote Data
1223
+ * @request POST:/votes/sync
1224
+ * @secure
1225
+ * @response `200` `HandlerMap` OK
1226
+ * @response `403` `(HandlerMap & {
1227
+ msg?: string,
1228
+
1229
+ })` Forbidden
1230
+ */
1231
+ syncVotes: (params = {}) => this.request(__spreadValues({
1232
+ path: `/votes/sync`,
1233
+ method: "POST",
1234
+ secure: true,
1235
+ format: "json"
1236
+ }, params)),
1237
+ /**
1238
+ * @description Vote for a specific comment or page
1239
+ *
1240
+ * @tags Vote
1241
+ * @name Vote
1242
+ * @summary Vote
1243
+ * @request POST:/votes/{type}/{target_id}
1244
+ * @response `200` `HandlerResponseVote` OK
1245
+ * @response `403` `(HandlerMap & {
1246
+ msg?: string,
1247
+
1248
+ })` Forbidden
1249
+ * @response `404` `(HandlerMap & {
1250
+ msg?: string,
1251
+
1252
+ })` Not Found
1253
+ * @response `500` `(HandlerMap & {
1254
+ msg?: string,
1255
+
1256
+ })` Internal Server Error
1257
+ */
1258
+ vote: (type, targetId, vote, params = {}) => this.request(__spreadValues({
1259
+ path: `/votes/${type}/${targetId}`,
1260
+ method: "POST",
1261
+ body: vote,
1262
+ type: "application/json",
1263
+ format: "json"
1264
+ }, params))
1265
+ });
1266
+ }
1267
+ };
231
1268
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
232
1269
  function getDefaultExportFromCjs(x) {
233
1270
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -628,746 +1665,91 @@ function getDefaultExportFromCjs(x) {
628
1665
  });
629
1666
  })(typeof self !== "undefined" ? self : commonjsGlobal);
630
1667
  });
631
- const en = {
632
- /* Editor */
633
- placeholder: "Leave a comment",
634
- noComment: "No Comment",
635
- send: "Send",
636
- save: "Save",
637
- nick: "Nickname",
638
- email: "Email",
639
- link: "Website",
640
- emoticon: "Emoji",
641
- preview: "Preview",
642
- image: "Image",
643
- uploadFail: "Upload Failed",
644
- commentFail: "Failed to comment",
645
- restoredMsg: "Content has been restored",
646
- onlyAdminCanReply: "Only admin can reply",
647
- uploadLoginMsg: "Please fill in your name and email to upload",
648
- /* List */
649
- counter: "{count} Comments",
650
- sortLatest: "Latest",
651
- sortOldest: "Oldest",
652
- sortBest: "Best",
653
- sortAuthor: "Author",
654
- openComment: "Open Comment",
655
- closeComment: "Close Comment",
656
- listLoadFailMsg: "Failed to load comments",
657
- listRetry: "Click to retry",
658
- loadMore: "Load More",
659
- /* Comment */
660
- admin: "Admin",
661
- reply: "Reply",
662
- voteUp: "Up",
663
- voteDown: "Down",
664
- voteFail: "Vote Failed",
665
- readMore: "Read More",
666
- actionConfirm: "Confirm",
667
- collapse: "Collapse",
668
- collapsed: "Collapsed",
669
- collapsedMsg: "This comment has been collapsed",
670
- expand: "Expand",
671
- approved: "Approved",
672
- pending: "Pending",
673
- pendingMsg: "Pending, visible only to commenter.",
674
- edit: "Edit",
675
- editCancel: "Cancel Edit",
676
- delete: "Delete",
677
- deleteConfirm: "Confirm",
678
- pin: "Pin",
679
- unpin: "Unpin",
680
- /* Time */
681
- seconds: "seconds ago",
682
- minutes: "minutes ago",
683
- hours: "hours ago",
684
- days: "days ago",
685
- now: "just now",
686
- /* Checker */
687
- adminCheck: "Enter admin password:",
688
- captchaCheck: "Enter the CAPTCHA to continue:",
689
- confirm: "Confirm",
690
- cancel: "Cancel",
691
- /* Sidebar */
692
- msgCenter: "Messages",
693
- ctrlCenter: "Admin",
694
- /* General */
695
- frontend: "Frontend",
696
- backend: "Backend",
697
- loading: "Loading",
698
- loadFail: "Load Failed",
699
- editing: "Editing",
700
- editFail: "Edit Failed",
701
- deleting: "Deleting",
702
- deleteFail: "Delete Failed",
703
- reqGot: "Request got",
704
- reqAborted: "Request timed out or terminated unexpectedly",
705
- updateMsg: "Please update Artalk {name} to get the full experience",
706
- currentVersion: "Current Version",
707
- ignore: "Ignore",
708
- open: "Open"
709
- };
710
- const zhCN = {
711
- /* Editor */
712
- placeholder: "键入内容...",
713
- noComment: "「此时无声胜有声」",
714
- send: "发送评论",
715
- save: "保存评论",
716
- nick: "昵称",
717
- email: "邮箱",
718
- link: "网址",
719
- emoticon: "表情",
720
- preview: "预览",
721
- image: "图片",
722
- uploadFail: "上传失败",
723
- commentFail: "评论失败",
724
- restoredMsg: "内容已自动恢复",
725
- onlyAdminCanReply: "仅管理员可评论",
726
- uploadLoginMsg: "填入你的名字邮箱才能上传哦",
727
- /* List */
728
- counter: "{count} 条评论",
729
- sortLatest: "最新",
730
- sortOldest: "最早",
731
- sortBest: "最热",
732
- sortAuthor: "作者",
733
- openComment: "打开评论",
734
- closeComment: "关闭评论",
735
- listLoadFailMsg: "无法获取评论列表数据",
736
- listRetry: "点击重新获取",
737
- loadMore: "加载更多",
738
- /* Comment */
739
- admin: "管理员",
740
- reply: "回复",
741
- voteUp: "赞同",
742
- voteDown: "反对",
743
- voteFail: "投票失败",
744
- readMore: "阅读更多",
745
- actionConfirm: "确认操作",
746
- collapse: "折叠",
747
- collapsed: "已折叠",
748
- collapsedMsg: "该评论已被系统或管理员折叠",
749
- expand: "展开",
750
- approved: "已审",
751
- pending: "待审",
752
- pendingMsg: "审核中,仅本人可见。",
753
- edit: "编辑",
754
- editCancel: "取消编辑",
755
- delete: "删除",
756
- deleteConfirm: "确认删除",
757
- pin: "置顶",
758
- unpin: "取消置顶",
759
- /* Time */
760
- seconds: "秒前",
761
- minutes: "分钟前",
762
- hours: "小时前",
763
- days: "天前",
764
- now: "刚刚",
765
- /* Checker */
766
- adminCheck: "键入密码来验证管理员身份:",
767
- captchaCheck: "键入验证码继续:",
768
- confirm: "确认",
769
- cancel: "取消",
770
- /* Sidebar */
771
- msgCenter: "通知中心",
772
- ctrlCenter: "控制中心",
773
- /* General */
774
- frontend: "前端",
775
- backend: "后端",
776
- loading: "加载中",
777
- loadFail: "加载失败",
778
- editing: "修改中",
779
- editFail: "修改失败",
780
- deleting: "删除中",
781
- deleteFail: "删除失败",
782
- reqGot: "请求响应",
783
- reqAborted: "请求超时或意外终止",
784
- updateMsg: "请更新 Artalk {name} 以获得完整体验",
785
- currentVersion: "当前版本",
786
- ignore: "忽略",
787
- open: "打开"
788
- };
789
- const GLOBAL_LOCALES_KEY = "ArtalkI18n";
790
- const internal = {
791
- "en": en,
792
- "en-US": en,
793
- "zh-CN": zhCN
794
- };
795
- function findLocaleSet(lang) {
796
- lang = lang.replace(
797
- /^([a-zA-Z]+)(-[a-zA-Z]+)?$/,
798
- (_, p1, p2) => p1.toLowerCase() + (p2 || "").toUpperCase()
799
- );
800
- if (internal[lang]) {
801
- return internal[lang];
802
- }
803
- if (window[GLOBAL_LOCALES_KEY] && window[GLOBAL_LOCALES_KEY][lang]) {
804
- return window[GLOBAL_LOCALES_KEY][lang];
805
- }
806
- return internal.en;
807
- }
808
- let LocaleConf = "en";
809
- let LocaleDict = findLocaleSet(LocaleConf);
810
- function setLocale(locale) {
811
- if (locale === LocaleConf)
812
- return;
813
- LocaleConf = locale;
814
- LocaleDict = typeof locale === "string" ? findLocaleSet(locale) : locale;
815
- }
816
- function t(key, args = {}) {
817
- let str = (LocaleDict == null ? void 0 : LocaleDict[key]) || key;
818
- str = str.replace(/\{\s*(\w+?)\s*\}/g, (_, token) => args[token] || "");
819
- return str;
820
- }
821
- function Fetch$1(opts, input, init2, timeout) {
822
- return __async(this, null, function* () {
823
- var _a, _b;
824
- if (opts.apiToken) {
825
- const headers = new Headers(init2.headers);
826
- headers.set("Authorization", `Bearer ${opts.apiToken}`);
827
- init2.headers = headers;
1668
+ const Fetch$1 = (opts, input, init2) => __async(void 0, null, function* () {
1669
+ const apiToken = opts.getApiToken && opts.getApiToken();
1670
+ const headers = new Headers(__spreadValues({
1671
+ "Authorization": apiToken ? `Bearer ${apiToken}` : ""
1672
+ }, init2 == null ? void 0 : init2.headers));
1673
+ if (!headers.get("Authorization"))
1674
+ headers.delete("Authorization");
1675
+ const resp = yield fetch(input, __spreadProps(__spreadValues({}, init2), {
1676
+ headers
1677
+ }));
1678
+ if (!resp.ok) {
1679
+ const json = (yield resp.json().catch(() => {
1680
+ })) || {};
1681
+ if (json.need_captcha) {
1682
+ opts.onNeedCheckCaptcha && (yield opts.onNeedCheckCaptcha({
1683
+ data: { imgData: json.img_data, iframe: json.iframe }
1684
+ }));
1685
+ return Fetch$1(opts, input, init2);
828
1686
  }
829
- const resp = yield timeoutFetch(input, timeout || opts.timeout || 15e3, init2);
830
- const respHttpCode = resp.status;
831
- const noAccessCodes = [401, 400];
832
- const isNoAccess = noAccessCodes.includes(respHttpCode);
833
- if (!resp.ok && !isNoAccess)
834
- throw new Error(`${t("reqGot")} ${respHttpCode}`);
835
- let json = yield resp.json();
836
- const recall = (resolve, reject) => {
837
- Fetch$1(opts, input, init2).then((d) => {
838
- resolve(d);
839
- }).catch((e) => {
840
- reject(e);
841
- });
842
- };
843
- if ((_a = json.data) == null ? void 0 : _a.need_captcha) {
844
- json = yield new Promise((resolve, reject) => {
845
- opts.onNeedCheckCaptcha && opts.onNeedCheckCaptcha({
846
- data: { imgData: json.data.img_data, iframe: json.data.iframe },
847
- recall: () => {
848
- recall(resolve, reject);
849
- },
850
- reject: () => {
851
- reject(json);
852
- }
853
- });
854
- });
855
- } else if (((_b = json.data) == null ? void 0 : _b.need_login) || isNoAccess) {
856
- json = yield new Promise((resolve, reject) => {
857
- opts.onNeedCheckAdmin && opts.onNeedCheckAdmin({
858
- recall: () => {
859
- recall(resolve, reject);
860
- },
861
- reject: () => {
862
- reject(json);
863
- }
864
- });
865
- });
1687
+ if (json.need_login) {
1688
+ opts.onNeedCheckAdmin && (yield opts.onNeedCheckAdmin({}));
1689
+ return Fetch$1(opts, input, init2);
866
1690
  }
867
- if (!json.success)
868
- throw json;
869
- return json;
870
- });
871
- }
872
- function POST(opts, url, data) {
873
- return __async(this, null, function* () {
874
- const init2 = {
875
- method: "POST"
876
- };
877
- data = __spreadValues({ site_name: opts.siteName || "" }, data || {});
878
- init2.body = ToFormData(data);
879
- const json = yield Fetch$1(opts, url, init2);
880
- return json.data || {};
881
- });
882
- }
883
- function ToFormData(object) {
884
- const formData = new FormData();
885
- Object.keys(object).forEach((key) => formData.append(key, String(object[key])));
886
- return formData;
887
- }
888
- function timeoutFetch(url, ms, opts) {
889
- var _a;
890
- const controller = new AbortController();
891
- (_a = opts.signal) == null ? void 0 : _a.addEventListener("abort", () => controller.abort());
892
- let promise = fetch(url, __spreadProps(__spreadValues({}, opts), { signal: controller.signal }));
893
- if (ms > 0) {
894
- const timer = setTimeout(() => controller.abort(), ms);
895
- promise.finally(() => {
896
- clearTimeout(timer);
897
- });
898
- }
899
- promise = promise.catch((err) => {
900
- throw (err || {}).name === "AbortError" ? new Error(t("reqAborted")) : err;
901
- });
902
- return promise;
903
- }
904
- class ApiBase {
905
- constructor(options) {
906
- this.options = options;
1691
+ throw createError(resp.status, json);
907
1692
  }
908
- POST(path, data) {
909
- return __async(this, null, function* () {
910
- return POST(this.options, this.options.baseURL + path, data);
911
- });
1693
+ return resp;
1694
+ });
1695
+ class FetchException extends Error {
1696
+ constructor() {
1697
+ super(...arguments);
1698
+ __publicField(this, "code", 0);
1699
+ __publicField(this, "message", "fetch error");
1700
+ __publicField(this, "data");
912
1701
  }
913
- Fetch(path, init2, timeout) {
914
- return __async(this, null, function* () {
915
- return Fetch$1(this.options, this.options.baseURL + path, init2, timeout);
1702
+ }
1703
+ function createError(code, data) {
1704
+ const err = new FetchException();
1705
+ err.message = data.msg || data.message || "fetch error";
1706
+ err.code = code;
1707
+ err.data = data;
1708
+ console.error(err);
1709
+ return err;
1710
+ }
1711
+ class Api2 extends Api$1 {
1712
+ constructor(opts) {
1713
+ super({
1714
+ baseUrl: opts.baseURL,
1715
+ customFetch: (input, init2) => Fetch$1(opts, input, init2)
916
1716
  });
1717
+ __publicField(this, "_opts");
1718
+ this._opts = opts;
917
1719
  }
918
1720
  /**
919
- * Carry user info to request params
1721
+ * Get user info as params for request
920
1722
  *
921
- * @param params Request params
922
1723
  * @returns Request params with user info
923
1724
  */
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
- }
932
- }
933
- class CommentApi extends ApiBase {
934
- /** 评论 · 获取 */
935
- get(offset, pageSize, flatMode, paramsEditor) {
936
- const params = {
937
- page_key: this.options.pageKey,
938
- site_name: this.options.siteName,
939
- limit: pageSize,
940
- offset
941
- };
942
- if (flatMode)
943
- params.flat_mode = flatMode;
944
- this.withUserInfo(params);
945
- if (paramsEditor)
946
- paramsEditor(params);
947
- return this.POST("/get", params);
948
- }
949
- /** 评论 · 创建 */
950
- add(comment) {
951
- return __async(this, null, function* () {
952
- const params = {
953
- name: comment.nick,
954
- email: comment.email,
955
- link: comment.link,
956
- content: comment.content,
957
- rid: comment.rid,
958
- page_key: comment.page_key,
959
- ua: yield getCorrectUserAgent()
960
- // 需要后端支持,获取修正后的 UA
961
- };
962
- if (comment.page_title)
963
- params.page_title = comment.page_title;
964
- if (comment.site_name)
965
- params.site_name = comment.site_name;
966
- const data = yield this.POST("/add", params);
967
- return data.comment;
968
- });
969
- }
970
- /** 评论 · 修改 */
971
- commentEdit(data) {
972
- return __async(this, null, function* () {
973
- const params = __spreadValues({}, data);
974
- const d = yield this.POST("/admin/comment-edit", params);
975
- return d.comment;
976
- });
977
- }
978
- /** 评论 · 删除 */
979
- commentDel(commentID, siteName) {
980
- const params = {
981
- id: String(commentID),
982
- site_name: siteName || ""
983
- };
984
- return this.POST("/admin/comment-del", params);
985
- }
986
- /** 投票 */
987
- vote(targetID, type) {
988
- return __async(this, null, function* () {
989
- const params = {
990
- target_id: targetID,
991
- type
992
- };
993
- this.withUserInfo(params);
994
- const data = yield this.POST("/vote", params);
995
- return data;
996
- });
1725
+ getUserFields() {
1726
+ const user = this._opts.userInfo;
1727
+ if (!(user == null ? void 0 : user.name) || !(user == null ? void 0 : user.email))
1728
+ return void 0;
1729
+ return { name: user.name, email: user.email };
997
1730
  }
998
1731
  }
999
- class PageApi extends ApiBase {
1000
- /** 页面 · 获取 */
1001
- pageGet(siteName, offset, limit) {
1002
- return __async(this, null, function* () {
1003
- const params = {
1004
- site_name: siteName || "",
1005
- offset: offset || 0,
1006
- limit: limit || 15
1007
- };
1008
- const d = yield this.POST("/admin/page-get", params);
1009
- return d;
1010
- });
1011
- }
1012
- /** 页面 · 修改 */
1013
- pageEdit(data) {
1014
- return __async(this, null, function* () {
1015
- const params = {
1016
- id: data.id,
1017
- key: data.key,
1018
- title: data.title,
1019
- admin_only: data.admin_only,
1020
- site_name: data.site_name || this.options.siteName
1021
- };
1022
- const d = yield this.POST("/admin/page-edit", params);
1023
- return d.page;
1024
- });
1025
- }
1026
- /** 页面 · 删除 */
1027
- pageDel(pageKey, siteName) {
1028
- const params = {
1029
- key: String(pageKey),
1030
- site_name: siteName || ""
1031
- };
1032
- return this.POST("/admin/page-del", params);
1033
- }
1034
- /** 页面 · 数据更新 */
1035
- pageFetch(id, siteName, getStatus) {
1036
- return __async(this, null, function* () {
1037
- const params = {};
1038
- if (id)
1039
- params.id = id;
1040
- if (siteName)
1041
- params.site_name = siteName;
1042
- if (getStatus)
1043
- params.get_status = getStatus;
1044
- const d = yield this.POST("/admin/page-fetch", params);
1045
- return d;
1046
- });
1047
- }
1048
- /** PV */
1049
- pv() {
1050
- return __async(this, null, function* () {
1051
- const params = {
1052
- page_key: this.options.pageKey || "",
1053
- page_title: this.options.pageTitle || ""
1054
- };
1055
- const p = yield this.POST("/pv", params);
1056
- return p.pv;
1057
- });
1058
- }
1059
- /** 统计 */
1060
- stat(type, pageKeys, limit) {
1061
- return __async(this, null, function* () {
1062
- const params = {
1063
- type
1064
- };
1065
- if (pageKeys)
1066
- params.page_keys = Array.isArray(pageKeys) ? pageKeys.join(",") : pageKeys;
1067
- if (limit)
1068
- params.limit = limit;
1069
- const data = yield this.POST(`/stat`, params);
1070
- return data;
1071
- });
1072
- }
1732
+ var escapes = {
1733
+ "&": "&amp;",
1734
+ "<": "&lt;",
1735
+ ">": "&gt;",
1736
+ '"': "&quot;",
1737
+ "'": "&#39;"
1738
+ };
1739
+ var unescapes = {
1740
+ "&amp;": "&",
1741
+ "&lt;": "<",
1742
+ "&gt;": ">",
1743
+ "&quot;": '"',
1744
+ "&#39;": "'"
1745
+ };
1746
+ var rescaped = /(&amp;|&lt;|&gt;|&quot;|&#39;)/g;
1747
+ var runescaped = /[&<>"']/g;
1748
+ function escapeHtmlChar(match) {
1749
+ return escapes[match];
1073
1750
  }
1074
- class SiteApi extends ApiBase {
1075
- /** 站点 · 获取 */
1076
- siteGet() {
1077
- return __async(this, null, function* () {
1078
- const params = {};
1079
- const d = yield this.POST("/admin/site-get", params);
1080
- return d.sites;
1081
- });
1082
- }
1083
- /** 站点 · 创建 */
1084
- siteAdd(name, urls) {
1085
- return __async(this, null, function* () {
1086
- const params = {
1087
- name,
1088
- urls,
1089
- site_name: ""
1090
- // 全局保留字段,当前站点名
1091
- };
1092
- const d = yield this.POST("/admin/site-add", params);
1093
- return d.site;
1094
- });
1095
- }
1096
- /** 站点 · 修改 */
1097
- siteEdit(data) {
1098
- return __async(this, null, function* () {
1099
- const params = {
1100
- id: data.id,
1101
- name: data.name || "",
1102
- urls: data.urls || ""
1103
- };
1104
- const d = yield this.POST("/admin/site-edit", params);
1105
- return d.site;
1106
- });
1107
- }
1108
- /** 站点 · 删除 */
1109
- siteDel(id, delContent = false) {
1110
- const params = { id, del_content: delContent };
1111
- return this.POST("/admin/site-del", params);
1112
- }
1113
- /** 导出 */
1114
- export() {
1115
- return __async(this, null, function* () {
1116
- var _a;
1117
- const d = yield this.Fetch(`/admin/export`, { method: "POST" }, 0);
1118
- return ((_a = d.data) == null ? void 0 : _a.data) || "";
1119
- });
1120
- }
1121
- }
1122
- class UserApi extends ApiBase {
1123
- /** 用户 · 登录 */
1124
- login(name, email, password) {
1125
- return __async(this, null, function* () {
1126
- const params = {
1127
- name,
1128
- email,
1129
- password
1130
- };
1131
- const data = yield this.POST("/login", params);
1132
- return data;
1133
- });
1134
- }
1135
- /** 用户 · 获取 */
1136
- userGet(name, email) {
1137
- const ctrl = new AbortController();
1138
- const params = {
1139
- name,
1140
- email
1141
- };
1142
- const req = this.Fetch(`/user-get`, {
1143
- method: "POST",
1144
- body: ToFormData(params),
1145
- signal: ctrl.signal
1146
- }).then((json) => ({
1147
- user: json.data.user,
1148
- is_login: json.data.is_login,
1149
- unread: json.data.unread || [],
1150
- unread_count: json.data.unread_count || 0
1151
- }));
1152
- return {
1153
- req,
1154
- abort: () => {
1155
- ctrl.abort();
1156
- }
1157
- };
1158
- }
1159
- /** 用户 · 登录状态 */
1160
- loginStatus() {
1161
- return __async(this, null, function* () {
1162
- const data = yield this.POST("/login-status", this.withUserInfo({}));
1163
- return data || { is_login: false, is_admin: false };
1164
- });
1165
- }
1166
- /** 用户 · 注销 */
1167
- logout() {
1168
- return __async(this, null, function* () {
1169
- return this.POST("/logout");
1170
- });
1171
- }
1172
- /** 已读标记 */
1173
- markRead(commentID, notifyKey, readAll = false) {
1174
- const params = {
1175
- comment_id: commentID,
1176
- notify_key: notifyKey
1177
- };
1178
- if (readAll) {
1179
- delete params.comment_id;
1180
- delete params.notify_key;
1181
- params.read_all = true;
1182
- this.withUserInfo(params);
1183
- }
1184
- return this.POST(`/mark-read`, params);
1185
- }
1186
- /** 用户 · 列表 */
1187
- userList(offset, limit, type) {
1188
- return __async(this, null, function* () {
1189
- const params = {
1190
- offset: offset || 0,
1191
- limit: limit || 15
1192
- };
1193
- if (type)
1194
- params.type = type;
1195
- const d = yield this.POST("/admin/user-get", params);
1196
- return d;
1197
- });
1198
- }
1199
- /** 用户 · 新增 */
1200
- userAdd(user, password) {
1201
- return __async(this, null, function* () {
1202
- const params = {
1203
- name: user.name || "",
1204
- email: user.email || "",
1205
- password: password || "",
1206
- link: user.link || "",
1207
- is_admin: user.is_admin || false,
1208
- site_names: user.site_names_raw || "",
1209
- receive_email: user.receive_email || true,
1210
- badge_name: user.badge_name || "",
1211
- badge_color: user.badge_color || ""
1212
- };
1213
- const d = yield this.POST("/admin/user-add", params);
1214
- return d.user;
1215
- });
1216
- }
1217
- /** 用户 · 修改 */
1218
- userEdit(user, password) {
1219
- return __async(this, null, function* () {
1220
- const params = {
1221
- id: user.id,
1222
- name: user.name || "",
1223
- email: user.email || "",
1224
- password: password || "",
1225
- link: user.link || "",
1226
- is_admin: user.is_admin || false,
1227
- site_names: user.site_names_raw || "",
1228
- receive_email: user.receive_email || true,
1229
- badge_name: user.badge_name || "",
1230
- badge_color: user.badge_color || ""
1231
- };
1232
- const d = yield this.POST("/admin/user-edit", params);
1233
- return d.user;
1234
- });
1235
- }
1236
- /** 用户 · 删除 */
1237
- userDel(userID) {
1238
- return this.POST("/admin/user-del", {
1239
- id: String(userID)
1240
- });
1241
- }
1242
- }
1243
- class SystemApi extends ApiBase {
1244
- /** 获取配置 */
1245
- conf() {
1246
- return __async(this, null, function* () {
1247
- const data = yield this.POST(`/conf`);
1248
- return {
1249
- frontend_conf: data.frontend_conf,
1250
- version: data.version
1251
- };
1252
- });
1253
- }
1254
- /** 获取配置数据 */
1255
- getSettings() {
1256
- return __async(this, null, function* () {
1257
- const data = yield this.POST("/admin/setting-get");
1258
- return data;
1259
- });
1260
- }
1261
- /** 保存配置数据 */
1262
- saveSettings(yamlStr) {
1263
- return __async(this, null, function* () {
1264
- const data = yield this.POST("/admin/setting-save", {
1265
- data: yamlStr
1266
- });
1267
- return data;
1268
- });
1269
- }
1270
- /** 获取 API 版本信息 */
1271
- version() {
1272
- return __async(this, null, function* () {
1273
- const resp = yield fetch(`${this.options.baseURL}/version`, { method: "POST" });
1274
- const data = yield resp.json();
1275
- return data;
1276
- });
1277
- }
1278
- }
1279
- class CaptchaApi extends ApiBase {
1280
- /** 验证码 · 获取 */
1281
- captchaGet() {
1282
- return __async(this, null, function* () {
1283
- const data = yield this.POST("/captcha/refresh");
1284
- return data.img_data || "";
1285
- });
1286
- }
1287
- /** 验证码 · 检验 */
1288
- captchaCheck(value) {
1289
- return __async(this, null, function* () {
1290
- const data = yield this.POST("/captcha/check", { value });
1291
- return data.img_data || "";
1292
- });
1293
- }
1294
- /** 验证码 · 状态 */
1295
- captchaStatus() {
1296
- return __async(this, null, function* () {
1297
- const data = yield this.POST("/captcha/status");
1298
- return data || { is_pass: false };
1299
- });
1300
- }
1301
- }
1302
- class AdminApi extends ApiBase {
1303
- /** 缓存清除 */
1304
- cacheFlushAll() {
1305
- const params = { flush_all: true };
1306
- return this.POST("/admin/cache-flush", params);
1307
- }
1308
- /** 缓存预热 */
1309
- cacheWarmUp() {
1310
- const params = {};
1311
- return this.POST("/admin/cache-warm", params);
1312
- }
1313
- }
1314
- class UploadApi extends ApiBase {
1315
- /** 图片上传 */
1316
- imgUpload(file) {
1317
- return __async(this, null, function* () {
1318
- const params = {
1319
- page_key: this.options.pageKey
1320
- };
1321
- this.withUserInfo(params);
1322
- const form = ToFormData(params);
1323
- form.set("file", file);
1324
- const init2 = {
1325
- method: "POST",
1326
- body: form
1327
- };
1328
- const json = yield this.Fetch("/img-upload", init2);
1329
- return json.data || {};
1330
- });
1331
- }
1332
- }
1333
- const ApiComponents = {
1334
- comment: CommentApi,
1335
- page: PageApi,
1336
- site: SiteApi,
1337
- user: UserApi,
1338
- system: SystemApi,
1339
- captcha: CaptchaApi,
1340
- admin: AdminApi,
1341
- upload: UploadApi
1342
- };
1343
- class Api {
1344
- constructor(opts) {
1345
- Object.entries(ApiComponents).forEach(([key, ApiComponent]) => {
1346
- this[key] = new ApiComponent(opts);
1347
- });
1348
- }
1349
- }
1350
- var escapes = {
1351
- "&": "&amp;",
1352
- "<": "&lt;",
1353
- ">": "&gt;",
1354
- '"': "&quot;",
1355
- "'": "&#39;"
1356
- };
1357
- var unescapes = {
1358
- "&amp;": "&",
1359
- "&lt;": "<",
1360
- "&gt;": ">",
1361
- "&quot;": '"',
1362
- "&#39;": "'"
1363
- };
1364
- var rescaped = /(&amp;|&lt;|&gt;|&quot;|&#39;)/g;
1365
- var runescaped = /[&<>"']/g;
1366
- function escapeHtmlChar(match) {
1367
- return escapes[match];
1368
- }
1369
- function unescapeHtmlChar(match) {
1370
- return unescapes[match];
1751
+ function unescapeHtmlChar(match) {
1752
+ return unescapes[match];
1371
1753
  }
1372
1754
  function escapeHtml(text) {
1373
1755
  return text == null ? "" : String(text).replace(runescaped, escapeHtmlChar);
@@ -1475,12 +1857,12 @@ function parser$1(html, handler) {
1475
1857
  }
1476
1858
  }
1477
1859
  function parseComment() {
1478
- var index2 = html.indexOf("-->");
1479
- if (index2 >= 0) {
1860
+ var index = html.indexOf("-->");
1861
+ if (index >= 0) {
1480
1862
  if (handler.comment) {
1481
- handler.comment(html.substring(4, index2));
1863
+ handler.comment(html.substring(4, index));
1482
1864
  }
1483
- html = html.substring(index2 + 3);
1865
+ html = html.substring(index + 3);
1484
1866
  chars = false;
1485
1867
  }
1486
1868
  }
@@ -1489,10 +1871,10 @@ function parser$1(html, handler) {
1489
1871
  return;
1490
1872
  }
1491
1873
  var text;
1492
- var index2 = html.indexOf("<");
1493
- if (index2 >= 0) {
1494
- text = html.substring(0, index2);
1495
- html = html.substring(index2);
1874
+ var index = html.indexOf("<");
1875
+ if (index >= 0) {
1876
+ text = html.substring(0, index);
1877
+ html = html.substring(index);
1496
1878
  } else {
1497
1879
  text = html;
1498
1880
  html = "";
@@ -1843,13 +2225,13 @@ var hanabi$1 = { exports: {} };
1843
2225
  };
1844
2226
  });
1845
2227
  var defaultColors = ["23AC69", "91C132", "F19726", "E8552D", "1AAB8E", "E1147F", "2980C1", "1BA1E6", "9FA0A0", "F19726", "E30B20", "E30B20", "A3338B"];
1846
- var index2 = function(input, ref) {
2228
+ var index = function(input, ref) {
1847
2229
  if (ref === void 0)
1848
2230
  ref = {};
1849
2231
  var colors = ref.colors;
1850
2232
  if (colors === void 0)
1851
2233
  colors = defaultColors;
1852
- var index3 = 0;
2234
+ var index2 = 0;
1853
2235
  var cache = {};
1854
2236
  var wordRe = /[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af\u0400-\u04FF]+|\w+/;
1855
2237
  var leftAngleRe = /</;
@@ -1865,18 +2247,18 @@ var hanabi$1 = { exports: {} };
1865
2247
  if (cache[word]) {
1866
2248
  color = cache[word];
1867
2249
  } else {
1868
- color = colors[index3];
2250
+ color = colors[index2];
1869
2251
  cache[word] = color;
1870
2252
  }
1871
2253
  var out = '<span style="color: #' + color + '">' + word + "</span>";
1872
- index3 = ++index3 % colors.length;
2254
+ index2 = ++index2 % colors.length;
1873
2255
  return out;
1874
2256
  });
1875
2257
  };
1876
2258
  function toComment(cm) {
1877
2259
  return '<span style="color: slategray">' + cm + "</span>";
1878
2260
  }
1879
- return index2;
2261
+ return index;
1880
2262
  });
1881
2263
  })(hanabi$1);
1882
2264
  var hanabiExports = hanabi$1.exports;
@@ -1912,14 +2294,9 @@ const markedCodeRenderer = () => (block, lang) => {
1912
2294
  let instance;
1913
2295
  let replacers = [];
1914
2296
  const markedOptions = {
1915
- pedantic: false,
1916
2297
  gfm: true,
1917
2298
  breaks: true,
1918
- smartLists: true,
1919
- smartypants: true,
1920
- xhtml: false,
1921
- sanitize: false,
1922
- silent: true
2299
+ async: false
1923
2300
  };
1924
2301
  function getInstance() {
1925
2302
  return instance;
@@ -1955,13 +2332,33 @@ function marked(src) {
1955
2332
  function simpleMarked(src) {
1956
2333
  return src.replace(/```\s*([^]+?.*?[^]+?[^]+?)```/g, (_, code) => `<pre><code>${renderCode(code)}</code></pre>`).replace(/!\[(.*?)\]\((.*?)\)/g, (_, alt, imgSrc) => `<img src="${imgSrc}" alt="${alt}" />`).replace(/\[(.*?)\]\((.*?)\)/g, (_, text, link) => `<a href="${link}" target="_blank">${text}</a>`).replace(/\n/g, "<br>");
1957
2334
  }
2335
+ function mergeDeep(...objects) {
2336
+ const isObject = (obj) => obj && typeof obj === "object" && obj.constructor === Object;
2337
+ return objects.reduce((prev, obj) => {
2338
+ Object.keys(obj != null ? obj : {}).forEach((key) => {
2339
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
2340
+ return;
2341
+ }
2342
+ const pVal = prev[key];
2343
+ const oVal = obj[key];
2344
+ if (Array.isArray(pVal) && Array.isArray(oVal)) {
2345
+ prev[key] = pVal.concat(...oVal);
2346
+ } else if (isObject(pVal) && isObject(oVal)) {
2347
+ prev[key] = mergeDeep(pVal, oVal);
2348
+ } else {
2349
+ prev[key] = oVal;
2350
+ }
2351
+ });
2352
+ return prev;
2353
+ }, {});
2354
+ }
1958
2355
  class DataManager {
1959
2356
  constructor(events) {
1960
2357
  __publicField(this, "loading", false);
1961
2358
  __publicField(this, "listLastFetch");
1962
2359
  __publicField(this, "comments", []);
1963
2360
  // Note: 无层级结构 + 无须排列
1964
- __publicField(this, "unreads", []);
2361
+ __publicField(this, "notifies", []);
1965
2362
  __publicField(this, "page");
1966
2363
  this.events = events;
1967
2364
  }
@@ -2021,25 +2418,385 @@ class DataManager {
2021
2418
  this.events.trigger("list-loaded", this.comments);
2022
2419
  }
2023
2420
  // -------------------------------------------------------------------
2024
- // Unreads
2421
+ // Notifies
2422
+ // -------------------------------------------------------------------
2423
+ getNotifies() {
2424
+ return this.notifies;
2425
+ }
2426
+ updateNotifies(notifies) {
2427
+ this.notifies = notifies;
2428
+ this.events.trigger("notifies-updated", this.notifies);
2429
+ }
2430
+ // -------------------------------------------------------------------
2431
+ // Page
2025
2432
  // -------------------------------------------------------------------
2026
- getUnreads() {
2027
- return this.unreads;
2433
+ getPage() {
2434
+ return this.page;
2435
+ }
2436
+ updatePage(pageData) {
2437
+ this.page = pageData;
2438
+ this.events.trigger("page-loaded", pageData);
2439
+ }
2440
+ }
2441
+ const en = {
2442
+ /* Editor */
2443
+ placeholder: "Leave a comment",
2444
+ noComment: "No Comment",
2445
+ send: "Send",
2446
+ save: "Save",
2447
+ nick: "Nickname",
2448
+ email: "Email",
2449
+ link: "Website",
2450
+ emoticon: "Emoji",
2451
+ preview: "Preview",
2452
+ image: "Image",
2453
+ uploadFail: "Upload Failed",
2454
+ commentFail: "Failed to comment",
2455
+ restoredMsg: "Content has been restored",
2456
+ onlyAdminCanReply: "Only admin can reply",
2457
+ uploadLoginMsg: "Please fill in your name and email to upload",
2458
+ /* List */
2459
+ counter: "{count} Comments",
2460
+ sortLatest: "Latest",
2461
+ sortOldest: "Oldest",
2462
+ sortBest: "Best",
2463
+ sortAuthor: "Author",
2464
+ openComment: "Open Comment",
2465
+ closeComment: "Close Comment",
2466
+ listLoadFailMsg: "Failed to load comments",
2467
+ listRetry: "Retry",
2468
+ loadMore: "Load More",
2469
+ /* Comment */
2470
+ admin: "Admin",
2471
+ reply: "Reply",
2472
+ voteUp: "Up",
2473
+ voteDown: "Down",
2474
+ voteFail: "Vote Failed",
2475
+ readMore: "Read More",
2476
+ actionConfirm: "Confirm",
2477
+ collapse: "Collapse",
2478
+ collapsed: "Collapsed",
2479
+ collapsedMsg: "This comment has been collapsed",
2480
+ expand: "Expand",
2481
+ approved: "Approved",
2482
+ pending: "Pending",
2483
+ pendingMsg: "Pending, visible only to commenter.",
2484
+ edit: "Edit",
2485
+ editCancel: "Cancel Edit",
2486
+ delete: "Delete",
2487
+ deleteConfirm: "Confirm",
2488
+ pin: "Pin",
2489
+ unpin: "Unpin",
2490
+ /* Time */
2491
+ seconds: "seconds ago",
2492
+ minutes: "minutes ago",
2493
+ hours: "hours ago",
2494
+ days: "days ago",
2495
+ now: "just now",
2496
+ /* Checker */
2497
+ adminCheck: "Enter admin password:",
2498
+ captchaCheck: "Enter the CAPTCHA to continue:",
2499
+ confirm: "Confirm",
2500
+ cancel: "Cancel",
2501
+ /* Sidebar */
2502
+ msgCenter: "Messages",
2503
+ ctrlCenter: "Admin",
2504
+ /* General */
2505
+ frontend: "Frontend",
2506
+ backend: "Backend",
2507
+ loading: "Loading",
2508
+ loadFail: "Load Failed",
2509
+ editing: "Editing",
2510
+ editFail: "Edit Failed",
2511
+ deleting: "Deleting",
2512
+ deleteFail: "Delete Failed",
2513
+ reqGot: "Request got",
2514
+ reqAborted: "Request timed out or terminated unexpectedly",
2515
+ updateMsg: "Please update Artalk {name} to get the full experience",
2516
+ currentVersion: "Current Version",
2517
+ ignore: "Ignore",
2518
+ open: "Open",
2519
+ openName: "Open {name}"
2520
+ };
2521
+ const zhCN = {
2522
+ /* Editor */
2523
+ placeholder: "键入内容...",
2524
+ noComment: "「此时无声胜有声」",
2525
+ send: "发送评论",
2526
+ save: "保存评论",
2527
+ nick: "昵称",
2528
+ email: "邮箱",
2529
+ link: "网址",
2530
+ emoticon: "表情",
2531
+ preview: "预览",
2532
+ image: "图片",
2533
+ uploadFail: "上传失败",
2534
+ commentFail: "评论失败",
2535
+ restoredMsg: "内容已自动恢复",
2536
+ onlyAdminCanReply: "仅管理员可评论",
2537
+ uploadLoginMsg: "填入你的名字邮箱才能上传哦",
2538
+ /* List */
2539
+ counter: "{count} 条评论",
2540
+ sortLatest: "最新",
2541
+ sortOldest: "最早",
2542
+ sortBest: "最热",
2543
+ sortAuthor: "作者",
2544
+ openComment: "打开评论",
2545
+ closeComment: "关闭评论",
2546
+ listLoadFailMsg: "无法获取评论列表数据",
2547
+ listRetry: "点击重新获取",
2548
+ loadMore: "加载更多",
2549
+ /* Comment */
2550
+ admin: "管理员",
2551
+ reply: "回复",
2552
+ voteUp: "赞同",
2553
+ voteDown: "反对",
2554
+ voteFail: "投票失败",
2555
+ readMore: "阅读更多",
2556
+ actionConfirm: "确认操作",
2557
+ collapse: "折叠",
2558
+ collapsed: "已折叠",
2559
+ collapsedMsg: "该评论已被系统或管理员折叠",
2560
+ expand: "展开",
2561
+ approved: "已审",
2562
+ pending: "待审",
2563
+ pendingMsg: "审核中,仅本人可见。",
2564
+ edit: "编辑",
2565
+ editCancel: "取消编辑",
2566
+ delete: "删除",
2567
+ deleteConfirm: "确认删除",
2568
+ pin: "置顶",
2569
+ unpin: "取消置顶",
2570
+ /* Time */
2571
+ seconds: "秒前",
2572
+ minutes: "分钟前",
2573
+ hours: "小时前",
2574
+ days: "天前",
2575
+ now: "刚刚",
2576
+ /* Checker */
2577
+ adminCheck: "键入密码来验证管理员身份:",
2578
+ captchaCheck: "键入验证码继续:",
2579
+ confirm: "确认",
2580
+ cancel: "取消",
2581
+ /* Sidebar */
2582
+ msgCenter: "通知中心",
2583
+ ctrlCenter: "控制中心",
2584
+ /* General */
2585
+ frontend: "前端",
2586
+ backend: "后端",
2587
+ loading: "加载中",
2588
+ loadFail: "加载失败",
2589
+ editing: "修改中",
2590
+ editFail: "修改失败",
2591
+ deleting: "删除中",
2592
+ deleteFail: "删除失败",
2593
+ reqGot: "请求响应",
2594
+ reqAborted: "请求超时或意外终止",
2595
+ updateMsg: "请更新 Artalk {name} 以获得完整体验",
2596
+ currentVersion: "当前版本",
2597
+ ignore: "忽略",
2598
+ open: "打开",
2599
+ openName: "打开{name}"
2600
+ };
2601
+ const GLOBAL_LOCALES_KEY = "ArtalkI18n";
2602
+ function createElement(htmlStr = "") {
2603
+ const div = document.createElement("div");
2604
+ div.innerHTML = htmlStr.trim();
2605
+ return div.firstElementChild || div;
2606
+ }
2607
+ function getHeight(el) {
2608
+ return parseFloat(getComputedStyle(el, null).height.replace("px", ""));
2609
+ }
2610
+ function htmlEncode(str) {
2611
+ const temp = document.createElement("div");
2612
+ temp.innerText = str;
2613
+ const output = temp.innerHTML;
2614
+ return output;
2615
+ }
2616
+ function getQueryParam(name) {
2617
+ const match = RegExp(`[?&]${name}=([^&]*)`).exec(window.location.search);
2618
+ return match && decodeURIComponent(match[1].replace(/\+/g, " "));
2619
+ }
2620
+ function getOffset(el, relativeTo) {
2621
+ const getOffsetRecursive = (element) => {
2622
+ const rect = element.getBoundingClientRect();
2623
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
2624
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
2625
+ return {
2626
+ top: rect.top + scrollTop,
2627
+ left: rect.left + scrollLeft
2628
+ };
2629
+ };
2630
+ const elOffset = getOffsetRecursive(el);
2631
+ if (!relativeTo)
2632
+ return elOffset;
2633
+ const relativeToOffset = getOffsetRecursive(relativeTo);
2634
+ return {
2635
+ top: elOffset.top - relativeToOffset.top,
2636
+ left: elOffset.left - relativeToOffset.left
2637
+ };
2638
+ }
2639
+ function padWithZeros(vNumber, width) {
2640
+ let numAsString = vNumber.toString();
2641
+ while (numAsString.length < width) {
2642
+ numAsString = `0${numAsString}`;
2643
+ }
2644
+ return numAsString;
2645
+ }
2646
+ function dateFormat(date) {
2647
+ const vDay = padWithZeros(date.getDate(), 2);
2648
+ const vMonth = padWithZeros(date.getMonth() + 1, 2);
2649
+ const vYear = padWithZeros(date.getFullYear(), 2);
2650
+ return `${vYear}-${vMonth}-${vDay}`;
2651
+ }
2652
+ function timeAgo(date, $t = (n) => n) {
2653
+ try {
2654
+ const oldTime = date.getTime();
2655
+ const currTime = (/* @__PURE__ */ new Date()).getTime();
2656
+ const diffValue = currTime - oldTime;
2657
+ const days = Math.floor(diffValue / (24 * 3600 * 1e3));
2658
+ if (days === 0) {
2659
+ const leave1 = diffValue % (24 * 3600 * 1e3);
2660
+ const hours = Math.floor(leave1 / (3600 * 1e3));
2661
+ if (hours === 0) {
2662
+ const leave2 = leave1 % (3600 * 1e3);
2663
+ const minutes = Math.floor(leave2 / (60 * 1e3));
2664
+ if (minutes === 0) {
2665
+ const leave3 = leave2 % (60 * 1e3);
2666
+ const seconds = Math.round(leave3 / 1e3);
2667
+ if (seconds < 10)
2668
+ return $t("now");
2669
+ return `${seconds} ${$t("seconds")}`;
2670
+ }
2671
+ return `${minutes} ${$t("minutes")}`;
2672
+ }
2673
+ return `${hours} ${$t("hours")}`;
2674
+ }
2675
+ if (days < 0)
2676
+ return $t("now");
2677
+ if (days < 8) {
2678
+ return `${days} ${$t("days")}`;
2679
+ }
2680
+ return dateFormat(date);
2681
+ } catch (error) {
2682
+ console.error(error);
2683
+ return " - ";
2684
+ }
2685
+ }
2686
+ function onImagesLoaded($container, event) {
2687
+ if (!$container)
2688
+ return;
2689
+ const images = $container.getElementsByTagName("img");
2690
+ if (!images.length)
2691
+ return;
2692
+ let loaded = images.length;
2693
+ for (let i = 0; i < images.length; i++) {
2694
+ if (images[i].complete) {
2695
+ loaded--;
2696
+ } else {
2697
+ images[i].addEventListener("load", () => {
2698
+ loaded--;
2699
+ if (loaded === 0)
2700
+ event();
2701
+ });
2702
+ }
2703
+ if (loaded === 0)
2704
+ event();
2705
+ }
2706
+ }
2707
+ function getGravatarURL(opts) {
2708
+ return `${opts.mirror.replace(/\/$/, "")}/${opts.emailMD5}?${opts.params.replace(/^\?/, "")}`;
2709
+ }
2710
+ function versionCompare(a, b) {
2711
+ const pa = a.split(".");
2712
+ const pb = b.split(".");
2713
+ for (let i = 0; i < 3; i++) {
2714
+ const na = Number(pa[i]);
2715
+ const nb = Number(pb[i]);
2716
+ if (na > nb)
2717
+ return 1;
2718
+ if (nb > na)
2719
+ return -1;
2720
+ if (!Number.isNaN(na) && Number.isNaN(nb))
2721
+ return 1;
2722
+ if (Number.isNaN(na) && !Number.isNaN(nb))
2723
+ return -1;
2028
2724
  }
2029
- updateUnreads(unread) {
2030
- this.unreads = unread;
2031
- this.events.trigger("unreads-updated", this.unreads);
2725
+ return 0;
2726
+ }
2727
+ function getCorrectUserAgent() {
2728
+ return __async(this, null, function* () {
2729
+ const uaRaw = navigator.userAgent;
2730
+ if (!navigator.userAgentData || !navigator.userAgentData.getHighEntropyValues) {
2731
+ return uaRaw;
2732
+ }
2733
+ const uaData = navigator.userAgentData;
2734
+ let uaGot = null;
2735
+ try {
2736
+ uaGot = yield uaData.getHighEntropyValues(["platformVersion"]);
2737
+ } catch (err) {
2738
+ console.error(err);
2739
+ return uaRaw;
2740
+ }
2741
+ const majorPlatformVersion = Number(uaGot.platformVersion.split(".")[0]);
2742
+ if (uaData.platform === "Windows") {
2743
+ if (majorPlatformVersion >= 13) {
2744
+ return uaRaw.replace(/Windows NT 10.0/, "Windows NT 11.0");
2745
+ }
2746
+ }
2747
+ if (uaData.platform === "macOS") {
2748
+ if (majorPlatformVersion >= 11) {
2749
+ return uaRaw.replace(/(Mac OS X \d+_\d+_\d+|Mac OS X)/, `Mac OS X ${uaGot.platformVersion.replace(/\./g, "_")}`);
2750
+ }
2751
+ }
2752
+ return uaRaw;
2753
+ });
2754
+ }
2755
+ function isValidURL(urlRaw) {
2756
+ let url;
2757
+ try {
2758
+ url = new URL(urlRaw);
2759
+ } catch (_) {
2760
+ return false;
2032
2761
  }
2033
- // -------------------------------------------------------------------
2034
- // Page
2035
- // -------------------------------------------------------------------
2036
- getPage() {
2037
- return this.page;
2762
+ return url.protocol === "http:" || url.protocol === "https:";
2763
+ }
2764
+ function getURLBasedOnApi(opts) {
2765
+ return getURLBasedOn(opts.base, opts.path);
2766
+ }
2767
+ function getURLBasedOn(baseURL, path) {
2768
+ return `${baseURL.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
2769
+ }
2770
+ const internal = {
2771
+ "en": en,
2772
+ "en-US": en,
2773
+ "zh-CN": zhCN
2774
+ };
2775
+ function findLocaleSet(lang) {
2776
+ lang = lang.replace(
2777
+ /^([a-zA-Z]+)(-[a-zA-Z]+)?$/,
2778
+ (_, p1, p2) => p1.toLowerCase() + (p2 || "").toUpperCase()
2779
+ );
2780
+ if (internal[lang]) {
2781
+ return internal[lang];
2038
2782
  }
2039
- updatePage(pageData) {
2040
- this.page = pageData;
2041
- this.events.trigger("page-loaded", pageData);
2783
+ if (window[GLOBAL_LOCALES_KEY] && window[GLOBAL_LOCALES_KEY][lang]) {
2784
+ return window[GLOBAL_LOCALES_KEY][lang];
2042
2785
  }
2786
+ return internal.en;
2787
+ }
2788
+ let LocaleConf = "en";
2789
+ let LocaleDict = findLocaleSet(LocaleConf);
2790
+ function setLocale(locale) {
2791
+ if (locale === LocaleConf)
2792
+ return;
2793
+ LocaleConf = locale;
2794
+ LocaleDict = typeof locale === "string" ? findLocaleSet(locale) : locale;
2795
+ }
2796
+ function t(key, args = {}) {
2797
+ let str = (LocaleDict == null ? void 0 : LocaleDict[key]) || key;
2798
+ str = str.replace(/\{\s*(\w+?)\s*\}/g, (_, token) => args[token] || "");
2799
+ return htmlEncode(str);
2043
2800
  }
2044
2801
  class EventManager {
2045
2802
  constructor() {
@@ -2110,18 +2867,11 @@ const defaults = {
2110
2867
  reqTimeout: 15e3,
2111
2868
  versionCheck: true,
2112
2869
  useBackendConf: true,
2113
- locale: "zh-CN"
2870
+ locale: "en"
2114
2871
  };
2115
- {
2116
- defaults.vote = false;
2117
- defaults.uaBadge = false;
2118
- defaults.emoticons = false;
2119
- }
2120
- function handelCustomConf(customConf) {
2121
- const conf = mergeDeep(defaults, customConf);
2122
- if (customConf.el)
2123
- conf.el = customConf.el;
2124
- if (typeof conf.el === "string" && !!conf.el) {
2872
+ function handelCustomConf(customConf, full = false) {
2873
+ const conf = full ? mergeDeep(defaults, customConf) : customConf;
2874
+ if (conf.el && typeof conf.el === "string") {
2125
2875
  try {
2126
2876
  const findEl = document.querySelector(conf.el);
2127
2877
  if (!findEl)
@@ -2132,20 +2882,18 @@ function handelCustomConf(customConf) {
2132
2882
  throw new Error("Please check your Artalk `el` config.");
2133
2883
  }
2134
2884
  }
2135
- conf.server = conf.server.replace(/\/$/, "").replace(/\/api\/?$/, "");
2136
- if (!conf.pageKey) {
2885
+ if (conf.pageKey === "")
2137
2886
  conf.pageKey = `${window.location.pathname}`;
2138
- }
2139
- if (!conf.pageTitle) {
2887
+ if (conf.pageTitle === "")
2140
2888
  conf.pageTitle = `${document.title}`;
2141
- }
2142
- if (conf.locale === "auto") {
2889
+ if (conf.server)
2890
+ conf.server = conf.server.replace(/\/$/, "").replace(/\/api\/?$/, "");
2891
+ if (conf.locale === "auto")
2143
2892
  conf.locale = navigator.language;
2144
- }
2145
- if (conf.flatMode === true || Number(conf.nestMax) <= 1)
2146
- conf.flatMode = true;
2147
2893
  if (conf.flatMode === "auto")
2148
2894
  conf.flatMode = window.matchMedia("(max-width: 768px)").matches;
2895
+ if (typeof conf.nestMax === "number" && Number(conf.nestMax) <= 1)
2896
+ conf.flatMode = true;
2149
2897
  return conf;
2150
2898
  }
2151
2899
  function handleConfFormServer(conf) {
@@ -2173,53 +2921,72 @@ function handleConfFormServer(conf) {
2173
2921
  }
2174
2922
  function convertApiOptions(conf, ctx) {
2175
2923
  return {
2176
- baseURL: `${conf.server}/api`,
2924
+ baseURL: `${conf.server}/api/v2`,
2177
2925
  siteName: conf.site || "",
2178
2926
  pageKey: conf.pageKey || "",
2179
2927
  pageTitle: conf.pageTitle || "",
2180
2928
  timeout: conf.reqTimeout,
2181
- apiToken: ctx == null ? void 0 : ctx.get("user").getData().token,
2929
+ getApiToken: () => ctx == null ? void 0 : ctx.get("user").getData().token,
2182
2930
  userInfo: (ctx == null ? void 0 : ctx.get("user").checkHasBasicUserInfo()) ? {
2183
2931
  name: ctx == null ? void 0 : ctx.get("user").getData().nick,
2184
2932
  email: ctx == null ? void 0 : ctx.get("user").getData().email
2185
2933
  } : void 0,
2186
- onNeedCheckAdmin(payload) {
2187
- ctx == null ? void 0 : ctx.checkAdmin({
2188
- onSuccess: () => {
2189
- payload.recall();
2190
- },
2191
- onCancel: () => {
2192
- payload.reject();
2193
- }
2194
- });
2934
+ onNeedCheckAdmin: (payload) => {
2935
+ if (!ctx)
2936
+ throw new Error("`ctx` is required when `onNeedCheckAdmin` is called.");
2937
+ return ctx.checkAdmin({});
2195
2938
  },
2196
- onNeedCheckCaptcha(payload) {
2197
- ctx == null ? void 0 : ctx.checkCaptcha({
2939
+ onNeedCheckCaptcha: (payload) => {
2940
+ if (!ctx)
2941
+ throw new Error("`ctx` is required when `onNeedCheckCaptcha` is called.");
2942
+ return ctx.checkCaptcha({
2198
2943
  imgData: payload.data.imgData,
2199
- iframe: payload.data.iframe,
2200
- onSuccess: () => {
2201
- payload.recall();
2202
- },
2203
- onCancel: () => {
2204
- payload.reject();
2205
- }
2944
+ iframe: payload.data.iframe
2206
2945
  });
2207
2946
  }
2208
2947
  };
2209
2948
  }
2949
+ function watchConf(ctx, keys, effect) {
2950
+ const deepEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
2951
+ const val = () => {
2952
+ const conf = ctx.getConf();
2953
+ const res = {};
2954
+ keys.forEach((key) => {
2955
+ res[key] = conf[key];
2956
+ });
2957
+ return res;
2958
+ };
2959
+ let lastVal = null;
2960
+ const handler = () => {
2961
+ const newVal = val();
2962
+ const isDiff = lastVal == null || !deepEqual(lastVal, newVal);
2963
+ if (isDiff) {
2964
+ lastVal = newVal;
2965
+ effect(newVal);
2966
+ }
2967
+ };
2968
+ ctx.on("mounted", handler);
2969
+ ctx.on("updated", handler);
2970
+ }
2210
2971
  class Context {
2211
- constructor(conf, $root) {
2972
+ constructor(conf) {
2212
2973
  /* 运行参数 */
2213
2974
  __publicField(this, "conf");
2214
2975
  __publicField(this, "data");
2215
2976
  __publicField(this, "$root");
2216
2977
  /* Event Manager */
2217
2978
  __publicField(this, "events", new EventManager());
2979
+ __publicField(this, "mounted", false);
2980
+ __publicField(this, "getCommentList", this.getCommentNodes);
2981
+ __publicField(this, "getCommentDataList", this.getComments);
2218
2982
  this.conf = conf;
2219
- this.$root = $root || document.createElement("div");
2983
+ this.$root = conf.el;
2220
2984
  this.$root.classList.add("artalk");
2221
2985
  this.$root.innerHTML = "";
2222
2986
  this.data = new DataManager(this.events);
2987
+ this.on("mounted", () => {
2988
+ this.mounted = true;
2989
+ });
2223
2990
  }
2224
2991
  inject(depName, obj) {
2225
2992
  this[depName] = obj;
@@ -2228,7 +2995,7 @@ class Context {
2228
2995
  return this[depName];
2229
2996
  }
2230
2997
  getApi() {
2231
- return new Api(convertApiOptions(this.conf, this));
2998
+ return new Api2(convertApiOptions(this.conf, this));
2232
2999
  }
2233
3000
  getData() {
2234
3001
  return this.data;
@@ -2245,10 +3012,17 @@ class Context {
2245
3012
  reload() {
2246
3013
  this.data.fetchComments({ offset: 0 });
2247
3014
  }
3015
+ /* List */
2248
3016
  listGotoFirst() {
2249
3017
  this.events.trigger("list-goto-first");
2250
3018
  }
2251
- /* 编辑器 */
3019
+ getCommentNodes() {
3020
+ return this.list.getCommentNodes();
3021
+ }
3022
+ getComments() {
3023
+ return this.data.getComments();
3024
+ }
3025
+ /* Editor */
2252
3026
  editorShowLoading() {
2253
3027
  this.editor.showLoading();
2254
3028
  }
@@ -2261,19 +3035,19 @@ class Context {
2261
3035
  editorResetState() {
2262
3036
  this.editor.resetState();
2263
3037
  }
2264
- /* 侧边栏 */
3038
+ /* Sidebar */
2265
3039
  showSidebar(payload) {
2266
3040
  this.sidebarLayer.show(payload);
2267
3041
  }
2268
3042
  hideSidebar() {
2269
3043
  this.sidebarLayer.hide();
2270
3044
  }
2271
- /* 权限检测 */
3045
+ /* Checker */
2272
3046
  checkAdmin(payload) {
2273
- this.checkerLauncher.checkAdmin(payload);
3047
+ return this.checkerLauncher.checkAdmin(payload);
2274
3048
  }
2275
3049
  checkCaptcha(payload) {
2276
- this.checkerLauncher.checkCaptcha(payload);
3050
+ return this.checkerLauncher.checkCaptcha(payload);
2277
3051
  }
2278
3052
  /* Events */
2279
3053
  on(name, handler) {
@@ -2290,16 +3064,24 @@ class Context {
2290
3064
  return t(key, args);
2291
3065
  }
2292
3066
  setDarkMode(darkMode) {
2293
- this.conf.darkMode = darkMode;
2294
- this.events.trigger("dark-mode-changed", darkMode);
3067
+ this.updateConf({ darkMode });
2295
3068
  }
2296
3069
  updateConf(nConf) {
2297
- this.conf = mergeDeep(this.conf, handelCustomConf(nConf));
2298
- this.events.trigger("conf-loaded", this.conf);
3070
+ this.conf = mergeDeep(this.conf, handelCustomConf(nConf, false));
3071
+ this.mounted && this.events.trigger("updated", this.conf);
3072
+ }
3073
+ getConf() {
3074
+ return this.conf;
3075
+ }
3076
+ getEl() {
3077
+ return this.$root;
2299
3078
  }
2300
3079
  getMarked() {
2301
3080
  return getInstance();
2302
3081
  }
3082
+ watchConf(keys, effect) {
3083
+ watchConf(this, keys, effect);
3084
+ }
2303
3085
  }
2304
3086
  class Dialog {
2305
3087
  constructor(contentEl) {
@@ -2492,8 +3274,8 @@ function imgBody(checker) {
2492
3274
  );
2493
3275
  elem.querySelector(".atk-captcha-img").onclick = () => {
2494
3276
  const imgEl = elem.querySelector(".atk-captcha-img");
2495
- checker.getApi().captcha.captchaGet().then((imgData) => {
2496
- imgEl.setAttribute("src", imgData);
3277
+ checker.getApi().captcha.getCaptcha().then((res) => {
3278
+ imgEl.setAttribute("src", res.data.img_data);
2497
3279
  }).catch((err) => {
2498
3280
  console.error("Failed to get captcha image ", err);
2499
3281
  });
@@ -2505,7 +3287,7 @@ function iframeBody(checker) {
2505
3287
  const $iframe = createElement(`<iframe class="atk-fade-in" referrerpolicy="strict-origin-when-cross-origin"></iframe>`);
2506
3288
  $iframe.style.display = "none";
2507
3289
  showLoading($iframeWrap, { transparentBg: true });
2508
- $iframe.src = `${checker.getOpts().getIframeURLBase() || ""}/api/captcha/get?t=${+/* @__PURE__ */ new Date()}`;
3290
+ $iframe.src = checker.getOpts().getCaptchaIframeURL();
2509
3291
  $iframe.onload = () => {
2510
3292
  $iframe.style.display = "";
2511
3293
  hideLoading($iframeWrap);
@@ -2527,8 +3309,8 @@ function iframeBody(checker) {
2527
3309
  return;
2528
3310
  let isPass = false;
2529
3311
  try {
2530
- const resp = yield checker.getApi().captcha.captchaStatus();
2531
- isPass = resp.is_pass;
3312
+ const resp = yield checker.getApi().captcha.getCaptchaStatus();
3313
+ isPass = resp.data.is_pass;
2532
3314
  } catch (e) {
2533
3315
  isPass = false;
2534
3316
  }
@@ -2547,7 +3329,9 @@ function iframeBody(checker) {
2547
3329
  }
2548
3330
  const CaptchaChecker = {
2549
3331
  request(checker, inputVal) {
2550
- return checker.getApi().captcha.captchaCheck(inputVal);
3332
+ return checker.getApi().captcha.verifyCaptcha({
3333
+ value: inputVal
3334
+ });
2551
3335
  },
2552
3336
  body(checker) {
2553
3337
  if (checker.get("iframe"))
@@ -2565,45 +3349,61 @@ const CaptchaChecker = {
2565
3349
  const AdminChecker = {
2566
3350
  inputType: "password",
2567
3351
  request(checker, inputVal) {
2568
- const data = {
2569
- name: checker.getUser().getData().nick,
2570
- email: checker.getUser().getData().email,
2571
- password: inputVal
2572
- };
2573
- return (() => __async(this, null, function* () {
2574
- const resp = yield checker.getApi().user.login(data.name, data.email, data.password);
2575
- return resp.token;
2576
- }))();
3352
+ return __async(this, null, function* () {
3353
+ return (yield checker.getApi().user.login({
3354
+ name: checker.getUser().getData().nick,
3355
+ email: checker.getUser().getData().email,
3356
+ password: inputVal
3357
+ })).data;
3358
+ });
2577
3359
  },
2578
3360
  body(checker) {
2579
3361
  return createElement(`<span>${t("adminCheck")}</span>`);
2580
3362
  },
2581
- onSuccess(checker, userToken, inputVal, formEl) {
3363
+ onSuccess(checker, res, inputVal, formEl) {
2582
3364
  checker.getUser().update({
2583
3365
  isAdmin: true,
2584
- token: userToken
3366
+ token: res.token
2585
3367
  });
2586
3368
  checker.getOpts().onReload();
2587
3369
  },
2588
3370
  onError(checker, err, inputVal, formEl) {
2589
3371
  }
2590
3372
  };
3373
+ function wrapPromise(fn) {
3374
+ return (payload) => new Promise((resolve, reject) => {
3375
+ const cancelFn = payload.onCancel;
3376
+ payload.onCancel = () => {
3377
+ cancelFn && cancelFn();
3378
+ reject(new Error("user canceled the checker"));
3379
+ };
3380
+ const successFn = payload.onSuccess;
3381
+ payload.onSuccess = () => {
3382
+ successFn && successFn();
3383
+ resolve();
3384
+ };
3385
+ fn(payload);
3386
+ });
3387
+ }
2591
3388
  class CheckerLauncher {
2592
3389
  constructor(opts) {
3390
+ __publicField(this, "checkCaptcha", wrapPromise((p) => {
3391
+ this.fire(CaptchaChecker, p, (ctx) => {
3392
+ ctx.set("img_data", p.imgData);
3393
+ ctx.set("iframe", p.iframe);
3394
+ });
3395
+ }));
3396
+ __publicField(this, "checkAdmin", wrapPromise((p) => {
3397
+ this.fire(AdminChecker, p);
3398
+ }));
2593
3399
  this.opts = opts;
2594
3400
  }
2595
- checkCaptcha(payload) {
2596
- this.fire(CaptchaChecker, payload, (ctx) => {
2597
- ctx.set("img_data", payload.imgData);
2598
- ctx.set("iframe", payload.iframe);
2599
- });
2600
- }
2601
- checkAdmin(payload) {
2602
- this.fire(AdminChecker, payload);
2603
- }
2604
3401
  fire(checker, payload, postFire) {
2605
3402
  const layer = this.opts.getCtx().get("layerManager").create(`checker-${(/* @__PURE__ */ new Date()).getTime()}`);
2606
3403
  layer.show();
3404
+ const close = () => {
3405
+ layer.destroy();
3406
+ };
2607
3407
  const checkerStore = {};
2608
3408
  let hideInteractInput = false;
2609
3409
  const checkerCtx = {
@@ -2618,14 +3418,14 @@ class CheckerLauncher {
2618
3418
  hideInteractInput = true;
2619
3419
  },
2620
3420
  triggerSuccess: () => {
2621
- this.close(checker, layer);
3421
+ close();
2622
3422
  if (checker.onSuccess)
2623
3423
  checker.onSuccess(checkerCtx, "", "", formEl);
2624
3424
  if (payload.onSuccess)
2625
- payload.onSuccess("", dialog.$el);
3425
+ payload.onSuccess();
2626
3426
  },
2627
3427
  cancel: () => {
2628
- this.close(checker, layer);
3428
+ close();
2629
3429
  if (payload.onCancel)
2630
3430
  payload.onCancel();
2631
3431
  }
@@ -2661,11 +3461,11 @@ class CheckerLauncher {
2661
3461
  };
2662
3462
  btnEl.innerText = `${t("loading")}...`;
2663
3463
  checker.request(checkerCtx, inputVal).then((data) => {
2664
- this.close(checker, layer);
3464
+ close();
2665
3465
  if (checker.onSuccess)
2666
3466
  checker.onSuccess(checkerCtx, data, inputVal, formEl);
2667
3467
  if (payload.onSuccess)
2668
- payload.onSuccess(inputVal, dialog.$el);
3468
+ payload.onSuccess();
2669
3469
  }).catch((err) => {
2670
3470
  btnTextSet(String(err.msg || String(err)));
2671
3471
  if (checker.onError)
@@ -2679,7 +3479,7 @@ class CheckerLauncher {
2679
3479
  return false;
2680
3480
  });
2681
3481
  dialog.setNo(() => {
2682
- this.close(checker, layer);
3482
+ close();
2683
3483
  if (payload.onCancel)
2684
3484
  payload.onCancel();
2685
3485
  return false;
@@ -2692,17 +3492,14 @@ class CheckerLauncher {
2692
3492
  if (payload.onMount)
2693
3493
  payload.onMount(dialog.$el);
2694
3494
  }
2695
- // 关闭 checker 对话框
2696
- close(checker, layer) {
2697
- layer.destroy();
2698
- }
2699
3495
  }
2700
3496
  class Component {
2701
3497
  constructor(ctx) {
2702
3498
  __publicField(this, "$el");
2703
- __publicField(this, "conf");
2704
3499
  this.ctx = ctx;
2705
- this.conf = ctx.conf;
3500
+ }
3501
+ get conf() {
3502
+ return this.ctx.conf;
2706
3503
  }
2707
3504
  }
2708
3505
  const EditorHTML = '<div class="atk-main-editor">\n <div class="atk-header">\n <input name="nick" class="atk-nick" type="text" required="required">\n <input name="email" class="atk-email" type="email" required="required">\n <input name="link" class="atk-link" type="url">\n </div>\n <div class="atk-textarea-wrap">\n <textarea class="atk-textarea"></textarea>\n </div>\n <div class="atk-plug-panel-wrap" style="display: none;"></div>\n <div class="atk-bottom">\n <div class="atk-item atk-plug-btn-wrap"></div>\n <div class="atk-item">\n <button type="button" class="atk-send-btn"></button>\n </div>\n </div>\n <div class="atk-notify-wrap"></div>\n</div>\n';
@@ -2925,7 +3722,10 @@ class SidebarLayer extends Component {
2925
3722
  __publicField(this, "$closeBtn");
2926
3723
  __publicField(this, "$iframeWrap");
2927
3724
  __publicField(this, "$iframe");
2928
- __publicField(this, "firstShow", true);
3725
+ /** Refresh iFrame on show */
3726
+ __publicField(this, "refreshOnShow", true);
3727
+ /** Animation timer */
3728
+ __publicField(this, "animTimer");
2929
3729
  this.$el = createElement(SidebarHTML);
2930
3730
  this.$header = this.$el.querySelector(".atk-sidebar-header");
2931
3731
  this.$closeBtn = this.$header.querySelector(".atk-sidebar-close");
@@ -2934,7 +3734,7 @@ class SidebarLayer extends Component {
2934
3734
  this.hide();
2935
3735
  };
2936
3736
  this.ctx.on("user-changed", () => {
2937
- this.firstShow = true;
3737
+ this.refreshOnShow = true;
2938
3738
  });
2939
3739
  }
2940
3740
  /** 显示 */
@@ -2943,45 +3743,43 @@ class SidebarLayer extends Component {
2943
3743
  this.$el.style.transform = "";
2944
3744
  this.initLayer();
2945
3745
  this.layer.show();
2946
- this.authCheck({
2947
- onSuccess: () => this.show(conf)
2948
- // retry show after auth check
2949
- });
2950
- if (this.firstShow) {
3746
+ if (this.refreshOnShow) {
3747
+ this.refreshOnShow = false;
2951
3748
  this.$iframeWrap.innerHTML = "";
2952
3749
  this.$iframe = this.createIframe(conf.view);
2953
3750
  this.$iframeWrap.append(this.$iframe);
2954
- this.firstShow = false;
2955
3751
  } else {
2956
3752
  const $iframe = this.$iframe;
2957
- const isIframeSrcDarkMode = $iframe.src.includes("darkMode=1");
2958
- if (this.conf.darkMode && !isIframeSrcDarkMode)
2959
- this.iframeLoad($iframe, `${this.$iframe.src}&darkMode=1`);
2960
- if (!this.conf.darkMode && isIframeSrcDarkMode)
2961
- this.iframeLoad($iframe, this.$iframe.src.replace("&darkMode=1", ""));
3753
+ const iFrameSrc = $iframe.src;
3754
+ if (this.conf.darkMode !== iFrameSrc.includes("darkMode=1")) {
3755
+ this.iframeLoad($iframe, this.conf.darkMode ? iFrameSrc.concat("&darkMode=1") : iFrameSrc.replace("&darkMode=1", ""));
3756
+ }
2962
3757
  }
2963
- setTimeout(() => {
3758
+ this.authCheck({
3759
+ onSuccess: () => this.show(conf)
3760
+ // retry show after auth check
3761
+ });
3762
+ this.animTimer = setTimeout(() => {
3763
+ this.animTimer = void 0;
2964
3764
  this.$el.style.transform = "translate(0, 0)";
3765
+ setTimeout(() => {
3766
+ this.ctx.getData().updateNotifies([]);
3767
+ }, 0);
3768
+ this.ctx.trigger("sidebar-show");
2965
3769
  }, 100);
2966
- setTimeout(() => {
2967
- this.ctx.getData().updateUnreads([]);
2968
- }, 0);
2969
- this.ctx.trigger("sidebar-show");
2970
3770
  });
2971
3771
  }
2972
3772
  /** 隐藏 */
2973
3773
  hide() {
2974
3774
  var _a;
2975
- this.$el.style.transform = "";
2976
3775
  (_a = this.layer) == null ? void 0 : _a.hide();
2977
- this.ctx.trigger("sidebar-hide");
2978
3776
  }
2979
3777
  // --------------------------------------------------
2980
3778
  authCheck(opts) {
2981
3779
  return __async(this, null, function* () {
2982
- const resp = yield this.ctx.getApi().user.loginStatus();
2983
- if (resp.is_admin && !resp.is_login) {
2984
- this.firstShow = true;
3780
+ const data = (yield this.ctx.getApi().user.getUserStatus(__spreadValues({}, this.ctx.getApi().getUserFields()))).data;
3781
+ if (data.is_admin && !data.is_login) {
3782
+ this.refreshOnShow = true;
2985
3783
  this.ctx.checkAdmin({
2986
3784
  onSuccess: () => {
2987
3785
  setTimeout(() => {
@@ -2992,6 +3790,7 @@ class SidebarLayer extends Component {
2992
3790
  this.hide();
2993
3791
  }
2994
3792
  });
3793
+ this.hide();
2995
3794
  }
2996
3795
  });
2997
3796
  }
@@ -3001,6 +3800,9 @@ class SidebarLayer extends Component {
3001
3800
  this.layer = this.ctx.get("layerManager").create("sidebar", this.$el);
3002
3801
  this.layer.setOnAfterHide(() => {
3003
3802
  this.ctx.editorResetState();
3803
+ this.animTimer && clearTimeout(this.animTimer);
3804
+ this.$el.style.transform = "";
3805
+ this.ctx.trigger("sidebar-hide");
3004
3806
  });
3005
3807
  }
3006
3808
  createIframe(view) {
@@ -3019,8 +3821,6 @@ class SidebarLayer extends Component {
3019
3821
  query.view = view;
3020
3822
  if (this.conf.darkMode)
3021
3823
  query.darkMode = "1";
3022
- if (typeof this.conf.locale === "string")
3023
- query.locale = this.conf.locale;
3024
3824
  const urlParams = new URLSearchParams(query);
3025
3825
  this.iframeLoad($iframe, `${baseURL}?${urlParams.toString()}`);
3026
3826
  return $iframe;
@@ -3563,7 +4363,7 @@ function renderReplyTo(r) {
3563
4363
  };
3564
4364
  let replyContent = marked(r.cConf.replyTo.content);
3565
4365
  if (r.cConf.replyTo.is_collapsed)
3566
- replyContent = `[${htmlEncode(r.ctx.$t("collapsed"))}]`;
4366
+ replyContent = `[${r.ctx.$t("collapsed")}]`;
3567
4367
  r.$replyTo.querySelector(".atk-content").innerHTML = replyContent;
3568
4368
  r.$body.prepend(r.$replyTo);
3569
4369
  }
@@ -3964,10 +4764,10 @@ class CommentActions {
3964
4764
  /** 投票操作 */
3965
4765
  vote(type) {
3966
4766
  const actionBtn = type === "up" ? this.comment.getRender().voteBtnUp : this.comment.getRender().voteBtnDown;
3967
- this.ctx.getApi().comment.vote(this.data.id, `comment_${type}`).then((v) => {
4767
+ this.ctx.getApi().votes.vote(`comment_${type}`, this.data.id, __spreadValues({}, this.ctx.getApi().getUserFields())).then((res) => {
3968
4768
  var _a, _b;
3969
- this.data.vote_up = v.up;
3970
- this.data.vote_down = v.down;
4769
+ this.data.vote_up = res.data.up;
4770
+ this.data.vote_down = res.data.down;
3971
4771
  (_a = this.comment.getRender().voteBtnUp) == null ? void 0 : _a.updateText();
3972
4772
  (_b = this.comment.getRender().voteBtnDown) == null ? void 0 : _b.updateText();
3973
4773
  }).catch((err) => {
@@ -3988,9 +4788,9 @@ class CommentActions {
3988
4788
  } else if (type === "pinned") {
3989
4789
  modify.is_pinned = !modify.is_pinned;
3990
4790
  }
3991
- this.ctx.getApi().comment.commentEdit(modify).then((data) => {
4791
+ this.ctx.getApi().comments.updateComment(this.data.id, __spreadValues({}, modify)).then((res) => {
3992
4792
  btnElem.setLoading(false);
3993
- this.comment.setData(data);
4793
+ this.comment.setData(res.data);
3994
4794
  }).catch((err) => {
3995
4795
  console.error(err);
3996
4796
  btnElem.setError(this.ctx.$t("editFail"));
@@ -4001,7 +4801,7 @@ class CommentActions {
4001
4801
  if (btnElem.isLoading)
4002
4802
  return;
4003
4803
  btnElem.setLoading(true, `${this.ctx.$t("deleting")}...`);
4004
- this.ctx.getApi().comment.commentDel(this.data.id, this.data.site_name).then(() => {
4804
+ this.ctx.getApi().comments.deleteComment(this.data.id).then(() => {
4005
4805
  btnElem.setLoading(false);
4006
4806
  if (this.cConf.onDelete)
4007
4807
  this.cConf.onDelete(this.comment);
@@ -4019,7 +4819,7 @@ class CommentActions {
4019
4819
  window.dispatchEvent(new Event("hashchange"));
4020
4820
  }
4021
4821
  }
4022
- class Comment extends Component {
4822
+ class CommentNode extends Component {
4023
4823
  // 最大嵌套层数
4024
4824
  constructor(ctx, data, conf) {
4025
4825
  super(ctx);
@@ -4160,7 +4960,7 @@ class Comment extends Component {
4160
4960
  }
4161
4961
  function createComment(ctx, comment, ctxComments) {
4162
4962
  var _a;
4163
- const instance2 = new Comment(ctx, comment, {
4963
+ const instance2 = new CommentNode(ctx, comment, {
4164
4964
  isFlatMode: (_a = ctx.getData().getListLastFetch()) == null ? void 0 : _a.params.flatMode,
4165
4965
  afterRender: () => {
4166
4966
  ctx.trigger("comment-rendered", instance2);
@@ -4308,9 +5108,13 @@ class Pagination {
4308
5108
  this.$el = createElement(
4309
5109
  `<div class="atk-pagination-wrap">
4310
5110
  <div class="atk-pagination">
4311
- <div class="atk-btn atk-btn-prev">Prev</div>
5111
+ <div class="atk-btn atk-btn-prev" aria-label="Previous page">
5112
+ <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="14px" width="14px" xmlns="http://www.w3.org/2000/svg"><path d="M217.9 256L345 129c9.4-9.4 9.4-24.6 0-33.9-9.4-9.4-24.6-9.3-34 0L167 239c-9.1 9.1-9.3 23.7-.7 33.1L310.9 417c4.7 4.7 10.9 7 17 7s12.3-2.3 17-7c9.4-9.4 9.4-24.6 0-33.9L217.9 256z"></path></svg>
5113
+ </div>
4312
5114
  <input type="text" class="atk-input" aria-label="Enter the number of page" />
4313
- <div class="atk-btn atk-btn-next">Next</div>
5115
+ <div class="atk-btn atk-btn-next" aria-label="Next page">
5116
+ <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="14px" width="14px" xmlns="http://www.w3.org/2000/svg"><path d="M294.1 256L167 129c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.3 34 0L345 239c9.1 9.1 9.3 23.7.7 33.1L201.1 417c-4.7 4.7-10.9 7-17 7s-12.3-2.3-17-7c-9.4-9.4-9.4-24.6 0-33.9l127-127.1z"></path></svg>
5117
+ </div>
4314
5118
  </div>
4315
5119
  </div>`
4316
5120
  );
@@ -4483,12 +5287,12 @@ function getPageDataByLastData(ctx) {
4483
5287
  return r;
4484
5288
  r.offset = last.params.offset;
4485
5289
  if (last.data)
4486
- r.total = last.params.flatMode ? last.data.total : last.data.total_roots;
5290
+ r.total = last.params.flatMode ? last.data.count : last.data.roots_count;
4487
5291
  return r;
4488
5292
  }
4489
5293
  const initListPaginatorFunc = (ctx) => {
4490
5294
  let paginator = null;
4491
- ctx.on("conf-loaded", (conf) => {
5295
+ ctx.watchConf(["pagination", "locale"], (conf) => {
4492
5296
  const list = ctx.get("list");
4493
5297
  if (paginator)
4494
5298
  paginator.dispose();
@@ -4512,7 +5316,7 @@ const initListPaginatorFunc = (ctx) => {
4512
5316
  ctx.getData().clearComments();
4513
5317
  }
4514
5318
  });
4515
- ctx.on("list-error", () => {
5319
+ ctx.on("list-failed", () => {
4516
5320
  var _a;
4517
5321
  (_a = paginator == null ? void 0 : paginator.showErr) == null ? void 0 : _a.call(paginator, t("loadFail"));
4518
5322
  });
@@ -4601,11 +5405,48 @@ function getScrollbarHelper() {
4601
5405
  }
4602
5406
  };
4603
5407
  }
5408
+ class Layer {
5409
+ constructor($el, opts) {
5410
+ __publicField(this, "allowMaskClose", true);
5411
+ __publicField(this, "onAfterHide");
5412
+ this.$el = $el;
5413
+ this.opts = opts;
5414
+ }
5415
+ setOnAfterHide(func) {
5416
+ this.onAfterHide = func;
5417
+ }
5418
+ setAllowMaskClose(allow) {
5419
+ this.allowMaskClose = allow;
5420
+ }
5421
+ getAllowMaskClose() {
5422
+ return this.allowMaskClose;
5423
+ }
5424
+ getEl() {
5425
+ return this.$el;
5426
+ }
5427
+ show() {
5428
+ this.opts.onShow();
5429
+ this.$el.style.display = "";
5430
+ }
5431
+ hide() {
5432
+ return __async(this, null, function* () {
5433
+ this.opts.onHide();
5434
+ this.$el.style.display = "none";
5435
+ this.onAfterHide && this.onAfterHide();
5436
+ });
5437
+ }
5438
+ destroy() {
5439
+ return __async(this, null, function* () {
5440
+ this.opts.onHide();
5441
+ this.$el.remove();
5442
+ this.onAfterHide && this.onAfterHide();
5443
+ });
5444
+ }
5445
+ }
4604
5446
  class LayerWrap {
4605
5447
  constructor() {
4606
5448
  __publicField(this, "$wrap");
4607
5449
  __publicField(this, "$mask");
4608
- __publicField(this, "allowMaskClose", true);
4609
5450
  __publicField(this, "items", []);
4610
5451
  this.$wrap = createElement(
4611
5452
  `<div class="atk-layer-wrap" style="display: none;"><div class="atk-layer-mask"></div></div>`
@@ -4613,14 +5454,24 @@ class LayerWrap {
4613
5454
  this.$mask = this.$wrap.querySelector(".atk-layer-mask");
4614
5455
  }
4615
5456
  createItem(name, el) {
4616
- if (!el) {
4617
- el = document.createElement("div");
4618
- el.classList.add("atk-layer-item");
4619
- el.setAttribute("data-layer-name", name);
4620
- el.style.display = "none";
4621
- }
5457
+ el = el || this.createItemElement(name);
5458
+ el.setAttribute("data-layer-name", name);
5459
+ this.$wrap.appendChild(el);
5460
+ const layer = new Layer(el, {
5461
+ onHide: () => this.hideWrap(el),
5462
+ onShow: () => this.showWrap()
5463
+ });
5464
+ this.getMask().addEventListener("click", () => {
5465
+ layer.getAllowMaskClose() && layer.hide();
5466
+ });
5467
+ this.items.push(layer);
5468
+ return layer;
5469
+ }
5470
+ createItemElement(name) {
5471
+ const el = document.createElement("div");
5472
+ el.classList.add("atk-layer-item");
5473
+ el.style.display = "none";
4622
5474
  this.$wrap.appendChild(el);
4623
- this.items.push(el);
4624
5475
  return el;
4625
5476
  }
4626
5477
  getWrap() {
@@ -4629,78 +5480,36 @@ class LayerWrap {
4629
5480
  getMask() {
4630
5481
  return this.$mask;
4631
5482
  }
4632
- setMaskClose(enabled) {
4633
- this.allowMaskClose = enabled;
4634
- }
4635
- show() {
5483
+ showWrap() {
4636
5484
  this.$wrap.style.display = "block";
4637
5485
  this.$mask.style.display = "block";
4638
5486
  this.$mask.classList.add("atk-fade-in");
4639
- this.$mask.onclick = () => {
4640
- if (this.allowMaskClose)
4641
- this.hide();
4642
- };
4643
5487
  getScrollbarHelper().lock();
4644
5488
  }
4645
- hide(callback) {
4646
- if (this.items.filter((e) => e.isConnected && e.style.display !== "none").length > 1) {
4647
- callback && callback();
5489
+ hideWrap($el) {
5490
+ if (this.items.map((l) => l.getEl()).filter((e) => e !== $el && e.isConnected && e.style.display !== "none").length > 0) {
4648
5491
  return;
4649
5492
  }
4650
- const onAfterHide = () => {
5493
+ const onHide = () => {
4651
5494
  this.$wrap.style.display = "none";
4652
5495
  this.$wrap.classList.remove("atk-fade-out");
4653
- callback && callback();
4654
5496
  getScrollbarHelper().unlock();
4655
5497
  this.$wrap.onanimationend = null;
4656
5498
  };
4657
5499
  this.$wrap.classList.add("atk-fade-out");
4658
5500
  if (window.getComputedStyle(this.$wrap)["animation-name"] !== "none") {
4659
- this.$wrap.onanimationend = () => onAfterHide();
5501
+ this.$wrap.onanimationend = () => onHide();
4660
5502
  } else {
4661
- onAfterHide();
5503
+ onHide();
4662
5504
  }
4663
5505
  }
4664
5506
  }
4665
- class Layer {
4666
- constructor(wrap, name, el) {
4667
- __publicField(this, "$el");
4668
- __publicField(this, "wrap");
4669
- __publicField(this, "onAfterHide");
4670
- this.wrap = wrap;
4671
- this.$el = this.wrap.createItem(name, el);
4672
- }
4673
- setOnAfterHide(func) {
4674
- this.onAfterHide = func;
4675
- }
4676
- getEl() {
4677
- return this.$el;
4678
- }
4679
- show() {
4680
- this.$el.style.display = "";
4681
- this.wrap.show();
4682
- }
4683
- hide() {
4684
- this.wrap.hide(() => {
4685
- this.$el.style.display = "none";
4686
- this.onAfterHide && this.onAfterHide();
4687
- });
4688
- }
4689
- destroy() {
4690
- this.wrap.hide(() => {
4691
- this.$el.remove();
4692
- this.onAfterHide && this.onAfterHide();
4693
- });
4694
- }
4695
- }
4696
5507
  class LayerManager {
4697
5508
  constructor(ctx) {
4698
5509
  __publicField(this, "wrap");
4699
- __publicField(this, "ctx");
4700
- this.ctx = ctx;
4701
5510
  this.wrap = new LayerWrap();
4702
5511
  document.body.appendChild(this.wrap.getWrap());
4703
- ctx.on("destroy", () => {
5512
+ ctx.on("unmounted", () => {
4704
5513
  this.wrap.getWrap().remove();
4705
5514
  });
4706
5515
  getScrollbarHelper().init();
@@ -4709,8 +5518,7 @@ class LayerManager {
4709
5518
  return this.wrap.getWrap();
4710
5519
  }
4711
5520
  create(name, el) {
4712
- const layer = new Layer(this.wrap, name, el);
4713
- return layer;
5521
+ return this.wrap.createItem(name, el);
4714
5522
  }
4715
5523
  }
4716
5524
  const LOCAL_USER_KEY = "ArtalkUser";
@@ -4730,7 +5538,7 @@ class User {
4730
5538
  getData() {
4731
5539
  return this.data;
4732
5540
  }
4733
- /** 保存用户到 localStorage 中 */
5541
+ /** Update user data and save to localStorage */
4734
5542
  update(obj = {}) {
4735
5543
  Object.entries(obj).forEach(([key, value]) => {
4736
5544
  this.data[key] = value;
@@ -4749,7 +5557,7 @@ class User {
4749
5557
  isAdmin: false
4750
5558
  });
4751
5559
  }
4752
- /** 是否已填写基本用户信息 */
5560
+ /** Check if user has filled basic data */
4753
5561
  checkHasBasicUserInfo() {
4754
5562
  return !!this.data.nick && !!this.data.email;
4755
5563
  }
@@ -4758,8 +5566,8 @@ const services = {
4758
5566
  // I18n
4759
5567
  i18n(ctx) {
4760
5568
  setLocale(ctx.conf.locale);
4761
- ctx.on("conf-loaded", () => {
4762
- setLocale(ctx.conf.locale);
5569
+ ctx.watchConf(["locale"], (conf) => {
5570
+ setLocale(conf.locale);
4763
5571
  });
4764
5572
  },
4765
5573
  // User Store
@@ -4780,8 +5588,9 @@ const services = {
4780
5588
  const checkerLauncher = new CheckerLauncher({
4781
5589
  getCtx: () => ctx,
4782
5590
  getApi: () => ctx.getApi(),
4783
- getIframeURLBase: () => ctx.conf.server,
4784
- onReload: () => ctx.reload()
5591
+ onReload: () => ctx.reload(),
5592
+ // make sure suffix with a slash, because it will be used as a base url when call `fetch`
5593
+ getCaptchaIframeURL: () => `${ctx.conf.server}/api/v2/captcha/?t=${+/* @__PURE__ */ new Date()}`
4785
5594
  });
4786
5595
  return checkerLauncher;
4787
5596
  },
@@ -4812,34 +5621,41 @@ const services = {
4812
5621
  }
4813
5622
  };
4814
5623
  function showErrorDialog(opts) {
4815
- const errEl = createElement(`<span>${opts.errMsg},${t("listLoadFailMsg")}<br/></span>`);
5624
+ const errEl = createElement(`<span><span class="error-message"></span><br/><br/></span>`);
5625
+ errEl.querySelector(".error-message").innerText = `${t("listLoadFailMsg")}
5626
+ ${opts.errMsg}`;
4816
5627
  if (opts.retryFn) {
4817
5628
  const $retryBtn = createElement(`<span style="cursor:pointer;">${t("listRetry")}</span>`);
4818
5629
  $retryBtn.onclick = () => opts.retryFn && opts.retryFn();
4819
5630
  errEl.appendChild($retryBtn);
4820
5631
  }
4821
5632
  if (opts.onOpenSidebar) {
4822
- const $openSidebar = createElement(`<span atk-only-admin-show> | <span style="cursor:pointer;">${t("open") + t("ctrlCenter")}</span></span>`);
5633
+ const $openSidebar = createElement(`<span atk-only-admin-show> | <span style="cursor:pointer;">${t("openName", { name: t("ctrlCenter") })}</span></span>`);
4823
5634
  errEl.appendChild($openSidebar);
4824
5635
  $openSidebar.onclick = () => opts.onOpenSidebar && opts.onOpenSidebar();
4825
5636
  }
4826
5637
  setError(opts.$err, errEl);
4827
5638
  }
4828
5639
  const ConfRemoter = (ctx) => {
4829
- ctx.on("inited", () => {
5640
+ ctx.on("created", () => {
5641
+ if (ctx.conf.immediateFetch !== false)
5642
+ ctx.trigger("conf-fetch");
5643
+ });
5644
+ ctx.on("conf-fetch", () => {
4830
5645
  loadConf(ctx);
4831
5646
  });
4832
5647
  };
4833
5648
  function loadConf(ctx) {
4834
- ctx.getApi().system.conf().then((data) => {
5649
+ ctx.getApi().conf.conf().then((res) => {
5650
+ var _a;
4835
5651
  let conf = {
4836
- apiVersion: data.version.version
5652
+ apiVersion: (_a = res.data.version) == null ? void 0 : _a.version
4837
5653
  // version info
4838
5654
  };
4839
5655
  if (ctx.conf.useBackendConf) {
4840
- if (!data.frontend_conf)
5656
+ if (!res.data.frontend_conf)
4841
5657
  throw new Error("The remote backend does not respond to the frontend conf, but `useBackendConf` conf is enabled");
4842
- conf = __spreadValues(__spreadValues({}, conf), handleConfFormServer(data.frontend_conf));
5658
+ conf = __spreadValues(__spreadValues({}, conf), handleConfFormServer(res.data.frontend_conf));
4843
5659
  }
4844
5660
  ctx.conf.remoteConfModifier && ctx.conf.remoteConfModifier(conf);
4845
5661
  ctx.updateConf(conf);
@@ -4861,7 +5677,10 @@ function loadConf(ctx) {
4861
5677
  }) : void 0
4862
5678
  // only show open sidebar button when user is admin
4863
5679
  });
5680
+ console.error(err);
4864
5681
  throw err;
5682
+ }).then(() => {
5683
+ ctx.trigger("mounted");
4865
5684
  }).then(() => {
4866
5685
  if (ctx.conf.remoteConfModifier)
4867
5686
  return;
@@ -4871,7 +5690,7 @@ function loadConf(ctx) {
4871
5690
  }
4872
5691
  const Markdown = (ctx) => {
4873
5692
  initMarked();
4874
- ctx.on("conf-loaded", (conf) => {
5693
+ ctx.on("updated", (conf) => {
4875
5694
  if (conf.markedReplacers)
4876
5695
  setReplacers(conf.markedReplacers);
4877
5696
  });
@@ -4959,23 +5778,27 @@ class SubmitAddPreset {
4959
5778
  }
4960
5779
  reqAdd() {
4961
5780
  return __async(this, null, function* () {
4962
- const nComment = yield this.kit.useApi().comment.add(__spreadValues({}, this.getSubmitAddParams()));
5781
+ const nComment = (yield this.kit.useApi().comments.createComment(__spreadValues({}, yield this.getSubmitAddParams()))).data;
4963
5782
  return nComment;
4964
5783
  });
4965
5784
  }
4966
5785
  getSubmitAddParams() {
4967
- const { nick, email, link } = this.kit.useUser().getData();
4968
- const conf = this.kit.useConf();
4969
- return {
4970
- content: this.kit.useEditor().getContentFinal(),
4971
- nick,
4972
- email,
4973
- link,
4974
- rid: 0,
4975
- page_key: conf.pageKey,
4976
- page_title: conf.pageTitle,
4977
- site_name: conf.site
4978
- };
5786
+ return __async(this, null, function* () {
5787
+ const { nick, email, link } = this.kit.useUser().getData();
5788
+ const conf = this.kit.useConf();
5789
+ return {
5790
+ content: this.kit.useEditor().getContentFinal(),
5791
+ name: nick,
5792
+ email,
5793
+ link,
5794
+ rid: 0,
5795
+ page_key: conf.pageKey,
5796
+ page_title: conf.pageTitle,
5797
+ site_name: conf.site,
5798
+ ua: yield getCorrectUserAgent()
5799
+ // Get the corrected UA
5800
+ };
5801
+ });
4979
5802
  }
4980
5803
  postSubmitAdd(commentNew) {
4981
5804
  this.kit.useGlobalCtx().getData().insertComment(commentNew);
@@ -5020,7 +5843,7 @@ class Submit extends EditorPlug {
5020
5843
  this.defaultPreset.postSubmitAdd(nComment);
5021
5844
  } catch (err) {
5022
5845
  console.error(err);
5023
- this.kit.useEditor().showNotify(`${t("commentFail")},${err.msg || String(err)}`, "e");
5846
+ this.kit.useEditor().showNotify(`${t("commentFail")}: ${err.msg || String(err)}`, "e");
5024
5847
  return;
5025
5848
  } finally {
5026
5849
  this.kit.useEditor().hideLoading();
@@ -5051,12 +5874,12 @@ class StateReply extends EditorPlug {
5051
5874
  req: () => __async(this, null, function* () {
5052
5875
  if (!this.comment)
5053
5876
  throw new Error("reply comment cannot be empty");
5054
- const nComment = yield this.kit.useApi().comment.add(__spreadProps(__spreadValues({}, defaultPreset.getSubmitAddParams()), {
5877
+ const nComment = (yield this.kit.useApi().comments.createComment(__spreadProps(__spreadValues({}, yield defaultPreset.getSubmitAddParams()), {
5055
5878
  rid: this.comment.id,
5056
5879
  page_key: this.comment.page_key,
5057
5880
  page_title: void 0,
5058
5881
  site_name: this.comment.site_name
5059
- }));
5882
+ }))).data;
5060
5883
  return nComment;
5061
5884
  }),
5062
5885
  post: (nComment) => {
@@ -5123,8 +5946,9 @@ class StateEdit extends EditorPlug {
5123
5946
  email: this.kit.useUI().$email.value,
5124
5947
  link: this.kit.useUI().$link.value
5125
5948
  };
5126
- const nComment = yield this.kit.useApi().comment.commentEdit(__spreadValues(__spreadValues({}, this.comment), saveData));
5127
- return nComment;
5949
+ const comment = this.comment;
5950
+ const nComment = yield this.kit.useApi().comments.updateComment(comment.id, __spreadValues(__spreadValues({}, comment), saveData));
5951
+ return nComment.data;
5128
5952
  }),
5129
5953
  post: (nComment) => {
5130
5954
  this.kit.useGlobalCtx().getData().updateComment(nComment);
@@ -5272,12 +6096,12 @@ class HeaderUser extends EditorPlug {
5272
6096
  this.query.abortFn();
5273
6097
  this.query.timer = window.setTimeout(() => {
5274
6098
  this.query.timer = null;
5275
- const { req, abort } = this.kit.useApi().user.userGet(
5276
- this.kit.useUser().getData().nick,
5277
- this.kit.useUser().getData().email
5278
- );
5279
- this.query.abortFn = abort;
5280
- req.then((data) => this.onUserInfoFetched(data)).catch((err) => {
6099
+ const api = this.kit.useApi();
6100
+ const CANCEL_TOKEN = "getUserCancelToken";
6101
+ this.query.abortFn = () => api.abortRequest(CANCEL_TOKEN);
6102
+ api.user.getUser(__spreadValues({}, api.getUserFields()), {
6103
+ cancelToken: CANCEL_TOKEN
6104
+ }).then((res) => this.onUserInfoFetched(res.data)).catch((err) => {
5281
6105
  }).finally(() => {
5282
6106
  this.query.abortFn = null;
5283
6107
  });
@@ -5292,7 +6116,7 @@ class HeaderUser extends EditorPlug {
5292
6116
  var _a;
5293
6117
  if (!data.is_login)
5294
6118
  this.kit.useUser().logout();
5295
- this.kit.useGlobalCtx().getData().updateUnreads(data.unread);
6119
+ this.kit.useGlobalCtx().getData().updateNotifies(data.notifies);
5296
6120
  if (this.kit.useUser().checkHasBasicUserInfo() && !data.is_login && ((_a = data.user) == null ? void 0 : _a.is_admin)) {
5297
6121
  this.kit.useGlobalCtx().checkAdmin({
5298
6122
  onSuccess: () => {
@@ -5386,7 +6210,7 @@ class Emoticons extends EditorPlug {
5386
6210
  data = [data];
5387
6211
  }
5388
6212
  if (!Array.isArray(data)) {
5389
- setError(this.$panel, "表情包数据必须为 Array/Object/String 类型");
6213
+ setError(this.$panel, `[${t("emoticon")}] Data must be of Array/Object/String type`);
5390
6214
  hideLoading(this.$panel);
5391
6215
  return [];
5392
6216
  }
@@ -5398,7 +6222,7 @@ class Emoticons extends EditorPlug {
5398
6222
  data.push(grp);
5399
6223
  };
5400
6224
  const remoteLoad = (d) => __async(this, null, function* () {
5401
- yield Promise.all(d.map((grp, index2) => __async(this, null, function* () {
6225
+ yield Promise.all(d.map((grp, index) => __async(this, null, function* () {
5402
6226
  if (typeof grp === "object" && !Array.isArray(grp)) {
5403
6227
  pushGrp(grp);
5404
6228
  } else if (Array.isArray(grp)) {
@@ -5443,7 +6267,7 @@ class Emoticons extends EditorPlug {
5443
6267
  } catch (err) {
5444
6268
  hideLoading(this.$panel);
5445
6269
  console.error("[Emoticons] Load Failed:", err);
5446
- setError(this.$panel, `${t("emoticon")}${t("loadFail")} ${String(err)}`);
6270
+ setError(this.$panel, `[${t("emoticon")}] ${t("loadFail")}: ${String(err)}`);
5447
6271
  return [];
5448
6272
  }
5449
6273
  });
@@ -5451,9 +6275,9 @@ class Emoticons extends EditorPlug {
5451
6275
  /** 避免表情 item.key 为 null 的情况 */
5452
6276
  solveNullKey(data) {
5453
6277
  data.forEach((grp) => {
5454
- grp.items.forEach((item, index2) => {
6278
+ grp.items.forEach((item, index) => {
5455
6279
  if (!item.key)
5456
- item.key = `${grp.name} ${index2 + 1}`;
6280
+ item.key = `${grp.name} ${index + 1}`;
5457
6281
  });
5458
6282
  });
5459
6283
  }
@@ -5486,14 +6310,14 @@ class Emoticons extends EditorPlug {
5486
6310
  const dest = [];
5487
6311
  Object.entries(owoData).forEach(([grpName, grp]) => {
5488
6312
  const nGrp = { name: grpName, type: grp.type, items: [] };
5489
- grp.container.forEach((item, index2) => {
6313
+ grp.container.forEach((item, index) => {
5490
6314
  const iconStr = item.icon;
5491
6315
  if (/<(img|IMG)/.test(iconStr)) {
5492
6316
  const find = /src=["'](.*?)["']/.exec(iconStr);
5493
6317
  if (find && find.length > 1)
5494
6318
  item.icon = find[1];
5495
6319
  }
5496
- nGrp.items.push({ key: item.text || `${grpName} ${index2 + 1}`, val: item.icon });
6320
+ nGrp.items.push({ key: item.text || `${grpName} ${index + 1}`, val: item.icon });
5497
6321
  });
5498
6322
  dest.push(nGrp);
5499
6323
  });
@@ -5503,10 +6327,10 @@ class Emoticons extends EditorPlug {
5503
6327
  initEmoticonsList() {
5504
6328
  this.$grpWrap = createElement(`<div class="atk-grp-wrap"></div>`);
5505
6329
  this.$panel.append(this.$grpWrap);
5506
- this.emoticons.forEach((grp, index2) => {
6330
+ this.emoticons.forEach((grp, index) => {
5507
6331
  const $grp = createElement(`<div class="atk-grp" style="display: none;"></div>`);
5508
6332
  this.$grpWrap.append($grp);
5509
- $grp.setAttribute("data-index", String(index2));
6333
+ $grp.setAttribute("data-index", String(index));
5510
6334
  $grp.setAttribute("data-grp-name", grp.name);
5511
6335
  $grp.setAttribute("data-type", grp.type);
5512
6336
  grp.items.forEach((item) => {
@@ -5534,11 +6358,11 @@ class Emoticons extends EditorPlug {
5534
6358
  if (this.emoticons.length > 1) {
5535
6359
  this.$grpSwitcher = createElement(`<div class="atk-grp-switcher"></div>`);
5536
6360
  this.$panel.append(this.$grpSwitcher);
5537
- this.emoticons.forEach((grp, index2) => {
6361
+ this.emoticons.forEach((grp, index) => {
5538
6362
  const $item = createElement("<span />");
5539
6363
  $item.innerText = grp.name;
5540
- $item.setAttribute("data-index", String(index2));
5541
- $item.onclick = () => this.openGrp(index2);
6364
+ $item.setAttribute("data-index", String(index));
6365
+ $item.onclick = () => this.openGrp(index);
5542
6366
  this.$grpSwitcher.append($item);
5543
6367
  });
5544
6368
  }
@@ -5546,18 +6370,18 @@ class Emoticons extends EditorPlug {
5546
6370
  this.openGrp(0);
5547
6371
  }
5548
6372
  /** 打开一个表情组 */
5549
- openGrp(index2) {
6373
+ openGrp(index) {
5550
6374
  var _a, _b, _c;
5551
6375
  Array.from(this.$grpWrap.children).forEach((item) => {
5552
6376
  const el = item;
5553
- if (el.getAttribute("data-index") !== String(index2)) {
6377
+ if (el.getAttribute("data-index") !== String(index)) {
5554
6378
  el.style.display = "none";
5555
6379
  } else {
5556
6380
  el.style.display = "";
5557
6381
  }
5558
6382
  });
5559
6383
  (_a = this.$grpSwitcher) == null ? void 0 : _a.querySelectorAll("span.active").forEach((item) => item.classList.remove("active"));
5560
- (_c = (_b = this.$grpSwitcher) == null ? void 0 : _b.querySelector(`span[data-index="${index2}"]`)) == null ? void 0 : _c.classList.add("active");
6384
+ (_c = (_b = this.$grpSwitcher) == null ? void 0 : _b.querySelector(`span[data-index="${index}"]`)) == null ? void 0 : _c.classList.add("active");
5561
6385
  this.changeListHeight();
5562
6386
  }
5563
6387
  changeListHeight() {
@@ -5569,7 +6393,7 @@ class Emoticons extends EditorPlug {
5569
6393
  this.emoticons.forEach((grp) => {
5570
6394
  if (grp.type !== "image")
5571
6395
  return;
5572
- Object.entries(grp.items).forEach(([index2, item]) => {
6396
+ Object.entries(grp.items).forEach(([index, item]) => {
5573
6397
  text = text.split(`:[${item.key}]`).join(`<img src="${item.val}" atk-emoticon="${item.key}">`);
5574
6398
  });
5575
6399
  });
@@ -5665,16 +6489,16 @@ class Upload extends EditorPlug {
5665
6489
  try {
5666
6490
  const customUploaderFn = this.kit.useConf().imgUploader;
5667
6491
  if (!customUploaderFn) {
5668
- resp = yield this.kit.useApi().upload.imgUpload(file);
6492
+ resp = (yield this.kit.useApi().upload.upload({ file })).data;
5669
6493
  } else {
5670
- resp = { img_url: yield customUploaderFn(file) };
6494
+ resp = { public_url: yield customUploaderFn(file) };
5671
6495
  }
5672
6496
  } catch (err) {
5673
6497
  console.error(err);
5674
- this.kit.useEditor().showNotify(`${t("uploadFail")},${err.msg}`, "e");
6498
+ this.kit.useEditor().showNotify(`${t("uploadFail")}: ${err.msg}`, "e");
5675
6499
  }
5676
- if (!!resp && resp.img_url) {
5677
- let imgURL = resp.img_url;
6500
+ if (!!resp && resp.public_url) {
6501
+ let imgURL = resp.public_url;
5678
6502
  if (!isValidURL(imgURL))
5679
6503
  imgURL = getURLBasedOnApi({
5680
6504
  base: this.kit.useConf().server,
@@ -5715,7 +6539,7 @@ class Preview extends EditorPlug {
5715
6539
  this.$panel.innerHTML = this.kit.useEditor().getContentMarked();
5716
6540
  }
5717
6541
  }
5718
- const ENABLED_PLUGS = [
6542
+ const EDITOR_PLUGS = [
5719
6543
  // Core
5720
6544
  LocalStorage,
5721
6545
  HeaderEvent,
@@ -5733,13 +6557,13 @@ const ENABLED_PLUGS = [
5733
6557
  Upload,
5734
6558
  Preview
5735
6559
  ];
5736
- function getDisabledPlugByConf(conf) {
5737
- return [
5738
- { k: Upload, v: conf.imgUpload },
5739
- { k: Emoticons, v: conf.emoticons },
5740
- { k: Preview, v: conf.preview },
5741
- { k: Mover, v: conf.editorTravel }
5742
- ].filter((n) => !n.v).flatMap((n) => n.k);
6560
+ function getEnabledPlugs(conf) {
6561
+ const confRefs = /* @__PURE__ */ new Map();
6562
+ confRefs.set(Upload, conf.imgUpload);
6563
+ confRefs.set(Emoticons, conf.emoticons);
6564
+ confRefs.set(Preview, conf.preview);
6565
+ confRefs.set(Mover, conf.editorTravel);
6566
+ return EDITOR_PLUGS.filter((p) => !confRefs.has(p) || !!confRefs.get(p));
5743
6567
  }
5744
6568
  class PlugKit {
5745
6569
  constructor(plugs) {
@@ -5802,11 +6626,16 @@ class PlugManager {
5802
6626
  __publicField(this, "events", new EventManager());
5803
6627
  this.editor = editor;
5804
6628
  let confLoaded = false;
5805
- this.editor.ctx.on("conf-loaded", () => {
6629
+ this.editor.ctx.watchConf([
6630
+ "imgUpload",
6631
+ "emoticons",
6632
+ "preview",
6633
+ "editorTravel",
6634
+ "locale"
6635
+ ], (conf) => {
5806
6636
  confLoaded && this.getEvents().trigger("unmounted");
5807
6637
  this.clear();
5808
- const DISABLED = getDisabledPlugByConf(this.editor.ctx.conf);
5809
- ENABLED_PLUGS.filter((p) => !DISABLED.includes(p)).forEach((Plug) => {
6638
+ getEnabledPlugs(conf).forEach((Plug) => {
5810
6639
  const kit = new PlugKit(this);
5811
6640
  this.plugs.push(new Plug(kit));
5812
6641
  });
@@ -5832,6 +6661,9 @@ class PlugManager {
5832
6661
  this.editor.getUI().$plugPanelWrap.innerHTML = "";
5833
6662
  this.editor.getUI().$plugPanelWrap.style.display = "none";
5834
6663
  this.editor.getUI().$plugBtnWrap.innerHTML = "";
6664
+ this.editor.getUI().$el.addEventListener("click", (e) => {
6665
+ e.stopPropagation();
6666
+ });
5835
6667
  this.plugs.forEach((plug) => this.loadPluginItem(plug));
5836
6668
  }
5837
6669
  /** Load the plug btn and plug panel on editor ui */
@@ -5896,7 +6728,7 @@ class PlugManager {
5896
6728
  }
5897
6729
  const WithEditor = (ctx) => {
5898
6730
  let $closeCommentBtn;
5899
- ctx.on("inited", () => {
6731
+ ctx.on("mounted", () => {
5900
6732
  const list = ctx.get("list");
5901
6733
  $closeCommentBtn = list.$el.querySelector('[data-action="admin-close-comment"]');
5902
6734
  $closeCommentBtn.addEventListener("click", () => {
@@ -5924,8 +6756,8 @@ const WithEditor = (ctx) => {
5924
6756
  };
5925
6757
  function adminPageEditSave(ctx, page) {
5926
6758
  ctx.editorShowLoading();
5927
- ctx.getApi().page.pageEdit(page).then((respPage) => {
5928
- ctx.getData().updatePage(respPage);
6759
+ ctx.getApi().pages.updatePage(page.id, page).then(({ data }) => {
6760
+ ctx.getData().updatePage(data);
5929
6761
  }).catch((err) => {
5930
6762
  ctx.editorShowNotify(`${t("editFail")}: ${err.msg || String(err)}`, "e");
5931
6763
  }).finally(() => {
@@ -5935,13 +6767,13 @@ function adminPageEditSave(ctx, page) {
5935
6767
  const Unread = (ctx) => {
5936
6768
  ctx.on("comment-rendered", (comment) => {
5937
6769
  if (ctx.conf.listUnreadHighlight === true) {
5938
- const unreads = ctx.getData().getUnreads();
5939
- const notify = unreads.find((o) => o.comment_id === comment.getID());
6770
+ const notifies = ctx.getData().getNotifies();
6771
+ const notify = notifies.find((o) => o.comment_id === comment.getID());
5940
6772
  if (notify) {
5941
6773
  comment.getRender().setUnread(true);
5942
6774
  comment.getRender().setOpenAction(() => {
5943
6775
  window.open(notify.read_link);
5944
- ctx.getData().updateUnreads(unreads.filter((o) => o.comment_id !== comment.getID()));
6776
+ ctx.getData().updateNotifies(notifies.filter((o) => o.comment_id !== comment.getID()));
5945
6777
  });
5946
6778
  } else {
5947
6779
  comment.getRender().setUnread(false);
@@ -5951,8 +6783,8 @@ const Unread = (ctx) => {
5951
6783
  ctx.on("list-goto", (commentID) => {
5952
6784
  const notifyKey = getQueryParam("atk_notify_key");
5953
6785
  if (notifyKey) {
5954
- ctx.getApi().user.markRead(commentID, notifyKey).then(() => {
5955
- ctx.getData().updateUnreads(ctx.getData().getUnreads().filter((o) => o.comment_id !== commentID));
6786
+ ctx.getApi().notifies.markNotifyRead(commentID, notifyKey).then(() => {
6787
+ ctx.getData().updateNotifies(ctx.getData().getNotifies().filter((o) => o.comment_id !== commentID));
5956
6788
  });
5957
6789
  }
5958
6790
  });
@@ -5964,7 +6796,7 @@ const Count = (ctx) => {
5964
6796
  const $count = list.$el.querySelector(".atk-comment-count .atk-text");
5965
6797
  if (!$count)
5966
6798
  return;
5967
- const text = htmlEncode(t("counter", { count: `${Number((_b = (_a = ctx.getData().getListLastFetch()) == null ? void 0 : _a.data) == null ? void 0 : _b.total) || 0}` }));
6799
+ const text = htmlEncode(t("counter", { count: `${Number((_b = (_a = ctx.getData().getListLastFetch()) == null ? void 0 : _a.data) == null ? void 0 : _b.count) || 0}` }));
5968
6800
  $count.innerHTML = text.replace(/(\d+)/, '<span class="atk-comment-count-num">$1</span>');
5969
6801
  };
5970
6802
  ctx.on("list-loaded", () => {
@@ -5973,12 +6805,12 @@ const Count = (ctx) => {
5973
6805
  ctx.on("comment-inserted", () => {
5974
6806
  const last = ctx.getData().getListLastFetch();
5975
6807
  if (last == null ? void 0 : last.data)
5976
- last.data.total += 1;
6808
+ last.data.count += 1;
5977
6809
  });
5978
6810
  ctx.on("comment-deleted", () => {
5979
6811
  const last = ctx.getData().getListLastFetch();
5980
6812
  if (last == null ? void 0 : last.data)
5981
- last.data.total -= 1;
6813
+ last.data.count -= 1;
5982
6814
  });
5983
6815
  };
5984
6816
  const SidebarBtn = (ctx) => {
@@ -5996,7 +6828,7 @@ const SidebarBtn = (ctx) => {
5996
6828
  $openSidebarBtn.classList.add("atk-hide");
5997
6829
  }
5998
6830
  };
5999
- ctx.on("conf-loaded", () => {
6831
+ ctx.watchConf(["locale"], (conf) => {
6000
6832
  const list = ctx.get("list");
6001
6833
  $openSidebarBtn = list.$el.querySelector('[data-action="open-sidebar"]');
6002
6834
  if (!$openSidebarBtn)
@@ -6022,12 +6854,12 @@ const UnreadBadge = (ctx) => {
6022
6854
  $unreadBadge.style.display = "none";
6023
6855
  }
6024
6856
  };
6025
- ctx.on("conf-loaded", () => {
6857
+ ctx.on("mounted", () => {
6026
6858
  const list = ctx.get("list");
6027
6859
  $unreadBadge = list.$el.querySelector(".atk-unread-badge");
6028
6860
  });
6029
- ctx.on("unreads-updated", (unreads) => {
6030
- showUnreadBadge(unreads.length || 0);
6861
+ ctx.on("notifies-updated", (notifies) => {
6862
+ showUnreadBadge(notifies.length || 0);
6031
6863
  });
6032
6864
  };
6033
6865
  const Goto = (ctx) => {
@@ -6043,11 +6875,11 @@ const Goto = (ctx) => {
6043
6875
  delayGoto = false;
6044
6876
  check2();
6045
6877
  };
6046
- ctx.on("inited", () => {
6878
+ ctx.on("mounted", () => {
6047
6879
  window.addEventListener("hashchange", hashChangeHandler);
6048
6880
  ctx.on("list-loaded", check2);
6049
6881
  });
6050
- ctx.on("destroy", () => {
6882
+ ctx.on("unmounted", () => {
6051
6883
  window.removeEventListener("hashchange", hashChangeHandler);
6052
6884
  ctx.off("list-loaded", check2);
6053
6885
  });
@@ -6085,9 +6917,9 @@ function extractCommentID() {
6085
6917
  }
6086
6918
  return commentId || null;
6087
6919
  }
6088
- const version = "2.7.2";
6920
+ const version = "2.8.0";
6089
6921
  const Copyright = (ctx) => {
6090
- ctx.on("conf-loaded", () => {
6922
+ ctx.on("mounted", () => {
6091
6923
  const list = ctx.get("list");
6092
6924
  const $copyright = list.$el.querySelector(".atk-copyright");
6093
6925
  if (!$copyright)
@@ -6096,7 +6928,14 @@ const Copyright = (ctx) => {
6096
6928
  });
6097
6929
  };
6098
6930
  const NoComment = (ctx) => {
6931
+ let isFetching = false;
6932
+ ctx.on("list-fetch", (params) => {
6933
+ isFetching = true;
6934
+ });
6099
6935
  ctx.on("list-loaded", (comments) => {
6936
+ if (!isFetching)
6937
+ return;
6938
+ isFetching = false;
6100
6939
  const list = ctx.get("list");
6101
6940
  const isNoComment = comments.length <= 0;
6102
6941
  let $noComment = list.getCommentsWrapEl().querySelector(".atk-list-no-comment");
@@ -6143,12 +6982,12 @@ const Dropdown = (ctx) => {
6143
6982
  ]
6144
6983
  });
6145
6984
  };
6146
- ctx.on("conf-loaded", () => {
6985
+ ctx.watchConf(["listSort", "locale"], (conf) => {
6147
6986
  const list = ctx.get("list");
6148
6987
  const $count = list.$el.querySelector(".atk-comment-count");
6149
6988
  if (!$count)
6150
6989
  return;
6151
- if (ctx.conf.listSort) {
6990
+ if (conf.listSort) {
6152
6991
  initDropdown($count);
6153
6992
  } else {
6154
6993
  removeDropdown({
@@ -6201,7 +7040,7 @@ function removeDropdown(conf) {
6201
7040
  }
6202
7041
  const TimeTicking = (ctx) => {
6203
7042
  let timer = null;
6204
- ctx.on("inited", () => {
7043
+ ctx.on("mounted", () => {
6205
7044
  timer = window.setInterval(() => {
6206
7045
  const list = ctx.get("list");
6207
7046
  list.$el.querySelectorAll("[data-atk-comment-date]").forEach((el) => {
@@ -6210,7 +7049,7 @@ const TimeTicking = (ctx) => {
6210
7049
  });
6211
7050
  }, 30 * 1e3);
6212
7051
  });
6213
- ctx.on("destroy", () => {
7052
+ ctx.on("unmounted", () => {
6214
7053
  timer && window.clearInterval(timer);
6215
7054
  });
6216
7055
  };
@@ -6219,7 +7058,7 @@ const ErrorDialog = (ctx) => {
6219
7058
  const list = ctx.get("list");
6220
7059
  setError(list.$el, null);
6221
7060
  });
6222
- ctx.on("list-error", (err) => {
7061
+ ctx.on("list-failed", (err) => {
6223
7062
  showErrorDialog({
6224
7063
  $err: ctx.get("list").$el,
6225
7064
  errMsg: err.msg,
@@ -6255,11 +7094,19 @@ const Fetch = (ctx) => {
6255
7094
  ctx.getData().setListLastFetch({
6256
7095
  params
6257
7096
  });
6258
- ctx.getApi().comment.get(params.offset, params.limit, params.flatMode, params.paramsModifier).then((data) => {
7097
+ const reqParams = {
7098
+ limit: params.limit,
7099
+ offset: params.offset,
7100
+ flat_mode: params.flatMode,
7101
+ page_key: ctx.getConf().pageKey,
7102
+ site_name: ctx.getConf().site
7103
+ };
7104
+ if (params.paramsModifier)
7105
+ params.paramsModifier(reqParams);
7106
+ ctx.getApi().comments.getComments(__spreadValues(__spreadValues({}, reqParams), ctx.getApi().getUserFields())).then(({ data }) => {
6259
7107
  ctx.getData().setListLastFetch({ params, data });
6260
7108
  ctx.getData().loadComments(data.comments);
6261
7109
  ctx.getData().updatePage(data.page);
6262
- ctx.getData().updateUnreads(data.unread || []);
6263
7110
  params.onSuccess && params.onSuccess(data);
6264
7111
  ctx.trigger("list-fetched", { params, data });
6265
7112
  }).catch((e) => {
@@ -6268,7 +7115,7 @@ const Fetch = (ctx) => {
6268
7115
  data: e.data
6269
7116
  };
6270
7117
  params.onError && params.onError(error);
6271
- ctx.trigger("list-error", error);
7118
+ ctx.trigger("list-failed", error);
6272
7119
  ctx.trigger("list-fetched", { params, error });
6273
7120
  throw e;
6274
7121
  }).finally(() => {
@@ -6277,15 +7124,19 @@ const Fetch = (ctx) => {
6277
7124
  });
6278
7125
  };
6279
7126
  const ReachBottom = (ctx) => {
6280
- const scrollEvtAt = document;
6281
7127
  let observer = null;
6282
7128
  const setupObserver = ($target) => {
7129
+ const scrollEvtAt = ctx.conf.scrollRelativeTo && ctx.conf.scrollRelativeTo() || null;
6283
7130
  observer = new IntersectionObserver(([entries]) => {
6284
7131
  if (entries.isIntersecting) {
6285
7132
  clearObserver();
6286
7133
  ctx.trigger("list-reach-bottom");
6287
7134
  }
6288
7135
  }, {
7136
+ threshold: 0.9,
7137
+ // when the target is 90% visible
7138
+ // @see https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root
7139
+ // If the root is null, then the bounds of the actual document viewport are used.
6289
7140
  root: scrollEvtAt
6290
7141
  });
6291
7142
  observer.observe($target);
@@ -6297,7 +7148,8 @@ const ReachBottom = (ctx) => {
6297
7148
  ctx.on("list-loaded", () => {
6298
7149
  clearObserver();
6299
7150
  const list = ctx.get("list");
6300
- const $target = list.getCommentsWrapEl().querySelector(".atk-comment-wrap:nth-last-child(3)");
7151
+ const children = list.getCommentsWrapEl().childNodes;
7152
+ const $target = children.length > 2 ? children[children.length - 2] : null;
6301
7153
  if (!$target)
6302
7154
  return;
6303
7155
  if (!("IntersectionObserver" in window)) {
@@ -6306,7 +7158,7 @@ const ReachBottom = (ctx) => {
6306
7158
  }
6307
7159
  setupObserver($target);
6308
7160
  });
6309
- ctx.on("destroy", () => {
7161
+ ctx.on("unmounted", () => {
6310
7162
  clearObserver();
6311
7163
  });
6312
7164
  };
@@ -6319,10 +7171,10 @@ const GotoFirst = (ctx) => {
6319
7171
  left: 0
6320
7172
  });
6321
7173
  };
6322
- ctx.on("inited", () => {
7174
+ ctx.on("mounted", () => {
6323
7175
  ctx.on("list-goto-first", handler);
6324
7176
  });
6325
- ctx.on("destroy", () => {
7177
+ ctx.on("unmounted", () => {
6326
7178
  ctx.off("list-goto-first", handler);
6327
7179
  });
6328
7180
  };
@@ -6343,14 +7195,32 @@ const ListPlugins = [
6343
7195
  ReachBottom,
6344
7196
  GotoFirst
6345
7197
  ];
7198
+ const Notifies = (ctx) => {
7199
+ ctx.on("list-fetch", (params) => {
7200
+ if (params.offset !== 0)
7201
+ return;
7202
+ const user = ctx.getApi().getUserFields();
7203
+ if (!user)
7204
+ return;
7205
+ ctx.getApi().notifies.getNotifies(user).then((res) => {
7206
+ ctx.getData().updateNotifies(res.data.notifies);
7207
+ });
7208
+ });
7209
+ };
6346
7210
  const PvCountWidget = (ctx) => {
6347
- ctx.on("conf-loaded", () => {
7211
+ ctx.watchConf([
7212
+ "site",
7213
+ "pageKey",
7214
+ "countEl",
7215
+ "pvEl"
7216
+ ], (conf) => {
6348
7217
  initCountWidget({
6349
7218
  getApi: () => ctx.getApi(),
6350
- pageKey: ctx.conf.pageKey,
6351
- countEl: ctx.conf.countEl,
6352
- pvEl: ctx.conf.pvEl,
6353
- pvAdd: true
7219
+ siteName: conf.site,
7220
+ pageKey: conf.pageKey,
7221
+ countEl: conf.countEl,
7222
+ pvEl: conf.pvEl,
7223
+ pvAdd: typeof ctx.conf.pvAdd === "boolean" ? ctx.conf.pvAdd : true
6354
7224
  });
6355
7225
  });
6356
7226
  };
@@ -6360,7 +7230,11 @@ function initCountWidget(opt) {
6360
7230
  refreshStatCount(opt, { query: "page_comment", numEl: opt.countEl });
6361
7231
  }
6362
7232
  const initialData = opt.pvAdd ? {
6363
- [opt.pageKey]: yield opt.getApi().page.pv()
7233
+ [opt.pageKey]: (yield opt.getApi().pages.logPv({
7234
+ page_key: opt.pageKey,
7235
+ page_title: opt.pageKey,
7236
+ site_name: opt.siteName
7237
+ })).data.pv
6364
7238
  // pv+1 and get pv count
6365
7239
  } : void 0;
6366
7240
  if (opt.pvEl && document.querySelector(opt.pvEl)) {
@@ -6378,7 +7252,10 @@ function refreshStatCount(opt, args) {
6378
7252
  let queryPageKeys = Array.from(document.querySelectorAll(args.numEl)).map((e) => e.getAttribute("data-page-key") || opt.pageKey).filter((k) => typeof data[k] !== "number");
6379
7253
  queryPageKeys = [...new Set(queryPageKeys)];
6380
7254
  if (queryPageKeys.length > 0) {
6381
- const res = yield opt.getApi().page.stat(args.query, queryPageKeys);
7255
+ const res = (yield opt.getApi().stats.getStats(args.query, {
7256
+ page_keys: queryPageKeys.join(","),
7257
+ site_name: opt.siteName
7258
+ })).data.data;
6382
7259
  data = __spreadValues(__spreadValues({}, data), res);
6383
7260
  }
6384
7261
  applyCountData(args.numEl, data, data[opt.pageKey]);
@@ -6393,10 +7270,10 @@ function applyCountData(selector, data, defaultCount) {
6393
7270
  }
6394
7271
  let IgnoreVersionCheck = false;
6395
7272
  const VersionCheck = (ctx) => {
6396
- ctx.on("conf-loaded", () => {
7273
+ ctx.watchConf(["apiVersion", "versionCheck"], (conf) => {
6397
7274
  const list = ctx.get("list");
6398
- if (ctx.conf.apiVersion && ctx.conf.versionCheck && !IgnoreVersionCheck)
6399
- versionCheck(list, version, ctx.conf.apiVersion);
7275
+ if (conf.apiVersion && conf.versionCheck && !IgnoreVersionCheck)
7276
+ versionCheck(list, version, conf.apiVersion);
6400
7277
  });
6401
7278
  };
6402
7279
  function versionCheck(list, feVer, beVer) {
@@ -6476,10 +7353,9 @@ const DarkMode = (ctx) => {
6476
7353
  updateClassnames($els, darkMode);
6477
7354
  }
6478
7355
  };
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", () => {
7356
+ ctx.watchConf(["darkMode"], (conf) => sync(conf.darkMode));
7357
+ ctx.on("created", () => sync(ctx.conf.darkMode));
7358
+ ctx.on("unmounted", () => {
6483
7359
  darkModeAutoHandler && (darkModeMedia == null ? void 0 : darkModeMedia.removeEventListener("change", darkModeAutoHandler));
6484
7360
  darkModeAutoHandler = void 0;
6485
7361
  });
@@ -6490,6 +7366,7 @@ const DefaultPlugins = [
6490
7366
  EditorKit,
6491
7367
  AdminOnlyElem,
6492
7368
  ...ListPlugins,
7369
+ Notifies,
6493
7370
  PvCountWidget,
6494
7371
  VersionCheck,
6495
7372
  DarkMode
@@ -6497,15 +7374,11 @@ const DefaultPlugins = [
6497
7374
  const GlobalPlugins = [...DefaultPlugins];
6498
7375
  class Artalk {
6499
7376
  constructor(conf) {
6500
- __publicField(this, "conf");
6501
7377
  __publicField(this, "ctx");
6502
- __publicField(this, "$root");
6503
7378
  /** Plugins */
6504
7379
  __publicField(this, "plugins", [...GlobalPlugins]);
6505
- this.conf = handelCustomConf(conf);
6506
- if (this.conf.el instanceof HTMLElement)
6507
- this.$root = this.conf.el;
6508
- this.ctx = new Context(this.conf, this.$root);
7380
+ const handledConf = handelCustomConf(conf, true);
7381
+ this.ctx = new Context(handledConf);
6509
7382
  Object.entries(services).forEach(([name, initService]) => {
6510
7383
  const obj = initService(this.ctx);
6511
7384
  if (obj)
@@ -6515,7 +7388,15 @@ class Artalk {
6515
7388
  if (typeof plugin === "function")
6516
7389
  plugin(this.ctx);
6517
7390
  });
6518
- this.ctx.trigger("inited");
7391
+ this.ctx.trigger("created");
7392
+ }
7393
+ /** Get the config of Artalk */
7394
+ getConf() {
7395
+ return this.ctx.getConf();
7396
+ }
7397
+ /** Get the root element of Artalk */
7398
+ getEl() {
7399
+ return this.ctx.$root;
6519
7400
  }
6520
7401
  /** Update config of Artalk */
6521
7402
  update(conf) {
@@ -6528,8 +7409,8 @@ class Artalk {
6528
7409
  }
6529
7410
  /** Destroy instance of Artalk */
6530
7411
  destroy() {
6531
- this.ctx.trigger("destroy");
6532
- this.$root.remove();
7412
+ this.ctx.trigger("unmounted");
7413
+ this.ctx.$root.remove();
6533
7414
  }
6534
7415
  /** Add an event listener */
6535
7416
  on(name, handler) {
@@ -6562,27 +7443,35 @@ class Artalk {
6562
7443
  }
6563
7444
  /** Load count widget */
6564
7445
  static loadCountWidget(c) {
6565
- const conf = handelCustomConf(c);
7446
+ const conf = handelCustomConf(c, true);
6566
7447
  initCountWidget({
6567
- getApi: () => new Api(convertApiOptions(conf)),
7448
+ getApi: () => new Api2(convertApiOptions(conf)),
7449
+ siteName: conf.site,
6568
7450
  pageKey: conf.pageKey,
6569
7451
  countEl: conf.countEl,
6570
7452
  pvEl: conf.pvEl,
6571
7453
  pvAdd: false
6572
7454
  });
6573
7455
  }
7456
+ // ===========================
7457
+ // Deprecated
7458
+ // ===========================
7459
+ /** @deprecated Please use `getEl()` instead */
7460
+ get $root() {
7461
+ return this.ctx.$root;
7462
+ }
7463
+ /** @description Please use `getConf()` instead */
7464
+ get conf() {
7465
+ return this.ctx.getConf();
7466
+ }
6574
7467
  }
6575
- const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
6576
- __proto__: null
6577
- }, Symbol.toStringTag, { value: "Module" }));
6578
7468
  const init = Artalk.init;
6579
7469
  const use = Artalk.use;
6580
7470
  const loadCountWidget = Artalk.loadCountWidget;
6581
7471
  export {
6582
- index as ArtalkType,
6583
7472
  Artalk as default,
6584
7473
  init,
6585
7474
  loadCountWidget,
6586
7475
  use
6587
7476
  };
6588
- //# sourceMappingURL=ArtalkLite.es.js.map
7477
+ //# sourceMappingURL=ArtalkLite.mjs.map