@waline/client 2.2.0 → 2.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waline/client",
3
- "version": "2.2.0",
3
+ "version": "2.3.2",
4
4
  "description": "client for waline comment system",
5
5
  "keywords": [
6
6
  "valine",
@@ -56,15 +56,6 @@
56
56
  "dist",
57
57
  "src"
58
58
  ],
59
- "scripts": {
60
- "build": "npm run rollup && npm run style",
61
- "clean": "rimraf ./dist",
62
- "dev": "vite -c config/vite.config.js",
63
- "lint": "eslint --ext .ts,.vue .",
64
- "prepublish": "npm run clean && npm run build",
65
- "rollup": "rollup -c ./config/rollup.config.js",
66
- "style": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed"
67
- },
68
59
  "browserslist": {
69
60
  "production": [
70
61
  ">0.5%",
@@ -80,9 +71,8 @@
80
71
  ]
81
72
  },
82
73
  "dependencies": {
83
- "@vueuse/core": "^8.3.1",
74
+ "@vueuse/core": "^8.4.0",
84
75
  "autosize": "^5.0.1",
85
- "hanabi": "^0.4.0",
86
76
  "marked": "^4.0.15",
87
77
  "vue": "^3.2.33"
88
78
  },
@@ -90,9 +80,18 @@
90
80
  "@types/autosize": "^4.0.1",
91
81
  "@types/marked": "^4.0.3",
92
82
  "@vitejs/plugin-vue": "^2.3.1",
93
- "vite": "^2.9.6"
83
+ "vite": "^2.9.7"
94
84
  },
95
85
  "engines": {
96
86
  "node": ">=12.20.0"
87
+ },
88
+ "scripts": {
89
+ "build": "pnpm rollup && pnpm style",
90
+ "clean": "rimraf ./dist",
91
+ "dev": "vite -c config/vite.config.js",
92
+ "lint": "eslint --ext .ts,.vue .",
93
+ "prepublish": "pnpm clean && pnpm build",
94
+ "rollup": "rollup -c ./config/rollup.config.js",
95
+ "style": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed"
97
96
  }
98
- }
97
+ }
@@ -405,9 +405,7 @@ export default defineComponent({
405
405
  if (
406
406
  (requiredMeta.indexOf('mail') > -1 && !comment.mail) ||
407
407
  (comment.mail &&
408
- !/^\w(?:[\w._-]*\w)?@(?:\w(?:[\w-]*\w)?\.){0,2}\w+$/.exec(
409
- comment.mail
410
- ))
408
+ !/^\w(?:[\w._-]*\w)?@(?:\w(?:[\w-]*\w)?\.)*\w+$/.exec(comment.mail))
411
409
  ) {
412
410
  inputRefs.value.mail?.focus();
413
411
  return alert(locale.value.mailError);
@@ -22,10 +22,11 @@
22
22
  class="wl-badge"
23
23
  v-text="locale.admin"
24
24
  />
25
+ <span v-if="comment.label" class="wl-badge" v-text="comment.label" />
25
26
  <span v-if="comment.sticky" class="wl-badge" v-text="locale.sticky" />
26
27
  <span
27
28
  v-if="comment.level >= 0"
28
- class="wl-badge"
29
+ :class="`wl-badge level${comment.level}`"
29
30
  v-text="locale[`level${comment.level}`] || `Level ${comment.level}`"
30
31
  />
31
32
 
@@ -67,7 +67,7 @@ import CommentBox from './CommentBox.vue';
67
67
  import CommentCard from './CommentCard.vue';
68
68
  import { LoadingIcon } from './Icons';
69
69
  import { useUserInfo } from '../composables';
70
- import { locales } from '../config';
70
+ import { defaultLocales } from '../config';
71
71
  import { fetchCommentList, getConfig, getDarkStyle } from '../utils';
72
72
 
73
73
  import type { PropType } from 'vue';
@@ -79,11 +79,115 @@ import type {
79
79
  WalineImageUploader,
80
80
  WalineLocale,
81
81
  WalineProps,
82
+ WalineMeta,
82
83
  } from '../typings';
83
84
 
84
85
  declare const SHOULD_VALIDATE: boolean;
85
86
  declare const VERSION: string;
86
87
 
88
+ const props = [
89
+ 'serverURL',
90
+ 'path',
91
+ 'meta',
92
+ 'requiredMeta',
93
+ 'dark',
94
+ 'lang',
95
+ 'locale',
96
+ 'pageSize',
97
+ 'wordLimit',
98
+ 'emoji',
99
+ 'login',
100
+ 'highlighter',
101
+ 'texRenderer',
102
+ 'imageUploader',
103
+ 'copyright',
104
+ ];
105
+
106
+ const propsWithValidate = {
107
+ serverURL: {
108
+ type: String,
109
+ required: true,
110
+ },
111
+
112
+ path: {
113
+ type: String,
114
+ required: true,
115
+ },
116
+
117
+ meta: {
118
+ type: Array as PropType<WalineMeta[]>,
119
+ default: (): WalineMeta[] => ['nick', 'mail', 'link'],
120
+ validator: (value: unknown): boolean =>
121
+ Array.isArray(value) &&
122
+ value.every((item) => ['nick', 'mail', 'link'].includes(item)),
123
+ },
124
+
125
+ requiredMeta: {
126
+ type: Array,
127
+ default: (): WalineMeta[] => [],
128
+ validator: (value: unknown): boolean =>
129
+ Array.isArray(value) &&
130
+ value.every((item) => ['nick', 'mail', 'link'].includes(item)),
131
+ },
132
+
133
+ dark: [String, Boolean],
134
+
135
+ lang: {
136
+ type: String,
137
+ default: 'zh-CN',
138
+ validator: (value: unknown): boolean =>
139
+ Object.keys(defaultLocales).includes(value as string),
140
+ },
141
+
142
+ locale: Object as PropType<Partial<WalineLocale>>,
143
+
144
+ pageSize: { type: Number, default: 10 },
145
+
146
+ wordLimit: {
147
+ type: [Number, Array] as PropType<number | [number, number]>,
148
+ validator: (value: unknown): boolean =>
149
+ typeof value === 'number' ||
150
+ (Array.isArray(value) &&
151
+ value.length === 2 &&
152
+ value.every((item) => typeof item === 'number')),
153
+ },
154
+
155
+ emoji: {
156
+ type: [Array, Boolean] as PropType<(string | WalineEmojiInfo)[] | false>,
157
+ validator: (value: unknown): boolean =>
158
+ value === false ||
159
+ (Array.isArray(value) &&
160
+ value.every(
161
+ (item) =>
162
+ typeof item === 'string' ||
163
+ (typeof item === 'object' &&
164
+ typeof item.name === 'string' &&
165
+ typeof item.folder === 'string' &&
166
+ typeof item.icon === 'string' &&
167
+ Array.isArray(item.items) &&
168
+ (item.items as unknown[]).every(
169
+ (icon) => typeof icon === 'string'
170
+ ))
171
+ )),
172
+ },
173
+
174
+ login: String as PropType<'enable' | 'disable' | 'force'>,
175
+
176
+ highlighter: Function as PropType<WalineHighlighter>,
177
+
178
+ imageUploader: {
179
+ type: [Function, Boolean] as PropType<WalineImageUploader | false>,
180
+ default: undefined,
181
+ },
182
+
183
+ texRenderer: {
184
+ type: [Function, Boolean] as PropType<WalineTexRenderer | false>,
185
+ default: undefined,
186
+ },
187
+
188
+ copyright: { type: Boolean, default: true },
189
+ };
190
+
87
191
  export default defineComponent({
88
192
  name: 'WalineRoot',
89
193
 
@@ -93,117 +197,10 @@ export default defineComponent({
93
197
  LoadingIcon,
94
198
  },
95
199
 
96
- props: {
97
- serverURL: {
98
- type: String,
99
- required: true,
100
- },
101
-
102
- path: {
103
- type: String,
104
- required: true,
105
- },
106
-
107
- meta: {
108
- type: Array,
109
- ...(SHOULD_VALIDATE
110
- ? {
111
- validator: (value: unknown): boolean =>
112
- Array.isArray(value) &&
113
- value.every((item) => ['nick', 'mail', 'link'].includes(item)),
114
- }
115
- : {}),
116
- },
117
-
118
- requiredMeta: {
119
- type: Array,
120
- ...(SHOULD_VALIDATE
121
- ? {
122
- validator: (value: unknown): boolean =>
123
- Array.isArray(value) &&
124
- value.every((item) => ['nick', 'mail', 'link'].includes(item)),
125
- }
126
- : {}),
127
- },
128
-
129
- dark: {
130
- type: [String, Boolean],
131
- },
132
-
133
- lang: {
134
- type: String,
135
- ...(SHOULD_VALIDATE
136
- ? {
137
- validator: (value: unknown): boolean =>
138
- Object.keys(locales).includes(value as string),
139
- }
140
- : {}),
141
- },
142
-
143
- locale: {
144
- type: Object as PropType<Partial<WalineLocale>>,
145
- },
146
-
147
- pageSize: {
148
- type: Number,
149
- },
150
-
151
- wordLimit: {
152
- type: [Number, Array] as PropType<number | [number, number]>,
153
- // default: 0,
154
- ...(SHOULD_VALIDATE
155
- ? {
156
- validator: (value: unknown): boolean =>
157
- typeof value === 'number' ||
158
- (Array.isArray(value) &&
159
- value.length === 2 &&
160
- value.every((item) => typeof item === 'number')),
161
- }
162
- : {}),
163
- },
164
-
165
- emoji: {
166
- type: [Array, Boolean] as PropType<(string | WalineEmojiInfo)[] | false>,
167
- ...(SHOULD_VALIDATE
168
- ? {
169
- validator: (value: unknown): boolean =>
170
- value === false ||
171
- (Array.isArray(value) &&
172
- value.every(
173
- (item) =>
174
- typeof item === 'string' ||
175
- (typeof item === 'object' &&
176
- typeof item.name === 'string' &&
177
- typeof item.folder === 'string' &&
178
- typeof item.icon === 'string' &&
179
- Array.isArray(item.items) &&
180
- (item.items as unknown[]).every(
181
- (icon) => typeof icon === 'string'
182
- ))
183
- )),
184
- }
185
- : {}),
186
- },
187
-
188
- login: {
189
- type: String as PropType<'enable' | 'disable' | 'force'>,
190
- },
191
-
192
- highlighter: {
193
- type: Function as PropType<WalineHighlighter>,
194
- },
195
-
196
- imageUploader: {
197
- type: [Function, Boolean] as PropType<WalineImageUploader | false>,
198
- },
199
-
200
- texRenderer: {
201
- type: [Function, Boolean] as PropType<WalineTexRenderer | false>,
202
- },
203
- },
200
+ props: SHOULD_VALIDATE ? propsWithValidate : props,
204
201
 
205
202
  setup(props) {
206
- const config = computed(() => getConfig(props as WalineProps));
203
+ const config = computed(() => getConfig(props as unknown as WalineProps));
207
204
 
208
205
  const userInfo = useUserInfo();
209
206
 
@@ -286,7 +283,7 @@ export default defineComponent({
286
283
 
287
284
  provide('config', config);
288
285
 
289
- watch(() => props.path, refresh);
286
+ watch(() => (props as unknown as WalineProps).path, refresh);
290
287
 
291
288
  onMounted(() => refresh());
292
289
 
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The MIT License (MIT)
3
+ *
4
+ * Copyright (c) egoist <0x142857@gmail.com> (https://egoistian.com)
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ *
24
+ */
25
+
26
+ const WORD_REGEXP =
27
+ /[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af\u0400-\u04FF]+|\w+/;
28
+ const LEFT_ANGLE_REGEXP = /</;
29
+ const LINE_COMMENT_REGEXP = /(?:^|\s)\/\/(.+?)$/gm;
30
+ const BLOCK_COMMENT_REGEXP = /\/\*([\S\s]*?)\*\//gm;
31
+ const REGEXP = new RegExp(
32
+ `(${WORD_REGEXP.source}|${LEFT_ANGLE_REGEXP.source})|((?:${LINE_COMMENT_REGEXP.source})|(?:${BLOCK_COMMENT_REGEXP.source}))`,
33
+ 'gmi'
34
+ );
35
+
36
+ const COLORS = [
37
+ '23AC69',
38
+ '91C132',
39
+ 'F19726',
40
+ 'E8552D',
41
+ '1AAB8E',
42
+ 'E1147F',
43
+ '2980C1',
44
+ '1BA1E6',
45
+ '9FA0A0',
46
+ 'F19726',
47
+ 'E30B20',
48
+ 'E30B20',
49
+ 'A3338B',
50
+ ];
51
+ const cache: Record<string, string> = {};
52
+
53
+ export const defaultHighlighter = (input: string): string => {
54
+ let index = 0;
55
+
56
+ return input.replace(REGEXP, (_match, word: string, comment: string) => {
57
+ if (comment) return `<span style="color: slategray">${comment}</span>`;
58
+ if (word === '<') return '&lt;';
59
+
60
+ let color: string;
61
+
62
+ if (cache[word]) color = cache[word];
63
+ else {
64
+ color = COLORS[index];
65
+ cache[word] = color;
66
+ }
67
+
68
+ const out = `<span style="color: #${color}">${word}</span>`;
69
+
70
+ index = ++index % COLORS.length;
71
+
72
+ return out;
73
+ });
74
+ };
@@ -10,7 +10,7 @@ import type { WalineLocale } from '../../typings';
10
10
 
11
11
  export type Locales = Record<string, WalineLocale>;
12
12
 
13
- export const locales: Locales = {
13
+ export const defaultLocales: Locales = {
14
14
  zh: zhCN,
15
15
  'zh-cn': zhCN,
16
16
  'zh-CN': zhCN,
@@ -1,2 +1,3 @@
1
1
  export * from './default';
2
+ export * from './highlighter';
2
3
  export * from './i18n';
@@ -1,4 +1,4 @@
1
- export * from '../config';
1
+ export { defaultLocales } from '../config';
2
2
  export * from '../comment';
3
3
  export * from '../init';
4
4
  export * from '../pageview';
@@ -1,4 +1,4 @@
1
1
  export * from '../init';
2
- export * from '../config';
2
+ export { defaultLocales } from '../config';
3
3
  export * from '../typings';
4
4
  export * from '../version';
@@ -43,12 +43,6 @@ export type WalineMeta = 'nick' | 'mail' | 'link';
43
43
 
44
44
  export type WalineImageUploader = (image: File) => Promise<string>;
45
45
 
46
- export type WalineHighlighter =
47
- | ((code: string, lang: string) => string)
48
- | ((
49
- code: string,
50
- lang: string,
51
- callback?: (error: unknown | undefined, code?: string) => void
52
- ) => void);
46
+ export type WalineHighlighter = (code: string, lang: string) => string;
53
47
 
54
48
  export type WalineTexRenderer = (blockMode: boolean, tex: string) => string;
@@ -24,4 +24,5 @@ export interface WalineComment extends Exclude<WalineCommentData, 'ua'> {
24
24
  os?: string;
25
25
  level?: number;
26
26
  addr?: string;
27
+ label?: string;
27
28
  }
@@ -6,7 +6,16 @@ export interface WalineDateLocale {
6
6
  now: string;
7
7
  }
8
8
 
9
- export interface WalineLocale extends WalineDateLocale {
9
+ export interface WalineLevelLocale {
10
+ level0: string;
11
+ level1: string;
12
+ level2: string;
13
+ level3: string;
14
+ level4: string;
15
+ level5: string;
16
+ }
17
+
18
+ export interface WalineLocale extends WalineDateLocale, WalineLevelLocale {
10
19
  nick: string;
11
20
  nickError: string;
12
21
  mail: string;
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  defaultLang,
3
3
  defaultUploadImage,
4
+ defaultHighlighter,
4
5
  defaultTexRenderer,
5
6
  getMeta,
6
- locales,
7
+ defaultLocales,
7
8
  } from '../config';
8
9
 
9
10
  import { decodePath, isLinkHttp, removeEndingSplash } from './path';
@@ -14,7 +15,6 @@ import type {
14
15
  WalineLocale,
15
16
  WalineProps,
16
17
  } from '../typings';
17
- import hanabi from 'hanabi';
18
18
 
19
19
  export interface WalineEmojiConfig {
20
20
  tabs: Pick<WalineEmojiInfo, 'name' | 'icon' | 'items'>[];
@@ -66,14 +66,14 @@ export const getConfig = ({
66
66
  serverURL: getServerURL(serverURL),
67
67
  path: decodePath(path),
68
68
  locale: {
69
- ...(locales[lang] || locales[defaultLang]),
69
+ ...(defaultLocales[lang] || defaultLocales[defaultLang]),
70
70
  ...(typeof locale === 'object' ? locale : {}),
71
71
  },
72
72
  wordLimit: getWordLimit(wordLimit),
73
73
  meta: getMeta(meta),
74
74
  requiredMeta: getMeta(requiredMeta),
75
75
  imageUploader: fallback(imageUploader, defaultUploadImage),
76
- highlighter: fallback(highlighter, hanabi),
76
+ highlighter: fallback(highlighter, defaultHighlighter),
77
77
  texRenderer: fallback(texRenderer, defaultTexRenderer),
78
78
  lang,
79
79
  dark,
@@ -1,9 +0,0 @@
1
- declare module 'hanabi' {
2
- const hanabi: (
3
- code: string,
4
- lang: string,
5
- callback?: (error: unknown, code?: string | undefined) => void
6
- ) => string | void;
7
-
8
- export default hanabi;
9
- }