@vuepress/plugin-pwa 2.0.0-rc.128 → 2.0.0-rc.130

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.
@@ -1,15 +1,15 @@
1
- import { t as PwaPluginLocaleConfig } from "./types-BLkMmayH.js";
1
+ import { t as PwaPluginLocaleConfig } from "./types-0w9cSsje.js";
2
2
  import { Slot } from "@vuepress/helper/client";
3
3
  import * as _$vue from "vue";
4
4
  import { PropType, SlotsType, VNode } from "vue";
5
5
  //#region src/client/components/PwaFoundPopup.d.ts
6
6
  declare const PwaFoundPopup: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
7
- /** locale data */locales: {
7
+ /** Locale data */locales: {
8
8
  type: PropType<PwaPluginLocaleConfig>;
9
9
  required: true;
10
10
  };
11
11
  }>, () => VNode, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<_$vue.ExtractPropTypes<{
12
- /** locale data */locales: {
12
+ /** Locale data */locales: {
13
13
  type: PropType<PwaPluginLocaleConfig>;
14
14
  required: true;
15
15
  };
@@ -21,4 +21,4 @@ declare const PwaFoundPopup: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
21
21
  }>, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
22
22
  //#endregion
23
23
  export { PwaFoundPopup as t };
24
- //# sourceMappingURL=PwaFoundPopup-U47ypQoC.d.ts.map
24
+ //# sourceMappingURL=PwaFoundPopup-DxHCqVkp.d.ts.map
@@ -1,19 +1,19 @@
1
- import { t as PwaPluginLocaleConfig } from "./types-BLkMmayH.js";
1
+ import { t as PwaPluginLocaleConfig } from "./types-0w9cSsje.js";
2
2
  import * as _$vue from "vue";
3
3
  import { PropType, VNode } from "vue";
4
4
 
5
5
  //#region src/client/components/PwaInstall.d.ts
6
6
  declare const PwaInstall: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
7
- /** locale data */locales: {
7
+ /** Locale data */locales: {
8
8
  type: PropType<PwaPluginLocaleConfig>;
9
9
  required: true;
10
10
  };
11
11
  }>, () => VNode, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<_$vue.ExtractPropTypes<{
12
- /** locale data */locales: {
12
+ /** Locale data */locales: {
13
13
  type: PropType<PwaPluginLocaleConfig>;
14
14
  required: true;
15
15
  };
16
16
  }>> & Readonly<{}>, {}, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
17
17
  //#endregion
18
18
  export { PwaInstall as t };
19
- //# sourceMappingURL=PwaInstall-IlBEJ5C2.d.ts.map
19
+ //# sourceMappingURL=PwaInstall-BXTaTtiv.d.ts.map
@@ -0,0 +1,3 @@
1
+ import './PwaInstall-DJF1evx8.css';
2
+ import{n as e,r as t,t as n}from"./icons-RRw4DIWa.js";import{useLocale as r}from"@vuepress/helper/client";import{useEventListener as i,useToggle as a}from"@vueuse/core";import{computed as o,defineComponent as s,h as c,onMounted as l,ref as u,shallowRef as d}from"vue";import{withBase as f}from"vuepress/client";const p=()=>{let e=document.querySelector(`.screenshot`);e&&e.scrollBy({left:-e.clientWidth,top:0,behavior:`smooth`})},m=()=>{let e=document.querySelector(`.screenshot`);e&&e.scrollBy({left:e.clientWidth,top:0,behavior:`smooth`})},h=s({name:`PwaInstallModal`,props:{locales:{type:Object,required:!0},useHint:Boolean},emits:[`canInstall`,`hint`,`close`],setup(a,{emit:o}){let s=r(a.locales),u=d({}),h=d(),g=async()=>{let e=localStorage.getItem(`manifest`);if(e)u.value=JSON.parse(e);else try{let e=await(await fetch(f(`manifest.webmanifest`))).json();u.value=e,localStorage.setItem(`manifest`,JSON.stringify(e))}catch{console.error(`[PWA]: Error getting manifest, check that you have a valid web manifest or network connection`)}},_=async()=>{if(h.value){h.value.prompt(),document.dispatchEvent(new CustomEvent(`show`));let e=await h.value.userChoice;console.info(e.outcome===`accepted`?`PWA has been installed`:`You choose to not install PWA`),o(`close`,!1),o(`canInstall`,!1)}},v=()=>{console.info(`You accepted the install hint`),o(`hint`)};return l(()=>{window.hasOwnProperty(`BeforeInstallPromptEvent`)&&(i(window,`beforeinstallprompt`,e=>{h.value=e,o(`canInstall`,!0),e.preventDefault()}),i(`keyup`,e=>{e.key===`Escape`&&o(`close`,!1)},{passive:!0}),g())}),()=>c(`div`,{id:`install-modal-wrapper`},[c(`div`,{class:`background`,onClick:()=>{o(`close`,!1)}}),c(`div`,{class:`install-modal`},[c(`div`,{class:`header`},[c(`button`,{type:`button`,class:`close-button`,"aria-label":s.value.close,onClick:()=>{o(`close`,!1)}},c(t)),c(`div`,{class:`logo`},[u.value.icons?c(`img`,{src:u.value.icons[0]?.src,alt:`App Logo`}):null,c(`div`,{class:`title`},[c(`h1`,u.value.short_name||u.value.name),c(`p`,{class:`desc`},s.value.explain)])])]),c(`div`,{class:`content`},[c(`div`,{class:`highlight`},[u.value.features?c(`div`,{class:`feature-wrapper`},[c(`h3`,s.value.feature),c(`ul`,u.value.features.map(e=>c(`li`,e)))]):null,u.value.screenshots?c(`div`,{class:`screenshot-wrapper`},[c(`button`,{type:`button`,"aria-label":s.value.prevImage,onClick:p},c(n)),c(`section`,{class:`screenshot`},[u.value.screenshots.map(e=>c(`div`,c(`img`,{src:e.src,alt:`App Screenshot`})))]),c(`button`,{type:`button`,"aria-label":s.value.nextImage,onClick:m},c(e))]):null]),c(`div`,{class:`description`},[c(`h3`,s.value.desc),c(`p`,u.value.description)])]),a.useHint?c(`div`,{class:`ios-text`,onClick:v},[c(`p`,s.value.iOSInstall),c(`button`,{type:`button`,class:`success`},`Got it!`)]):c(`div`,{class:`button-wrapper`},[c(`button`,{type:`button`,class:`install-button`,onClick:_},[s.value.install,c(`span`,u.value.short_name)]),c(`button`,{type:`button`,class:`cancel-button`,onClick:()=>{o(`close`,!1)}},s.value.cancel)])])])}}),g=s({name:`PwaInstall`,props:{locales:{type:Object,required:!0}},setup(e){let t=r(e.locales),[n,i]=a(),s=u(!1),d=u(!1),f=u(!1),p=u(!1),m=u(!1),g=o(()=>f.value&&p.value&&!m.value),_=o(()=>d.value&&s.value||g.value),v=()=>navigator.standalone?navigator.standalone:matchMedia(`(display-mode: standalone)`).matches,y=()=>{i(!1),m.value=!0,localStorage.setItem(`iOS-pwa-hint`,`hinted`)};return l(()=>{if(v()){let{userAgent:e}=navigator;f.value=e.includes(`iPhone`)||e.includes(`iPad`)||!!(e.includes(`Macintosh`)&&navigator.maxTouchPoints&&navigator.maxTouchPoints>2),p.value=navigator.userAgent.includes(`Safari`)&&!e.includes(`Chrome`),m.value=!!localStorage.getItem(`iOS-pwa-hint`)}`getInstalledRelatedApps`in navigator&&navigator.getInstalledRelatedApps().then(e=>{d.value=e.length>0})}),()=>c(`div`,{id:`pwa-install`},[_.value?c(`button`,{type:`button`,class:`modal-button`,onClick:()=>{i(!0)}},t.value.install):null,c(h,{style:{display:n.value?`block`:`none`},locales:e.locales,useHint:g.value,onCanInstall:e=>{s.value=e},onHint:()=>{y()},onClose:()=>i(!1)})])}});export{g as t};
3
+ //# sourceMappingURL=PwaInstall-DJF1evx8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PwaInstall-DJF1evx8.js","names":[],"sources":["../src/client/components/PwaInstallModal.ts","../src/client/components/PwaInstall.ts"],"sourcesContent":["/* oxlint-disable no-console */\nimport { useLocale } from '@vuepress/helper/client'\nimport { useEventListener } from '@vueuse/core'\nimport type { PropType, VNode } from 'vue'\nimport { defineComponent, h, onMounted, shallowRef } from 'vue'\nimport { withBase } from 'vuepress/client'\n\nimport type { AppManifest } from '../../shared/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { ArrowLeftIcon, ArrowRightIcon, CloseIcon } from './icons.js'\n\ninterface InstallPromptEvent extends Event {\n readonly platforms: string\n prompt: () => void\n readonly userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>\n}\n\nconst scrollToLeft = (): void => {\n const screenshotsDiv = document.querySelector('.screenshot')\n\n if (screenshotsDiv) {\n screenshotsDiv.scrollBy({\n left: -screenshotsDiv.clientWidth,\n top: 0,\n behavior: 'smooth',\n })\n }\n}\n\nconst scrollToRight = (): void => {\n const screenshotsDiv = document.querySelector('.screenshot')\n\n if (screenshotsDiv) {\n screenshotsDiv.scrollBy({\n left: screenshotsDiv.clientWidth,\n top: 0,\n behavior: 'smooth',\n })\n }\n}\n\nexport const PwaInstallModal = defineComponent({\n name: 'PwaInstallModal',\n\n props: {\n /** Locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n\n /**\n * Whether use hint message instead of showing a button\n *\n * 是否使用提示\n */\n useHint: Boolean,\n },\n\n emits: ['canInstall', 'hint', 'close'],\n\n setup(props, { emit }) {\n const locale = useLocale(props.locales)\n\n const manifest = shallowRef<AppManifest>({})\n const deferredPrompt = shallowRef<InstallPromptEvent>()\n\n const getManifest = async (): Promise<void> => {\n const manifestContent = localStorage.getItem('manifest')\n\n if (manifestContent) {\n manifest.value = JSON.parse(manifestContent) as AppManifest\n } else {\n try {\n const response = await fetch(withBase('manifest.webmanifest'))\n const data = (await response.json()) as AppManifest\n\n manifest.value = data\n localStorage.setItem('manifest', JSON.stringify(data))\n } catch {\n console.error(\n '[PWA]: Error getting manifest, check that you have a valid web manifest or network connection',\n )\n }\n }\n }\n\n const install = async (): Promise<void> => {\n if (deferredPrompt.value) {\n deferredPrompt.value.prompt()\n\n document.dispatchEvent(new CustomEvent('show'))\n\n const choiceResult = await deferredPrompt.value.userChoice\n\n console.info(\n choiceResult.outcome === 'accepted'\n ? 'PWA has been installed'\n : 'You choose to not install PWA',\n )\n\n emit('close', false)\n emit('canInstall', false)\n }\n }\n\n const hint = (): void => {\n console.info('You accepted the install hint')\n emit('hint')\n }\n\n onMounted(() => {\n // oxlint-disable-next-line no-prototype-builtins\n if (window.hasOwnProperty('BeforeInstallPromptEvent')) {\n useEventListener(window, 'beforeinstallprompt', (event) => {\n deferredPrompt.value = event as InstallPromptEvent\n\n emit('canInstall', true)\n event.preventDefault()\n })\n\n useEventListener(\n 'keyup',\n (event): void => {\n if (event.key === 'Escape') emit('close', false)\n },\n { passive: true },\n )\n\n void getManifest()\n }\n })\n\n return (): VNode =>\n h('div', { id: 'install-modal-wrapper' }, [\n h('div', {\n class: 'background',\n onClick: () => {\n emit('close', false)\n },\n }),\n\n h('div', { class: 'install-modal' }, [\n h('div', { class: 'header' }, [\n // close button\n h(\n 'button',\n {\n 'type': 'button',\n 'class': 'close-button',\n 'aria-label': locale.value.close,\n 'onClick': () => {\n emit('close', false)\n },\n },\n h(CloseIcon),\n ),\n\n h('div', { class: 'logo' }, [\n manifest.value.icons\n ? h('img', {\n src: manifest.value.icons[0]?.src,\n alt: 'App Logo',\n })\n : null,\n h('div', { class: 'title' }, [\n h('h1', manifest.value.short_name || manifest.value.name),\n h('p', { class: 'desc' }, locale.value.explain),\n ]),\n ]),\n ]),\n\n h('div', { class: 'content' }, [\n h('div', { class: 'highlight' }, [\n manifest.value.features\n ? h('div', { class: 'feature-wrapper' }, [\n h('h3', locale.value.feature),\n h(\n 'ul',\n manifest.value.features.map((feature) =>\n h('li', feature),\n ),\n ),\n ])\n : null,\n\n manifest.value.screenshots\n ? h('div', { class: 'screenshot-wrapper' }, [\n h(\n 'button',\n {\n 'type': 'button',\n 'aria-label': locale.value.prevImage,\n 'onClick': scrollToLeft,\n },\n h(ArrowLeftIcon),\n ),\n h('section', { class: 'screenshot' }, [\n manifest.value.screenshots.map((screenshot) =>\n h(\n 'div',\n h('img', {\n src: screenshot.src,\n alt: 'App Screenshot',\n }),\n ),\n ),\n ]),\n h(\n 'button',\n {\n 'type': 'button',\n 'aria-label': locale.value.nextImage,\n 'onClick': scrollToRight,\n },\n h(ArrowRightIcon),\n ),\n ])\n : null,\n ]),\n\n h('div', { class: 'description' }, [\n h('h3', locale.value.desc),\n h('p', manifest.value.description),\n ]),\n ]),\n\n props.useHint\n ? h('div', { class: 'ios-text', onClick: hint }, [\n h('p', locale.value.iOSInstall),\n h('button', { type: 'button', class: 'success' }, 'Got it!'),\n ])\n : h('div', { class: 'button-wrapper' }, [\n h(\n 'button',\n { type: 'button', class: 'install-button', onClick: install },\n [locale.value.install, h('span', manifest.value.short_name)],\n ),\n h(\n 'button',\n {\n type: 'button',\n class: 'cancel-button',\n onClick: () => {\n emit('close', false)\n },\n },\n locale.value.cancel,\n ),\n ]),\n ]),\n ])\n },\n})\n","import { useLocale } from '@vuepress/helper/client'\nimport { useToggle } from '@vueuse/core'\nimport type { PropType, VNode } from 'vue'\nimport { computed, defineComponent, h, onMounted, ref } from 'vue'\n\nimport type { ManifestExternalApplicationResource } from '../../shared/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { PwaInstallModal } from './PwaInstallModal.js'\n\nimport '../styles/modal.scss'\n\ninterface ModernNavigator extends Navigator {\n // Nonstandard Api\n getInstalledRelatedApps: () => Promise<ManifestExternalApplicationResource[]>\n}\n\ninterface SafariNavigator extends Navigator {\n // Available on Apple’s iOS Safari only.\n standalone: boolean\n}\n\nexport const PwaInstall = defineComponent({\n name: 'PwaInstall',\n\n props: {\n /** Locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n },\n\n setup(props) {\n const locale = useLocale(props.locales)\n const [isOpen, toggleIsOpen] = useToggle()\n\n const canInstall = ref(false)\n const hasRelatedApps = ref(false)\n const isIOS = ref(false)\n const isSafari = ref(false)\n const hinted = ref(false)\n\n const useHint = computed(\n () => isIOS.value && isSafari.value && !hinted.value,\n )\n\n const showInstall = computed(\n () => (hasRelatedApps.value && canInstall.value) || useHint.value,\n )\n\n const getInstallStatus = (): boolean => {\n if ((navigator as SafariNavigator).standalone)\n return (navigator as SafariNavigator).standalone\n\n return matchMedia('(display-mode: standalone)').matches\n }\n\n const hint = (): void => {\n toggleIsOpen(false)\n hinted.value = true\n // do not notify again\n localStorage.setItem('iOS-pwa-hint', 'hinted')\n }\n\n onMounted(() => {\n if (getInstallStatus()) {\n const { userAgent } = navigator\n\n // handle iOS specifically\n isIOS.value =\n // regular iPhone\n userAgent.includes('iPhone') ||\n // regular iPad\n userAgent.includes('iPad') ||\n // iPad pro\n Boolean(\n userAgent.includes('Macintosh') &&\n navigator.maxTouchPoints &&\n navigator.maxTouchPoints > 2,\n )\n\n isSafari.value =\n navigator.userAgent.includes('Safari') &&\n !userAgent.includes('Chrome')\n\n hinted.value = Boolean(localStorage.getItem('iOS-pwa-hint'))\n }\n\n if ('getInstalledRelatedApps' in (navigator as ModernNavigator)) {\n void (navigator as ModernNavigator)\n .getInstalledRelatedApps()\n .then((result) => {\n hasRelatedApps.value = result.length > 0\n })\n }\n })\n\n return (): VNode =>\n h('div', { id: 'pwa-install' }, [\n showInstall.value\n ? h(\n 'button',\n {\n type: 'button',\n class: 'modal-button',\n onClick: () => {\n toggleIsOpen(true)\n },\n },\n locale.value.install,\n )\n : null,\n h(PwaInstallModal, {\n style: {\n display: isOpen.value ? 'block' : 'none',\n },\n locales: props.locales,\n useHint: useHint.value,\n onCanInstall: (value: boolean) => {\n canInstall.value = value\n },\n onHint: () => {\n hint()\n },\n onClose: () => toggleIsOpen(false),\n }),\n ])\n },\n})\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PwaReadyPopup-Da6_dOG6.js","names":[],"sources":["../src/client/utils/skipWaiting.ts","../src/client/components/PwaReadyPopup.ts"],"sourcesContent":["/**\n * Call `skipWaiting()` inside current waiting worker\n *\n * 在当前等待中的 Service Worker 中调用 `skipWaiting()`\n *\n * @param registration - The registration of the service worker you want activate / 想要激活的 Service Worker 的注册\n */\nexport const skipWaiting = (registration: ServiceWorkerRegistration): void => {\n // Get the waiting worker\n const worker = registration.waiting\n\n // If there is no waiting worker, return directly\n if (!worker) return\n\n // Post SKIP_WAITING message to the waiting worker\n const channel = new MessageChannel()\n\n worker.postMessage({ type: 'SKIP_WAITING' }, [channel.port2])\n}\n","import type { Slot } from '@vuepress/helper/client'\nimport { useLocale } from '@vuepress/helper/client'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport {\n Transition,\n computed,\n defineComponent,\n h,\n onMounted,\n shallowRef,\n} from 'vue'\n\nimport { usePwaEvent } from '../composables/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { skipWaiting } from '../utils/index.js'\nimport { UpdateIcon } from './icons.js'\n\nimport '@vuepress/helper/transition/fade-in-scale-up.css'\nimport '../styles/popup.scss'\n\nexport const PwaReadyPopup = defineComponent({\n name: 'PwaReadyPopup',\n\n props: {\n /** locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n },\n\n slots: Object as SlotsType<{\n default?: Slot<{ isReady: boolean; reload: () => void }>\n }>,\n\n setup(props, { slots }) {\n const locale = useLocale(props.locales)\n const registration = shallowRef<ServiceWorkerRegistration>()\n\n const isReady = computed(() => Boolean(registration.value))\n\n const reload = (): void => {\n if (registration.value) {\n skipWaiting(registration.value)\n registration.value = undefined\n }\n }\n\n onMounted(() => {\n const event = usePwaEvent()\n\n event.on('updated', (reg) => {\n registration.value = reg\n })\n })\n\n return (): VNode =>\n h(\n Transition,\n { name: 'fade-in-scale-up' },\n () =>\n slots.default?.({\n isReady: isReady.value,\n reload,\n }) ??\n (isReady.value\n ? h(\n 'button',\n {\n type: 'button',\n class: 'sw-update-popup',\n tabindex: 0,\n onClick: () => {\n reload()\n },\n },\n [\n locale.value.update,\n h('span', { class: 'icon-wrapper' }, h(UpdateIcon)),\n ],\n )\n : null),\n )\n },\n})\n"],"mappings":"yUAOA,MAAa,EAAe,GAAkD,CAE5E,IAAM,EAAS,EAAa,QAG5B,GAAI,CAAC,EAAQ,OAGb,IAAM,EAAU,IAAI,eAEpB,EAAO,YAAY,CAAE,KAAM,eAAgB,CAAE,CAAC,EAAQ,MAAM,CAAC,ECGlD,EAAgB,EAAgB,CAC3C,KAAM,gBAEN,MAAO,CAEL,QAAS,CACP,KAAM,OACN,SAAU,GACX,CACF,CAED,MAAO,OAIP,MAAM,EAAO,CAAE,SAAS,CACtB,IAAM,EAAS,EAAU,EAAM,QAAQ,CACjC,EAAe,GAAuC,CAEtD,EAAU,MAAe,EAAQ,EAAa,MAAO,CAErD,MAAqB,CACzB,AAEE,EAAa,SADb,EAAY,EAAa,MAAM,CACV,IAAA,KAYzB,OARA,MAAgB,CACA,GAAa,CAErB,GAAG,UAAY,GAAQ,CAC3B,EAAa,MAAQ,GACrB,EACF,KAGA,EACE,EACA,CAAE,KAAM,mBAAoB,KAE1B,EAAM,UAAU,CACd,QAAS,EAAQ,MACjB,SACD,CAAC,GACD,EAAQ,MACL,EACE,SACA,CACE,KAAM,SACN,MAAO,kBACP,SAAU,EACV,YAAe,CACb,GAAQ,EAEX,CACD,CACE,EAAO,MAAM,OACb,EAAE,OAAQ,CAAE,MAAO,eAAgB,CAAE,EAAE,EAAW,CAAC,CACpD,CACF,CACD,MACP,EAEN,CAAC"}
1
+ {"version":3,"file":"PwaReadyPopup-Da6_dOG6.js","names":[],"sources":["../src/client/utils/skipWaiting.ts","../src/client/components/PwaReadyPopup.ts"],"sourcesContent":["/**\n * Call `skipWaiting()` inside current waiting worker\n *\n * 在当前等待中的 Service Worker 中调用 `skipWaiting()`\n *\n * @param registration - The registration of the service worker you want\n * activate / 想要激活的 Service Worker 的注册\n */\nexport const skipWaiting = (registration: ServiceWorkerRegistration): void => {\n // Get the waiting worker\n const worker = registration.waiting\n\n // If there is no waiting worker, return directly\n if (!worker) return\n\n // Post SKIP_WAITING message to the waiting worker\n const channel = new MessageChannel()\n\n worker.postMessage({ type: 'SKIP_WAITING' }, [channel.port2])\n}\n","import type { Slot } from '@vuepress/helper/client'\nimport { useLocale } from '@vuepress/helper/client'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport {\n Transition,\n computed,\n defineComponent,\n h,\n onMounted,\n shallowRef,\n} from 'vue'\n\nimport { usePwaEvent } from '../composables/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { skipWaiting } from '../utils/index.js'\nimport { UpdateIcon } from './icons.js'\n\nimport '@vuepress/helper/transition/fade-in-scale-up.css'\nimport '../styles/popup.scss'\n\nexport const PwaReadyPopup = defineComponent({\n name: 'PwaReadyPopup',\n\n props: {\n /** Locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n },\n\n slots: Object as SlotsType<{\n default?: Slot<{ isReady: boolean; reload: () => void }>\n }>,\n\n setup(props, { slots }) {\n const locale = useLocale(props.locales)\n const registration = shallowRef<ServiceWorkerRegistration>()\n\n const isReady = computed(() => Boolean(registration.value))\n\n const reload = (): void => {\n if (registration.value) {\n skipWaiting(registration.value)\n registration.value = undefined\n }\n }\n\n onMounted(() => {\n const event = usePwaEvent()\n\n event.on('updated', (reg) => {\n registration.value = reg\n })\n })\n\n return (): VNode =>\n h(\n Transition,\n { name: 'fade-in-scale-up' },\n () =>\n slots.default?.({\n isReady: isReady.value,\n reload,\n }) ??\n (isReady.value\n ? h(\n 'button',\n {\n type: 'button',\n class: 'sw-update-popup',\n tabindex: 0,\n onClick: () => {\n reload()\n },\n },\n [\n locale.value.update,\n h('span', { class: 'icon-wrapper' }, h(UpdateIcon)),\n ],\n )\n : null),\n )\n },\n})\n"],"mappings":"yUAQA,MAAa,EAAe,GAAkD,CAE5E,IAAM,EAAS,EAAa,QAG5B,GAAI,CAAC,EAAQ,OAGb,IAAM,EAAU,IAAI,eAEpB,EAAO,YAAY,CAAE,KAAM,cAAe,EAAG,CAAC,EAAQ,KAAK,CAAC,CAC9D,ECCa,EAAgB,EAAgB,CAC3C,KAAM,gBAEN,MAAO,CAEL,QAAS,CACP,KAAM,OACN,SAAU,EACZ,CACF,EAEA,MAAO,OAIP,MAAM,EAAO,CAAE,SAAS,CACtB,IAAM,EAAS,EAAU,EAAM,OAAO,EAChC,EAAe,EAAsC,EAErD,EAAU,MAAe,EAAQ,EAAa,KAAM,EAEpD,MAAqB,CACzB,AAEE,EAAa,SADb,EAAY,EAAa,KAAK,EACT,IAAA,GAEzB,EAUA,OARA,MAAgB,CAGd,EAAI,EAAE,GAAG,UAAY,GAAQ,CAC3B,EAAa,MAAQ,CACvB,CAAC,CACH,CAAC,MAGC,EACE,EACA,CAAE,KAAM,kBAAmB,MAEzB,EAAM,UAAU,CACd,QAAS,EAAQ,MACjB,QACF,CAAC,IACA,EAAQ,MACL,EACE,SACA,CACE,KAAM,SACN,MAAO,kBACP,SAAU,EACV,YAAe,CACb,EAAO,CACT,CACF,EACA,CACE,EAAO,MAAM,OACb,EAAE,OAAQ,CAAE,MAAO,cAAe,EAAG,EAAE,CAAU,CAAC,CACpD,CACF,EACA,KACR,CACJ,CACF,CAAC"}
@@ -1,15 +1,15 @@
1
- import { t as PwaPluginLocaleConfig } from "./types-BLkMmayH.js";
1
+ import { t as PwaPluginLocaleConfig } from "./types-0w9cSsje.js";
2
2
  import { Slot } from "@vuepress/helper/client";
3
3
  import * as _$vue from "vue";
4
4
  import { PropType, SlotsType, VNode } from "vue";
5
5
  //#region src/client/components/PwaReadyPopup.d.ts
6
6
  declare const PwaReadyPopup: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
7
- /** locale data */locales: {
7
+ /** Locale data */locales: {
8
8
  type: PropType<PwaPluginLocaleConfig>;
9
9
  required: true;
10
10
  };
11
11
  }>, () => VNode, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<_$vue.ExtractPropTypes<{
12
- /** locale data */locales: {
12
+ /** Locale data */locales: {
13
13
  type: PropType<PwaPluginLocaleConfig>;
14
14
  required: true;
15
15
  };
@@ -21,4 +21,4 @@ declare const PwaReadyPopup: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
21
21
  }>, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
22
22
  //#endregion
23
23
  export { PwaReadyPopup as t };
24
- //# sourceMappingURL=PwaReadyPopup-BaFjDiPo.d.ts.map
24
+ //# sourceMappingURL=PwaReadyPopup-Dk929o_6.d.ts.map
@@ -1,2 +1,2 @@
1
- import { t as PwaFoundPopup } from "../../PwaFoundPopup-U47ypQoC.js";
1
+ import { t as PwaFoundPopup } from "../../PwaFoundPopup-DxHCqVkp.js";
2
2
  export { PwaFoundPopup };
@@ -1 +1 @@
1
- {"version":3,"file":"PwaFoundPopup.js","names":[],"sources":["../../../src/client/components/PwaFoundPopup.ts"],"sourcesContent":["import type { Slot } from '@vuepress/helper/client'\nimport { useLocale } from '@vuepress/helper/client'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport { Transition, defineComponent, h, onMounted, ref } from 'vue'\n\nimport { usePwaEvent } from '../composables/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { UpdateIcon } from './icons.js'\n\nimport '@vuepress/helper/transition/fade-in-scale-up.css'\nimport '../styles/popup.scss'\n\nexport const PwaFoundPopup = defineComponent({\n name: 'PwaFoundPopup',\n\n props: {\n /** locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n },\n\n slots: Object as SlotsType<{\n default?: Slot<{ found: boolean; refresh: () => void }>\n }>,\n\n setup(props, { slots }) {\n const locale = useLocale(props.locales)\n const found = ref(false)\n\n const refresh = (): void => {\n if (found.value) {\n // force refresh\n // @ts-expect-error: A non-standard API\n window.location.reload(true)\n found.value = false\n }\n }\n\n onMounted(() => {\n const event = usePwaEvent()\n\n event.on('updatefound', () => {\n void navigator.serviceWorker.getRegistration().then((registration) => {\n // Check whether a valid service worker is active\n if (registration?.active) found.value = true\n })\n })\n\n event.on('updated', () => {\n found.value = false\n })\n })\n\n return (): VNode =>\n h(\n Transition,\n { name: 'fade-in-scale-up' },\n () =>\n slots.default?.({\n found: found.value,\n refresh,\n }) ??\n (found.value\n ? h(\n 'button',\n {\n type: 'button',\n class: 'sw-hint-popup',\n tabindex: 0,\n onClick: () => {\n refresh()\n },\n },\n [\n locale.value.hint,\n h('span', { class: 'icon-wrapper' }, h(UpdateIcon)),\n ],\n )\n : null),\n )\n },\n})\n"],"mappings":"gUAYA,MAAa,EAAgB,EAAgB,CAC3C,KAAM,gBAEN,MAAO,CAEL,QAAS,CACP,KAAM,OACN,SAAU,GACX,CACF,CAED,MAAO,OAIP,MAAM,EAAO,CAAE,SAAS,CACtB,IAAM,EAAS,EAAU,EAAM,QAAQ,CACjC,EAAQ,EAAI,GAAM,CAElB,MAAsB,CAC1B,AAIE,EAAM,SADN,OAAO,SAAS,OAAO,GAAK,CACd,KAmBlB,OAfA,MAAgB,CACd,IAAM,EAAQ,GAAa,CAE3B,EAAM,GAAG,kBAAqB,CACvB,UAAU,cAAc,iBAAiB,CAAC,KAAM,GAAiB,CAEhE,GAAc,SAAQ,EAAM,MAAQ,KACxC,EACF,CAEF,EAAM,GAAG,cAAiB,CACxB,EAAM,MAAQ,IACd,EACF,KAGA,EACE,EACA,CAAE,KAAM,mBAAoB,KAE1B,EAAM,UAAU,CACd,MAAO,EAAM,MACb,UACD,CAAC,GACD,EAAM,MACH,EACE,SACA,CACE,KAAM,SACN,MAAO,gBACP,SAAU,EACV,YAAe,CACb,GAAS,EAEZ,CACD,CACE,EAAO,MAAM,KACb,EAAE,OAAQ,CAAE,MAAO,eAAgB,CAAE,EAAE,EAAW,CAAC,CACpD,CACF,CACD,MACP,EAEN,CAAC"}
1
+ {"version":3,"file":"PwaFoundPopup.js","names":[],"sources":["../../../src/client/components/PwaFoundPopup.ts"],"sourcesContent":["import type { Slot } from '@vuepress/helper/client'\nimport { useLocale } from '@vuepress/helper/client'\nimport type { PropType, SlotsType, VNode } from 'vue'\nimport { Transition, defineComponent, h, onMounted, ref } from 'vue'\n\nimport { usePwaEvent } from '../composables/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { UpdateIcon } from './icons.js'\n\nimport '@vuepress/helper/transition/fade-in-scale-up.css'\nimport '../styles/popup.scss'\n\nexport const PwaFoundPopup = defineComponent({\n name: 'PwaFoundPopup',\n\n props: {\n /** Locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n },\n\n slots: Object as SlotsType<{\n default?: Slot<{ found: boolean; refresh: () => void }>\n }>,\n\n setup(props, { slots }) {\n const locale = useLocale(props.locales)\n const found = ref(false)\n\n const refresh = (): void => {\n if (found.value) {\n // force refresh\n // @ts-expect-error: A non-standard API\n window.location.reload(true)\n found.value = false\n }\n }\n\n onMounted(() => {\n const event = usePwaEvent()\n\n event.on('updatefound', () => {\n void navigator.serviceWorker.getRegistration().then((registration) => {\n // Check whether a valid service worker is active\n if (registration?.active) found.value = true\n })\n })\n\n event.on('updated', () => {\n found.value = false\n })\n })\n\n return (): VNode =>\n h(\n Transition,\n { name: 'fade-in-scale-up' },\n () =>\n slots.default?.({\n found: found.value,\n refresh,\n }) ??\n (found.value\n ? h(\n 'button',\n {\n type: 'button',\n class: 'sw-hint-popup',\n tabindex: 0,\n onClick: () => {\n refresh()\n },\n },\n [\n locale.value.hint,\n h('span', { class: 'icon-wrapper' }, h(UpdateIcon)),\n ],\n )\n : null),\n )\n },\n})\n"],"mappings":"gUAYA,MAAa,EAAgB,EAAgB,CAC3C,KAAM,gBAEN,MAAO,CAEL,QAAS,CACP,KAAM,OACN,SAAU,EACZ,CACF,EAEA,MAAO,OAIP,MAAM,EAAO,CAAE,SAAS,CACtB,IAAM,EAAS,EAAU,EAAM,OAAO,EAChC,EAAQ,EAAI,EAAK,EAEjB,MAAsB,CAC1B,AAIE,EAAM,SADN,OAAO,SAAS,OAAO,EAAI,EACb,GAElB,EAiBA,OAfA,MAAgB,CACd,IAAM,EAAQ,EAAY,EAE1B,EAAM,GAAG,kBAAqB,CAC5B,UAAe,cAAc,gBAAgB,EAAE,KAAM,GAAiB,CAEhE,GAAc,SAAQ,EAAM,MAAQ,GAC1C,CAAC,CACH,CAAC,EAED,EAAM,GAAG,cAAiB,CACxB,EAAM,MAAQ,EAChB,CAAC,CACH,CAAC,MAGC,EACE,EACA,CAAE,KAAM,kBAAmB,MAEzB,EAAM,UAAU,CACd,MAAO,EAAM,MACb,SACF,CAAC,IACA,EAAM,MACH,EACE,SACA,CACE,KAAM,SACN,MAAO,gBACP,SAAU,EACV,YAAe,CACb,EAAQ,CACV,CACF,EACA,CACE,EAAO,MAAM,KACb,EAAE,OAAQ,CAAE,MAAO,cAAe,EAAG,EAAE,CAAU,CAAC,CACpD,CACF,EACA,KACR,CACJ,CACF,CAAC"}
@@ -1,2 +1,2 @@
1
- import { t as PwaInstall } from "../../PwaInstall-IlBEJ5C2.js";
1
+ import { t as PwaInstall } from "../../PwaInstall-BXTaTtiv.js";
2
2
  export { PwaInstall };
@@ -1 +1 @@
1
- import{t as e}from"../../PwaInstall-D2rYRuV_.js";export{e as PwaInstall};
1
+ import{t as e}from"../../PwaInstall-DJF1evx8.js";export{e as PwaInstall};
@@ -1,2 +1,2 @@
1
- import { t as PwaReadyPopup } from "../../PwaReadyPopup-BaFjDiPo.js";
1
+ import { t as PwaReadyPopup } from "../../PwaReadyPopup-Dk929o_6.js";
2
2
  export { PwaReadyPopup };
@@ -1,7 +1,7 @@
1
- import { t as PwaPluginLocaleConfig } from "../types-BLkMmayH.js";
2
- import { t as PwaFoundPopup } from "../PwaFoundPopup-U47ypQoC.js";
3
- import { t as PwaInstall } from "../PwaInstall-IlBEJ5C2.js";
4
- import { t as PwaReadyPopup } from "../PwaReadyPopup-BaFjDiPo.js";
1
+ import { t as PwaPluginLocaleConfig } from "../types-0w9cSsje.js";
2
+ import { t as PwaFoundPopup } from "../PwaFoundPopup-DxHCqVkp.js";
3
+ import { t as PwaInstall } from "../PwaInstall-BXTaTtiv.js";
4
+ import { t as PwaReadyPopup } from "../PwaReadyPopup-Dk929o_6.js";
5
5
  import { PwaEvent, pwaEventSymbol, setupPwa, setupViewPoint, usePwaEvent, useRegisterSW } from "./composables/index.js";
6
6
  import { Hooks } from "register-service-worker";
7
7
 
@@ -31,7 +31,8 @@ declare const registerSW: (serviceWorkerPath: string, hooks?: Hooks, showStatus?
31
31
  *
32
32
  * 在当前等待中的 Service Worker 中调用 `skipWaiting()`
33
33
  *
34
- * @param registration - The registration of the service worker you want activate / 想要激活的 Service Worker 的注册
34
+ * @param registration - The registration of the service worker you want
35
+ * activate / 想要激活的 Service Worker 的注册
35
36
  */
36
37
  declare const skipWaiting: (registration: ServiceWorkerRegistration) => void;
37
38
  //#endregion
@@ -41,7 +42,8 @@ declare const skipWaiting: (registration: ServiceWorkerRegistration) => void;
41
42
  *
42
43
  * 在当前激活的 Service Worker 中调用 `unregister()`
43
44
  *
44
- * @returns `true` if unregister success, `false` if unregister failed / `true` 表示注销成功,`false` 表示注销失败
45
+ * @returns `true` if unregister success, `false` if unregister failed / `true`
46
+ * 表示注销成功,`false` 表示注销失败
45
47
  */
46
48
  declare const unregisterSW: () => Promise<boolean>;
47
49
  //#endregion
@@ -1,2 +1,2 @@
1
- import{t as e}from"../PwaInstall-D2rYRuV_.js";import{a as t,i as n,n as r,o as i,r as a,s as o,t as s}from"../composables-Bdxx2hts.js";import{n as c,t as l}from"../PwaReadyPopup-Da6_dOG6.js";import{PwaFoundPopup as u}from"./components/PwaFoundPopup.js";const d=async()=>{try{let e=await navigator.serviceWorker.getRegistration();if(e){let t=await e.unregister();return t&&console.log(`[PWA] Current service worker unregistered`),t}}catch(e){console.error(`[PWA] Unregister current service worker failed with error:`,e)}return!1};export{u as PwaFoundPopup,e as PwaInstall,l as PwaReadyPopup,o as forceUpdate,n as pwaEventSymbol,i as registerSW,r as setupPwa,s as setupViewPoint,c as skipWaiting,d as unregisterSW,t as usePwaEvent,a as useRegisterSW};
1
+ import{t as e}from"../PwaInstall-DJF1evx8.js";import{a as t,i as n,n as r,o as i,r as a,s as o,t as s}from"../composables-Bdxx2hts.js";import{n as c,t as l}from"../PwaReadyPopup-Da6_dOG6.js";import{PwaFoundPopup as u}from"./components/PwaFoundPopup.js";const d=async()=>{try{let e=await navigator.serviceWorker.getRegistration();if(e){let t=await e.unregister();return t&&console.log(`[PWA] Current service worker unregistered`),t}}catch(e){console.error(`[PWA] Unregister current service worker failed with error:`,e)}return!1};export{u as PwaFoundPopup,e as PwaInstall,l as PwaReadyPopup,o as forceUpdate,n as pwaEventSymbol,i as registerSW,r as setupPwa,s as setupViewPoint,c as skipWaiting,d as unregisterSW,t as usePwaEvent,a as useRegisterSW};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/client/utils/unregisterSW.ts"],"sourcesContent":["/* oxlint-disable no-console */\n/**\n * Call `unregister()` inside current active worker\n *\n * 在当前激活的 Service Worker 中调用 `unregister()`\n *\n * @returns `true` if unregister success, `false` if unregister failed / `true` 表示注销成功,`false` 表示注销失败\n */\nexport const unregisterSW = async (): Promise<boolean> => {\n try {\n const registration = await navigator.serviceWorker.getRegistration()\n if (registration) {\n const found = await registration.unregister()\n if (found) console.log('[PWA] Current service worker unregistered')\n return found\n }\n } catch (err: unknown) {\n console.error(\n '[PWA] Unregister current service worker failed with error:',\n err,\n )\n }\n return false\n}\n"],"mappings":"6PAQA,MAAa,EAAe,SAA8B,CACxD,GAAI,CACF,IAAM,EAAe,MAAM,UAAU,cAAc,iBAAiB,CACpE,GAAI,EAAc,CAChB,IAAM,EAAQ,MAAM,EAAa,YAAY,CAE7C,OADI,GAAO,QAAQ,IAAI,4CAA4C,CAC5D,SAEF,EAAc,CACrB,QAAQ,MACN,6DACA,EACD,CAEH,MAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/client/utils/unregisterSW.ts"],"sourcesContent":["/* oxlint-disable no-console */\n/**\n * Call `unregister()` inside current active worker\n *\n * 在当前激活的 Service Worker 中调用 `unregister()`\n *\n * @returns `true` if unregister success, `false` if unregister failed / `true`\n * 表示注销成功,`false` 表示注销失败\n */\nexport const unregisterSW = async (): Promise<boolean> => {\n try {\n const registration = await navigator.serviceWorker.getRegistration()\n if (registration) {\n const found = await registration.unregister()\n if (found) console.log('[PWA] Current service worker unregistered')\n return found\n }\n } catch (err: unknown) {\n console.error(\n '[PWA] Unregister current service worker failed with error:',\n err,\n )\n }\n return false\n}\n"],"mappings":"6PASA,MAAa,EAAe,SAA8B,CACxD,GAAI,CACF,IAAM,EAAe,MAAM,UAAU,cAAc,gBAAgB,EACnE,GAAI,EAAc,CAChB,IAAM,EAAQ,MAAM,EAAa,WAAW,EAE5C,OADI,GAAO,QAAQ,IAAI,2CAA2C,EAC3D,CACT,CACF,OAAS,EAAc,CACrB,QAAQ,MACN,6DACA,CACF,CACF,CACA,MAAO,EACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"composables-Bdxx2hts.js","names":[],"sources":["../src/client/utils/forceUpdate.ts","../src/client/utils/registerSW.ts","../src/client/composables/usePwaEvent.ts","../src/client/composables/useRegisterSW.ts","../src/client/composables/setupPwa.ts","../src/client/composables/setupViewPoint.ts"],"sourcesContent":["/**\n * Force update page content\n *\n * 强制更新页面内容\n */\nexport const forceUpdate = (): void => {\n void navigator.serviceWorker.getRegistration().then((registration) => {\n // Check whether a valid service worker is active\n if (registration?.active) {\n registration.addEventListener('updatefound', () => {\n // force refresh\n // @ts-expect-error: A non-standard API\n window.location.reload(true)\n })\n }\n })\n}\n","/* oxlint-disable no-console */\nimport type { Hooks } from 'register-service-worker'\n\n/**\n * Register serviceWorker under `serviceWorkerPath`\n *\n * 在 `serviceWorkerPath` 下注册 Service Worker\n *\n * @param serviceWorkerPath - Service Worker path / Service Worker 路径\n * @param hooks - Service worker hooks / Service Worker 钩子\n * @param showStatus - Whether to show status in console / 是否在控制台显示状态\n */\nexport const registerSW = async (\n serviceWorkerPath: string,\n hooks: Hooks = {},\n showStatus = true,\n): Promise<void> => {\n const { register } = await import(\n /* webpackChunkName: \"register-service-worker\" */ 'register-service-worker'\n )\n\n // Register service worker\n register(serviceWorkerPath, {\n ready(registration) {\n if (showStatus) console.info('[Service Worker]: active')\n hooks.ready?.(registration)\n },\n\n registered(registration) {\n if (showStatus) console.log('[Service Worker]: registered')\n hooks.registered?.(registration)\n },\n\n cached(registration) {\n if (showStatus) console.log('[Service Worker]: cached')\n hooks.cached?.(registration)\n },\n\n updatefound(registration) {\n if (showStatus) console.log('[Service Worker]: update found')\n hooks.updatefound?.(registration)\n },\n\n updated(registration) {\n if (showStatus) console.log('[Service Worker]: updated')\n hooks.updated?.(registration)\n },\n\n offline() {\n if (showStatus) console.log('[Service Worker]: offline')\n hooks.offline?.()\n },\n\n error(err) {\n if (showStatus) console.error('[Service Worker]:', err)\n hooks.error?.(err)\n },\n })\n}\n","import type { Emitter } from 'mitt'\nimport type { InjectionKey } from 'vue'\nimport { inject } from 'vue'\n\ndeclare const __VUEPRESS_DEV__: boolean\n\nexport type PwaEvent = Emitter<{\n ready: ServiceWorkerRegistration\n registered: ServiceWorkerRegistration\n cached: ServiceWorkerRegistration\n updatefound: ServiceWorkerRegistration\n updated: ServiceWorkerRegistration\n offline: void\n error: Error\n}>\n\nexport const pwaEventSymbol: InjectionKey<PwaEvent> = Symbol(\n __VUEPRESS_DEV__ ? 'PwaEvent' : '',\n)\n\n/**\n * Use PWA event emitter\n *\n * 使用 PWA 事件发射器\n *\n * @returns PWA event emitter / PWA 事件发射器\n */\nexport const usePwaEvent = (): PwaEvent => {\n const pwaEvent = inject(pwaEventSymbol)\n\n if (!pwaEvent) throw new Error('usePwaEvent() is called without provider.')\n\n return pwaEvent\n}\n","import { withBase } from 'vuepress/client'\n\nimport { registerSW } from '../utils/index.js'\nimport type { PwaEvent } from './usePwaEvent.js'\n\n/**\n * Register service worker with event emitter\n *\n * 使用事件发射器注册 Service Worker\n *\n * @param serviceWorkerPath - Service Worker path / Service Worker 路径\n * @param event - PWA event emitter / PWA 事件发射器\n */\nexport const useRegisterSW = async (\n serviceWorkerPath: string,\n event: PwaEvent,\n): Promise<void> => {\n await registerSW(withBase(serviceWorkerPath), {\n ready(registration) {\n event.emit('ready', registration)\n },\n\n registered(registration) {\n event.emit('registered', registration)\n },\n\n cached(registration) {\n event.emit('cached', registration)\n },\n\n updatefound(registration) {\n event.emit('updatefound', registration)\n },\n\n updated(registration) {\n const key = 'service-worker-version'\n const version = Number(localStorage.getItem(key) || 0)\n\n localStorage.setItem(key, (version + 1).toString())\n localStorage.removeItem('manifest')\n\n event.emit('updated', registration)\n },\n\n offline() {\n event.emit('offline')\n },\n\n error(err) {\n event.emit('error', err)\n },\n })\n}\n","import mitt from 'mitt'\nimport { onMounted, provide } from 'vue'\n\nimport { forceUpdate } from '../utils/index.js'\nimport type { PwaEvent } from './index.js'\nimport { pwaEventSymbol } from './usePwaEvent.js'\nimport { useRegisterSW } from './useRegisterSW.js'\n\n/**\n * Setup PWA functionality\n *\n * 设置 PWA 功能\n *\n * @param serviceWorkerPath - Service Worker path / Service Worker 路径\n * @param shouldForceUpdate - Whether to force update / 是否强制更新\n */\nexport const setupPwa = (\n serviceWorkerPath: string,\n shouldForceUpdate = false,\n): void => {\n if (__VUEPRESS_SSR__) return\n\n // Create event emitter and provide it\n const event: PwaEvent = mitt()\n\n provide(pwaEventSymbol, event)\n\n onMounted(async () => {\n if (__VUEPRESS_DEV__ || !('serviceWorker' in navigator)) return\n\n let refreshing = false\n\n // Only listen controllerchange event when a serviceWorker is active\n if (navigator.serviceWorker.controller) {\n navigator.serviceWorker.addEventListener('controllerchange', () => {\n if (refreshing) return\n\n refreshing = true\n window.location.reload()\n })\n }\n\n if (shouldForceUpdate) forceUpdate()\n\n await useRegisterSW(serviceWorkerPath, event)\n })\n}\n","import { onMounted } from 'vue'\n\n/**\n * Setup viewport for PWA standalone mode\n *\n * 为 PWA 独立模式设置视口\n */\nexport const setupViewPoint = (): void => {\n onMounted(() => {\n const isStandAlone = window.matchMedia('(display-mode: standalone)').matches\n\n if (isStandAlone) {\n const head = document.head.querySelector('meta[name=\"viewport\"]')\n\n if (head) {\n head.setAttribute(\n 'content',\n 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover',\n )\n return\n }\n\n const viewportMeta = document.createElement('meta')\n\n viewportMeta.name = 'viewport'\n viewportMeta.content =\n 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover'\n\n document.head.append(viewportMeta)\n }\n })\n}\n"],"mappings":"wHAKA,MAAa,MAA0B,CAChC,UAAU,cAAc,iBAAiB,CAAC,KAAM,GAAiB,CAEhE,GAAc,QAChB,EAAa,iBAAiB,kBAAqB,CAGjD,OAAO,SAAS,OAAO,GAAK,EAC5B,EAEJ,ECHS,EAAa,MACxB,EACA,EAAe,EAAE,CACjB,EAAa,KACK,CAClB,GAAM,CAAE,YAAa,MAAM,OACyB,2BAIpD,EAAS,EAAmB,CAC1B,MAAM,EAAc,CACd,GAAY,QAAQ,KAAK,2BAA2B,CACxD,EAAM,QAAQ,EAAa,EAG7B,WAAW,EAAc,CACnB,GAAY,QAAQ,IAAI,+BAA+B,CAC3D,EAAM,aAAa,EAAa,EAGlC,OAAO,EAAc,CACf,GAAY,QAAQ,IAAI,2BAA2B,CACvD,EAAM,SAAS,EAAa,EAG9B,YAAY,EAAc,CACpB,GAAY,QAAQ,IAAI,iCAAiC,CAC7D,EAAM,cAAc,EAAa,EAGnC,QAAQ,EAAc,CAChB,GAAY,QAAQ,IAAI,4BAA4B,CACxD,EAAM,UAAU,EAAa,EAG/B,SAAU,CACJ,GAAY,QAAQ,IAAI,4BAA4B,CACxD,EAAM,WAAW,EAGnB,MAAM,EAAK,CACL,GAAY,QAAQ,MAAM,oBAAqB,EAAI,CACvD,EAAM,QAAQ,EAAI,EAErB,CAAC,ECzCS,EAAyC,OACpD,iBAAmB,WAAa,GACjC,CASY,MAA8B,CACzC,IAAM,EAAW,EAAO,EAAe,CAEvC,GAAI,CAAC,EAAU,MAAU,MAAM,4CAA4C,CAE3E,OAAO,GCnBI,EAAgB,MAC3B,EACA,IACkB,CAClB,MAAM,EAAW,EAAS,EAAkB,CAAE,CAC5C,MAAM,EAAc,CAClB,EAAM,KAAK,QAAS,EAAa,EAGnC,WAAW,EAAc,CACvB,EAAM,KAAK,aAAc,EAAa,EAGxC,OAAO,EAAc,CACnB,EAAM,KAAK,SAAU,EAAa,EAGpC,YAAY,EAAc,CACxB,EAAM,KAAK,cAAe,EAAa,EAGzC,QAAQ,EAAc,CACpB,IAAM,EAAM,yBACN,EAAU,OAAO,aAAa,QAAQ,EAAI,EAAI,EAAE,CAEtD,aAAa,QAAQ,GAAM,EAAU,GAAG,UAAU,CAAC,CACnD,aAAa,WAAW,WAAW,CAEnC,EAAM,KAAK,UAAW,EAAa,EAGrC,SAAU,CACR,EAAM,KAAK,UAAU,EAGvB,MAAM,EAAK,CACT,EAAM,KAAK,QAAS,EAAI,EAE3B,CAAC,ECnCS,GACX,EACA,EAAoB,KACX,CACT,GAAI,iBAAkB,OAGtB,IAAM,EAAkB,GAAM,CAE9B,EAAQ,EAAgB,EAAM,CAE9B,EAAU,SAAY,CACpB,GAAI,kBAAoB,EAAE,kBAAmB,WAAY,OAEzD,IAAI,EAAa,GAGb,UAAU,cAAc,YAC1B,UAAU,cAAc,iBAAiB,uBAA0B,CAC7D,IAEJ,EAAa,GACb,OAAO,SAAS,QAAQ,GACxB,CAGA,GAAmB,GAAa,CAEpC,MAAM,EAAc,EAAmB,EAAM,EAC7C,ECtCS,MAA6B,CACxC,MAAgB,CAGd,GAFqB,OAAO,WAAW,6BAA6B,CAAC,QAEnD,CAChB,IAAM,EAAO,SAAS,KAAK,cAAc,wBAAwB,CAEjE,GAAI,EAAM,CACR,EAAK,aACH,UACA,iGACD,CACD,OAGF,IAAM,EAAe,SAAS,cAAc,OAAO,CAEnD,EAAa,KAAO,WACpB,EAAa,QACX,iGAEF,SAAS,KAAK,OAAO,EAAa,GAEpC"}
1
+ {"version":3,"file":"composables-Bdxx2hts.js","names":[],"sources":["../src/client/utils/forceUpdate.ts","../src/client/utils/registerSW.ts","../src/client/composables/usePwaEvent.ts","../src/client/composables/useRegisterSW.ts","../src/client/composables/setupPwa.ts","../src/client/composables/setupViewPoint.ts"],"sourcesContent":["/**\n * Force update page content\n *\n * 强制更新页面内容\n */\nexport const forceUpdate = (): void => {\n void navigator.serviceWorker.getRegistration().then((registration) => {\n // Check whether a valid service worker is active\n if (registration?.active) {\n registration.addEventListener('updatefound', () => {\n // force refresh\n // @ts-expect-error: A non-standard API\n window.location.reload(true)\n })\n }\n })\n}\n","/* oxlint-disable no-console */\nimport type { Hooks } from 'register-service-worker'\n\n/**\n * Register serviceWorker under `serviceWorkerPath`\n *\n * 在 `serviceWorkerPath` 下注册 Service Worker\n *\n * @param serviceWorkerPath - Service Worker path / Service Worker 路径\n * @param hooks - Service worker hooks / Service Worker 钩子\n * @param showStatus - Whether to show status in console / 是否在控制台显示状态\n */\nexport const registerSW = async (\n serviceWorkerPath: string,\n hooks: Hooks = {},\n showStatus = true,\n): Promise<void> => {\n const { register } = await import(\n /* webpackChunkName: \"register-service-worker\" */ 'register-service-worker'\n )\n\n // Register service worker\n register(serviceWorkerPath, {\n ready(registration) {\n if (showStatus) console.info('[Service Worker]: active')\n hooks.ready?.(registration)\n },\n\n registered(registration) {\n if (showStatus) console.log('[Service Worker]: registered')\n hooks.registered?.(registration)\n },\n\n cached(registration) {\n if (showStatus) console.log('[Service Worker]: cached')\n hooks.cached?.(registration)\n },\n\n updatefound(registration) {\n if (showStatus) console.log('[Service Worker]: update found')\n hooks.updatefound?.(registration)\n },\n\n updated(registration) {\n if (showStatus) console.log('[Service Worker]: updated')\n hooks.updated?.(registration)\n },\n\n offline() {\n if (showStatus) console.log('[Service Worker]: offline')\n hooks.offline?.()\n },\n\n error(err) {\n if (showStatus) console.error('[Service Worker]:', err)\n hooks.error?.(err)\n },\n })\n}\n","import type { Emitter } from 'mitt'\nimport type { InjectionKey } from 'vue'\nimport { inject } from 'vue'\n\ndeclare const __VUEPRESS_DEV__: boolean\n\nexport type PwaEvent = Emitter<{\n ready: ServiceWorkerRegistration\n registered: ServiceWorkerRegistration\n cached: ServiceWorkerRegistration\n updatefound: ServiceWorkerRegistration\n updated: ServiceWorkerRegistration\n offline: void\n error: Error\n}>\n\nexport const pwaEventSymbol: InjectionKey<PwaEvent> = Symbol(\n __VUEPRESS_DEV__ ? 'PwaEvent' : '',\n)\n\n/**\n * Use PWA event emitter\n *\n * 使用 PWA 事件发射器\n *\n * @returns PWA event emitter / PWA 事件发射器\n */\nexport const usePwaEvent = (): PwaEvent => {\n const pwaEvent = inject(pwaEventSymbol)\n\n if (!pwaEvent) throw new Error('usePwaEvent() is called without provider.')\n\n return pwaEvent\n}\n","import { withBase } from 'vuepress/client'\n\nimport { registerSW } from '../utils/index.js'\nimport type { PwaEvent } from './usePwaEvent.js'\n\n/**\n * Register service worker with event emitter\n *\n * 使用事件发射器注册 Service Worker\n *\n * @param serviceWorkerPath - Service Worker path / Service Worker 路径\n * @param event - PWA event emitter / PWA 事件发射器\n */\nexport const useRegisterSW = async (\n serviceWorkerPath: string,\n event: PwaEvent,\n): Promise<void> => {\n await registerSW(withBase(serviceWorkerPath), {\n ready(registration) {\n event.emit('ready', registration)\n },\n\n registered(registration) {\n event.emit('registered', registration)\n },\n\n cached(registration) {\n event.emit('cached', registration)\n },\n\n updatefound(registration) {\n event.emit('updatefound', registration)\n },\n\n updated(registration) {\n const key = 'service-worker-version'\n const version = Number(localStorage.getItem(key) || 0)\n\n localStorage.setItem(key, (version + 1).toString())\n localStorage.removeItem('manifest')\n\n event.emit('updated', registration)\n },\n\n offline() {\n event.emit('offline')\n },\n\n error(err) {\n event.emit('error', err)\n },\n })\n}\n","import mitt from 'mitt'\nimport { onMounted, provide } from 'vue'\n\nimport { forceUpdate } from '../utils/index.js'\nimport type { PwaEvent } from './index.js'\nimport { pwaEventSymbol } from './usePwaEvent.js'\nimport { useRegisterSW } from './useRegisterSW.js'\n\n/**\n * Setup PWA functionality\n *\n * 设置 PWA 功能\n *\n * @param serviceWorkerPath - Service Worker path / Service Worker 路径\n * @param shouldForceUpdate - Whether to force update / 是否强制更新\n */\nexport const setupPwa = (\n serviceWorkerPath: string,\n shouldForceUpdate = false,\n): void => {\n if (__VUEPRESS_SSR__) return\n\n // Create event emitter and provide it\n const event: PwaEvent = mitt()\n\n provide(pwaEventSymbol, event)\n\n onMounted(async () => {\n if (__VUEPRESS_DEV__ || !('serviceWorker' in navigator)) return\n\n let refreshing = false\n\n // Only listen controllerchange event when a serviceWorker is active\n if (navigator.serviceWorker.controller) {\n navigator.serviceWorker.addEventListener('controllerchange', () => {\n if (refreshing) return\n\n refreshing = true\n window.location.reload()\n })\n }\n\n if (shouldForceUpdate) forceUpdate()\n\n await useRegisterSW(serviceWorkerPath, event)\n })\n}\n","import { onMounted } from 'vue'\n\n/**\n * Setup viewport for PWA standalone mode\n *\n * 为 PWA 独立模式设置视口\n */\nexport const setupViewPoint = (): void => {\n onMounted(() => {\n const isStandAlone = window.matchMedia('(display-mode: standalone)').matches\n\n if (isStandAlone) {\n const head = document.head.querySelector('meta[name=\"viewport\"]')\n\n if (head) {\n head.setAttribute(\n 'content',\n 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover',\n )\n return\n }\n\n const viewportMeta = document.createElement('meta')\n\n viewportMeta.name = 'viewport'\n viewportMeta.content =\n 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover'\n\n document.head.append(viewportMeta)\n }\n })\n}\n"],"mappings":"wHAKA,MAAa,MAA0B,CACrC,UAAe,cAAc,gBAAgB,EAAE,KAAM,GAAiB,CAEhE,GAAc,QAChB,EAAa,iBAAiB,kBAAqB,CAGjD,OAAO,SAAS,OAAO,EAAI,CAC7B,CAAC,CAEL,CAAC,CACH,ECJa,EAAa,MACxB,EACA,EAAe,CAAC,EAChB,EAAa,KACK,CAClB,GAAM,CAAE,YAAa,MAAM,OACyB,2BAIpD,EAAS,EAAmB,CAC1B,MAAM,EAAc,CACd,GAAY,QAAQ,KAAK,0BAA0B,EACvD,EAAM,QAAQ,CAAY,CAC5B,EAEA,WAAW,EAAc,CACnB,GAAY,QAAQ,IAAI,8BAA8B,EAC1D,EAAM,aAAa,CAAY,CACjC,EAEA,OAAO,EAAc,CACf,GAAY,QAAQ,IAAI,0BAA0B,EACtD,EAAM,SAAS,CAAY,CAC7B,EAEA,YAAY,EAAc,CACpB,GAAY,QAAQ,IAAI,gCAAgC,EAC5D,EAAM,cAAc,CAAY,CAClC,EAEA,QAAQ,EAAc,CAChB,GAAY,QAAQ,IAAI,2BAA2B,EACvD,EAAM,UAAU,CAAY,CAC9B,EAEA,SAAU,CACJ,GAAY,QAAQ,IAAI,2BAA2B,EACvD,EAAM,UAAU,CAClB,EAEA,MAAM,EAAK,CACL,GAAY,QAAQ,MAAM,oBAAqB,CAAG,EACtD,EAAM,QAAQ,CAAG,CACnB,CACF,CAAC,CACH,EC1Ca,EAAyC,OACpD,iBAAmB,WAAa,EAClC,EASa,MAA8B,CACzC,IAAM,EAAW,EAAO,CAAc,EAEtC,GAAI,CAAC,EAAU,MAAU,MAAM,2CAA2C,EAE1E,OAAO,CACT,ECpBa,EAAgB,MAC3B,EACA,IACkB,CAClB,MAAM,EAAW,EAAS,CAAiB,EAAG,CAC5C,MAAM,EAAc,CAClB,EAAM,KAAK,QAAS,CAAY,CAClC,EAEA,WAAW,EAAc,CACvB,EAAM,KAAK,aAAc,CAAY,CACvC,EAEA,OAAO,EAAc,CACnB,EAAM,KAAK,SAAU,CAAY,CACnC,EAEA,YAAY,EAAc,CACxB,EAAM,KAAK,cAAe,CAAY,CACxC,EAEA,QAAQ,EAAc,CACpB,IAAM,EAAM,yBACN,EAAU,OAAO,aAAa,QAAQ,CAAG,GAAK,CAAC,EAErD,aAAa,QAAQ,GAAM,EAAU,GAAG,SAAS,CAAC,EAClD,aAAa,WAAW,UAAU,EAElC,EAAM,KAAK,UAAW,CAAY,CACpC,EAEA,SAAU,CACR,EAAM,KAAK,SAAS,CACtB,EAEA,MAAM,EAAK,CACT,EAAM,KAAK,QAAS,CAAG,CACzB,CACF,CAAC,CACH,ECpCa,GACX,EACA,EAAoB,KACX,CACT,GAAI,iBAAkB,OAGtB,IAAM,EAAkB,EAAK,EAE7B,EAAQ,EAAgB,CAAK,EAE7B,EAAU,SAAY,CACpB,GAAI,kBAAoB,EAAE,kBAAmB,WAAY,OAEzD,IAAI,EAAa,GAGb,UAAU,cAAc,YAC1B,UAAU,cAAc,iBAAiB,uBAA0B,CAC7D,IAEJ,EAAa,GACb,OAAO,SAAS,OAAO,EACzB,CAAC,EAGC,GAAmB,EAAY,EAEnC,MAAM,EAAc,EAAmB,CAAK,CAC9C,CAAC,CACH,ECvCa,MAA6B,CACxC,MAAgB,CAGd,GAFqB,OAAO,WAAW,4BAA4B,EAAE,QAEnD,CAChB,IAAM,EAAO,SAAS,KAAK,cAAc,uBAAuB,EAEhE,GAAI,EAAM,CACR,EAAK,aACH,UACA,gGACF,EACA,MACF,CAEA,IAAM,EAAe,SAAS,cAAc,MAAM,EAElD,EAAa,KAAO,WACpB,EAAa,QACX,iGAEF,SAAS,KAAK,OAAO,CAAY,CACnC,CACF,CAAC,CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"icons-RRw4DIWa.js","names":[],"sources":["../src/client/components/icons.ts"],"sourcesContent":["// oxlint-disable id-length\nimport type { FunctionalComponent, VNode } from 'vue'\nimport { h } from 'vue'\n\ninterface SVGWrapperProps {\n name?: string\n color?: string\n}\n\nconst SVGWrapper: FunctionalComponent<\n SVGWrapperProps,\n Record<never, never>,\n { default: () => VNode | VNode[] }\n> = ({ name = '', color = 'currentColor' }, { slots }) =>\n h(\n 'svg',\n {\n 'xmlns': 'http://www.w3.org/2000/svg',\n 'class': ['icon', `${name}-icon`],\n 'viewBox': '0 0 1024 1024',\n 'fill': color,\n 'aria-label': `${name} icon`,\n },\n slots.default(),\n )\n\nSVGWrapper.displayName = 'SVGWrapper'\n\nexport const ArrowLeftIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'arrow-left' }, () =>\n h('path', {\n d: 'M802.8 448h-428l166-158.8c23.8-25 23.8-65.4 0-90.4s-62.4-25-86.4 0L178 466.8c-12 11.6-18 27.4-18 44.8v0.8c0 17.4 6 33.2 18 44.8l276.2 268c24 25 62.6 25 86.4 0 23.8-25 23.8-65.4 0-90.4l-166-158.8h428c33.8 0 61.2-28.6 61.2-64 0.2-36-27.2-64-61-64z',\n }),\n )\n\nArrowLeftIcon.displayName = 'ArrowLeftIcon'\n\nexport const ArrowRightIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'arrow-right' }, () =>\n h('path', {\n d: 'M569.8 825.2l276.2-268c12-11.6 18-27.4 18-44.8v-0.8c0-17.4-6-33.2-18-44.8l-276.2-268c-24-25-62.6-25-86.4 0-23.8 25-23.8 65.4 0 90.4l166 158.8h-428c-34 0-61.4 28.6-61.4 64 0 36 27.4 64 61.2 64h428l-166 158.8c-23.8 25-23.8 65.4 0 90.4 24 25 62.6 25 86.6 0z',\n }),\n )\n\nArrowRightIcon.displayName = 'ArrowRightIcon'\n\nexport const CloseIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'close' }, () =>\n h('path', {\n d: 'M589.654 511.965 1007.212 84.22a49.777 49.777 0 0 0-.73-70.02 49.046 49.046 0 0 0-69.687.665L519.967 441.946 85.882 14.2a49.08 49.08 0 0 0-69.687.664 49.777 49.777 0 0 0 .664 70.019l433.454 427.082L16.859 939.048a49.777 49.777 0 0 0-.664 70.019 49.013 49.013 0 0 0 69.687.663l434.085-427.746 416.828 427.083A49.013 49.013 0 0 0 972.037 1024a48.416 48.416 0 0 0 34.512-14.27 49.777 49.777 0 0 0 .73-70.019z',\n }),\n )\n\nCloseIcon.displayName = 'CloseIcon'\n\nexport const UpdateIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'update' }, () =>\n h('path', {\n d: 'M949.949 146.25v255.826c0 21.981-13.989 35.97-35.97 35.97H658.154c-13.988 0-25.983-7.992-33.973-21.981-5.997-13.989-4-27.977 7.991-39.97l79.942-77.946c-55.954-51.973-121.918-77.955-199.863-77.955-37.975 0-75.95 8.002-113.924 21.99-37.975 15.985-67.948 37.976-91.934 63.957-25.982 23.987-47.973 53.96-63.957 91.934-29.983 73.955-29.983 153.895 0 227.85 15.984 37.976 37.975 67.947 63.957 91.934 23.986 25.982 53.959 47.973 91.934 63.956 37.974 13.989 75.95 21.991 113.924 21.991 45.967 0 87.942-9.998 127.913-29.982 41.976-17.99 75.951-45.967 101.931-83.943 7.993-4 11.994-5.995 13.989-5.995 5.997 0 9.998 1.994 13.988 5.995l77.958 77.946c3.989 4 5.986 7.993 5.986 11.994 0 1.994-1.996 5.995-3.99 11.994-43.973 51.962-93.941 91.934-151.9 117.914-53.958 25.983-115.92 39.972-185.874 39.972-61.961 0-119.921-11.984-169.89-33.973-57.96-25.985-105.923-57.963-139.896-93.943-35.98-33.972-67.958-81.936-93.94-139.897-45.967-101.93-45.967-237.846 0-339.777 25.982-57.96 57.96-105.923 93.94-139.896 33.973-35.98 81.936-67.958 139.896-93.94 49.968-21.99 107.928-33.974 169.89-33.974 55.963 0 109.923 9.988 161.885 29.973 53.97 21.99 101.933 51.963 139.908 89.938l73.954-73.944c9.987-9.998 23.987-13.988 39.971-8.002 13.988 8.002 21.98 19.995 21.98 33.984z',\n }),\n )\n\nUpdateIcon.displayName = 'UpdateIcon'\n"],"mappings":"wBASA,MAAM,GAID,CAAE,OAAO,GAAI,QAAQ,gBAAkB,CAAE,WAC5C,EACE,MACA,CACE,MAAS,6BACT,MAAS,CAAC,OAAQ,GAAG,EAAK,OAAO,CACjC,QAAW,gBACX,KAAQ,EACR,aAAc,GAAG,EAAK,OACvB,CACD,EAAM,SAAS,CAChB,CAEH,EAAW,YAAc,aAEzB,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,aAAc,KAClC,EAAE,OAAQ,CACR,EAAG,wPACJ,CAAC,CACH,CAEH,EAAc,YAAc,gBAE5B,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,cAAe,KACnC,EAAE,OAAQ,CACR,EAAG,iQACJ,CAAC,CACH,CAEH,EAAe,YAAc,iBAE7B,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,QAAS,KAC7B,EAAE,OAAQ,CACR,EAAG,wZACJ,CAAC,CACH,CAEH,EAAU,YAAc,YAExB,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,SAAU,KAC9B,EAAE,OAAQ,CACR,EAAG,guCACJ,CAAC,CACH,CAEH,EAAW,YAAc"}
1
+ {"version":3,"file":"icons-RRw4DIWa.js","names":[],"sources":["../src/client/components/icons.ts"],"sourcesContent":["// oxlint-disable id-length\nimport type { FunctionalComponent, VNode } from 'vue'\nimport { h } from 'vue'\n\ninterface SVGWrapperProps {\n name?: string\n color?: string\n}\n\nconst SVGWrapper: FunctionalComponent<\n SVGWrapperProps,\n Record<never, never>,\n { default: () => VNode | VNode[] }\n> = ({ name = '', color = 'currentColor' }, { slots }) =>\n h(\n 'svg',\n {\n 'xmlns': 'http://www.w3.org/2000/svg',\n 'class': ['icon', `${name}-icon`],\n 'viewBox': '0 0 1024 1024',\n 'fill': color,\n 'aria-label': `${name} icon`,\n },\n slots.default(),\n )\n\nSVGWrapper.displayName = 'SVGWrapper'\n\nexport const ArrowLeftIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'arrow-left' }, () =>\n h('path', {\n d: 'M802.8 448h-428l166-158.8c23.8-25 23.8-65.4 0-90.4s-62.4-25-86.4 0L178 466.8c-12 11.6-18 27.4-18 44.8v0.8c0 17.4 6 33.2 18 44.8l276.2 268c24 25 62.6 25 86.4 0 23.8-25 23.8-65.4 0-90.4l-166-158.8h428c33.8 0 61.2-28.6 61.2-64 0.2-36-27.2-64-61-64z',\n }),\n )\n\nArrowLeftIcon.displayName = 'ArrowLeftIcon'\n\nexport const ArrowRightIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'arrow-right' }, () =>\n h('path', {\n d: 'M569.8 825.2l276.2-268c12-11.6 18-27.4 18-44.8v-0.8c0-17.4-6-33.2-18-44.8l-276.2-268c-24-25-62.6-25-86.4 0-23.8 25-23.8 65.4 0 90.4l166 158.8h-428c-34 0-61.4 28.6-61.4 64 0 36 27.4 64 61.2 64h428l-166 158.8c-23.8 25-23.8 65.4 0 90.4 24 25 62.6 25 86.6 0z',\n }),\n )\n\nArrowRightIcon.displayName = 'ArrowRightIcon'\n\nexport const CloseIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'close' }, () =>\n h('path', {\n d: 'M589.654 511.965 1007.212 84.22a49.777 49.777 0 0 0-.73-70.02 49.046 49.046 0 0 0-69.687.665L519.967 441.946 85.882 14.2a49.08 49.08 0 0 0-69.687.664 49.777 49.777 0 0 0 .664 70.019l433.454 427.082L16.859 939.048a49.777 49.777 0 0 0-.664 70.019 49.013 49.013 0 0 0 69.687.663l434.085-427.746 416.828 427.083A49.013 49.013 0 0 0 972.037 1024a48.416 48.416 0 0 0 34.512-14.27 49.777 49.777 0 0 0 .73-70.019z',\n }),\n )\n\nCloseIcon.displayName = 'CloseIcon'\n\nexport const UpdateIcon: FunctionalComponent = () =>\n h(SVGWrapper, { name: 'update' }, () =>\n h('path', {\n d: 'M949.949 146.25v255.826c0 21.981-13.989 35.97-35.97 35.97H658.154c-13.988 0-25.983-7.992-33.973-21.981-5.997-13.989-4-27.977 7.991-39.97l79.942-77.946c-55.954-51.973-121.918-77.955-199.863-77.955-37.975 0-75.95 8.002-113.924 21.99-37.975 15.985-67.948 37.976-91.934 63.957-25.982 23.987-47.973 53.96-63.957 91.934-29.983 73.955-29.983 153.895 0 227.85 15.984 37.976 37.975 67.947 63.957 91.934 23.986 25.982 53.959 47.973 91.934 63.956 37.974 13.989 75.95 21.991 113.924 21.991 45.967 0 87.942-9.998 127.913-29.982 41.976-17.99 75.951-45.967 101.931-83.943 7.993-4 11.994-5.995 13.989-5.995 5.997 0 9.998 1.994 13.988 5.995l77.958 77.946c3.989 4 5.986 7.993 5.986 11.994 0 1.994-1.996 5.995-3.99 11.994-43.973 51.962-93.941 91.934-151.9 117.914-53.958 25.983-115.92 39.972-185.874 39.972-61.961 0-119.921-11.984-169.89-33.973-57.96-25.985-105.923-57.963-139.896-93.943-35.98-33.972-67.958-81.936-93.94-139.897-45.967-101.93-45.967-237.846 0-339.777 25.982-57.96 57.96-105.923 93.94-139.896 33.973-35.98 81.936-67.958 139.896-93.94 49.968-21.99 107.928-33.974 169.89-33.974 55.963 0 109.923 9.988 161.885 29.973 53.97 21.99 101.933 51.963 139.908 89.938l73.954-73.944c9.987-9.998 23.987-13.988 39.971-8.002 13.988 8.002 21.98 19.995 21.98 33.984z',\n }),\n )\n\nUpdateIcon.displayName = 'UpdateIcon'\n"],"mappings":"wBASA,MAAM,GAID,CAAE,OAAO,GAAI,QAAQ,gBAAkB,CAAE,WAC5C,EACE,MACA,CACE,MAAS,6BACT,MAAS,CAAC,OAAQ,GAAG,EAAK,MAAM,EAChC,QAAW,gBACX,KAAQ,EACR,aAAc,GAAG,EAAK,MACxB,EACA,EAAM,QAAQ,CAChB,EAEF,EAAW,YAAc,aAEzB,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,YAAa,MACjC,EAAE,OAAQ,CACR,EAAG,uPACL,CAAC,CACH,EAEF,EAAc,YAAc,gBAE5B,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,aAAc,MAClC,EAAE,OAAQ,CACR,EAAG,gQACL,CAAC,CACH,EAEF,EAAe,YAAc,iBAE7B,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,OAAQ,MAC5B,EAAE,OAAQ,CACR,EAAG,uZACL,CAAC,CACH,EAEF,EAAU,YAAc,YAExB,MAAa,MACX,EAAE,EAAY,CAAE,KAAM,QAAS,MAC7B,EAAE,OAAQ,CACR,EAAG,+tCACL,CAAC,CACH,EAEF,EAAW,YAAc"}
@@ -7,9 +7,9 @@ interface PwaPluginLocaleData {
7
7
  */
8
8
  install: string;
9
9
  /**
10
- * iOS install hint text
10
+ * IOS install hint text
11
11
  *
12
- * iOS 安装文字
12
+ * IOS 安装文字
13
13
  */
14
14
  iOSInstall: string;
15
15
  /**
@@ -69,4 +69,4 @@ interface PwaPluginLocaleData {
69
69
  }
70
70
  //#endregion
71
71
  export { PwaPluginLocaleData as t };
72
- //# sourceMappingURL=locales-BzKyD3qP.d.ts.map
72
+ //# sourceMappingURL=locales-D1imGthS.d.ts.map
@@ -1,25 +1,17 @@
1
- import { t as PwaPluginLocaleData } from "../locales-BzKyD3qP.js";
1
+ import { t as PwaPluginLocaleData } from "../locales-D1imGthS.js";
2
2
  import { DefaultLocaleInfo } from "@vuepress/helper";
3
3
  import { GenerateSWOptions } from "workbox-build";
4
4
  import { LocaleConfig } from "vuepress/shared";
5
5
  import { PluginFunction } from "vuepress/core";
6
6
 
7
7
  //#region src/shared/manifest.d.ts
8
- /**
9
- * @see https://www.w3.org/TR/mediaqueries-5/#display-mode
10
- */
8
+ /** @see https://www.w3.org/TR/mediaqueries-5/#display-mode */
11
9
  type DisplayMode = 'browser' | 'fullscreen' | 'minimal-ui' | 'standalone';
12
- /**
13
- * @see https://github.com/w3c/manifest/wiki/Categories
14
- */
10
+ /** @see https://github.com/w3c/manifest/wiki/Categories */
15
11
  type ManifestCategory = 'books' | 'business' | 'education' | 'entertainment' | 'finance' | 'fitness' | 'food' | 'games' | 'government' | 'health' | 'kids' | 'lifestyle' | 'magazines' | 'medical' | 'music' | 'navigation' | 'news' | 'personalization' | 'photo' | 'politics' | 'productivity' | 'security' | 'shopping' | 'social' | 'sports' | 'travel' | 'utilities' | 'weather';
16
- /**
17
- * @see https://www.w3.org/TR/screen-orientation/#dom-orientationlocktype
18
- */
12
+ /** @see https://www.w3.org/TR/screen-orientation/#dom-orientationlocktype */
19
13
  type OrientationLockType = 'any' | 'landscape-primary' | 'landscape-secondary' | 'landscape' | 'natural' | 'portrait-primary' | 'portrait-secondary' | 'portrait';
20
- /**
21
- * @see https://www.w3.org/TR/appmanifest/#manifest-image-resources
22
- */
14
+ /** @see https://www.w3.org/TR/appmanifest/#manifest-image-resources */
23
15
  interface ManifestImageResource {
24
16
  src: string;
25
17
  sizes: string;
@@ -28,13 +20,9 @@ interface ManifestImageResource {
28
20
  interface ManifestIcon extends ManifestImageResource {
29
21
  purpose?: 'any' | 'maskable' | 'monochrome';
30
22
  }
31
- /**
32
- * @see https://www.w3.org/TR/appmanifest/#external-application-resource
33
- */
23
+ /** @see https://www.w3.org/TR/appmanifest/#external-application-resource */
34
24
  interface ManifestExternalApplicationResource {
35
- /**
36
- * @see https://github.com/w3c/manifest/wiki/Platforms
37
- */
25
+ /** @see https://github.com/w3c/manifest/wiki/Platforms */
38
26
  platform: 'amazon' | 'chrome_web_store' | 'chromeos_play' | 'f-droid' | 'itunes' | 'play' | 'webapp' | 'windows';
39
27
  url: string;
40
28
  id?: string;
@@ -44,9 +32,7 @@ interface ManifestExternalApplicationResource {
44
32
  value: string;
45
33
  }[];
46
34
  }
47
- /**
48
- * @see https://www.w3.org/TR/appmanifest/#shortcut-items
49
- */
35
+ /** @see https://www.w3.org/TR/appmanifest/#shortcut-items */
50
36
  interface ManifestShortCutItem {
51
37
  name: string;
52
38
  url: string;
@@ -54,9 +40,7 @@ interface ManifestShortCutItem {
54
40
  description?: string;
55
41
  icons?: ManifestIcon[];
56
42
  }
57
- /**
58
- * @see https://www.w3.org/TR/appmanifest/
59
- */
43
+ /** @see https://www.w3.org/TR/appmanifest/ */
60
44
  interface AppManifest extends Record<string, unknown> {
61
45
  /**
62
46
  * @see https://www.w3.org/TR/appmanifest/#name-member
@@ -136,9 +120,7 @@ interface AppManifest extends Record<string, unknown> {
136
120
  }
137
121
  //#endregion
138
122
  //#region src/node/locales.d.ts
139
- /**
140
- * Default locale info for `@vuepress/plugin-pwa`
141
- */
123
+ /** Default locale info for `@vuepress/plugin-pwa` */
142
124
  declare const pwaLocaleInfo: DefaultLocaleInfo<PwaPluginLocaleData>;
143
125
  //#endregion
144
126
  //#region src/node/options.d.ts
@@ -165,8 +147,7 @@ interface ApplePwaOptions {
165
147
  * Color of status bar
166
148
  *
167
149
  * 状态栏的颜色
168
- *
169
- * @default "default"
150
+ * @default 'default'
170
151
  */
171
152
  statusBarColor?: 'black-translucent' | 'black' | 'default';
172
153
  }
@@ -176,7 +157,7 @@ interface PwaPluginOptions {
176
157
  *
177
158
  * Service Worker 文件路径
178
159
  *
179
- * @default "service-worker.js"
160
+ * @default 'service-worker.js'
180
161
  */
181
162
  serviceWorkerFilename?: string;
182
163
  /**
@@ -190,13 +171,13 @@ interface PwaPluginOptions {
190
171
  /**
191
172
  * Manifest file Config
192
173
  *
193
- * manifest 文件设置
174
+ * Manifest 文件设置
194
175
  */
195
176
  manifest?: AppManifest;
196
177
  /**
197
178
  * Path of favicon
198
179
  *
199
- * favicon 地址
180
+ * Favicon 地址
200
181
  */
201
182
  favicon?: string;
202
183
  /**
@@ -204,7 +185,7 @@ interface PwaPluginOptions {
204
185
  *
205
186
  * 主题色
206
187
  *
207
- * @default "#46bd87"
188
+ * @default '#46bd87'
208
189
  */
209
190
  themeColor?: string;
210
191
  /**
@@ -248,19 +229,26 @@ interface PwaPluginOptions {
248
229
  /**
249
230
  * Update logic
250
231
  *
251
- * - `"disable"`: Do nothing even when new service worker is available. After new service work succeeds installing and starts waiting, it will control page and provide new content in next visit.
252
- * - `"available"`: Only display update popup when the new service worker is available
253
- * - `"hint"`: Display a hint to let user choose to refresh immediately. This is helpful when you want users to see new docs immediately.
254
- * - `"force"`: unregister current service worker immediately then refresh to get new content. **This may affect visiting experiences**!
232
+ * - `"disable"`: Do nothing even when new service worker is available. After
233
+ * new service work succeeds installing and starts waiting, it will control
234
+ * page and provide new content in next visit.
235
+ * - `"available"`: Only display update popup when the new service worker is
236
+ * available
237
+ * - `"hint"`: Display a hint to let user choose to refresh immediately. This is
238
+ * helpful when you want users to see new docs immediately.
239
+ * - `"force"`: unregister current service worker immediately then refresh to
240
+ * get new content. **This may affect visiting experiences**!
255
241
  *
256
242
  * 更新逻辑
257
243
  *
258
- * - `"disable"`: 即使有新的 service worker 也不做任何事情,新的 service work 开始等待后,会在用户下次访问时接管页面,让用户获得新内容。
244
+ * - `"disable"`: 即使有新的 service worker 也不做任何事情,新的 service work
245
+ * 开始等待后,会在用户下次访问时接管页面,让用户获得新内容。
259
246
  * - `"available"`: 仅当新的 service worker 可用时才显示更新弹出窗口
260
- * - `"hint"`: 显示更新内容可用提示,并允许用户立即刷新。当新的 SW 成功注册后,将转为更新内容就绪弹窗。当你希望用户立即查看新文档时,这很有帮助。
247
+ * - `"hint"`: 显示更新内容可用提示,并允许用户立即刷新。当新的 SW
248
+ * 成功注册后,将转为更新内容就绪弹窗。当你希望用户立即查看新文档时,这很有帮助。
261
249
  * - `"force"`: 立即注销当前 Service Worker 然后刷新以获取新内容。**这可能会影响访问体验**!
262
250
  *
263
- * @default "available"
251
+ * @default 'available'
264
252
  */
265
253
  update?: 'available' | 'disable' | 'force' | 'hint';
266
254
  /**
@@ -268,7 +256,7 @@ interface PwaPluginOptions {
268
256
  *
269
257
  * 用于替换默认提示弹出组件的自定义组件。
270
258
  *
271
- * @default "PwaFoundPopup"
259
+ * @default 'PwaFoundPopup'
272
260
  */
273
261
  foundComponent?: string;
274
262
  /**
@@ -276,12 +264,12 @@ interface PwaPluginOptions {
276
264
  *
277
265
  * 用于替换默认更新弹出组件的自定义组件。
278
266
  *
279
- * @default "PwaReadyPopup"
267
+ * @default 'PwaReadyPopup'
280
268
  */
281
269
  readyComponent?: string;
282
270
  /**
283
- * workbox-build’s [generateSW config](https://developers.google.com/web/tools/workbox/modules/workbox-build#full_generatesw_config)
284
- *
271
+ * Workbox-build’s [generateSW
272
+ * config](https://developers.google.com/web/tools/workbox/modules/workbox-build#full_generatesw_config)
285
273
  */
286
274
  generateSWConfig?: Partial<GenerateSWOptions>;
287
275
  /**
@@ -306,25 +294,23 @@ interface PwaPluginOptions {
306
294
  *
307
295
  * PWA 插件
308
296
  *
309
- * @param options - Plugin options / 插件选项
310
- * @returns VuePress plugin / VuePress 插件
311
- *
312
297
  * @example
313
- * ```ts
314
- * import { pwaPlugin } from '@vuepress/plugin-pwa'
298
+ * import { pwaPlugin } from '@vuepress/plugin-pwa'
315
299
  *
316
- * export default {
317
- * plugins: [
318
- * pwaPlugin({
319
- * showInstall: true,
320
- * manifest: {
321
- * name: 'My PWA App'
322
- * },
323
- * update: 'hint'
324
- * })
325
- * ]
326
- * }
327
- * ```
300
+ * export default {
301
+ * plugins: [
302
+ * pwaPlugin({
303
+ * showInstall: true,
304
+ * manifest: {
305
+ * name: 'My PWA App',
306
+ * },
307
+ * update: 'hint',
308
+ * }),
309
+ * ],
310
+ * }
311
+ *
312
+ * @param options - Plugin options / 插件选项
313
+ * @returns VuePress plugin / VuePress 插件
328
314
  */
329
315
  declare const pwaPlugin: (options?: PwaPluginOptions) => PluginFunction;
330
316
  //#endregion
@@ -1,5 +1,5 @@
1
- import{Logger as e,addViteOptimizeDepsExclude as t,addViteSsrNoExternal as n,customizeDevServer as r,endsWith as i,getFullLocaleConfig as a,getModulePath as o,isLinkAbsolute as s}from"@vuepress/helper";import{colors as c,fs as l,getDirname as u,path as d}from"vuepress/utils";import{generateSW as f}from"workbox-build";import{isPlainObject as p}from"vuepress/shared";const m=[[[`en`,`en-US`],{install:`Install`,iOSInstall:`Tap the share button and then 'Add to Home Screen'`,cancel:`Cancel`,close:`Close`,prevImage:`Previous Image`,nextImage:`Next Image`,desc:`Description`,feature:`Key Features`,explain:`This app can be installed on your PC or mobile device. This will allow this web app to look and behave like any other installed app. You will find it in your app lists and be able to pin it to your home screen, start menus or task bars. This installed web app will also be able to safely interact with other apps and your operating system. `,hint:`New content found.`,update:`New content is available.`}],[[`zh`,`zh-CN`,`zh-Hans`],{install:`安装`,iOSInstall:`点击分享按钮然后点击“添加到主屏幕”`,cancel:`取消`,close:`关闭`,prevImage:`上一张图片`,nextImage:`下一张图片`,desc:`详情`,feature:`主要特色`,explain:`该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。`,hint:`发现新内容可用`,update:`新内容已就绪`}],[[`zh-TW`,`zh-Hant`],{install:`安裝`,iOSInstall:`點擊分享按鈕然後點擊“添加到主畫面”`,cancel:`取消`,close:`關閉`,prevImage:`上一張圖片`,nextImage:`下一張圖片`,desc:`詳情`,feature:`主要特色`,explain:`該應用可以安裝在你的 PC 或行動裝置上。這將使該 Web 應用程式外觀和行為與其他應用程式相同。它將在出現在應用程式列表中,並可以固定到主畫面,開始菜單或任務欄。此 Web 應用程式還將能夠與其他應用程式和你的操作系統安全地進行交互。`,hint:`發現新內容可用`,update:`新內容已就緒`}],[[`de`,`de-DE`],{install:`Installieren`,iOSInstall:`Drucke den Share-Button und dann 'zu Homescreen hinzufügen'`,cancel:`Abbrechen`,close:`Schließen`,prevImage:`Vorheriges Bild`,nextImage:`Nächstes Bild`,desc:`Beschreibung`,feature:`Funktionen`,explain:`Diese App kann auf Ihrem PC oder Mobilgerät installiert werden. Dadurch sieht diese Web-App aus und verhält sich wie jede andere installierte App. Sie finden sie in Ihren App-Listen und können sie an den Startbildschirm, die Startmenüs oder die Taskleisten anheften. Diese installierte Web-App kann auch sicher mit anderen Apps und Ihrem Betriebssystem interagieren.`,hint:`Neuer Inhalt gefunden.`,update:`Neue Inhalte sind verfügbar.`}],[[`vi`,`vi-VN`],{install:`Tải về`,iOSInstall:`Nhấn vào nút chia sẻ và sau đó 'Thêm vào Màn hình chính'`,cancel:`Huỷ bỏ`,close:`Đóng`,prevImage:`Hình ảnh trước đó`,nextImage:`Hình ảnh tiếp theo`,desc:`Sự miêu tả`,feature:`Các tính năng chính`,explain:`Ứng dụng này có thể được cài đặt trên PC hoặc thiết bị di động của bạn. Điều này sẽ cho phép ứng dụng web này trông và hoạt động giống như bất kỳ ứng dụng đã cài đặt nào khác. Bạn sẽ tìm thấy nó trong danh sách ứng dụng của mình và có thể ghim nó vào màn hình chính, menu bắt đầu hoặc thanh tác vụ. Ứng dụng web đã cài đặt này cũng sẽ có thể tương tác an toàn với các ứng dụng khác và hệ điều hành của bạn.`,hint:`Nội dung mới được tìm thấy`,update:`Đã có nội dung mới`}],[[`uk`],{install:`Встановити`,iOSInstall:`Торкніться кнопки «Поділитися», а потім «Додати на головний екран»`,cancel:`Скасувати`,close:`Закрити`,prevImage:`Попереднє зображення`,nextImage:`Наступне зображення`,desc:`Опис`,feature:`Основні характеристики`,explain:`Цю програму можна встановити на ПК або мобільний пристрій. Це дозволить цій веб-програмі виглядати та вести себе як будь-яка інша встановлена програма. Ви знайдете її у списках додатків і зможете закріпити на головному екрані, в меню «Пуск» або на панелі завдань. Ця встановлена веб-програма також зможе безпечно взаємодіяти з іншими програмами та вашою операційною системою. `,hint:`Знайдено новий вміст`,update:`Доступний новий контент.`}],[[`ru`,`ru-RU`],{install:`Установить`,iOSInstall:`Нажмите кнопку «Поделиться», а затем «Добавить на главный экран»`,cancel:`Отменить`,close:`Закрыть`,prevImage:`Предыдущее изображение`,nextImage:`Следующее изображение`,desc:`Описание`,feature:`Основные функции`,explain:`Это приложение может быть установлено на вашем компьютере или мобильном устройстве. Это позволит веб-приложению выглядеть и вести себя как любое другое установленное приложение. Вы найдете его в списках приложений и сможете закрепить его на домашнем экране, в меню пуск или на панели задач. Установленное веб-приложение также сможет безопасно взаимодействовать с другими приложениями и операционной системой. `,hint:`Найден новый контент`,update:`Доступен новый контент.`}],[[`br`],{install:`Instalar`,iOSInstall:`Toque no botão de compartilhar e depois 'Adicionar à Home'`,cancel:`Cancelar`,close:`Fechar`,prevImage:`Imagem anterior`,nextImage:`Próxima imagem`,desc:`Descrição`,feature:`Características Chave`,explain:`Esta aplicação web pode ser instalada no seu PC ou dispositivo móvel. Isso fará com que ela se pareça e se comporte como qualquer outra aplicação. Você a encontrará na lista de apps e poderá adicionar seu ícone à tela de entrada, menus ou barras de tarefa. Uma vez instalada, esta aplicação web também poderá interagir com outras aplicações ou com o próprio sistema operacional. `,hint:`Novo conteúdo encontrado`,update:`Novo conteúdo está disponível.`}],[[`pl`,`pl-PL`],{install:`Zainstaluj`,iOSInstall:`Stuknij przycisk udostępniania, a następnie „Dodaj do ekranu głównego”`,cancel:`Anuluj`,close:`Zamknij`,prevImage:`Poprzedni obrazek`,nextImage:`Następny obrazek`,desc:`Opis`,feature:`Kluczowe cechy`,explain:`Tę aplikację można zainstalować na komputerze lub urządzeniu mobilnym. Dzięki temu ta aplikacja internetowa będzie wyglądać i zachowywać się jak każda inna zainstalowana aplikacja. Znajdziesz ją na listach aplikacji i będziesz mógł przypiąć go do ekranu głównego, menu startowego lub pasków zadań. Ta zainstalowana aplikacja internetowa będzie również mogła bezpiecznie komunikować się z innymi aplikacjami i systemem operacyjnym.`,hint:`Znaleziono nową zawartość.`,update:`Nowa zawartość jest dostępna.`}],[[`sk`,`sk-SK`],{install:`Insštalácia`,iOSInstall:`Klikni na tlačidlo zdielania a potom 'Daj na domovskú obrazovku'`,cancel:`Zrušiť`,close:`Zavrieť`,prevImage:`Prodošlí obrázok`,nextImage:`Ďalší obrázok`,desc:`Poznámka`,feature:`Kľúčové vlastnosti`,explain:`Túto aplikáciu je možné nainštalovať na počítač alebo mobil. Toto umožný sa správať aplikácii ako každej inej nainštalovanej aplikácii. Nájdeš ju vo svojom liste aplikácii a budeš môcť ju pripnúť na domovskú stránku, štartovacieho menu alebo do panelu úloh. Táto nainštalovaná webová aplikácia umžní tiež bezpečne komunikovať s ostatnými nainštalovanými aplikáciami a operačným systémom. `,hint:`Nový obsah bol nájdený.`,update:`Nový obsah je dostupný.`}],[[`fr`,`fr-FR`],{install:`Installer`,iOSInstall:`Appuyez sur le bouton partager puis 'Ajouter à l'écran d'accueil'`,cancel:`Annuler`,close:`Fermer`,prevImage:`Image précédente`,nextImage:`Image suivante`,desc:`Description`,feature:`Composants clés`,explain:`Cette app peut être installée sur PC ou smartphone. Cela permettra de rendre cette page web comme n'importe quelle autre application. Vous la trouverez dans votre liste d'application et serez capable de la pin sur votre écran principal et divers menus. L'application web installée sera capable d'interagir avec les autres applications et le système d'exploitation.`,hint:`New content found.`,update:`New content is available.`}],[[`es`,`es-ES`],{install:`Instalar`,iOSInstall:`Toque el botón compartir y luego 'Agregar a la pantalla de inicio'`,cancel:`Cancelar`,close:`Cerrar`,prevImage:`Imagen anterior`,nextImage:`Imagen siguiente`,desc:`Descripción`,feature:`Características clave`,explain:`Esta aplicación se puede instalar en su PC o dispositivo móvil. Esto permitirá que esta aplicación web se vea y se comporte como cualquier otra aplicación instalada. Lo encontrará en su lista de aplicaciones y podrá fijarlo a su pantalla de inicio, menús de inicio o barras de tareas. Esta aplicación web instalada también podrá interactuar de manera segura con otras aplicaciones y su sistema operativo.`,hint:`Nuevo contenido encontrado.`,update:`Hay nuevo contenido disponible.`}],[[`ja`,`ja-JP`],{install:`インストール`,iOSInstall:`共有ボタンをタップし、「ホームスクリーンに追加」をタップします`,cancel:`キャンセル`,close:`閉じる`,prevImage:`前の画像`,nextImage:`次の画像`,desc:`詳細`,feature:`主な特徴`,explain:`このアプリは、PCまたはモバイルデバイスにインストールすることができます。 これにより、このウェブアプリは、インストールされている他のアプリと同様に表示され、動作するようになります。 アプリ一覧で見つけることができ、ホーム画面、スタートメニュー、タスクバーに固定することができます。 このインストールされたウェブアプリケーションは、他のアプリケーションやオペレーティングシステムと安全にやり取りすることもできます。`,hint:`新しいコンテンツが見つかりました。`,update:`新しいコンテンツが登場しました。`}],[[`tr`,`tr-TR`],{install:`Yükle`,iOSInstall:`Paylaş düğmesine ve ardından 'Ana Ekrana Ekle' düğmesine basın`,cancel:`İptal`,close:`Kapat`,prevImage:`Önceki Resim`,nextImage:`Sonraki Resim`,desc:`Tanım`,feature:`Ana Özellikler`,explain:`Bu uygulama PC'nize veya mobil cihazınıza yüklenebilir. Yüklenmesi bu web uygulamasının diğer yüklü uygulamalar gibi görünmesini ve davranmasını sağlar. Yüklenen web uygulamasını uygulama listenizde bulabilir ve ana ekranınıza, menülere veya görev çubuklarına sabitleyebilirsiniz. Aynı zamanda yüklenen web uygulaması, diğer uygulamalar ve işletim sisteminizle güvenli bir şekilde etkileşime girebilecektir.`,hint:`Yeni içerik bulundu.`,update:`Yeni içerik mevcut.`}],[[`ko`,`ko-KO`],{install:`설치`,iOSInstall:`공유 버튼을 누르고 '홈 화면에 추가'를 누르세요`,cancel:`취소`,close:`닫기`,prevImage:`이전 이미지`,nextImage:`다음 이미지`,desc:`설명`,feature:`주요 기능`,explain:`이 앱은 PC 또는 모바일 장치에 설치할 수 있습니다. 이렇게 하면 이 웹 앱은 다른 설치된 앱과 마찬가지로 표시되고 작동합니다. 앱 목록에서 찾을 수 있으며 홈 화면, 시작 메뉴, 작업 표시줄에 고정할 수 있습니다. 설치된 웹 앱은 다른 앱과 안전하게 상호 작용할 수 있습니다.`,hint:`새로운 콘텐츠를 찾았습니다.`,update:`새로운 콘텐츠가 있습니다.`}],[[`fi`,`fi-FI`],{install:`Asenna`,iOSInstall:`Paina Jaa-painiketta ja sitten 'Lisää kotiin'-painiketta`,cancel:`Peruuta`,close:`Sulje`,prevImage:`Edellinen kuva`,nextImage:`Seuraava kuva`,desc:`Kuvaus`,feature:`Avainominaisuudet`,explain:`Tämä sovellus on asennettavissa tietokoneelle tai mobiililaitteelle. Tämä mahdollistaa sovelluksen toiminnan tietokoneohjelmana. Löydät sen sovelluslistasta ja voit kiinnittää sen työpöydälle, kotinäytölle, tehtäväpalkkiin tai muulle listalle. Asennettu sovellus voi turvallisesti olla vuorovaikutuksessa muiden sovellusten ja käyttöjärjestelmäsi kanssa.`,hint:`Uutta sisältöä.`,update:`Uutta sisältöä on saatavilla.`}],[[`hu`,`hu-HU`],{install:`Telepítés`,iOSInstall:`Nyomd meg a megosztás gombot, majd a 'Hozzáadás a kezdőképernyőhöz' opciót`,cancel:`Mégse`,close:`Bezárás`,prevImage:`Előző kép`,nextImage:`Következő kép`,desc:`Leírás`,feature:`Főbb jellemzők`,explain:`Ez az alkalmazás telepíthető PC-re vagy mobil eszközre. Ez lehetővé teszi, hogy ez a webalkalmazás úgy nézzen ki és viselkedjen, mint bármely más telepített alkalmazás. Az alkalmazáslistában találod majd, és hozzáadhatod a kezdőképernyőhöz, indító menühöz vagy a feladatok sávjához. Az telepített webalkalmazás biztonságosan interakcióba léphet más alkalmazásokkal és az operációs rendszerrel.`,hint:`Új tartalom érhető el.`,update:`Új tartalom érhető el.`}],[[`id`,`id-ID`],{install:`Install`,iOSInstall:`Ketuk tombol bagikan, lalu 'Tambahkan ke Layar Utama'`,cancel:`Batal`,close:`Tutup`,prevImage:`Gambar sebelumnya`,nextImage:`Gambar selanjutnya`,desc:`Keterangan`,feature:`Fitur`,explain:`Aplikasi ini dapat diinstal di PC atau perangkat seluler Anda. Ini akan memungkinkan aplikasi web ini terlihat seperti aplikasi terpasang lainnya. Anda bisa menemukannya di daftar aplikasi dan dapat menyematkannya ke layar beranda, menu start, atau menu ke taskbar. Aplikasi web yang terinstal ini juga dapat berinteraksi dengan aplikasi lain dan dengan sistem operasi yang Anda gunakan. `,hint:`Konten baru ditemukan.`,update:`Konten baru telah tersedia.`}],[[`nl`,`nl-NL`],{install:`Installeren`,iOSInstall:`Druk op de share button en dan op 'Add to Home Screen'`,cancel:`Annuleren`,close:`Sluiten`,prevImage:`Vorige Foto`,nextImage:`Volgende Foto`,desc:`Beschrijving`,feature:`Belangrijkste mogelijkheden`,explain:`Deze app kan op uw PC of mobiel toestel geïnstalleerd worden. Dit laat toe om deze webapp er uit te laten alsof het een normale app is. Je kan het terugvinden in jouw applijsten en kan het op je homescreen, start menu of taakbalk vastzetten. Deze geïnstalleerde webapp zal ook veilig samenwerken met andere apps en uw besturingssysteem. `,hint:`Nieuwe inhoud gevonden.`,update:`Nieuwe inhoud is beschikbaar.`}]],h=async(e,t)=>{let{base:n,title:r,description:i,lang:a,locales:o}=e.siteData,s=o[`/`]??{},c=e.dir.source(`.vuepress/public/manifest.webmanifest`),u=e.dir.source(`.vuepress/public/manifest.json`),d=JSON.parse(l.existsSync(c)?await l.readFile(c,`utf-8`):l.existsSync(u)?await l.readFile(u,`utf-8`):`{}`);return{name:r||s.title||`Site`,short_name:r||s.title||`Site`,description:i||s.description||`A site built with vuepress`,lang:s.lang??a,start_url:n,scope:n,display:`standalone`,theme_color:t.themeColor||`#46bd87`,background_color:`#ffffff`,orientation:`portrait-primary`,prefer_related_applications:!1,...d,...t.manifest}},g=`@vuepress/plugin-pwa`,_=new e(g),v=async(e,t)=>{let{succeed:n}=_.load(`Generating manifest.webmanifest`),r=await h(e,t),i=e.dir.dest(`manifest.webmanifest`);await l.writeJSON(i,r,{flag:`w`}),n(`Manifest generated and saved to ${c.cyan(d.relative(process.cwd(),i))}!`)},y=[`png`,`jpg`,`jpeg`,`webp`,`bmp`,`gif`],b=[`js`,`css`,`svg`,`woff`,`woff2`,`eot`,`ttf`,`otf`],x=(e=1024)=>t=>{let n=[],r=[];for(let a of t){let{url:t,size:o}=a;y.some(e=>i(t,`.${e}`))&&o>e*1024?n.push(`Skipped ${t}, as it's ${Math.ceil(o/1024)} KB.`):r.push(a)}return{warnings:n,manifest:r}},S=async(e,t)=>{let{succeed:n}=_.load(`Generating service worker`),r=[`**/*.{${b.join(`,`)}}`];t.cacheHTML?r.push(`**/*.html`):r.push(`./index.html`,`./404.html`),t.cacheImage&&r.push(`**/*.{${y.join(`,`)}}`),await f({dontCacheBustURLsMatching:RegExp(`\\.[0-9a-f]{8}\\.(${[`html`,...b,...y].join(`|`)})$`),globPatterns:r,cleanupOutdatedCaches:!0,clientsClaim:!0,maximumFileSizeToCacheInBytes:(t.maxSize??2048)*1024,manifestTransforms:[x(t.maxImageSize)],mode:e.env.isDebug?`development`:`production`,sourcemap:e.env.isDebug,...t.generateSWConfig,globDirectory:e.dir.dest(),swDest:e.dir.dest(t.serviceWorkerFilename??`service-worker.js`)}).then(({count:e,size:t,warnings:r})=>{n(),_.info(`Precache ${c.cyan(`${e} files`)}, totaling ${c.cyan(`${(t/1024/1024).toFixed(2)} Mb.`)}.`),r.length>0&&_.warn(`\n${r.map(e=>` · ${e}`).join(`
2
- `)}`),t>104857600?_.error(`Cache Size is larger than 100MB, so that it can not be registered on all browsers.\n${c.blue("Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\n")}`):t>52428800&&_.warn(`\nCache Size is larger than 50MB, which will not be registered on Safari.\n${c.blue("Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\n")}`)})},C=(e,t)=>s(t)?t.replace(/^\//,e):t,w=(e,t)=>(t.icons&&=t.icons.map(t=>({...t,src:C(e,t.src)})),t.shortcuts&&=t.shortcuts.map(t=>({...t,icons:t.icons?.map(t=>({...t,src:C(e,t.src)}))??[],url:C(e,t.url)})),t.screenshots&&=t.screenshots.map(t=>({...t,src:C(e,t.src)})),t),T=(e,t)=>{t.favicon&&=C(e,t.favicon),t.apple&&(t.apple.icon&&(t.apple.icon=C(e,t.apple.icon)),t.apple.maskIcon&&(t.apple.maskIcon=C(e,t.apple.maskIcon))),t.manifest&&=w(e,t.manifest)},E=(e,{favicon:t,manifest:n,themeColor:r=`#46bd87`,apple:i})=>{let{base:a,head:o}=e.siteData,s=[],c=[];o.forEach(e=>{e[0]===`meta`?s.push(e[1].name):e[0]===`link`&&c.push(e[1].rel)});let l=n?.name??e.siteData.title,u=``,d=(e,t,n={})=>{c.includes(e)||o.push([`link`,{rel:e,href:t,...n}])},f=(e,t,n={})=>{s.includes(e)||o.push([`meta`,{name:e,content:t,...n}])};if(l&&f(`application-name`,l),f(`mobile-web-app-capable`,`yes`),f(`theme-color`,r||`#46bd87`),p(i)&&i.statusBarColor&&f(`apple-mobile-web-app-status-bar-style`,i.statusBarColor),t&&d(`icon`,t),d(`manifest`,`${a}manifest.webmanifest`,{crossorigin:`use-credentials`}),n?.icons){let{icons:e}=n;e.length>0&&(u=e[0].src,n.icons.forEach(e=>{e.type?d(`icon`,e.src,{type:e.type,sizes:e.sizes}):d(`icon`,e.src,{sizes:e.sizes})}))}p(i)&&(i.icon||u)?(d(`apple-touch-icon`,i.icon||u),i.maskIcon&&d(`mask-icon`,i.maskIcon,{color:r||`#46bd87`})):(i??!0)&&u&&d(`apple-touch-icon`,u)},D=import.meta.dirname||u(import.meta.url),O=(e,t)=>{let n=``,r=[];return t.showInstall&&(n+=`\
1
+ import{Logger as e,addViteOptimizeDepsExclude as t,addViteSsrNoExternal as n,customizeDevServer as r,endsWith as i,getFullLocaleConfig as a,getModulePath as o,isLinkAbsolute as s}from"@vuepress/helper";import{colors as c,fs as l,getDirname as u,path as d}from"vuepress/utils";import{generateSW as f}from"workbox-build";import{isPlainObject as p}from"vuepress/shared";const m=[[[`en`,`en-US`],{install:`Install`,iOSInstall:`Tap the share button and then 'Add to Home Screen'`,cancel:`Cancel`,close:`Close`,prevImage:`Previous Image`,nextImage:`Next Image`,desc:`Description`,feature:`Key Features`,explain:`This app can be installed on your PC or mobile device. This will allow this web app to look and behave like any other installed app. You will find it in your app lists and be able to pin it to your home screen, start menus or task bars. This installed web app will also be able to safely interact with other apps and your operating system. `,hint:`New content found.`,update:`New content is available.`}],[[`zh`,`zh-CN`,`zh-Hans`],{install:`安装`,iOSInstall:`点击分享按钮然后点击“添加到主屏幕”`,cancel:`取消`,close:`关闭`,prevImage:`上一张图片`,nextImage:`下一张图片`,desc:`详情`,feature:`主要特色`,explain:`该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。`,hint:`发现新内容可用`,update:`新内容已就绪`}],[[`zh-TW`,`zh-Hant`],{install:`安裝`,iOSInstall:`點擊分享按鈕然後點擊“添加到主畫面”`,cancel:`取消`,close:`關閉`,prevImage:`上一張圖片`,nextImage:`下一張圖片`,desc:`詳情`,feature:`主要特色`,explain:`該應用可以安裝在你的 PC 或行動裝置上。這將使該 Web 應用程式外觀和行為與其他應用程式相同。它將在出現在應用程式列表中,並可以固定到主畫面,開始菜單或任務欄。此 Web 應用程式還將能夠與其他應用程式和你的操作系統安全地進行交互。`,hint:`發現新內容可用`,update:`新內容已就緒`}],[[`de`,`de-DE`],{install:`Installieren`,iOSInstall:`Drucke den Share-Button und dann 'zu Homescreen hinzufügen'`,cancel:`Abbrechen`,close:`Schließen`,prevImage:`Vorheriges Bild`,nextImage:`Nächstes Bild`,desc:`Beschreibung`,feature:`Funktionen`,explain:`Diese App kann auf Ihrem PC oder Mobilgerät installiert werden. Dadurch sieht diese Web-App aus und verhält sich wie jede andere installierte App. Sie finden sie in Ihren App-Listen und können sie an den Startbildschirm, die Startmenüs oder die Taskleisten anheften. Diese installierte Web-App kann auch sicher mit anderen Apps und Ihrem Betriebssystem interagieren.`,hint:`Neuer Inhalt gefunden.`,update:`Neue Inhalte sind verfügbar.`}],[[`vi`,`vi-VN`],{install:`Tải về`,iOSInstall:`Nhấn vào nút chia sẻ và sau đó 'Thêm vào Màn hình chính'`,cancel:`Huỷ bỏ`,close:`Đóng`,prevImage:`Hình ảnh trước đó`,nextImage:`Hình ảnh tiếp theo`,desc:`Sự miêu tả`,feature:`Các tính năng chính`,explain:`Ứng dụng này có thể được cài đặt trên PC hoặc thiết bị di động của bạn. Điều này sẽ cho phép ứng dụng web này trông và hoạt động giống như bất kỳ ứng dụng đã cài đặt nào khác. Bạn sẽ tìm thấy nó trong danh sách ứng dụng của mình và có thể ghim nó vào màn hình chính, menu bắt đầu hoặc thanh tác vụ. Ứng dụng web đã cài đặt này cũng sẽ có thể tương tác an toàn với các ứng dụng khác và hệ điều hành của bạn.`,hint:`Nội dung mới được tìm thấy`,update:`Đã có nội dung mới`}],[[`uk`],{install:`Встановити`,iOSInstall:`Торкніться кнопки «Поділитися», а потім «Додати на головний екран»`,cancel:`Скасувати`,close:`Закрити`,prevImage:`Попереднє зображення`,nextImage:`Наступне зображення`,desc:`Опис`,feature:`Основні характеристики`,explain:`Цю програму можна встановити на ПК або мобільний пристрій. Це дозволить цій веб-програмі виглядати та вести себе як будь-яка інша встановлена програма. Ви знайдете її у списках додатків і зможете закріпити на головному екрані, в меню «Пуск» або на панелі завдань. Ця встановлена веб-програма також зможе безпечно взаємодіяти з іншими програмами та вашою операційною системою. `,hint:`Знайдено новий вміст`,update:`Доступний новий контент.`}],[[`ru`,`ru-RU`],{install:`Установить`,iOSInstall:`Нажмите кнопку «Поделиться», а затем «Добавить на главный экран»`,cancel:`Отменить`,close:`Закрыть`,prevImage:`Предыдущее изображение`,nextImage:`Следующее изображение`,desc:`Описание`,feature:`Основные функции`,explain:`Это приложение может быть установлено на вашем компьютере или мобильном устройстве. Это позволит веб-приложению выглядеть и вести себя как любое другое установленное приложение. Вы найдете его в списках приложений и сможете закрепить его на домашнем экране, в меню пуск или на панели задач. Установленное веб-приложение также сможет безопасно взаимодействовать с другими приложениями и операционной системой. `,hint:`Найден новый контент`,update:`Доступен новый контент.`}],[[`br`],{install:`Instalar`,iOSInstall:`Toque no botão de compartilhar e depois 'Adicionar à Home'`,cancel:`Cancelar`,close:`Fechar`,prevImage:`Imagem anterior`,nextImage:`Próxima imagem`,desc:`Descrição`,feature:`Características Chave`,explain:`Esta aplicação web pode ser instalada no seu PC ou dispositivo móvel. Isso fará com que ela se pareça e se comporte como qualquer outra aplicação. Você a encontrará na lista de apps e poderá adicionar seu ícone à tela de entrada, menus ou barras de tarefa. Uma vez instalada, esta aplicação web também poderá interagir com outras aplicações ou com o próprio sistema operacional. `,hint:`Novo conteúdo encontrado`,update:`Novo conteúdo está disponível.`}],[[`pl`,`pl-PL`],{install:`Zainstaluj`,iOSInstall:`Stuknij przycisk udostępniania, a następnie „Dodaj do ekranu głównego”`,cancel:`Anuluj`,close:`Zamknij`,prevImage:`Poprzedni obrazek`,nextImage:`Następny obrazek`,desc:`Opis`,feature:`Kluczowe cechy`,explain:`Tę aplikację można zainstalować na komputerze lub urządzeniu mobilnym. Dzięki temu ta aplikacja internetowa będzie wyglądać i zachowywać się jak każda inna zainstalowana aplikacja. Znajdziesz ją na listach aplikacji i będziesz mógł przypiąć go do ekranu głównego, menu startowego lub pasków zadań. Ta zainstalowana aplikacja internetowa będzie również mogła bezpiecznie komunikować się z innymi aplikacjami i systemem operacyjnym.`,hint:`Znaleziono nową zawartość.`,update:`Nowa zawartość jest dostępna.`}],[[`sk`,`sk-SK`],{install:`Insštalácia`,iOSInstall:`Klikni na tlačidlo zdielania a potom 'Daj na domovskú obrazovku'`,cancel:`Zrušiť`,close:`Zavrieť`,prevImage:`Prodošlí obrázok`,nextImage:`Ďalší obrázok`,desc:`Poznámka`,feature:`Kľúčové vlastnosti`,explain:`Túto aplikáciu je možné nainštalovať na počítač alebo mobil. Toto umožný sa správať aplikácii ako každej inej nainštalovanej aplikácii. Nájdeš ju vo svojom liste aplikácii a budeš môcť ju pripnúť na domovskú stránku, štartovacieho menu alebo do panelu úloh. Táto nainštalovaná webová aplikácia umžní tiež bezpečne komunikovať s ostatnými nainštalovanými aplikáciami a operačným systémom. `,hint:`Nový obsah bol nájdený.`,update:`Nový obsah je dostupný.`}],[[`fr`,`fr-FR`],{install:`Installer`,iOSInstall:`Appuyez sur le bouton partager puis 'Ajouter à l'écran d'accueil'`,cancel:`Annuler`,close:`Fermer`,prevImage:`Image précédente`,nextImage:`Image suivante`,desc:`Description`,feature:`Composants clés`,explain:`Cette app peut être installée sur PC ou smartphone. Cela permettra de rendre cette page web comme n'importe quelle autre application. Vous la trouverez dans votre liste d'application et serez capable de la pin sur votre écran principal et divers menus. L'application web installée sera capable d'interagir avec les autres applications et le système d'exploitation.`,hint:`New content found.`,update:`New content is available.`}],[[`es`,`es-ES`],{install:`Instalar`,iOSInstall:`Toque el botón compartir y luego 'Agregar a la pantalla de inicio'`,cancel:`Cancelar`,close:`Cerrar`,prevImage:`Imagen anterior`,nextImage:`Imagen siguiente`,desc:`Descripción`,feature:`Características clave`,explain:`Esta aplicación se puede instalar en su PC o dispositivo móvil. Esto permitirá que esta aplicación web se vea y se comporte como cualquier otra aplicación instalada. Lo encontrará en su lista de aplicaciones y podrá fijarlo a su pantalla de inicio, menús de inicio o barras de tareas. Esta aplicación web instalada también podrá interactuar de manera segura con otras aplicaciones y su sistema operativo.`,hint:`Nuevo contenido encontrado.`,update:`Hay nuevo contenido disponible.`}],[[`ja`,`ja-JP`],{install:`インストール`,iOSInstall:`共有ボタンをタップし、「ホームスクリーンに追加」をタップします`,cancel:`キャンセル`,close:`閉じる`,prevImage:`前の画像`,nextImage:`次の画像`,desc:`詳細`,feature:`主な特徴`,explain:`このアプリは、PCまたはモバイルデバイスにインストールすることができます。 これにより、このウェブアプリは、インストールされている他のアプリと同様に表示され、動作するようになります。 アプリ一覧で見つけることができ、ホーム画面、スタートメニュー、タスクバーに固定することができます。 このインストールされたウェブアプリケーションは、他のアプリケーションやオペレーティングシステムと安全にやり取りすることもできます。`,hint:`新しいコンテンツが見つかりました。`,update:`新しいコンテンツが登場しました。`}],[[`tr`,`tr-TR`],{install:`Yükle`,iOSInstall:`Paylaş düğmesine ve ardından 'Ana Ekrana Ekle' düğmesine basın`,cancel:`İptal`,close:`Kapat`,prevImage:`Önceki Resim`,nextImage:`Sonraki Resim`,desc:`Tanım`,feature:`Ana Özellikler`,explain:`Bu uygulama PC'nize veya mobil cihazınıza yüklenebilir. Yüklenmesi bu web uygulamasının diğer yüklü uygulamalar gibi görünmesini ve davranmasını sağlar. Yüklenen web uygulamasını uygulama listenizde bulabilir ve ana ekranınıza, menülere veya görev çubuklarına sabitleyebilirsiniz. Aynı zamanda yüklenen web uygulaması, diğer uygulamalar ve işletim sisteminizle güvenli bir şekilde etkileşime girebilecektir.`,hint:`Yeni içerik bulundu.`,update:`Yeni içerik mevcut.`}],[[`ko`,`ko-KO`],{install:`설치`,iOSInstall:`공유 버튼을 누르고 '홈 화면에 추가'를 누르세요`,cancel:`취소`,close:`닫기`,prevImage:`이전 이미지`,nextImage:`다음 이미지`,desc:`설명`,feature:`주요 기능`,explain:`이 앱은 PC 또는 모바일 장치에 설치할 수 있습니다. 이렇게 하면 이 웹 앱은 다른 설치된 앱과 마찬가지로 표시되고 작동합니다. 앱 목록에서 찾을 수 있으며 홈 화면, 시작 메뉴, 작업 표시줄에 고정할 수 있습니다. 설치된 웹 앱은 다른 앱과 안전하게 상호 작용할 수 있습니다.`,hint:`새로운 콘텐츠를 찾았습니다.`,update:`새로운 콘텐츠가 있습니다.`}],[[`fi`,`fi-FI`],{install:`Asenna`,iOSInstall:`Paina Jaa-painiketta ja sitten 'Lisää kotiin'-painiketta`,cancel:`Peruuta`,close:`Sulje`,prevImage:`Edellinen kuva`,nextImage:`Seuraava kuva`,desc:`Kuvaus`,feature:`Avainominaisuudet`,explain:`Tämä sovellus on asennettavissa tietokoneelle tai mobiililaitteelle. Tämä mahdollistaa sovelluksen toiminnan tietokoneohjelmana. Löydät sen sovelluslistasta ja voit kiinnittää sen työpöydälle, kotinäytölle, tehtäväpalkkiin tai muulle listalle. Asennettu sovellus voi turvallisesti olla vuorovaikutuksessa muiden sovellusten ja käyttöjärjestelmäsi kanssa.`,hint:`Uutta sisältöä.`,update:`Uutta sisältöä on saatavilla.`}],[[`hu`,`hu-HU`],{install:`Telepítés`,iOSInstall:`Nyomd meg a megosztás gombot, majd a 'Hozzáadás a kezdőképernyőhöz' opciót`,cancel:`Mégse`,close:`Bezárás`,prevImage:`Előző kép`,nextImage:`Következő kép`,desc:`Leírás`,feature:`Főbb jellemzők`,explain:`Ez az alkalmazás telepíthető PC-re vagy mobil eszközre. Ez lehetővé teszi, hogy ez a webalkalmazás úgy nézzen ki és viselkedjen, mint bármely más telepített alkalmazás. Az alkalmazáslistában találod majd, és hozzáadhatod a kezdőképernyőhöz, indító menühöz vagy a feladatok sávjához. Az telepített webalkalmazás biztonságosan interakcióba léphet más alkalmazásokkal és az operációs rendszerrel.`,hint:`Új tartalom érhető el.`,update:`Új tartalom érhető el.`}],[[`id`,`id-ID`],{install:`Install`,iOSInstall:`Ketuk tombol bagikan, lalu 'Tambahkan ke Layar Utama'`,cancel:`Batal`,close:`Tutup`,prevImage:`Gambar sebelumnya`,nextImage:`Gambar selanjutnya`,desc:`Keterangan`,feature:`Fitur`,explain:`Aplikasi ini dapat diinstal di PC atau perangkat seluler Anda. Ini akan memungkinkan aplikasi web ini terlihat seperti aplikasi terpasang lainnya. Anda bisa menemukannya di daftar aplikasi dan dapat menyematkannya ke layar beranda, menu start, atau menu ke taskbar. Aplikasi web yang terinstal ini juga dapat berinteraksi dengan aplikasi lain dan dengan sistem operasi yang Anda gunakan. `,hint:`Konten baru ditemukan.`,update:`Konten baru telah tersedia.`}],[[`nl`,`nl-NL`],{install:`Installeren`,iOSInstall:`Druk op de share button en dan op 'Add to Home Screen'`,cancel:`Annuleren`,close:`Sluiten`,prevImage:`Vorige Foto`,nextImage:`Volgende Foto`,desc:`Beschrijving`,feature:`Belangrijkste mogelijkheden`,explain:`Deze app kan op uw PC of mobiel toestel geïnstalleerd worden. Dit laat toe om deze webapp er uit te laten alsof het een normale app is. Je kan het terugvinden in jouw applijsten en kan het op je homescreen, start menu of taakbalk vastzetten. Deze geïnstalleerde webapp zal ook veilig samenwerken met andere apps en uw besturingssysteem. `,hint:`Nieuwe inhoud gevonden.`,update:`Nieuwe inhoud is beschikbaar.`}]],h=async(e,t)=>{let{base:n,title:r,description:i,lang:a,locales:o}=e.siteData,s=o[`/`]??{},c=e.dir.source(`.vuepress/public/manifest.webmanifest`),u=e.dir.source(`.vuepress/public/manifest.json`),d=JSON.parse(l.existsSync(c)?await l.readFile(c,`utf-8`):l.existsSync(u)?await l.readFile(u,`utf-8`):`{}`);return{name:r||s.title||`Site`,short_name:r||s.title||`Site`,description:i||s.description||`A site built with vuepress`,lang:s.lang??a,start_url:n,scope:n,display:`standalone`,theme_color:t.themeColor||`#46bd87`,background_color:`#ffffff`,orientation:`portrait-primary`,prefer_related_applications:!1,...d,...t.manifest}},g=`@vuepress/plugin-pwa`,_=new e(g),v=async(e,t)=>{let{succeed:n}=_.load(`Generating manifest.webmanifest`),r=await h(e,t),i=e.dir.dest(`manifest.webmanifest`);await l.writeJSON(i,r,{flag:`w`}),n(`Manifest generated and saved to ${c.cyan(d.relative(process.cwd(),i))}!`)},y=[`png`,`jpg`,`jpeg`,`webp`,`bmp`,`gif`],b=[`js`,`css`,`svg`,`woff`,`woff2`,`eot`,`ttf`,`otf`],x=(e=1024)=>t=>{let n=[],r=[];for(let a of t){let{url:t,size:o}=a;y.some(e=>i(t,`.${e}`))&&o>e*1024?n.push(`Skipped ${t}, as it's ${Math.ceil(o/1024)} KB.`):r.push(a)}return{warnings:n,manifest:r}},S=async(e,t)=>{let{succeed:n}=_.load(`Generating service worker`),r=[`**/*.{${b.join(`,`)}}`];t.cacheHTML?r.push(`**/*.html`):r.push(`./index.html`,`./404.html`),t.cacheImage&&r.push(`**/*.{${y.join(`,`)}}`),await f({dontCacheBustURLsMatching:RegExp(`\\.[0-9a-f]{8}\\.(${[`html`,...b,...y].join(`|`)})$`,`u`),globPatterns:r,cleanupOutdatedCaches:!0,clientsClaim:!0,maximumFileSizeToCacheInBytes:(t.maxSize??2048)*1024,manifestTransforms:[x(t.maxImageSize)],mode:e.env.isDebug?`development`:`production`,sourcemap:e.env.isDebug,...t.generateSWConfig,globDirectory:e.dir.dest(),swDest:e.dir.dest(t.serviceWorkerFilename??`service-worker.js`)}).then(({count:e,size:t,warnings:r})=>{n(),_.info(`Precache ${c.cyan(`${e} files`)}, totaling ${c.cyan(`${(t/1024/1024).toFixed(2)} Mb.`)}.`),r.length>0&&_.warn(`\n${r.map(e=>` · ${e}`).join(`
2
+ `)}`),t>104857600?_.error(`Cache Size is larger than 100MB, so that it can not be registered on all browsers.\n${c.blue("Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\n")}`):t>52428800&&_.warn(`\nCache Size is larger than 50MB, which will not be registered on Safari.\n${c.blue("Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\n")}`)})},C=(e,t)=>s(t)?t.replace(/^\//u,e):t,w=(e,t)=>(t.icons&&=t.icons.map(t=>({...t,src:C(e,t.src)})),t.shortcuts&&=t.shortcuts.map(t=>({...t,icons:t.icons?.map(t=>({...t,src:C(e,t.src)}))??[],url:C(e,t.url)})),t.screenshots&&=t.screenshots.map(t=>({...t,src:C(e,t.src)})),t),T=(e,t)=>{t.favicon&&=C(e,t.favicon),t.apple&&(t.apple.icon&&(t.apple.icon=C(e,t.apple.icon)),t.apple.maskIcon&&(t.apple.maskIcon=C(e,t.apple.maskIcon))),t.manifest&&=w(e,t.manifest)},E=(e,{favicon:t,manifest:n,themeColor:r=`#46bd87`,apple:i})=>{let{base:a,head:o}=e.siteData,s=[],c=[];o.forEach(e=>{e[0]===`meta`?s.push(e[1].name):e[0]===`link`&&c.push(e[1].rel)});let l=n?.name??e.siteData.title,u=``,d=(e,t,n={})=>{c.includes(e)||o.push([`link`,{rel:e,href:t,...n}])},f=(e,t,n={})=>{s.includes(e)||o.push([`meta`,{name:e,content:t,...n}])};if(l&&f(`application-name`,l),f(`mobile-web-app-capable`,`yes`),f(`theme-color`,r||`#46bd87`),p(i)&&i.statusBarColor&&f(`apple-mobile-web-app-status-bar-style`,i.statusBarColor),t&&d(`icon`,t),d(`manifest`,`${a}manifest.webmanifest`,{crossorigin:`use-credentials`}),n?.icons){let{icons:e}=n;e.length>0&&(u=e[0].src,n.icons.forEach(e=>{e.type?d(`icon`,e.src,{type:e.type,sizes:e.sizes}):d(`icon`,e.src,{sizes:e.sizes})}))}p(i)&&(i.icon||u)?(d(`apple-touch-icon`,i.icon||u),i.maskIcon&&d(`mask-icon`,i.maskIcon,{color:r||`#46bd87`})):(i??!0)&&u&&d(`apple-touch-icon`,u)},D=import.meta.dirname||u(import.meta.url),O=(e,t)=>{let n=``,r=[];return t.showInstall&&(n+=`\
3
3
  import { PwaInstall as _PwaInstall } from "${d.join(D,`../client/components/PwaInstall.js`)}";
4
4
  `,r.push(`PwaInstall`)),t.update===`hint`?(n+=t.foundComponent?`import _PwaFoundPopup from "${t.foundComponent}";
5
5
  `:`\
@@ -26,5 +26,5 @@ ${r.map(e=>` () => h(_${e}, { locales }),`).join(`
26
26
  `)}
27
27
  ],
28
28
  });
29
- `)},k=(e={})=>i=>{i.env.isDebug&&_.info(`Options:`,e);let{shouldPrefetch:a=!0}=i.options,{base:o}=i.siteData;return e.appendBase&&T(o,e),a===!0&&_.warn(`The plugin will register service worker to handle assets, so we recommend you to set "shouldPrefetch: false" in VuePress config file.`),E(i,e),{name:g,extendsBundlerOptions:a=>{t(a,i,[`mitt`,`register-service-worker`]),n(a,i,`@vuepress/helper`),r(a,i,{path:`/manifest.webmanifest`,response:async(t,n)=>(n.setHeader(`Content-Type`,`application/manifest+json`),JSON.stringify(await h(i,e))),errMsg:`Unexpected manifest generation error`})},onGenerated:async()=>{await v(i,e),await S(i,e)},clientConfigFile:()=>O(i,e)}};export{m as pwaLocaleInfo,k as pwaPlugin};
29
+ `)},k=(e={})=>i=>{i.env.isDebug&&_.info(`Options:`,e);let{shouldPrefetch:a}=i.options,{base:o}=i.siteData;return e.appendBase&&T(o,e),a!==!0&&_.warn(`The plugin will register service worker to handle assets, so we recommend you to set "shouldPrefetch: false" in VuePress config file.`),E(i,e),{name:g,extendsBundlerOptions:a=>{t(a,i,[`mitt`,`register-service-worker`]),n(a,i,`@vuepress/helper`),r(a,i,{path:`/manifest.webmanifest`,response:async(t,n)=>(n.setHeader(`Content-Type`,`application/manifest+json`),JSON.stringify(await h(i,e))),errMsg:`Unexpected manifest generation error`})},onGenerated:async()=>{await v(i,e),await S(i,e)},clientConfigFile:()=>O(i,e)}};export{m as pwaLocaleInfo,k as pwaPlugin};
30
30
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/node/locales.ts","../../src/node/getManifest.ts","../../src/node/logger.ts","../../src/node/generateManifest.ts","../../src/node/generateServiceWorker.ts","../../src/node/helper.ts","../../src/node/injectLinksToHead.ts","../../src/node/prepareClientConfigFile.ts","../../src/node/pwaPlugin.ts"],"sourcesContent":["import type { DefaultLocaleInfo } from '@vuepress/helper'\n\nimport type { PwaPluginLocaleData } from '../shared/index.js'\n\n/**\n * Default locale info for `@vuepress/plugin-pwa`\n */\nexport const pwaLocaleInfo: DefaultLocaleInfo<PwaPluginLocaleData> = [\n [\n ['en', 'en-US'],\n {\n install: 'Install',\n iOSInstall: \"Tap the share button and then 'Add to Home Screen'\",\n cancel: 'Cancel',\n close: 'Close',\n prevImage: 'Previous Image',\n nextImage: 'Next Image',\n desc: 'Description',\n feature: 'Key Features',\n explain:\n 'This app can be installed on your PC or mobile device. This will allow this web app to look and behave like any other installed app. You will find it in your app lists and be able to pin it to your home screen, start menus or task bars. This installed web app will also be able to safely interact with other apps and your operating system. ',\n hint: 'New content found.',\n update: 'New content is available.',\n },\n ],\n [\n ['zh', 'zh-CN', 'zh-Hans'],\n {\n install: '安装',\n iOSInstall: '点击分享按钮然后点击“添加到主屏幕”',\n cancel: '取消',\n close: '关闭',\n prevImage: '上一张图片',\n nextImage: '下一张图片',\n desc: '详情',\n feature: '主要特色',\n explain:\n '该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。',\n hint: '发现新内容可用',\n update: '新内容已就绪',\n },\n ],\n [\n ['zh-TW', 'zh-Hant'],\n {\n install: '安裝',\n iOSInstall: '點擊分享按鈕然後點擊“添加到主畫面”',\n cancel: '取消',\n close: '關閉',\n prevImage: '上一張圖片',\n nextImage: '下一張圖片',\n desc: '詳情',\n feature: '主要特色',\n explain:\n '該應用可以安裝在你的 PC 或行動裝置上。這將使該 Web 應用程式外觀和行為與其他應用程式相同。它將在出現在應用程式列表中,並可以固定到主畫面,開始菜單或任務欄。此 Web 應用程式還將能夠與其他應用程式和你的操作系統安全地進行交互。',\n hint: '發現新內容可用',\n update: '新內容已就緒',\n },\n ],\n [\n ['de', 'de-DE'],\n {\n install: 'Installieren',\n iOSInstall: \"Drucke den Share-Button und dann 'zu Homescreen hinzufügen'\",\n cancel: 'Abbrechen',\n close: 'Schließen',\n prevImage: 'Vorheriges Bild',\n nextImage: 'Nächstes Bild',\n desc: 'Beschreibung',\n feature: 'Funktionen',\n explain:\n 'Diese App kann auf Ihrem PC oder Mobilgerät installiert werden. Dadurch sieht diese Web-App aus und verhält sich wie jede andere installierte App. Sie finden sie in Ihren App-Listen und können sie an den Startbildschirm, die Startmenüs oder die Taskleisten anheften. Diese installierte Web-App kann auch sicher mit anderen Apps und Ihrem Betriebssystem interagieren.',\n hint: 'Neuer Inhalt gefunden.',\n update: 'Neue Inhalte sind verfügbar.',\n },\n ],\n [\n ['vi', 'vi-VN'],\n {\n install: 'Tải về',\n iOSInstall: \"Nhấn vào nút chia sẻ và sau đó 'Thêm vào Màn hình chính'\",\n cancel: 'Huỷ bỏ',\n close: 'Đóng',\n prevImage: 'Hình ảnh trước đó',\n nextImage: 'Hình ảnh tiếp theo',\n desc: 'Sự miêu tả',\n feature: 'Các tính năng chính',\n explain:\n 'Ứng dụng này có thể được cài đặt trên PC hoặc thiết bị di động của bạn. Điều này sẽ cho phép ứng dụng web này trông và hoạt động giống như bất kỳ ứng dụng đã cài đặt nào khác. Bạn sẽ tìm thấy nó trong danh sách ứng dụng của mình và có thể ghim nó vào màn hình chính, menu bắt đầu hoặc thanh tác vụ. Ứng dụng web đã cài đặt này cũng sẽ có thể tương tác an toàn với các ứng dụng khác và hệ điều hành của bạn.',\n hint: 'Nội dung mới được tìm thấy',\n update: 'Đã có nội dung mới',\n },\n ],\n [\n ['uk'],\n {\n install: 'Встановити',\n iOSInstall:\n 'Торкніться кнопки «Поділитися», а потім «Додати на головний екран»',\n cancel: 'Скасувати',\n close: 'Закрити',\n prevImage: 'Попереднє зображення',\n nextImage: 'Наступне зображення',\n desc: 'Опис',\n feature: 'Основні характеристики',\n explain:\n 'Цю програму можна встановити на ПК або мобільний пристрій. Це дозволить цій веб-програмі виглядати та вести себе як будь-яка інша встановлена програма. Ви знайдете її у списках додатків і зможете закріпити на головному екрані, в меню «Пуск» або на панелі завдань. Ця встановлена веб-програма також зможе безпечно взаємодіяти з іншими програмами та вашою операційною системою. ',\n hint: 'Знайдено новий вміст',\n update: 'Доступний новий контент.',\n },\n ],\n [\n ['ru', 'ru-RU'],\n {\n install: 'Установить',\n iOSInstall:\n 'Нажмите кнопку «Поделиться», а затем «Добавить на главный экран»',\n cancel: 'Отменить',\n close: 'Закрыть',\n prevImage: 'Предыдущее изображение',\n nextImage: 'Следующее изображение',\n desc: 'Описание',\n feature: 'Основные функции',\n explain:\n 'Это приложение может быть установлено на вашем компьютере или мобильном устройстве. Это позволит веб-приложению выглядеть и вести себя как любое другое установленное приложение. Вы найдете его в списках приложений и сможете закрепить его на домашнем экране, в меню пуск или на панели задач. Установленное веб-приложение также сможет безопасно взаимодействовать с другими приложениями и операционной системой. ',\n hint: 'Найден новый контент',\n update: 'Доступен новый контент.',\n },\n ],\n [\n ['br'],\n {\n install: 'Instalar',\n iOSInstall: \"Toque no botão de compartilhar e depois 'Adicionar à Home'\",\n cancel: 'Cancelar',\n close: 'Fechar',\n prevImage: 'Imagem anterior',\n nextImage: 'Próxima imagem',\n desc: 'Descrição',\n feature: 'Características Chave',\n explain:\n 'Esta aplicação web pode ser instalada no seu PC ou dispositivo móvel. Isso fará com que ela se pareça e se comporte como qualquer outra aplicação. Você a encontrará na lista de apps e poderá adicionar seu ícone à tela de entrada, menus ou barras de tarefa. Uma vez instalada, esta aplicação web também poderá interagir com outras aplicações ou com o próprio sistema operacional. ',\n hint: 'Novo conteúdo encontrado',\n update: 'Novo conteúdo está disponível.',\n },\n ],\n [\n ['pl', 'pl-PL'],\n {\n install: 'Zainstaluj',\n iOSInstall:\n 'Stuknij przycisk udostępniania, a następnie „Dodaj do ekranu głównego”',\n cancel: 'Anuluj',\n close: 'Zamknij',\n prevImage: 'Poprzedni obrazek',\n nextImage: 'Następny obrazek',\n desc: 'Opis',\n feature: 'Kluczowe cechy',\n explain:\n 'Tę aplikację można zainstalować na komputerze lub urządzeniu mobilnym. Dzięki temu ta aplikacja internetowa będzie wyglądać i zachowywać się jak każda inna zainstalowana aplikacja. Znajdziesz ją na listach aplikacji i będziesz mógł przypiąć go do ekranu głównego, menu startowego lub pasków zadań. Ta zainstalowana aplikacja internetowa będzie również mogła bezpiecznie komunikować się z innymi aplikacjami i systemem operacyjnym.',\n hint: 'Znaleziono nową zawartość.',\n update: 'Nowa zawartość jest dostępna.',\n },\n ],\n [\n ['sk', 'sk-SK'],\n {\n install: 'Insštalácia',\n iOSInstall:\n \"Klikni na tlačidlo zdielania a potom 'Daj na domovskú obrazovku'\",\n cancel: 'Zrušiť',\n close: 'Zavrieť',\n prevImage: 'Prodošlí obrázok',\n nextImage: 'Ďalší obrázok',\n desc: 'Poznámka',\n feature: 'Kľúčové vlastnosti',\n explain:\n 'Túto aplikáciu je možné nainštalovať na počítač alebo mobil. Toto umožný sa správať aplikácii ako každej inej nainštalovanej aplikácii. Nájdeš ju vo svojom liste aplikácii a budeš môcť ju pripnúť na domovskú stránku, štartovacieho menu alebo do panelu úloh. Táto nainštalovaná webová aplikácia umžní tiež bezpečne komunikovať s ostatnými nainštalovanými aplikáciami a operačným systémom. ',\n hint: 'Nový obsah bol nájdený.',\n update: 'Nový obsah je dostupný.',\n },\n ],\n [\n ['fr', 'fr-FR'],\n {\n install: 'Installer',\n iOSInstall:\n \"Appuyez sur le bouton partager puis 'Ajouter à l'écran d'accueil'\",\n cancel: 'Annuler',\n close: 'Fermer',\n prevImage: 'Image précédente',\n nextImage: 'Image suivante',\n desc: 'Description',\n feature: 'Composants clés',\n explain:\n \"Cette app peut être installée sur PC ou smartphone. Cela permettra de rendre cette page web comme n'importe quelle autre application. Vous la trouverez dans votre liste d'application et serez capable de la pin sur votre écran principal et divers menus. L'application web installée sera capable d'interagir avec les autres applications et le système d'exploitation.\",\n hint: 'New content found.',\n update: 'New content is available.',\n },\n ],\n [\n ['es', 'es-ES'],\n {\n install: 'Instalar',\n iOSInstall:\n \"Toque el botón compartir y luego 'Agregar a la pantalla de inicio'\",\n cancel: 'Cancelar',\n close: 'Cerrar',\n prevImage: 'Imagen anterior',\n nextImage: 'Imagen siguiente',\n desc: 'Descripción',\n feature: 'Características clave',\n explain:\n 'Esta aplicación se puede instalar en su PC o dispositivo móvil. Esto permitirá que esta aplicación web se vea y se comporte como cualquier otra aplicación instalada. Lo encontrará en su lista de aplicaciones y podrá fijarlo a su pantalla de inicio, menús de inicio o barras de tareas. Esta aplicación web instalada también podrá interactuar de manera segura con otras aplicaciones y su sistema operativo.',\n hint: 'Nuevo contenido encontrado.',\n update: 'Hay nuevo contenido disponible.',\n },\n ],\n [\n ['ja', 'ja-JP'],\n {\n install: 'インストール',\n iOSInstall:\n '共有ボタンをタップし、「ホームスクリーンに追加」をタップします',\n cancel: 'キャンセル',\n close: '閉じる',\n prevImage: '前の画像',\n nextImage: '次の画像',\n desc: '詳細',\n feature: '主な特徴',\n explain:\n 'このアプリは、PCまたはモバイルデバイスにインストールすることができます。 これにより、このウェブアプリは、インストールされている他のアプリと同様に表示され、動作するようになります。 アプリ一覧で見つけることができ、ホーム画面、スタートメニュー、タスクバーに固定することができます。 このインストールされたウェブアプリケーションは、他のアプリケーションやオペレーティングシステムと安全にやり取りすることもできます。',\n hint: '新しいコンテンツが見つかりました。',\n update: '新しいコンテンツが登場しました。',\n },\n ],\n [\n ['tr', 'tr-TR'],\n {\n install: 'Yükle',\n iOSInstall:\n \"Paylaş düğmesine ve ardından 'Ana Ekrana Ekle' düğmesine basın\",\n cancel: 'İptal',\n close: 'Kapat',\n prevImage: 'Önceki Resim',\n nextImage: 'Sonraki Resim',\n desc: 'Tanım',\n feature: 'Ana Özellikler',\n explain:\n \"Bu uygulama PC'nize veya mobil cihazınıza yüklenebilir. Yüklenmesi bu web uygulamasının diğer yüklü uygulamalar gibi görünmesini ve davranmasını sağlar. Yüklenen web uygulamasını uygulama listenizde bulabilir ve ana ekranınıza, menülere veya görev çubuklarına sabitleyebilirsiniz. Aynı zamanda yüklenen web uygulaması, diğer uygulamalar ve işletim sisteminizle güvenli bir şekilde etkileşime girebilecektir.\",\n hint: 'Yeni içerik bulundu.',\n update: 'Yeni içerik mevcut.',\n },\n ],\n [\n ['ko', 'ko-KO'],\n {\n install: '설치',\n iOSInstall: \"공유 버튼을 누르고 '홈 화면에 추가'를 누르세요\",\n cancel: '취소',\n close: '닫기',\n prevImage: '이전 이미지',\n nextImage: '다음 이미지',\n desc: '설명',\n feature: '주요 기능',\n explain:\n '이 앱은 PC 또는 모바일 장치에 설치할 수 있습니다. 이렇게 하면 이 웹 앱은 다른 설치된 앱과 마찬가지로 표시되고 작동합니다. 앱 목록에서 찾을 수 있으며 홈 화면, 시작 메뉴, 작업 표시줄에 고정할 수 있습니다. 설치된 웹 앱은 다른 앱과 안전하게 상호 작용할 수 있습니다.',\n hint: '새로운 콘텐츠를 찾았습니다.',\n update: '새로운 콘텐츠가 있습니다.',\n },\n ],\n [\n ['fi', 'fi-FI'],\n {\n install: 'Asenna',\n iOSInstall: \"Paina Jaa-painiketta ja sitten 'Lisää kotiin'-painiketta\",\n cancel: 'Peruuta',\n close: 'Sulje',\n prevImage: 'Edellinen kuva',\n nextImage: 'Seuraava kuva',\n desc: 'Kuvaus',\n feature: 'Avainominaisuudet',\n explain:\n 'Tämä sovellus on asennettavissa tietokoneelle tai mobiililaitteelle. Tämä mahdollistaa sovelluksen toiminnan tietokoneohjelmana. Löydät sen sovelluslistasta ja voit kiinnittää sen työpöydälle, kotinäytölle, tehtäväpalkkiin tai muulle listalle. Asennettu sovellus voi turvallisesti olla vuorovaikutuksessa muiden sovellusten ja käyttöjärjestelmäsi kanssa.',\n hint: 'Uutta sisältöä.',\n update: 'Uutta sisältöä on saatavilla.',\n },\n ],\n [\n ['hu', 'hu-HU'],\n {\n install: 'Telepítés',\n iOSInstall:\n \"Nyomd meg a megosztás gombot, majd a 'Hozzáadás a kezdőképernyőhöz' opciót\",\n cancel: 'Mégse',\n close: 'Bezárás',\n prevImage: 'Előző kép',\n nextImage: 'Következő kép',\n desc: 'Leírás',\n feature: 'Főbb jellemzők',\n explain:\n 'Ez az alkalmazás telepíthető PC-re vagy mobil eszközre. Ez lehetővé teszi, hogy ez a webalkalmazás úgy nézzen ki és viselkedjen, mint bármely más telepített alkalmazás. Az alkalmazáslistában találod majd, és hozzáadhatod a kezdőképernyőhöz, indító menühöz vagy a feladatok sávjához. Az telepített webalkalmazás biztonságosan interakcióba léphet más alkalmazásokkal és az operációs rendszerrel.',\n hint: 'Új tartalom érhető el.',\n update: 'Új tartalom érhető el.',\n },\n ],\n [\n ['id', 'id-ID'],\n {\n install: 'Install',\n iOSInstall: \"Ketuk tombol bagikan, lalu 'Tambahkan ke Layar Utama'\",\n cancel: 'Batal',\n close: 'Tutup',\n prevImage: 'Gambar sebelumnya',\n nextImage: 'Gambar selanjutnya',\n desc: 'Keterangan',\n feature: 'Fitur',\n explain:\n 'Aplikasi ini dapat diinstal di PC atau perangkat seluler Anda. Ini akan memungkinkan aplikasi web ini terlihat seperti aplikasi terpasang lainnya. Anda bisa menemukannya di daftar aplikasi dan dapat menyematkannya ke layar beranda, menu start, atau menu ke taskbar. Aplikasi web yang terinstal ini juga dapat berinteraksi dengan aplikasi lain dan dengan sistem operasi yang Anda gunakan. ',\n hint: 'Konten baru ditemukan.',\n update: 'Konten baru telah tersedia.',\n },\n ],\n [\n ['nl', 'nl-NL'],\n {\n install: 'Installeren',\n iOSInstall: \"Druk op de share button en dan op 'Add to Home Screen'\",\n cancel: 'Annuleren',\n close: 'Sluiten',\n prevImage: 'Vorige Foto',\n nextImage: 'Volgende Foto',\n desc: 'Beschrijving',\n feature: 'Belangrijkste mogelijkheden',\n explain:\n 'Deze app kan op uw PC of mobiel toestel geïnstalleerd worden. Dit laat toe om deze webapp er uit te laten alsof het een normale app is. Je kan het terugvinden in jouw applijsten en kan het op je homescreen, start menu of taakbalk vastzetten. Deze geïnstalleerde webapp zal ook veilig samenwerken met andere apps en uw besturingssysteem. ',\n hint: 'Nieuwe inhoud gevonden.',\n update: 'Nieuwe inhoud is beschikbaar.',\n },\n ],\n]\n","import type { App } from 'vuepress/core'\nimport { fs } from 'vuepress/utils'\n\nimport type { AppManifest } from '../shared/index.js'\nimport type { PwaPluginOptions } from './options.js'\n\nexport const getManifest = async (\n app: App,\n options: PwaPluginOptions,\n): Promise<AppManifest> => {\n const { base, title, description, lang, locales } = app.siteData\n\n const rootLocale = locales['/'] ?? {}\n\n const userManifestPath = app.dir.source(\n '.vuepress/public/manifest.webmanifest',\n )\n const userManifestJSONPath = app.dir.source('.vuepress/public/manifest.json')\n\n const manifestFileContent = JSON.parse(\n fs.existsSync(userManifestPath)\n ? await fs.readFile(userManifestPath, 'utf-8')\n : fs.existsSync(userManifestJSONPath)\n ? await fs.readFile(userManifestJSONPath, 'utf-8')\n : '{}',\n ) as AppManifest\n\n const manifest: AppManifest = {\n name: title || rootLocale.title || 'Site',\n short_name: title || rootLocale.title || 'Site',\n description:\n description || rootLocale.description || 'A site built with vuepress',\n lang: rootLocale.lang ?? lang,\n start_url: base,\n scope: base,\n\n display: 'standalone',\n theme_color: options.themeColor || '#46bd87',\n background_color: '#ffffff',\n orientation: 'portrait-primary',\n prefer_related_applications: false,\n\n ...manifestFileContent,\n ...options.manifest,\n }\n\n return manifest\n}\n","import { Logger } from '@vuepress/helper'\n\nexport const PLUGIN_NAME = '@vuepress/plugin-pwa'\n\nexport const logger = new Logger(PLUGIN_NAME)\n","import type { App } from 'vuepress/core'\nimport { colors, fs, path } from 'vuepress/utils'\n\nimport { getManifest } from './getManifest.js'\nimport { logger } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\n\nexport const generateManifest = async (\n app: App,\n options: PwaPluginOptions,\n): Promise<void> => {\n const { succeed } = logger.load('Generating manifest.webmanifest')\n\n const manifest = await getManifest(app, options)\n const manifestPath = app.dir.dest('manifest.webmanifest')\n\n await fs.writeJSON(manifestPath, manifest, {\n flag: 'w',\n })\n\n succeed(\n `Manifest generated and saved to ${colors.cyan(\n path.relative(process.cwd(), manifestPath),\n )}!`,\n )\n}\n","import { endsWith } from '@vuepress/helper'\nimport type { App } from 'vuepress/core'\nimport { colors } from 'vuepress/utils'\nimport type {\n ManifestEntry,\n ManifestTransform,\n ManifestTransformResult,\n} from 'workbox-build'\nimport { generateSW } from 'workbox-build'\n\nimport { logger } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\n\nconst imageExtensions = ['png', 'jpg', 'jpeg', 'webp', 'bmp', 'gif']\nconst cacheExtensions = [\n 'js',\n 'css',\n 'svg',\n 'woff',\n 'woff2',\n 'eot',\n 'ttf',\n 'otf',\n]\n\nconst imageFilter =\n (maxSize = 1024): ManifestTransform =>\n (\n manifestEntries: (ManifestEntry & { size: number })[],\n ): ManifestTransformResult => {\n const warnings: string[] = []\n const manifest: (ManifestEntry & { size: number })[] = []\n\n for (const entry of manifestEntries) {\n const { url, size } = entry\n\n if (imageExtensions.some((ext) => endsWith(url, `.${ext}`))) {\n if (size > maxSize * 1024)\n warnings.push(`Skipped ${url}, as it's ${Math.ceil(size / 1024)} KB.`)\n else manifest.push(entry)\n } else {\n manifest.push(entry)\n }\n }\n\n return { warnings, manifest }\n }\n\nexport const generateServiceWorker = async (\n app: App,\n options: PwaPluginOptions,\n): Promise<void> => {\n const { succeed } = logger.load('Generating service worker')\n\n const globPatterns = [`**/*.{${cacheExtensions.join(',')}}`]\n\n if (options.cacheHTML) globPatterns.push('**/*.html')\n else globPatterns.push('./index.html', './404.html')\n\n if (options.cacheImage)\n globPatterns.push(`**/*.{${imageExtensions.join(',')}}`)\n\n await generateSW({\n dontCacheBustURLsMatching: new RegExp(\n `\\\\.[0-9a-f]{8}\\\\.(${['html', ...cacheExtensions, ...imageExtensions].join('|')})$`,\n ),\n globPatterns,\n cleanupOutdatedCaches: true,\n clientsClaim: true,\n maximumFileSizeToCacheInBytes: (options.maxSize ?? 2048) * 1024,\n manifestTransforms: [imageFilter(options.maxImageSize)],\n mode: app.env.isDebug ? 'development' : 'production',\n sourcemap: app.env.isDebug,\n ...options.generateSWConfig,\n // should not be override by user config\n globDirectory: app.dir.dest(),\n swDest: app.dir.dest(options.serviceWorkerFilename ?? 'service-worker.js'),\n }).then(({ count, size, warnings }) => {\n succeed()\n\n logger.info(\n `Precache ${colors.cyan(`${count} files`)}, totaling ${colors.cyan(\n `${(size / 1024 / 1024).toFixed(2)} Mb.`,\n )}.`,\n )\n\n if (warnings.length > 0)\n logger.warn(`\\n${warnings.map((warning) => ` · ${warning}`).join('\\n')}`)\n\n if (size > 104857600) {\n logger.error(\n `Cache Size is larger than 100MB, so that it can not be registered on all browsers.\\n${colors.blue(\n 'Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\\n',\n )}`,\n )\n } else if (size > 52428800) {\n logger.warn(\n `\\nCache Size is larger than 50MB, which will not be registered on Safari.\\n${colors.blue(\n 'Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\\n',\n )}`,\n )\n }\n })\n}\n","import { isLinkAbsolute } from '@vuepress/helper'\n\nimport type { AppManifest } from '../shared/index.js'\nimport type { PwaPluginOptions } from './options.js'\n\nconst appendBaseToLink = (base: string, link: string): string =>\n isLinkAbsolute(link) ? link.replace(/^\\//, base) : link\n\nexport const appendBaseToManifest = (\n base: string,\n manifest: AppManifest,\n): AppManifest => {\n if (manifest.icons) {\n manifest.icons = manifest.icons.map((icon) => ({\n ...icon,\n src: appendBaseToLink(base, icon.src),\n }))\n }\n\n if (manifest.shortcuts) {\n manifest.shortcuts = manifest.shortcuts.map((shortcut) => ({\n ...shortcut,\n icons:\n shortcut.icons?.map((icon) => ({\n ...icon,\n src: appendBaseToLink(base, icon.src),\n })) ?? [],\n url: appendBaseToLink(base, shortcut.url),\n }))\n }\n\n if (manifest.screenshots) {\n manifest.screenshots = manifest.screenshots.map((screenshot) => ({\n ...screenshot,\n src: appendBaseToLink(base, screenshot.src),\n }))\n }\n\n return manifest\n}\n\nexport const appendBase = (base: string, options: PwaPluginOptions): void => {\n if (options.favicon) options.favicon = appendBaseToLink(base, options.favicon)\n\n if (options.apple) {\n if (options.apple.icon)\n options.apple.icon = appendBaseToLink(base, options.apple.icon)\n\n if (options.apple.maskIcon)\n options.apple.maskIcon = appendBaseToLink(base, options.apple.maskIcon)\n }\n\n if (options.manifest)\n options.manifest = appendBaseToManifest(base, options.manifest)\n}\n","import type { App } from 'vuepress/core'\nimport { isPlainObject } from 'vuepress/shared'\n\nimport type { PwaPluginOptions } from './options.js'\n\n// oxlint-disable-next-line complexity\nexport const injectLinksToHead = (\n app: App,\n { favicon, manifest, themeColor = '#46bd87', apple }: PwaPluginOptions,\n): void => {\n const { base, head } = app.siteData\n const metaKeys: string[] = []\n const linkKeys: string[] = []\n\n // Generate Hash for Head\n head.forEach((item) => {\n if (item[0] === 'meta') metaKeys.push(item[1].name as string)\n else if (item[0] === 'link') linkKeys.push(item[1].rel as string)\n })\n\n const appTitle = manifest?.name ?? app.siteData.title\n let fallBackIcon = ''\n\n const setLink = (\n rel: string,\n href: string,\n more: Record<string, string> = {},\n ): void => {\n if (!linkKeys.includes(rel)) head.push(['link', { rel, href, ...more }])\n }\n\n const setMeta = (\n name: string,\n content: string,\n more: Record<string, string> = {},\n ): void => {\n if (!metaKeys.includes(name))\n head.push(['meta', { name, content, ...more }])\n }\n\n if (appTitle) setMeta('application-name', appTitle)\n\n setMeta('mobile-web-app-capable', 'yes')\n setMeta('theme-color', themeColor || '#46bd87')\n\n // oxlint-disable-next-line typescript/no-deprecated\n if (isPlainObject(apple) && apple.statusBarColor)\n // oxlint-disable-next-line typescript/no-deprecated\n setMeta('apple-mobile-web-app-status-bar-style', apple.statusBarColor)\n\n if (favicon) setLink('icon', favicon)\n\n setLink('manifest', `${base}manifest.webmanifest`, {\n crossorigin: 'use-credentials',\n })\n\n if (manifest?.icons) {\n const { icons } = manifest\n\n if (icons.length > 0) {\n fallBackIcon = icons[0].src\n\n manifest.icons.forEach((icon) => {\n if (icon.type)\n setLink('icon', icon.src, { type: icon.type, sizes: icon.sizes })\n else setLink('icon', icon.src, { sizes: icon.sizes })\n })\n }\n }\n\n if (isPlainObject(apple) && (apple.icon || fallBackIcon)) {\n setLink('apple-touch-icon', apple.icon || fallBackIcon)\n if (apple.maskIcon) {\n setLink('mask-icon', apple.maskIcon, {\n color: themeColor || '#46bd87',\n })\n }\n } else if ((apple ?? true) && fallBackIcon) {\n setLink('apple-touch-icon', fallBackIcon)\n }\n}\n","import { getFullLocaleConfig, getModulePath } from '@vuepress/helper'\nimport type { App } from 'vuepress/core'\nimport { getDirname, path } from 'vuepress/utils'\n\nimport { pwaLocaleInfo } from './locales.js'\nimport { PLUGIN_NAME } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\n\nconst __dirname = import.meta.dirname || getDirname(import.meta.url)\n\nexport const prepareClientConfigFile = (\n app: App,\n options: PwaPluginOptions,\n): Promise<string> => {\n let configImport = ''\n const rootComponents: string[] = []\n\n if (options.showInstall) {\n configImport += `\\\nimport { PwaInstall as _PwaInstall } from \"${path.join(__dirname, '../client/components/PwaInstall.js')}\";\n`\n\n rootComponents.push('PwaInstall')\n }\n\n if (options.update === 'hint') {\n configImport += options.foundComponent\n ? `import _PwaFoundPopup from \"${options.foundComponent}\";\n`\n : `\\\nimport { PwaFoundPopup as _PwaFoundPopup } from \"${path.join(\n __dirname,\n '../client/components/PwaFoundPopup.js',\n )}\";\n`\n\n rootComponents.push('PwaFoundPopup')\n } else if (options.update !== 'disable' && options.update !== 'force') {\n configImport += options.readyComponent\n ? `import _PwaReadyPopup from \"${options.readyComponent}\";\n`\n : `\\\nimport { PwaReadyPopup as _PwaReadyPopup } from \"${path.join(\n __dirname,\n '../client/components/PwaReadyPopup.js',\n )}\";\n`\n\n rootComponents.push('PwaReadyPopup')\n }\n\n return app.writeTemp(\n `pwa/config.js`,\n `\\\nimport { h } from \"vue\";\nimport { defineClientConfig } from \"vuepress/client\";\nimport { setupPwa, setupViewPoint } from \"${path.join(__dirname, '../client/composables/index.js')}\";\n${configImport}\nimport \"${getModulePath('@vuepress/plugin-pwa/styles/vars.css', import.meta)}\";\n\nconst locales = ${JSON.stringify(\n getFullLocaleConfig({\n app,\n name: PLUGIN_NAME,\n default: pwaLocaleInfo,\n config: options.locales,\n }),\n )};\n\nexport default defineClientConfig({\n setup: () => {\n setupPwa(${JSON.stringify(options.serviceWorkerFilename ?? 'service-worker.js')}, ${options.update === 'force'});\n setupViewPoint();\n },\n rootComponents: [\n${rootComponents.map((item) => ` () => h(_${item}, { locales }),`).join('\\n')}\n ],\n});\n`,\n )\n}\n","import {\n addViteOptimizeDepsExclude,\n addViteSsrNoExternal,\n customizeDevServer,\n} from '@vuepress/helper'\nimport type { PluginFunction } from 'vuepress/core'\n\nimport { generateManifest } from './generateManifest.js'\nimport { generateServiceWorker } from './generateServiceWorker.js'\nimport { getManifest } from './getManifest.js'\nimport { appendBase } from './helper.js'\nimport { injectLinksToHead } from './injectLinksToHead.js'\nimport { PLUGIN_NAME, logger } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\nimport { prepareClientConfigFile } from './prepareClientConfigFile.js'\n\n/**\n * PWA plugin\n *\n * PWA 插件\n *\n * @param options - Plugin options / 插件选项\n * @returns VuePress plugin / VuePress 插件\n *\n * @example\n * ```ts\n * import { pwaPlugin } from '@vuepress/plugin-pwa'\n *\n * export default {\n * plugins: [\n * pwaPlugin({\n * showInstall: true,\n * manifest: {\n * name: 'My PWA App'\n * },\n * update: 'hint'\n * })\n * ]\n * }\n * ```\n */\nexport const pwaPlugin =\n (options: PwaPluginOptions = {}): PluginFunction =>\n (app) => {\n if (app.env.isDebug) logger.info('Options:', options)\n\n const { shouldPrefetch = true } = app.options\n const { base } = app.siteData\n\n if (options.appendBase) appendBase(base, options)\n\n if (shouldPrefetch === true) {\n logger.warn(\n 'The plugin will register service worker to handle assets, so we recommend you to set \"shouldPrefetch: false\" in VuePress config file.',\n )\n }\n\n injectLinksToHead(app, options)\n\n return {\n name: PLUGIN_NAME,\n\n extendsBundlerOptions: (bundlerOptions: unknown) => {\n addViteOptimizeDepsExclude(bundlerOptions, app, [\n 'mitt',\n 'register-service-worker',\n ])\n addViteSsrNoExternal(bundlerOptions, app, '@vuepress/helper')\n\n customizeDevServer(bundlerOptions, app, {\n path: '/manifest.webmanifest',\n response: async (_, response) => {\n response.setHeader('Content-Type', 'application/manifest+json')\n\n return JSON.stringify(await getManifest(app, options))\n },\n errMsg: 'Unexpected manifest generation error',\n })\n },\n\n onGenerated: async () => {\n await generateManifest(app, options)\n await generateServiceWorker(app, options)\n },\n\n clientConfigFile: () => prepareClientConfigFile(app, options),\n }\n }\n"],"mappings":"+WAOA,MAAa,EAAwD,CACnE,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,UACT,WAAY,qDACZ,OAAQ,SACR,MAAO,QACP,UAAW,iBACX,UAAW,aACX,KAAM,cACN,QAAS,eACT,QACE,0VACF,KAAM,qBACN,OAAQ,4BACT,CACF,CACD,CACE,CAAC,KAAM,QAAS,UAAU,CAC1B,CACE,QAAS,KACT,WAAY,qBACZ,OAAQ,KACR,MAAO,KACP,UAAW,QACX,UAAW,QACX,KAAM,KACN,QAAS,OACT,QACE,yHACF,KAAM,UACN,OAAQ,SACT,CACF,CACD,CACE,CAAC,QAAS,UAAU,CACpB,CACE,QAAS,KACT,WAAY,qBACZ,OAAQ,KACR,MAAO,KACP,UAAW,QACX,UAAW,QACX,KAAM,KACN,QAAS,OACT,QACE,yHACF,KAAM,UACN,OAAQ,SACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,eACT,WAAY,8DACZ,OAAQ,YACR,MAAO,YACP,UAAW,kBACX,UAAW,gBACX,KAAM,eACN,QAAS,aACT,QACE,iXACF,KAAM,yBACN,OAAQ,+BACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,SACT,WAAY,2DACZ,OAAQ,SACR,MAAO,OACP,UAAW,oBACX,UAAW,qBACX,KAAM,aACN,QAAS,sBACT,QACE,yZACF,KAAM,6BACN,OAAQ,qBACT,CACF,CACD,CACE,CAAC,KAAK,CACN,CACE,QAAS,aACT,WACE,qEACF,OAAQ,YACR,MAAO,UACP,UAAW,uBACX,UAAW,sBACX,KAAM,OACN,QAAS,yBACT,QACE,2XACF,KAAM,uBACN,OAAQ,2BACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,aACT,WACE,mEACF,OAAQ,WACR,MAAO,UACP,UAAW,yBACX,UAAW,wBACX,KAAM,WACN,QAAS,mBACT,QACE,+ZACF,KAAM,uBACN,OAAQ,0BACT,CACF,CACD,CACE,CAAC,KAAK,CACN,CACE,QAAS,WACT,WAAY,6DACZ,OAAQ,WACR,MAAO,SACP,UAAW,kBACX,UAAW,iBACX,KAAM,YACN,QAAS,wBACT,QACE,gYACF,KAAM,2BACN,OAAQ,iCACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,aACT,WACE,yEACF,OAAQ,SACR,MAAO,UACP,UAAW,oBACX,UAAW,mBACX,KAAM,OACN,QAAS,iBACT,QACE,ibACF,KAAM,6BACN,OAAQ,gCACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,cACT,WACE,mEACF,OAAQ,SACR,MAAO,UACP,UAAW,mBACX,UAAW,gBACX,KAAM,WACN,QAAS,qBACT,QACE,0YACF,KAAM,0BACN,OAAQ,0BACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,YACT,WACE,oEACF,OAAQ,UACR,MAAO,SACP,UAAW,mBACX,UAAW,iBACX,KAAM,cACN,QAAS,kBACT,QACE,kXACF,KAAM,qBACN,OAAQ,4BACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,WACT,WACE,qEACF,OAAQ,WACR,MAAO,SACP,UAAW,kBACX,UAAW,mBACX,KAAM,cACN,QAAS,wBACT,QACE,uZACF,KAAM,8BACN,OAAQ,kCACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,SACT,WACE,kCACF,OAAQ,QACR,MAAO,MACP,UAAW,OACX,UAAW,OACX,KAAM,KACN,QAAS,OACT,QACE,kNACF,KAAM,oBACN,OAAQ,mBACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,QACT,WACE,iEACF,OAAQ,QACR,MAAO,QACP,UAAW,eACX,UAAW,gBACX,KAAM,QACN,QAAS,iBACT,QACE,0ZACF,KAAM,uBACN,OAAQ,sBACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,KACT,WAAY,8BACZ,OAAQ,KACR,MAAO,KACP,UAAW,SACX,UAAW,SACX,KAAM,KACN,QAAS,QACT,QACE,+JACF,KAAM,kBACN,OAAQ,iBACT,CACF,CACD,CACE,CAAC,KAAM,QAAQ,CACf,CACE,QAAS,SACT,WAAY,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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/node/locales.ts","../../src/node/getManifest.ts","../../src/node/logger.ts","../../src/node/generateManifest.ts","../../src/node/generateServiceWorker.ts","../../src/node/helper.ts","../../src/node/injectLinksToHead.ts","../../src/node/prepareClientConfigFile.ts","../../src/node/pwaPlugin.ts"],"sourcesContent":["import type { DefaultLocaleInfo } from '@vuepress/helper'\n\nimport type { PwaPluginLocaleData } from '../shared/index.js'\n\n/** Default locale info for `@vuepress/plugin-pwa` */\nexport const pwaLocaleInfo: DefaultLocaleInfo<PwaPluginLocaleData> = [\n [\n ['en', 'en-US'],\n {\n install: 'Install',\n iOSInstall: \"Tap the share button and then 'Add to Home Screen'\",\n cancel: 'Cancel',\n close: 'Close',\n prevImage: 'Previous Image',\n nextImage: 'Next Image',\n desc: 'Description',\n feature: 'Key Features',\n explain:\n 'This app can be installed on your PC or mobile device. This will allow this web app to look and behave like any other installed app. You will find it in your app lists and be able to pin it to your home screen, start menus or task bars. This installed web app will also be able to safely interact with other apps and your operating system. ',\n hint: 'New content found.',\n update: 'New content is available.',\n },\n ],\n [\n ['zh', 'zh-CN', 'zh-Hans'],\n {\n install: '安装',\n iOSInstall: '点击分享按钮然后点击“添加到主屏幕”',\n cancel: '取消',\n close: '关闭',\n prevImage: '上一张图片',\n nextImage: '下一张图片',\n desc: '详情',\n feature: '主要特色',\n explain:\n '该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。',\n hint: '发现新内容可用',\n update: '新内容已就绪',\n },\n ],\n [\n ['zh-TW', 'zh-Hant'],\n {\n install: '安裝',\n iOSInstall: '點擊分享按鈕然後點擊“添加到主畫面”',\n cancel: '取消',\n close: '關閉',\n prevImage: '上一張圖片',\n nextImage: '下一張圖片',\n desc: '詳情',\n feature: '主要特色',\n explain:\n '該應用可以安裝在你的 PC 或行動裝置上。這將使該 Web 應用程式外觀和行為與其他應用程式相同。它將在出現在應用程式列表中,並可以固定到主畫面,開始菜單或任務欄。此 Web 應用程式還將能夠與其他應用程式和你的操作系統安全地進行交互。',\n hint: '發現新內容可用',\n update: '新內容已就緒',\n },\n ],\n [\n ['de', 'de-DE'],\n {\n install: 'Installieren',\n iOSInstall: \"Drucke den Share-Button und dann 'zu Homescreen hinzufügen'\",\n cancel: 'Abbrechen',\n close: 'Schließen',\n prevImage: 'Vorheriges Bild',\n nextImage: 'Nächstes Bild',\n desc: 'Beschreibung',\n feature: 'Funktionen',\n explain:\n 'Diese App kann auf Ihrem PC oder Mobilgerät installiert werden. Dadurch sieht diese Web-App aus und verhält sich wie jede andere installierte App. Sie finden sie in Ihren App-Listen und können sie an den Startbildschirm, die Startmenüs oder die Taskleisten anheften. Diese installierte Web-App kann auch sicher mit anderen Apps und Ihrem Betriebssystem interagieren.',\n hint: 'Neuer Inhalt gefunden.',\n update: 'Neue Inhalte sind verfügbar.',\n },\n ],\n [\n ['vi', 'vi-VN'],\n {\n install: 'Tải về',\n iOSInstall: \"Nhấn vào nút chia sẻ và sau đó 'Thêm vào Màn hình chính'\",\n cancel: 'Huỷ bỏ',\n close: 'Đóng',\n prevImage: 'Hình ảnh trước đó',\n nextImage: 'Hình ảnh tiếp theo',\n desc: 'Sự miêu tả',\n feature: 'Các tính năng chính',\n explain:\n 'Ứng dụng này có thể được cài đặt trên PC hoặc thiết bị di động của bạn. Điều này sẽ cho phép ứng dụng web này trông và hoạt động giống như bất kỳ ứng dụng đã cài đặt nào khác. Bạn sẽ tìm thấy nó trong danh sách ứng dụng của mình và có thể ghim nó vào màn hình chính, menu bắt đầu hoặc thanh tác vụ. Ứng dụng web đã cài đặt này cũng sẽ có thể tương tác an toàn với các ứng dụng khác và hệ điều hành của bạn.',\n hint: 'Nội dung mới được tìm thấy',\n update: 'Đã có nội dung mới',\n },\n ],\n [\n ['uk'],\n {\n install: 'Встановити',\n iOSInstall:\n 'Торкніться кнопки «Поділитися», а потім «Додати на головний екран»',\n cancel: 'Скасувати',\n close: 'Закрити',\n prevImage: 'Попереднє зображення',\n nextImage: 'Наступне зображення',\n desc: 'Опис',\n feature: 'Основні характеристики',\n explain:\n 'Цю програму можна встановити на ПК або мобільний пристрій. Це дозволить цій веб-програмі виглядати та вести себе як будь-яка інша встановлена програма. Ви знайдете її у списках додатків і зможете закріпити на головному екрані, в меню «Пуск» або на панелі завдань. Ця встановлена веб-програма також зможе безпечно взаємодіяти з іншими програмами та вашою операційною системою. ',\n hint: 'Знайдено новий вміст',\n update: 'Доступний новий контент.',\n },\n ],\n [\n ['ru', 'ru-RU'],\n {\n install: 'Установить',\n iOSInstall:\n 'Нажмите кнопку «Поделиться», а затем «Добавить на главный экран»',\n cancel: 'Отменить',\n close: 'Закрыть',\n prevImage: 'Предыдущее изображение',\n nextImage: 'Следующее изображение',\n desc: 'Описание',\n feature: 'Основные функции',\n explain:\n 'Это приложение может быть установлено на вашем компьютере или мобильном устройстве. Это позволит веб-приложению выглядеть и вести себя как любое другое установленное приложение. Вы найдете его в списках приложений и сможете закрепить его на домашнем экране, в меню пуск или на панели задач. Установленное веб-приложение также сможет безопасно взаимодействовать с другими приложениями и операционной системой. ',\n hint: 'Найден новый контент',\n update: 'Доступен новый контент.',\n },\n ],\n [\n ['br'],\n {\n install: 'Instalar',\n iOSInstall: \"Toque no botão de compartilhar e depois 'Adicionar à Home'\",\n cancel: 'Cancelar',\n close: 'Fechar',\n prevImage: 'Imagem anterior',\n nextImage: 'Próxima imagem',\n desc: 'Descrição',\n feature: 'Características Chave',\n explain:\n 'Esta aplicação web pode ser instalada no seu PC ou dispositivo móvel. Isso fará com que ela se pareça e se comporte como qualquer outra aplicação. Você a encontrará na lista de apps e poderá adicionar seu ícone à tela de entrada, menus ou barras de tarefa. Uma vez instalada, esta aplicação web também poderá interagir com outras aplicações ou com o próprio sistema operacional. ',\n hint: 'Novo conteúdo encontrado',\n update: 'Novo conteúdo está disponível.',\n },\n ],\n [\n ['pl', 'pl-PL'],\n {\n install: 'Zainstaluj',\n iOSInstall:\n 'Stuknij przycisk udostępniania, a następnie „Dodaj do ekranu głównego”',\n cancel: 'Anuluj',\n close: 'Zamknij',\n prevImage: 'Poprzedni obrazek',\n nextImage: 'Następny obrazek',\n desc: 'Opis',\n feature: 'Kluczowe cechy',\n explain:\n 'Tę aplikację można zainstalować na komputerze lub urządzeniu mobilnym. Dzięki temu ta aplikacja internetowa będzie wyglądać i zachowywać się jak każda inna zainstalowana aplikacja. Znajdziesz ją na listach aplikacji i będziesz mógł przypiąć go do ekranu głównego, menu startowego lub pasków zadań. Ta zainstalowana aplikacja internetowa będzie również mogła bezpiecznie komunikować się z innymi aplikacjami i systemem operacyjnym.',\n hint: 'Znaleziono nową zawartość.',\n update: 'Nowa zawartość jest dostępna.',\n },\n ],\n [\n ['sk', 'sk-SK'],\n {\n install: 'Insštalácia',\n iOSInstall:\n \"Klikni na tlačidlo zdielania a potom 'Daj na domovskú obrazovku'\",\n cancel: 'Zrušiť',\n close: 'Zavrieť',\n prevImage: 'Prodošlí obrázok',\n nextImage: 'Ďalší obrázok',\n desc: 'Poznámka',\n feature: 'Kľúčové vlastnosti',\n explain:\n 'Túto aplikáciu je možné nainštalovať na počítač alebo mobil. Toto umožný sa správať aplikácii ako každej inej nainštalovanej aplikácii. Nájdeš ju vo svojom liste aplikácii a budeš môcť ju pripnúť na domovskú stránku, štartovacieho menu alebo do panelu úloh. Táto nainštalovaná webová aplikácia umžní tiež bezpečne komunikovať s ostatnými nainštalovanými aplikáciami a operačným systémom. ',\n hint: 'Nový obsah bol nájdený.',\n update: 'Nový obsah je dostupný.',\n },\n ],\n [\n ['fr', 'fr-FR'],\n {\n install: 'Installer',\n iOSInstall:\n \"Appuyez sur le bouton partager puis 'Ajouter à l'écran d'accueil'\",\n cancel: 'Annuler',\n close: 'Fermer',\n prevImage: 'Image précédente',\n nextImage: 'Image suivante',\n desc: 'Description',\n feature: 'Composants clés',\n explain:\n \"Cette app peut être installée sur PC ou smartphone. Cela permettra de rendre cette page web comme n'importe quelle autre application. Vous la trouverez dans votre liste d'application et serez capable de la pin sur votre écran principal et divers menus. L'application web installée sera capable d'interagir avec les autres applications et le système d'exploitation.\",\n hint: 'New content found.',\n update: 'New content is available.',\n },\n ],\n [\n ['es', 'es-ES'],\n {\n install: 'Instalar',\n iOSInstall:\n \"Toque el botón compartir y luego 'Agregar a la pantalla de inicio'\",\n cancel: 'Cancelar',\n close: 'Cerrar',\n prevImage: 'Imagen anterior',\n nextImage: 'Imagen siguiente',\n desc: 'Descripción',\n feature: 'Características clave',\n explain:\n 'Esta aplicación se puede instalar en su PC o dispositivo móvil. Esto permitirá que esta aplicación web se vea y se comporte como cualquier otra aplicación instalada. Lo encontrará en su lista de aplicaciones y podrá fijarlo a su pantalla de inicio, menús de inicio o barras de tareas. Esta aplicación web instalada también podrá interactuar de manera segura con otras aplicaciones y su sistema operativo.',\n hint: 'Nuevo contenido encontrado.',\n update: 'Hay nuevo contenido disponible.',\n },\n ],\n [\n ['ja', 'ja-JP'],\n {\n install: 'インストール',\n iOSInstall:\n '共有ボタンをタップし、「ホームスクリーンに追加」をタップします',\n cancel: 'キャンセル',\n close: '閉じる',\n prevImage: '前の画像',\n nextImage: '次の画像',\n desc: '詳細',\n feature: '主な特徴',\n explain:\n 'このアプリは、PCまたはモバイルデバイスにインストールすることができます。 これにより、このウェブアプリは、インストールされている他のアプリと同様に表示され、動作するようになります。 アプリ一覧で見つけることができ、ホーム画面、スタートメニュー、タスクバーに固定することができます。 このインストールされたウェブアプリケーションは、他のアプリケーションやオペレーティングシステムと安全にやり取りすることもできます。',\n hint: '新しいコンテンツが見つかりました。',\n update: '新しいコンテンツが登場しました。',\n },\n ],\n [\n ['tr', 'tr-TR'],\n {\n install: 'Yükle',\n iOSInstall:\n \"Paylaş düğmesine ve ardından 'Ana Ekrana Ekle' düğmesine basın\",\n cancel: 'İptal',\n close: 'Kapat',\n prevImage: 'Önceki Resim',\n nextImage: 'Sonraki Resim',\n desc: 'Tanım',\n feature: 'Ana Özellikler',\n explain:\n \"Bu uygulama PC'nize veya mobil cihazınıza yüklenebilir. Yüklenmesi bu web uygulamasının diğer yüklü uygulamalar gibi görünmesini ve davranmasını sağlar. Yüklenen web uygulamasını uygulama listenizde bulabilir ve ana ekranınıza, menülere veya görev çubuklarına sabitleyebilirsiniz. Aynı zamanda yüklenen web uygulaması, diğer uygulamalar ve işletim sisteminizle güvenli bir şekilde etkileşime girebilecektir.\",\n hint: 'Yeni içerik bulundu.',\n update: 'Yeni içerik mevcut.',\n },\n ],\n [\n ['ko', 'ko-KO'],\n {\n install: '설치',\n iOSInstall: \"공유 버튼을 누르고 '홈 화면에 추가'를 누르세요\",\n cancel: '취소',\n close: '닫기',\n prevImage: '이전 이미지',\n nextImage: '다음 이미지',\n desc: '설명',\n feature: '주요 기능',\n explain:\n '이 앱은 PC 또는 모바일 장치에 설치할 수 있습니다. 이렇게 하면 이 웹 앱은 다른 설치된 앱과 마찬가지로 표시되고 작동합니다. 앱 목록에서 찾을 수 있으며 홈 화면, 시작 메뉴, 작업 표시줄에 고정할 수 있습니다. 설치된 웹 앱은 다른 앱과 안전하게 상호 작용할 수 있습니다.',\n hint: '새로운 콘텐츠를 찾았습니다.',\n update: '새로운 콘텐츠가 있습니다.',\n },\n ],\n [\n ['fi', 'fi-FI'],\n {\n install: 'Asenna',\n iOSInstall: \"Paina Jaa-painiketta ja sitten 'Lisää kotiin'-painiketta\",\n cancel: 'Peruuta',\n close: 'Sulje',\n prevImage: 'Edellinen kuva',\n nextImage: 'Seuraava kuva',\n desc: 'Kuvaus',\n feature: 'Avainominaisuudet',\n explain:\n 'Tämä sovellus on asennettavissa tietokoneelle tai mobiililaitteelle. Tämä mahdollistaa sovelluksen toiminnan tietokoneohjelmana. Löydät sen sovelluslistasta ja voit kiinnittää sen työpöydälle, kotinäytölle, tehtäväpalkkiin tai muulle listalle. Asennettu sovellus voi turvallisesti olla vuorovaikutuksessa muiden sovellusten ja käyttöjärjestelmäsi kanssa.',\n hint: 'Uutta sisältöä.',\n update: 'Uutta sisältöä on saatavilla.',\n },\n ],\n [\n ['hu', 'hu-HU'],\n {\n install: 'Telepítés',\n iOSInstall:\n \"Nyomd meg a megosztás gombot, majd a 'Hozzáadás a kezdőképernyőhöz' opciót\",\n cancel: 'Mégse',\n close: 'Bezárás',\n prevImage: 'Előző kép',\n nextImage: 'Következő kép',\n desc: 'Leírás',\n feature: 'Főbb jellemzők',\n explain:\n 'Ez az alkalmazás telepíthető PC-re vagy mobil eszközre. Ez lehetővé teszi, hogy ez a webalkalmazás úgy nézzen ki és viselkedjen, mint bármely más telepített alkalmazás. Az alkalmazáslistában találod majd, és hozzáadhatod a kezdőképernyőhöz, indító menühöz vagy a feladatok sávjához. Az telepített webalkalmazás biztonságosan interakcióba léphet más alkalmazásokkal és az operációs rendszerrel.',\n hint: 'Új tartalom érhető el.',\n update: 'Új tartalom érhető el.',\n },\n ],\n [\n ['id', 'id-ID'],\n {\n install: 'Install',\n iOSInstall: \"Ketuk tombol bagikan, lalu 'Tambahkan ke Layar Utama'\",\n cancel: 'Batal',\n close: 'Tutup',\n prevImage: 'Gambar sebelumnya',\n nextImage: 'Gambar selanjutnya',\n desc: 'Keterangan',\n feature: 'Fitur',\n explain:\n 'Aplikasi ini dapat diinstal di PC atau perangkat seluler Anda. Ini akan memungkinkan aplikasi web ini terlihat seperti aplikasi terpasang lainnya. Anda bisa menemukannya di daftar aplikasi dan dapat menyematkannya ke layar beranda, menu start, atau menu ke taskbar. Aplikasi web yang terinstal ini juga dapat berinteraksi dengan aplikasi lain dan dengan sistem operasi yang Anda gunakan. ',\n hint: 'Konten baru ditemukan.',\n update: 'Konten baru telah tersedia.',\n },\n ],\n [\n ['nl', 'nl-NL'],\n {\n install: 'Installeren',\n iOSInstall: \"Druk op de share button en dan op 'Add to Home Screen'\",\n cancel: 'Annuleren',\n close: 'Sluiten',\n prevImage: 'Vorige Foto',\n nextImage: 'Volgende Foto',\n desc: 'Beschrijving',\n feature: 'Belangrijkste mogelijkheden',\n explain:\n 'Deze app kan op uw PC of mobiel toestel geïnstalleerd worden. Dit laat toe om deze webapp er uit te laten alsof het een normale app is. Je kan het terugvinden in jouw applijsten en kan het op je homescreen, start menu of taakbalk vastzetten. Deze geïnstalleerde webapp zal ook veilig samenwerken met andere apps en uw besturingssysteem. ',\n hint: 'Nieuwe inhoud gevonden.',\n update: 'Nieuwe inhoud is beschikbaar.',\n },\n ],\n]\n","import type { App } from 'vuepress/core'\nimport { fs } from 'vuepress/utils'\n\nimport type { AppManifest } from '../shared/index.js'\nimport type { PwaPluginOptions } from './options.js'\n\nexport const getManifest = async (\n app: App,\n options: PwaPluginOptions,\n): Promise<AppManifest> => {\n const { base, title, description, lang, locales } = app.siteData\n\n const rootLocale = locales['/'] ?? {}\n\n const userManifestPath = app.dir.source(\n '.vuepress/public/manifest.webmanifest',\n )\n const userManifestJSONPath = app.dir.source('.vuepress/public/manifest.json')\n\n const manifestFileContent = JSON.parse(\n fs.existsSync(userManifestPath)\n ? await fs.readFile(userManifestPath, 'utf-8')\n : fs.existsSync(userManifestJSONPath)\n ? await fs.readFile(userManifestJSONPath, 'utf-8')\n : '{}',\n ) as AppManifest\n\n const manifest: AppManifest = {\n name: title || rootLocale.title || 'Site',\n short_name: title || rootLocale.title || 'Site',\n description:\n description || rootLocale.description || 'A site built with vuepress',\n lang: rootLocale.lang ?? lang,\n start_url: base,\n scope: base,\n\n display: 'standalone',\n theme_color: options.themeColor || '#46bd87',\n background_color: '#ffffff',\n orientation: 'portrait-primary',\n prefer_related_applications: false,\n\n ...manifestFileContent,\n ...options.manifest,\n }\n\n return manifest\n}\n","import { Logger } from '@vuepress/helper'\n\nexport const PLUGIN_NAME = '@vuepress/plugin-pwa'\n\nexport const logger = new Logger(PLUGIN_NAME)\n","import type { App } from 'vuepress/core'\nimport { colors, fs, path } from 'vuepress/utils'\n\nimport { getManifest } from './getManifest.js'\nimport { logger } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\n\nexport const generateManifest = async (\n app: App,\n options: PwaPluginOptions,\n): Promise<void> => {\n const { succeed } = logger.load('Generating manifest.webmanifest')\n\n const manifest = await getManifest(app, options)\n const manifestPath = app.dir.dest('manifest.webmanifest')\n\n await fs.writeJSON(manifestPath, manifest, {\n flag: 'w',\n })\n\n succeed(\n `Manifest generated and saved to ${colors.cyan(\n path.relative(process.cwd(), manifestPath),\n )}!`,\n )\n}\n","import { endsWith } from '@vuepress/helper'\nimport type { App } from 'vuepress/core'\nimport { colors } from 'vuepress/utils'\nimport type {\n ManifestEntry,\n ManifestTransform,\n ManifestTransformResult,\n} from 'workbox-build'\nimport { generateSW } from 'workbox-build'\n\nimport { logger } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\n\nconst imageExtensions = ['png', 'jpg', 'jpeg', 'webp', 'bmp', 'gif']\nconst cacheExtensions = [\n 'js',\n 'css',\n 'svg',\n 'woff',\n 'woff2',\n 'eot',\n 'ttf',\n 'otf',\n]\n\nconst imageFilter =\n (maxSize = 1024): ManifestTransform =>\n (\n manifestEntries: (ManifestEntry & { size: number })[],\n ): ManifestTransformResult => {\n const warnings: string[] = []\n const manifest: (ManifestEntry & { size: number })[] = []\n\n for (const entry of manifestEntries) {\n const { url, size } = entry\n\n if (imageExtensions.some((ext) => endsWith(url, `.${ext}`))) {\n if (size > maxSize * 1024)\n warnings.push(`Skipped ${url}, as it's ${Math.ceil(size / 1024)} KB.`)\n else manifest.push(entry)\n } else {\n manifest.push(entry)\n }\n }\n\n return { warnings, manifest }\n }\n\nexport const generateServiceWorker = async (\n app: App,\n options: PwaPluginOptions,\n): Promise<void> => {\n const { succeed } = logger.load('Generating service worker')\n\n const globPatterns = [`**/*.{${cacheExtensions.join(',')}}`]\n\n if (options.cacheHTML) globPatterns.push('**/*.html')\n else globPatterns.push('./index.html', './404.html')\n\n if (options.cacheImage)\n globPatterns.push(`**/*.{${imageExtensions.join(',')}}`)\n\n await generateSW({\n dontCacheBustURLsMatching: new RegExp(\n `\\\\.[0-9a-f]{8}\\\\.(${['html', ...cacheExtensions, ...imageExtensions].join('|')})$`,\n 'u',\n ),\n globPatterns,\n cleanupOutdatedCaches: true,\n clientsClaim: true,\n maximumFileSizeToCacheInBytes: (options.maxSize ?? 2048) * 1024,\n manifestTransforms: [imageFilter(options.maxImageSize)],\n mode: app.env.isDebug ? 'development' : 'production',\n sourcemap: app.env.isDebug,\n ...options.generateSWConfig,\n // should not be override by user config\n globDirectory: app.dir.dest(),\n swDest: app.dir.dest(options.serviceWorkerFilename ?? 'service-worker.js'),\n }).then(({ count, size, warnings }) => {\n succeed()\n\n logger.info(\n `Precache ${colors.cyan(`${count} files`)}, totaling ${colors.cyan(\n `${(size / 1024 / 1024).toFixed(2)} Mb.`,\n )}.`,\n )\n\n if (warnings.length > 0)\n logger.warn(`\\n${warnings.map((warning) => ` · ${warning}`).join('\\n')}`)\n\n if (size > 104857600) {\n logger.error(\n `Cache Size is larger than 100MB, so that it can not be registered on all browsers.\\n${colors.blue(\n 'Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\\n',\n )}`,\n )\n } else if (size > 52428800) {\n logger.warn(\n `\\nCache Size is larger than 50MB, which will not be registered on Safari.\\n${colors.blue(\n 'Please consider disable `cacheHTML` and `cacheImage`, or set `maxSize` and `maxImageSize` option.\\n',\n )}`,\n )\n }\n })\n}\n","import { isLinkAbsolute } from '@vuepress/helper'\n\nimport type { AppManifest } from '../shared/index.js'\nimport type { PwaPluginOptions } from './options.js'\n\nconst appendBaseToLink = (base: string, link: string): string =>\n isLinkAbsolute(link) ? link.replace(/^\\//u, base) : link\n\nexport const appendBaseToManifest = (\n base: string,\n manifest: AppManifest,\n): AppManifest => {\n if (manifest.icons) {\n manifest.icons = manifest.icons.map((icon) => ({\n ...icon,\n src: appendBaseToLink(base, icon.src),\n }))\n }\n\n if (manifest.shortcuts) {\n manifest.shortcuts = manifest.shortcuts.map((shortcut) => ({\n ...shortcut,\n icons:\n shortcut.icons?.map((icon) => ({\n ...icon,\n src: appendBaseToLink(base, icon.src),\n })) ?? [],\n url: appendBaseToLink(base, shortcut.url),\n }))\n }\n\n if (manifest.screenshots) {\n manifest.screenshots = manifest.screenshots.map((screenshot) => ({\n ...screenshot,\n src: appendBaseToLink(base, screenshot.src),\n }))\n }\n\n return manifest\n}\n\nexport const appendBase = (base: string, options: PwaPluginOptions): void => {\n if (options.favicon) options.favicon = appendBaseToLink(base, options.favicon)\n\n if (options.apple) {\n if (options.apple.icon)\n options.apple.icon = appendBaseToLink(base, options.apple.icon)\n\n if (options.apple.maskIcon)\n options.apple.maskIcon = appendBaseToLink(base, options.apple.maskIcon)\n }\n\n if (options.manifest)\n options.manifest = appendBaseToManifest(base, options.manifest)\n}\n","import type { App } from 'vuepress/core'\nimport { isPlainObject } from 'vuepress/shared'\n\nimport type { PwaPluginOptions } from './options.js'\n\n// oxlint-disable-next-line complexity\nexport const injectLinksToHead = (\n app: App,\n { favicon, manifest, themeColor = '#46bd87', apple }: PwaPluginOptions,\n): void => {\n const { base, head } = app.siteData\n const metaKeys: string[] = []\n const linkKeys: string[] = []\n\n // Generate Hash for Head\n head.forEach((item) => {\n if (item[0] === 'meta') metaKeys.push(item[1].name as string)\n else if (item[0] === 'link') linkKeys.push(item[1].rel as string)\n })\n\n const appTitle = manifest?.name ?? app.siteData.title\n let fallBackIcon = ''\n\n const setLink = (\n rel: string,\n href: string,\n more: Record<string, string> = {},\n ): void => {\n if (!linkKeys.includes(rel)) head.push(['link', { rel, href, ...more }])\n }\n\n const setMeta = (\n name: string,\n content: string,\n more: Record<string, string> = {},\n ): void => {\n if (!metaKeys.includes(name))\n head.push(['meta', { name, content, ...more }])\n }\n\n if (appTitle) setMeta('application-name', appTitle)\n\n setMeta('mobile-web-app-capable', 'yes')\n setMeta('theme-color', themeColor || '#46bd87')\n\n // oxlint-disable-next-line typescript/no-deprecated\n if (isPlainObject(apple) && apple.statusBarColor)\n // oxlint-disable-next-line typescript/no-deprecated\n setMeta('apple-mobile-web-app-status-bar-style', apple.statusBarColor)\n\n if (favicon) setLink('icon', favicon)\n\n setLink('manifest', `${base}manifest.webmanifest`, {\n crossorigin: 'use-credentials',\n })\n\n if (manifest?.icons) {\n const { icons } = manifest\n\n if (icons.length > 0) {\n fallBackIcon = icons[0].src\n\n manifest.icons.forEach((icon) => {\n if (icon.type)\n setLink('icon', icon.src, { type: icon.type, sizes: icon.sizes })\n else setLink('icon', icon.src, { sizes: icon.sizes })\n })\n }\n }\n\n if (isPlainObject(apple) && (apple.icon || fallBackIcon)) {\n setLink('apple-touch-icon', apple.icon || fallBackIcon)\n if (apple.maskIcon) {\n setLink('mask-icon', apple.maskIcon, {\n color: themeColor || '#46bd87',\n })\n }\n } else if ((apple ?? true) && fallBackIcon) {\n setLink('apple-touch-icon', fallBackIcon)\n }\n}\n","import { getFullLocaleConfig, getModulePath } from '@vuepress/helper'\nimport type { App } from 'vuepress/core'\nimport { getDirname, path } from 'vuepress/utils'\n\nimport { pwaLocaleInfo } from './locales.js'\nimport { PLUGIN_NAME } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\n\nconst __dirname = import.meta.dirname || getDirname(import.meta.url)\n\nexport const prepareClientConfigFile = (\n app: App,\n options: PwaPluginOptions,\n): Promise<string> => {\n let configImport = ''\n const rootComponents: string[] = []\n\n if (options.showInstall) {\n configImport += `\\\nimport { PwaInstall as _PwaInstall } from \"${path.join(__dirname, '../client/components/PwaInstall.js')}\";\n`\n\n rootComponents.push('PwaInstall')\n }\n\n if (options.update === 'hint') {\n configImport += options.foundComponent\n ? `import _PwaFoundPopup from \"${options.foundComponent}\";\n`\n : `\\\nimport { PwaFoundPopup as _PwaFoundPopup } from \"${path.join(\n __dirname,\n '../client/components/PwaFoundPopup.js',\n )}\";\n`\n\n rootComponents.push('PwaFoundPopup')\n } else if (options.update !== 'disable' && options.update !== 'force') {\n configImport += options.readyComponent\n ? `import _PwaReadyPopup from \"${options.readyComponent}\";\n`\n : `\\\nimport { PwaReadyPopup as _PwaReadyPopup } from \"${path.join(\n __dirname,\n '../client/components/PwaReadyPopup.js',\n )}\";\n`\n\n rootComponents.push('PwaReadyPopup')\n }\n\n return app.writeTemp(\n `pwa/config.js`,\n `\\\nimport { h } from \"vue\";\nimport { defineClientConfig } from \"vuepress/client\";\nimport { setupPwa, setupViewPoint } from \"${path.join(__dirname, '../client/composables/index.js')}\";\n${configImport}\nimport \"${getModulePath('@vuepress/plugin-pwa/styles/vars.css', import.meta)}\";\n\nconst locales = ${JSON.stringify(\n getFullLocaleConfig({\n app,\n name: PLUGIN_NAME,\n default: pwaLocaleInfo,\n config: options.locales,\n }),\n )};\n\nexport default defineClientConfig({\n setup: () => {\n setupPwa(${JSON.stringify(options.serviceWorkerFilename ?? 'service-worker.js')}, ${options.update === 'force'});\n setupViewPoint();\n },\n rootComponents: [\n${rootComponents.map((item) => ` () => h(_${item}, { locales }),`).join('\\n')}\n ],\n});\n`,\n )\n}\n","import {\n addViteOptimizeDepsExclude,\n addViteSsrNoExternal,\n customizeDevServer,\n} from '@vuepress/helper'\nimport type { PluginFunction } from 'vuepress/core'\n\nimport { generateManifest } from './generateManifest.js'\nimport { generateServiceWorker } from './generateServiceWorker.js'\nimport { getManifest } from './getManifest.js'\nimport { appendBase } from './helper.js'\nimport { injectLinksToHead } from './injectLinksToHead.js'\nimport { PLUGIN_NAME, logger } from './logger.js'\nimport type { PwaPluginOptions } from './options.js'\nimport { prepareClientConfigFile } from './prepareClientConfigFile.js'\n\n/**\n * PWA plugin\n *\n * PWA 插件\n *\n * @example\n * import { pwaPlugin } from '@vuepress/plugin-pwa'\n *\n * export default {\n * plugins: [\n * pwaPlugin({\n * showInstall: true,\n * manifest: {\n * name: 'My PWA App',\n * },\n * update: 'hint',\n * }),\n * ],\n * }\n *\n * @param options - Plugin options / 插件选项\n * @returns VuePress plugin / VuePress 插件\n */\nexport const pwaPlugin =\n (options: PwaPluginOptions = {}): PluginFunction =>\n (app) => {\n if (app.env.isDebug) logger.info('Options:', options)\n\n const { shouldPrefetch } = app.options\n const { base } = app.siteData\n\n if (options.appendBase) appendBase(base, options)\n\n if (shouldPrefetch !== true) {\n logger.warn(\n 'The plugin will register service worker to handle assets, so we recommend you to set \"shouldPrefetch: false\" in VuePress config file.',\n )\n }\n\n injectLinksToHead(app, options)\n\n return {\n name: PLUGIN_NAME,\n\n extendsBundlerOptions: (bundlerOptions: unknown) => {\n addViteOptimizeDepsExclude(bundlerOptions, app, [\n 'mitt',\n 'register-service-worker',\n ])\n addViteSsrNoExternal(bundlerOptions, app, '@vuepress/helper')\n\n customizeDevServer(bundlerOptions, app, {\n path: '/manifest.webmanifest',\n response: async (_, response) => {\n response.setHeader('Content-Type', 'application/manifest+json')\n\n return JSON.stringify(await getManifest(app, options))\n },\n errMsg: 'Unexpected manifest generation error',\n })\n },\n\n onGenerated: async () => {\n await generateManifest(app, options)\n await generateServiceWorker(app, options)\n },\n\n clientConfigFile: () => prepareClientConfigFile(app, options),\n }\n }\n"],"mappings":"+WAKA,MAAa,EAAwD,CACnE,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,UACT,WAAY,qDACZ,OAAQ,SACR,MAAO,QACP,UAAW,iBACX,UAAW,aACX,KAAM,cACN,QAAS,eACT,QACE,0VACF,KAAM,qBACN,OAAQ,2BACV,CACF,EACA,CACE,CAAC,KAAM,QAAS,SAAS,EACzB,CACE,QAAS,KACT,WAAY,qBACZ,OAAQ,KACR,MAAO,KACP,UAAW,QACX,UAAW,QACX,KAAM,KACN,QAAS,OACT,QACE,yHACF,KAAM,UACN,OAAQ,QACV,CACF,EACA,CACE,CAAC,QAAS,SAAS,EACnB,CACE,QAAS,KACT,WAAY,qBACZ,OAAQ,KACR,MAAO,KACP,UAAW,QACX,UAAW,QACX,KAAM,KACN,QAAS,OACT,QACE,yHACF,KAAM,UACN,OAAQ,QACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,eACT,WAAY,8DACZ,OAAQ,YACR,MAAO,YACP,UAAW,kBACX,UAAW,gBACX,KAAM,eACN,QAAS,aACT,QACE,iXACF,KAAM,yBACN,OAAQ,8BACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,SACT,WAAY,2DACZ,OAAQ,SACR,MAAO,OACP,UAAW,oBACX,UAAW,qBACX,KAAM,aACN,QAAS,sBACT,QACE,yZACF,KAAM,6BACN,OAAQ,oBACV,CACF,EACA,CACE,CAAC,IAAI,EACL,CACE,QAAS,aACT,WACE,qEACF,OAAQ,YACR,MAAO,UACP,UAAW,uBACX,UAAW,sBACX,KAAM,OACN,QAAS,yBACT,QACE,2XACF,KAAM,uBACN,OAAQ,0BACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,aACT,WACE,mEACF,OAAQ,WACR,MAAO,UACP,UAAW,yBACX,UAAW,wBACX,KAAM,WACN,QAAS,mBACT,QACE,+ZACF,KAAM,uBACN,OAAQ,yBACV,CACF,EACA,CACE,CAAC,IAAI,EACL,CACE,QAAS,WACT,WAAY,6DACZ,OAAQ,WACR,MAAO,SACP,UAAW,kBACX,UAAW,iBACX,KAAM,YACN,QAAS,wBACT,QACE,gYACF,KAAM,2BACN,OAAQ,gCACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,aACT,WACE,yEACF,OAAQ,SACR,MAAO,UACP,UAAW,oBACX,UAAW,mBACX,KAAM,OACN,QAAS,iBACT,QACE,ibACF,KAAM,6BACN,OAAQ,+BACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,cACT,WACE,mEACF,OAAQ,SACR,MAAO,UACP,UAAW,mBACX,UAAW,gBACX,KAAM,WACN,QAAS,qBACT,QACE,0YACF,KAAM,0BACN,OAAQ,yBACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,YACT,WACE,oEACF,OAAQ,UACR,MAAO,SACP,UAAW,mBACX,UAAW,iBACX,KAAM,cACN,QAAS,kBACT,QACE,kXACF,KAAM,qBACN,OAAQ,2BACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,WACT,WACE,qEACF,OAAQ,WACR,MAAO,SACP,UAAW,kBACX,UAAW,mBACX,KAAM,cACN,QAAS,wBACT,QACE,uZACF,KAAM,8BACN,OAAQ,iCACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,SACT,WACE,kCACF,OAAQ,QACR,MAAO,MACP,UAAW,OACX,UAAW,OACX,KAAM,KACN,QAAS,OACT,QACE,kNACF,KAAM,oBACN,OAAQ,kBACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,QACT,WACE,iEACF,OAAQ,QACR,MAAO,QACP,UAAW,eACX,UAAW,gBACX,KAAM,QACN,QAAS,iBACT,QACE,0ZACF,KAAM,uBACN,OAAQ,qBACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,KACT,WAAY,8BACZ,OAAQ,KACR,MAAO,KACP,UAAW,SACX,UAAW,SACX,KAAM,KACN,QAAS,QACT,QACE,+JACF,KAAM,kBACN,OAAQ,gBACV,CACF,EACA,CACE,CAAC,KAAM,OAAO,EACd,CACE,QAAS,SACT,WAAY,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"}
@@ -1,8 +1,8 @@
1
- import { t as PwaPluginLocaleData } from "./locales-BzKyD3qP.js";
1
+ import { t as PwaPluginLocaleData } from "./locales-D1imGthS.js";
2
2
  import { ExactLocaleConfig } from "@vuepress/helper/client";
3
3
 
4
4
  //#region src/client/types.d.ts
5
5
  type PwaPluginLocaleConfig = ExactLocaleConfig<PwaPluginLocaleData>;
6
6
  //#endregion
7
7
  export { PwaPluginLocaleConfig as t };
8
- //# sourceMappingURL=types-BLkMmayH.d.ts.map
8
+ //# sourceMappingURL=types-0w9cSsje.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vuepress/plugin-pwa",
3
- "version": "2.0.0-rc.128",
3
+ "version": "2.0.0-rc.130",
4
4
  "description": "VuePress plugin - progressive web application",
5
5
  "keywords": [
6
6
  "plugin",
@@ -46,15 +46,15 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@vuepress/helper": "2.0.0-rc.128",
50
- "@vueuse/core": "^14.2.1",
49
+ "@vuepress/helper": "2.0.0-rc.130",
50
+ "@vueuse/core": "^14.3.0",
51
51
  "mitt": "^3.0.1",
52
52
  "register-service-worker": "^1.7.2",
53
- "vue": "^3.5.31",
54
- "workbox-build": "^7.4.0"
53
+ "vue": "^3.5.34",
54
+ "workbox-build": "^7.4.1"
55
55
  },
56
56
  "peerDependencies": {
57
- "vuepress": "2.0.0-rc.28"
57
+ "vuepress": "2.0.0-rc.30"
58
58
  },
59
- "gitHead": "47b25c2008dc496e4638cae7528374846d3660dd"
59
+ "gitHead": "3612bba34c7299f3bad032390904c8c27cd417cc"
60
60
  }
@@ -1,3 +0,0 @@
1
- import './PwaInstall-D2rYRuV_.css';
2
- import{n as e,r as t,t as n}from"./icons-RRw4DIWa.js";import{useLocale as r}from"@vuepress/helper/client";import{useEventListener as i,useToggle as a}from"@vueuse/core";import{computed as o,defineComponent as s,h as c,onMounted as l,ref as u,shallowRef as d}from"vue";import{withBase as f}from"vuepress/client";const p=()=>{let e=document.querySelector(`.screenshot`);e&&e.scrollBy({left:-e.clientWidth,top:0,behavior:`smooth`})},m=()=>{let e=document.querySelector(`.screenshot`);e&&e.scrollBy({left:e.clientWidth,top:0,behavior:`smooth`})},h=s({name:`PwaInstallModal`,props:{locales:{type:Object,required:!0},useHint:Boolean},emits:[`canInstall`,`hint`,`close`],setup(a,{emit:o}){let s=r(a.locales),u=d({}),h=d(),g=async()=>{let e=localStorage.getItem(`manifest`);if(e)u.value=JSON.parse(e);else try{let e=await(await fetch(f(`manifest.webmanifest`))).json();u.value=e,localStorage.setItem(`manifest`,JSON.stringify(e))}catch{console.error(`[PWA]: Error getting manifest, check that you have a valid web manifest or network connection`)}},_=async()=>{h.value&&(h.value.prompt(),document.dispatchEvent(new CustomEvent(`show`)),(await h.value.userChoice).outcome===`accepted`?(console.info(`PWA has been installed`),o(`close`,!1),o(`canInstall`,!1)):(console.info(`You choose to not install PWA`),o(`close`,!1),o(`canInstall`,!1)))},v=()=>{console.info(`You accepted the install hint`),o(`hint`)};return l(()=>{window.hasOwnProperty(`BeforeInstallPromptEvent`)&&(i(window,`beforeinstallprompt`,e=>{h.value=e,o(`canInstall`,!0),e.preventDefault()}),i(`keyup`,e=>{e.key===`Escape`&&o(`close`,!1)},{passive:!0}),g())}),()=>c(`div`,{id:`install-modal-wrapper`},[c(`div`,{class:`background`,onClick:()=>{o(`close`,!1)}}),c(`div`,{class:`install-modal`},[c(`div`,{class:`header`},[c(`button`,{type:`button`,class:`close-button`,"aria-label":s.value.close,onClick:()=>{o(`close`,!1)}},c(t)),c(`div`,{class:`logo`},[u.value.icons?c(`img`,{src:u.value.icons[0]?.src,alt:`App Logo`}):null,c(`div`,{class:`title`},[c(`h1`,u.value.short_name||u.value.name),c(`p`,{class:`desc`},s.value.explain)])])]),c(`div`,{class:`content`},[c(`div`,{class:`highlight`},[u.value.features?c(`div`,{class:`feature-wrapper`},[c(`h3`,s.value.feature),c(`ul`,u.value.features.map(e=>c(`li`,e)))]):null,u.value.screenshots?c(`div`,{class:`screenshot-wrapper`},[c(`button`,{type:`button`,"aria-label":s.value.prevImage,onClick:p},c(n)),c(`section`,{class:`screenshot`},[u.value.screenshots.map(e=>c(`div`,c(`img`,{src:e.src,alt:`App Screenshot`})))]),c(`button`,{type:`button`,"aria-label":s.value.nextImage,onClick:m},c(e))]):null]),c(`div`,{class:`description`},[c(`h3`,s.value.desc),c(`p`,u.value.description)])]),a.useHint?c(`div`,{class:`ios-text`,onClick:v},[c(`p`,s.value.iOSInstall),c(`button`,{type:`button`,class:`success`},`Got it!`)]):c(`div`,{class:`button-wrapper`},[c(`button`,{type:`button`,class:`install-button`,onClick:_},[s.value.install,c(`span`,u.value.short_name)]),c(`button`,{type:`button`,class:`cancel-button`,onClick:()=>{o(`close`,!1)}},s.value.cancel)])])])}}),g=s({name:`PwaInstall`,props:{locales:{type:Object,required:!0}},setup(e){let t=r(e.locales),[n,i]=a(),s=u(!1),d=u(!1),f=u(!1),p=u(!1),m=u(!1),g=o(()=>f.value&&p.value&&!m.value),_=o(()=>d.value&&s.value||g.value),v=()=>navigator.standalone?navigator.standalone:matchMedia(`(display-mode: standalone)`).matches,y=()=>{i(!1),m.value=!0,localStorage.setItem(`iOS-pwa-hint`,`hinted`)};return l(()=>{if(v()){let{userAgent:e}=navigator;f.value=e.includes(`iPhone`)||e.includes(`iPad`)||!!(e.includes(`Macintosh`)&&navigator.maxTouchPoints&&navigator.maxTouchPoints>2),p.value=navigator.userAgent.includes(`Safari`)&&!e.includes(`Chrome`),m.value=!!localStorage.getItem(`iOS-pwa-hint`)}`getInstalledRelatedApps`in navigator&&navigator.getInstalledRelatedApps().then(e=>{d.value=e.length>0})}),()=>c(`div`,{id:`pwa-install`},[_.value?c(`button`,{type:`button`,class:`modal-button`,onClick:()=>{i(!0)}},t.value.install):null,c(h,{style:{display:n.value?`block`:`none`},locales:e.locales,useHint:g.value,onCanInstall:e=>{s.value=e},onHint:()=>{y()},onClose:()=>i(!1)})])}});export{g as t};
3
- //# sourceMappingURL=PwaInstall-D2rYRuV_.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PwaInstall-D2rYRuV_.js","names":[],"sources":["../src/client/components/PwaInstallModal.ts","../src/client/components/PwaInstall.ts"],"sourcesContent":["/* oxlint-disable no-console */\nimport { useLocale } from '@vuepress/helper/client'\nimport { useEventListener } from '@vueuse/core'\nimport type { PropType, VNode } from 'vue'\nimport { defineComponent, h, onMounted, shallowRef } from 'vue'\nimport { withBase } from 'vuepress/client'\n\nimport type { AppManifest } from '../../shared/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { ArrowLeftIcon, ArrowRightIcon, CloseIcon } from './icons.js'\n\ninterface InstallPromptEvent extends Event {\n readonly platforms: string\n prompt: () => void\n readonly userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>\n}\n\nconst scrollToLeft = (): void => {\n const screenshotsDiv = document.querySelector('.screenshot')\n\n if (screenshotsDiv) {\n screenshotsDiv.scrollBy({\n left: -screenshotsDiv.clientWidth,\n top: 0,\n behavior: 'smooth',\n })\n }\n}\n\nconst scrollToRight = (): void => {\n const screenshotsDiv = document.querySelector('.screenshot')\n\n if (screenshotsDiv) {\n screenshotsDiv.scrollBy({\n left: screenshotsDiv.clientWidth,\n top: 0,\n behavior: 'smooth',\n })\n }\n}\n\nexport const PwaInstallModal = defineComponent({\n name: 'PwaInstallModal',\n\n props: {\n /** locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n\n /**\n * Whether use hint message instead of showing a button\n *\n * 是否使用提示\n */\n useHint: Boolean,\n },\n\n emits: ['canInstall', 'hint', 'close'],\n\n setup(props, { emit }) {\n const locale = useLocale(props.locales)\n\n const manifest = shallowRef<AppManifest>({})\n const deferredPrompt = shallowRef<InstallPromptEvent>()\n\n const getManifest = async (): Promise<void> => {\n const manifestContent = localStorage.getItem('manifest')\n\n if (manifestContent) {\n manifest.value = JSON.parse(manifestContent) as AppManifest\n } else {\n try {\n const response = await fetch(withBase('manifest.webmanifest'))\n const data = (await response.json()) as AppManifest\n\n manifest.value = data\n localStorage.setItem('manifest', JSON.stringify(data))\n } catch {\n console.error(\n '[PWA]: Error getting manifest, check that you have a valid web manifest or network connection',\n )\n }\n }\n }\n\n const install = async (): Promise<void> => {\n if (deferredPrompt.value) {\n deferredPrompt.value.prompt()\n\n document.dispatchEvent(new CustomEvent('show'))\n\n const choiceResult = await deferredPrompt.value.userChoice\n\n if (choiceResult.outcome === 'accepted') {\n console.info('PWA has been installed')\n\n emit('close', false)\n emit('canInstall', false)\n } else {\n console.info('You choose to not install PWA')\n\n emit('close', false)\n emit('canInstall', false)\n }\n }\n }\n\n const hint = (): void => {\n console.info('You accepted the install hint')\n emit('hint')\n }\n\n onMounted(() => {\n // oxlint-disable-next-line no-prototype-builtins\n if (window.hasOwnProperty('BeforeInstallPromptEvent')) {\n useEventListener(window, 'beforeinstallprompt', (event) => {\n deferredPrompt.value = event as InstallPromptEvent\n\n emit('canInstall', true)\n event.preventDefault()\n })\n\n useEventListener(\n 'keyup',\n (event): void => {\n if (event.key === 'Escape') emit('close', false)\n },\n { passive: true },\n )\n\n void getManifest()\n }\n })\n\n return (): VNode =>\n h('div', { id: 'install-modal-wrapper' }, [\n h('div', {\n class: 'background',\n onClick: () => {\n emit('close', false)\n },\n }),\n\n h('div', { class: 'install-modal' }, [\n h('div', { class: 'header' }, [\n // close button\n h(\n 'button',\n {\n 'type': 'button',\n 'class': 'close-button',\n 'aria-label': locale.value.close,\n 'onClick': () => {\n emit('close', false)\n },\n },\n h(CloseIcon),\n ),\n\n h('div', { class: 'logo' }, [\n manifest.value.icons\n ? h('img', {\n src: manifest.value.icons[0]?.src,\n alt: 'App Logo',\n })\n : null,\n h('div', { class: 'title' }, [\n h('h1', manifest.value.short_name || manifest.value.name),\n h('p', { class: 'desc' }, locale.value.explain),\n ]),\n ]),\n ]),\n\n h('div', { class: 'content' }, [\n h('div', { class: 'highlight' }, [\n manifest.value.features\n ? h('div', { class: 'feature-wrapper' }, [\n h('h3', locale.value.feature),\n h(\n 'ul',\n manifest.value.features.map((feature) =>\n h('li', feature),\n ),\n ),\n ])\n : null,\n\n manifest.value.screenshots\n ? h('div', { class: 'screenshot-wrapper' }, [\n h(\n 'button',\n {\n 'type': 'button',\n 'aria-label': locale.value.prevImage,\n 'onClick': scrollToLeft,\n },\n h(ArrowLeftIcon),\n ),\n h('section', { class: 'screenshot' }, [\n manifest.value.screenshots.map((screenshot) =>\n h(\n 'div',\n h('img', {\n src: screenshot.src,\n alt: 'App Screenshot',\n }),\n ),\n ),\n ]),\n h(\n 'button',\n {\n 'type': 'button',\n 'aria-label': locale.value.nextImage,\n 'onClick': scrollToRight,\n },\n h(ArrowRightIcon),\n ),\n ])\n : null,\n ]),\n\n h('div', { class: 'description' }, [\n h('h3', locale.value.desc),\n h('p', manifest.value.description),\n ]),\n ]),\n\n props.useHint\n ? h('div', { class: 'ios-text', onClick: hint }, [\n h('p', locale.value.iOSInstall),\n h('button', { type: 'button', class: 'success' }, 'Got it!'),\n ])\n : h('div', { class: 'button-wrapper' }, [\n h(\n 'button',\n { type: 'button', class: 'install-button', onClick: install },\n [locale.value.install, h('span', manifest.value.short_name)],\n ),\n h(\n 'button',\n {\n type: 'button',\n class: 'cancel-button',\n onClick: () => {\n emit('close', false)\n },\n },\n locale.value.cancel,\n ),\n ]),\n ]),\n ])\n },\n})\n","import { useLocale } from '@vuepress/helper/client'\nimport { useToggle } from '@vueuse/core'\nimport type { PropType, VNode } from 'vue'\nimport { computed, defineComponent, h, onMounted, ref } from 'vue'\n\nimport type { ManifestExternalApplicationResource } from '../../shared/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { PwaInstallModal } from './PwaInstallModal.js'\n\nimport '../styles/modal.scss'\n\ninterface ModernNavigator extends Navigator {\n // Nonstandard Api\n getInstalledRelatedApps: () => Promise<ManifestExternalApplicationResource[]>\n}\n\ninterface SafariNavigator extends Navigator {\n // Available on Apple’s iOS Safari only.\n standalone: boolean\n}\n\nexport const PwaInstall = defineComponent({\n name: 'PwaInstall',\n\n props: {\n /** locale data */\n locales: {\n type: Object as PropType<PwaPluginLocaleConfig>,\n required: true,\n },\n },\n\n setup(props) {\n const locale = useLocale(props.locales)\n const [isOpen, toggleIsOpen] = useToggle()\n\n const canInstall = ref(false)\n const hasRelatedApps = ref(false)\n const isIOS = ref(false)\n const isSafari = ref(false)\n const hinted = ref(false)\n\n const useHint = computed(\n () => isIOS.value && isSafari.value && !hinted.value,\n )\n\n const showInstall = computed(\n () => (hasRelatedApps.value && canInstall.value) || useHint.value,\n )\n\n const getInstallStatus = (): boolean => {\n if ((navigator as SafariNavigator).standalone)\n return (navigator as SafariNavigator).standalone\n\n return matchMedia('(display-mode: standalone)').matches\n }\n\n const hint = (): void => {\n toggleIsOpen(false)\n hinted.value = true\n // do not notify again\n localStorage.setItem('iOS-pwa-hint', 'hinted')\n }\n\n onMounted(() => {\n if (getInstallStatus()) {\n const { userAgent } = navigator\n\n // handle iOS specifically\n isIOS.value =\n // regular iPhone\n userAgent.includes('iPhone') ||\n // regular iPad\n userAgent.includes('iPad') ||\n // iPad pro\n Boolean(\n userAgent.includes('Macintosh') &&\n navigator.maxTouchPoints &&\n navigator.maxTouchPoints > 2,\n )\n\n isSafari.value =\n navigator.userAgent.includes('Safari') &&\n !userAgent.includes('Chrome')\n\n hinted.value = Boolean(localStorage.getItem('iOS-pwa-hint'))\n }\n\n if ('getInstalledRelatedApps' in (navigator as ModernNavigator)) {\n void (navigator as ModernNavigator)\n .getInstalledRelatedApps()\n .then((result) => {\n hasRelatedApps.value = result.length > 0\n })\n }\n })\n\n return (): VNode =>\n h('div', { id: 'pwa-install' }, [\n showInstall.value\n ? h(\n 'button',\n {\n type: 'button',\n class: 'modal-button',\n onClick: () => {\n toggleIsOpen(true)\n },\n },\n locale.value.install,\n )\n : null,\n h(PwaInstallModal, {\n style: {\n display: isOpen.value ? 'block' : 'none',\n },\n locales: props.locales,\n useHint: useHint.value,\n onCanInstall: (value: boolean) => {\n canInstall.value = value\n },\n onHint: () => {\n hint()\n },\n onClose: () => toggleIsOpen(false),\n }),\n ])\n },\n})\n"],"mappings":"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"}