@waline/client 2.5.1 → 2.6.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.
- package/dist/component.esm.js +1 -1
- package/dist/component.esm.js.map +1 -1
- package/dist/component.js +1 -1
- package/dist/component.js.map +1 -1
- package/dist/legacy.d.ts +40 -0
- package/dist/legacy.js +1 -1
- package/dist/legacy.js.map +1 -1
- package/dist/pageview.cjs.js +1 -1
- package/dist/pageview.cjs.js.map +1 -1
- package/dist/pageview.esm.js +1 -1
- package/dist/pageview.esm.js.map +1 -1
- package/dist/pageview.js +1 -1
- package/dist/pageview.js.map +1 -1
- package/dist/shim.d.ts +41 -1
- package/dist/shim.esm.d.ts +41 -1
- package/dist/shim.esm.js +1 -1
- package/dist/shim.esm.js.map +1 -1
- package/dist/shim.js +1 -1
- package/dist/shim.js.map +1 -1
- package/dist/waline.cjs.d.ts +41 -1
- package/dist/waline.cjs.js +1 -1
- package/dist/waline.cjs.js.map +1 -1
- package/dist/waline.css +1 -1
- package/dist/waline.css.map +1 -1
- package/dist/waline.d.ts +41 -1
- package/dist/waline.esm.d.ts +41 -1
- package/dist/waline.esm.js +1 -1
- package/dist/waline.esm.js.map +1 -1
- package/dist/waline.js +1 -1
- package/dist/waline.js.map +1 -1
- package/package.json +20 -21
- package/src/comment.ts +7 -2
- package/src/components/CommentBox.vue +40 -34
- package/src/components/ImageWall.vue +32 -18
- package/src/config/default.ts +91 -1
- package/src/init.ts +0 -3
- package/src/pageview.ts +2 -1
- package/src/styles/emoji.scss +20 -0
- package/src/typings/base.ts +40 -0
- package/src/typings/waline.ts +8 -0
- package/src/utils/config.ts +5 -2
- package/src/utils/index.ts +0 -2
- package/src/utils/fetchGif.ts +0 -63
- package/src/utils/throttle.ts +0 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waline/client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "client for waline comment system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"valine",
|
|
@@ -71,30 +71,29 @@
|
|
|
71
71
|
]
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@vueuse/core": "^8.
|
|
74
|
+
"@vueuse/core": "^8.6.0",
|
|
75
75
|
"autosize": "^5.0.1",
|
|
76
76
|
"marked": "^4.0.16",
|
|
77
|
-
"vue": "^3.2.
|
|
77
|
+
"vue": "^3.2.37"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@babel/core": "
|
|
81
|
-
"@babel/preset-env": "
|
|
82
|
-
"@rollup/plugin-babel": "
|
|
83
|
-
"@rollup/plugin-commonjs": "
|
|
84
|
-
"@rollup/plugin-node-resolve": "
|
|
85
|
-
"@rollup/plugin-replace": "
|
|
86
|
-
"@types/autosize": "
|
|
87
|
-
"@types/marked": "
|
|
88
|
-
"@types/node": "
|
|
89
|
-
"@vitejs/plugin-vue": "
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"rollup": "
|
|
93
|
-
"rollup-plugin-
|
|
94
|
-
"rollup-plugin-
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"vite": "^2.9.9"
|
|
80
|
+
"@babel/core": "7.18.2",
|
|
81
|
+
"@babel/preset-env": "7.18.2",
|
|
82
|
+
"@rollup/plugin-babel": "5.3.1",
|
|
83
|
+
"@rollup/plugin-commonjs": "22.0.0",
|
|
84
|
+
"@rollup/plugin-node-resolve": "13.3.0",
|
|
85
|
+
"@rollup/plugin-replace": "4.0.0",
|
|
86
|
+
"@types/autosize": "4.0.1",
|
|
87
|
+
"@types/marked": "4.0.3",
|
|
88
|
+
"@types/node": "17.0.41",
|
|
89
|
+
"@vitejs/plugin-vue": "2.3.3",
|
|
90
|
+
"rimraf": "3.0.2",
|
|
91
|
+
"rollup": "2.75.6",
|
|
92
|
+
"rollup-plugin-dts": "4.2.2",
|
|
93
|
+
"rollup-plugin-terser": "7.0.2",
|
|
94
|
+
"rollup-plugin-ts": "3.0.2",
|
|
95
|
+
"typescript": "4.7.3",
|
|
96
|
+
"vite": "2.9.10"
|
|
98
97
|
},
|
|
99
98
|
"engines": {
|
|
100
99
|
"node": ">=14"
|
package/src/comment.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { useUserInfo } from './composables';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
decodePath,
|
|
4
|
+
errorHandler,
|
|
5
|
+
fetchCommentCount,
|
|
6
|
+
getServerURL,
|
|
7
|
+
} from './utils';
|
|
3
8
|
import type { WalineAbort } from './typings';
|
|
4
9
|
|
|
5
10
|
export interface WalineCommentCountOptions {
|
|
@@ -54,7 +59,7 @@ WalineCommentCountOptions): WalineAbort => {
|
|
|
54
59
|
|
|
55
60
|
if (elements.length)
|
|
56
61
|
void fetchCommentCount({
|
|
57
|
-
serverURL,
|
|
62
|
+
serverURL: getServerURL(serverURL),
|
|
58
63
|
paths: Array.from(elements).map((element) =>
|
|
59
64
|
decodePath(element.dataset.path || element.getAttribute('id') || path)
|
|
60
65
|
),
|
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
</button>
|
|
90
90
|
|
|
91
91
|
<button
|
|
92
|
+
v-if="config.search"
|
|
92
93
|
ref="gifButtonRef"
|
|
93
94
|
class="wl-action"
|
|
94
95
|
:class="{ actived: showGif }"
|
|
@@ -245,6 +246,7 @@
|
|
|
245
246
|
</template>
|
|
246
247
|
|
|
247
248
|
<script lang="ts">
|
|
249
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
248
250
|
import autosize from 'autosize';
|
|
249
251
|
import {
|
|
250
252
|
computed,
|
|
@@ -252,11 +254,11 @@ import {
|
|
|
252
254
|
inject,
|
|
253
255
|
onMounted,
|
|
254
256
|
onUnmounted,
|
|
257
|
+
reactive,
|
|
255
258
|
ref,
|
|
256
259
|
watch,
|
|
257
260
|
} from 'vue';
|
|
258
261
|
|
|
259
|
-
import ImageWall from './ImageWall.vue';
|
|
260
262
|
import {
|
|
261
263
|
CloseIcon,
|
|
262
264
|
EmojiIcon,
|
|
@@ -266,25 +268,25 @@ import {
|
|
|
266
268
|
LoadingIcon,
|
|
267
269
|
GifIcon,
|
|
268
270
|
} from './Icons';
|
|
271
|
+
import ImageWall from './ImageWall.vue';
|
|
269
272
|
import { useEditor, useUserMeta, useUserInfo } from '../composables';
|
|
270
273
|
import {
|
|
271
|
-
fetchGif,
|
|
272
274
|
getEmojis,
|
|
273
275
|
getImagefromDataTransfer,
|
|
274
276
|
getWordNumber,
|
|
275
277
|
parseEmoji,
|
|
276
278
|
parseMarkdown,
|
|
277
279
|
postComment,
|
|
278
|
-
throttle,
|
|
279
280
|
} from '../utils';
|
|
280
281
|
|
|
281
282
|
import type { ComputedRef, DeepReadonly } from 'vue';
|
|
282
|
-
import type { WalineCommentData, WalineImageUploader } from '../typings';
|
|
283
283
|
import type {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
284
|
+
WalineCommentData,
|
|
285
|
+
WalineImageUploader,
|
|
286
|
+
WalineSearchOptions,
|
|
287
|
+
WalineSearchResult,
|
|
288
|
+
} from '../typings';
|
|
289
|
+
import type { WalineConfig, WalineEmojiConfig } from '../utils';
|
|
288
290
|
|
|
289
291
|
export default defineComponent({
|
|
290
292
|
name: 'CommentBox',
|
|
@@ -342,11 +344,11 @@ export default defineComponent({
|
|
|
342
344
|
const showPreview = ref(false);
|
|
343
345
|
const previewText = ref('');
|
|
344
346
|
const wordNumber = ref(0);
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
loading:
|
|
348
|
-
list:
|
|
349
|
-
}
|
|
347
|
+
|
|
348
|
+
const searchResults = reactive({
|
|
349
|
+
loading: true,
|
|
350
|
+
list: [] as WalineSearchResult[],
|
|
351
|
+
});
|
|
350
352
|
|
|
351
353
|
const wordLimit = ref(0);
|
|
352
354
|
const isWordNumberLegal = ref(false);
|
|
@@ -614,31 +616,30 @@ export default defineComponent({
|
|
|
614
616
|
const { scrollTop, clientHeight, scrollHeight } =
|
|
615
617
|
event.target as HTMLDivElement;
|
|
616
618
|
const percent = (clientHeight + scrollTop) / scrollHeight;
|
|
619
|
+
const searchOptions = config.value.search as WalineSearchOptions;
|
|
620
|
+
const keyword = gifSearchInputRef.value?.value || '';
|
|
617
621
|
|
|
618
|
-
if (percent < 0.9 ||
|
|
622
|
+
if (percent < 0.9 || searchResults.loading) return;
|
|
619
623
|
|
|
620
|
-
|
|
624
|
+
searchResults.loading = true;
|
|
621
625
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
});
|
|
626
|
+
searchResults.list.push(
|
|
627
|
+
...(searchOptions.more
|
|
628
|
+
? await searchOptions.more(keyword, searchResults.list.length)
|
|
629
|
+
: await searchOptions.search(keyword))
|
|
630
|
+
);
|
|
628
631
|
|
|
629
|
-
|
|
630
|
-
gifData.value.list = gifData.value.list.concat(data.results);
|
|
632
|
+
searchResults.loading = false;
|
|
631
633
|
|
|
632
634
|
setTimeout(() => {
|
|
633
635
|
(event.target as HTMLDivElement).scrollTop = scrollTop;
|
|
634
636
|
}, 50);
|
|
635
637
|
};
|
|
636
638
|
|
|
637
|
-
const onGifSearch =
|
|
638
|
-
|
|
639
|
-
gifData.value.list = [];
|
|
639
|
+
const onGifSearch = useDebounceFn((event: Event) => {
|
|
640
|
+
searchResults.list = [];
|
|
640
641
|
onImageWallScroll(event);
|
|
641
|
-
});
|
|
642
|
+
}, 300);
|
|
642
643
|
|
|
643
644
|
// update wordNumber
|
|
644
645
|
watch(
|
|
@@ -668,13 +669,18 @@ export default defineComponent({
|
|
|
668
669
|
watch(showGif, async (showGif) => {
|
|
669
670
|
if (!showGif) return;
|
|
670
671
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
672
|
+
const searchOptions = config.value.search as WalineSearchOptions;
|
|
673
|
+
|
|
674
|
+
// clear input
|
|
675
|
+
if (gifSearchInputRef.value) gifSearchInputRef.value.value = '';
|
|
676
|
+
|
|
677
|
+
searchResults.loading = true;
|
|
678
|
+
|
|
679
|
+
searchResults.list = searchOptions.default
|
|
680
|
+
? await searchOptions.default()
|
|
681
|
+
: await searchOptions.search('');
|
|
675
682
|
|
|
676
|
-
|
|
677
|
-
gifData.value.list = gifData.value.list.concat(data.results);
|
|
683
|
+
searchResults.loading = false;
|
|
678
684
|
});
|
|
679
685
|
|
|
680
686
|
onMounted(() => {
|
|
@@ -756,7 +762,7 @@ export default defineComponent({
|
|
|
756
762
|
showEmoji,
|
|
757
763
|
|
|
758
764
|
// gif
|
|
759
|
-
gifData,
|
|
765
|
+
gifData: searchResults,
|
|
760
766
|
showGif,
|
|
761
767
|
|
|
762
768
|
// image
|
|
@@ -31,17 +31,21 @@ SOFTWARE. -->
|
|
|
31
31
|
:data-index="columnIndex"
|
|
32
32
|
:style="{ gap: `${gap}px` }"
|
|
33
33
|
>
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
<template v-for="itemIndex in column" :key="itemIndex">
|
|
35
|
+
<LoadingIcon
|
|
36
|
+
v-if="!state[items[itemIndex].src]"
|
|
37
|
+
:size="36"
|
|
38
|
+
style="margin: 20px auto"
|
|
39
|
+
/>
|
|
40
|
+
<img
|
|
41
|
+
class="wl-gallery-item"
|
|
42
|
+
:src="items[itemIndex].src"
|
|
43
|
+
:title="items[itemIndex].title"
|
|
44
|
+
loading="lazy"
|
|
45
|
+
@load="state[items[itemIndex].src] = true"
|
|
46
|
+
@click="$emit('insert', ``)"
|
|
47
|
+
/>
|
|
48
|
+
</template>
|
|
45
49
|
</div>
|
|
46
50
|
</div>
|
|
47
51
|
</template>
|
|
@@ -56,16 +60,24 @@ import {
|
|
|
56
60
|
watch,
|
|
57
61
|
} from 'vue';
|
|
58
62
|
|
|
63
|
+
import { LoadingIcon } from './Icons';
|
|
64
|
+
|
|
59
65
|
import type { PropType } from 'vue';
|
|
66
|
+
import type { WalineSearchResult } from '../typings';
|
|
60
67
|
|
|
61
68
|
type Column = number[];
|
|
62
69
|
|
|
63
70
|
export default defineComponent({
|
|
71
|
+
name: 'ImageWall',
|
|
72
|
+
|
|
73
|
+
components: {
|
|
74
|
+
LoadingIcon,
|
|
75
|
+
},
|
|
76
|
+
|
|
64
77
|
props: {
|
|
78
|
+
items: { type: Array as PropType<WalineSearchResult[]>, default: () => [] },
|
|
65
79
|
columnWidth: { type: Number, default: 300 },
|
|
66
|
-
items: { type: Array as PropType<unknown[]>, default: () => [] },
|
|
67
80
|
gap: { type: Number, default: 0 },
|
|
68
|
-
rtl: { type: Boolean, default: false },
|
|
69
81
|
},
|
|
70
82
|
|
|
71
83
|
emit: ['insert'],
|
|
@@ -73,7 +85,7 @@ export default defineComponent({
|
|
|
73
85
|
setup(props) {
|
|
74
86
|
let resizeObserver: ResizeObserver | null = null;
|
|
75
87
|
const wall = ref<HTMLDivElement | null>(null);
|
|
76
|
-
|
|
88
|
+
const state = ref<Record<string, boolean>>({});
|
|
77
89
|
const columns = ref<Column[]>([]);
|
|
78
90
|
|
|
79
91
|
const getColumnCount = (): number => {
|
|
@@ -98,8 +110,6 @@ export default defineComponent({
|
|
|
98
110
|
wall.value?.children || []
|
|
99
111
|
) as HTMLDivElement[];
|
|
100
112
|
|
|
101
|
-
if (props.rtl) columnDivs.reverse();
|
|
102
|
-
|
|
103
113
|
const target = columnDivs.reduce((prev, curr) =>
|
|
104
114
|
curr.getBoundingClientRect().height <
|
|
105
115
|
prev.getBoundingClientRect().height
|
|
@@ -125,8 +135,11 @@ export default defineComponent({
|
|
|
125
135
|
};
|
|
126
136
|
|
|
127
137
|
watch(
|
|
128
|
-
() => [props.items
|
|
129
|
-
() =>
|
|
138
|
+
() => [props.items],
|
|
139
|
+
() => {
|
|
140
|
+
state.value = {};
|
|
141
|
+
redraw(true);
|
|
142
|
+
}
|
|
130
143
|
);
|
|
131
144
|
watch(
|
|
132
145
|
() => [props.columnWidth, props.gap],
|
|
@@ -145,6 +158,7 @@ export default defineComponent({
|
|
|
145
158
|
|
|
146
159
|
return {
|
|
147
160
|
columns,
|
|
161
|
+
state,
|
|
148
162
|
wall,
|
|
149
163
|
};
|
|
150
164
|
},
|
package/src/config/default.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WalineMeta } from '../typings';
|
|
1
|
+
import type { WalineMeta, WalineSearchOptions } from '../typings';
|
|
2
2
|
|
|
3
3
|
const availableMeta: WalineMeta[] = ['nick', 'mail', 'link'];
|
|
4
4
|
|
|
@@ -19,3 +19,93 @@ export const defaultTexRenderer = (blockMode: boolean): string =>
|
|
|
19
19
|
blockMode === true
|
|
20
20
|
? '<p class="wl-tex">Tex is not available in preview</p>'
|
|
21
21
|
: '<span class="wl-tex">Tex is not available in preview</span>';
|
|
22
|
+
|
|
23
|
+
export const getDefaultSearchOptions = (): WalineSearchOptions => {
|
|
24
|
+
interface FetchGifRequest {
|
|
25
|
+
keyword: string;
|
|
26
|
+
pos?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type GifFormat =
|
|
30
|
+
| 'gif'
|
|
31
|
+
| 'mediumgif'
|
|
32
|
+
| 'tinygif'
|
|
33
|
+
| 'nanogif'
|
|
34
|
+
| 'mp4'
|
|
35
|
+
| 'loopedmp4'
|
|
36
|
+
| 'tinymp4'
|
|
37
|
+
| 'nanomp4'
|
|
38
|
+
| 'webm'
|
|
39
|
+
| 'tinywebm'
|
|
40
|
+
| 'nanowebm';
|
|
41
|
+
|
|
42
|
+
interface MediaObject {
|
|
43
|
+
preview: string;
|
|
44
|
+
url: string;
|
|
45
|
+
dims: number[];
|
|
46
|
+
size: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface GifObject {
|
|
50
|
+
created: number;
|
|
51
|
+
hasaudio: boolean;
|
|
52
|
+
id: string;
|
|
53
|
+
media: Record<GifFormat, MediaObject>[];
|
|
54
|
+
tags: string[];
|
|
55
|
+
title: string;
|
|
56
|
+
itemurl: string;
|
|
57
|
+
hascaption: boolean;
|
|
58
|
+
url: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface FetchGifResponse {
|
|
62
|
+
next: string;
|
|
63
|
+
results: GifObject[];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const state = {
|
|
67
|
+
next: '',
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const fetchGif = ({
|
|
71
|
+
keyword,
|
|
72
|
+
pos,
|
|
73
|
+
}: FetchGifRequest): Promise<FetchGifResponse> => {
|
|
74
|
+
const baseUrl = `https://g.tenor.com/v1/search`;
|
|
75
|
+
const query = new URLSearchParams('media_filter=minimal');
|
|
76
|
+
query.set('key', 'PAY5JLFIH6V6');
|
|
77
|
+
query.set('limit', '20');
|
|
78
|
+
query.set('pos', pos || '');
|
|
79
|
+
query.set('q', keyword);
|
|
80
|
+
|
|
81
|
+
return fetch(`${baseUrl}?${query.toString()}`, {
|
|
82
|
+
headers: {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
84
|
+
'Content-Type': 'application/json',
|
|
85
|
+
},
|
|
86
|
+
})
|
|
87
|
+
.then((resp) => resp.json() as Promise<FetchGifResponse>)
|
|
88
|
+
.catch(() => ({ next: pos || '', results: [] }));
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
search: (word = '') =>
|
|
93
|
+
fetchGif({ keyword: word }).then((resp) => {
|
|
94
|
+
state.next = resp.next;
|
|
95
|
+
|
|
96
|
+
return resp.results.map((item) => ({
|
|
97
|
+
title: item.title,
|
|
98
|
+
src: item.media[0].tinygif.url,
|
|
99
|
+
}));
|
|
100
|
+
}),
|
|
101
|
+
more: (word) =>
|
|
102
|
+
fetchGif({ keyword: word, pos: state.next }).then((resp) => {
|
|
103
|
+
state.next = resp.next;
|
|
104
|
+
|
|
105
|
+
return resp.results.map((item) => ({
|
|
106
|
+
title: item.title,
|
|
107
|
+
src: item.media[0].tinygif.url,
|
|
108
|
+
}));
|
|
109
|
+
}),
|
|
110
|
+
};
|
|
111
|
+
};
|
package/src/init.ts
CHANGED
|
@@ -83,9 +83,6 @@ export const init = ({
|
|
|
83
83
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
84
84
|
if (app) app.mount(root!);
|
|
85
85
|
|
|
86
|
-
updateCommentCount();
|
|
87
|
-
updatePageviewCount();
|
|
88
|
-
|
|
89
86
|
const stopComment = watchEffect(updateCommentCount);
|
|
90
87
|
const stopPageview = watchEffect(updatePageviewCount);
|
|
91
88
|
|
package/src/pageview.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
errorHandler,
|
|
3
3
|
fetchPageviews,
|
|
4
4
|
getQuery,
|
|
5
|
+
getServerURL,
|
|
5
6
|
updatePageviews,
|
|
6
7
|
} from './utils';
|
|
7
8
|
|
|
@@ -83,7 +84,7 @@ export const pageviewCount = ({
|
|
|
83
84
|
|
|
84
85
|
const fetch = (elements: HTMLElement[]): Promise<void> =>
|
|
85
86
|
fetchPageviews({
|
|
86
|
-
serverURL,
|
|
87
|
+
serverURL: getServerURL(serverURL),
|
|
87
88
|
paths: elements.map((element) => getQuery(element) || path),
|
|
88
89
|
lang,
|
|
89
90
|
signal: controller.signal,
|
package/src/styles/emoji.scss
CHANGED
|
@@ -81,6 +81,8 @@
|
|
|
81
81
|
position: relative;
|
|
82
82
|
height: 2em;
|
|
83
83
|
padding: 0 6px 1px;
|
|
84
|
+
overflow-x: scroll;
|
|
85
|
+
white-space: nowrap;
|
|
84
86
|
|
|
85
87
|
&::before {
|
|
86
88
|
content: ' ';
|
|
@@ -95,6 +97,24 @@
|
|
|
95
97
|
|
|
96
98
|
background: var(--waline-border-color);
|
|
97
99
|
}
|
|
100
|
+
|
|
101
|
+
&::-webkit-scrollbar {
|
|
102
|
+
width: 6px;
|
|
103
|
+
height: 6px;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&::-webkit-scrollbar-track-piece:horizontal {
|
|
107
|
+
-webkit-border-radius: 6px;
|
|
108
|
+
border-radius: 6px;
|
|
109
|
+
background: rgb(0 0 0 / 10%);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
&::-webkit-scrollbar-thumb:horizontal {
|
|
113
|
+
height: 6px;
|
|
114
|
+
-webkit-border-radius: 6px;
|
|
115
|
+
border-radius: 6px;
|
|
116
|
+
background: var(--waline-theme-color);
|
|
117
|
+
}
|
|
98
118
|
}
|
|
99
119
|
|
|
100
120
|
.wl-tab {
|
package/src/typings/base.ts
CHANGED
|
@@ -39,6 +39,46 @@ export interface WalineEmojiInfo {
|
|
|
39
39
|
|
|
40
40
|
export type WalineEmojiMaps = Record<string, string>;
|
|
41
41
|
|
|
42
|
+
export interface WalineSearchResult extends Record<string, unknown> {
|
|
43
|
+
/**
|
|
44
|
+
* Image link
|
|
45
|
+
*/
|
|
46
|
+
src: string;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Image title, optional
|
|
50
|
+
*/
|
|
51
|
+
title?: string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Image preview link, optional
|
|
55
|
+
*
|
|
56
|
+
* @default src
|
|
57
|
+
*/
|
|
58
|
+
preview?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface WalineSearchOptions {
|
|
62
|
+
/**
|
|
63
|
+
* Search action
|
|
64
|
+
*/
|
|
65
|
+
search: (word: string) => Promise<WalineSearchResult[]>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Default search action
|
|
69
|
+
*
|
|
70
|
+
* @default () => search('')
|
|
71
|
+
*/
|
|
72
|
+
default?: () => Promise<WalineSearchResult[]>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Fetch more action
|
|
76
|
+
*
|
|
77
|
+
* @default (word) => search(word)
|
|
78
|
+
*/
|
|
79
|
+
more?: (word: string, currectCount: number) => Promise<WalineSearchResult[]>;
|
|
80
|
+
}
|
|
81
|
+
|
|
42
82
|
export type WalineMeta = 'nick' | 'mail' | 'link';
|
|
43
83
|
|
|
44
84
|
export type WalineImageUploader = (image: File) => Promise<string>;
|
package/src/typings/waline.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
WalineImageUploader,
|
|
5
5
|
WalineMeta,
|
|
6
6
|
WalineTexRenderer,
|
|
7
|
+
WalineSearchOptions,
|
|
7
8
|
} from './base';
|
|
8
9
|
import type { WalineLocale } from './locale';
|
|
9
10
|
|
|
@@ -148,6 +149,13 @@ export interface WalineProps {
|
|
|
148
149
|
*/
|
|
149
150
|
emoji?: (string | WalineEmojiInfo)[] | false;
|
|
150
151
|
|
|
152
|
+
/**
|
|
153
|
+
* 设置搜索功能
|
|
154
|
+
*
|
|
155
|
+
* Customize Search feature
|
|
156
|
+
*/
|
|
157
|
+
search?: WalineSearchOptions | false;
|
|
158
|
+
|
|
151
159
|
/**
|
|
152
160
|
* 代码高亮
|
|
153
161
|
*
|
package/src/utils/config.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defaultLang,
|
|
3
|
+
defaultLocales,
|
|
3
4
|
defaultUploadImage,
|
|
4
5
|
defaultHighlighter,
|
|
5
6
|
defaultTexRenderer,
|
|
7
|
+
getDefaultSearchOptions,
|
|
6
8
|
getMeta,
|
|
7
|
-
defaultLocales,
|
|
8
9
|
} from '../config';
|
|
9
10
|
|
|
10
11
|
import { decodePath, isLinkHttp, removeEndingSplash } from './path';
|
|
@@ -27,7 +28,7 @@ export interface WalineConfig extends Required<Omit<WalineProps, 'wordLimit'>> {
|
|
|
27
28
|
// emoji: Promise<EmojiConfig>;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
const getServerURL = (serverURL: string): string => {
|
|
31
|
+
export const getServerURL = (serverURL: string): string => {
|
|
31
32
|
const result = removeEndingSplash(serverURL);
|
|
32
33
|
|
|
33
34
|
return isLinkHttp(result) ? result : `https://${result}`;
|
|
@@ -61,6 +62,7 @@ export const getConfig = ({
|
|
|
61
62
|
texRenderer,
|
|
62
63
|
copyright = true,
|
|
63
64
|
login = 'enable',
|
|
65
|
+
search = getDefaultSearchOptions(),
|
|
64
66
|
...more
|
|
65
67
|
}: WalineProps): WalineConfig => ({
|
|
66
68
|
serverURL: getServerURL(serverURL),
|
|
@@ -81,5 +83,6 @@ export const getConfig = ({
|
|
|
81
83
|
pageSize,
|
|
82
84
|
login,
|
|
83
85
|
copyright,
|
|
86
|
+
search,
|
|
84
87
|
...more,
|
|
85
88
|
});
|
package/src/utils/index.ts
CHANGED
package/src/utils/fetchGif.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export type GifFormat =
|
|
2
|
-
| 'gif'
|
|
3
|
-
| 'mediumgif'
|
|
4
|
-
| 'tinygif'
|
|
5
|
-
| 'nanogif'
|
|
6
|
-
| 'mp4'
|
|
7
|
-
| 'loopedmp4'
|
|
8
|
-
| 'tinymp4'
|
|
9
|
-
| 'nanomp4'
|
|
10
|
-
| 'webm'
|
|
11
|
-
| 'tinywebm'
|
|
12
|
-
| 'nanowebm';
|
|
13
|
-
export interface MediaObject {
|
|
14
|
-
preview: string;
|
|
15
|
-
url: string;
|
|
16
|
-
dims: number[];
|
|
17
|
-
size: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface FetchGifRequest {
|
|
21
|
-
key?: string;
|
|
22
|
-
keyword: string;
|
|
23
|
-
pos?: string;
|
|
24
|
-
limit?: number;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface GifObject {
|
|
28
|
-
created: number;
|
|
29
|
-
hasaudio: boolean;
|
|
30
|
-
id: string;
|
|
31
|
-
media: Record<GifFormat, MediaObject>[];
|
|
32
|
-
tags: string[];
|
|
33
|
-
title: string;
|
|
34
|
-
itemurl: string;
|
|
35
|
-
hascaption: boolean;
|
|
36
|
-
url: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface FetchGifResponse {
|
|
40
|
-
next: string;
|
|
41
|
-
results: GifObject[];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export const fetchGif = ({
|
|
45
|
-
key,
|
|
46
|
-
keyword,
|
|
47
|
-
pos,
|
|
48
|
-
limit,
|
|
49
|
-
}: FetchGifRequest): Promise<FetchGifResponse> => {
|
|
50
|
-
const baseUrl = `https://g.tenor.com/v1/search`;
|
|
51
|
-
const query = new URLSearchParams('media_filter=minimal');
|
|
52
|
-
query.set('key', key || 'PAY5JLFIH6V6');
|
|
53
|
-
query.set('limit', (limit || 20).toString());
|
|
54
|
-
query.set('pos', pos || '');
|
|
55
|
-
query.set('q', keyword);
|
|
56
|
-
|
|
57
|
-
return fetch(`${baseUrl}?${query.toString()}`, {
|
|
58
|
-
headers: {
|
|
59
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
60
|
-
'Content-Type': 'application/json',
|
|
61
|
-
},
|
|
62
|
-
}).then((resp) => resp.json() as Promise<FetchGifResponse>);
|
|
63
|
-
};
|
package/src/utils/throttle.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export const throttle = (
|
|
2
|
-
func: (...args: any[]) => void,
|
|
3
|
-
timeout = 300
|
|
4
|
-
): ((...args: []) => void) => {
|
|
5
|
-
let timer: number | null;
|
|
6
|
-
|
|
7
|
-
return (...args: []): void => {
|
|
8
|
-
if (timer) clearTimeout(timer);
|
|
9
|
-
|
|
10
|
-
timer = window.setTimeout(() => {
|
|
11
|
-
func(...args);
|
|
12
|
-
timer = null;
|
|
13
|
-
}, timeout);
|
|
14
|
-
};
|
|
15
|
-
};
|