@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.
- package/LICENSE +339 -0
- package/dist/api.cjs +2 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +1 -0
- package/dist/api.d.mts +1 -0
- package/dist/api.d.ts +1 -0
- package/dist/api.mjs +2 -0
- package/dist/api.mjs.map +1 -0
- package/dist/comment.cjs +2 -0
- package/dist/comment.cjs.map +1 -0
- package/dist/comment.d.cts +39 -0
- package/dist/comment.d.mts +39 -0
- package/dist/comment.d.ts +39 -0
- package/dist/comment.js +2 -0
- package/dist/comment.js.map +1 -0
- package/dist/comment.mjs +2 -0
- package/dist/comment.mjs.map +1 -0
- package/dist/component.mjs +1 -1
- package/dist/component.mjs.map +1 -1
- package/dist/legacy.umd.js +1 -1
- package/dist/legacy.umd.js.map +1 -1
- package/dist/pageview.cjs +1 -1
- package/dist/pageview.cjs.map +1 -1
- package/dist/pageview.js +1 -1
- package/dist/pageview.js.map +1 -1
- package/dist/pageview.mjs +1 -1
- package/dist/pageview.mjs.map +1 -1
- package/dist/shim.cjs +1 -1
- package/dist/shim.cjs.map +1 -1
- package/dist/shim.mjs +1 -1
- package/dist/shim.mjs.map +1 -1
- package/dist/waline-meta.css +1 -1
- package/dist/waline-meta.css.map +1 -1
- package/dist/waline.cjs +1 -1
- package/dist/waline.cjs.map +1 -1
- package/dist/waline.css +1 -1
- package/dist/waline.css.map +1 -1
- package/dist/waline.js +1 -1
- package/dist/waline.js.map +1 -1
- package/dist/waline.mjs +1 -1
- package/dist/waline.mjs.map +1 -1
- package/package.json +34 -13
- package/src/api/articleCounter.ts +53 -0
- package/src/api/comment.ts +147 -0
- package/src/api/commentCount.ts +30 -0
- package/src/api/index.ts +6 -0
- package/src/api/login.ts +53 -0
- package/src/api/pageview.ts +41 -0
- package/src/api/recentComment.ts +29 -0
- package/src/api/utils.ts +23 -0
- package/src/comment.ts +2 -10
- package/src/components/ArticleReaction.vue +18 -30
- package/src/components/CommentBox.vue +23 -48
- package/src/components/Waline.vue +9 -9
- package/src/composables/index.ts +3 -1
- package/src/composables/recaptchaV3.ts +23 -0
- package/src/composables/userInfo.ts +1 -12
- package/src/entrys/api.ts +1 -0
- package/src/entrys/comment.ts +2 -0
- package/src/init.ts +0 -11
- package/src/pageview.ts +2 -7
- package/src/styles/card.scss +1 -1
- package/src/styles/helpers/_svg.scss +12 -12
- package/src/styles/index.scss +1 -1
- package/src/styles/meta.scss +10 -14
- package/src/styles/reaction.scss +24 -18
- package/src/utils/config.ts +3 -3
- package/src/utils/index.ts +0 -1
- package/src/widgets/recentComments.ts +2 -1
- package/src/components/RecaptchaV3/IReCaptchaOptions.ts +0 -6
- package/src/components/RecaptchaV3/README.md +0 -3
- package/src/components/RecaptchaV3/RecaptchaVuePlugin.ts +0 -86
- 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
|
-
}
|
package/src/utils/fetch.ts
DELETED
|
@@ -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
|
-
});
|