@waline/client 2.11.2 → 2.12.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 (51) hide show
  1. package/dist/api.cjs +1 -1
  2. package/dist/api.cjs.map +1 -1
  3. package/dist/api.d.cts +194 -0
  4. package/dist/api.d.mts +194 -0
  5. package/dist/api.d.ts +194 -0
  6. package/dist/api.mjs +1 -1
  7. package/dist/api.mjs.map +1 -1
  8. package/dist/comment.cjs +1 -1
  9. package/dist/comment.cjs.map +1 -1
  10. package/dist/comment.js +1 -1
  11. package/dist/comment.js.map +1 -1
  12. package/dist/comment.mjs +1 -1
  13. package/dist/comment.mjs.map +1 -1
  14. package/dist/component.mjs +1 -1
  15. package/dist/component.mjs.map +1 -1
  16. package/dist/legacy.umd.d.ts +57 -30
  17. package/dist/legacy.umd.js +1 -1
  18. package/dist/legacy.umd.js.map +1 -1
  19. package/dist/pageview.cjs +1 -1
  20. package/dist/pageview.cjs.map +1 -1
  21. package/dist/pageview.js +1 -1
  22. package/dist/pageview.js.map +1 -1
  23. package/dist/pageview.mjs +1 -1
  24. package/dist/pageview.mjs.map +1 -1
  25. package/dist/shim.cjs +1 -1
  26. package/dist/shim.cjs.map +1 -1
  27. package/dist/shim.d.cts +58 -31
  28. package/dist/shim.d.mts +58 -31
  29. package/dist/shim.mjs +1 -1
  30. package/dist/shim.mjs.map +1 -1
  31. package/dist/waline.cjs +1 -1
  32. package/dist/waline.cjs.map +1 -1
  33. package/dist/waline.d.cts +58 -31
  34. package/dist/waline.d.mts +58 -31
  35. package/dist/waline.d.ts +58 -31
  36. package/dist/waline.js +1 -1
  37. package/dist/waline.js.map +1 -1
  38. package/dist/waline.mjs +1 -1
  39. package/dist/waline.mjs.map +1 -1
  40. package/package.json +22 -20
  41. package/src/compact/convert.ts +2 -2
  42. package/src/components/ArticleReaction.vue +36 -24
  43. package/src/components/CommentBox.vue +6 -5
  44. package/src/components/ImageWall.vue +7 -2
  45. package/src/composables/vote.ts +5 -2
  46. package/src/config/default.ts +45 -83
  47. package/src/entrys/api.ts +1 -1
  48. package/src/typings/base.ts +33 -7
  49. package/src/typings/locale.ts +37 -23
  50. package/src/utils/config.ts +10 -4
  51. package/LICENSE +0 -339
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waline/client",
3
- "version": "2.11.2",
3
+ "version": "2.12.0",
4
4
  "description": "client for waline comment system",
5
5
  "keywords": [
6
6
  "valine",
@@ -93,6 +93,17 @@
93
93
  "dist",
94
94
  "src"
95
95
  ],
96
+ "scripts": {
97
+ "build": "pnpm rollup && pnpm style",
98
+ "clean": "rimraf ./dist",
99
+ "dev": "vite -c config/vite.config.js",
100
+ "lint": "eslint --ext .ts,.vue .",
101
+ "prepublishOnly": "pnpm clean && pnpm build",
102
+ "rollup": "rollup -c ./config/rollup.config.js",
103
+ "style": "pnpm style:main && pnpm style:meta",
104
+ "style:main": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed",
105
+ "style:meta": "sass ./src/styles/meta.scss ./dist/waline-meta.css --style=compressed"
106
+ },
96
107
  "browserslist": {
97
108
  "production": [
98
109
  ">0.5%",
@@ -108,21 +119,22 @@
108
119
  ]
109
120
  },
110
121
  "dependencies": {
111
- "@vueuse/core": "^9.2.0",
122
+ "@vueuse/core": "^9.3.0",
112
123
  "autosize": "^5.0.1",
113
- "marked": "^4.1.0",
114
- "vue": "^3.2.39"
124
+ "marked": "^4.1.1",
125
+ "vue": "^3.2.40"
115
126
  },
116
127
  "devDependencies": {
117
- "@babel/core": "7.19.1",
118
- "@babel/preset-env": "7.19.1",
128
+ "@babel/core": "7.19.3",
129
+ "@babel/preset-env": "7.19.3",
130
+ "@giphy/js-types": "4.2.1",
119
131
  "@rollup/plugin-babel": "5.3.1",
120
132
  "@rollup/plugin-commonjs": "22.0.2",
121
133
  "@rollup/plugin-node-resolve": "14.1.0",
122
134
  "@rollup/plugin-replace": "4.0.0",
123
135
  "@types/autosize": "4.0.1",
124
136
  "@types/marked": "4.0.7",
125
- "@types/node": "18.7.21",
137
+ "@types/node": "18.7.23",
126
138
  "@vitejs/plugin-vue": "3.1.0",
127
139
  "recaptcha-v3": "1.10.0",
128
140
  "rimraf": "3.0.2",
@@ -130,20 +142,10 @@
130
142
  "rollup-plugin-dts": "4.2.2",
131
143
  "rollup-plugin-terser": "7.0.2",
132
144
  "rollup-plugin-ts": "3.0.2",
133
- "typescript": "4.8.3",
134
- "vite": "3.1.3"
145
+ "typescript": "4.8.4",
146
+ "vite": "3.1.4"
135
147
  },
136
148
  "engines": {
137
149
  "node": ">=14"
138
- },
139
- "scripts": {
140
- "build": "pnpm rollup && pnpm style",
141
- "clean": "rimraf ./dist",
142
- "dev": "vite -c config/vite.config.js",
143
- "lint": "eslint --ext .ts,.vue .",
144
- "rollup": "rollup -c ./config/rollup.config.js",
145
- "style": "pnpm style:main && pnpm style:meta",
146
- "style:main": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed",
147
- "style:meta": "sass ./src/styles/meta.scss ./dist/waline-meta.css --style=compressed"
148
150
  }
149
- }
151
+ }
@@ -1,11 +1,11 @@
1
1
  import { warning } from './logger';
2
2
  import { resolveOldEmojiMap } from './valine';
3
-
4
- import type { DeprecatedValineOptions } from './valine';
5
3
  import {
6
4
  DROPPED_OPTIONS_WHICH_CAN_NOT_BE_POLYFILLED,
7
5
  DROPPED_OPTIONS_WHICH_CAN_STILL_BE_POLYFILLED,
8
6
  } from './dropped';
7
+
8
+ import type { DeprecatedValineOptions } from './valine';
9
9
  import type { DeprecatedWalineOptions } from './v1';
10
10
  import type { WalineInitOptions } from '../typings';
11
11
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div v-if="reaction && reaction.length" class="wl-reaction">
2
+ <div v-if="reaction.length" class="wl-reaction">
3
3
  <h4 v-text="locale.reactionTitle" />
4
4
  <ul>
5
5
  <li
@@ -29,7 +29,7 @@ import {
29
29
  ref,
30
30
  } from 'vue';
31
31
  import { fetchArticleCounter, updateArticleCounter } from '../api';
32
- import { useVoteStorage } from '../composables';
32
+ import { VOTE_IDENTIFIER, VOTE_INDEX, useVoteStorage } from '../composables';
33
33
  import type { WalineConfig } from '../utils';
34
34
  import type { WalineLocale } from '../typings';
35
35
 
@@ -49,42 +49,48 @@ export default defineComponent({
49
49
  const reaction = computed((): ReactionItem[] => {
50
50
  const { reaction, path } = config.value;
51
51
 
52
- return (Array.isArray(reaction) ? reaction : []).map((icon, index) => ({
52
+ return reaction.map((icon, index) => ({
53
53
  icon,
54
54
  vote: votes.value[index] || 0,
55
55
  desc: locale.value[`reaction${index}` as keyof WalineLocale],
56
56
  active: Boolean(
57
- voteStorage.value.find(({ u, i }) => u === path && i === index)
57
+ voteStorage.value.find(
58
+ ({ [VOTE_IDENTIFIER]: voteIdentifier, [VOTE_INDEX]: voteIndex }) =>
59
+ voteIdentifier === path && voteIndex === index
60
+ )
58
61
  ),
59
62
  }));
60
63
  });
61
64
 
62
- const controller = new AbortController();
65
+ let abort: () => void;
63
66
 
64
- const fetchCounter = async (): Promise<void> => {
67
+ const fetchCounter = (): void => {
65
68
  const { serverURL, lang, path, reaction } = config.value;
66
69
 
67
- if (!Array.isArray(reaction)) {
68
- return;
69
- }
70
-
71
- const resp = await fetchArticleCounter({
72
- serverURL,
73
- lang,
74
- paths: [path],
75
- type: reaction.map((_, k) => `reaction${k}`),
76
- signal: controller.signal,
77
- });
70
+ if (reaction.length) {
71
+ const controller = new AbortController();
78
72
 
79
- if (Array.isArray(resp) || typeof resp === 'number') return;
73
+ fetchArticleCounter({
74
+ serverURL,
75
+ lang,
76
+ paths: [path],
77
+ type: reaction.map((_, k) => `reaction${k}`),
78
+ signal: controller.signal,
79
+ }).then((resp) => {
80
+ if (Array.isArray(resp) || typeof resp === 'number') return;
81
+ votes.value = reaction.map((_, k) => resp[`reaction${k}`]);
82
+ });
80
83
 
81
- votes.value = reaction.map((_, k) => resp[`reaction${k}`]);
84
+ abort = controller.abort.bind(controller);
85
+ }
82
86
  };
83
87
 
84
88
  const vote = async (index: number): Promise<void> => {
85
89
  const { serverURL, lang, path } = config.value;
86
- const hasVoted = voteStorage.value.find(({ u }) => u === path);
87
- const hasVotedTheReaction = hasVoted && hasVoted.i === index;
90
+ const hasVoted = voteStorage.value.find(
91
+ ({ [VOTE_IDENTIFIER]: voteIdentifier }) => voteIdentifier === path
92
+ );
93
+ const hasVotedTheReaction = hasVoted && hasVoted[VOTE_INDEX] === index;
88
94
 
89
95
  if (hasVotedTheReaction) return;
90
96
 
@@ -97,7 +103,10 @@ export default defineComponent({
97
103
 
98
104
  votes.value[index] = (votes.value[index] || 0) + 1;
99
105
  if (hasVoted) {
100
- votes.value[hasVoted.i] = Math.max(votes.value[hasVoted.i] - 1, 0);
106
+ votes.value[hasVoted[VOTE_INDEX]] = Math.max(
107
+ votes.value[hasVoted[VOTE_INDEX]] - 1,
108
+ 0
109
+ );
101
110
  updateArticleCounter({
102
111
  serverURL,
103
112
  lang,
@@ -109,7 +118,10 @@ export default defineComponent({
109
118
  hasVoted.i = index;
110
119
  voteStorage.value = Array.from(voteStorage.value);
111
120
  } else {
112
- voteStorage.value = [...voteStorage.value, { u: path, i: index }];
121
+ voteStorage.value = [
122
+ ...voteStorage.value,
123
+ { [VOTE_IDENTIFIER]: path, [VOTE_INDEX]: index },
124
+ ];
113
125
  }
114
126
 
115
127
  if (voteStorage.value.length > 50)
@@ -117,7 +129,7 @@ export default defineComponent({
117
129
  };
118
130
 
119
131
  onMounted(() => fetchCounter());
120
- onUnmounted(() => controller.abort());
132
+ onUnmounted(() => abort?.());
121
133
 
122
134
  return {
123
135
  reaction,
@@ -368,7 +368,7 @@ export default defineComponent({
368
368
 
369
369
  const searchResults = reactive({
370
370
  loading: true,
371
- list: [] as WalineSearchResult[],
371
+ list: [] as WalineSearchResult,
372
372
  });
373
373
 
374
374
  const wordLimit = ref(0);
@@ -624,11 +624,12 @@ export default defineComponent({
624
624
 
625
625
  searchResults.loading = true;
626
626
 
627
- searchResults.list.push(
628
- ...(searchOptions.more
627
+ searchResults.list = [
628
+ ...searchResults.list,
629
+ ...(searchOptions.more && searchResults.list.length
629
630
  ? await searchOptions.more(keyword, searchResults.list.length)
630
- : await searchOptions.search(keyword))
631
- );
631
+ : await searchOptions.search(keyword)),
632
+ ];
632
633
 
633
634
  searchResults.loading = false;
634
635
 
@@ -42,7 +42,7 @@ SOFTWARE. -->
42
42
  :src="items[itemIndex].src"
43
43
  :title="items[itemIndex].title"
44
44
  loading="lazy"
45
- @load="state[items[itemIndex].src] = true"
45
+ @load="imageLoad"
46
46
  @click="$emit('insert', `![](${items[itemIndex].src})`)"
47
47
  />
48
48
  </template>
@@ -75,7 +75,7 @@ export default defineComponent({
75
75
  },
76
76
 
77
77
  props: {
78
- items: { type: Array as PropType<WalineSearchResult[]>, default: () => [] },
78
+ items: { type: Array as PropType<WalineSearchResult>, default: () => [] },
79
79
  columnWidth: { type: Number, default: 300 },
80
80
  gap: { type: Number, default: 0 },
81
81
  },
@@ -133,6 +133,10 @@ export default defineComponent({
133
133
  window.scrollTo({ top: scrollY });
134
134
  };
135
135
 
136
+ const imageLoad = (e: Event) => {
137
+ state.value[(e.target as HTMLImageElement).src] = true;
138
+ };
139
+
136
140
  watch(
137
141
  () => [props.items],
138
142
  () => {
@@ -158,6 +162,7 @@ export default defineComponent({
158
162
  columns,
159
163
  state,
160
164
  wall,
165
+ imageLoad,
161
166
  };
162
167
  },
163
168
  });
@@ -4,9 +4,12 @@ import type { Ref } from 'vue';
4
4
 
5
5
  const VOTE_KEY = 'WALINE_VOTE';
6
6
 
7
+ export const VOTE_IDENTIFIER = 'id';
8
+ export const VOTE_INDEX = 'i';
9
+
7
10
  export interface VoteLogItem {
8
- u: string;
9
- i: number;
11
+ [VOTE_IDENTIFIER]: string;
12
+ [VOTE_INDEX]: number;
10
13
  }
11
14
 
12
15
  export type VoteRef = Ref<VoteLogItem[]>;
@@ -1,4 +1,9 @@
1
- import type { WalineMeta, WalineSearchOptions } from '../typings';
1
+ import type { IGif } from '@giphy/js-types';
2
+ import type {
3
+ WalineMeta,
4
+ WalineSearchOptions,
5
+ WalineSearchResult,
6
+ } from '../typings';
2
7
 
3
8
  const availableMeta: WalineMeta[] = ['nick', 'mail', 'link'];
4
9
 
@@ -25,94 +30,51 @@ export const defaultTexRenderer = (blockMode: boolean): string =>
25
30
  ? '<p class="wl-tex">Tex is not available in preview</p>'
26
31
  : '<span class="wl-tex">Tex is not available in preview</span>';
27
32
 
28
- export const getDefaultSearchOptions = (): WalineSearchOptions => {
29
- interface FetchGifRequest {
30
- keyword: string;
31
- pos?: string;
33
+ export const getDefaultSearchOptions = (lang: string): WalineSearchOptions => {
34
+ interface Result {
35
+ meta: {
36
+ msg: string;
37
+ response_id: string;
38
+ status: number;
39
+ };
40
+ pagination: {
41
+ count: number;
42
+ total_count: number;
43
+ offset: number;
44
+ };
32
45
  }
33
-
34
- type GifFormat =
35
- | 'gif'
36
- | 'mediumgif'
37
- | 'tinygif'
38
- | 'nanogif'
39
- | 'mp4'
40
- | 'loopedmp4'
41
- | 'tinymp4'
42
- | 'nanomp4'
43
- | 'webm'
44
- | 'tinywebm'
45
- | 'nanowebm';
46
-
47
- interface MediaObject {
48
- preview: string;
49
- url: string;
50
- dims: number[];
51
- size: number;
52
- }
53
-
54
- interface GifObject {
55
- created: number;
56
- hasaudio: boolean;
57
- id: string;
58
- media: Record<GifFormat, MediaObject>[];
59
- tags: string[];
60
- title: string;
61
- itemurl: string;
62
- hascaption: boolean;
63
- url: string;
64
- }
65
-
66
- interface FetchGifResponse {
67
- next: string;
68
- results: GifObject[];
46
+ interface GifsResult extends Result {
47
+ data: IGif[];
69
48
  }
70
49
 
71
- const state = {
72
- next: '',
73
- };
74
-
75
- const fetchGif = ({
76
- keyword,
77
- pos,
78
- }: FetchGifRequest): Promise<FetchGifResponse> => {
79
- const baseUrl = `https://g.tenor.com/v1/search`;
80
- const query = new URLSearchParams('media_filter=minimal');
81
-
82
- query.set('key', 'PAY5JLFIH6V6');
83
- query.set('limit', '20');
84
- query.set('pos', pos || '');
85
- query.set('q', keyword);
86
-
87
- return fetch(`${baseUrl}?${query.toString()}`, {
88
- headers: {
89
- // eslint-disable-next-line @typescript-eslint/naming-convention
90
- 'Content-Type': 'application/json',
91
- },
92
- })
93
- .then((resp) => resp.json() as Promise<FetchGifResponse>)
94
- .catch(() => ({ next: pos || '', results: [] }));
50
+ const fetchGiphy = async (
51
+ url: string,
52
+ params: Record<string, string> = {}
53
+ ): Promise<WalineSearchResult> => {
54
+ const querystring = new URLSearchParams({
55
+ lang,
56
+ limit: '20',
57
+ rating: 'g',
58
+ api_key: '6CIMLkNMMOhRcXPoMCPkFy4Ybk2XUiMp',
59
+ ...params,
60
+ }).toString();
61
+
62
+ const resp = await fetch(
63
+ `https://api.giphy.com/v1/gifs/${url}?${querystring}`
64
+ ).then((resp) => resp.json() as Promise<GifsResult>);
65
+
66
+ return resp.data.map((gif) => ({
67
+ title: gif.title,
68
+ src: gif.images.downsized_medium.url,
69
+ }));
95
70
  };
96
71
 
97
72
  return {
98
- search: (word = '') =>
99
- fetchGif({ keyword: word }).then((resp) => {
100
- state.next = resp.next;
101
-
102
- return resp.results.map((item) => ({
103
- title: item.title,
104
- src: item.media[0].tinygif.url,
105
- }));
106
- }),
107
- more: (word) =>
108
- fetchGif({ keyword: word, pos: state.next }).then((resp) => {
109
- state.next = resp.next;
110
-
111
- return resp.results.map((item) => ({
112
- title: item.title,
113
- src: item.media[0].tinygif.url,
114
- }));
115
- }),
73
+ search: (word: string): Promise<WalineSearchResult> =>
74
+ fetchGiphy('search', { q: word, offset: '0' }),
75
+ default: (): Promise<WalineSearchResult> => fetchGiphy('trending', {}),
76
+ more: (word: string, offset = 0): Promise<WalineSearchResult> =>
77
+ fetchGiphy('search', { q: word, offset: offset.toString() }),
116
78
  };
117
79
  };
118
80
 
package/src/entrys/api.ts CHANGED
@@ -1 +1 @@
1
- export * from './api';
1
+ export * from '../api';
@@ -39,44 +39,70 @@ export interface WalineEmojiInfo {
39
39
 
40
40
  export type WalineEmojiMaps = Record<string, string>;
41
41
 
42
- export interface WalineSearchResult extends Record<string, unknown> {
42
+ export interface WalineSearchImageData extends Record<string, unknown> {
43
43
  /**
44
+ * 图片链接
45
+ *
44
46
  * Image link
45
47
  */
46
48
  src: string;
47
49
 
48
50
  /**
49
- * Image title, optional
51
+ * 图片标题
52
+ *
53
+ * @description 用于图片的 alt 属性
54
+ *
55
+ * Image title
56
+ *
57
+ * @description Used for alt attribute of image
50
58
  */
51
59
  title?: string;
52
60
 
53
61
  /**
54
- * Image preview link, optional
62
+ * 图片缩略图
63
+ *
64
+ * @description 为了更好的加载性能,我们会优先在列表中使用此缩略图
65
+ *
66
+ * Image preview link
67
+ *
68
+ * @description For better loading performance, we will use this thumbnail first in the list
55
69
  *
56
70
  * @default src
57
71
  */
58
72
  preview?: string;
59
73
  }
60
74
 
75
+ export type WalineSearchResult = WalineSearchImageData[];
76
+
61
77
  export interface WalineSearchOptions {
62
78
  /**
79
+ * 搜索操作
80
+ *
63
81
  * Search action
64
82
  */
65
- search: (word: string) => Promise<WalineSearchResult[]>;
83
+ search: (word: string) => Promise<WalineSearchResult>;
66
84
 
67
85
  /**
68
- * Default search action
86
+ * 打开列表时展示的默认结果
87
+ *
88
+ * Default result when opening list
69
89
  *
70
90
  * @default () => search('')
71
91
  */
72
- default?: () => Promise<WalineSearchResult[]>;
92
+ default?: () => Promise<WalineSearchResult>;
73
93
 
74
94
  /**
95
+ * 获取更多的操作
96
+ *
97
+ * @description 会在列表滚动到底部时触发,如果你的搜索服务支持分页功能,你应该设置此项实现无限滚动
98
+ *
75
99
  * Fetch more action
76
100
  *
101
+ * @description It will be triggered when the list scrolls to the bottom. If your search service supports paging, you should set this to achieve infinite scrolling
102
+ *
77
103
  * @default (word) => search(word)
78
104
  */
79
- more?: (word: string, currectCount: number) => Promise<WalineSearchResult[]>;
105
+ more?: (word: string, currectCount: number) => Promise<WalineSearchResult>;
80
106
  }
81
107
 
82
108
  export type WalineMeta = 'nick' | 'mail' | 'link';
@@ -8,52 +8,66 @@ export interface WalineDateLocale {
8
8
 
9
9
  export type WalineLevelLocale = Record<`level${number}`, string>;
10
10
 
11
- export interface WalineLocale extends WalineDateLocale, WalineLevelLocale {
11
+ export interface WalineReactionLocale {
12
+ reactionTitle: string;
13
+ reaction0: string;
14
+ reaction1: string;
15
+ reaction2: string;
16
+ reaction3: string;
17
+ reaction4: string;
18
+ reaction5: string;
19
+ reaction6: string;
20
+ reaction7: string;
21
+ reaction8: string;
22
+ }
23
+
24
+ export interface WalineLocale
25
+ extends WalineDateLocale,
26
+ WalineLevelLocale,
27
+ WalineReactionLocale {
12
28
  nick: string;
13
- nickError: string;
14
29
  mail: string;
15
- mailError: string;
16
30
  link: string;
17
31
  optional: string;
18
32
  placeholder: string;
19
33
  sofa: string;
20
34
  submit: string;
21
- like: string;
22
- cancelLike: string;
23
- reply: string;
24
- cancelReply: string;
25
35
  comment: string;
26
36
  refresh: string;
27
37
  more: string;
28
- preview: string;
29
- emoji: string;
30
- uploadImage: string;
31
38
  uploading: string;
32
39
  login: string;
33
- logout: string;
34
40
  admin: string;
35
41
  sticky: string;
36
42
  word: string;
37
- wordHint: string;
38
43
  anonymous: string;
39
44
  gif: string;
40
45
  gifSearchPlaceholder: string;
41
- profile: string;
46
+
47
+ // manage
42
48
  approved: string;
43
49
  waiting: string;
44
50
  spam: string;
45
51
  unsticky: string;
52
+
53
+ // sorting
46
54
  oldest: string;
47
55
  latest: string;
48
56
  hottest: string;
49
- reactionTitle: string;
50
- reaction0: string;
51
- reaction1: string;
52
- reaction2: string;
53
- reaction3: string;
54
- reaction4: string;
55
- reaction5: string;
56
- reaction6: string;
57
- reaction7: string;
58
- reaction8: string;
57
+
58
+ // hint
59
+ nickError: string;
60
+ mailError: string;
61
+ wordHint: string;
62
+
63
+ // i18n
64
+ like: string;
65
+ cancelLike: string;
66
+ reply: string;
67
+ cancelReply: string;
68
+ preview: string;
69
+ emoji: string;
70
+ uploadImage: string;
71
+ profile: string;
72
+ logout: string;
59
73
  }
@@ -23,9 +23,11 @@ export interface WalineEmojiConfig {
23
23
  map: WalineEmojiMaps;
24
24
  }
25
25
 
26
- export interface WalineConfig extends Required<Omit<WalineProps, 'wordLimit'>> {
26
+ export interface WalineConfig
27
+ extends Required<Omit<WalineProps, 'wordLimit' | 'reaction'>> {
27
28
  locale: WalineLocale;
28
29
  wordLimit: [number, number] | false;
30
+ reaction: string[];
29
31
  }
30
32
 
31
33
  export const getServerURL = (serverURL: string): string => {
@@ -62,7 +64,7 @@ export const getConfig = ({
62
64
  texRenderer,
63
65
  copyright = true,
64
66
  login = 'enable',
65
- search = getDefaultSearchOptions(),
67
+ search,
66
68
  reaction,
67
69
  recaptchaV3Key = '',
68
70
  ...more
@@ -85,8 +87,12 @@ export const getConfig = ({
85
87
  pageSize,
86
88
  login,
87
89
  copyright,
88
- search,
90
+ search: search || getDefaultSearchOptions(lang),
89
91
  recaptchaV3Key,
90
- reaction: reaction === true ? defaultReaction : reaction || false,
92
+ reaction: Array.isArray(reaction)
93
+ ? reaction
94
+ : reaction === true
95
+ ? defaultReaction
96
+ : [],
91
97
  ...more,
92
98
  });