@waline/client 2.14.8 → 2.15.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 (87) hide show
  1. package/dist/api.cjs.map +1 -1
  2. package/dist/api.d.cts +4 -0
  3. package/dist/api.d.mts +4 -0
  4. package/dist/api.d.ts +4 -0
  5. package/dist/api.mjs.map +1 -1
  6. package/dist/comment.cjs +1 -1
  7. package/dist/comment.cjs.map +1 -1
  8. package/dist/comment.js +1 -1
  9. package/dist/comment.js.map +1 -1
  10. package/dist/comment.mjs +1 -1
  11. package/dist/comment.mjs.map +1 -1
  12. package/dist/component.mjs +1 -1
  13. package/dist/component.mjs.map +1 -1
  14. package/dist/legacy.umd.d.ts +92 -88
  15. package/dist/legacy.umd.js +1 -1
  16. package/dist/legacy.umd.js.map +1 -1
  17. package/dist/pageview.cjs +1 -1
  18. package/dist/pageview.cjs.map +1 -1
  19. package/dist/pageview.js +1 -1
  20. package/dist/pageview.js.map +1 -1
  21. package/dist/pageview.mjs +1 -1
  22. package/dist/pageview.mjs.map +1 -1
  23. package/dist/shim.cjs +1 -1
  24. package/dist/shim.cjs.map +1 -1
  25. package/dist/shim.d.cts +10 -2
  26. package/dist/shim.d.mts +10 -2
  27. package/dist/shim.mjs +1 -1
  28. package/dist/shim.mjs.map +1 -1
  29. package/dist/waline.cjs +1 -1
  30. package/dist/waline.cjs.map +1 -1
  31. package/dist/waline.css +1 -1
  32. package/dist/waline.css.map +1 -1
  33. package/dist/waline.d.cts +10 -2
  34. package/dist/waline.d.mts +10 -2
  35. package/dist/waline.d.ts +10 -2
  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 +7 -17
  41. package/src/api/articleCounter.ts +1 -2
  42. package/src/api/comment.ts +10 -3
  43. package/src/api/commentCount.ts +1 -1
  44. package/src/api/login.ts +1 -1
  45. package/src/api/pageview.ts +2 -2
  46. package/src/api/recentComment.ts +2 -2
  47. package/src/api/user.ts +6 -3
  48. package/src/comment.ts +3 -3
  49. package/src/compact/convert.ts +6 -7
  50. package/src/compact/v1.ts +5 -5
  51. package/src/compact/valine.ts +6 -6
  52. package/src/components/ArticleReaction.vue +3 -4
  53. package/src/components/CommentBox.vue +62 -49
  54. package/src/components/CommentCard.vue +8 -7
  55. package/src/components/Icons.ts +4 -3
  56. package/src/components/ImageWall.vue +1 -2
  57. package/src/components/WalineComment.vue +8 -7
  58. package/src/composables/inputs.ts +1 -2
  59. package/src/composables/like.ts +1 -2
  60. package/src/composables/reaction.ts +1 -2
  61. package/src/composables/recaptchaV3.ts +1 -3
  62. package/src/composables/turnstile.ts +79 -0
  63. package/src/composables/userInfo.ts +2 -2
  64. package/src/config/default.ts +23 -22
  65. package/src/config/i18n/generate.ts +1 -1
  66. package/src/config/i18n/index.ts +8 -9
  67. package/src/entries/full.ts +1 -1
  68. package/src/entries/init.ts +1 -1
  69. package/src/entries/legacy.ts +10 -10
  70. package/src/init.ts +4 -5
  71. package/src/pageview.ts +3 -4
  72. package/src/shims-vue.d.ts +2 -1
  73. package/src/styles/card.scss +16 -14
  74. package/src/styles/emoji.scss +0 -3
  75. package/src/styles/index.scss +0 -5
  76. package/src/typings/comment.ts +5 -0
  77. package/src/typings/options.ts +1 -1
  78. package/src/typings/waline.ts +17 -12
  79. package/src/utils/config.ts +19 -19
  80. package/src/utils/emoji.ts +3 -3
  81. package/src/utils/index.ts +12 -11
  82. package/src/utils/markdown.ts +6 -6
  83. package/src/utils/markedMathExtension.ts +3 -2
  84. package/src/utils/userAgent.ts +1 -1
  85. package/src/utils/wordCount.ts +1 -1
  86. package/src/widgets/recentComments.ts +4 -5
  87. package/src/widgets/userList.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waline/client",
3
- "version": "2.14.8",
3
+ "version": "2.15.0",
4
4
  "description": "client for waline comment system",
5
5
  "keywords": [
6
6
  "valine",
@@ -121,29 +121,19 @@
121
121
  "dependencies": {
122
122
  "@vueuse/core": "^9.13.0",
123
123
  "autosize": "^6.0.1",
124
- "marked": "^4.2.12",
125
- "user-agent-data-types": "^0.3.1",
124
+ "marked": "^4.3.0",
126
125
  "vue": "^3.2.47"
127
126
  },
128
127
  "devDependencies": {
129
- "@babel/core": "7.21.0",
130
- "@babel/preset-env": "7.20.2",
128
+ "@babel/core": "7.21.4",
129
+ "@babel/preset-env": "7.21.4",
131
130
  "@giphy/js-types": "4.4.0",
132
- "@rollup/plugin-babel": "6.0.3",
133
- "@rollup/plugin-commonjs": "24.0.1",
134
- "@rollup/plugin-node-resolve": "15.0.1",
135
- "@rollup/plugin-replace": "5.0.2",
136
- "@rollup/plugin-terser": "0.4.0",
137
131
  "@types/autosize": "4.0.1",
138
132
  "@types/marked": "4.0.8",
139
- "@types/node": "18.14.2",
140
- "@vitejs/plugin-vue": "4.0.0",
133
+ "@vitejs/plugin-vue": "4.1.0",
141
134
  "recaptcha-v3": "1.10.0",
142
- "rollup": "3.17.3",
143
- "rollup-plugin-dts": "5.2.0",
144
- "rollup-plugin-ts": "3.2.0",
145
- "typescript": "4.9.5",
146
- "vite": "4.1.4"
135
+ "user-agent-data-types": "0.3.1",
136
+ "vite": "4.2.1"
147
137
  },
148
138
  "engines": {
149
139
  "node": ">=14"
@@ -1,5 +1,4 @@
1
- import { JSON_HEADERS } from './utils';
2
- import type { BaseAPIOptions } from './utils';
1
+ import { type BaseAPIOptions, JSON_HEADERS } from './utils.js';
3
2
 
4
3
  export interface GetArticleCounterOptions extends BaseAPIOptions {
5
4
  /**
@@ -1,6 +1,13 @@
1
- import { JSON_HEADERS, errorCheck } from './utils';
2
- import type { BaseAPIOptions, ErrorStatusResponse } from './utils';
3
- import type { WalineComment, WalineCommentData } from '../typings';
1
+ import {
2
+ type BaseAPIOptions,
3
+ type ErrorStatusResponse,
4
+ JSON_HEADERS,
5
+ errorCheck,
6
+ } from './utils.js';
7
+ import {
8
+ type WalineComment,
9
+ type WalineCommentData,
10
+ } from '../typings/index.js';
4
11
 
5
12
  export interface GetCommentOptions extends BaseAPIOptions {
6
13
  /**
@@ -1,4 +1,4 @@
1
- import type { BaseAPIOptions } from './utils';
1
+ import { type BaseAPIOptions } from './utils.js';
2
2
 
3
3
  export interface GetCommentCountOptions extends BaseAPIOptions {
4
4
  /**
package/src/api/login.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
2
- import type { BaseAPIOptions } from './utils';
2
+ import { type BaseAPIOptions } from './utils.js';
3
3
 
4
4
  export interface UserInfo {
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { getArticleCounter, updateArticleCounter } from './articleCounter';
2
- import type { BaseAPIOptions } from './utils';
1
+ import { getArticleCounter, updateArticleCounter } from './articleCounter.js';
2
+ import { type BaseAPIOptions } from './utils.js';
3
3
 
4
4
  interface GetPageviewOptions extends BaseAPIOptions {
5
5
  /**
@@ -1,5 +1,5 @@
1
- import type { BaseAPIOptions } from './utils';
2
- import type { WalineComment } from '../typings';
1
+ import { type BaseAPIOptions } from './utils.js';
2
+ import { type WalineComment } from '../typings/index.js';
3
3
 
4
4
  export interface GetRecentCommentOptions extends BaseAPIOptions {
5
5
  /**
package/src/api/user.ts CHANGED
@@ -1,6 +1,9 @@
1
- import { errorCheck, ErrorStatusResponse } from './utils';
2
- import type { BaseAPIOptions } from './utils';
3
- import type { WalineComment } from '../typings';
1
+ import {
2
+ type BaseAPIOptions,
3
+ errorCheck,
4
+ ErrorStatusResponse,
5
+ } from './utils.js';
6
+ import { type WalineComment } from '../typings/index.js';
4
7
 
5
8
  export interface GetUserListOptions extends BaseAPIOptions {
6
9
  /**
package/src/comment.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { fetchCommentCount } from './api';
2
- import { decodePath, errorHandler, getServerURL } from './utils';
3
- import type { WalineAbort } from './typings';
1
+ import { fetchCommentCount } from './api/index.js';
2
+ import { type WalineAbort } from './typings/index.js';
3
+ import { decodePath, errorHandler, getServerURL } from './utils/index.js';
4
4
 
5
5
  export interface WalineCommentCountOptions {
6
6
  /**
@@ -1,13 +1,12 @@
1
- import { warning } from './logger';
2
- import { resolveOldEmojiMap } from './valine';
3
1
  import {
4
2
  DROPPED_OPTIONS_WHICH_CAN_NOT_BE_POLYFILLED,
5
3
  DROPPED_OPTIONS_WHICH_CAN_STILL_BE_POLYFILLED,
6
- } from './dropped';
7
-
8
- import type { DeprecatedValineOptions } from './valine';
9
- import type { DeprecatedWalineOptions } from './v1';
10
- import type { WalineInitOptions } from '../typings';
4
+ } from './dropped.js';
5
+ import { warning } from './logger.js';
6
+ import { type DeprecatedWalineOptions } from './v1.js';
7
+ import { resolveOldEmojiMap } from './valine.js';
8
+ import { type DeprecatedValineOptions } from './valine.js';
9
+ import { type WalineInitOptions } from '../typings/index.js';
11
10
 
12
11
  export const covertOptions = (
13
12
  options: WalineInitOptions & DeprecatedValineOptions & DeprecatedWalineOptions
package/src/compact/v1.ts CHANGED
@@ -1,8 +1,8 @@
1
- import type {
2
- WalineHighlighter,
3
- WalineImageUploader,
4
- WalineTexRenderer,
5
- } from '../typings';
1
+ import {
2
+ type WalineHighlighter,
3
+ type WalineImageUploader,
4
+ type WalineTexRenderer,
5
+ } from '../typings/index.js';
6
6
 
7
7
  export interface DeprecatedWalineOptions {
8
8
  /**
@@ -1,9 +1,9 @@
1
- import type {
2
- WalineEmojiInfo,
3
- WalineEmojiMaps,
4
- WalineLocale,
5
- WalineMeta,
6
- } from '../typings';
1
+ import {
2
+ type WalineEmojiInfo,
3
+ type WalineEmojiMaps,
4
+ type WalineLocale,
5
+ type WalineMeta,
6
+ } from '../typings/index.js';
7
7
 
8
8
  export type DeprecatedAvatar =
9
9
  | ''
@@ -32,15 +32,14 @@
32
32
  </template>
33
33
 
34
34
  <script setup lang="ts">
35
+ import { type ComputedRef } from 'vue';
35
36
  import { computed, inject, onMounted, onUnmounted, ref, watch } from 'vue';
36
37
 
37
38
  import { LoadingIcon } from './Icons.js';
38
39
  import { getArticleCounter, updateArticleCounter } from '../api/index.js';
39
40
  import { useReactionStorage } from '../composables/index.js';
40
-
41
- import type { ComputedRef } from 'vue';
42
- import type { WalineConfig } from '../utils/index.js';
43
- import type { WalineReactionLocale } from '../typings';
41
+ import { type WalineReactionLocale } from '../typings/index.js';
42
+ import { type WalineConfig } from '../utils/index.js';
44
43
 
45
44
  defineExpose();
46
45
 
@@ -154,6 +154,8 @@
154
154
  </div>
155
155
 
156
156
  <div class="wl-info">
157
+ <div class="wl-captcha-container"></div>
158
+
157
159
  <div class="wl-text-number">
158
160
  {{ wordNumber }}
159
161
 
@@ -286,6 +288,8 @@
286
288
  import { useDebounceFn } from '@vueuse/core';
287
289
  import autosize from 'autosize';
288
290
  import {
291
+ type ComputedRef,
292
+ type DeepReadonly,
289
293
  computed,
290
294
  inject,
291
295
  onMounted,
@@ -303,7 +307,7 @@ import {
303
307
  LoadingIcon,
304
308
  MarkdownIcon,
305
309
  PreviewIcon,
306
- } from './Icons';
310
+ } from './Icons.js';
307
311
  import ImageWall from './ImageWall.vue';
308
312
  import { addComment, login, updateComment, UserInfo } from '../api/index.js';
309
313
  import {
@@ -312,25 +316,25 @@ import {
312
316
  useUserInfo,
313
317
  useUserMeta,
314
318
  } from '../composables/index.js';
319
+ import { useTurnstile } from '../composables/turnstile';
320
+ import {
321
+ type WalineComment,
322
+ type WalineCommentData,
323
+ type WalineImageUploader,
324
+ type WalineSearchOptions,
325
+ type WalineSearchResult,
326
+ } from '../typings/index.js';
315
327
  import {
328
+ type WalineConfig,
329
+ type WalineEmojiConfig,
316
330
  getEmojis,
317
331
  getImageFromDataTransfer,
318
332
  getWordNumber,
319
333
  parseEmoji,
320
334
  parseMarkdown,
335
+ userAgent,
321
336
  } from '../utils/index.js';
322
337
 
323
- import type { ComputedRef, DeepReadonly } from 'vue';
324
- import type {
325
- WalineComment,
326
- WalineCommentData,
327
- WalineImageUploader,
328
- WalineSearchOptions,
329
- WalineSearchResult,
330
- } from '../typings/index.js';
331
- import type { WalineConfig, WalineEmojiConfig } from '../utils/index.js';
332
- import { userAgent } from '../utils/userAgent';
333
-
334
338
  const props = withDefaults(
335
339
  defineProps<{
336
340
  /**
@@ -482,12 +486,15 @@ const onChange = (): void => {
482
486
  };
483
487
 
484
488
  const submitComment = async (): Promise<void> => {
485
- const { serverURL, lang, login, wordLimit, requiredMeta } = config.value;
486
-
487
- let token = '';
488
-
489
- if (config.value.recaptchaV3Key)
490
- token = await useReCaptcha(config.value.recaptchaV3Key).execute('social');
489
+ const {
490
+ serverURL,
491
+ lang,
492
+ login,
493
+ wordLimit,
494
+ requiredMeta,
495
+ recaptchaV3Key,
496
+ turnstileKey,
497
+ } = config.value;
491
498
 
492
499
  const ua = await userAgent();
493
500
  const comment: WalineCommentData = {
@@ -496,7 +503,6 @@ const submitComment = async (): Promise<void> => {
496
503
  mail: userMeta.value.mail,
497
504
  link: userMeta.value.link,
498
505
  url: config.value.path,
499
- recaptchaV3: token,
500
506
  ua,
501
507
  };
502
508
 
@@ -527,14 +533,14 @@ const submitComment = async (): Promise<void> => {
527
533
  return alert(locale.value.mailError);
528
534
  }
529
535
 
530
- // check comment
531
- if (!comment.comment) {
532
- editorRef.value?.focus();
536
+ if (!comment.nick) comment.nick = locale.value.anonymous;
537
+ }
533
538
 
534
- return;
535
- }
539
+ // check comment
540
+ if (!comment.comment) {
541
+ editorRef.value?.focus();
536
542
 
537
- if (!comment.nick) comment.nick = locale.value.anonymous;
543
+ return;
538
544
  }
539
545
 
540
546
  if (!isWordNumberLegal.value)
@@ -555,37 +561,44 @@ const submitComment = async (): Promise<void> => {
555
561
 
556
562
  isSubmitting.value = true;
557
563
 
558
- const options = {
559
- serverURL,
560
- lang,
561
- token: userInfo.value?.token,
562
- comment,
563
- };
564
+ try {
565
+ if (recaptchaV3Key)
566
+ comment.recaptchaV3 = await useReCaptcha(recaptchaV3Key).execute('social');
564
567
 
565
- void (
566
- props.edit
567
- ? updateComment({ objectId: props.edit.objectId, ...options })
568
- : addComment(options)
569
- )
570
- .then((resp) => {
571
- isSubmitting.value = false;
568
+ if (turnstileKey)
569
+ comment.turnstile = await useTurnstile(turnstileKey).execute('social');
572
570
 
573
- if (resp.errmsg) return alert(resp.errmsg);
571
+ const options = {
572
+ serverURL,
573
+ lang,
574
+ token: userInfo.value?.token,
575
+ comment,
576
+ };
574
577
 
575
- emit('submit', resp.data!);
578
+ const resp = await (props.edit
579
+ ? updateComment({
580
+ objectId: props.edit.objectId,
581
+ ...options,
582
+ })
583
+ : addComment(options));
576
584
 
577
- editor.value = '';
585
+ isSubmitting.value = false;
578
586
 
579
- previewText.value = '';
587
+ if (resp.errmsg) return alert(resp.errmsg);
580
588
 
581
- if (props.replyId) emit('cancelReply');
582
- if (props.edit?.objectId) emit('cancelEdit');
583
- })
584
- .catch((err: TypeError) => {
585
- isSubmitting.value = false;
589
+ emit('submit', resp.data!);
586
590
 
587
- alert(err.message);
588
- });
591
+ editor.value = '';
592
+
593
+ previewText.value = '';
594
+
595
+ if (props.replyId) emit('cancelReply');
596
+ if (props.edit?.objectId) emit('cancelEdit');
597
+ } catch (err: unknown) {
598
+ isSubmitting.value = false;
599
+
600
+ alert((err as TypeError).message);
601
+ }
589
602
  };
590
603
 
591
604
  const onLogin = (event: Event): void => {
@@ -13,7 +13,7 @@
13
13
  class="wl-nick"
14
14
  :href="link"
15
15
  target="_blank"
16
- rel="noopener noreferrer"
16
+ rel="nofollow noopener noreferrer"
17
17
  >{{ comment.nick }}</a
18
18
  >
19
19
 
@@ -177,7 +177,8 @@
177
177
 
178
178
  <script setup lang="ts">
179
179
  import { useNow } from '@vueuse/core';
180
- import { computed, inject } from 'vue';
180
+ import { type ComputedRef, computed, inject } from 'vue';
181
+
181
182
  import CommentBox from './CommentBox.vue';
182
183
  import {
183
184
  DeleteIcon,
@@ -186,12 +187,12 @@ import {
186
187
  ReplyIcon,
187
188
  VerifiedIcon,
188
189
  } from './Icons.js';
189
- import { getTimeAgo, isLinkHttp } from '../utils';
190
190
  import { useLikeStorage, useUserInfo } from '../composables/index.js';
191
-
192
- import type { ComputedRef } from 'vue';
193
- import type { WalineConfig } from '../utils/index.js';
194
- import type { WalineComment, WalineCommentStatus } from '../typings/index.js';
191
+ import {
192
+ type WalineComment,
193
+ type WalineCommentStatus,
194
+ } from '../typings/index.js';
195
+ import { type WalineConfig, getTimeAgo, isLinkHttp } from '../utils/index.js';
195
196
 
196
197
  const props = withDefaults(
197
198
  defineProps<{
@@ -1,5 +1,4 @@
1
- import { h } from 'vue';
2
- import type { FunctionalComponent } from 'vue';
1
+ import { type FunctionalComponent, h } from 'vue';
3
2
 
4
3
  export const CloseIcon: FunctionalComponent<{ size: number }> = ({ size }) =>
5
4
  h(
@@ -127,7 +126,9 @@ export const VerifiedIcon: FunctionalComponent = () =>
127
126
  })
128
127
  );
129
128
 
130
- export const LoadingIcon: FunctionalComponent<{ size: number }> = ({ size }) =>
129
+ export const LoadingIcon: FunctionalComponent<{ size?: number }> = ({
130
+ size = 100,
131
+ }) =>
131
132
  h(
132
133
  'svg',
133
134
  {
@@ -59,8 +59,7 @@
59
59
  import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
60
60
 
61
61
  import { LoadingIcon } from './Icons.js';
62
-
63
- import type { WalineSearchResult } from '../typings/index.js';
62
+ import { type WalineSearchResult } from '../typings/index.js';
64
63
 
65
64
  type Column = number[];
66
65
 
@@ -90,22 +90,22 @@
90
90
  /* eslint-disable vue/require-prop-types */
91
91
  import { useStyleTag } from '@vueuse/core';
92
92
  import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue';
93
+
93
94
  import Reaction from './ArticleReaction.vue';
94
95
  import CommentBox from './CommentBox.vue';
95
96
  import CommentCard from './CommentCard.vue';
96
97
  import { LoadingIcon } from './Icons.js';
97
98
  import { deleteComment, getComment, updateComment } from '../api/index.js';
98
99
  import { useUserInfo, useLikeStorage } from '../composables/index.js';
100
+ import {
101
+ type WalineComment,
102
+ type WalineCommentSorting,
103
+ type WalineCommentStatus,
104
+ type WalineProps,
105
+ } from '../typings/index.js';
99
106
  import { getConfig, getDarkStyle } from '../utils/index.js';
100
107
  import { version } from '../version.js';
101
108
 
102
- import type {
103
- WalineComment,
104
- WalineCommentSorting,
105
- WalineCommentStatus,
106
- WalineProps,
107
- } from '../typings/index.js';
108
-
109
109
  type SortKey = 'insertedAt_desc' | 'insertedAt_asc' | 'like_desc';
110
110
 
111
111
  const props = defineProps([
@@ -127,6 +127,7 @@ const props = defineProps([
127
127
  'search',
128
128
  'copyright',
129
129
  'recaptchaV3Key',
130
+ 'turnstileKey',
130
131
  'reaction',
131
132
  ]);
132
133
 
@@ -1,5 +1,4 @@
1
- import { useStorage } from '@vueuse/core';
2
- import type { RemovableRef } from '@vueuse/core';
1
+ import { type RemovableRef, useStorage } from '@vueuse/core';
3
2
 
4
3
  export interface UserMeta {
5
4
  nick: string;
@@ -1,6 +1,5 @@
1
1
  import { useStorage } from '@vueuse/core';
2
-
3
- import type { Ref } from 'vue';
2
+ import { type Ref } from 'vue';
4
3
 
5
4
  const LIKE_KEY = 'WALINE_LIKE';
6
5
 
@@ -1,6 +1,5 @@
1
1
  import { useStorage } from '@vueuse/core';
2
-
3
- import type { Ref } from 'vue';
2
+ import { type Ref } from 'vue';
4
3
 
5
4
  const REACTION_KEY = 'WALINE_REACTION';
6
5
 
@@ -1,6 +1,4 @@
1
- import { load } from 'recaptcha-v3';
2
-
3
- import type { ReCaptchaInstance } from 'recaptcha-v3';
1
+ import { type ReCaptchaInstance, load } from 'recaptcha-v3';
4
2
 
5
3
  const recaptchaStore: Record<string, Promise<ReCaptchaInstance>> = {};
6
4
 
@@ -0,0 +1,79 @@
1
+ interface TurnstileOptions {
2
+ sitekey: string;
3
+ action?: string;
4
+ size?: 'normal' | 'compact';
5
+ callback?: (token: string) => void;
6
+ }
7
+ interface TurnstileInstance {
8
+ ready: (fn: () => void) => void;
9
+ render: (className: string, options?: TurnstileOptions) => void;
10
+ }
11
+
12
+ declare global {
13
+ interface Window {
14
+ turnstile?: TurnstileInstance;
15
+ }
16
+ }
17
+
18
+ interface Turnstile {
19
+ execute: (action: string) => Promise<string>;
20
+ }
21
+
22
+ interface LoadScriptParameters {
23
+ src: string;
24
+ async?: boolean;
25
+ defer?: boolean;
26
+ }
27
+
28
+ const isBrowser =
29
+ typeof window !== 'undefined' && typeof window.document !== 'undefined';
30
+
31
+ async function loadScript(
32
+ options: LoadScriptParameters
33
+ ): Promise<Event | undefined> {
34
+ if (!isBrowser) {
35
+ return Promise.resolve(undefined);
36
+ }
37
+
38
+ const el = document.createElement('script');
39
+
40
+ el.async = Boolean(options.async);
41
+ el.defer = Boolean(options.defer);
42
+
43
+ return new Promise((resolve, reject) => {
44
+ el.onload = resolve;
45
+ el.onerror = reject;
46
+ el.src = options.src;
47
+
48
+ document.head.appendChild(el);
49
+ });
50
+ }
51
+
52
+ const turnstileScriptPromise = loadScript({
53
+ src: 'https://challenges.cloudflare.com/turnstile/v0/api.js',
54
+ async: false,
55
+ });
56
+
57
+ export const useTurnstile = (key: string): Turnstile => {
58
+ async function execute(action: string): Promise<string> {
59
+ await turnstileScriptPromise;
60
+ const turnstile = window?.turnstile;
61
+
62
+ return new Promise((resolve) => {
63
+ const options: TurnstileOptions = {
64
+ sitekey: key,
65
+ action,
66
+ size: 'compact',
67
+ callback(token: string): void {
68
+ resolve(token);
69
+ },
70
+ };
71
+
72
+ turnstile?.ready(() =>
73
+ turnstile?.render('.wl-captcha-container', options)
74
+ );
75
+ });
76
+ }
77
+
78
+ return { execute };
79
+ };
@@ -1,7 +1,7 @@
1
1
  import { useStorage } from '@vueuse/core';
2
+ import { type Ref } from 'vue';
2
3
 
3
- import type { Ref } from 'vue';
4
- import type { UserInfo } from '../api';
4
+ import { type UserInfo } from '../api/index.js';
5
5
 
6
6
  export const USER_KEY = 'WALINE_USER';
7
7