@waline/client 2.11.2 → 2.11.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waline/client",
3
- "version": "2.11.2",
3
+ "version": "2.11.3",
4
4
  "description": "client for waline comment system",
5
5
  "keywords": [
6
6
  "valine",
@@ -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);
@@ -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
  },
@@ -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[]>;
@@ -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 => {
@@ -87,6 +89,10 @@ export const getConfig = ({
87
89
  copyright,
88
90
  search,
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
  });