diff --git a/plugins/plugin-comment/src/client/components/ArtalkComment.ts b/plugins/plugin-comment/src/client/components/ArtalkComment.ts index 6bd885b7f2..ae41c69dcb 100644 --- a/plugins/plugin-comment/src/client/components/ArtalkComment.ts +++ b/plugins/plugin-comment/src/client/components/ArtalkComment.ts @@ -2,6 +2,7 @@ import { isString } from '@vuepress/helper/client' import type Artalk from 'artalk' import type { VNode } from 'vue' import { + computed, defineComponent, h, nextTick, @@ -48,7 +49,7 @@ export default defineComponent({ let artalk: Artalk | null = null - const enableArtalk = isString(artalkOptions.server) + const enableArtalk = computed(() => isString(artalkOptions.value.server)) const initArtalk = async (): Promise => { const [{ default: Artalk }] = await Promise.all([ @@ -56,7 +57,7 @@ export default defineComponent({ new Promise((resolve) => { setTimeout(() => { resolve() - }, artalkOptions.delay || 800) + }, artalkOptions.value.delay || 800) }), ]) @@ -67,13 +68,13 @@ export default defineComponent({ useBackendConf: false, site: site.value.title, pageTitle: page.value.title, - ...artalkOptions, + ...artalkOptions.value, el: artalkContainer.value!, pageKey: props.identifier, darkMode: props.darkmode, }) - if (artalkOptions.useBackendConf) + if (artalkOptions.value.useBackendConf) artalk.on('mounted', () => { artalk!.setDarkMode(props.darkmode) }) @@ -89,7 +90,14 @@ export default defineComponent({ } onMounted(() => { - initArtalk() + watch( + () => artalkOptions.value, + () => { + artalk?.destroy() + initArtalk() + }, + { immediate: true }, + ) watch( () => props.identifier, @@ -111,7 +119,7 @@ export default defineComponent({ }) return (): VNode | null => - enableArtalk + enableArtalk.value ? h('div', { class: 'artalk-wrapper' }, [ loaded.value ? null : h(LoadingIcon), h('div', { ref: artalkContainer }), diff --git a/plugins/plugin-comment/src/client/components/CommentService.ts b/plugins/plugin-comment/src/client/components/CommentService.ts index 3c4e630803..4d5380c169 100644 --- a/plugins/plugin-comment/src/client/components/CommentService.ts +++ b/plugins/plugin-comment/src/client/components/CommentService.ts @@ -22,12 +22,12 @@ export default defineComponent({ const page = usePageData() const frontmatter = usePageFrontmatter() - const enableComment = commentOptions.comment !== false + const enableComment = computed(() => commentOptions.value.comment !== false) const enabled = computed( () => frontmatter.value.comment || - (enableComment && frontmatter.value.comment !== false), + (enableComment.value && frontmatter.value.comment !== false), ) return (): VNode | null => diff --git a/plugins/plugin-comment/src/client/components/GiscusComment.ts b/plugins/plugin-comment/src/client/components/GiscusComment.ts index 4fbd936565..4aefc4d91a 100644 --- a/plugins/plugin-comment/src/client/components/GiscusComment.ts +++ b/plugins/plugin-comment/src/client/components/GiscusComment.ts @@ -89,15 +89,15 @@ export default defineComponent({ const giscusOptions = useGiscusOptions() const lang = usePageLang() - const enableGiscus = Boolean( - giscusOptions.repo && - giscusOptions.repoId && - giscusOptions.category && - giscusOptions.categoryId, + const enableGiscus = computed(() => + Boolean( + giscusOptions.value.repo && + giscusOptions.value.repoId && + giscusOptions.value.category && + giscusOptions.value.categoryId, + ), ) - const { repo, repoId, category, categoryId } = giscusOptions - const loaded = ref(false) const giscusLang = computed(() => { @@ -114,21 +114,21 @@ export default defineComponent({ const config = computed( () => ({ - repo, - repoId, - category, - categoryId, + repo: giscusOptions.value.repo, + repoId: giscusOptions.value.repoId, + category: giscusOptions.value.category, + categoryId: giscusOptions.value.categoryId, lang: giscusLang.value, theme: props.darkmode - ? giscusOptions.darkTheme || 'dark' - : giscusOptions.lightTheme || 'light', - mapping: giscusOptions.mapping || 'pathname', + ? giscusOptions.value.darkTheme || 'dark' + : giscusOptions.value.lightTheme || 'light', + mapping: giscusOptions.value.mapping || 'pathname', term: props.identifier, - inputPosition: giscusOptions.inputPosition || 'top', + inputPosition: giscusOptions.value.inputPosition || 'top', reactionsEnabled: - giscusOptions.reactionsEnabled === false ? '0' : '1', - strict: giscusOptions.strict === false ? '0' : '1', - loading: giscusOptions.lazyLoading === false ? 'eager' : 'lazy', + giscusOptions.value.reactionsEnabled === false ? '0' : '1', + strict: giscusOptions.value.strict === false ? '0' : '1', + loading: giscusOptions.value.lazyLoading === false ? 'eager' : 'lazy', emitMetadata: '0', }) as GiscusProps, ) @@ -139,14 +139,14 @@ export default defineComponent({ }) return (): VNode | null => - enableGiscus + enableGiscus.value ? h( 'div', { id: 'comment', class: [ 'giscus-wrapper', - { 'input-top': giscusOptions.inputPosition !== 'bottom' }, + { 'input-top': giscusOptions.value.inputPosition !== 'bottom' }, ], }, loaded.value ? h('giscus-widget', config.value) : h(LoadingIcon), diff --git a/plugins/plugin-comment/src/client/components/TwikooComment.ts b/plugins/plugin-comment/src/client/components/TwikooComment.ts index a206d1fb15..d5f480d730 100644 --- a/plugins/plugin-comment/src/client/components/TwikooComment.ts +++ b/plugins/plugin-comment/src/client/components/TwikooComment.ts @@ -1,5 +1,13 @@ import type { VNode } from 'vue' -import { defineComponent, h, nextTick, onMounted, ref, watch } from 'vue' +import { + computed, + defineComponent, + h, + nextTick, + onMounted, + ref, + watch, +} from 'vue' import { usePageLang } from 'vuepress/client' import { useTwikooOptions } from '../helpers/index.js' import { LoadingIcon } from './LoadingIcon.js' @@ -23,7 +31,7 @@ export default defineComponent({ const loaded = ref(false) - const enableTwikoo = Boolean(twikooOptions.envId) + const enableTwikoo = computed(() => Boolean(twikooOptions.value.envId)) const initTwikoo = async (): Promise => { const [{ init }] = await Promise.all([ @@ -31,7 +39,7 @@ export default defineComponent({ new Promise((resolve) => { setTimeout(() => { resolve() - }, twikooOptions.delay || 800) + }, twikooOptions.value.delay || 800) }), ]) @@ -42,21 +50,21 @@ export default defineComponent({ await init({ lang: lang.value === 'zh-CN' ? 'zh-CN' : 'en', path: props.identifier, - ...twikooOptions, + ...twikooOptions.value, el: '#twikoo-comment', }) } onMounted(() => { watch( - () => props.identifier, + () => [props.identifier, twikooOptions.value], () => initTwikoo(), { immediate: true }, ) }) return (): VNode | null => - enableTwikoo + enableTwikoo.value ? h('div', { id: 'comment', class: 'twikoo-wrapper' }, [ loaded.value ? null : h(LoadingIcon), h('div', { id: 'twikoo-comment' }), diff --git a/plugins/plugin-comment/src/client/components/WalineComment.ts b/plugins/plugin-comment/src/client/components/WalineComment.ts index a0338ee1f2..11dc95223e 100644 --- a/plugins/plugin-comment/src/client/components/WalineComment.ts +++ b/plugins/plugin-comment/src/client/components/WalineComment.ts @@ -48,11 +48,11 @@ export default defineComponent({ const walineLocale = useLocaleConfig(walineLocales) let abort: () => void - const enableWaline = Boolean(walineOptions.serverURL) + const enableWaline = computed(() => Boolean(walineOptions.value.serverURL)) const enablePageViews = computed(() => { - if (!enableWaline) return false - const pluginConfig = walineOptions.pageview !== false + if (!enableWaline.value) return false + const pluginConfig = walineOptions.value.pageview !== false const pageConfig = frontmatter.value.pageview return ( @@ -67,13 +67,18 @@ export default defineComponent({ lang: lang.value === 'zh-CN' ? 'zh-CN' : 'en', locale: walineLocale.value, dark: 'html.dark', - ...walineOptions, + ...walineOptions.value, path: props.identifier, })) onMounted(() => { watch( - () => props.identifier, + () => [ + props.identifier, + walineOptions.value.serverURL, + walineOptions.value.delay, + enablePageViews.value, + ], () => { abort?.() @@ -81,10 +86,10 @@ export default defineComponent({ nextTick().then(() => { setTimeout(() => { abort = pageviewCount({ - serverURL: walineOptions.serverURL, + serverURL: walineOptions.value.serverURL, path: props.identifier, }) - }, walineOptions.delay || 800) + }, walineOptions.value.delay || 800) }) }, { immediate: true }, @@ -92,7 +97,7 @@ export default defineComponent({ }) return (): VNode | null => - enableWaline + enableWaline.value ? h( 'div', { id: 'comment', class: 'waline-wrapper' }, diff --git a/plugins/plugin-comment/src/client/helpers/comment.ts b/plugins/plugin-comment/src/client/helpers/comment.ts index 7be5536a49..b538b74b45 100644 --- a/plugins/plugin-comment/src/client/helpers/comment.ts +++ b/plugins/plugin-comment/src/client/helpers/comment.ts @@ -1,5 +1,6 @@ -import type { App } from 'vue' -import { inject } from 'vue' +import { isFunction } from '@vuepress/helper/client' +import type { App, MaybeRefOrGetter, Ref } from 'vue' +import { inject, isRef, ref, watch } from 'vue' import type { ArtalkOptions, CommentOptions, @@ -13,15 +14,30 @@ declare const __COMMENT_OPTIONS__: CommentOptions const commentOptions = __COMMENT_OPTIONS__ -let comment: CommentOptions = commentOptions +const comment: Ref = ref(commentOptions) const commentSymbol = Symbol(__VUEPRESS_DEV__ ? 'comment' : '') -const defineCommentConfig = (options: T): void => { - comment = { ...commentOptions, ...options } +const defineCommentConfig = ( + options: MaybeRefOrGetter, +): void => { + if (isRef(options)) { + watch( + () => options.value, + (value) => { + comment.value = { ...commentOptions, ...value } + }, + ) + } else if (isFunction(options)) { + watch(options, (value) => { + comment.value = { ...commentOptions, ...value } + }) + } else { + comment.value = { ...commentOptions, ...options } + } } -export const useCommentOptions = (): T => +export const useCommentOptions = (): Ref => inject(commentSymbol)! export const defineArtalkConfig = defineCommentConfig diff --git a/plugins/plugin-comment/src/client/pageview/artalk.ts b/plugins/plugin-comment/src/client/pageview/artalk.ts index dd28aca5fa..7ba6e9bcd5 100644 --- a/plugins/plugin-comment/src/client/pageview/artalk.ts +++ b/plugins/plugin-comment/src/client/pageview/artalk.ts @@ -5,12 +5,12 @@ import type { UpdatePageview } from './typings.js' export const isSupported = true export const usePageview = (): UpdatePageview => { - const { server, site } = useArtalkOptions() + const options = useArtalkOptions() return ({ selector }) => Artalk.loadCountWidget({ - server, - site, + server: options.value.server, + site: options.value.site, ...(selector ? { countEl: selector } : {}), }) } diff --git a/plugins/plugin-comment/src/client/pageview/waline.ts b/plugins/plugin-comment/src/client/pageview/waline.ts index 8dd06211e5..e7faf4a42e 100644 --- a/plugins/plugin-comment/src/client/pageview/waline.ts +++ b/plugins/plugin-comment/src/client/pageview/waline.ts @@ -5,7 +5,8 @@ import type { UpdatePageview } from './typings.js' export const isSupported = true export const usePageview = (): UpdatePageview => { - const { serverURL } = useWalineOptions() + const walineOptions = useWalineOptions() - return (options) => pageviewCount({ serverURL, ...options }) + return (options) => + pageviewCount({ serverURL: walineOptions.value.serverURL, ...options }) } diff --git a/plugins/plugin-docsearch/src/client/helpers/docsearch.ts b/plugins/plugin-docsearch/src/client/helpers/docsearch.ts index 458c15d430..e3258d10ef 100644 --- a/plugins/plugin-docsearch/src/client/helpers/docsearch.ts +++ b/plugins/plugin-docsearch/src/client/helpers/docsearch.ts @@ -1,7 +1,7 @@ import type { DocSearchProps } from '@docsearch/react' -import { deepAssign } from '@vuepress/helper/client' -import type { App, ComputedRef, InjectionKey } from 'vue' -import { computed, inject } from 'vue' +import { deepAssign, isFunction } from '@vuepress/helper/client' +import type { App, ComputedRef, InjectionKey, MaybeRefOrGetter, Ref } from 'vue' +import { computed, inject, isRef, ref, watch } from 'vue' import { useRouteLocale } from 'vuepress/client' import type { DocsearchOptions } from '../../shared/index.js' @@ -10,12 +10,14 @@ declare const __DOCSEARCH_OPTIONS__: DocsearchOptions const docSearchOptions: Partial = __DOCSEARCH_OPTIONS__ -let docsearch: Partial = docSearchOptions +const docsearch: Ref> = ref(docSearchOptions) const docsearchSymbol: InjectionKey< - DocSearchProps & { - locales?: Record - } + Ref< + DocSearchProps & { + locales?: Record + } + > > = Symbol(__VUEPRESS_DEV__ ? 'docsearch' : '') export type DocSearchClientLocaleOptions = Partial< @@ -27,9 +29,22 @@ export interface DocSearchClientOptions extends DocSearchClientLocaleOptions { } export const defineDocSearchConfig = ( - options: DocSearchClientOptions, + options: MaybeRefOrGetter, ): void => { - docsearch = deepAssign({}, docSearchOptions, options) + if (isRef(options)) { + watch( + () => options.value, + (value) => { + docsearch.value = deepAssign({}, docSearchOptions, value) + }, + ) + } else if (isFunction(options)) { + watch(options, (value) => { + docsearch.value = deepAssign({}, docSearchOptions, value) + }) + } else { + docsearch.value = deepAssign({}, docSearchOptions, options) + } } export const useDocSearchOptions = (): ComputedRef => { @@ -37,8 +52,8 @@ export const useDocSearchOptions = (): ComputedRef => { const routeLocale = useRouteLocale() return computed(() => ({ - ...options, - ...options.locales?.[routeLocale.value], + ...options.value, + ...options.value.locales?.[routeLocale.value], })) } diff --git a/plugins/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts b/plugins/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts index 9cf17056fb..26d1173223 100644 --- a/plugins/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts +++ b/plugins/plugin-photo-swipe/src/client/composables/usePhotoSwipe.ts @@ -45,7 +45,7 @@ export const usePhotoSwipe = ({ destroy = await registerPhotoSwipe( getImages(imageSelector), { - ...photoSwipeOptions, + ...photoSwipeOptions.value, ...locale.value, }, scrollToClose, @@ -57,7 +57,7 @@ export const usePhotoSwipe = ({ setupPhotoSwipe() watch( - () => page.value.path, + () => [page.value.path, photoSwipeOptions.value], () => { destroy?.() setupPhotoSwipe() diff --git a/plugins/plugin-photo-swipe/src/client/helpers/photo-swipe.ts b/plugins/plugin-photo-swipe/src/client/helpers/photo-swipe.ts index e8968e24b3..9ed32279b3 100644 --- a/plugins/plugin-photo-swipe/src/client/helpers/photo-swipe.ts +++ b/plugins/plugin-photo-swipe/src/client/helpers/photo-swipe.ts @@ -1,6 +1,7 @@ +import { isFunction } from '@vuepress/helper/client' import type { PhotoSwipeOptions as OriginalPhotoSwipeOptions } from 'photoswipe' -import type { App } from 'vue' -import { inject } from 'vue' +import type { App, MaybeRefOrGetter, Ref } from 'vue' +import { inject, isRef, ref, watch } from 'vue' export type PhotoSwipeOptions = Omit< OriginalPhotoSwipeOptions, @@ -10,15 +11,30 @@ export type PhotoSwipeOptions = Omit< declare const __VUEPRESS_DEV__: boolean -let photoswipeOptions: PhotoSwipeOptions = {} +const photoswipeOptions: Ref = ref({}) const photoswipeSymbol = Symbol(__VUEPRESS_DEV__ ? 'photoswipe' : '') -export const definePhotoSwipeConfig = (options: PhotoSwipeOptions): void => { - photoswipeOptions = options +export const definePhotoSwipeConfig = ( + options: MaybeRefOrGetter, +): void => { + if (isRef(options)) { + watch( + () => options.value, + (value) => { + photoswipeOptions.value = value + }, + ) + } else if (isFunction(options)) { + watch(options, (value) => { + photoswipeOptions.value = value + }) + } else { + photoswipeOptions.value = options + } } -export const usePhotoSwipeOptions = (): PhotoSwipeOptions => +export const usePhotoSwipeOptions = (): Ref => inject(photoswipeSymbol)! export const injectPhotoSwipeConfig = (app: App): void => {