@vuepress/plugin-pwa 2.0.0-rc.119 → 2.0.0-rc.120

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 +1 @@
1
- {"version":3,"file":"PwaInstall.js","sources":["../../../src/client/components/PwaInstallModal.ts","../../../src/client/components/PwaInstall.ts"],"sourcesContent":["/* eslint-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'\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\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 const 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 const 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 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 // eslint-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'\nimport type { ManifestExternalApplicationResource } from '../../shared/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { PwaInstallModal } from './PwaInstallModal.js'\n\nimport '../styles/modal.css'\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 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"],"names":["PwaInstallModal","defineComponent","props","emit","locale","useLocale","manifest","shallowRef","deferredPrompt","getManifest","manifestContent","data","withBase","scrollToLeft","screenshotsDiv","scrollToRight","install","hint","onMounted","useEventListener","event","h","CloseIcon","feature","ArrowLeftIcon","screenshot","ArrowRightIcon","PwaInstall","isOpen","toggleIsOpen","useToggle","canInstall","ref","hasRelatedApps","isIOS","isSafari","hinted","useHint","computed","showInstall","getInstallStatus","userAgent","result","value"],"mappings":"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"}
1
+ {"version":3,"file":"PwaInstall.js","sources":["../../../src/client/components/PwaInstallModal.ts","../../../src/client/components/PwaInstall.ts"],"sourcesContent":["/* eslint-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'\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\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 const 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 const 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 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 // eslint-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'\nimport type { ManifestExternalApplicationResource } from '../../shared/index.js'\nimport type { PwaPluginLocaleConfig } from '../types.js'\nimport { PwaInstallModal } from './PwaInstallModal.js'\n\nimport '../styles/modal.css'\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 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"],"names":["PwaInstallModal","defineComponent","props","emit","locale","useLocale","manifest","shallowRef","deferredPrompt","getManifest","manifestContent","data","withBase","scrollToLeft","screenshotsDiv","scrollToRight","install","hint","onMounted","useEventListener","event","h","CloseIcon","feature","ArrowLeftIcon","screenshot","ArrowRightIcon","PwaInstall","isOpen","toggleIsOpen","useToggle","canInstall","ref","hasRelatedApps","isIOS","isSafari","hinted","useHint","computed","showInstall","getInstallStatus","userAgent","result","value"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{s as p,a as r,u as i}from"../index-DYf0Bvv5.js";import{p as u,u as w}from"../usePwaEvent-CUDY9qle.js";import"mitt";import"vue";import"vuepress/client";export{u as pwaEventSymbol,p as setupPwa,r as setupViewPoint,w as usePwaEvent,i as useRegisterSW};
1
+ import{s as p,a as r,u as i}from"../index-B2tGW6v2.js";import{p as u,u as w}from"../usePwaEvent-CUDY9qle.js";import"mitt";import"vue";import"vuepress/client";export{u as pwaEventSymbol,p as setupPwa,r as setupViewPoint,w as usePwaEvent,i as useRegisterSW};
2
2
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,2 @@
1
+ import s from"mitt";import{provide as l,onMounted as i}from"vue";import{p as m}from"./usePwaEvent-CUDY9qle.js";import{withBase as u}from"vuepress/client";const n=()=>{navigator.serviceWorker.getRegistration().then(r=>{r?.active&&r.addEventListener("updatefound",()=>{window.location.reload(!0)})})},c=async(r,t={},e=!0)=>{const{register:a}=await import("register-service-worker");a(r,{ready(o){e&&console.info("[Service Worker]: active"),t.ready?.(o)},registered(o){e&&console.log("[Service Worker]: registered"),t.registered?.(o)},cached(o){e&&console.log("[Service Worker]: cached"),t.cached?.(o)},updatefound(o){e&&console.log("[Service Worker]: update found"),t.updatefound?.(o)},updated(o){e&&console.log("[Service Worker]: updated"),t.updated?.(o)},offline(){e&&console.log("[Service Worker]: offline"),t.offline?.()},error(o){e&&console.error("[Service Worker]: ",o),t.error?.(o)}})},d=async(r,t)=>c(u(r),{ready(e){t.emit("ready",e)},registered(e){t.emit("registered",e)},cached(e){t.emit("cached",e)},updatefound(e){t.emit("updatefound",e)},updated(e){const a="service-worker-version",o=Number(localStorage.getItem(a)||0);localStorage.setItem(a,(o+1).toString()),localStorage.removeItem("manifest"),t.emit("updated",e)},offline(){t.emit("offline")},error(e){t.emit("error",e)}}),f=(r,t=!1)=>{if(__VUEPRESS_SSR__)return;const e=s();l(m,e),i(async()=>{if(__VUEPRESS_DEV__||!("serviceWorker"in navigator))return;let a=!1;navigator.serviceWorker.controller&&navigator.serviceWorker.addEventListener("controllerchange",()=>{a||(a=!0,window.location.reload())}),t&&n(),await d(r,e)})},v=()=>{i(()=>{if(window.matchMedia("(display-mode: standalone)").matches){const r=document.head.querySelector('meta[name="viewport"]');if(r){r.setAttribute("content","width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover");return}const t=document.createElement("meta");t.name="viewport",t.content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover",document.head.appendChild(t)}})};export{v as a,n as f,c as r,f as s,d as u};
2
+ //# sourceMappingURL=index-B2tGW6v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-B2tGW6v2.js","sources":["../../src/client/utils/forceUpdate.ts","../../src/client/utils/registerSW.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","/* eslint-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 { withBase } from 'vuepress/client'\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 * @returns Promise that resolves when registration is complete / 注册完成时解析的 Promise\n */\nexport const useRegisterSW = async (\n serviceWorkerPath: string,\n event: PwaEvent,\n): Promise<void> =>\n 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","import mitt from 'mitt'\nimport { onMounted, provide } from 'vue'\nimport { forceUpdate } from '../utils/index.js'\nimport { pwaEventSymbol } from './usePwaEvent.js'\nimport { useRegisterSW } from './useRegisterSW.js'\nimport type { PwaEvent } from './index.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 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.appendChild(viewportMeta)\n }\n })\n}\n"],"names":["forceUpdate","registration","registerSW","serviceWorkerPath","hooks","showStatus","register","err","useRegisterSW","event","withBase","key","version","setupPwa","shouldForceUpdate","mitt","provide","pwaEventSymbol","onMounted","refreshing","setupViewPoint","head","viewportMeta"],"mappings":"0JAKO,MAAMA,EAAc,IAAY,CAChC,UAAU,cAAc,kBAAkB,KAAMC,GAAiB,CAEhEA,GAAc,QAChBA,EAAa,iBAAiB,cAAe,IAAM,CAGjD,OAAO,SAAS,OAAO,EAAI,CAC7B,CAAC,CACL,CAAC,CACH,ECHaC,EAAa,MACxBC,EACAC,EAAe,CAAA,EACfC,EAAa,KACK,CAClB,KAAM,CAAE,SAAAC,CAAS,EAAI,KAAM,QACyB,yBACpD,EAGAA,EAASH,EAAmB,CAC1B,MAAMF,EAAc,CACdI,GAAY,QAAQ,KAAK,0BAA0B,EACvDD,EAAM,QAAQH,CAAY,CAC5B,EAEA,WAAWA,EAAc,CACnBI,GAAY,QAAQ,IAAI,8BAA8B,EAC1DD,EAAM,aAAaH,CAAY,CACjC,EAEA,OAAOA,EAAc,CACfI,GAAY,QAAQ,IAAI,0BAA0B,EACtDD,EAAM,SAASH,CAAY,CAC7B,EAEA,YAAYA,EAAc,CACpBI,GAAY,QAAQ,IAAI,gCAAgC,EAC5DD,EAAM,cAAcH,CAAY,CAClC,EAEA,QAAQA,EAAc,CAChBI,GAAY,QAAQ,IAAI,2BAA2B,EACvDD,EAAM,UAAUH,CAAY,CAC9B,EAEA,SAAU,CACJI,GAAY,QAAQ,IAAI,2BAA2B,EACvDD,EAAM,UAAA,CACR,EAEA,MAAMG,EAAK,CACLF,GAAY,QAAQ,MAAM,qBAAsBE,CAAG,EACvDH,EAAM,QAAQG,CAAG,CACnB,CACF,CAAC,CACH,EC7CaC,EAAgB,MAC3BL,EACAM,IAEAP,EAAWQ,EAASP,CAAiB,EAAG,CACtC,MAAMF,EAAc,CAClBQ,EAAM,KAAK,QAASR,CAAY,CAClC,EAEA,WAAWA,EAAc,CACvBQ,EAAM,KAAK,aAAcR,CAAY,CACvC,EAEA,OAAOA,EAAc,CACnBQ,EAAM,KAAK,SAAUR,CAAY,CACnC,EAEA,YAAYA,EAAc,CACxBQ,EAAM,KAAK,cAAeR,CAAY,CACxC,EAEA,QAAQA,EAAc,CACpB,MAAMU,EAAM,yBACNC,EAAU,OAAO,aAAa,QAAQD,CAAG,GAAK,CAAC,EAErD,aAAa,QAAQA,GAAMC,EAAU,GAAG,SAAA,CAAU,EAClD,aAAa,WAAW,UAAU,EAElCH,EAAM,KAAK,UAAWR,CAAY,CACpC,EAEA,SAAU,CACRQ,EAAM,KAAK,SAAS,CACtB,EAEA,MAAMF,EAAK,CACTE,EAAM,KAAK,QAASF,CAAG,CACzB,CACF,CAAC,ECpCUM,EAAW,CACtBV,EACAW,EAAoB,KACX,CACT,GAAI,iBAAkB,OAGtB,MAAML,EAAkBM,IAExBC,EAAQC,EAAgBR,CAAK,EAE7BS,EAAU,SAAY,CACpB,GAAI,kBAAoB,EAAE,kBAAmB,WAAY,OAEzD,IAAIC,EAAa,GAGb,UAAU,cAAc,YAC1B,UAAU,cAAc,iBAAiB,mBAAoB,IAAM,CAC7DA,IAEJA,EAAa,GACb,OAAO,SAAS,OAAA,EAClB,CAAC,EAECL,GAAmBd,IAEvB,MAAMQ,EAAcL,EAAmBM,CAAK,CAC9C,CAAC,CACH,ECrCaW,EAAiB,IAAY,CACxCF,EAAU,IAAM,CAGd,GAFqB,OAAO,WAAW,4BAA4B,EAAE,QAEnD,CAChB,MAAMG,EAAO,SAAS,KAAK,cAAc,uBAAuB,EAEhE,GAAIA,EAAM,CACRA,EAAK,aACH,UACA,gGACF,EACA,MACF,CAEA,MAAMC,EAAe,SAAS,cAAc,MAAM,EAElDA,EAAa,KAAO,WACpBA,EAAa,QACX,iGAEF,SAAS,KAAK,YAAYA,CAAY,CACxC,CACF,CAAC,CACH"}
@@ -1,2 +1,2 @@
1
- import{PwaInstall as f}from"./components/PwaInstall.js";import{PwaFoundPopup as l}from"./components/PwaFoundPopup.js";import{P as v,s as x}from"./PwaReadyPopup-BPfm3Qt3.js";import{f as h,r as k,s as S,a as R,u as y}from"./index-DYf0Bvv5.js";import{p as E,u as U}from"./usePwaEvent-CUDY9qle.js";import"@vuepress/helper/client";import"@vueuse/core";import"vue";import"vuepress/client";import"./icons-DQk7h1-3.js";import"./styles/modal.css";import"@vuepress/helper/transition/fade-in-scale-up.css";import"./styles/popup.css";import"mitt";const t=()=>navigator.serviceWorker.getRegistration().then(r=>r?r.unregister().then(e=>(e&&console.log("[PWA] Current service worker unregistered"),e)):!1).catch(r=>(console.error("[PWA] Unregister current service worker failed with error:",r),!1));export{l as PwaFoundPopup,f as PwaInstall,v as PwaReadyPopup,h as forceUpdate,E as pwaEventSymbol,k as registerSW,S as setupPwa,R as setupViewPoint,x as skipWaiting,t as unregisterSW,U as usePwaEvent,y as useRegisterSW};
1
+ import{PwaInstall as f}from"./components/PwaInstall.js";import{PwaFoundPopup as l}from"./components/PwaFoundPopup.js";import{P as v,s as x}from"./PwaReadyPopup-BPfm3Qt3.js";import{f as h,r as k,s as S,a as R,u as y}from"./index-B2tGW6v2.js";import{p as E,u as U}from"./usePwaEvent-CUDY9qle.js";import"@vuepress/helper/client";import"@vueuse/core";import"vue";import"vuepress/client";import"./icons-DQk7h1-3.js";import"./styles/modal.css";import"@vuepress/helper/transition/fade-in-scale-up.css";import"./styles/popup.css";import"mitt";const t=()=>navigator.serviceWorker.getRegistration().then(r=>r?r.unregister().then(e=>(e&&console.log("[PWA] Current service worker unregistered"),e)):!1).catch(r=>(console.error("[PWA] Unregister current service worker failed with error:",r),!1));export{l as PwaFoundPopup,f as PwaInstall,v as PwaReadyPopup,h as forceUpdate,E as pwaEventSymbol,k as registerSW,S as setupPwa,R as setupViewPoint,x as skipWaiting,t as unregisterSW,U as usePwaEvent,y as useRegisterSW};
2
2
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vuepress/plugin-pwa",
3
- "version": "2.0.0-rc.119",
3
+ "version": "2.0.0-rc.120",
4
4
  "description": "VuePress plugin - progressive web application",
5
5
  "keywords": [
6
6
  "vuepress-plugin",
@@ -36,15 +36,15 @@
36
36
  "lib"
37
37
  ],
38
38
  "dependencies": {
39
- "@vuepress/helper": "2.0.0-rc.118",
40
- "@vueuse/core": "^14.0.0",
39
+ "@vuepress/helper": "2.0.0-rc.120",
40
+ "@vueuse/core": "^14.1.0",
41
41
  "mitt": "^3.0.1",
42
42
  "register-service-worker": "^1.7.2",
43
- "vue": "^3.5.22",
44
- "workbox-build": "^7.3.0"
43
+ "vue": "^3.5.25",
44
+ "workbox-build": "^7.4.0"
45
45
  },
46
46
  "devDependencies": {
47
- "rollup": "^4.52.5"
47
+ "rollup": "^4.53.3"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "vuepress": "2.0.0-rc.26"
@@ -52,5 +52,5 @@
52
52
  "publishConfig": {
53
53
  "access": "public"
54
54
  },
55
- "gitHead": "195adf59181c092bef15877075290aee786cd4d3"
55
+ "gitHead": "02d058c345d689f6a639ca01f937b664deda33d3"
56
56
  }
@@ -1,2 +0,0 @@
1
- import d from"mitt";import{provide as l,onMounted as i}from"vue";import{p as m}from"./usePwaEvent-CUDY9qle.js";import{withBase as u}from"vuepress/client";const n=()=>{navigator.serviceWorker.getRegistration().then(r=>{r?.active&&r.addEventListener("updatefound",()=>{window.location.reload(!0)})})},c=async(r,t={},e=!0)=>{const{register:a}=await import("register-service-worker");a(r,{ready(o){e&&console.info("[Service Worker]: active"),t.ready?.(o)},registered(o){e&&console.log("[Service Worker]: registered"),t.registered?.(o)},cached(o){e&&console.log("[Service Worker]: cached"),t.cached?.(o)},async updatefound(o){await navigator.serviceWorker.getRegistration()&&(e&&console.log("[Service Worker]: update found"),t.updatefound?.(o))},updated(o){e&&console.log("[Service Worker]: updated"),t.updated?.(o)},offline(){e&&console.log("[Service Worker]: offline"),t.offline?.()},error(o){e&&console.error("[Service Worker]: ",o),t.error?.(o)}})},s=async(r,t)=>c(u(r),{ready(e){t.emit("ready",e)},registered(e){t.emit("registered",e)},cached(e){t.emit("cached",e)},updatefound(e){t.emit("updatefound",e)},updated(e){const a="service-worker-version",o=Number(localStorage.getItem(a)||0);localStorage.setItem(a,(o+1).toString()),localStorage.removeItem("manifest"),t.emit("updated",e)},offline(){t.emit("offline")},error(e){t.emit("error",e)}}),v=(r,t=!1)=>{if(__VUEPRESS_SSR__)return;const e=d();l(m,e),i(async()=>{if(__VUEPRESS_DEV__||!("serviceWorker"in navigator))return;let a=!1;navigator.serviceWorker.controller&&navigator.serviceWorker.addEventListener("controllerchange",()=>{a||(a=!0,window.location.reload())}),t&&n(),await s(r,e)})},f=()=>{i(()=>{if(window.matchMedia("(display-mode: standalone)").matches){const r=document.head.querySelector('meta[name="viewport"]');if(r){r.setAttribute("content","width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover");return}const t=document.createElement("meta");t.name="viewport",t.content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover",document.head.appendChild(t)}})};export{f as a,n as f,c as r,v as s,s as u};
2
- //# sourceMappingURL=index-DYf0Bvv5.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-DYf0Bvv5.js","sources":["../../src/client/utils/forceUpdate.ts","../../src/client/utils/registerSW.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","/* eslint-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 async updatefound(registration) {\n if (await navigator.serviceWorker.getRegistration()) {\n if (showStatus) console.log('[Service Worker]: update found')\n hooks.updatefound?.(registration)\n }\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 { withBase } from 'vuepress/client'\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 * @returns Promise that resolves when registration is complete / 注册完成时解析的 Promise\n */\nexport const useRegisterSW = async (\n serviceWorkerPath: string,\n event: PwaEvent,\n): Promise<void> =>\n 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","import mitt from 'mitt'\nimport { onMounted, provide } from 'vue'\nimport { forceUpdate } from '../utils/index.js'\nimport { pwaEventSymbol } from './usePwaEvent.js'\nimport { useRegisterSW } from './useRegisterSW.js'\nimport type { PwaEvent } from './index.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 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.appendChild(viewportMeta)\n }\n })\n}\n"],"names":["forceUpdate","registration","registerSW","serviceWorkerPath","hooks","showStatus","register","err","useRegisterSW","event","withBase","key","version","setupPwa","shouldForceUpdate","mitt","provide","pwaEventSymbol","onMounted","refreshing","setupViewPoint","head","viewportMeta"],"mappings":"0JAKO,MAAMA,EAAc,IAAY,CAChC,UAAU,cAAc,kBAAkB,KAAMC,GAAiB,CAEhEA,GAAc,QAChBA,EAAa,iBAAiB,cAAe,IAAM,CAGjD,OAAO,SAAS,OAAO,EAAI,CAC7B,CAAC,CACL,CAAC,CACH,ECHaC,EAAa,MACxBC,EACAC,EAAe,GACfC,EAAa,KACK,CAClB,KAAM,CAAE,SAAAC,CAAS,EAAI,KAAM,QACyB,yBACpD,EAGAA,EAASH,EAAmB,CAC1B,MAAMF,EAAc,CACdI,GAAY,QAAQ,KAAK,0BAA0B,EACvDD,EAAM,QAAQH,CAAY,CAC5B,EAEA,WAAWA,EAAc,CACnBI,GAAY,QAAQ,IAAI,8BAA8B,EAC1DD,EAAM,aAAaH,CAAY,CACjC,EAEA,OAAOA,EAAc,CACfI,GAAY,QAAQ,IAAI,0BAA0B,EACtDD,EAAM,SAASH,CAAY,CAC7B,EAEA,MAAM,YAAYA,EAAc,CAC1B,MAAM,UAAU,cAAc,gBAAA,IAC5BI,GAAY,QAAQ,IAAI,gCAAgC,EAC5DD,EAAM,cAAcH,CAAY,EAEpC,EAEA,QAAQA,EAAc,CAChBI,GAAY,QAAQ,IAAI,2BAA2B,EACvDD,EAAM,UAAUH,CAAY,CAC9B,EAEA,SAAU,CACJI,GAAY,QAAQ,IAAI,2BAA2B,EACvDD,EAAM,UAAA,CACR,EAEA,MAAMG,EAAK,CACLF,GAAY,QAAQ,MAAM,qBAAsBE,CAAG,EACvDH,EAAM,QAAQG,CAAG,CACnB,CACF,CAAC,CACH,EC/CaC,EAAgB,MAC3BL,EACAM,IAEAP,EAAWQ,EAASP,CAAiB,EAAG,CACtC,MAAMF,EAAc,CAClBQ,EAAM,KAAK,QAASR,CAAY,CAClC,EAEA,WAAWA,EAAc,CACvBQ,EAAM,KAAK,aAAcR,CAAY,CACvC,EAEA,OAAOA,EAAc,CACnBQ,EAAM,KAAK,SAAUR,CAAY,CACnC,EAEA,YAAYA,EAAc,CACxBQ,EAAM,KAAK,cAAeR,CAAY,CACxC,EAEA,QAAQA,EAAc,CACpB,MAAMU,EAAM,yBACNC,EAAU,OAAO,aAAa,QAAQD,CAAG,GAAK,CAAC,EAErD,aAAa,QAAQA,GAAMC,EAAU,GAAG,SAAA,CAAU,EAClD,aAAa,WAAW,UAAU,EAElCH,EAAM,KAAK,UAAWR,CAAY,CACpC,EAEA,SAAU,CACRQ,EAAM,KAAK,SAAS,CACtB,EAEA,MAAMF,EAAK,CACTE,EAAM,KAAK,QAASF,CAAG,CACzB,CACF,CAAC,ECpCUM,EAAW,CACtBV,EACAW,EAAoB,KACX,CACT,GAAI,iBAAkB,OAGtB,MAAML,EAAkBM,IAExBC,EAAQC,EAAgBR,CAAK,EAE7BS,EAAU,SAAY,CACpB,GAAI,kBAAoB,EAAE,kBAAmB,WAAY,OAEzD,IAAIC,EAAa,GAGb,UAAU,cAAc,YAC1B,UAAU,cAAc,iBAAiB,mBAAoB,IAAM,CAC7DA,IAEJA,EAAa,GACb,OAAO,SAAS,OAAA,EAClB,CAAC,EAECL,GAAmBd,IAEvB,MAAMQ,EAAcL,EAAmBM,CAAK,CAC9C,CAAC,CACH,ECrCaW,EAAiB,IAAY,CACxCF,EAAU,IAAM,CAGd,GAFqB,OAAO,WAAW,4BAA4B,EAAE,QAEnD,CAChB,MAAMG,EAAO,SAAS,KAAK,cAAc,uBAAuB,EAEhE,GAAIA,EAAM,CACRA,EAAK,aACH,UACA,gGACF,EACA,MACF,CAEA,MAAMC,EAAe,SAAS,cAAc,MAAM,EAElDA,EAAa,KAAO,WACpBA,EAAa,QACX,iGAEF,SAAS,KAAK,YAAYA,CAAY,CACxC,CACF,CAAC,CACH"}