@waline/client 2.11.1 → 2.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +339 -0
  2. package/dist/api.cjs +2 -0
  3. package/dist/api.cjs.map +1 -0
  4. package/dist/api.d.cts +1 -0
  5. package/dist/api.d.mts +1 -0
  6. package/dist/api.d.ts +1 -0
  7. package/dist/api.mjs +2 -0
  8. package/dist/api.mjs.map +1 -0
  9. package/dist/comment.cjs +2 -0
  10. package/dist/comment.cjs.map +1 -0
  11. package/dist/comment.d.cts +39 -0
  12. package/dist/comment.d.mts +39 -0
  13. package/dist/comment.d.ts +39 -0
  14. package/dist/comment.js +2 -0
  15. package/dist/comment.js.map +1 -0
  16. package/dist/comment.mjs +2 -0
  17. package/dist/comment.mjs.map +1 -0
  18. package/dist/component.mjs +1 -1
  19. package/dist/component.mjs.map +1 -1
  20. package/dist/legacy.umd.js +1 -1
  21. package/dist/legacy.umd.js.map +1 -1
  22. package/dist/pageview.cjs +1 -1
  23. package/dist/pageview.cjs.map +1 -1
  24. package/dist/pageview.js +1 -1
  25. package/dist/pageview.js.map +1 -1
  26. package/dist/pageview.mjs +1 -1
  27. package/dist/pageview.mjs.map +1 -1
  28. package/dist/shim.cjs +1 -1
  29. package/dist/shim.cjs.map +1 -1
  30. package/dist/shim.mjs +1 -1
  31. package/dist/shim.mjs.map +1 -1
  32. package/dist/waline-meta.css +1 -1
  33. package/dist/waline-meta.css.map +1 -1
  34. package/dist/waline.cjs +1 -1
  35. package/dist/waline.cjs.map +1 -1
  36. package/dist/waline.css +1 -1
  37. package/dist/waline.css.map +1 -1
  38. package/dist/waline.js +1 -1
  39. package/dist/waline.js.map +1 -1
  40. package/dist/waline.mjs +1 -1
  41. package/dist/waline.mjs.map +1 -1
  42. package/package.json +34 -13
  43. package/src/api/articleCounter.ts +53 -0
  44. package/src/api/comment.ts +147 -0
  45. package/src/api/commentCount.ts +30 -0
  46. package/src/api/index.ts +6 -0
  47. package/src/api/login.ts +53 -0
  48. package/src/api/pageview.ts +41 -0
  49. package/src/api/recentComment.ts +29 -0
  50. package/src/api/utils.ts +23 -0
  51. package/src/comment.ts +2 -10
  52. package/src/components/ArticleReaction.vue +18 -30
  53. package/src/components/CommentBox.vue +23 -48
  54. package/src/components/Waline.vue +9 -9
  55. package/src/composables/index.ts +3 -1
  56. package/src/composables/recaptchaV3.ts +23 -0
  57. package/src/composables/userInfo.ts +1 -12
  58. package/src/entrys/api.ts +1 -0
  59. package/src/entrys/comment.ts +2 -0
  60. package/src/init.ts +0 -11
  61. package/src/pageview.ts +2 -7
  62. package/src/styles/card.scss +1 -1
  63. package/src/styles/helpers/_svg.scss +12 -12
  64. package/src/styles/index.scss +1 -1
  65. package/src/styles/meta.scss +10 -14
  66. package/src/styles/reaction.scss +24 -18
  67. package/src/utils/config.ts +3 -3
  68. package/src/utils/index.ts +0 -1
  69. package/src/widgets/recentComments.ts +2 -1
  70. package/src/components/RecaptchaV3/IReCaptchaOptions.ts +0 -6
  71. package/src/components/RecaptchaV3/README.md +0 -3
  72. package/src/components/RecaptchaV3/RecaptchaVuePlugin.ts +0 -86
  73. package/src/utils/fetch.ts +0 -310
@@ -1,86 +0,0 @@
1
- import { load as loadReCaptcha, ReCaptchaInstance } from 'recaptcha-v3';
2
- import { App, Ref, ref, inject, InjectionKey } from 'vue';
3
- import { IReCaptchaOptions } from './IReCaptchaOptions'
4
-
5
- const VueReCaptchaInjectKey: InjectionKey<IReCaptchaComposition> = Symbol(
6
- 'VueReCaptchaInjectKey'
7
- );
8
-
9
- interface IGlobalConfig {
10
- loadedWaiters: Array<{
11
- resolve: (resolve: boolean) => void;
12
- reject: (reject: Error) => void;
13
- }>;
14
- error: Error | null;
15
- }
16
- const globalConfig: IGlobalConfig = {
17
- loadedWaiters: [],
18
- error: null,
19
- };
20
-
21
- export const VueReCaptcha = {
22
- install(app: App, options: IReCaptchaOptions): void {
23
- const isLoaded = ref(false);
24
- const instance: Ref<ReCaptchaInstance | undefined> = ref(undefined);
25
-
26
- app.config.globalProperties.$recaptchaLoaded = recaptchaLoaded(isLoaded);
27
-
28
- initializeReCaptcha(options)
29
- .then((wrapper) => {
30
- isLoaded.value = true;
31
- instance.value = wrapper;
32
-
33
- app.config.globalProperties.$recaptcha = recaptcha(instance);
34
- app.config.globalProperties.$recaptchaInstance = instance;
35
-
36
- globalConfig.loadedWaiters.forEach((v) => v.resolve(true));
37
- })
38
- .catch((error: Error) => {
39
- globalConfig.error = error;
40
- globalConfig.loadedWaiters.forEach((v) => v.reject(error));
41
- });
42
-
43
- app.provide(VueReCaptchaInjectKey, {
44
- instance,
45
- isLoaded,
46
- executeRecaptcha: recaptcha(instance),
47
- recaptchaLoaded: recaptchaLoaded(isLoaded),
48
- });
49
- },
50
- };
51
-
52
- export function useReCaptcha(): IReCaptchaComposition | undefined {
53
- return inject(VueReCaptchaInjectKey);
54
- }
55
-
56
- async function initializeReCaptcha(
57
- options: IReCaptchaOptions
58
- ): Promise<ReCaptchaInstance> {
59
- return await loadReCaptcha(options.siteKey, options.loaderOptions)
60
- }
61
-
62
- function recaptchaLoaded(isLoaded: Ref<boolean>) {
63
- return (): Promise<boolean> =>
64
- new Promise<boolean>((resolve, reject) => {
65
- if (globalConfig.error !== null) {
66
- return reject(globalConfig.error);
67
- }
68
- if (isLoaded.value) {
69
- return resolve(true);
70
- }
71
- globalConfig.loadedWaiters.push({ resolve, reject });
72
- });
73
- }
74
-
75
- function recaptcha(instance: Ref<ReCaptchaInstance | undefined>) {
76
- return async (action: string): Promise<string | undefined> => {
77
- return await instance.value?.execute(action);
78
- };
79
- }
80
-
81
- export interface IReCaptchaComposition {
82
- isLoaded: Ref<boolean>;
83
- instance: Ref<ReCaptchaInstance | undefined>;
84
- executeRecaptcha: (action: string) => Promise<string>;
85
- recaptchaLoaded: () => Promise<boolean>;
86
- }
@@ -1,310 +0,0 @@
1
- import type { WalineComment, WalineCommentData } from '../typings';
2
-
3
- export interface FetchErrorData {
4
- errno: number;
5
- errmsg: string;
6
- }
7
-
8
- const JSON_HEADERS: Record<string, string> = {
9
- // eslint-disable-next-line @typescript-eslint/naming-convention
10
- 'Content-Type': 'application/json',
11
- };
12
-
13
- const errorCheck = <T = unknown>(data: T | FetchErrorData, name = ''): T => {
14
- if (typeof data === 'object' && (data as FetchErrorData).errno)
15
- throw new TypeError(
16
- `Fetch ${name} failed with ${(data as FetchErrorData).errno}: ${(data as FetchErrorData).errmsg
17
- }`
18
- );
19
-
20
- return data as T;
21
- };
22
-
23
- export interface FetchCountOptions {
24
- serverURL: string;
25
- lang: string;
26
- paths: string[];
27
- signal: AbortSignal;
28
- token?: string;
29
- }
30
-
31
- export const fetchCommentCount = ({
32
- serverURL,
33
- lang,
34
- paths,
35
- signal,
36
- token,
37
- }: FetchCountOptions): Promise<number[]> => {
38
- const headers: Record<string, string> = {};
39
-
40
- if (token) headers.Authorization = `Bearer ${token}`;
41
-
42
- return (
43
- fetch(
44
- `${serverURL}/comment?type=count&url=${encodeURIComponent(
45
- paths.join(',')
46
- )}&lang=${lang}`,
47
- { signal, headers }
48
- )
49
- .then((resp) => resp.json() as Promise<number | number[]>)
50
- .then((data) => errorCheck(data, 'comment count'))
51
- // TODO: Improve this API
52
- .then((counts) => (Array.isArray(counts) ? counts : [counts]))
53
- );
54
- };
55
- export interface FetchRecentOptions {
56
- serverURL: string;
57
- lang: string;
58
- count: number;
59
- signal: AbortSignal;
60
- token?: string;
61
- }
62
-
63
- export const fetchRecentComment = ({
64
- serverURL,
65
- lang,
66
- count,
67
- signal,
68
- token,
69
- }: FetchRecentOptions): Promise<WalineComment[]> => {
70
- const headers: Record<string, string> = {};
71
-
72
- if (token) headers.Authorization = `Bearer ${token}`;
73
-
74
- return fetch(`${serverURL}/comment?type=recent&count=${count}&lang=${lang}`, {
75
- signal,
76
- headers,
77
- })
78
- .then((resp) => resp.json() as Promise<WalineComment[]>)
79
- .then((data) => errorCheck(data, 'recent comment'));
80
- };
81
-
82
- export interface FetchListOptions {
83
- serverURL: string;
84
- path: string;
85
- page: number;
86
- pageSize: number;
87
- sortBy: string;
88
- signal: AbortSignal;
89
- token?: string;
90
- lang: string;
91
- }
92
-
93
- export interface FetchListResult {
94
- count: number;
95
- data: WalineComment[];
96
- totalPages: number;
97
- }
98
-
99
- export const fetchCommentList = ({
100
- serverURL,
101
- lang,
102
- path,
103
- page,
104
- pageSize,
105
- sortBy,
106
- signal,
107
- token,
108
- }: FetchListOptions): Promise<FetchListResult> => {
109
- const headers: Record<string, string> = {};
110
-
111
- if (token) headers.Authorization = `Bearer ${token}`;
112
-
113
- return fetch(
114
- `${serverURL}/comment?path=${encodeURIComponent(
115
- path
116
- )}&pageSize=${pageSize}&page=${page}&lang=${lang}&sortBy=${sortBy}`,
117
- { signal, headers }
118
- )
119
- .then((resp) => resp.json() as Promise<FetchListResult>)
120
- .then((data) => errorCheck(data, 'comment list'));
121
- };
122
-
123
- export interface PostCommentOptions {
124
- serverURL: string;
125
- lang: string;
126
- token?: string;
127
- comment: WalineCommentData;
128
- }
129
-
130
- export interface PostCommentResponse {
131
- data?: WalineComment;
132
- errmsg?: string;
133
- }
134
-
135
- export const postComment = ({
136
- serverURL,
137
- lang,
138
- token,
139
- comment,
140
- }: PostCommentOptions): Promise<PostCommentResponse> => {
141
- const headers: Record<string, string> = {
142
- // eslint-disable-next-line @typescript-eslint/naming-convention
143
- 'Content-Type': 'application/json',
144
- };
145
-
146
- if (token) headers.Authorization = `Bearer ${token}`;
147
-
148
- if (comment.eid) {
149
- return fetch(`${serverURL}/comment/${comment.eid}?lang=${lang}`, {
150
- method: 'PUT',
151
- headers,
152
- body: JSON.stringify(comment),
153
- }).then((resp) => resp.json() as Promise<PostCommentResponse>);
154
- }
155
-
156
- return fetch(`${serverURL}/comment?lang=${lang}`, {
157
- method: 'POST',
158
- headers,
159
- body: JSON.stringify(comment),
160
- }).then((resp) => resp.json() as Promise<PostCommentResponse>);
161
- };
162
-
163
- export interface DeleteCommentOptions {
164
- serverURL: string;
165
- lang: string;
166
- token: string;
167
- objectId: string | number;
168
- }
169
-
170
- export const deleteComment = ({
171
- serverURL,
172
- lang,
173
- token,
174
- objectId,
175
- }: DeleteCommentOptions): Promise<void> => {
176
- const headers: Record<string, string> = {
177
- Authorization: `Bearer ${token}`,
178
- };
179
-
180
- return fetch(`${serverURL}/comment/${objectId}?lang=${lang}`, {
181
- method: 'DELETE',
182
- headers,
183
- }).then((resp) => resp.json() as Promise<void>);
184
- };
185
-
186
- export interface LikeCommentOptions {
187
- serverURL: string;
188
- lang: string;
189
- objectId: number | string;
190
- like: boolean;
191
- }
192
-
193
- export const likeComment = ({
194
- serverURL,
195
- lang,
196
- objectId,
197
- like,
198
- }: LikeCommentOptions): Promise<void> =>
199
- fetch(`${serverURL}/comment/${objectId}?lang=${lang}`, {
200
- method: 'PUT',
201
- headers: JSON_HEADERS,
202
- body: JSON.stringify({ like }),
203
- }).then((resp) => resp.json() as Promise<void>);
204
-
205
- export interface UpdateCommentOptions {
206
- serverURL: string;
207
- lang: string;
208
- token: string;
209
- objectId: number | string;
210
- status?: 'approved' | 'waiting' | 'spam';
211
- sticky?: number;
212
- }
213
-
214
- export const updateComment = ({
215
- serverURL,
216
- lang,
217
- token,
218
- objectId,
219
- ...data
220
- }: UpdateCommentOptions): Promise<void> => {
221
- const headers: Record<string, string> = {
222
- // eslint-disable-next-line @typescript-eslint/naming-convention
223
- 'Content-Type': 'application/json',
224
- Authorization: `Bearer ${token}`,
225
- };
226
-
227
- return fetch(`${serverURL}/comment/${objectId}?lang=${lang}`, {
228
- method: 'PUT',
229
- headers,
230
- body: JSON.stringify(data),
231
- }).then((resp) => resp.json() as Promise<void>);
232
- };
233
-
234
- export interface FetchArticleCounterOptions {
235
- serverURL: string;
236
- lang: string;
237
- paths: string[];
238
- type: string[];
239
- signal: AbortSignal;
240
- }
241
-
242
- export const fetchArticleCounter = ({
243
- serverURL,
244
- lang,
245
- paths,
246
- type,
247
- signal,
248
- }: FetchArticleCounterOptions): Promise<
249
- Record<string, number>[] | Record<string, number> | number[] | number
250
- > =>
251
- fetch(
252
- `${serverURL}/article?path=${encodeURIComponent(
253
- paths.join(',')
254
- )}&type=${encodeURIComponent(type.join(','))}&lang=${lang}`,
255
- { signal }
256
- )
257
- .then(
258
- (resp) =>
259
- resp.json() as Promise<Record<string, number>[] | number[] | number>
260
- )
261
- .then((data) => errorCheck(data, 'article count'));
262
-
263
- export const fetchPageviews = ({
264
- serverURL,
265
- lang,
266
- paths,
267
- signal,
268
- }: Omit<FetchArticleCounterOptions, 'type'>): Promise<number[]> =>
269
- fetchArticleCounter({
270
- serverURL,
271
- lang,
272
- paths,
273
- type: ['time'],
274
- signal,
275
- })
276
- // TODO: Improve this API
277
- .then((counts) => (Array.isArray(counts) ? counts : [counts])) as Promise<
278
- number[]
279
- >;
280
-
281
- export interface UpdateArticleCounterOptions {
282
- serverURL: string;
283
- lang: string;
284
- path: string;
285
- type: string;
286
- action?: 'inc' | 'desc';
287
- }
288
-
289
- export const updateArticleCounter = ({
290
- serverURL,
291
- lang,
292
- path,
293
- type,
294
- action,
295
- }: UpdateArticleCounterOptions): Promise<number> =>
296
- fetch(`${serverURL}/article?lang=${lang}`, {
297
- method: 'POST',
298
- headers: JSON_HEADERS,
299
- body: JSON.stringify({ path, type, action }),
300
- })
301
- .then((resp) => resp.json() as Promise<number>)
302
- .then((data) => errorCheck(data, 'article count'));
303
-
304
- export const updatePageviews = (
305
- options: Omit<UpdateArticleCounterOptions, 'type'>
306
- ): Promise<number> =>
307
- updateArticleCounter({
308
- ...options,
309
- type: 'time',
310
- });