diff --git a/docs/.vitepress/components.d.ts b/docs/.vitepress/components.d.ts new file mode 100644 index 00000000..cd67af27 --- /dev/null +++ b/docs/.vitepress/components.d.ts @@ -0,0 +1,26 @@ +// generated by unplugin-vue-components +// We suggest you to commit this file into source control +// Read more: https://github.com/vuejs/vue-next/pull/3399 +import '@vue/runtime-core' + +declare module '@vue/runtime-core' { + export interface GlobalComponents { + CleanupOutdatedCaches: typeof import('./theme/components/CleanupOutdatedCaches.md')['default'] + ExamplesBehaviors: typeof import('./theme/components/ExamplesBehaviors.md')['default'] + ExamplesGenerateSW: typeof import('./theme/components/ExamplesGenerateSW.md')['default'] + ExamplesInjectManifest: typeof import('./theme/components/ExamplesInjectManifest.md')['default'] + GenerateSWCleanupOutdatedCaches: typeof import('./theme/components/GenerateSWCleanupOutdatedCaches.md')['default'] + GenerateSWSourceMap: typeof import('./theme/components/GenerateSWSourceMap.md')['default'] + HeuristicWorkboxWindow: typeof import('./theme/components/HeuristicWorkboxWindow.md')['default'] + InjectManifestCleanupOutdatedCaches: typeof import('./theme/components/InjectManifestCleanupOutdatedCaches.md')['default'] + InjectManifestSourceMap: typeof import('./theme/components/InjectManifestSourceMap.md')['default'] + PromptForUpdateImg: typeof import('./theme/components/PromptForUpdateImg.vue')['default'] + ReloadPrompt: typeof import('./theme/components/ReloadPrompt.vue')['default'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + RunExamples: typeof import('./theme/components/RunExamples.md')['default'] + SsrSsg: typeof import('./theme/components/SsrSsg.md')['default'] + } +} + +export {} diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 2afb937c..439ec14e 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,4 +1,5 @@ -import type { UserConfig } from 'vitepress' +import { defineConfig } from 'vitepress' +import { version } from '../../package.json' const Guide = [ { @@ -6,17 +7,29 @@ const Guide = [ link: '/guide/', }, { - text: 'Generate Service Worker', - link: '/guide/generate', + text: 'Register Service Worker', + link: '/guide/register-service-worker', }, { - text: 'Prompt for update', - link: '/guide/prompt-for-update', + text: 'Service Worker Precache', + link: '/guide/service-worker-precache', + }, + { + text: 'PWA Minimal Requirements', + link: '/guide/pwa-minimal-requirements', + }, + { + text: 'Service Worker Strategies And Behaviors', + link: '/guide/service-worker-strategies-and-behaviors', }, { text: 'Automatic reload', link: '/guide/auto-update', }, + { + text: 'Prompt for update', + link: '/guide/prompt-for-update', + }, { text: 'Advanced (injectManifest)', link: '/guide/inject-manifest', @@ -33,10 +46,6 @@ const Guide = [ text: 'Development', link: '/guide/development', }, - { - text: 'Testing Service Worker', - link: '/guide/testing', - }, { text: 'FAQ', link: '/guide/faq', @@ -103,6 +112,14 @@ const Frameworks = [ text: 'VitePress', link: '/frameworks/vitepress', }, + { + text: 'îles', + link: '/frameworks/iles', + }, + { + text: 'Astro (WIP)', + link: '/frameworks/astro', + }, ] const Examples = [ @@ -138,6 +155,14 @@ const Examples = [ text: 'VitePress', link: '/examples/vitepress', }, + { + text: 'îles', + link: '/examples/iles', + }, + { + text: 'Astro (WIP)', + link: '/examples/astro', + }, ] const Workbox = [ @@ -155,109 +180,138 @@ const Workbox = [ }, ] -const slidebars = [ - { - text: 'Guide', - children: Guide.map((e) => { - (e as any).useLinkText = `${e.text} | Guide` - return e - }), - }, - { - text: 'Frameworks', - children: Frameworks.map((e) => { - (e as any).useLinkText = `${e.text} | Frameworks` - return e - }), - }, - { - text: 'Examples', - children: Examples.map((e) => { - (e as any).useLinkText = `${e.text} | Examples` - return e - }), - }, - { - text: 'Deployment', - children: Deployment.map((e) => { - (e as any).useLinkText = `${e.text} | Deployment` - return e - }), - }, - { - text: 'Workbox', - children: Workbox.map((e) => { - (e as any).useLinkText = `${e.text} | Workbox` - return e - }), - }, -] +function prepareSidebar(idx: number) { + return [ + { + text: 'Guide', + collapsible: true, + collapsed: true, + items: Guide, + }, + { + text: 'Frameworks', + collapsible: true, + collapsed: true, + items: Frameworks, + }, + { + text: 'Examples', + collapsible: true, + collapsed: true, + items: Examples, + }, + { + text: 'Deploy', + collapsible: true, + collapsed: true, + items: Deployment, + }, + { + text: 'Workbox', + collapsible: true, + collapsed: true, + items: Workbox, + }, + ].map((entry, i) => { + if (idx === i) + entry.collapsed = false + + return entry + }) +} -const config: UserConfig = { +export default defineConfig({ + lang: 'en-US', title: 'Vite Plugin PWA', description: 'Zero-config PWA Framework-agnostic Plugin for Vite', - lang: 'en-US', head: [ ['meta', { name: 'theme-color', content: '#ffffff' }], ['link', { rel: 'icon', href: '/favicon.svg', type: 'image/svg+xml' }], ['link', { rel: 'alternate icon', href: '/favicon.ico', type: 'image/png', sizes: '16x16' }], ['link', { rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#ffffff' }], ['meta', { name: 'author', content: 'Anthony Fu' }], - ['meta', { name: 'keywords', content: 'react, pwa, vue, vitepress, preact, svelte, sveltekit, workbox, solidjs, vite, vite-plugin' }], + ['meta', { + name: 'keywords', + content: 'PWA, React, Vue, VitePress, Preact, Svelte, SvelteKit, workbox, SolidJS, Vite, vite-plugin, îles, Astro', + }], ['meta', { property: 'og:title', content: 'Vite Plugin PWA' }], ['meta', { property: 'og:description', content: 'Zero-config PWA Framework-agnostic Plugin for Vite' }], ['meta', { name: 'twitter:card', content: 'summary_large_image' }], ['meta', { name: 'twitter:creator', content: '@antfu7' }], ['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }], ], + lastUpdated: true, + markdown: { + theme: { + light: 'vitesse-light', + dark: 'vitesse-dark', + }, + }, themeConfig: { - logo: '/favicon.svg', - repo: 'antfu/vite-plugin-pwa', - docsDir: 'docs', - editLinks: true, - editLinkText: 'Edit this page', - lastUpdated: 'Last Updated', - /* - algolia: { - apiKey: 'todo@antfu: replace this', - indexName: 'vite-plugin-pwa', - searchParameters: { - // for translations maintainers: change the filter to your locale code (subdomain name) - facetFilters: ['language:en'] - } - }, - */ + // logo: '/favicon.svg', + editLink: { + pattern: 'https://github.com/antfu/vite-plugin-pwa/edit/main/docs/:path', + text: 'Suggest changes to this page', + }, + algolia: { + appId: 'TTO9T0AE3F', + apiKey: '71bd3d3c7274205843267bb1ccb6b1a8', + indexName: 'vite-plugin-pwa', + }, + socialLinks: [ + { icon: 'discord', link: 'https://chat.antfu.me' }, + { icon: 'github', link: 'https://github.com/antfu/vite-plugin-pwa' }, + ], + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2021-PRESENT Anthony Fu', + }, nav: [ { text: 'Guide', - items: Guide, + items: [ + { + text: 'Getting Started', + link: '/guide/', + }, + { + text: 'Frameworks', + link: '/frameworks/', + }, + { + text: 'Examples', + link: '/examples/', + }, + ], }, { - text: 'Frameworks', - items: Frameworks, + text: 'Deploy', + link: '/deployment/', }, { - text: 'Examples', - items: Examples, - }, - { - text: 'Deployment', - items: Deployment, + text: 'Workbox', + link: '/workbox/', }, { - text: 'Workbox', - items: Workbox, + text: `v${version}`, + items: [ + { + text: 'Release Notes', + link: 'https://github.com/antfu/vite-plugin-pwa/releases', + }, + { + text: 'Contributing', + link: 'https://github.com/antfu/vite-plugin-pwa/blob/main/CONTRIBUTING.md', + }, + ], }, ], sidebar: { - '/guide/': slidebars, - '/frameworks/': slidebars, - '/examples/': slidebars, - '/deployment/': slidebars, - '/workbox/': slidebars, - '/': slidebars, + '/guide/': prepareSidebar(0), + '/frameworks/': prepareSidebar(1), + '/examples/': prepareSidebar(2), + '/deployment/': prepareSidebar(3), + '/workbox/': prepareSidebar(4), }, }, -} - -export default config +}) diff --git a/docs/.vitepress/theme/Layout.vue b/docs/.vitepress/theme/Layout.vue deleted file mode 100644 index 5257fed8..00000000 --- a/docs/.vitepress/theme/Layout.vue +++ /dev/null @@ -1,137 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/NotFound.vue b/docs/.vitepress/theme/NotFound.vue deleted file mode 100644 index 2a1f38e3..00000000 --- a/docs/.vitepress/theme/NotFound.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/docs/.vitepress/theme/components/CleanupOutdatedCaches.md b/docs/.vitepress/theme/components/CleanupOutdatedCaches.md index 4bb9db69..c66ff3bf 100644 --- a/docs/.vitepress/theme/components/CleanupOutdatedCaches.md +++ b/docs/.vitepress/theme/components/CleanupOutdatedCaches.md @@ -1,5 +1,5 @@ -The service worker will store all your application assets in a browser cache (or set of caches). Every time you make -changes to your application and rebuild it, the `service worker` will be also rebuild, including in its cache manifest -all new modified assets, which will have their revision changed (all assets that have been modified will have a new -version). Assets that have not been modified will also be included in the service worker manifest cache, but their -revision will not change from the previous version. +The service worker will store all your application assets in a browser cache (or set of caches). Every time you make changes to your application and rebuild it, the `service worker` will be also rebuild, including in its precache manifest all new modified assets, which will have their revision changed (all assets that have been modified will have a new version). Assets that have not been modified will also be included in the service worker precache manifest, but their revision will not change from the previous one. + +::: tip Precache Manifest Entry Revision +The precache manifest entry revision is just a `MD5` hash of the asset content, if an asset is not modififed, the calculated hash will be always the same. +::: diff --git a/docs/.vitepress/theme/components/DarkModeSwitch.vue b/docs/.vitepress/theme/components/DarkModeSwitch.vue deleted file mode 100644 index 949a0db4..00000000 --- a/docs/.vitepress/theme/components/DarkModeSwitch.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/EditLink.vue b/docs/.vitepress/theme/components/EditLink.vue deleted file mode 100644 index 4c75402f..00000000 --- a/docs/.vitepress/theme/components/EditLink.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/GenerateSWCleanupOutdatedCaches.md b/docs/.vitepress/theme/components/GenerateSWCleanupOutdatedCaches.md index 8c97b10c..e02be1fa 100644 --- a/docs/.vitepress/theme/components/GenerateSWCleanupOutdatedCaches.md +++ b/docs/.vitepress/theme/components/GenerateSWCleanupOutdatedCaches.md @@ -1,11 +1,8 @@ -When the user installs the new version of the application, we will have on the service worker cache all new assets and -also the old ones. To delete old assets (from previous versions that are no longer necessary), you have to configure -an option on the `workbox` entry of the plugin configuration. +When the browser detects and installs the new version of your application, it will have in the cache storage all new assets and also the old ones. To delete old assets (from previous versions that are no longer necessary), you have to configure an option in the `workbox` entry of the plugin configuration. -When using the `generateSW` strategy, it is not necessary to activate it, the plugin will activate it by default. +When using the `generateSW` strategy, it is not necessary to configure it, the plugin will activate it by default. -We strongly recommend you to **NOT** deactivate the option. If you are curious, you can deactivate it using -this code on your plugin configuration: +We strongly recommend you to **NOT** deactivate the option. If you are curious, you can deactivate it using the following code in your plugin configuration: ```ts import { VitePWA } from 'vite-plugin-pwa' diff --git a/docs/.vitepress/theme/components/GenerateSWSourceMap.md b/docs/.vitepress/theme/components/GenerateSWSourceMap.md index 40331787..8c57b650 100644 --- a/docs/.vitepress/theme/components/GenerateSWSourceMap.md +++ b/docs/.vitepress/theme/components/GenerateSWSourceMap.md @@ -1,9 +1,6 @@ -Since plugin version `0.11.2`, your service worker's source map will not be generated as it uses the `build.sourcemap` -option from the Vite config, which by default is `false`. +Since plugin version `0.11.2`, your service worker's source map will not be generated as it uses the `build.sourcemap` option from the Vite config, which by default is `false`. -Your service worker source map will be generated when Vite's `build.sourcemap` configuration option has the value -`true`, `'online'` or `'hidden'`, and you have not configured the `workbox.sourcemap` option in the plugin -configuration. If you configure the `workbox.sourcemap` option, the plugin will not change that value. +Your service worker source map will be generated when Vite's `build.sourcemap` configuration option has the value `true`, `'online'` or `'hidden'`, and you have not configured the `workbox.sourcemap` option in the plugin configuration. If you configure the `workbox.sourcemap` option, the plugin will not change that value. If you want to generate the source map of your service worker, you can use this code: diff --git a/docs/.vitepress/theme/components/HeuristicWorkboxWindow.md b/docs/.vitepress/theme/components/HeuristicWorkboxWindow.md index 1eb2dd96..8cc540dc 100644 --- a/docs/.vitepress/theme/components/HeuristicWorkboxWindow.md +++ b/docs/.vitepress/theme/components/HeuristicWorkboxWindow.md @@ -1,6 +1,5 @@ -> Since `workbox-window` uses a time-based `heuristic` algorithm to handle service worker updates, if you -build your service worker and register it again, if the time between last registration and the new one is less than -1 minute, then, `workbox-window` will handle the `service worker update found` event as an external event, and so the -behavior could be strange (for example, if using `prompt`, instead showing the dialog for new content available, the -ready to work offline dialog will be shown; if using `autoUpdate`, the ready to work offline dialog will be shown and -shouldn't be shown). +::: warning +**This only applies when importing any of the virtual modules or using `workbox-window` module**. + +Since `workbox-window` uses a time-based `heuristic` algorithm to handle service worker updates, if you build your service worker and register it again, if the time between last registration and the new one is less than 1 minute, then, `workbox-window` will handle the `service worker update found` event as an external event, and so the behavior could be strange (for example, if using `prompt`, instead showing the dialog for new content available, the ready to work offline dialog will be shown; if using `autoUpdate`, the ready to work offline dialog will be shown and shouldn't be shown). +::: diff --git a/docs/.vitepress/theme/components/Home.vue b/docs/.vitepress/theme/components/Home.vue deleted file mode 100644 index 9eb605f5..00000000 --- a/docs/.vitepress/theme/components/Home.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/HomeFeatures.vue b/docs/.vitepress/theme/components/HomeFeatures.vue deleted file mode 100644 index 166868ba..00000000 --- a/docs/.vitepress/theme/components/HomeFeatures.vue +++ /dev/null @@ -1,147 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/HomeFooter.vue b/docs/.vitepress/theme/components/HomeFooter.vue deleted file mode 100644 index f7678b43..00000000 --- a/docs/.vitepress/theme/components/HomeFooter.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/HomeHero.vue b/docs/.vitepress/theme/components/HomeHero.vue deleted file mode 100644 index 228a8ef8..00000000 --- a/docs/.vitepress/theme/components/HomeHero.vue +++ /dev/null @@ -1,131 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/InjectManifestCleanupOutdatedCaches.md b/docs/.vitepress/theme/components/InjectManifestCleanupOutdatedCaches.md index 01297e16..0679bbf3 100644 --- a/docs/.vitepress/theme/components/InjectManifestCleanupOutdatedCaches.md +++ b/docs/.vitepress/theme/components/InjectManifestCleanupOutdatedCaches.md @@ -1,6 +1,4 @@ -When the user installs the new version of the application, we will have on the service worker cache all new assets and -also the old ones. To delete old assets (from previous versions that are no longer necessary), and since you are -building your own service worker, you will need to add the following code to your custom service worker: +When the user installs the new version of the application, we will have on the service worker cache all new assets and also the old ones. To delete old assets (from previous versions that are no longer necessary), and since you are building your own service worker, you will need to add the following code to your custom service worker: ```js import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching' diff --git a/docs/.vitepress/theme/components/InjectManifestSourceMap.md b/docs/.vitepress/theme/components/InjectManifestSourceMap.md index 6b4f22a0..7120ca00 100644 --- a/docs/.vitepress/theme/components/InjectManifestSourceMap.md +++ b/docs/.vitepress/theme/components/InjectManifestSourceMap.md @@ -1,5 +1,3 @@ -Since you are building your own service worker, this plugin will use Vite's `build.sourcemap` configuration option, -which default value is `false`, to generate the source map. +Since you are building your own service worker, this plugin will use Vite's `build.sourcemap` configuration option, which default value is `false`, to generate the source map. -If you want to generate the source map for your service worker, you will need to generate the source map for the -entire application. +If you want to generate the source map for your service worker, you will need to generate the source map for the entire application. diff --git a/docs/.vitepress/theme/components/MdListAnchor.vue b/docs/.vitepress/theme/components/MdListAnchor.vue deleted file mode 100644 index 9fbf3d98..00000000 --- a/docs/.vitepress/theme/components/MdListAnchor.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/NavBar.vue b/docs/.vitepress/theme/components/NavBar.vue deleted file mode 100644 index 28ea1017..00000000 --- a/docs/.vitepress/theme/components/NavBar.vue +++ /dev/null @@ -1,105 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/NavBarTitle.vue b/docs/.vitepress/theme/components/NavBarTitle.vue deleted file mode 100644 index 222114b4..00000000 --- a/docs/.vitepress/theme/components/NavBarTitle.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/NavDropdownLink.vue b/docs/.vitepress/theme/components/NavDropdownLink.vue deleted file mode 100644 index a4e42766..00000000 --- a/docs/.vitepress/theme/components/NavDropdownLink.vue +++ /dev/null @@ -1,130 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/NavDropdownLinkItem.vue b/docs/.vitepress/theme/components/NavDropdownLinkItem.vue deleted file mode 100644 index ad398502..00000000 --- a/docs/.vitepress/theme/components/NavDropdownLinkItem.vue +++ /dev/null @@ -1,74 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/NavLink.vue b/docs/.vitepress/theme/components/NavLink.vue deleted file mode 100644 index e16f81e3..00000000 --- a/docs/.vitepress/theme/components/NavLink.vue +++ /dev/null @@ -1,59 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/NavLinks.vue b/docs/.vitepress/theme/components/NavLinks.vue deleted file mode 100644 index 50b0cf3e..00000000 --- a/docs/.vitepress/theme/components/NavLinks.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/NextAndPrevLinks.vue b/docs/.vitepress/theme/components/NextAndPrevLinks.vue deleted file mode 100644 index 89124f5e..00000000 --- a/docs/.vitepress/theme/components/NextAndPrevLinks.vue +++ /dev/null @@ -1,102 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/Note.vue b/docs/.vitepress/theme/components/Note.vue deleted file mode 100644 index 0329e9f3..00000000 --- a/docs/.vitepress/theme/components/Note.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/docs/.vitepress/theme/components/Page.vue b/docs/.vitepress/theme/components/Page.vue deleted file mode 100644 index 9baf7109..00000000 --- a/docs/.vitepress/theme/components/Page.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/PageFooter.vue b/docs/.vitepress/theme/components/PageFooter.vue deleted file mode 100644 index 93f42b31..00000000 --- a/docs/.vitepress/theme/components/PageFooter.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/PluginVersion.vue b/docs/.vitepress/theme/components/PluginVersion.vue deleted file mode 100644 index c430d555..00000000 --- a/docs/.vitepress/theme/components/PluginVersion.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/PromptForUpdateImg.vue b/docs/.vitepress/theme/components/PromptForUpdateImg.vue index 454dcd07..0487dbf1 100644 --- a/docs/.vitepress/theme/components/PromptForUpdateImg.vue +++ b/docs/.vitepress/theme/components/PromptForUpdateImg.vue @@ -1,14 +1,14 @@ - diff --git a/docs/.vitepress/theme/components/PwaLogo.vue b/docs/.vitepress/theme/components/PwaLogo.vue deleted file mode 100644 index def9fe50..00000000 --- a/docs/.vitepress/theme/components/PwaLogo.vue +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/ReloadPrompt.vue b/docs/.vitepress/theme/components/ReloadPrompt.vue index bf5d9c61..de34f35e 100644 --- a/docs/.vitepress/theme/components/ReloadPrompt.vue +++ b/docs/.vitepress/theme/components/ReloadPrompt.vue @@ -1,33 +1,51 @@ diff --git a/docs/.vitepress/theme/components/RunExamples.md b/docs/.vitepress/theme/components/RunExamples.md index 116f2f3a..ad846ace 100644 --- a/docs/.vitepress/theme/components/RunExamples.md +++ b/docs/.vitepress/theme/components/RunExamples.md @@ -1,22 +1,19 @@ -To run the examples, execute the following script from your shell (from root folder), it will start a CLI where you -will select the framework and the pwa options: +::: warning +Before following the instructions below, read the [Contribution Guide](https://github.com/antfu/vite-plugin-pwa/blob/main/CONTRIBUTING.md). +::: -```shell -pnpm run examples -``` - - -
- Make sure you run pnpx build first +Make sure you install project dependencies, and build the repo on your local clone/fork: ```shell cd vite-plugin-pwa pnpm install pnpm run build -pnpm run examples ``` -If you don't do `pnpm run build` first, -you may see an error like, `failed to load config` or `Please verify that the package.json has a valid "main" entry`. +To run the examples, execute the following script from your shell (from root folder), it will start a CLI where you will select the framework and the pwa options: + +```shell +pnpm run examples +``` -
+If you don't run `pnpm build` first, you may see an error like, `failed to load config` or `Please verify that the package.json has a valid "main" entry`. diff --git a/docs/.vitepress/theme/components/SideBar.vue b/docs/.vitepress/theme/components/SideBar.vue deleted file mode 100644 index 12583d3a..00000000 --- a/docs/.vitepress/theme/components/SideBar.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/SideBarLink.ts b/docs/.vitepress/theme/components/SideBarLink.ts deleted file mode 100644 index 7d344bd2..00000000 --- a/docs/.vitepress/theme/components/SideBarLink.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { FunctionalComponent, VNode } from 'vue' -import { h } from 'vue' -import { useData, useRoute } from 'vitepress' -import type { DefaultTheme } from '../config' -import { isActive, joinUrl } from '../utils' - -export interface Header { - level: number - title: string - slug: string -} - -interface HeaderWithChildren extends Header { - children?: Header[] -} - -export const SideBarLink: FunctionalComponent<{ - item: DefaultTheme.SideBarItem -}> = (props) => { - const route = useRoute() - const { site } = useData() - - const headers = route.data.headers - const text = props.item.text - const link = resolveLink(site.value.base, props.item.link) - const children = (props.item as DefaultTheme.SideBarGroup).children - const active = isActive(route, props.item.link) - const childItems = createChildren(active, children, headers) - - return h('li', { class: 'sidebar-link' }, [ - h( - link ? 'a' : 'p', - { - class: { 'sidebar-link-item': true, active }, - href: link, - }, - text, - ), - childItems, - ]) -} - -function resolveLink(base: string, path?: string): string | undefined { - if (path === undefined) - return path - - // keep relative hash to the same page - if (path.startsWith('#')) - return path - - return joinUrl(base, path) -} - -function createChildren( - active: boolean, - children?: DefaultTheme.SideBarItem[], - headers?: Header[], -): VNode | null { - if (children && children.length > 0) { - return h( - 'ul', - { class: 'sidebar-links' }, - children.map((c) => { - return h(SideBarLink, { item: c }) - }), - ) - } - - return active && headers - ? createChildren(false, resolveHeaders(headers)) - : null -} - -function resolveHeaders(headers: Header[]): DefaultTheme.SideBarItem[] { - return mapHeaders(groupHeaders(headers)) -} - -function groupHeaders(headers: Header[]): HeaderWithChildren[] { - headers = headers.map(h => Object.assign({}, h)) - let lastH2: HeaderWithChildren - headers.forEach((h) => { - if (h.level === 2) - lastH2 = h - - else if (lastH2) - (lastH2.children || (lastH2.children = [])).push(h) - }) - return headers.filter(h => h.level === 2) -} - -function mapHeaders(headers: HeaderWithChildren[]): DefaultTheme.SideBarItem[] { - return headers.map(header => ({ - text: header.title, - link: `#${header.slug}`, - children: header.children ? mapHeaders(header.children) : undefined, - })) -} diff --git a/docs/.vitepress/theme/components/SideBarLinks.vue b/docs/.vitepress/theme/components/SideBarLinks.vue deleted file mode 100644 index a86e665c..00000000 --- a/docs/.vitepress/theme/components/SideBarLinks.vue +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/components/SsrSsg.md b/docs/.vitepress/theme/components/SsrSsg.md index de4b2939..3ab35d12 100644 --- a/docs/.vitepress/theme/components/SsrSsg.md +++ b/docs/.vitepress/theme/components/SsrSsg.md @@ -1,5 +1,4 @@ -If you are using `SSR/SSG`, you need to import `virtual:pwa-register` module using dynamic import and checking if -`window` is not `undefined`. +If you are using `SSR/SSG`, you need to import `virtual:pwa-register` module using dynamic import and checking if `window` is not `undefined`. You can register the service worker on `src/pwa.ts` module: @@ -16,4 +15,4 @@ if (typeof window !== 'undefined') import('./pwa') ``` -You can see the [FAQ](/guide/faq.md#navigator-window-is-undefined) entry for more info. +You can see the [FAQ](/guide/faq#navigator-window-is-undefined) entry for more info. diff --git a/docs/.vitepress/theme/components/ToggleSideBarButton.vue b/docs/.vitepress/theme/components/ToggleSideBarButton.vue deleted file mode 100644 index 43f3bfcf..00000000 --- a/docs/.vitepress/theme/components/ToggleSideBarButton.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - - - diff --git a/docs/.vitepress/theme/components/icons/ArrowLeft.vue b/docs/.vitepress/theme/components/icons/ArrowLeft.vue deleted file mode 100644 index 3f64f1a7..00000000 --- a/docs/.vitepress/theme/components/icons/ArrowLeft.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/docs/.vitepress/theme/components/icons/ArrowRight.vue b/docs/.vitepress/theme/components/icons/ArrowRight.vue deleted file mode 100644 index 19d2186c..00000000 --- a/docs/.vitepress/theme/components/icons/ArrowRight.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/docs/.vitepress/theme/components/icons/OutboundLink.vue b/docs/.vitepress/theme/components/icons/OutboundLink.vue deleted file mode 100644 index 4d74eeeb..00000000 --- a/docs/.vitepress/theme/components/icons/OutboundLink.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - diff --git a/docs/.vitepress/theme/composables/activeSidebarLink.ts b/docs/.vitepress/theme/composables/activeSidebarLink.ts deleted file mode 100644 index c8617b88..00000000 --- a/docs/.vitepress/theme/composables/activeSidebarLink.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { onMounted, onUnmounted, onUpdated } from 'vue' - -export function useActiveSidebarLinks() { - let rootActiveLink: HTMLAnchorElement | null = null - let activeLink: HTMLAnchorElement | null = null - - const onScroll = throttleAndDebounce(setActiveLink, 300) - - function setActiveLink(): void { - const sidebarLinks = getSidebarLinks() - const anchors = getAnchors(sidebarLinks) - - for (let i = 0; i < anchors.length; i++) { - const anchor = anchors[i] - const nextAnchor = anchors[i + 1] - - const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor) - - if (isActive) { - history.replaceState(null, document.title, hash || ' ') - activateLink(hash) - return - } - } - } - - function activateLink(hash: string | null): void { - deactiveLink(activeLink) - deactiveLink(rootActiveLink) - - activeLink = document.querySelector(`.sidebar a[href="${hash}"]`) - - if (!activeLink) - return - - activeLink.classList.add('active') - - // also add active class to parent h2 anchors - const rootLi = activeLink.closest('.sidebar-links > ul > li') - - if (rootLi && rootLi !== activeLink.parentElement) { - rootActiveLink = rootLi.querySelector('a') - rootActiveLink && rootActiveLink.classList.add('active') - } - else { - rootActiveLink = null - } - } - - function deactiveLink(link: HTMLAnchorElement | null): void { - link && link.classList.remove('active') - } - - onMounted(() => { - setActiveLink() - window.addEventListener('scroll', onScroll) - }) - - onUpdated(() => { - // sidebar update means a route change - activateLink(decodeURIComponent(location.hash)) - }) - - onUnmounted(() => { - window.removeEventListener('scroll', onScroll) - }) -} - -function getSidebarLinks(): HTMLAnchorElement[] { - return [].slice.call( - document.querySelectorAll('.sidebar a.sidebar-link-item'), - ) -} - -function getAnchors(sidebarLinks: HTMLAnchorElement[]): HTMLAnchorElement[] { - return [].slice - .call(document.querySelectorAll('.header-anchor')) - .filter((anchor: HTMLAnchorElement) => - sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash), - ) as HTMLAnchorElement[] -} - -function getPageOffset(): number { - return (document.querySelector('.nav-bar') as HTMLElement).offsetHeight -} - -function getAnchorTop(anchor: HTMLAnchorElement): number { - const pageOffset = getPageOffset() - - return anchor.parentElement!.offsetTop - pageOffset - 15 -} - -function isAnchorActive( - index: number, - anchor: HTMLAnchorElement, - nextAnchor: HTMLAnchorElement, -): [boolean, string | null] { - const scrollTop = window.scrollY - - if (index === 0 && scrollTop === 0) - return [true, null] - - if (scrollTop < getAnchorTop(anchor)) - return [false, null] - - if (!nextAnchor || scrollTop < getAnchorTop(nextAnchor)) - return [true, decodeURIComponent(anchor.hash)] - - return [false, null] -} - -function throttleAndDebounce(fn: () => void, delay: number): () => void { - let timeout: NodeJS.Timeout - let called = false - - return () => { - if (timeout) - clearTimeout(timeout) - - if (!called) { - fn() - called = true - setTimeout(() => { - called = false - }, delay) - } - else { - timeout = setTimeout(fn, delay) - } - } -} diff --git a/docs/.vitepress/theme/composables/dark.ts b/docs/.vitepress/theme/composables/dark.ts deleted file mode 100644 index 5976a5a6..00000000 --- a/docs/.vitepress/theme/composables/dark.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { useDark } from '@vueuse/core' - -export const isDark = useDark() diff --git a/docs/.vitepress/theme/composables/editLink.ts b/docs/.vitepress/theme/composables/editLink.ts deleted file mode 100644 index ed37480e..00000000 --- a/docs/.vitepress/theme/composables/editLink.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { computed } from 'vue' -import { useData } from 'vitepress' -import { endingSlashRE, isExternal, isNullish } from '../utils' - -const bitbucketRE = /bitbucket.org/ - -export function useEditLink() { - const { site, page } = useData() - - const url = computed(() => { - const showEditLink = isNullish(page.value.frontmatter.editLink) - ? site.value.themeConfig.editLinks - : page.value.frontmatter.editLink - - const { - repo, - docsDir = '', - docsBranch = 'main', - docsRepo = repo, - } = site.value.themeConfig - - const { relativePath } = page.value - - if (!showEditLink || !relativePath || !repo) - return null - - return createUrl(repo, docsRepo, docsDir, docsBranch, relativePath) - }) - - const text = computed(() => { - return site.value.themeConfig.editLinkText || 'Edit this page' - }) - - return { - url, - text, - } -} - -function createUrl( - repo: string, - docsRepo: string, - docsDir: string, - docsBranch: string, - path: string, -): string { - return bitbucketRE.test(repo) - ? createBitbucketUrl(repo, docsRepo, docsDir, docsBranch, path) - : createGitHubUrl(repo, docsRepo, docsDir, docsBranch, path) -} - -function createGitHubUrl( - repo: string, - docsRepo: string, - docsDir: string, - docsBranch: string, - path: string, -): string { - const base = isExternal(docsRepo) - ? docsRepo - : `https://github.com/${docsRepo}` - - return ( - `${base.replace(endingSlashRE, '') - }/edit` - + `/${docsBranch}/${ - docsDir ? `${docsDir.replace(endingSlashRE, '')}/` : '' - }${path}` - ) -} - -function createBitbucketUrl( - repo: string, - docsRepo: string, - docsDir: string, - docsBranch: string, - path: string, -): string { - const base = isExternal(docsRepo) ? docsRepo : repo - - return ( - `${base.replace(endingSlashRE, '') - }/src` - + `/${docsBranch}/${ - docsDir ? `${docsDir.replace(endingSlashRE, '')}/` : '' - }${path - }?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default` - ) -} diff --git a/docs/.vitepress/theme/composables/nav.ts b/docs/.vitepress/theme/composables/nav.ts deleted file mode 100644 index 4aad3512..00000000 --- a/docs/.vitepress/theme/composables/nav.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { computed } from 'vue' -import { inBrowser, useData, useRoute } from 'vitepress' -import type { DefaultTheme } from '../config' - -export function useLocaleLinks() { - const route = useRoute() - const { site } = useData() - - return computed(() => { - const theme = site.value.themeConfig as DefaultTheme.Config - const locales = theme.locales - - if (!locales) - return null - - const localeKeys = Object.keys(locales) - - if (localeKeys.length <= 1) - return null - - // handle site base - const siteBase = inBrowser ? site.value.base : '/' - - const siteBaseWithoutSuffix = siteBase.endsWith('/') - ? siteBase.slice(0, -1) - : siteBase - - // remove site base in browser env - const routerPath = route.path.slice(siteBaseWithoutSuffix.length) - - const currentLangBase = localeKeys.find((key) => { - return key === '/' ? false : routerPath.startsWith(key) - }) - - const currentContentPath = currentLangBase - ? routerPath.substring(currentLangBase.length - 1) - : routerPath - - const candidates = localeKeys.map((v) => { - const localePath = v.endsWith('/') ? v.slice(0, -1) : v - - return { - text: locales[v].label, - link: `${localePath}${currentContentPath}`, - } - }) - - const currentLangKey = currentLangBase || '/' - - const selectText = locales[currentLangKey].selectText - ? locales[currentLangKey].selectText - : 'Languages' - - return { - text: selectText, - items: candidates, - } as DefaultTheme.NavItemWithChildren - }) -} diff --git a/docs/.vitepress/theme/composables/navLink.ts b/docs/.vitepress/theme/composables/navLink.ts deleted file mode 100644 index e9d0a89e..00000000 --- a/docs/.vitepress/theme/composables/navLink.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { Ref } from 'vue' -import { computed } from 'vue' -import { useRoute, withBase } from 'vitepress' -import type { DefaultTheme } from '../config' -import { isExternal as isExternalCheck } from '../utils' - -export function useNavLink(item: Ref) { - const route = useRoute() - - const isExternal = isExternalCheck(item.value.link) - - const props = computed(() => { - const link = interpret(item.value.link) - const routePath = normalizePath(`/${route.data.relativePath}`) - - let active = false - if (item.value.activeMatch) { - active = new RegExp(item.value.activeMatch).test(routePath) - } - else { - const itemPath = normalizePath(withBase(link)) - active - = itemPath === '/' - ? itemPath === routePath - : routePath.startsWith(itemPath) - // fix /frameworks/sveltekit and /frameworks/svelte - if (routePath === '/frameworks/sveltekit' && itemPath === '/frameworks/svelte' && active) - active = false - // fix /examples/sveltekit and /examples/svelte - if (routePath === '/examples/sveltekit' && itemPath === '/examples/svelte' && active) - active = false - } - - return { - 'class': { - active, - isExternal, - }, - 'href': isExternal ? link : withBase(link), - 'target': item.value.target || isExternal ? '_blank' : null, - 'rel': item.value.rel || isExternal ? 'noopener noreferrer' : null, - 'aria-label': item.value.ariaLabel, - } - }) - - return { - props, - isExternal, - } -} - -function interpret(path = '') { - return path - .replace(/{{pathname}}/, typeof window === 'undefined' ? '/' : location.pathname) -} - -function normalizePath(path: string): string { - return path - .replace(/#.*$/, '') - .replace(/\?.*$/, '') - .replace(/\.(html|md)$/, '') - .replace(/\/index$/, '/') -} diff --git a/docs/.vitepress/theme/composables/nextAndPrevLinks.ts b/docs/.vitepress/theme/composables/nextAndPrevLinks.ts deleted file mode 100644 index 39d52864..00000000 --- a/docs/.vitepress/theme/composables/nextAndPrevLinks.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { computed } from 'vue' -import { useData } from 'vitepress' -import { ensureStartingSlash, isArray, removeExtention } from '../utils' -import { getFlatSideBarLinks, getSideBarConfig } from '../support/sideBar' - -export function useNextAndPrevLinks() { - const { page, theme } = useData() - - const path = computed(() => { - return removeExtention(ensureStartingSlash(page.value.relativePath)) - }) - - const candidates = computed(() => { - const config = getSideBarConfig(theme.value.sidebar, path.value) - - return isArray(config) ? getFlatSideBarLinks(config) : [] - }) - - const index = computed(() => { - return candidates.value.findIndex((item) => { - return item.link === path.value - }) - }) - - const next = computed(() => { - if ( - theme.value.nextLinks !== false - && index.value > -1 - && index.value < candidates.value.length - 1 - ) - return candidates.value[index.value + 1] - - return undefined - }) - - const prev = computed(() => { - if (theme.value.prevLinks !== false && index.value > 0) - return candidates.value[index.value - 1] - - return undefined - }) - - const hasLinks = computed(() => !!next.value || !!prev.value) - - return { - next, - prev, - hasLinks, - } -} diff --git a/docs/.vitepress/theme/composables/repo.ts b/docs/.vitepress/theme/composables/repo.ts deleted file mode 100644 index e14e686f..00000000 --- a/docs/.vitepress/theme/composables/repo.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { computed } from 'vue' -import { useData } from 'vitepress' -import type { DefaultTheme } from '../config' - -export const platforms = ['GitHub'].map((platform) => { - return [platform, new RegExp(platform, 'i')] as const -}) - -export function useRepo() { - const { site } = useData() - - return computed(() => { - const theme = site.value.themeConfig as DefaultTheme.Config - const name = theme.docsRepo || theme.repo - - if (!name) - return null - - const link = getRepoUrl(name) - const text = getRepoText(link, theme.repoLabel) - - return { text, link } - }) -} - -function getRepoUrl(repo: string): string { - // if the full url is not provided, default to GitHub repo - return /^https?:/.test(repo) ? repo : `https://github.com/${repo}` -} - -function getRepoText(url: string, text?: string): string { - if (text) - return text - - // if no label is provided, deduce it from the repo url - const hosts = url.match(/^https?:\/\/[^/]+/) - - if (!hosts) - return 'Source' - - const platform = platforms.find(([, re]) => re.test(hosts[0])) - - if (platform && platform[0]) - return platform[0] - - return 'Source' -} diff --git a/docs/.vitepress/theme/composables/sideBar.ts b/docs/.vitepress/theme/composables/sideBar.ts deleted file mode 100644 index d025bfb0..00000000 --- a/docs/.vitepress/theme/composables/sideBar.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { computed } from 'vue' -import { useData, useRoute } from 'vitepress' -// import { Header } from '/@types/shared' -import { getSideBarConfig } from '../support/sideBar' -import type { DefaultTheme } from '../config' -import { useActiveSidebarLinks } from './activeSidebarLink' - -export function useSideBar() { - const route = useRoute() - const { site } = useData() - - useActiveSidebarLinks() - - return computed(() => { - // at first, we'll check if we can find the sidebar setting in frontmatter. - const headers = route.data.headers - const frontSidebar = route.data.frontmatter.sidebar - const sidebarDepth = route.data.frontmatter.sidebarDepth - - // if it's `false`, we'll just return an empty array here. - if (frontSidebar === false) - return [] - - // if it's `atuo`, render headers of the current page - if (frontSidebar === 'auto') - return resolveAutoSidebar(headers, sidebarDepth) - - // now, there's no sidebar setting at frontmatter; let's see the configs - const themeSidebar = getSideBarConfig( - site.value.themeConfig.sidebar, - route.path, - ) - - if (themeSidebar === false) - return [] - - if (themeSidebar === 'auto') - return resolveAutoSidebar(headers, sidebarDepth) - - return themeSidebar - }) -} - -function resolveAutoSidebar( - headers: any[], - depth: number, -): DefaultTheme.SideBarItem[] { - const ret: DefaultTheme.SideBarItem[] = [] - - if (headers === undefined) - return [] - - let lastH2: DefaultTheme.SideBarItem | undefined - headers.forEach(({ level, title, slug }) => { - if (level - 1 > depth) - return - - const item: DefaultTheme.SideBarItem = { - text: title, - link: `#${slug}`, - } - if (level === 2) { - lastH2 = item - ret.push(item) - } - else if (lastH2) { - ((lastH2 as any).children || ((lastH2 as any).children = [])).push(item) - } - }) - - return ret -} diff --git a/docs/.vitepress/theme/composables/url.ts b/docs/.vitepress/theme/composables/url.ts deleted file mode 100644 index 72a97bba..00000000 --- a/docs/.vitepress/theme/composables/url.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { /* useData, */ withBase } from 'vitepress' - -// todo@userquin: to be removed: just use withBase from vitepress -export function useUrl() { - // const { site } = useData() - - // function withBase(path: string): string { - // if (!path) - // return '' - // return joinPath(site.value.base, path) - // } - // - return { - withBase, - } -} diff --git a/docs/.vitepress/theme/config.ts b/docs/.vitepress/theme/config.ts deleted file mode 100644 index 7b5ec663..00000000 --- a/docs/.vitepress/theme/config.ts +++ /dev/null @@ -1,126 +0,0 @@ -export namespace DefaultTheme { - export interface Config { - logo?: string - nav?: NavItem[] | false - sidebar?: SideBarConfig | MultiSideBarConfig - - /** - * GitHub repository following the format /. - * - * @example `"vuejs/vue-next"` - */ - repo?: string - - /** - * Customize the header label. Defaults to GitHub/Gitlab/Bitbucket - * depending on the provided repo. - * - * @exampe `"Contribute!"` - */ - repoLabel?: string - - /** - * If your docs are in a different repository from your main project. - * - * @example `"vuejs/docs-next"` - */ - docsRepo?: string - - /** - * If your docs are not at the root of the repo. - * - * @example `"docs"` - */ - docsDir?: string - - /** - * If your docs are in a different branch. Defaults to `main`. - * - * @example `"next"` - */ - docsBranch?: string - - /** - * Enable links to edit pages at the bottom of the page. - */ - editLinks?: boolean - - /** - * Custom text for edit link. Defaults to "Edit this page". - */ - editLinkText?: string - - /** - * Show last updated time at the bottom of the page. Defaults to `false`. - * If given a string, it will be displayed as a prefix (default value: - * "Last Updated"). - */ - lastUpdated?: string | boolean - - prevLinks?: boolean - nextLinks?: boolean - - locales?: Record> - } - - // navbar -------------------------------------------------------------------- - - export type NavItem = NavItemWithLink | NavItemWithChildren - - export interface NavItemBase { - text: string - target?: string - rel?: string - ariaLabel?: string - activeMatch?: string - } - - export interface NavItemWithLink extends NavItemBase { - link: string - } - - export interface NavItemWithChildren extends NavItemBase { - items: NavItemWithLink[] - } - - // sidebar ------------------------------------------------------------------- - - export type SideBarConfig = SideBarItem[] | 'auto' | false - - export type MultiSideBarConfig = Record - - export type SideBarItem = SideBarLink | SideBarGroup - - export interface SideBarLink { - text: string - link: string - useLinkText?: string - } - - export interface SideBarGroup { - text: string - link?: string - useLinkText?: string - - /** - * @default false - */ - collapsable?: boolean - - children: SideBarItem[] - } - - // locales ------------------------------------------------------------------- - - export interface LocaleConfig { - /** - * Text for the language dropdown. - */ - selectText?: string - - /** - * Label for this locale in the language dropdown. - */ - label?: string - } -} diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 550a0504..b4f64d27 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,18 +1,16 @@ -import 'vue-global-api' - -import Layout from './Layout.vue' -import NotFound from './NotFound.vue' - +import { h } from 'vue' +import Theme from 'vitepress/theme' +import './styles/main.css' import './styles/vars.css' -import './styles/layout.css' -import './styles/code.css' -import './styles/sidebar-links.css' +import 'uno.css' +import ReloadPrompt from './components/ReloadPrompt.vue' -import 'virtual:windi.css' - -const theme = { - Layout, - NotFound, +export default { + ...Theme, + Layout() { + return h(Theme.Layout, null, { + // TODO: review this when https://github.com/vuejs/vitepress/issues/760 included + 'layout-bottom': () => h(ReloadPrompt), + }) + }, } - -export default theme diff --git a/docs/.vitepress/theme/shim.d.ts b/docs/.vitepress/theme/shim.d.ts deleted file mode 100644 index 2322043b..00000000 --- a/docs/.vitepress/theme/shim.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -declare const __VP_HASH_MAP__: Record - -declare module '*.vue' { - import type { ComponentOptions } from 'vue' - const comp: ComponentOptions - export default comp -} - -declare module '@siteData' { - const data: string - export default data -} diff --git a/docs/.vitepress/theme/styles/code.css b/docs/.vitepress/theme/styles/code.css deleted file mode 100644 index ad669d23..00000000 --- a/docs/.vitepress/theme/styles/code.css +++ /dev/null @@ -1,107 +0,0 @@ -/* https://github.com/antfu/prism-theme-vars */ -@import 'prism-theme-vars/base.css'; -@import 'prism-theme-vars/marker.css'; - -:root { - --prism-font-family: var(--font-family-mono); - --prism-font-size: 0.85rem; - --prism-marker-opacity: 0; -} - -html:not(.dark) { - --prism-foreground: #393a34; - --prism-background: #fafafa; - --prism-inline-background: #f5f5f5; - --prism-comment: #a0ada0; - --prism-string: #a56051; - --prism-literal: #2f8a89; - --prism-number: #296aa3; - --prism-keyword: #1c6b48; - --prism-function: #6c7834; - --prism-boolean: #1c6b48; - --prism-constant: #a65e2b; - --prism-deleted: #a14f55; - --prism-class: #2993a3; - --prism-builtin: #ab5959; - --prism-property: #926a41; - --prism-namespace: #b05a78; - --prism-punctuation: #8e8f8b; - --prism-decorator: #bd8f8f; - --prism-regex: #ab5e3f; - --prism-json-property: #698c96; -} - -html.dark { - --prism-scheme: dark; - --prism-foreground: #d4cfbf; - --prism-background: #181818; - --prism-comment: #758575; - --prism-string: #d48372; - --prism-literal: #429988; - --prism-keyword: #4d9375; - --prism-boolean: #1c6b48; - --prism-number: #6394bf; - --prism-variable: #c2b36e; - --prism-function: #a1b567; - --prism-deleted: #bc6066; - --prism-class: #54b1bf; - --prism-builtin: #e0a569; - --prism-property: #dd8e6e; - --prism-namespace: #db889a; - --prism-punctuation: #858585; - --prism-decorator: #bd8f8f; - --prism-regex: #ab5e3f; - --prism-json-property: #6b8b9e; - --prism-line-number: #888888; - --prism-line-number-gutter: #eeeeee; - --prism-line-highlight-background: #444444; - --prism-selection-background: #444444; - --prism-inline-background: theme('colors.dark.300'); -} - -/* Overrides */ - -:not(pre) > code { - background: var(--prism-inline-background); - padding: 1px 6px; - border-radius: 3px; -} - -a > code { - color: var(--c-brand-dark); -} - -div[class*='language-'] { - position: relative; -} - -div[class*='language-'] pre { - margin: 0; - z-index: 1; -} - -div[class*='language-'] code { - font-size: var(--prism-font-size); - font-family: var(--prism-font-family); -} - -/* Line highlighting */ - -.highlight-lines { - position: absolute; - top: 0; - bottom: 0; - left: 0; - padding: var(--prism-block-padding-y) 0; - width: 100%; - line-height: var(--prism-line-height); - font-family: var(--prism-font-family); - font-size: var(--prism-font-size); - user-select: none; - overflow: hidden; - z-index: -1; -} - -.highlight-lines .highlighted { - background-color: var(--prism-line-highlight-background); -} diff --git a/docs/.vitepress/theme/styles/layout.css b/docs/.vitepress/theme/styles/layout.css deleted file mode 100644 index 68764792..00000000 --- a/docs/.vitepress/theme/styles/layout.css +++ /dev/null @@ -1,302 +0,0 @@ -*, -::before, -::after { - box-sizing: border-box; -} - -* { - scrollbar-color: var(--c-divider-light) var(--c-bg); -} -::-webkit-scrollbar { - width: var(--scrollbar-width); -} -::-webkit-scrollbar:horizontal { - height: var(--scrollbar-width); -} -::-webkit-scrollbar-track { - background: var(--c-bg); - border-radius: 10px; -} -::-webkit-scrollbar-thumb { - background: var(--c-divider-light); - border-radius: 10px; -} -::-webkit-scrollbar-thumb:hover { - background: var(--c-divider-dark); -} - -html { - line-height: 1.4; - font-size: 16px; - -webkit-text-size-adjust: 100%; -} - -body { - margin: 0; - width: 100%; - min-width: 320px; - min-height: 100vh; - line-height: 1.4; - font-family: var(--font-family-base); - font-size: 16px; - font-weight: 400; - color: var(--c-text); - background-color: var(--c-bg); - direction: ltr; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - overflow-x: hidden; -} - -main { - display: block; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 0; - line-height: 1.25; -} - -h1, -h2, -h3, -h4, -h5, -h6, -strong, -b { - font-weight: 600; -} - -h1:hover .header-anchor, -h1:focus .header-anchor, -h2:hover .header-anchor, -h2:focus .header-anchor, -h3:hover .header-anchor, -h3:focus .header-anchor, -h4:hover .header-anchor, -h4:focus .header-anchor, -h5:hover .header-anchor, -h5:focus .header-anchor, -h6:hover .header-anchor, -h6:focus .header-anchor { - opacity: 1; -} - -h1 { - margin-top: 1.5rem; - font-size: 1.9rem; -} - -@media screen and (min-width: 420px) { - h1 { - font-size: 2.2rem; - } -} - -h2 { - margin-top: 2.25rem; - margin-bottom: 1.25rem; - border-bottom: 1px solid var(--c-divider); - padding-bottom: 0.3rem; - line-height: 1.25; - font-size: 1.65rem; - /* overflow-x: auto; */ -} - -h2 + h3 { - margin-top: 1.5rem; -} - -h3 { - margin-top: 2rem; - font-size: 1.35rem; -} - -h4 { - font-size: 1.15rem; -} - -p, -ol, -ul { - margin: 1rem 0; - line-height: 1.7; -} - -a, -area, -button, -[role="button"], -input, -label, -select, -summary, -textarea { - touch-action: manipulation; -} - -a { - text-decoration: none; - font-weight: bolder; - color: var(--c-brand-active); -} - -a:hover { - text-decoration: underline; -} - -a.header-anchor { - float: left; - margin-top: 0.125em; - margin-left: -0.87em; - padding-right: 0.23em; - font-size: 0.85em; - opacity: 0; -} - -a.header-anchor:hover, -a.header-anchor:focus { - text-decoration: none; -} - -figure { - margin: 0; -} - -img { - max-width: 100%; -} - -ul, -ol { - padding-left: 1.25em; -} - -li > ul, -li > ol { - margin: 0; -} - -table { - display: block; - border-collapse: collapse; - margin: 1rem 0; - overflow-x: auto; -} - -tr { - border-top: 1px solid var(--c-divider-light); -} - -tr:nth-child(2n) { - background-color: var(--code-inline-bg-color); -} - -th, -td { - border: 1px solid var(--c-divider-light); - padding: 0.6em 1em; -} - -blockquote { - margin: 1rem 0; - border-left: 0.2rem solid #dfe2e5; - padding: 0.25rem 0.25rem 0.25rem 1rem; - font-size: 1rem; - color: var(--c-text); - @apply bg-gray-400 bg-opacity-10; -} - -blockquote > p { - margin: 0; -} - -form { - margin: 0; -} - -.theme.sidebar-open .sidebar-mask { - display: block; -} - -.theme.no-navbar > h1, -.theme.no-navbar > h2, -.theme.no-navbar > h3, -.theme.no-navbar > h4, -.theme.no-navbar > h5, -.theme.no-navbar > h6 { - margin-top: 1.5rem; - padding-top: 0; -} - -.theme.no-navbar aside { - top: 0; -} - -@media screen and (min-width: 780px) { - .theme.no-sidebar aside { - display: none; - } - - .theme.no-sidebar main { - margin-left: 0; - } -} - -.sidebar-mask { - position: fixed; - z-index: 2; - display: none; - width: 100vw; - height: 100vh; -} - -.icon-button { - display: flex; - font-size: 1.05rem; - border: 0; - /*outline: none;*/ - background: none; - color: var(--c-text); - opacity: 0.8; - cursor: pointer; -} -.icon-button:hover { - opacity: 1; -} -.icon-button svg { - margin: auto; -} -.external-link { - font-size: 0.95rem; - opacity: 0.7; -} - -.version-img { - text-align: center; - -} - -html.dark .version-img { - text-align: center; -} - -html.dark .prompt-img img { - filter: invert(93%); -} - -details summary { - cursor: pointer; -} -details summary strong { - color: var(--c-brand-active); -} - diff --git a/docs/.vitepress/theme/styles/main.css b/docs/.vitepress/theme/styles/main.css new file mode 100644 index 00000000..13aa48af --- /dev/null +++ b/docs/.vitepress/theme/styles/main.css @@ -0,0 +1,90 @@ +.dark [img-light], .dark .logo[light-logo] { + display: none; +} + +html:not(.dark) [img-dark], html:not(.dark) .logo[dark-logo] { + display: none; +} + +/* Overrides */ + +.VPSocialLink { + transform: scale(0.9); +} + +.vp-doc th, +.vp-doc td { + padding: 6px 10px; + border: 1px solid #8882; +} + +/* h3 breaks SEO => replaced with h2 with the same size */ +.home-content h2 { + margin-top: 2rem; + font-size: 1.35rem; + border-bottom: none; + margin-bottom: 0; +} + +img.resizable-img { + width: unset; + height: unset; +} + +.dark .prompt-img { + filter: invert(86%); +} + +.tagline { + white-space: pre-wrap; +} + +details > summary:hover { + cursor: pointer; +} +/* remove the gray color from code block inside details > summary */ +.vp-doc .custom-block div[class*=language-] code, +.vp-doc details > summary + div[class*='language-'] > pre > code { + --vp-code-block-bg: transparent; +} + +.pwa-toast { + --c-divider: var(--vp-c-divider-light); +} +.pwa-toast .pwa-refresh { + border-color: var(--vp-button-brand-border); + color: var(--vp-button-brand-text); + background-color: var(--vp-button-brand-bg); +} +.pwa-toast .pwa-refresh:hover { + border-color: var(--vp-button-brand-hover-border); + color: var(--vp-button-brand-hover-text); + background-color: var(--vp-button-brand-hover-bg); +} +.pwa-toast .pwa-refresh:active { + border-color: var(--vp-button-brand-active-border); + color: var(--vp-button-brand-active-text); + background-color: var(--vp-button-brand-active-bg); +} +.pwa-toast .pwa-cancel { + border-color: var(--vp-button-alt-border); + color: var(--vp-button-alt-text); + background-color: var(--vp-button-alt-bg); +} +.pwa-toast .pwa-cancel:hover { + border-color: var(--vp-button-alt-hover-border); + color: var(--vp-button-alt-hover-text); + background-color: var(--vp-button-alt-hover-bg); +} +.pwa-toast .pwa-cancel:active { + border-color: var(--vp-button-alt-active-border); + color: var(--vp-button-alt-active-text); + background-color: var(--vp-button-alt-active-bg); +} +.dark .pwa-toast { + --pwa-divider: var(--vp-c-divider-dark-1); +} + +.vp-doc :not(pre) > code { + padding: 1px 6px; +} diff --git a/docs/.vitepress/theme/styles/sidebar-links.css b/docs/.vitepress/theme/styles/sidebar-links.css deleted file mode 100644 index 74851e9a..00000000 --- a/docs/.vitepress/theme/styles/sidebar-links.css +++ /dev/null @@ -1,102 +0,0 @@ -.sidebar-links { - margin: 0; - padding: 0; - list-style: none; -} - -.sidebar-link-item { - display: block; - margin: 0; - border-left: .25rem solid transparent; - color: var(--c-text); -} - -a.sidebar-link-item:hover { - text-decoration: none; - color: var(--c-text); -} - -a.sidebar-link-item.active { - color: var(--c-text); -} - -.sidebar > .sidebar-links { - padding: .75rem 0 5rem; -} - -@media (min-width: 780px) { - .sidebar > .sidebar-links { - padding: 1.5rem 0; - } -} - -.sidebar > .sidebar-links > .sidebar-link + .sidebar-link { - padding-top: .5rem; -} - -@media (min-width: 780px) { - .sidebar > .sidebar-links > .sidebar-link + .sidebar-link { - padding-top: 1.25rem; - } -} - -.sidebar > .sidebar-links > .sidebar-link > .sidebar-link-item { - padding: .35rem 1.5rem .35rem 1.25rem; - font-size: 1.1rem; - font-weight: 700; -} - -.sidebar > .sidebar-links > .sidebar-link > a.sidebar-link-item.active { - border-left-color: var(--c-brand-dark); - font-weight: 600; -} - -.sidebar > .sidebar-links > .sidebar-link > .sidebar-links > .sidebar-link > .sidebar-link-item { - display: block; - padding: .35rem 1.5rem .35rem 2rem; - line-height: 1.4; - font-size: 1rem; - font-weight: 400; -} - -.sidebar > .sidebar-links > .sidebar-link > .sidebar-links > .sidebar-link > a.sidebar-link-item.active { - border-left-color: var(--c-brand-dark); - font-weight: 600; -} - -.sidebar > -.sidebar-links > -.sidebar-link > -.sidebar-links > -.sidebar-link > -.sidebar-links > -.sidebar-link > -.sidebar-link-item { - display: block; - padding: .3rem 1.5rem .3rem 3rem; - line-height: 1.4; - font-size: .9rem; - font-weight: 400; -} - -.sidebar > -.sidebar-links > -.sidebar-link > -.sidebar-links > -.sidebar-link > -.sidebar-links > -.sidebar-link > -.sidebar-links > -.sidebar-link > -.sidebar-link-item { - display: block; - padding: .3rem 1.5rem .3rem 4rem; - line-height: 1.4; - font-size: .9rem; - font-weight: 400; -} -/* -a.sidebar-link-item { - font-family: monospace; - letter-spacing: -0.5px; -} */ diff --git a/docs/.vitepress/theme/styles/vars.css b/docs/.vitepress/theme/styles/vars.css index 01de04cd..b3636e91 100644 --- a/docs/.vitepress/theme/styles/vars.css +++ b/docs/.vitepress/theme/styles/vars.css @@ -1,112 +1,78 @@ -/** Base Styles */ -:root { - - /** - * Colors - * --------------------------------------------------------------------- */ - --c-bg: #fff; - --c-bg-semi: rgba(255,255,255,0.8); - --c-bg-secondary: #f3f5f7; - - --c-white: #ffffff; - --c-black: #000000; - - --c-divider-light: rgba(60, 60, 67, .12); - --c-divider-dark: rgba(84, 84, 88, .48); - - --c-text-light-1: #2c3e50; - --c-text-light-2: #476582; - --c-text-light-3: #90a4b7; - - --c-brand: #2e859c; - --c-brand-active: #2c7f95; - --c-brand-dark: #00586e; - --c-brand-light: #52b1cc; - - --c-disabled-bg: #e5e5e5; - --c-disabled-fg: #666; - - --code-bg-color: #f8f8f8; - --code-inline-bg-color: rgba(27, 31, 35, .04); - --code-highlight: rgba(0, 0, 0, .04); - - /** - * Typography - * --------------------------------------------------------------------- */ - - --font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; - --font-family-mono: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; - - /** - * Z Indexes - * - * Algolia SearchBox has a z-index of 200, so make sure not to go above - * that value. - * --------------------------------------------------------------------- */ - - --z-index-navbar: 10; - --z-index-sidebar: 6; - - /** - * Shadows - * --------------------------------------------------------------------- */ +/** + * Colors + * -------------------------------------------------------------------------- */ - --shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06); - --shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07); - --shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08); - --shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12); - --shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16); - - /** - * Sizes - * --------------------------------------------------------------------- */ - - --header-height: 3.6rem; - --sidebar-width: 17.5rem; - --scrollbar-width: 6px; - - --pwa-logo-p: #3e3e3e; +:root { + --vp-c-accent: #2c7f95; + --vp-c-brand: #2c7f95; + --vp-c-brand-light: #2e859c; + --vp-c-brand-lighter: #3392ac; + --vp-c-brand-dark: #00586e; + --vp-c-brand-darker: #00586e; + --vp-c-text-code: #2c3e50; + --vp-code-block-bg: rgba(125, 125, 125, 0.04); + --vp-c-bg-mute: #f5f5f5; + --vp-custom-block-tip-border: var(--vp-c-brand); + --vp-custom-block-tip-text: var(--vp-c-brand-dark); + --vp-custom-block-tip-bg: transparent; + --vp-custom-block-tip-code-bg: var(--vp-custom-block-tip-bg); } -html.dark { - - --c-bg: #111; - --c-bg-semi: rgba(17,17,17,0.8); - --c-bg-secondary: #222; - --c-text: #f5f7fa; - --c-text-light: #f9f9f9; - --c-text-lighter: #ffffff; - - --c-divider-light: rgba(200, 200, 200, .12); - --c-divider-dark: rgba(200, 200, 200, .48); - --code-bg-color: #191919; - --code-inline-bg-color: rgba(255, 255, 255, .04); - --code-highlight: rgba(0, 0, 0, .66); - - --c-brand: #4AA6C0; - --c-brand-active: #3392ac; - --c-brand-dark: #00586e; - --c-brand-light: #52b1cc; +.dark { + --vp-c-accent: #4aa6c0; + --vp-c-brand: #4aa6c0; + --vp-c-brand-light: #52b1cc; + --vp-c-brand-lighter: #52b1cc; + --vp-c-brand-dark: #52b1cc; + --vp-c-brand-darker: #52b1cc; + --vp-code-block-bg: rgba(0, 0, 0, 0.2); + --vp-c-text-code: #f5f7fa; + --vp-c-bg-mute: #2d2d2d; +} - --c-disabled-bg: #333; - --c-disabled-fg: #aaa; +/** + * Component: Button + * -------------------------------------------------------------------------- */ - --pwa-logo-p: #b9b9b9; +:root { + --vp-button-brand-border: var(--vp-c-brand-light); + --vp-button-brand-text: var(--vp-c-text-dark-1); + --vp-button-brand-bg: var(--vp-c-brand); + --vp-button-brand-hover-border: var(--vp-c-brand-light); + --vp-button-brand-hover-text: var(--vp-c-text-dark-1); + --vp-button-brand-hover-bg: var(--vp-c-brand-light); + --vp-button-brand-active-border: var(--vp-c-brand-light); + --vp-button-brand-active-text: var(--vp-c-text-dark-1); + --vp-button-brand-active-bg: var(--vp-button-brand-bg); } -/** Fallback Styles */ +/** + * Component: Home + * -------------------------------------------------------------------------- */ + :root { - --c-divider: var(--c-divider-light); + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: linear-gradient(347deg, #358399 30%, #3bb89c); + --vp-home-hero-image-background-image: linear-gradient(45deg, #00586e60 30%, #e5e05660); + --vp-home-hero-image-filter: blur(30px); +} - --c-text: var(--c-text-light-1); - --c-text-light: var(--c-text-light-2); - --c-text-lighter: var(--c-text-light-3); +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} - --c-bg: var(--c-white); +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(72px); + } +} - --code-line-height: 24px; - --code-font-family: var(--font-family-mono); - --code-font-size: 14px; +/** + * Component: Algolia + * -------------------------------------------------------------------------- */ - --pwa-logo-w: var(--c-brand); +.DocSearch { + --docsearch-primary-color: var(--vp-c-brand) !important; } diff --git a/docs/.vitepress/theme/support/sideBar.ts b/docs/.vitepress/theme/support/sideBar.ts deleted file mode 100644 index 12ec1219..00000000 --- a/docs/.vitepress/theme/support/sideBar.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { DefaultTheme } from '../config' -import { - ensureSlash, - ensureStartingSlash, - isArray, - removeExtention, -} from '../utils' - -export function isSideBarConfig( - sidebar: DefaultTheme.SideBarConfig | DefaultTheme.MultiSideBarConfig, -): sidebar is DefaultTheme.SideBarConfig { - return sidebar === false || sidebar === 'auto' || isArray(sidebar) -} - -export function isSideBarGroup( - item: DefaultTheme.SideBarItem, -): item is DefaultTheme.SideBarGroup { - return (item as DefaultTheme.SideBarGroup).children !== undefined -} - -/** - * Get the `SideBarConfig` from sidebar option. This method will ensure to get - * correct sidebar config from `MultiSideBarConfig` with various path - * combinations such as matching `guide/` and `/guide/`. If no matching config - * was found, it will return `auto` as a fallback. - */ -export function getSideBarConfig( - sidebar: DefaultTheme.SideBarConfig | DefaultTheme.MultiSideBarConfig, - path: string, -): DefaultTheme.SideBarConfig { - if (isSideBarConfig(sidebar)) - return sidebar - - // get the very first segment of the path to compare with nulti sidebar keys - // and make sure it's surrounded by slash - path = removeExtention(path) - path = ensureStartingSlash(path).split('/')[1] || '/' - path = ensureSlash(path) - - for (const dir of Object.keys(sidebar)) { - // make sure the multi sidebar key is surrounded by slash too - if (path === ensureSlash(dir)) - return sidebar[dir] - } - - return 'auto' -} - -/** - * Get flat sidebar links from the sidebar items. This method is useful for - * creating the "next and prev link" feature. It will ignore any items that - * don't have `link` property and removes `.md` or `.html` extension if a - * link contains it. - */ -export function getFlatSideBarLinks( - sidebar: DefaultTheme.SideBarItem[], -): DefaultTheme.SideBarLink[] { - return sidebar.reduce((links, item) => { - if (item.link) - links.push({ text: item.text, link: removeExtention(item.link), useLinkText: item.useLinkText }) - - if (isSideBarGroup(item)) - links = [...links, ...getFlatSideBarLinks(item.children)] - - return links - }, []) -} diff --git a/docs/.vitepress/theme/utils.ts b/docs/.vitepress/theme/utils.ts deleted file mode 100644 index 039996be..00000000 --- a/docs/.vitepress/theme/utils.ts +++ /dev/null @@ -1,77 +0,0 @@ -export const hashRE = /#.*$/ -export const extRE = /(index)?\.(md|html)$/ -export const endingSlashRE = /\/$/ -export const outboundRE = /^[a-z]+:/i - -export function isNullish(value: any): value is null | undefined { - return value === null || value === undefined -} - -export function isArray(value: any): value is any[] { - return Array.isArray(value) -} - -export function isExternal(path: string): boolean { - return outboundRE.test(path) -} - -export function isActive(route: any, path?: string): boolean { - if (path === undefined) - return false - - const routePath = normalize(route.path) - const pagePath = normalize(path) - - return routePath.toLowerCase() === pagePath.toLowerCase() -} - -export function normalize(path: string): string { - return decodeURI(path).replace(hashRE, '').replace(extRE, '') -} - -export function joinUrl(base: string, path: string): string { - const baseEndsWithSlash = base.endsWith('/') - const pathStartsWithSlash = path.startsWith('/') - - if (baseEndsWithSlash && pathStartsWithSlash) - return base.slice(0, -1) + path - - if (!baseEndsWithSlash && !pathStartsWithSlash) - return `${base}/${path}` - - return base + path -} - -/** - * get the path without filename (the last segment). for example, if the given - * path is `/guide/getting-started.html`, this method will return `/guide/`. - * Always with a trailing slash. - */ -export function getPathDirName(path: string): string { - const segments = path.split('/') - - if (segments[segments.length - 1]) - segments.pop() - - return ensureEndingSlash(segments.join('/')) -} - -export function ensureSlash(path: string): string { - return ensureEndingSlash(ensureStartingSlash(path)) -} - -export function ensureStartingSlash(path: string): string { - return /^\//.test(path) ? path : `/${path}` -} - -export function ensureEndingSlash(path: string): string { - return /(\.html|\/)$/.test(path) ? path : `${path}/` -} - -/** - * Remove `.md` or `.html` extention from the given path. It also converts - * `index` to slush. - */ -export function removeExtention(path: string): string { - return path.replace(/(index)?(\.(md|html))?$/, '') || '/' -} diff --git a/docs/deployment/aws.md b/docs/deployment/aws.md index ba7aeead..677bcafd 100644 --- a/docs/deployment/aws.md +++ b/docs/deployment/aws.md @@ -4,4 +4,6 @@ title: AWS Amplify | Deployment # AWS Amplify -> Work in progress +::: info WIP +Will coming soon. +::: diff --git a/docs/deployment/index.md b/docs/deployment/index.md index fd70c308..4fb78deb 100644 --- a/docs/deployment/index.md +++ b/docs/deployment/index.md @@ -1,38 +1,27 @@ --- -title: Getting Started | Deployment +title: Getting Started | Deploy --- # Getting Started -Since you need to install your application as a [Progressive Web App](https://web.dev/progressive-web-apps/) -you must configure your server to meet PWA requirements, that is, your server must: - -- serve `manifest.webmanifest` with mime type `application/manifest+json` -- you must serve your application over `https`: you must also redirect from `http` to `https` +Since you need to install your application as a [Progressive Web App](https://web.dev/progressive-web-apps/), you must configure your server to meet [PWA Minimal Requirements](/guide/#pwa-minimal-requirements), that is, your server **must**: +- serve `manifest.webmanifest` with `application/manifest+json` mime type +- you must serve your application over `https` +- you must redirect from `http` to `https` ## Servers -
    - - - - - - - - - - - - - - - -
+- [Netlify](/deployment/netlify) +- [AWS Amplify](/deployment/aws) +- [Vercel](/deployment/aws) +- [NGINX](/deployment/nginx) +- [Apache Http Server 2.4+](/deployment/apache) + ## Testing your application on production -Once you deploy your application to your server, you can test it using [WebPageTest](https://www.webpagetest.org/) . +Once you deploy your application to your server, you can test it using [WebPageTest](https://www.webpagetest.org/). + There are many test sites, but we suggest you use `WebPageTest` as this is the most comprehensive in terms of test: - Security. - First byte time. @@ -43,9 +32,6 @@ There are many test sites, but we suggest you use `WebPageTest` as this is the m - Lighthouse: Core Web Vitals, Performance, Images size optimization... - And more... -Enter the url of your application, click `Start Test` button, wait for the test to finish, the `WebPageTest` result -will hint you what things on your application must be fixed/changed. The `WebPageTest` result will also score your application, -it will also test your site with `Lighthouse`. +Enter the url of your application, click `Start Test` button, wait for the test to finish, the `WebPageTest` result will hint you what things on your application must be fixed/changed. The `WebPageTest` result will also score your application, it will also test your site with `Lighthouse`. -For example, go to [WebPageTest](https://www.webpagetest.org/) , enter `https://vite-plugin-pwa.netlify.app/`, -click `Start Test` button, wait a few seconds for the test to finish, and see the results for this site. +For example, go to [WebPageTest](https://www.webpagetest.org/), enter `https://vite-plugin-pwa.netlify.app/`, click `Start Test` button, wait a few seconds for the test to finish, and see the results for this site. diff --git a/docs/deployment/nginx.md b/docs/deployment/nginx.md index 37091df1..5d2e2e56 100644 --- a/docs/deployment/nginx.md +++ b/docs/deployment/nginx.md @@ -90,4 +90,6 @@ location / { Be aware that this is a very simplistic approach and you must test every change, as the NGINX match precedences for locations are not very intuitive and error prone if you do not know the [exact rules](https://docs.nginx.com/nginx/admin-guide/web-server/web-server/#location_priority). +::: danger **Always re-test and re-assure** that the caching for mission critical files is **as low** as possible if not hashed files or you might invalidate clients for a long time. +::: diff --git a/docs/deployment/vercel.md b/docs/deployment/vercel.md index 7cd1f807..8ba1a884 100644 --- a/docs/deployment/vercel.md +++ b/docs/deployment/vercel.md @@ -4,4 +4,6 @@ title: Vercel | Deployment # Vercel -> Work in progress +::: info WIP +Will coming soon. +::: diff --git a/docs/examples/astro.md b/docs/examples/astro.md new file mode 100644 index 00000000..c8d25263 --- /dev/null +++ b/docs/examples/astro.md @@ -0,0 +1,9 @@ +--- +title: Astro | Examples +--- + +# Astro + +::: info WIP +Will coming soon. +::: diff --git a/docs/examples/iles.md b/docs/examples/iles.md new file mode 100644 index 00000000..1fd94975 --- /dev/null +++ b/docs/examples/iles.md @@ -0,0 +1,9 @@ +--- +title: îles | Frameworks +--- + +# îles + +You can test `îles` using the source code from its documentation website, you can find it under [docs](https://github.com/ElMassimo/iles/tree/main/docs) package/directory. + +The behavior used in this website is [Prompt for update](/guide/prompt-for-update). diff --git a/docs/examples/index.md b/docs/examples/index.md index a5674d12..30f9f400 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -4,43 +4,40 @@ title: Getting Started | Examples # Getting Started -You can find a set of example projects on [Vite Plugin PWA GitHub repo](https://github.com/antfu/vite-plugin-pwa/tree/main/examples) . +You can find a set of examples projects on [Vite Plugin PWA GitHub repo](https://github.com/antfu/vite-plugin-pwa/tree/main/examples). -All the example projects are under `examples` package/directory of the repo root directory. +All the examples projects are under `examples` package/directory of the repo root directory. -> The main purpose of these example projects is to test the service worker and not to meet the `PWA requeriments`, -that is, if you use any of these examples for your projects, you will need to modify the code supplied and then test -that meet the `PWA requeriments`. Almost all example projects should meet `PWA requeriments` but you must check it on -your target project. +::: info +The main purpose of these examples projects is to test the service worker and not to meet the [PWA Minimal Requirements](/guide/#pwa-minimal-requirements), that is, if you use any of these examples for your projects, you will need to modify the code supplied and then test that it meets the [PWA Minimal Requirements](/guide/#pwa-minimal-requirements). Almost all the examples projects should meet [PWA Minimal Requirements](/guide/#pwa-minimal-requirements), but you must check it on your target project. -> All example projects use `@rollup/plugin-replace` to configure a timestamp initialized to `now` on each build, and so, -the service worker will be regenerated/versioned on each build: this timestamp will help us since the service worker -won't be regenerated/versioned if none source code changed (on your project you shouldn't want this behavior, -you should want to only regenerate/version the service worker when your source code change). +All the examples projects use `@rollup/plugin-replace` to configure a timestamp initialized to `now` on each build, and so, the service worker will be regenerated/versioned on each build: this timestamp will help us since the service worker won't be regenerated/versioned if none source code changed (on your project you shouldn't want this behavior, you should want to only regenerate/version the service worker when your source code change). +::: -> **TRY TO AVOID INCLUDING AUTOMATIC TIMESTAMP ON YOU APPLICATION IF YOU DON'T CHANGE YOUR CODE**. -We use the timestamp in example projects to avoid having to touch a file each time we need to test: for example, to test -`Prompt for update`, we need to install the service worker first time (first build), then rebuild and restart the -example project and finally refresh the browser to check the `Prompt for update` is shown. +::: warning TRY TO AVOID INCLUDING AUTOMATIC TIMESTAMP ON YOU APPLICATION IF YOU DON'T CHANGE YOUR CODE +We use the timestamp in the examples projects to avoid having to touch a file each time we need to test: for example, to test `Prompt for update`, we need to install the service worker first time (first build), then rebuild and restart the example project and finally refresh the browser to check the `Prompt for update` is shown. +::: -## How to run example projects? +## How to run examples projects? -If you want to run any of the example projects you will need to download/clone to your local machine the -`Vite Plugin PWA GitHub repo`. +If you want to run any of the examples projects you will need to download/clone to your local machine the `Vite Plugin PWA GitHub repo`. -You will need `node 12` (or newer) to be able to build the `Vite Plugin PWA`. +You will need `node 14` (or newer) to be able to build the `Vite Plugin PWA`. -Once the repo is on your local machine, you must install project dependencies and build the `Vite Plugin PWA`, -just run (from `vite-plugin-pwa` directory cloned locally): +::: warning +Before following the instructions below, read the [Contribution Guide](https://github.com/antfu/vite-plugin-pwa/blob/main/CONTRIBUTING.md). +::: +If you don't have installed `PNPM`, you must install it globally via `npm`: ```shell -pnpm install -pnpm run build +npm install -g pnpm ``` -If you don't have installed `PNPM`, you must install it globally via `npm`: +Once the repo is on your local machine, you must install project dependencies and build the `vite-plugin-pwa` plugin, just run (from `vite-plugin-pwa` directory cloned locally): + ```shell -npm install -g pnpm +pnpm install +pnpm run build ``` We use `PNPM` but should work with any `package manager`, for example, with `YARN`: @@ -48,144 +45,63 @@ We use `PNPM` but should work with any `package manager`, for example, with `YAR yarn && yarn build ``` -> From here on, we will only show the commands to run the example projects using `PNPM`, we leave it to you how to -execute them with any other` package manager`. +::: info +From here on, we will only show the commands to run the examples projects using `PNPM`, we leave it to you how to execute them with any other` package manager`. +::: -Before we start running the sample projects, you should consider the following: -- Use `Chromium based` browser: `Chrome`, `Chromium` or `Edge`. -- All the examples that are executed in this guide will be done over https, that is, all the projects will respond -at address `https://localhost` -- When testing an example project, the `service worker` will be installed in `https://localhost`, and so, subsequent -tests in other example projects may interfere with the previous test, because the `service worker` of the previous -project keep installed on the browser. -- Tests should be done on a private window, and so, browser addons/plugins will not interfere with the test. +Before we start running the examples projects, you should consider the following: +- Use `Chromium based` browser: `Chrome`, `Chromium` or `Edge` +- All the examples that are executed in this guide will be done over https, that is, all the projects will respond at address `https://localhost` +- When testing an example project, the `service worker` will be installed in `https://localhost`, and so, subsequent tests in another examples projects may interfere with the previous test, because the `service worker` of the previous project will keep installed on the browser +- Tests should be done on a private window, and so, browser addons/plugins will not interfere with the test -To avoid `service worker` interference, you should do the following tasks when switching between example projects: +To avoid `service worker` interference, you should do the following tasks when switching between examples projects: - Open `dev tools` (`Option + ⌘ + J` on `macOS`, `Shift + CTRL + J` on `Windows/Linux`) - Go to `Application > Storage`, you should check following checkboxes: - Application: [x] Unregister service worker - Storage: [x] Local and session storage - Cache: [x] Cache storage and [x] Application cache - Click on `Clear site data` button -- Go to `Application > Service Workers` and check the current `service worker` is missing or has the state `deleted`. - -Once we remove the `service worker`, run the corresponding script and just press browser `Refresh` button (or enter -`https://localhost` on browser address). - -## How to test example projects Offline? - -To test any example projects (or your project) on `offline`, just open `dev tools` (`Option + ⌘ + J` on `macOS`, -`Shift + CTRL + J` on `Windows/Linux`) and go to `Application > Network`, then locate `No throttling` selector: open -it and select `Offline` option. - -A common mistake is to select `Offline` option, then restart the example project (or your project), and refresh the -page. In that case, you will have unexpected behavior, and you should remove the service worker. - -If you click the browser `Refresh` button, you can inspect `Application > Network` tab on `dev tools` to see that -the `Service Worker` is serving all assets instead request them to the server. - -> Don't do a `hard refresh` since this will force the browser to go to the server, and then you will get -`No internet connection` page on browser. - -## Available Example Projects - -> - -We provide the following example projects: - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+- Go to `Application > Service Workers` and check the current `service worker` is missing or has the state `deleted` + +Once we remove the `service worker`, run the corresponding script and just press browser `Refresh` button (or enter `https://localhost` on browser address). + +## How to test the examples projects Offline? + +To test any of the examples projects (or your project) on `offline`, just open `dev tools` (`Option + ⌘ + J` on `macOS`, `Shift + CTRL + J` on `Windows/Linux`) and go to `Application > Network`, then locate `No throttling` selector: open it and select `Offline` option. + +A common pitfall is to select `Offline` option, then restart the example project (or your project), and refresh the page. In that case, you will have unexpected behavior, and you should remove the service worker. + +If you click the browser `Refresh` button, you can inspect `Application > Network` tab on `dev tools` to check that the `Service Worker` is serving all assets instead request them to the server. + +::: danger +Don't do a `hard refresh` since this will force the browser to go to the server, and then you will get `No internet connection` page on the browser. +::: + +## Available Examples Projects + + + +We provide the following examples projects: +- [Vue 3](/examples/vue) + - [Vue 3 generateSW Router Examples](/examples/vue#generatesw): set of examples with disparate behaviors. + - [Vue 3 injectManifest Router Examples](/examples/vue#generatesw): set of examples with disparate behaviors. +- [React](/examples/react) + - [React generateSW Router Examples](/examples/react#generatesw): set of examples with disparate behaviors. + - [React injectManifest Router Examples](/examples/react#generatesw): set of examples with disparate behaviors. +- [Svelte](/examples/svelte) + - [Svelte generateSW Router Examples](/examples/svelte#generatesw): set of examples with disparate behaviors. + - [Svelte injectManifest Router Examples](/examples/svelte#generatesw): set of examples with disparate behaviors. +- [SvelteKit](/examples/sveltekit) + - [SvelteKit generateSW Examples](/examples/sveltekit#generatesw): set of examples with disparate behaviors. + - [SvelteKit injectManifest Examples](/examples/sveltekit#generatesw): set of examples with disparate behaviors. +- [SolidJS](/examples/solidjs) + - [SolidJS generateSW Router Examples](/examples/solidjs#generatesw): set of examples with disparate behaviors. + - [SolidJS injectManifest Router Examples](/examples/solidjs#generatesw): set of examples with disparate behaviors. +- [Preact](/examples/preact) + - [Preact generateSW Router Examples](/examples/preact#generatesw): set of examples with disparate behaviors. + - [Preact injectManifest Router Examples](/examples/preact#generatesw): set of examples with disparate behaviors. +- [VitePress](/examples/vitepress): prompt for update. +- [îles](/examples/iles): prompt for update. +- [Astro](/examples/astro): coming soon (WIP). + diff --git a/docs/examples/preact.md b/docs/examples/preact.md index 63da6c54..c023a0cc 100644 --- a/docs/examples/preact.md +++ b/docs/examples/preact.md @@ -6,12 +6,11 @@ title: Preact | Examples The `Preact` example project can be found on `examples/preact-router` package/directory. -The router used on this example project is [preact-router](https://github.com/preactjs/preact-router) . +The router used on this example project is [preact-router](https://github.com/preactjs/preact-router). The `Preact` example has been created using `create-vite` template with `pnpx`: -
- pnpx create-vite +::: details pnpx create-vite ```shell pnpx create-vite @@ -28,7 +27,7 @@ Done. Now run: npm install npm run dev ``` -
+::: To test `new content available`, you should rerun the corresponding script, and then refresh the page. diff --git a/docs/examples/react.md b/docs/examples/react.md index c13c22d1..739dcca1 100644 --- a/docs/examples/react.md +++ b/docs/examples/react.md @@ -6,12 +6,11 @@ title: React | Examples The `React` example project can be found on `examples/react-router` package/directory. -The router used on this example project is [react-router](https://reactrouter.com/) . +The router used on this example project is [react-router](https://reactrouter.com/). The `React` example has been created using `create-vite` template with `pnpx`: -
- pnpx create-vite +::: details pnpx create-vite ```shell pnpx create-vite @@ -28,7 +27,7 @@ Done. Now run: npm install npm run dev ``` -
+::: To test `new content available`, you should rerun the corresponding script, and then refresh the page. diff --git a/docs/examples/solidjs.md b/docs/examples/solidjs.md index 30d989e7..7c28e605 100644 --- a/docs/examples/solidjs.md +++ b/docs/examples/solidjs.md @@ -6,18 +6,17 @@ title: SolidJS | Examples The `SolidJS` example project can be found on `examples/solid-router` package/directory. -The router used on this example project is [solid-app-router](https://github.com/solidjs/solid-app-router) . +The router used on this example project is [solid-app-router](https://github.com/solidjs/solid-app-router). The `SolidJS` example has been created using `https://github.com/solidjs/templates` template with `npx`: -
- npx degit solidjs/templates/ts-router solid-router +::: details npx degit solidjs/templates/ts-router solid-router ```shell npx degit solidjs/templates/ts-router solid-router > cloned solidjs/templates#HEAD to solid-router ``` -
+::: To test `new content available`, you should rerun the corresponding script, and then refresh the page. diff --git a/docs/examples/svelte.md b/docs/examples/svelte.md index ab30e39a..be0d885c 100644 --- a/docs/examples/svelte.md +++ b/docs/examples/svelte.md @@ -6,13 +6,11 @@ title: Svelte | Examples The `Svelte` example project can be found on `examples/svelte-routify` package/directory. -The router used on this example project is [@roxi/routify](https://routify.dev/) . +The router used on this example project is [@roxi/routify](https://routify.dev/). The `Svelte` example has been created using `create-vite` template with `pnpx`: -
- pnpx create-vite - +::: details pnpx create-vite ```shell pnpx create-vite + create-vite 2.5.4 @@ -28,7 +26,7 @@ Done. Now run: npm install npm run dev ``` -
+::: To test `new content available`, you should rerun the corresponding script, and then refresh the page. diff --git a/docs/examples/sveltekit.md b/docs/examples/sveltekit.md index 688b8c2e..f6c40c73 100644 --- a/docs/examples/sveltekit.md +++ b/docs/examples/sveltekit.md @@ -8,9 +8,7 @@ The `SvelteKit` example project can be found on `examples/sveltekit-pwa` package The `SvelteKit` example has been created using `svelte@next` template with `pnpm`: -
- pnpm create svelte@next sveltekit-pwa - +::: details pnpm create svelte@next sveltekit-pwa ```shell pnpm create svelte@next sveltekit-pwa + create-svelte 2.0.0-next.89 @@ -45,7 +43,7 @@ Next steps: 3: git init && git add -A && git commit -m "Initial commit" (optional) 4: npm run dev -- --open ``` -
+::: To test `new content available`, you should rerun the corresponding script, and then refresh the page. diff --git a/docs/examples/vitepress.md b/docs/examples/vitepress.md index 223bb5fc..f52ed5a8 100644 --- a/docs/examples/vitepress.md +++ b/docs/examples/vitepress.md @@ -4,11 +4,11 @@ title: VitePress | Examples # VitePress -You can test `VitePress` using the source code of this site, you can find it under `docs` package/directory. +You can test `VitePress` using the source code of this documentation website, you can find it under [docs](https://github.com/antfu/vite-plugin-pwa/tree/main/docs) package/directory. -The behavior used in this site is only `Prompt for update`. +The behavior used in this website is [Prompt for update](/guide/prompt-for-update). -To run this site on local, execute the following script from your shell (from root folder): +To run this site on your local, execute the following script from your shell (from root folder): ```shell pnpm run docs:serve ``` diff --git a/docs/examples/vue.md b/docs/examples/vue.md index debf9465..a12bf7a4 100644 --- a/docs/examples/vue.md +++ b/docs/examples/vue.md @@ -6,12 +6,11 @@ title: Vue | Examples The `Vue 3` example project can be found on `examples/vue-router` package/directory. -The router used on this example project is [vue-router](https://next.router.vuejs.org/) . +The router used on this example project is [vue-router](https://next.router.vuejs.org/). The `Vue 3` example has been created using `create-vite` template with `pnpx`: -
- pnpx create-vite +::: details pnpx create-vite ```shell pnpx create-vite @@ -28,7 +27,7 @@ Done. Now run: npm install npm run dev ``` -
+::: To test `new content available`, you should rerun the corresponding script, and then refresh the page. diff --git a/docs/frameworks/astro.md b/docs/frameworks/astro.md new file mode 100644 index 00000000..2fd9b877 --- /dev/null +++ b/docs/frameworks/astro.md @@ -0,0 +1,9 @@ +--- +title: Astro | Frameworks +--- + +# Astro + +::: info WIP +Will coming soon. +::: diff --git a/docs/frameworks/iles.md b/docs/frameworks/iles.md new file mode 100644 index 00000000..fc4aea07 --- /dev/null +++ b/docs/frameworks/iles.md @@ -0,0 +1,11 @@ +--- +title: îles | Examples +--- + +# îles + +We have included the integration with `îles` on their repo, adding `@islands/pwa` module. + +You can find the documentation here: +- [@islands/pwa](https://iles-docs.netlify.app/guide/plugins#islandspwa) +- [Progressive Web Application (PWA)](https://iles-docs.netlify.app/guide/pwa) diff --git a/docs/frameworks/index.md b/docs/frameworks/index.md index f177437a..eb38c2e7 100644 --- a/docs/frameworks/index.md +++ b/docs/frameworks/index.md @@ -2,7 +2,18 @@ title: Getting Started | Frameworks --- -# Getting Started +# Getting Started + +::: tip +If you use the default `registerType` which is `prompt`, and you want to prompt the users to reload, then you could use our framework modules. + +But if you: +1. use `autoUpdate` +2. don't like `autoUpdate`, but also don't feel it's necessary to prompt +3. use `injectManifest` + +Then, you **don't need** to learn the framework stuff. +::: This plugin is Framework-agnostic and so you can use it with Vanilla JavaScript, TypeScript and with any framework. @@ -22,107 +33,73 @@ declare module 'virtual:pwa-register' { } ``` -## Usage +## Import Virtual Modules + +`vite-plugin-pwa` plugin exposes a `Vite` virtual module to interact with the service worker. + +::: tip +You only need to import the virtual modules exposed by `vite-plugin-pwa` plugin when you need to interact with the user, otherwise you don't need to import any of them, that is, when using `registerType: 'prompt'` or when using `registerType: 'autoUpdate'` and you want to inform the user that the application is ready to work offline. +::: -This plugin exposes a `Vite` virtual module to interact with the service worker, you must import this virtual module -when you need to work with [Prompt for update](/guide/prompt-for-update.html) on new content available: +### Auto Update + +You must import the virtual module when you configure `registerType: 'autoUpdate'` and you want your application inform the user when the application is ready to work `offline`: ```ts import { registerSW } from 'virtual:pwa-register' const updateSW = registerSW({ - onNeedRefresh() {}, onOfflineReady() {} }) ``` -You will need to: -- show a prompt to the user with refresh and cancel buttons inside `onNeedRefresh` method. -- show a ready to work offline message to the user with an OK button inside `onOfflineReady` method. +You need to show a ready to work offline message to the user with an OK button inside `onOfflineReady` method. -When the user clicks the "refresh" button when `onNeedRefresh` called, then call `updateSW()` function; the page will -reload and the up-to-date content will be served. +When the user clicks the `OK` button, just hide the prompt shown on `onOfflineReady` method. -In any case, when the user clicks the `Cancel` or `OK` buttons in case `onNeedRefresh` or `onOfflineReady` respectively, -close the corresponding showed prompt. +### Prompt For Update -You must also import the virtual module when you need to work with [Automatic reload](/guide/auto-update.html) when new -content available, and you need to notify the user the application is ready to work `offline`: +When using `registerType: 'prompt'`, you **must** import the virtual module: ```ts import { registerSW } from 'virtual:pwa-register' const updateSW = registerSW({ + onNeedRefresh() {}, onOfflineReady() {} }) ``` -You will need to show a ready to work offline message to the user with an OK button inside `onOfflineReady` method. +You will need to: +- show a prompt to the user with refresh and cancel buttons inside `onNeedRefresh` method. +- show a ready to work offline message to the user with an OK button inside `onOfflineReady` method. -When the user clicks the `OK` button, just hide the prompt shown on `onOfflineReady` method. +When the user clicks the "refresh" button when `onNeedRefresh` called, then call `updateSW()` function; the page will reload and the up-to-date content will be served. + +In any case, when the user clicks the `Cancel` or `OK` buttons in case `onNeedRefresh` or `onOfflineReady` respectively, close the corresponding showed prompt. ## Custom Vite Virtual Modules -This plugin also exposes a set of virtual modules for [Vue 3](https://v3.vuejs.org/) , -[React](https://reactjs.org/) , [Svelte](https://svelte.dev/docs) , -[SolidJS](https://www.solidjs.com/) and [Preact](https://preactjs.com/) . - -

These custom virtual modules will expose a wrapper for -virtual:pwa-register using framework reactivity system, that is:

- -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
- -**Note**: for [Vue 2](https://vuejs.org/) you need to use a custom `mixin` provided on -[Vue 2](/frameworks/vue.html#vue-2) section. +`vite-plugin-pwa` plugin also exposes a set of virtual modules for [Vue 3](https://v3.vuejs.org/), [React](https://reactjs.org/), [Svelte](https://svelte.dev/docs), [SolidJS](https://www.solidjs.com/) and [Preact](https://preactjs.com/). + +These custom virtual modules will expose a wrapper for virtual:pwa-register using framework reactivity system, that is: +- virtual:pwa-register/vue: [ref](https://v3.vuejs.org/api/refs-api.html#ref) for Vue 3 +- virtual:pwa-register/react: [useState](https://reactjs.org/docs/hooks-reference.html#usestate) for React +- virtual:pwa-register/svelte: [writable](https://svelte.dev/docs#writable) for Svelte +- virtual:pwa-register/solid: [createSignal](https://www.solidjs.com/docs/latest/api#createsignal) for SolidJS +- virtual:pwa-register/preact: [useState](https://preactjs.com/guide/v10/hooks#usestate) for Preact + +**Note**: for [Vue 2](https://vuejs.org/) you need to use a custom `mixin` provided on [Vue 2](/frameworks/vue#vue-2) section. ## Frameworks -
    - - - - - - - - - - - - - - - - - - - - - -
+These custom virtual modules will expose a wrapper for virtual:pwa-register using framework reactivity system, that is: +- [Vue](/frameworks/vue) +- [React](/frameworks/react) +- [Svelte](/frameworks/svelte) +- [SvelteKit](/frameworks/sveltekit) +- [SolidJS](/frameworks/solidjs) +- [Preact](/frameworks/preact) +- [VitePress](/frameworks/vitepress) +- [îles](/frameworks/iles) +- [Astro](/frameworks/astro) diff --git a/docs/frameworks/preact.md b/docs/frameworks/preact.md index 12206751..1b28aa41 100644 --- a/docs/frameworks/preact.md +++ b/docs/frameworks/preact.md @@ -4,10 +4,11 @@ title: Preact | Frameworks # Preact -You can use the built-in `Vite` virtual module `virtual:pwa-register/preact` for `Preact` which will return -`useState` stateful values (`useState`) for `offlineReady` and `needRefresh`. +You can use the built-in `Vite` virtual module `virtual:pwa-register/preact` for `Preact` which will return `useState` stateful values (`useState`) for `offlineReady` and `needRefresh`. -> You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: warning +You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: ## Type declarations @@ -36,9 +37,7 @@ declare module 'virtual:pwa-register/preact' { You can use this `ReloadPrompt.tsx` component: -
- ReloadPrompt.tsx code - +::: details ReloadPrompt.tsx ```tsx import './ReloadPrompt.css' @@ -84,13 +83,11 @@ function ReloadPrompt() { export default ReloadPrompt ``` -
+::: and its corresponding `ReloadPrompt.css` styles file: -
- ReloadPrompt.css code - +::: details ReloadPrompt.css ```css .ReloadPrompt-container { padding: 0; @@ -122,12 +119,11 @@ and its corresponding `ReloadPrompt.css` styles file: padding: 3px 10px; } ``` -
+::: ## Periodic SW Updates -As explained in [Periodic Service Worker Updates](/guide/periodic-sw-updates.html), you can use this code to configure this -behavior on your application with the virtual module `virtual:pwa-register/preact`: +As explained in [Periodic Service Worker Updates](/guide/periodic-sw-updates), you can use this code to configure this behavior on your application with the virtual module `virtual:pwa-register/preact`: ```ts import { useRegisterSW } from 'virtual:pwa-register/preact' diff --git a/docs/frameworks/react.md b/docs/frameworks/react.md index ffb78b2d..6a9df939 100644 --- a/docs/frameworks/react.md +++ b/docs/frameworks/react.md @@ -4,10 +4,11 @@ title: React | Frameworks # React -You can use the built-in `Vite` virtual module `virtual:pwa-register/react` for `React` which will return -`useState` stateful values (`useState`) for `offlineReady` and `needRefresh`. +You can use the built-in `Vite` virtual module `virtual:pwa-register/react` for `React` which will return `useState` stateful values (`useState`) for `offlineReady` and `needRefresh`. -> You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: warning +You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: ## Type declarations @@ -36,9 +37,7 @@ declare module 'virtual:pwa-register/react' { You can use this `ReloadPrompt.tsx` component: -
- ReloadPrompt.tsx code - +:::details ReloadPrompt.tsx ```tsx import React from 'react' import './ReloadPrompt.css' @@ -85,13 +84,11 @@ function ReloadPrompt() { export default ReloadPrompt ``` -
+::: and its corresponding `ReloadPrompt.css` styles file: -
- ReloadPrompt.css code - +:::details ReloadPrompt.css ```css .ReloadPrompt-container { padding: 0; @@ -123,12 +120,11 @@ and its corresponding `ReloadPrompt.css` styles file: padding: 3px 10px; } ``` -
+::: ## Periodic SW Updates -As explained in [Periodic Service Worker Updates](/guide/periodic-sw-updates.html), you can use this code to configure this -behavior on your application with the virtual module `virtual:pwa-register/react`: +As explained in [Periodic Service Worker Updates](/guide/periodic-sw-updates), you can use this code to configure this behavior on your application with the virtual module `virtual:pwa-register/react`: ```ts import { useRegisterSW } from 'virtual:pwa-register/react' diff --git a/docs/frameworks/solidjs.md b/docs/frameworks/solidjs.md index 0880c3e7..1784042a 100644 --- a/docs/frameworks/solidjs.md +++ b/docs/frameworks/solidjs.md @@ -4,10 +4,11 @@ title: SolidJS | Frameworks # SolidJS -You can use the built-in `Vite` virtual module `virtual:pwa-register/solid` for `SolidJS` which will return -`createSignal` stateful values (`createSignal`) for `offlineReady` and `needRefresh`. +You can use the built-in `Vite` virtual module `virtual:pwa-register/solid` for `SolidJS` which will return `createSignal` stateful values (`createSignal`) for `offlineReady` and `needRefresh`. -> You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: warning +You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: ## Type declarations @@ -36,9 +37,7 @@ declare module 'virtual:pwa-register/solid' { You can use this `ReloadPrompt.tsx` component: -
- ReloadPrompt.tsx code - +::: details ReloadPrompt.tsx ```tsx import type { Component } from 'solid-js' import { Show } from 'solid-js' @@ -89,13 +88,11 @@ const ReloadPrompt: Component = () => { export default ReloadPrompt ``` -
+::: and its corresponding `ReloadPrompt.module.css` styles module: -
- ReloadPrompt.module.css code - +::: details ReloadPrompt.module.css ```css .Container { padding: 0; @@ -127,12 +124,11 @@ and its corresponding `ReloadPrompt.module.css` styles module: padding: 3px 10px; } ``` -
+::: ## Periodic SW Updates -As explained in [Periodic Service Worker Updates](/guide/periodic-sw-updates.html), you can use this code to configure this -behavior on your application with the virtual module `virtual:pwa-register/solid`: +As explained in [Periodic Service Worker Updates](/guide/periodic-sw-updates), you can use this code to configure this behavior on your application with the virtual module `virtual:pwa-register/solid`: ```ts import { useRegisterSW } from 'virtual:pwa-register/solid' diff --git a/docs/frameworks/svelte.md b/docs/frameworks/svelte.md index 2ce206a6..374f1503 100644 --- a/docs/frameworks/svelte.md +++ b/docs/frameworks/svelte.md @@ -4,11 +4,12 @@ title: Svelte | Frameworks # Svelte -You can use the built-in `Vite` virtual module `virtual:pwa-register/svelte` for `Svelte` which will return -`writable` stores (`Writable`) for `offlineReady` and `needRefresh`. +You can use the built-in `Vite` virtual module `virtual:pwa-register/svelte` for `Svelte` which will return `writable` stores (`Writable`) for `offlineReady` and `needRefresh`. + +::: warning +You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: -> You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. -> ## Type declarations ```ts @@ -36,9 +37,7 @@ declare module 'virtual:pwa-register/svelte' { You can use this `ReloadPrompt.svelte` component: -
- components/ReloadPrompt.svelte code - +::: details ReloadPrompt.svelte ```html +``` diff --git a/docs/guide/generate.md b/docs/guide/generate.md deleted file mode 100644 index fa9f6748..00000000 --- a/docs/guide/generate.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Generate Service Worker | Guide ---- - -# Generate Service Worker - -Edit your `vite.config.ts` file to add `Vite Plugin PWA Plugin`: - -
- VitePWA options code - -```ts -import { VitePWA } from 'vite-plugin-pwa' -export default defineConfig({ - plugins: [ - VitePWA({ - includeAssets: ['favicon.svg', 'favicon.ico', 'robots.txt', 'apple-touch-icon.png'], - manifest: { - name: 'Name of your app', - short_name: 'Short name of your app', - description: 'Description of your app', - theme_color: '#ffffff', - icons: [ - { - src: 'pwa-192x192.png', - sizes: '192x192', - type: 'image/png', - }, - { - src: 'pwa-512x512.png', - sizes: '512x512', - type: 'image/png', - }, - { - src: 'pwa-512x512.png', - sizes: '512x512', - type: 'image/png', - purpose: 'any maskable', - } - ] - } - }) - ] -}) -``` -
- -You will need to create your `robots.txt`, `favicon.svg`, `favicon.ico`, `apple-touch-icon.png`. - -You can create `robots.txt` on `public` directory with the following content: -```txt -User-agent: * -Allow: / -``` - -For `manifest` icons entry, you will need to create `pwa-192x192.png`, and `pwa-512x512.png`. The icons specified above -are the minimum required to meet PWA, that is, icons with `192x192` and `512x512` resolutions (last one duplicate for -`purpose: 'any maskable'`). - -We suggest that you create an SVG or PNG icon (if it is a PNG icon, with the maximum resolution possible) icon for -your application and use it to generate a favicon package on [Favicon Generator](https://realfavicongenerator.net/) . - -Once generated, download the ZIP and use -`android-*` icons for `pwa-*`: - -- use `android-chrome-192x192.png` for `pwa-192x192.png` -- use `android-chrome-512x512.png` for `pwa-512x512.png` -- `apple-touch-icon.png` is `apple-touch-icon.png` -- `favicon.ico` is `favicon.ico` - -You will also need to change your `index.html` file to include at least the following content to meet PWA requirements, -you must change the `title` and the `description`, `favicon.svg` is the svg you have created: - -
- index.html code - -```html - - - - Your app title - - - - - - - -``` -
- -For `mask-icon` in the html use the `svg` or the `png` used to generate the `favicon` package. - -The `theme-color` in the html and the` theme_color` in the PWA `manifest` entry should match, change it to the color -you want. - diff --git a/docs/guide/index.md b/docs/guide/index.md index ebcec3f5..7e26a872 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -4,15 +4,37 @@ title: Getting Started | Guide # Getting Started -`Vite Plugin PWA` uses [Workbox](https://developers.google.com/web/tools/workbox) library to build the service worker, -you can find more information on [Workbox](/workbox/) section. +::: tip [Learn PWA](https://web.dev/learn/pwa/) +Progressive Web Apps (PWAs) are web application built and enhanced with modern APIs to deliver enhanced capabilities, reliability, and installability while reaching anyone, anywhere, on any device, all with a single codebase. -If you are new to **Progressive Web Apps (PWA)**, we suggest read this guide before starting writing code (it is still work in progress): -[Learn PWA](https://web.dev/learn/pwa/) . +If you want to build a Progressive Web App, you may be wondering where to start, if it's possible to upgrade a website to a PWA without starting from scratch, or how to move from a platform-specific app to a PWA. +::: -## Installation +A PWA mainly consists of a [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest), a service worker and a script/module to register the service worker in the browser. -Add `vite-plugin-pwa` dependency to your project as a `dev dependency`: +If you are new to **Progressive Web Apps (PWA)**, we suggest read this guide before starting writing code: [Learn PWA](https://web.dev/learn/pwa/). + +## Service Worker + +Service workers essentially act as proxy servers that sit between web applications, the browser, and the network (when available). They are intended, among other things, to enable the creation of effective offline experiences, intercept network requests and take appropriate action based on whether the network is available, and update assets residing on the server. They will also allow access to push notifications and background sync APIs. + +A service worker is an event-driven [worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker) registered against an origin and a path. It takes the form of a JavaScript file that can control the web-page/site that it is associated with, intercepting and modifying navigation and resource requests, and caching resources in a very granular fashion to give you complete control over how your app behaves in certain situations (the most obvious one being when the network is not available). + +You can find more information about service workers in [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). + +## vite-plugin-pwa + +`vite-plugin-pwa` will help you to add PWA, with almost zero configuration, to your existing applications. The plugin will add sensible built-in default configuration for common use cases. + +The `vite-plugin-pwa` plugin will: +- generate the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest): using the `manifest` plugin option +- configure the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) on your application entry point: adding a link on the `head` on your entry point +- generate the service worker: using the `strategies` plugin option (for more information read [Service Worker Strategies](/guide/service-worker-strategies-and-behaviors#service-worker-strategies) section) +- generate the script to register the service worker in the browser: using `injectRegister` plugin option (for more information read [Register Service Worker](/guide/register-service-worker) section) + +## Installing vite-plugin-pwa + +To install the `vite-plugin-pwa` plugin, just add it to your project as a `dev dependency`: With **YARN**: ```shell @@ -29,52 +51,58 @@ With **PNPM**: pnpm i vite-plugin-pwa -D ``` -## Setup +## Configuring vite-plugin-pwa + +Edit your `vite.config.js / vite.config.ts` file and add the `vite-plugin-pwa`: + +```ts +import { VitePWA } from 'vite-plugin-pwa' +export default defineConfig({ + plugins: [ + VitePWA({ registerType: 'autoUpdate' }) + ] +}) +``` + +With this minimal configuration of the `vite-plugin-pwa` plugin, your application is now able to generate the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) and inject it at the entry point, generate the service worker and register it in the browser. -Edit your `vite.config.ts` file to add `Vite Plugin PWA`: +::: warning +If you are **NOT** using `vite-plugin-pwa` version `0.12.1+`, there is a bug handling `injectRegister` (the service worker generated will not include the code required to allow work with `autoUpdate` behavior). +If you're using a `vite-plugin-pwa` plugin version prior to `0.12.1`, you can fix the bug using this plugin configuration: ```ts import { VitePWA } from 'vite-plugin-pwa' export default defineConfig({ plugins: [ - VitePWA({}) + VitePWA({ + registerType: 'autoUpdate', + workbox: { + clientsClaim: true, + skipWaiting: true + } + }) ] }) ``` +::: -## Features - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+If you want to check it in `dev`, add the `devOptions` option to the plugin configuration (you will have the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) and the generated service worker): +```ts +import { VitePWA } from 'vite-plugin-pwa' +export default defineConfig({ + plugins: [ + VitePWA({ + registerType: 'autoUpdate', + devOptions: { + enabled: true + } + }) + ] +}) +``` +If you build your application, the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) will be generated and configured on the application entry point, the service worker will be also generated and the script/module to register it in the browser added. +::: info +`vite-plugin-pwa` plugin uses [workbox-build](https://developer.chrome.com/docs/workbox/reference/workbox-build/) node library to build the service worker, you can find more information in the [Service Worker Strategies And Behaviors](/guide/service-worker-strategies-and-behaviors) and [Workbox](/workbox/) sections. +::: diff --git a/docs/guide/inject-manifest.md b/docs/guide/inject-manifest.md index 89c216b5..39924c11 100644 --- a/docs/guide/inject-manifest.md +++ b/docs/guide/inject-manifest.md @@ -4,18 +4,37 @@ title: Advanced (injectManifest) | Guide # Advanced (injectManifest) -With this option you can build your own service worker. +With this service worker `strategy` you can build your own service worker. -## Custom Service worker +The `vite-plugin-pwa` plugin will compile your custom service worker and inject its service worker's precache manifest. + +By default, the plugin will assume the `service worker` source code is located at the `Vite's public` folder with the name `sw.js`, that's, it will search in the following file: `/public/sw.js`. + +If you want to change the location and/or the service worker name, you will need to change the following plugin options: +- `srcDir`: **must** be relative to the project root folder +- `filename`: including the file extension and **must** be relative to the `srcDir` folder + +For example, if your service worker is located at `/src/my-sw.js` you must configure it using: +```ts +import { VitePWA } from 'vite-plugin-pwa' +export default defineConfig({ + plugins: [ + VitePWA({ + strategies: 'injectManifest', + srcDir: 'src', + filename: 'my-sw.js' + }) + ] +}) +``` -We recommend use [Workbox](https://developers.google.com/web/tools/workbox) to build your service worker, -you will need to include `workbox-*` dependencies as `dev dependencies` to your project. +## Custom Service worker -### Setup +We recommend you to use [Workbox](https://developers.google.com/web/tools/workbox) to build your service worker instead using `importScripts`, you will need to include `workbox-*` dependencies as `dev dependencies` to your project. -Go to [Generate Service Worker](/guide/generate.html) section for basic configuration options. +### Plugin Configuration -You must add `strategies: 'injectManifest'` to `Vite PWA` options in your `vite.config.ts` file: +You **must** configure `strategies: 'injectManifest'` in `vite-plugin-pwa` plugin options in your `vite.config.ts` file: ```ts VitePWA({ @@ -23,9 +42,9 @@ VitePWA({ }) ``` -### Runtime +### Service Worker Code -Your custom service worker (`public/sw.js`) should have at least this code: +Your custom service worker (`public/sw.js`) should have at least this code (you also need to install `workbox-precaching` as `dev dependency` to your project): ```js import { precacheAndRoute } from 'workbox-precaching' @@ -42,32 +61,13 @@ precacheAndRoute(self.__WB_MANIFEST) -## Prompt for new content +## Auto Update Behavior -If you need your custom service worker works with `Prompt for new content` behavior, you need to change -your service worker code. +If you need your custom service worker works with `Auto Update` behavior, you need to change the plugin configuration options and add some custom code to your service worker code. -### Runtime +### Plugin Configuration -You need to include on your service worker at least this code: - -```js -self.addEventListener('message', (event) => { - if (event.data && event.data.type === 'SKIP_WAITING') - self.skipWaiting() -}) -``` - -> You also need to add the code to your application described on [Prompt for new content refreshing](/guide/prompt-for-update.html#runtime) - -## Auto update for new content - -If you need your custom service worker works with `Auto update for new content` behavior, you need to change -your service worker code and the plugin configuration options. - -### Setup - -You must add `registerType: 'autoUpdate'` to `Vite PWA` options in your `vite.config.ts` file: +You must configure `registerType: 'autoUpdate'` to `vite-plugin-pwa` plugin options in your `vite.config.ts` file: ```ts VitePWA({ @@ -75,10 +75,9 @@ VitePWA({ }) ``` -### Runtime +### Service Worker Code -Include on your service worker at least this code (you also need to install `workbox-core` as `dev dependency` -to your project): +You **must** include in your service worker code at least this code (you also need to install `workbox-core` as `dev dependency` to your project): ```js import { clientsClaim } from 'workbox-core' @@ -87,13 +86,24 @@ self.skipWaiting() clientsClaim() ``` -> You also need to add the code to your application described on [Automatic reload](/guide/auto-update.html#runtime) +## Prompt For Update Behavior + +If you need your custom service worker works with `Prompt For Update` behavior, you need to change your service worker code. +### Service Worker Code + +You need to include on your service worker at least this code: + +```js +self.addEventListener('message', (event) => { + if (event.data && event.data.type === 'SKIP_WAITING') + self.skipWaiting() +}) +``` ## TypeScript support -You can use TypeScript to write your custom service worker. To resolve service worker types, just add `WebWorker` to `lib` -entry on your `tsconfig.json` file: +You can use TypeScript to write your custom service worker. To resolve service worker types, just add `WebWorker` to `lib` entry on your `tsconfig.json` file: ```json { @@ -103,12 +113,11 @@ entry on your `tsconfig.json` file: } ``` -### Setup +### Plugin Configuration -We recommend you to put your custom service worker on `src` directory. +We recommend you to put your custom service worker inside `src` directory. -You need to add `srcDir: 'src'` and `filename: 'sw.ts'` options to `Vite PWA` in your `vite.config.ts` file, -configure both options with the directory and the name of your custom service worker properly: +You need to configure `srcDir: 'src'` and `filename: 'sw.ts'` plugin options in your `vite.config.ts` file, configure both options with the directory and the name of your custom service worker properly: ```ts VitePWA({ @@ -117,7 +126,7 @@ VitePWA({ }) ``` -### Runtime +### Service Worker Code You need to define `self` scope with `ServiceWorkerGlobalScope`: diff --git a/docs/guide/periodic-sw-updates.md b/docs/guide/periodic-sw-updates.md index b24f7e96..51cf3392 100644 --- a/docs/guide/periodic-sw-updates.md +++ b/docs/guide/periodic-sw-updates.md @@ -4,13 +4,13 @@ title: Periodic Service Worker Updates | Guide # Periodic Service Worker Updates -As explained in [Manual Updates](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#manual_updates) -entry on `The Service Worker Lifecycle`, you can use this code to configure periodic service worker updates on your -application on your `main.ts` or `main.js`: +:::info +If you're not importing any of the virtual modules provided by `vite-plugin-pwa` you'll need to figure out how to configure it, it is out of the scope of this guide. +::: -
- main.ts / main.js code +As explained in [Manual Updates](https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#manual-updates) entry in [The Service Worker Lifecycle](https://web.dev/service-worker-lifecycle/) article, you can use this code to configure periodic service worker updates on your application on your `main.ts` or `main.js`: +::: details main.ts / main.js ```ts import { registerSW } from 'virtual:pwa-register' @@ -24,7 +24,7 @@ const updateSW = registerSW({ } }) ``` -
+::: The interval must be in milliseconds, in the example above it is configured to check the service worker every hour. diff --git a/docs/guide/prompt-for-update.md b/docs/guide/prompt-for-update.md index 6c7a5e56..60c19de6 100644 --- a/docs/guide/prompt-for-update.md +++ b/docs/guide/prompt-for-update.md @@ -6,13 +6,9 @@ title: Prompt for new content refreshing | Guide -> This is the default option when `strategies` and `registerType` are not configured. -In order for the service worker to be registered, you must invoke the `registerSW` method -from the `virtual:pwa-register` module. +## Plugin Configuration -## Setup - -Go to [Generate Service Worker](/guide/generate.html) section for basic configuration options. +Since this is the default behavior for the `registerType` plugin option, you don't need to configure it. ### Cleanup Outdated Caches @@ -24,7 +20,7 @@ Go to [Generate Service Worker](/guide/generate.html) section for basic configur -## Runtime +## Importing Virtual Modules You must include the following code on your `main.ts` or `main.js` file: ```ts @@ -40,12 +36,9 @@ You will need to: - show a prompt to the user with refresh and cancel buttons inside `onNeedRefresh` method. - show a ready to work offline message to the user with an OK button inside `onOfflineReady` method. -When the user clicks the "refresh" button when `onNeedRefresh` called, then call `updateSW()` function; the page will -reload and the up-to-date content will be served. - -In any case, when the user clicks the `Cancel` or `OK` buttons in case `onNeedRefresh` or `onOfflineReady` respectively, -close the corresponding showed prompt. +When the user clicks the "refresh" button when `onNeedRefresh` called, then call `updateSW()` function; the page will reload and the up-to-date content will be served. +In any case, when the user clicks the `Cancel` or `OK` buttons in case `onNeedRefresh` or `onOfflineReady` respectively, close the corresponding showed prompt. ### SSR/SSG diff --git a/docs/guide/pwa-minimal-requirements.md b/docs/guide/pwa-minimal-requirements.md new file mode 100644 index 00000000..60d15d39 --- /dev/null +++ b/docs/guide/pwa-minimal-requirements.md @@ -0,0 +1,135 @@ +--- +title: PWA Minimal Requirements | Guide +--- + +# PWA Minimal Requirements + +Previous steps in this guide, are the minimal requirements and configuration to create the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) and the service worker when you build your application, but you'll need to include more options to meet PWA Minimal Requirements. + +Your application **must** meet the PWA Minimal Requirements before deploying it to production or when testing your build on local: for example, when testing your PWA application on local using `LightHouse`. + +To make your PWA application installable (one of the requirements), you will need to modify your application entry point, add some minimal entries to your `Web App Manifest`, allow search engines to crawl all your application pages and configure your server properly (only for production, on local you can use `https-localhost` dependency and `node`). + +## Entry Point + +Your application entry point (usually `index.html`) **must** have the following entries in the `` section: +- mobile viewport configuration +- a title +- a description +- a favicon +- a link for `apple-touch-icon` +- a link for `mask-icon` +- a meta entry for `theme-color` + +For example, here a minimal configuration (you must provide all the icons and images): +```html + + + My Awesome App + + + + + + +``` + +## Web App Manifest + +Your application [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) **must** have the following entries: +- a scope: omitted here for simplicity, the `vite-plugin-pwa` plugin will use the `Vite` base option to configure it (default is `/`) +- a name +- a short description +- a description +- a `theme_color`: **must match** the configured one on `Entry Point theme-color` +- an icon with `192x192` size +- an icon with `512x512` size + +To configure the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest), add the `manifest` entry to the `vite-plugin-pwa` plugin options. + +Following with the example, here a minimal configuration (you must provide all the icons and images): +```ts +import { VitePWA } from 'vite-plugin-pwa' +export default defineConfig({ + plugins: [ + VitePWA({ + includeAssets: ['favicon.ico', 'apple-touch-icon.png', 'masked-icon.svg'], + manifest: { + name: 'My Awesome App', + short_name: 'MyApp', + description: 'My Awesome App description', + theme_color: '#ffffff', + icons: [ + { + src: 'pwa-192x192.png', + sizes: '192x192', + type: 'image/png' + }, + { + src: 'pwa-512x512.png', + sizes: '512x512', + type: 'image/png' + } + ] + } + }) + ] +}) +``` + +## Icons / Images + +For `manifest` icons entry, you will need to create `pwa-192x192.png`, and `pwa-512x512.png` icons. The icons specified above are the minimum required to meet PWA, that is, icons with `192x192` and `512x512` resolutions (last one duplicated for `purpose: 'any maskable'` if you want to add it, it is not required). + +We suggest you to create a svg or png icon (if it is a png icon, with the maximum resolution possible) for your application and use it to generate a favicon package in [Favicon Generator](https://realfavicongenerator.net/). + +For `mask-icon` in the entry point, use the svg or the png used to generate the favicon package. + +Once generated, download the ZIP and use `android-*` icons for `pwa-*`: +- use `android-chrome-192x192.png` for `pwa-192x192.png` +- use `android-chrome-512x512.png` for `pwa-512x512.png` +- `apple-touch-icon.png` is `apple-touch-icon.png` +- `favicon.ico` is `favicon.ico` + +If you want to add the `purpose: 'any maskable'` icon to the Web App Manifest: +```ts +icons: [ + { + src: 'pwa-192x192.png', + sizes: '192x192', + type: 'image/png' + }, + { + src: 'pwa-512x512.png', + sizes: '512x512', + type: 'image/png' + }, + { + src: 'pwa-512x512.png', + sizes: '512x512', + type: 'image/png', + purpose: 'any maskable' + } +] +``` + +## Search Engines + +You **must** add a `robots.txt` file to allow search engines to crawl all your application pages, just add `robots.txt` to the `public` folder on your application: +```txt +User-agent: * +Allow: / +``` + +:::warning +`public` folder must be on the root folder of your application, not inside the `src` folder. +::: + +## Server Configuration + +You can use the server you want, but your server **must**: +- serve `manifest.webmanifest` with `application/manifest+json` mime type +- serve your application over `https` +- redirect from `http` to `https` + +You can find more information in the [Deploy](/deployment/) section. diff --git a/docs/guide/register-service-worker.md b/docs/guide/register-service-worker.md new file mode 100644 index 00000000..f2ec7034 --- /dev/null +++ b/docs/guide/register-service-worker.md @@ -0,0 +1,76 @@ +--- +title: Register Service Worker | Guide +--- + +# Register Service Worker + +`vite-plugin-pwa` plugin will register the service worker automatically for you, using the `injectRegister` configuration option (**optional**). + +If you want to configure the `injectRegister` plugin option: +```ts +import { VitePWA } from 'vite-plugin-pwa' +export default defineConfig({ + plugins: [ + VitePWA({ + injectRegister: 'auto' + }) + ] +}) +``` + +The `injectRegister` plugin configuration option, will control how to register the service worker in your application: +- `inline`: injects a simple register script, inlined in the application entry point +- `script`: injects a `script` tag in the `head` with the `service worker` to a generated simple register +- `null` (manual): do nothing, you will need to register the service worker yourself, or import any of the virtual modules exposed by the plugin +- **`auto` (default value)**: depends on whether you use any of the virtual modules exposed by the plugin, it will do nothing or switch to `script` mode + + +You can find more information about the virtual modules exposed by the plugin in the [Frameworks](/frameworks/) section. + +## Inline Registration + +When configuring `injectRegister: 'inline'` in the plugin configuration, the plugin will inline a head script adding in to your application entry point: +::: details **inlined head script** +```html + + + +``` +::: + +## Script Registration + +When configuring `injectRegister: 'script'` in the plugin configuration, the plugin will generate a `registerSW.js` script adding it to your application entry point: +::: details **head script** +```html + + + +``` +::: + +::: details **/registerSW.js** +```js +if('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker.register('/sw.js', { scope: '/' }) + }) +} +``` +::: + +## Manual Registration + +When configuring `injectRegister: null` in the plugin configuration, the plugin will do nothing, you must register the service workbox manually yourself. + +Or you can import any of the virtual modules exposed by the plugin. + +## Auto Registration + +If your application code base is not importing any of the virtual modules exposed by the plugin, the plugin will fallback to [Script Registration](/guide/register-service-worker#script-registration), otherwise, the imported virtual module will register the service worker for you. diff --git a/docs/guide/service-worker-precache.md b/docs/guide/service-worker-precache.md new file mode 100644 index 00000000..14a6750a --- /dev/null +++ b/docs/guide/service-worker-precache.md @@ -0,0 +1,50 @@ +--- +title: Service Worker Precache | Guide +--- + +# Service Worker Precache + +As we have mentioned in [Service Worker](/guide/#service-worker) section, service workers act as proxies intercepting requests between the browser and the server. + +Since we are going to add PWA to your application, we need to configure the service worker so that your application can work offline. To do this, we need to configure the service worker's precache manifest, which will include all the resources of your application (basically we need to instruct the service worker what resources to store in cache storage so that it can be used for `network requests interception` and when the application is offline). + +::: tip Network requests interception +You can also configure how to control the network requests interception for any of your application resources. + +You can find more information on [Workbox - Caching Strategies](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#caching-strategies). +::: + +Once the application registers the service worker, the browser will try to install it downloading all the resources in the service worker's precache manifest. Once all the resources downloaded and stored in the cache storage by the browser, it will try to activate the service worker to take the control of the application. + +::: tip +The browser **will only download all the resources** in the service worker's precache manifest if the service worker is not installed (first time the user visit your application) or if there is a new version of your application (if you change some resource in your application, the service worker will also change once you build the application, since its precache manifest is modified to include your changes). + +In any case, the browser **will always download all the resources in a background thread** and not in the main browser thread, this way people can use the application while the browser is trying to install the service worker. + +You can check this website or the [VueUse docs site](https://vueuse.org/) in a private window, just open `Network Tab` on dev tools before visiting the sites: the browser will start download all the resources while you navigate the site. +::: + +## Precache Manifest + +Since `vite-plugin-pwa` plugin uses [workbox-build](https://developer.chrome.com/docs/workbox/modules/workbox-build/) node library to build the service worker, it will only include `css`, `js` and `html` resources in the manifest precache (check the `globPatterns` entry in [GlobPartial](https://developer.chrome.com/docs/workbox/reference/workbox-build/#type-GlobPartial)). + +`workbox-build` node library is file based, that is, it will traverse the build output folder of your application. `Vite` will generate your build in the `dist` folder, and so, `workbox-build` will traverse the `dist` folder adding all resources found in it to the service worker's precache manifest. + +If you need to include another resource types, you will need to add them to the `globPatterns` entry. Depending on the `strategy` configured in the `vite-plugin-pwa` plugin configuration, you will need to add it under the `workbox` or `injectManifest` configuration option. + +You can find more information in the [Static assets handling](/guide/static-assets) section. + +For example, if you need to add `ico`, `png` and `svg` resources in the example from the [Configuring vite-plugin-pwa - Guide](/guide/#configuring-vite-plugin-pwa) section, you will need to add `globPatterns` under `workbox` entry, since we're using the default `vite-plugin-pwa` strategy (`generateSW`): +```ts +import { VitePWA } from 'vite-plugin-pwa' +export default defineConfig({ + plugins: [ + VitePWA({ + registerType: 'autoUpdate', + workbox: { + globPatterns: ['**/*{js,css,html,ico,png,svg}'] + } + }) + ] +}) +``` diff --git a/docs/guide/service-worker-strategies-and-behaviors.md b/docs/guide/service-worker-strategies-and-behaviors.md new file mode 100644 index 00000000..76d6603f --- /dev/null +++ b/docs/guide/service-worker-strategies-and-behaviors.md @@ -0,0 +1,29 @@ +--- +title: Service Worker Strategies And Behaviors | Guide +--- + +# Service Worker Strategies And Behaviors + +A service worker strategy is related to how the `vite-plugin-pwa` plugin will generate your service worker, while the behavior of a service worker is related to how the service worker will work in the browser once the browser detect a new version of your application. + +## Service Worker Strategies + +As we mention in [Configuring vite-plugin-pwa](/guide/#configuring-vite-plugin-pwa) section, `vite-plugin-pwa` plugin will use `workbox-build` node library to generate your service worker. There are 2 available strategies, `generateSW` and `injectManifest`: +- `generateSW`: the `vite-plugin-pwa` will generate the service worker for you, you don't need to write the code for the service worker +- `injectManifest`: the `vite-plugin-pwa` plugin will compile your custom service worker and inject its service worker's precache manifest + +To configure the service worker strategy, use the `strategies`' plugin option with `generateSW` (**default strategy**) or `injectManifest` value. + +You can find more information about the strategies in the [generateSW](/workbox/generate-sw) or [injectManifest](/workbox/inject-manifest) `Workbox` sections. + +## Service Worker Behaviors + +The behavior of the service worker will help you to update the application in the browser, that is, when the browser detects a new version of your application, you can control how the browser updates it. + +You may want to not bother users and just have the browser update the application when there is a new version: the user will only see a reload of the page they are on. + +Or you may want to inform the user that there is a new version of the application, and let the user decide when to update it: simply because you want it to behave that way or because your application requires it (for example, to avoid data loss if the user is filling out a form). + +To configure the service worker behavior, use the `registerType` plugin option with `autoUpdate` or `prompt` (**default strategy**) value. + +You can find more information about the behaviors in the [auto-update](/guide/auto-update) or [prompt-for-update](/guide/prompt-for-update) sections for `generateSW` strategy or in [inject-manifest](/guide/inject-manifest) section for `injectManifest` strategy. diff --git a/docs/guide/static-assets.md b/docs/guide/static-assets.md index f97bb28a..97dd3774 100644 --- a/docs/guide/static-assets.md +++ b/docs/guide/static-assets.md @@ -4,37 +4,23 @@ title: Static assets handling | Guide # Static assets handling -By default, all icons on `PWA Manifest` option found under Vite's `publicDir` option directory, will be included -in the service worker *precache*. You can disable this option using `includeManifestIcons: false`. - -You can also add another static assets such as `favicon`, `svg` and `font` files using `includeAssets` option. -The `includeAssets` option will be resolved using `fast-glob` found under Vite's `publicDir` option directory, and so -you can use regular expressions to include those assets, for example: `includeAssets: ['fonts/*.ttf', 'images/*.png']`. -You don't need to configure `PWA Manifest icons` on `includeAssets` option. - -If you need to include other assets that are not under Vite's `publicDir` option directory, you can use the -`globPatterns` parameter of [workbox](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.generateSW) -or [injectManifest](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.injectManifest) -plugin options. - ->
:::warning::: **WARNING**

-If you configure `globPatterns` on `workbox` or `injectManifest` plugin option, you **MUST** include all your assets -patterns: `globPatterns` will be used by `workbox-build` to match files on `dist` folder. -
-
-By default, `globPatterns` will be `**/*.{js,css,html}`: `workbox` will use -[glob primer](https://github.com/isaacs/node-glob#glob-primer) to match files using `globPatterns` -as filter. -
-
-A common pitfall is to only include some assets and forget to add `css`, `js` and `html` assets pattern, and then your -service worker will complain about missing resources. -
-
-For example, if you don't include `html` assets pattern, you will get this error from your service worker: -**WorkboxError non-precached-url index.html**. -
-
+By default, all icons on `PWA Web App Manifest` option found under `Vite's publicDir` option directory, will be included in the service worker *precache*. You can disable this option using `includeManifestIcons: false`. + +You can also add another static assets such as `favicon`, `svg` and `font` files using `includeAssets` option. The `includeAssets` option will be resolved using `fast-glob` found under Vite's `publicDir` option directory, and so you can use regular expressions to include those assets, for example: `includeAssets: ['fonts/*.ttf', 'images/*.png']`. You don't need to configure `PWA Manifest icons` on `includeAssets` option. + +## globPatterns + +If you need to include other assets that are not under Vite's `publicDir` option directory, you can use the `globPatterns` parameter of [workbox](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.generateSW) or [injectManifest](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.injectManifest) plugin options. + +::: warning +If you configure `globPatterns` on `workbox` or `injectManifest` plugin option, you **MUST** include all your assets patterns: `globPatterns` will be used by `workbox-build` to match files on `dist` folder. + +By default, `globPatterns` will be `**/*.{js,css,html}`: `workbox` will use [glob primer](https://github.com/isaacs/node-glob#glob-primer) to match files using `globPatterns` as filter. + +A common pitfall is to only include some assets and forget to add `css`, `js` and `html` assets pattern, and then your service worker will complain about missing resources. + +For example, if you don't include `html` assets pattern, you will get this error from your service worker: **WorkboxError non-precached-url index.html**. +::: If you use `generateSW` strategy, then you need to configure `globPatterns` inside `workbox` plugin option: diff --git a/docs/guide/testing.md b/docs/guide/testing.md deleted file mode 100644 index 62527904..00000000 --- a/docs/guide/testing.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Testing Service Worker | Guide ---- - -# Testing Service Worker - -Since this plugin will not generate the service worker on `development`, you can test it on local following these steps: - -1) add `serve` script to your `package.json` or modify existing with: -```json -{ - "scripts": { - "serve": "vite preview" - } -} -``` -2) build your app and run `serve`: - - with **YARN**: - ```shell - yarn build && yarn serve - ``` - - with **NPM**: - ```shell - npm run build && npm run serve - ``` - - with **PNPM**: - ```shell - pnpm run build && pnpm run serve - ``` - -## Testing Service Worker over https - -If you want to test your service worker using `https`, follow these steps: - -1) add `https-localhost` as `dev dependency`: - - with **YARN**: - ```shell - yarn add https-localhost -D - ``` - - with **NPM**: - ```shell - npm i https-localhost -D - ``` - - with **PNPM**: - ```shell - pnpm i https-localhost -D - ``` - -2) add `https-preview` script to your `package.json`: - -```json -{ - "scripts": { - "https-preview": "serve dist" - } -} -``` - -3) build your app and run `https-preview`: - - with **YARN**: - ```shell - yarn build && yarn https-preview - ``` - - with **NPM**: - ```shell - npm run build && npm run https-preview - ``` - - with **PNPM**: - ```shell - pnpm run build && pnpm run https-preview - ``` - -First time you run the script, `https-localhost` will ask you about installing `localhost` certificate -(that will be generated for you), confirm installation on OS (keychain on MACOSX and certificate manager on WINDOWS) -and open `https://localhost` on browser. - -If you would like to know more, go to [https-localhost](https://www.npmjs.com/package/https-localhost) . - diff --git a/docs/index.md b/docs/index.md index 18b62f29..7f99feb7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,26 +1,54 @@ --- -home: true +layout: home +sidebar: false -actionText: Get Started -actionLink: /guide/ +title: Vite Plugin PWA + +hero: + name: PWA + text: Vite Plugin + tagline: | + Zero-config and framework-agnostic + PWA Plugin for Vite + image: + light: + src: /icon_light.svg + alt: Vite Plugin PWA + dark: + src: /icon_dark.svg + alt: Vite Plugin PWA + actions: + - theme: brand + text: Get Started + link: /guide/ + - theme: alt + text: View on GitHub + link: https://github.com/antfu/vite-plugin-pwa features: - - title: 👌 Zero-Config + - icon: 👌 + title: Zero-Config details: Sensible built-in default configs for common use cases - - title: 🔩 Extensible + - icon: 🔩 + title: Extensible details: Expose the full ability to customize the behavior of the plugin - - title: 🔌 Offline Support + - icon: 🔌 + title: Offline Support details: Generate Service Worker with Offline support (via Workbox) - - title: ⚡ Fully tree shakable + - icon: ⚡ + title: Fully tree shakable details: Auto inject Web App Manifest - - title: 💬 Prompt for new content + - icon: 💬 + title: Prompt for new content details: Built-in support for Vanilla JavaScript, Vue 3, React, Svelte, SolidJS and Preact - - title: ⚙️ Stale-while-revalidate + - icon: ⚙️ + title: Stale-while-revalidate details: Automatic reload when new content is available - - title: ✨ Static assets handling + - icon: ✨ + title: Static assets handling details: Configure static assets for offline support - - title: 🐞 Development Support + - icon: 🐞 + title: Development Support details: Debug your custom service worker logic as you develop your application -footer: MIT Licensed | Copyright © 2021-PRESENT Anthony Fu --- diff --git a/docs/netlify.toml b/docs/netlify.toml index 0512635c..09ba9959 100644 --- a/docs/netlify.toml +++ b/docs/netlify.toml @@ -6,6 +6,31 @@ publish = "dist" command = "npx pnpm i --store=node_modules/.pnpm-store && npx pnpm run build" +[[redirects]] + from = "/deployment/" + to = "/deployment/index.html" + status = 200 + +[[redirects]] + from = "/examples/" + to = "/examples/index.html" + status = 200 + +[[redirects]] + from = "/frameworks/" + to = "/frameworks/index.html" + status = 200 + +[[redirects]] + from = "/guide/" + to = "/guide/index.html" + status = 200 + +[[redirects]] + from = "/workbox/" + to = "/workbox/index.html" + status = 200 + [[redirects]] from = "/*" to = "/index.html" @@ -14,4 +39,4 @@ [[headers]] for = "/manifest.webmanifest" [headers.values] - Content-Type = "application/manifest+json" \ No newline at end of file + Content-Type = "application/manifest+json" diff --git a/docs/package.json b/docs/package.json index 1263c100..5955b514 100644 --- a/docs/package.json +++ b/docs/package.json @@ -5,31 +5,29 @@ "scripts": { "dev": "vitepress dev", "build": "vitepress build && esno scripts/build.ts", + "preview": "npm run build && vitepress serve", "serve": "npm run build && serve .vitepress/dist" }, "dependencies": { "@vueuse/core": "^8.5.0", "@vueuse/shared": "^8.5.0", - "vue": "^3.2.35", - "vue-global-api": "^0.4.1" + "vue": "^3.2.37" }, "devDependencies": { - "@iconify/json": "^2.1.47", - "@rollup/plugin-replace": "^4.0.0", "@types/fs-extra": "^9.0.13", + "@vitejs/plugin-vue": "^2.3.3", "@vueuse/core": "^8.5.0", "esbuild-register": "^3.3.2", "eslint": "^8.16.0", "fast-glob": "^3.2.11", "fs-extra": "^10.1.0", "https-localhost": "^4.7.1", - "prism-theme-vars": "^0.2.3", "typescript": "^4.6.4", - "unplugin-icons": "^0.14.3", + "unocss": "^0.38.1", "unplugin-vue-components": "^0.19.5", "vite": "^2.9.9", "vite-plugin-pwa": "workspace:*", - "vite-plugin-windicss": "^1.8.4", - "vitepress": "^0.22.4" + "vitepress": "^1.0.0-alpha.4", + "workbox-window": "^6.5.3" } } diff --git a/docs/plugins/navbar.ts b/docs/plugins/navbar.ts new file mode 100644 index 00000000..2954106a --- /dev/null +++ b/docs/plugins/navbar.ts @@ -0,0 +1,70 @@ +import type { Plugin } from 'vite' + +export default function NavbarFix(): Plugin { + return { + name: 'vitepress-sidebar-logo-fix', + enforce: 'pre', + transform(code, id) { + if (id.includes('VPNavBarTitle.vue') && !id.endsWith('.css')) { + return ` + + + + + +` + } + }, + } +} diff --git a/docs/public/icon_dark.svg b/docs/public/icon_dark.svg index b4e3c4e8..df53cac5 100644 --- a/docs/public/icon_dark.svg +++ b/docs/public/icon_dark.svg @@ -1,4 +1,4 @@ - + diff --git a/docs/public/icon_gray.svg b/docs/public/icon_gray.svg new file mode 100644 index 00000000..c683dd29 --- /dev/null +++ b/docs/public/icon_gray.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/public/icon_light.svg b/docs/public/icon_light.svg index 6f06c886..d4936c5e 100644 --- a/docs/public/icon_light.svg +++ b/docs/public/icon_light.svg @@ -1,5 +1,5 @@ - + - + diff --git a/docs/scripts/assets.ts b/docs/scripts/assets.ts index 1a8cd639..4dbf8fa7 100644 --- a/docs/scripts/assets.ts +++ b/docs/scripts/assets.ts @@ -43,20 +43,21 @@ export const optimizePages = async () => { - ${preloadImg}\n`).trim() - - html = html.replace( - '', - '\t\n', - ) + ${preloadImg} + \n`).trim() + // html = html.replace( + // '', + // '\t\n', + // ) + // html = html.replace(/aria-hidden="true"/gi, 'tabindex="-1" aria-hidden="true"') await fs.writeFile(i, html, 'utf-8') diff --git a/docs/vite.config.ts b/docs/vite.config.ts index d9e5fbec..dcde7f10 100644 --- a/docs/vite.config.ts +++ b/docs/vite.config.ts @@ -1,20 +1,19 @@ import { defineConfig } from 'vite' import Components from 'unplugin-vue-components/vite' -import WindiCSS from 'vite-plugin-windicss' -import Icons from 'unplugin-icons/vite' -import IconsResolver from 'unplugin-icons/resolver' -import replace from '@rollup/plugin-replace' +import { presetUno } from 'unocss' +import Unocss from 'unocss/vite' import { VitePWA } from '../dist' -import { version } from '../package.json' +import NavbarFix from './plugins/navbar' export default defineConfig({ build: { + // sourcemap: true, + // minify: false, ssrManifest: false, manifest: false, }, optimizeDeps: { exclude: [ - 'vue-global-api', '@vueuse/core', ], }, @@ -24,11 +23,6 @@ export default defineConfig({ }, }, plugins: [ - replace({ - preventAssignment: true, - __PWA_VERSION__: version, - }), - // https://github.com/antfu/vite-plugin-components Components({ dirs: [ @@ -41,38 +35,21 @@ export default defineConfig({ include: [/\.vue$/, /\.vue\?vue/, /\.md$/], // generate `components.d.ts` for ts support with Volar - dts: false, - // auto import icons - resolvers: [ - // https://github.com/antfu/vite-plugin-icons - IconsResolver({ - componentPrefix: '', - // enabledCollections: ['carbon'], - }), - ], + dts: '.vitepress/components.d.ts', }), - // https://github.com/antfu/vite-plugin-icons - Icons(), + NavbarFix(), - // https://github.com/antfu/vite-plugin-windicss - WindiCSS(), + // https://github.com/unocss/unocss + Unocss({ + presets: [presetUno()], + }), // https://github.com/antfu/vite-plugin-pwa VitePWA({ outDir: '.vitepress/dist', registerType: 'prompt', - includeAssets: [ - 'favicon.svg', - 'favicon.ico', - 'robots.txt', - 'safari-pinned-tab.svg', - 'banner_light.svg', - 'banner_dark.svg', - 'icon_light.svg', - 'icon_dark.svg', - 'prompt-update.png', - ], + includeManifestIcons: false, manifest: { id: '/', name: 'Vite Plugin PWA', @@ -99,6 +76,7 @@ export default defineConfig({ ], }, workbox: { + globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'], runtimeCaching: [ { urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i, diff --git a/docs/windi.config.ts b/docs/windi.config.ts deleted file mode 100644 index b98ffeb4..00000000 --- a/docs/windi.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { defineConfig } from 'vite-plugin-windicss' - -export default defineConfig({ - preflight: false, - extract: { - include: [ - '.vitepress/**/*.vue', - ], - }, - theme: { - extend: { - colors: { - primary: '#2e859c', - }, - }, - }, -}) diff --git a/docs/workbox/generate-sw.md b/docs/workbox/generate-sw.md index 7c699967..5dc9c337 100644 --- a/docs/workbox/generate-sw.md +++ b/docs/workbox/generate-sw.md @@ -4,29 +4,21 @@ title: generateSW | Workbox # generateSW -You must read [Which Mode to Use](https://developers.google.com/web/tools/workbox/modules/workbox-build#which_mode_to_use) -before decide using this strategy on `vite-plugin-pwa` plugin. +You must read [Which Mode to Use](https://developer.chrome.com/docs/workbox/modules/workbox-build/#which-mode-to-use) before decide using this strategy on `vite-plugin-pwa` plugin. -You can find the documentation for this method on `workbox` site: [generateSW](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.generateSW) . +You can find the documentation for this method on `workbox` site: [generateSW](https://developer.chrome.com/docs/workbox/reference/workbox-build/#method-generateSW). -You can find a guide for plugins on `workbox` site: [Using Plugins](https://developers.google.com/web/tools/workbox/guides/using-plugins) . +You can find a guide for plugins on `workbox` site: [Using Plugins](https://developers.google.com/web/tools/workbox/guides/using-plugins). ## Cache External Resources -If you use some `CDN` to download some resources like `fonts` and `css`, you must include them into the service worker -precache, and so your application will work when offline. - -> You also need to add the logic to interact from the client logic: [Generate Service Worker](/guide/generate.html). +If you use some `CDN` to download some resources like `fonts` and `css`, you must include them into the service worker precache, and so your application will work when offline. The following example will use `css` from `https://fonts.googleapis.com` and `fonts` from `https://fonts.gstatic.com`. -On `index.html` file you must configure the `css` `link`, you **MUST** also include `crossorigin="anonymous"` attribute -for the external resources -(see [Handle Third Party Requests](https://developers.google.com/web/tools/workbox/guides/handle-third-party-requests) ): - -
-
index.html code +On `index.html` file you must configure the `css` `link`, you **MUST** also include `crossorigin="anonymous"` attribute for the external resources (see [Handle Third Party Requests](https://developers.google.com/web/tools/workbox/guides/handle-third-party-requests)): +::: details index.html ```html @@ -36,13 +28,11 @@ for the external resources ``` -
+::: Then on your `vite.config.ts` file add the following code: -
- VitePWA options code - +::: details VitePWA options ```ts VitePWA({ workbox: { @@ -79,17 +69,29 @@ VitePWA({ } }) ``` -
+::: -## Background Sync +## Exclude routes -You can add this code to the plugin on your `vite.config.ts` file to add a `Background Sync` manager to your service worker: +To exclude some routes from being intercepted by the service worker, you just need to add those routes using a `regex` list to the `navigateFallbackDenylist` option of `workbox`: -> You also need to add the logic to interact from the client logic: [Generate Service Worker](/guide/generate.html). +```ts +VitePWA({ + workbox: { + navigateFallbackDenylist: [/^\/backoffice/] + } +}) +``` + +::: warning +You must deal with offline support for excluded routes: if requesting a page excluded on `navigateFallbackDenylist` you will get `No internet connection`. +::: -
- VitePWA options code +## Background Sync + +You can add this code to the plugin on your `vite.config.ts` file to add a `Background Sync` manager to your service worker: +::: details VitePWA options ```ts VitePWA({ workbox: { @@ -109,4 +111,4 @@ VitePWA({ } }) ``` -
+::: diff --git a/docs/workbox/index.md b/docs/workbox/index.md index 5f696515..d60d3d82 100644 --- a/docs/workbox/index.md +++ b/docs/workbox/index.md @@ -4,33 +4,21 @@ title: Getting Started | Workbox # Getting Started -[**Workbox**](https://developers.google.com/web/tools/workbox/) is a massive package with many modules to make service worker development more enjoyable and remove the need to deal with the low-level service worker API. +[**Workbox**](https://developers.google.com/web/tools/workbox/) is a massive package with many modules to make service worker development more enjoyable and remove the need to deal with the low-level service worker API. -In this document, we focus only on the -[workbox-build](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build) -module from **Workbox**. +In this document, we focus only on the [workbox-build](https://developer.chrome.com/docs/workbox/reference/workbox-build/) module from **Workbox**. ## workbox-build module This module is for build process purposes (a `node` module); that is, `Vite Plugin PWA` will use it to build your service-worker. We focus on 2 methods of this module: +- [generateSW](/workbox/generate-sw): for generating the service worker. +- [injectManifest](/workbox/inject-manifest): for when you need more control over your service worker. -
    - - - - - - - - -
+You should read [Which Mode to Use](https://developer.chrome.com/docs/workbox/modules/workbox-build/#which-mode-to-use) before deciding which strategy to use. -You should read [Which Mode to Use](https://developers.google.com/web/tools/workbox/modules/workbox-build#which_mode_to_use) before deciding which strategy to use. - -In short, the `generateSW` function abstracts away the need to work directly with the service worker API when building the service worker. This method can be configured using plugins instead of writing your own service worker code (`generateSW` will generate -the code for you). +In short, the `generateSW` function abstracts away the need to work directly with the service worker API when building the service worker. This method can be configured using plugins instead of writing your own service worker code (`generateSW` will generate the code for you). While the `injectManifest` method will use your existing service worker and build/compile it. @@ -38,7 +26,6 @@ While the `injectManifest` method will use your existing service worker and buil `vite-plugin-pwa` uses `generateSW` and `injectManifest` `workbox` methods internally when the `strategies` option is set to `generateSW` and `injectManifest` respectively. -When you configure `strategies: 'generateSW'` option (the default value) in your `vite.config.*` file, the -plugin invokes workbox' `generateSW` method. The options passed to the `workbox-build` method will be those provided via the `workbox` option of the plugin configuration. +When you configure `strategies: 'generateSW'` option (the default value) in your `vite.config.*` file, the plugin invokes workbox' `generateSW` method. The options passed to the `workbox-build` method will be those provided via the `workbox` option of the plugin configuration. When you configure `strategies: with the 'injectManifest'` option, the plugin will first build your custom service worker via `rollup`. With the build result, vite-plugin-pwa will call Workbox' `injectManifest` method passing those options provided via the `workbox` option of the plugin configuration. diff --git a/docs/workbox/inject-manifest.md b/docs/workbox/inject-manifest.md index 219b783c..602f070c 100644 --- a/docs/workbox/inject-manifest.md +++ b/docs/workbox/inject-manifest.md @@ -4,22 +4,42 @@ title: injectManifest | Workbox # injectManifest -You must read [Which Mode to Use](https://developers.google.com/web/tools/workbox/modules/workbox-build#which_mode_to_use) -before decide using this strategy on `vite-plugin-pwa` plugin. +You must read [Which Mode to Use](https://developer.chrome.com/docs/workbox/modules/workbox-build/#which-mode-to-use) before decide using this strategy on `vite-plugin-pwa` plugin. -Before writing your custom service worker, check if `workbox` can generate the code for you using `generateSW` strategy, -looking for some plugin on `workbox` site on [Runtime Caching Entry](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.RuntimeCachingEntry) . +Before writing your custom service worker, check if `workbox` can generate the code for you using `generateSW` strategy, looking for some plugin on `workbox` site on [Runtime Caching Entry](https://developer.chrome.com/docs/workbox/reference/workbox-build/#type-RuntimeCaching). -You can find the documentation for this method on `workbox` site: [injectManifest](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.injectManifest) +You can find the documentation for this method on `workbox` site: [injectManifest](https://developer.chrome.com/docs/workbox/reference/workbox-build/#method-injectManifest) -## Network First Strategy -You can use the following code to create your custom service worker to be used with network first strategy. We also include -how to configure [Custom Cache Network Race Strategy](https://jakearchibald.com/2014/offline-cookbook/#cache--network-race) . +## Exclude routes -
- VitePWA options code +To exclude some routes from being intercepted by the service worker, you just need to add those routes using a `regex` array to the `denylist` option of `NavigationRoute`: +```ts +import { createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching' +import { NavigationRoute, registerRoute } from 'workbox-routing' + +declare let self: ServiceWorkerGlobalScope + +// self.__WB_MANIFEST is default injection point +precacheAndRoute(self.__WB_MANIFEST) + +// to allow work offline +registerRoute(new NavigationRoute( + createHandlerBoundToURL('index.html'), + { denylist: [/^\/backoffice/] }, +)) +``` + +::: warning +You must deal with offline support for excluded routes: if requesting a page included on `denylist` you will get `No internet connection`. +::: + +## Network First Strategy + +You can use the following code to create your custom service worker to be used with network first strategy. We also include how to configure [Custom Cache Network Race Strategy](https://jakearchibald.com/2014/offline-cookbook/#cache--network-race). + +::: details VitePWA options ```ts VitePWA({ strategies: 'injectManifest', @@ -27,20 +47,19 @@ VitePWA({ filename: 'sw.ts' }) ``` -
+::: -> You also need to add the logic to interact from the client logic: [Advanced (injectManifest)](/guide/inject-manifest.html). +::: warning +You also need to add the logic to interact from the client logic: [Advanced (injectManifest)](/guide/inject-manifest). +::: -Then in your `src/sw.ts` file, remember you will also need to add following `workbox` dependencies as `dev` -dependencies: +Then in your `src/sw.ts` file, remember you will also need to add following `workbox` dependencies as `dev` dependencies: - `workbox-core` - `workbox-routing` - `workbox-strategies` - `workbox-build` -
- src/sw.ts code - +::: details src/sw.ts ```ts import { cacheNames, clientsClaim } from 'workbox-core' import { registerRoute, setCatchHandler, setDefaultHandler } from 'workbox-routing' @@ -169,7 +188,7 @@ setCatchHandler(({ event }): Promise => { self.skipWaiting() clientsClaim() ``` -
+::: ## Server Push Notifications diff --git a/examples/vue-basic-cdn/package.json b/examples/vue-basic-cdn/package.json index 7e01708e..b3e54381 100644 --- a/examples/vue-basic-cdn/package.json +++ b/examples/vue-basic-cdn/package.json @@ -10,12 +10,11 @@ "serve": "serve dist" }, "dependencies": { - "vue": "^3.2.35" + "vue": "^3.2.37" }, "devDependencies": { "@rollup/plugin-replace": "^4.0.0", "@vitejs/plugin-vue": "^2.3.3", - "@vue/compiler-sfc": "^3.2.35", "@vueuse/core": "^8.5.0", "cross-env": "^7.0.3", "https-localhost": "^4.7.1", diff --git a/examples/vue-router/package.json b/examples/vue-router/package.json index 1b526a0c..f12d7a25 100644 --- a/examples/vue-router/package.json +++ b/examples/vue-router/package.json @@ -25,13 +25,12 @@ "serve": "serve dist" }, "dependencies": { - "vue": "^3.2.35", + "vue": "^3.2.37", "vue-router": "^4.0.15" }, "devDependencies": { "@rollup/plugin-replace": "^4.0.0", "@vitejs/plugin-vue": "^2.3.3", - "@vue/compiler-sfc": "^3.2.35", "@vueuse/core": "^8.5.0", "cross-env": "^7.0.3", "https-localhost": "^4.7.1", diff --git a/package.json b/package.json index c6925d89..51c6e8b3 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "docs": "npm -C docs run dev", "docs:build": "npm -C docs run build", "docs:serve": "npm -C docs run serve", + "docs:preview": "npm -C docs run preview", "lint": "eslint .", "dev": "esno scripts/dev.ts", "build": "esno scripts/build.ts", @@ -81,6 +82,6 @@ "tsup": "^6.1.0", "typescript": "^4.7.3", "vite": "^2.9.9", - "vue": "^3.2.36" + "vue": "^3.2.37" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 118f4fc3..5073c4ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,7 +27,7 @@ importers: tsup: ^6.1.0 typescript: ^4.7.3 vite: ^2.9.9 - vue: ^3.2.36 + vue: ^3.2.37 workbox-build: ^6.5.3 workbox-window: ^6.5.3 dependencies: @@ -57,13 +57,12 @@ importers: tsup: 6.1.0_typescript@4.7.3 typescript: 4.7.3 vite: 2.9.9 - vue: 3.2.36 + vue: 3.2.37 docs: specifiers: - '@iconify/json': ^2.1.47 - '@rollup/plugin-replace': ^4.0.0 '@types/fs-extra': ^9.0.13 + '@vitejs/plugin-vue': ^2.3.3 '@vueuse/core': ^8.5.0 '@vueuse/shared': ^8.5.0 esbuild-register: ^3.3.2 @@ -71,38 +70,33 @@ importers: fast-glob: ^3.2.11 fs-extra: ^10.1.0 https-localhost: ^4.7.1 - prism-theme-vars: ^0.2.3 typescript: ^4.6.4 - unplugin-icons: ^0.14.3 + unocss: ^0.38.1 unplugin-vue-components: ^0.19.5 vite: ^2.9.9 vite-plugin-pwa: workspace:* - vite-plugin-windicss: ^1.8.4 - vitepress: ^0.22.4 - vue: ^3.2.35 - vue-global-api: ^0.4.1 - dependencies: - '@vueuse/core': 8.5.0_vue@3.2.35 - '@vueuse/shared': 8.5.0_vue@3.2.35 - vue: 3.2.35 - vue-global-api: 0.4.1_vue@3.2.35 + vitepress: ^1.0.0-alpha.4 + vue: ^3.2.37 + workbox-window: ^6.5.3 + dependencies: + '@vueuse/core': 8.5.0_vue@3.2.37 + '@vueuse/shared': 8.5.0_vue@3.2.37 + vue: 3.2.37 devDependencies: - '@iconify/json': 2.1.47 - '@rollup/plugin-replace': 4.0.0 '@types/fs-extra': 9.0.13 + '@vitejs/plugin-vue': 2.3.3_vite@2.9.9+vue@3.2.37 esbuild-register: 3.3.2 eslint: 8.16.0 fast-glob: 3.2.11 fs-extra: 10.1.0 https-localhost: 4.7.1 - prism-theme-vars: 0.2.3 typescript: 4.6.4 - unplugin-icons: 0.14.3_vite@2.9.9 - unplugin-vue-components: 0.19.5_vite@2.9.9+vue@3.2.35 + unocss: 0.38.1_vite@2.9.9 + unplugin-vue-components: 0.19.5_vite@2.9.9+vue@3.2.37 vite: 2.9.9 vite-plugin-pwa: link:.. - vite-plugin-windicss: 1.8.4_vite@2.9.9 - vitepress: 0.22.4 + vitepress: 1.0.0-alpha.4 + workbox-window: 6.5.3 examples/preact-router: specifiers: @@ -282,7 +276,7 @@ importers: devDependencies: '@rollup/plugin-replace': 4.0.0 '@sveltejs/adapter-static': 1.0.0-next.34 - '@sveltejs/kit': 1.0.0-next.348_svelte@3.48.0 + '@sveltejs/kit': 1.0.0-next.352_svelte@3.48.0 '@typescript-eslint/eslint-plugin': 5.25.0_jorowkvdqu6pwramweg5le7ncu '@typescript-eslint/parser': 5.25.0_utdtartgf6fqqgkivzeynh76la cross-env: 7.0.3 @@ -305,21 +299,19 @@ importers: specifiers: '@rollup/plugin-replace': ^4.0.0 '@vitejs/plugin-vue': ^2.3.3 - '@vue/compiler-sfc': ^3.2.35 '@vueuse/core': ^8.5.0 cross-env: ^7.0.3 https-localhost: ^4.7.1 typescript: ^4.6.4 vite: ^2.9.9 vite-plugin-pwa: workspace:* - vue: ^3.2.35 + vue: ^3.2.37 dependencies: - vue: 3.2.35 + vue: 3.2.37 devDependencies: '@rollup/plugin-replace': 4.0.0 - '@vitejs/plugin-vue': 2.3.3_vite@2.9.9+vue@3.2.35 - '@vue/compiler-sfc': 3.2.35 - '@vueuse/core': 8.5.0_vue@3.2.35 + '@vitejs/plugin-vue': 2.3.3_vite@2.9.9+vue@3.2.37 + '@vueuse/core': 8.5.0_vue@3.2.37 cross-env: 7.0.3 https-localhost: 4.7.1 typescript: 4.6.4 @@ -330,7 +322,6 @@ importers: specifiers: '@rollup/plugin-replace': ^4.0.0 '@vitejs/plugin-vue': ^2.3.3 - '@vue/compiler-sfc': ^3.2.35 '@vueuse/core': ^8.5.0 cross-env: ^7.0.3 https-localhost: ^4.7.1 @@ -338,20 +329,19 @@ importers: typescript: ^4.6.4 vite: ^2.9.9 vite-plugin-pwa: workspace:* - vue: ^3.2.35 + vue: ^3.2.37 vue-router: ^4.0.15 workbox-core: ^6.5.3 workbox-precaching: ^6.5.3 workbox-routing: ^6.5.3 workbox-window: ^6.5.3 dependencies: - vue: 3.2.35 - vue-router: 4.0.15_vue@3.2.35 + vue: 3.2.37 + vue-router: 4.0.15_vue@3.2.37 devDependencies: '@rollup/plugin-replace': 4.0.0 - '@vitejs/plugin-vue': 2.3.3_vite@2.9.9+vue@3.2.35 - '@vue/compiler-sfc': 3.2.35 - '@vueuse/core': 8.5.0_vue@3.2.35 + '@vitejs/plugin-vue': 2.3.3_vite@2.9.9+vue@3.2.37 + '@vueuse/core': 8.5.0_vue@3.2.37 cross-env: 7.0.3 https-localhost: 4.7.1 rimraf: 3.0.2 @@ -2278,7 +2268,7 @@ packages: resolution: {integrity: sha512-5XSK+xbP0hcTIp54MECqxkWLs6kf7Ug4nWdxWNtx8cUpLiFNFnKXDxCb35wnyNpjukmrx7Q9DkO5tFFsmNVxng==} dependencies: '@docsearch/react': 3.1.0 - preact: 10.7.2 + preact: 10.7.3 transitivePeerDependencies: - '@types/react' - react @@ -2329,13 +2319,6 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@iconify/json/2.1.47: - resolution: {integrity: sha512-Q+0mMJ3/1n+Q0V2LcFbUKT/bykrQXL6bXJyulstPh2zjerKkGiTEXD0h7ov9JncGXKod+kEYgSc4do5MG4fawA==} - dependencies: - '@iconify/types': 1.1.0 - pathe: 0.2.0 - dev: true - /@iconify/types/1.1.0: resolution: {integrity: sha512-Jh0llaK2LRXQoYsorIH8maClebsnzTcve+7U3rQUSnC11X4jtPnFuyatqFLvMxZ8MLG8dB4zfHsbPfuvxluONw==} dev: true @@ -2394,6 +2377,10 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.11.0 + /@polka/url/1.0.0-next.21: + resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} + dev: true + /@preact/preset-vite/2.2.0_preact@10.7.2+vite@2.9.9: resolution: {integrity: sha512-xOtPzyVSPphUF/tRnzjxkCR/ovbCS6O25ekdCw5MGKcaAkb6PDRo50tS1x2n0+O9qL7Z/qrHJKpyCVn29A4iMg==} peerDependencies: @@ -2584,18 +2571,18 @@ packages: tiny-glob: 0.2.9 dev: true - /@sveltejs/kit/1.0.0-next.348_svelte@3.48.0: - resolution: {integrity: sha512-K9dfgzIbotWmbcdCsQ6ROGs9R+bsGWwmSdN6l6km1QV5esQehqg1UYHGD9q0VJsg4rJg/zmKVBYo0oBquSHPZw==} + /@sveltejs/kit/1.0.0-next.352_svelte@3.48.0: + resolution: {integrity: sha512-cYQWGZ2TU1iMsh1cqi44FJm5Aqs3iOkuUOnRpoecthcbmiZaqkD1sPG/uROBIPexXSbfyUfrck/hgr9vdCAmCw==} engines: {node: '>=16.7'} hasBin: true peerDependencies: svelte: ^3.44.0 dependencies: - '@sveltejs/vite-plugin-svelte': 1.0.0-next.47_svelte@3.48.0+vite@2.9.9 + '@sveltejs/vite-plugin-svelte': 1.0.0-next.49_svelte@3.48.0+vite@2.9.10 chokidar: 3.5.3 sade: 1.8.1 svelte: 3.48.0 - vite: 2.9.9 + vite: 2.9.10 transitivePeerDependencies: - diff-match-patch - less @@ -2627,8 +2614,8 @@ packages: - supports-color dev: true - /@sveltejs/vite-plugin-svelte/1.0.0-next.47_svelte@3.48.0+vite@2.9.9: - resolution: {integrity: sha512-J6n8UN51aq/TEZGQ89/EtdXTtca3cRcTJGzi6fi+xK8LkgsHQLCZhRj+PJ+swktRSWTX9IOmQS55SqVg6bz5fA==} + /@sveltejs/vite-plugin-svelte/1.0.0-next.49_svelte@3.48.0+vite@2.9.10: + resolution: {integrity: sha512-AKh0Ka8EDgidnxWUs8Hh2iZLZovkETkefO99XxZ4sW4WGJ7VFeBx5kH/NIIGlaNHLcrIvK3CK0HkZwC3Cici0A==} engines: {node: ^14.13.1 || >= 16} peerDependencies: diff-match-patch: ^1.0.5 @@ -2645,7 +2632,7 @@ packages: magic-string: 0.26.2 svelte: 3.48.0 svelte-hmr: 0.14.12_svelte@3.48.0 - vite: 2.9.9 + vite: 2.9.10 transitivePeerDependencies: - supports-color dev: true @@ -3079,6 +3066,140 @@ packages: eslint-visitor-keys: 3.3.0 dev: true + /@unocss/cli/0.38.1: + resolution: {integrity: sha512-R4PcnzXK+mb9FJSsLIQ5oiAin5NliZta9bVSu5K8xQ4A3L17zPY8e8V8XV778rxkmKWu2BA9dFXmoywqev/elw==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@unocss/config': 0.38.1 + '@unocss/core': 0.38.1 + '@unocss/preset-uno': 0.38.1 + cac: 6.7.12 + chokidar: 3.5.3 + colorette: 2.0.17 + consola: 2.15.3 + fast-glob: 3.2.11 + pathe: 0.3.0 + perfect-debounce: 0.1.3 + dev: true + + /@unocss/config/0.38.1: + resolution: {integrity: sha512-+9OPsc7WjuZKF9HV7F1PF4sQq3h0vu+Plc3ehpPZVZdQCWcstZ4edOA4LZtLvQM+h75cuLYRdC0fSR+r1NtnqQ==} + engines: {node: '>=14'} + dependencies: + '@unocss/core': 0.38.1 + unconfig: 0.3.4 + dev: true + + /@unocss/core/0.38.1: + resolution: {integrity: sha512-X9nYsiDn/ePvP8pq6b3UZgT1J+Ai6PqBbY5HKmJrKbV9eqrbRcBA/oajK5mHPUSmbSC8nBhhJJz7sz4o5CUzpA==} + dev: true + + /@unocss/inspector/0.38.1: + resolution: {integrity: sha512-Xgc8nVUGp0oh6J5KJrJEQIrDmrOSsDDkpq3z2HBIdO6CubrLImzvZmKWFhh+K+QEh7MlhVxFoFcco9GJ6WsmTw==} + dependencies: + gzip-size: 6.0.0 + sirv: 2.0.2 + dev: true + + /@unocss/preset-attributify/0.38.1: + resolution: {integrity: sha512-tsnQArFD0mGIESdk0y2v2tm5YHL15VAKYf0BGIVvCyax9nUOXELc2pdpyZg7PglLkIMC7Oh5HLGu/RcC1+NBJw==} + dependencies: + '@unocss/core': 0.38.1 + dev: true + + /@unocss/preset-icons/0.38.1: + resolution: {integrity: sha512-D4Mf17BRqqntkBhHyW3GTvSWmntTIvrEIa5a9UHU1nhwpf5d/7to+bp+eNoPUo2IddnLTFfgx+B+PsWL39VKiA==} + dependencies: + '@iconify/utils': 1.0.32 + '@unocss/core': 0.38.1 + ohmyfetch: 0.4.18 + transitivePeerDependencies: + - supports-color + dev: true + + /@unocss/preset-mini/0.38.1: + resolution: {integrity: sha512-5NEoX1I84SqRZcxbSK6qnsHxxdEKFV1M+5pnodphhztO0zBAWCDHeq+IP4QYH1OXbWd9dOzH7C1eKOsNm/MHxg==} + dependencies: + '@unocss/core': 0.38.1 + dev: true + + /@unocss/preset-tagify/0.38.1: + resolution: {integrity: sha512-bV+DDWE05/4Aws44I2AIIfeSra9PiOOqOebYD+XtYl8DS1li+jGBkgs2QSxKTCt1FzWJvlAzcTKSqRXEkuhCLw==} + dependencies: + '@unocss/core': 0.38.1 + dev: true + + /@unocss/preset-typography/0.38.1: + resolution: {integrity: sha512-ukAcYc7StT2SffcqibEu8hheIvd16gUdqiZwKuDjc1o3aF8qDOqFHbPQ9G+XapXEaE6OWAMfJit+jK4JQljAOA==} + dependencies: + '@unocss/core': 0.38.1 + dev: true + + /@unocss/preset-uno/0.38.1: + resolution: {integrity: sha512-P3KhGJLpQmiGZl2N8AiqAP9djaD416IhvW08bgwMlYlKKLruicYQC9AM9Obv2N5UwY4I+xUpV4B6aHrMnU8Dww==} + dependencies: + '@unocss/core': 0.38.1 + '@unocss/preset-mini': 0.38.1 + '@unocss/preset-wind': 0.38.1 + dev: true + + /@unocss/preset-web-fonts/0.38.1: + resolution: {integrity: sha512-Q+2w7stTKIbaHsEMZJqLdhuIGFmsWOCLeaAWnuySQN04EIoe1jIWSmOJFDIcA3mijtdT8EaCi+b8hyGe46RXiA==} + dependencies: + '@unocss/core': 0.38.1 + ohmyfetch: 0.4.18 + dev: true + + /@unocss/preset-wind/0.38.1: + resolution: {integrity: sha512-vCZuj6RalDGNKiIjUdtJNfkLql4dxqkRUW9Eeu2xpQuzRwGdg3u1AV8RApIuq4RmIkar4ZJp35JPSYb7JcE7jw==} + dependencies: + '@unocss/core': 0.38.1 + '@unocss/preset-mini': 0.38.1 + dev: true + + /@unocss/reset/0.38.1: + resolution: {integrity: sha512-nMdOEuDZkWmaarwFqORJVtWW5BEbpart2jXcq7er1lkIn5mKsgimOTwnvooysX86OqrqRl4HWKhf7xhZS1MG2A==} + dev: true + + /@unocss/scope/0.38.1: + resolution: {integrity: sha512-svuMmUDAKnn3Oa+v23FUim9bmZXrKTB15FLGcEEs87Xnt1gkFAQb4yiLHjqnAOGbVeEVGt34n0/eNC/zzlVyBg==} + dev: true + + /@unocss/transformer-compile-class/0.38.1: + resolution: {integrity: sha512-BvcDE2sEXLKMgcss3iPcgv0V5x0tRjuPEs0GLti1EIKQum8qYWgZXdwOoGr5NLuKI7k+LmDjKwETb1V/JYUTgg==} + dependencies: + '@unocss/core': 0.38.1 + dev: true + + /@unocss/transformer-directives/0.38.1: + resolution: {integrity: sha512-qK1xLRgM3VrmT+uteC+AFvZzhac0cdVrxK+pBN43oj6ZfMYhtbfJn0Gwpj71mYwZhL1/lJqPud9AAUPm+NR6yQ==} + dependencies: + '@unocss/core': 0.38.1 + css-tree: 2.1.0 + dev: true + + /@unocss/transformer-variant-group/0.38.1: + resolution: {integrity: sha512-d9TfCEqkpAHlF7GIJRrvdrL6hVEm8mIDr14+u+O0fM+qHLqQQfVNB0+7NpdB0va6Nj0WfaVEQacX7rlp6JeqpA==} + dependencies: + '@unocss/core': 0.38.1 + dev: true + + /@unocss/vite/0.38.1_vite@2.9.9: + resolution: {integrity: sha512-f4WNUJiorQYf/ZYlNnp96CN9FeXBuX6f0mNlMAbnwyiiUWroQDMx8fHOnFSrqljKIBY3jJWW1cZ9Izp1IEh8Rg==} + peerDependencies: + vite: ^2.9.0 + dependencies: + '@rollup/pluginutils': 4.2.1 + '@unocss/config': 0.38.1 + '@unocss/core': 0.38.1 + '@unocss/inspector': 0.38.1 + '@unocss/scope': 0.38.1 + '@unocss/transformer-directives': 0.38.1 + magic-string: 0.26.2 + vite: 2.9.9 + dev: true + /@vitejs/plugin-react-refresh/1.3.6: resolution: {integrity: sha512-iNR/UqhUOmFFxiezt0em9CgmiJBdWR+5jGxB2FihaoJfqGt76kiwaKoVOJVU5NYcDWMdN06LbyN2VIGIoYdsEA==} engines: {node: '>=12.0.0'} @@ -3092,178 +3213,105 @@ packages: - supports-color dev: true - /@vitejs/plugin-vue/2.3.3_vite@2.9.9+vue@3.2.35: + /@vitejs/plugin-vue/2.3.3_vite@2.9.10+vue@3.2.37: resolution: {integrity: sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==} engines: {node: '>=12.0.0'} peerDependencies: vite: ^2.5.10 vue: ^3.2.25 dependencies: - vite: 2.9.9 - vue: 3.2.35 + vite: 2.9.10 + vue: 3.2.37 dev: true - /@vue/compiler-core/3.2.35: - resolution: {integrity: sha512-1Mtmh8ceVUoUsn/PME5oM+Dus648rCeV/fBaZ4ERLFbTHBJXj6QmDPrSn9mfEyPDXE0RYIwyJNn884NdWK+Yiw==} + /@vitejs/plugin-vue/2.3.3_vite@2.9.9+vue@3.2.37: + resolution: {integrity: sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==} + engines: {node: '>=12.0.0'} + peerDependencies: + vite: ^2.5.10 + vue: ^3.2.25 dependencies: - '@babel/parser': 7.17.9 - '@vue/shared': 3.2.35 - estree-walker: 2.0.2 - source-map: 0.6.1 + vite: 2.9.9 + vue: 3.2.37 + dev: true - /@vue/compiler-core/3.2.36: - resolution: {integrity: sha512-bbyZM5hvBicv0PW3KUfVi+x3ylHnfKG7DOn5wM+f2OztTzTjLEyBb/5yrarIYpmnGitVGbjZqDbODyW4iK8hqw==} + /@vue/compiler-core/3.2.37: + resolution: {integrity: sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==} dependencies: '@babel/parser': 7.17.9 - '@vue/shared': 3.2.36 + '@vue/shared': 3.2.37 estree-walker: 2.0.2 source-map: 0.6.1 - dev: true - /@vue/compiler-dom/3.2.35: - resolution: {integrity: sha512-I4bXB9MkRSTJ3gVXRQ4iaYJgABZGew+K/CCBoAh9fdLaeY7A7uUlS5nWGOlICSVfOH0/xk4QlcXeGZYCJkEleA==} + /@vue/compiler-dom/3.2.37: + resolution: {integrity: sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==} dependencies: - '@vue/compiler-core': 3.2.35 - '@vue/shared': 3.2.35 + '@vue/compiler-core': 3.2.37 + '@vue/shared': 3.2.37 - /@vue/compiler-dom/3.2.36: - resolution: {integrity: sha512-tcOTAOiW4s24QLnq+ON6J+GRONXJ+A/mqKCORi0LSlIh8XQlNnlm24y8xIL8la+ZDgkdbjarQ9ZqYSvEja6gVA==} - dependencies: - '@vue/compiler-core': 3.2.36 - '@vue/shared': 3.2.36 - dev: true - - /@vue/compiler-sfc/3.2.35: - resolution: {integrity: sha512-2wKQtnuHfwBFc7uV2Cmtms3Cc7u/u6kKJI3F+i0A+9xnuahK39cCMNJKHzI9x93Xai+uft64fDc5JSh8zDQBQA==} + /@vue/compiler-sfc/3.2.37: + resolution: {integrity: sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==} dependencies: '@babel/parser': 7.17.9 - '@vue/compiler-core': 3.2.35 - '@vue/compiler-dom': 3.2.35 - '@vue/compiler-ssr': 3.2.35 - '@vue/reactivity-transform': 3.2.35 - '@vue/shared': 3.2.35 + '@vue/compiler-core': 3.2.37 + '@vue/compiler-dom': 3.2.37 + '@vue/compiler-ssr': 3.2.37 + '@vue/reactivity-transform': 3.2.37 + '@vue/shared': 3.2.37 estree-walker: 2.0.2 magic-string: 0.25.7 postcss: 8.4.14 source-map: 0.6.1 - /@vue/compiler-sfc/3.2.36: - resolution: {integrity: sha512-AvGb4bTj4W8uQ4BqaSxo7UwTEqX5utdRSMyHy58OragWlt8nEACQ9mIeQh3K4di4/SX+41+pJrLIY01lHAOFOA==} + /@vue/compiler-ssr/3.2.37: + resolution: {integrity: sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==} dependencies: - '@babel/parser': 7.17.9 - '@vue/compiler-core': 3.2.36 - '@vue/compiler-dom': 3.2.36 - '@vue/compiler-ssr': 3.2.36 - '@vue/reactivity-transform': 3.2.36 - '@vue/shared': 3.2.36 - estree-walker: 2.0.2 - magic-string: 0.25.7 - postcss: 8.4.14 - source-map: 0.6.1 - dev: true - - /@vue/compiler-ssr/3.2.35: - resolution: {integrity: sha512-dJyqB8fZbvVQEnWl5VGxkWHTqx0ERnZXXqInFzyOX8FpTEidmQbUSmDrXidea7bZTdeg6ly94kZFGPYXT29mgQ==} - dependencies: - '@vue/compiler-dom': 3.2.35 - '@vue/shared': 3.2.35 - - /@vue/compiler-ssr/3.2.36: - resolution: {integrity: sha512-+KugInUFRvOxEdLkZwE+W43BqHyhBh0jpYXhmqw1xGq2dmE6J9eZ8UUSOKNhdHtQ/iNLWWeK/wPZkVLUf3YGaw==} - dependencies: - '@vue/compiler-dom': 3.2.36 - '@vue/shared': 3.2.36 - dev: true + '@vue/compiler-dom': 3.2.37 + '@vue/shared': 3.2.37 /@vue/devtools-api/6.1.4: resolution: {integrity: sha512-IiA0SvDrJEgXvVxjNkHPFfDx6SXw0b/TUkqMcDZWNg9fnCAHbTpoo59YfJ9QLFkwa3raau5vSlRVzMSLDnfdtQ==} - dev: false - /@vue/reactivity-transform/3.2.35: - resolution: {integrity: sha512-VjdQU4nIrgsh1iPqAdYZufWgFqdH9fIl6ttO2PCFlLsrQl7b8BcuawM6moSBLF8damBzSNcqvbvQDBhsI3fyVQ==} + /@vue/reactivity-transform/3.2.37: + resolution: {integrity: sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==} dependencies: '@babel/parser': 7.17.9 - '@vue/compiler-core': 3.2.35 - '@vue/shared': 3.2.35 + '@vue/compiler-core': 3.2.37 + '@vue/shared': 3.2.37 estree-walker: 2.0.2 magic-string: 0.25.7 - /@vue/reactivity-transform/3.2.36: - resolution: {integrity: sha512-Jk5o2BhpODC9XTA7o4EL8hSJ4JyrFWErLtClG3NH8wDS7ri9jBDWxI7/549T7JY9uilKsaNM+4pJASLj5dtRwA==} + /@vue/reactivity/3.2.37: + resolution: {integrity: sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==} dependencies: - '@babel/parser': 7.17.9 - '@vue/compiler-core': 3.2.36 - '@vue/shared': 3.2.36 - estree-walker: 2.0.2 - magic-string: 0.25.7 - dev: true + '@vue/shared': 3.2.37 - /@vue/reactivity/3.2.35: - resolution: {integrity: sha512-6j9N9R1SwHVcJas4YqAzwdRS/cgmj3Z9aUert5Mv1jk5B9H9ivN/zot/fgMUbseWXigkkmX60OsfRbz49o8kCw==} + /@vue/runtime-core/3.2.37: + resolution: {integrity: sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==} dependencies: - '@vue/shared': 3.2.35 + '@vue/reactivity': 3.2.37 + '@vue/shared': 3.2.37 - /@vue/reactivity/3.2.36: - resolution: {integrity: sha512-c2qvopo0crh9A4GXi2/2kfGYMxsJW4tVILrqRPydVGZHhq0fnzy6qmclWOhBFckEhmyxmpHpdJtIRYGeKcuhnA==} + /@vue/runtime-dom/3.2.37: + resolution: {integrity: sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==} dependencies: - '@vue/shared': 3.2.36 - dev: true - - /@vue/runtime-core/3.2.35: - resolution: {integrity: sha512-P8AeGPRGyIiYdOdvLc/7KR8VSdbUGG8Jxdx6Xlj5okEjyV9IYxeHRIQIoye85K0lZXBH4zuh1syD1mX+oZ0KqQ==} - dependencies: - '@vue/reactivity': 3.2.35 - '@vue/shared': 3.2.35 - - /@vue/runtime-core/3.2.36: - resolution: {integrity: sha512-PTWBD+Lub+1U3/KhbCExrfxyS14hstLX+cBboxVHaz+kXoiDLNDEYAovPtxeTutbqtClIXtft+wcGdC+FUQ9qQ==} - dependencies: - '@vue/reactivity': 3.2.36 - '@vue/shared': 3.2.36 - dev: true - - /@vue/runtime-dom/3.2.35: - resolution: {integrity: sha512-M5xrVJ/b0KqssjPQMdpwLp3KwzG1Tn2w/IrOptVqGY5c9fEBluIbm18AeO4Fr3YxfeyaPWm1rY8POrEso0UE3w==} - dependencies: - '@vue/runtime-core': 3.2.35 - '@vue/shared': 3.2.35 - csstype: 2.6.17 - - /@vue/runtime-dom/3.2.36: - resolution: {integrity: sha512-gYPYblm7QXHVuBohqNRRT7Wez0f2Mx2D40rb4fleehrJU9CnkjG0phhcGEZFfGwCmHZRqBCRgbFWE98bPULqkg==} - dependencies: - '@vue/runtime-core': 3.2.36 - '@vue/shared': 3.2.36 + '@vue/runtime-core': 3.2.37 + '@vue/shared': 3.2.37 csstype: 2.6.17 - dev: true - /@vue/server-renderer/3.2.35_vue@3.2.35: - resolution: {integrity: sha512-ZMF8V+bZ0EIjSB7yzPEmDlxRDOIXj04iqG4Rw/H5rIuBCf0b7rNTleiOldlX5haG++zUq6uiL2AVp/A9uyz+cw==} + /@vue/server-renderer/3.2.37_vue@3.2.37: + resolution: {integrity: sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==} peerDependencies: - vue: 3.2.35 + vue: 3.2.37 dependencies: - '@vue/compiler-ssr': 3.2.35 - '@vue/shared': 3.2.35 - vue: 3.2.35 + '@vue/compiler-ssr': 3.2.37 + '@vue/shared': 3.2.37 + vue: 3.2.37 - /@vue/server-renderer/3.2.36_vue@3.2.36: - resolution: {integrity: sha512-uZE0+jfye6yYXWvAQYeHZv+f50sRryvy16uiqzk3jn8hEY8zTjI+rzlmZSGoE915k+W/Ol9XSw6vxOUD8dGkUg==} - peerDependencies: - vue: 3.2.36 - dependencies: - '@vue/compiler-ssr': 3.2.36 - '@vue/shared': 3.2.36 - vue: 3.2.36 - dev: true - - /@vue/shared/3.2.35: - resolution: {integrity: sha512-/sxDqMcy0MsfQ3LQixKYDxIinDYNy1dXTsF2Am0pv0toImWabymFQ8cFmPJnPt+gh5ElKwwn7KzQcDbLHar60A==} + /@vue/shared/3.2.37: + resolution: {integrity: sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==} - /@vue/shared/3.2.36: - resolution: {integrity: sha512-JtB41wXl7Au3+Nl3gD16Cfpj7k/6aCroZ6BbOiCMFCMvrOpkg/qQUXTso2XowaNqBbnkuGHurLAqkLBxNGc1hQ==} - dev: true - - /@vueuse/core/8.5.0_vue@3.2.35: + /@vueuse/core/8.5.0_vue@3.2.37: resolution: {integrity: sha512-VEJ6sGNsPlUp0o9BGda2YISvDZbhWJSOJu5zlp2TufRGVrLcYUKr31jyFEOj6RXzG3k/H4aCYeZyjpItfU8glw==} peerDependencies: '@vue/composition-api': ^1.1.0 @@ -3275,14 +3323,14 @@ packages: optional: true dependencies: '@vueuse/metadata': 8.5.0 - '@vueuse/shared': 8.5.0_vue@3.2.35 - vue: 3.2.35 - vue-demi: 0.12.5_vue@3.2.35 + '@vueuse/shared': 8.5.0_vue@3.2.37 + vue: 3.2.37 + vue-demi: 0.12.5_vue@3.2.37 /@vueuse/metadata/8.5.0: resolution: {integrity: sha512-WxsD+Cd+bn+HcjpY6Dl9FJ8ywTRTT9pTwk3bCQpzEhXVYAyNczKDSahk50fCfIJKeWHhyI4B2+/ZEOxQAkUr0g==} - /@vueuse/shared/8.5.0_vue@3.2.35: + /@vueuse/shared/8.5.0_vue@3.2.37: resolution: {integrity: sha512-qKG+SZb44VvGD4dU5cQ63z4JE2Yk39hQUecR0a9sEdJA01cx+XrxAvFKJfPooxwoiqalAVw/ktWK6xbyc/jS3g==} peerDependencies: '@vue/composition-api': ^1.1.0 @@ -3293,32 +3341,8 @@ packages: vue: optional: true dependencies: - vue: 3.2.35 - vue-demi: 0.12.5_vue@3.2.35 - - /@windicss/config/1.8.4: - resolution: {integrity: sha512-i4fFGFfZoRess6WMkauykHC3PFd9xKYVx7lSuLfMK7sgo6x3+l4dY42GbsWMHyLqH1sTMfyt1LgfXSIKYJozSA==} - dependencies: - debug: 4.3.4 - jiti: 1.13.0 - windicss: 3.5.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@windicss/plugin-utils/1.8.4: - resolution: {integrity: sha512-DqJVwAfzlgd8nYSNlmhXOey32pI8UwH7QiOWdFS/AR2O/q9oLDGHDn97Its/kZdfoyhi8ylwZNP2Pk0H7cihhQ==} - dependencies: - '@antfu/utils': 0.5.1 - '@windicss/config': 1.8.4 - debug: 4.3.4 - fast-glob: 3.2.11 - magic-string: 0.26.1 - micromatch: 4.0.5 - windicss: 3.5.1 - transitivePeerDependencies: - - supports-color - dev: true + vue: 3.2.37 + vue-demi: 0.12.5_vue@3.2.37 /abab/2.0.5: resolution: {integrity: sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==} @@ -3602,6 +3626,10 @@ packages: - supports-color dev: true + /body-scroll-lock/4.0.0-beta.0: + resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} + dev: true + /boolbase/1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true @@ -3801,6 +3829,10 @@ packages: resolution: {integrity: sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==} dev: true + /colorette/2.0.17: + resolution: {integrity: sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g==} + dev: true + /combined-stream/1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -3858,6 +3890,10 @@ packages: dotenv: 8.6.0 dev: true + /consola/2.15.3: + resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} + dev: true + /content-disposition/0.5.3: resolution: {integrity: sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==} engines: {node: '>= 0.6'} @@ -3936,6 +3972,14 @@ packages: engines: {node: '>=8'} dev: false + /css-tree/2.1.0: + resolution: {integrity: sha512-PcysZRzToBbrpoUrZ9qfblRIRf8zbEAkU0AIpQFtgkFK0vSbzOmBCvdSAx2Zg7Xx5wiYJKUKk0NMP7kxevie/A==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + dependencies: + mdn-data: 2.0.27 + source-map-js: 1.0.2 + dev: true + /cssesc/3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -4044,6 +4088,10 @@ packages: has-property-descriptors: 1.0.0 object-keys: 1.1.1 + /defu/6.0.0: + resolution: {integrity: sha512-t2MZGLf1V2rV4VBZbWIaXKdX/mUcYW0n2znQZoADBkGGxYL8EWqCuCZBmJPJ/Yy9fofJkyuuSuo5GSwo0XdEgw==} + dev: true + /delayed-stream/1.0.0: resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=} engines: {node: '>=0.4.0'} @@ -4054,6 +4102,10 @@ packages: engines: {node: '>= 0.6'} dev: true + /destr/1.1.1: + resolution: {integrity: sha512-QqkneF8LrYmwATMdnuD2MLI3GHQIcBnG6qFC2q9bSH430VTCDAVjcspPmUaKhPGtAtPAftIUFqY1obQYQuwmbg==} + dev: true + /destroy/1.0.4: resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=} dev: true @@ -4127,6 +4179,10 @@ packages: engines: {node: '>=10'} dev: true + /duplexer/0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + dev: true + /ee-first/1.1.1: resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=} dev: true @@ -4704,10 +4760,6 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-vue-global-api/0.4.1: - resolution: {integrity: sha512-mJTiKBGLe1FXmEifYzCQzUTBpFv8OtfYzP6PAOuVRf+3hkGLMeiDh4bVzZEaJfdExtc8mPw9vp35YSLhwTselQ==} - dev: false - /eslint-import-resolver-node/0.3.6: resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==} dependencies: @@ -5479,6 +5531,13 @@ packages: /graceful-fs/4.2.8: resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==} + /gzip-size/6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + dependencies: + duplexer: 0.1.2 + dev: true + /handle-thing/2.0.1: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} dev: true @@ -6005,6 +6064,10 @@ packages: semver: 7.3.7 dev: true + /jsonc-parser/3.0.0: + resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==} + dev: true + /jsonfile/6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: @@ -6165,6 +6228,10 @@ packages: resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} dev: true + /mdn-data/2.0.27: + resolution: {integrity: sha512-kwqO0I0jtWr25KcfLm9pia8vLZ8qoAKhWZuZMbneJq3jjBD3gl5nZs8l8Tu3ZBlBAHVQtDur9rdDGyvtfVraHQ==} + dev: true + /media-typer/0.3.0: resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} engines: {node: '>= 0.6'} @@ -6210,14 +6277,6 @@ packages: braces: 3.0.2 picomatch: 2.3.0 - /micromatch/4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - /mime-db/1.46.0: resolution: {integrity: sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==} engines: {node: '>= 0.6'} @@ -6287,6 +6346,11 @@ packages: engines: {node: '>=4'} dev: true + /mrmime/1.0.0: + resolution: {integrity: sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==} + engines: {node: '>=10'} + dev: true + /ms/2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} dev: true @@ -6324,6 +6388,10 @@ packages: engines: {node: '>= 0.6'} dev: true + /node-fetch-native/0.1.3: + resolution: {integrity: sha512-Jf1IQZdovUIv9E+5avmN6Sf+bND+rnMlODnBQhdE2VRyuWP9WgqZb/KEgPekh19DAN1X2C4vbS1VCOaz2OH19g==} + dev: true + /node-fetch/2.6.1: resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==} engines: {node: 4.x || >=6.0.0} @@ -6440,6 +6508,15 @@ packages: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} dev: true + /ohmyfetch/0.4.18: + resolution: {integrity: sha512-MslzNrQzBLtZHmiZBI8QMOcMpdNFlK61OJ34nFNFynZ4v+4BonfCQ7VIN4EGXvGGq5zhDzgdJoY3o9S1l2T7KQ==} + dependencies: + destr: 1.1.1 + node-fetch-native: 0.1.3 + ufo: 0.8.4 + undici: 5.4.0 + dev: true + /on-finished/2.3.0: resolution: {integrity: sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=} engines: {node: '>= 0.8'} @@ -6608,8 +6685,12 @@ packages: engines: {node: '>=8'} dev: true - /pathe/0.2.0: - resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} + /pathe/0.3.0: + resolution: {integrity: sha512-3vUjp552BJzCw9vqKsO5sttHkbYqqsZtH0x1PNtItgqx8BXEXzoY1SYRKcL6BTyVh4lGJGLj0tM42elUDMvcYA==} + dev: true + + /perfect-debounce/0.1.3: + resolution: {integrity: sha512-NOT9AcKiDGpnV/HBhI22Str++XWcErO/bALvHCuhv33owZW/CjH8KAFLZDCmu3727sihe0wTxpDhyGc6M8qacQ==} dev: true /picocolors/1.0.0: @@ -6701,14 +6782,6 @@ packages: engines: {node: ^14.13.1 || >=16.0.0} dev: false - /prism-theme-vars/0.2.3: - resolution: {integrity: sha512-lpRg8GWfxu38m4rZwjrvOxeHlmL4tERhe9sTjrC47HMu6uCEch3bLUQVNlISoEq9Z24g5Xm+B7AKdyiKSevktg==} - dev: true - - /prismjs/1.25.0: - resolution: {integrity: sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==} - dev: true - /process-nextick-args/2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true @@ -7151,6 +7224,14 @@ packages: engines: {node: '>=8'} dev: true + /shiki/0.10.1: + resolution: {integrity: sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==} + dependencies: + jsonc-parser: 3.0.0 + vscode-oniguruma: 1.6.2 + vscode-textmate: 5.2.0 + dev: true + /side-channel/1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: @@ -7162,6 +7243,15 @@ packages: resolution: {integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==} dev: true + /sirv/2.0.2: + resolution: {integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==} + engines: {node: '>= 10'} + dependencies: + '@polka/url': 1.0.0-next.21 + mrmime: 1.0.0 + totalist: 3.0.0 + dev: true + /sisteransi/1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} dev: true @@ -7219,7 +7309,7 @@ packages: dev: false /source-map/0.5.7: - resolution: {integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=} + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} /source-map/0.6.1: @@ -7574,7 +7664,7 @@ packages: dev: true /to-fast-properties/2.0.0: - resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} /to-regex-range/5.0.1: @@ -7588,6 +7678,11 @@ packages: engines: {node: '>=0.6'} dev: true + /totalist/3.0.0: + resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==} + engines: {node: '>=6'} + dev: true + /tough-cookie/4.0.0: resolution: {integrity: sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==} engines: {node: '>=6'} @@ -7748,6 +7843,10 @@ packages: hasBin: true dev: true + /ufo/0.8.4: + resolution: {integrity: sha512-/+BmBDe8GvlB2nIflWasLLAInjYG0bC9HRnfEpNi4sw77J2AJNnEVnTDReVrehoh825+Q/evF3THXTAweyam2g==} + dev: true + /uglify-js/3.15.4: resolution: {integrity: sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==} engines: {node: '>=0.8.0'} @@ -7771,6 +7870,19 @@ packages: has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + /unconfig/0.3.4: + resolution: {integrity: sha512-cf39F1brwQuLSuMLTYXOdWJH0O1CJee6a4QW1nYtO7SoBUfVvQCvEel6ssTNXtPfi17kop1ADmVtmC49NlFkIQ==} + dependencies: + '@antfu/utils': 0.5.1 + defu: 6.0.0 + jiti: 1.13.0 + dev: true + + /undici/5.4.0: + resolution: {integrity: sha512-A1SRXysDg7J+mVP46jF+9cKANw0kptqSFZ8tGyL+HBiv0K1spjxPX8Z4EGu+Eu6pjClJUBdnUPlxrOafR668/g==} + engines: {node: '>=12.18'} + dev: true + /unicode-canonical-property-names-ecmascript/1.0.4: resolution: {integrity: sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==} engines: {node: '>=4'} @@ -7816,44 +7928,41 @@ packages: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} - /unpipe/1.0.0: - resolution: {integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=} - engines: {node: '>= 0.8'} - dev: true - - /unplugin-icons/0.14.3_vite@2.9.9: - resolution: {integrity: sha512-PyyNMACpZ/EAiG3B6K1wPGZ151VGdlHIEx8/utgP546yVmPpV/xC1k1V2eEebf71fGm3WD6gzPrERNsbMgIVgg==} + /unocss/0.38.1_vite@2.9.9: + resolution: {integrity: sha512-p0GK+cAwjZeRHMBkKtr9hrQyhwDrew8kgf01Kt4+ISp1UMeldLH9b5j/jevpYqP1oQitAP64gX7jD94wOXYSxg==} + engines: {node: '>=14'} peerDependencies: - '@svgr/core': '>=5.5.0' - '@vue/compiler-sfc': ^3.0.2 - vue-template-compiler: ^2.6.12 - vue-template-es2015-compiler: ^1.9.0 + '@unocss/webpack': 0.38.1 peerDependenciesMeta: - '@svgr/core': - optional: true - '@vue/compiler-sfc': - optional: true - vue-template-compiler: - optional: true - vue-template-es2015-compiler: + '@unocss/webpack': optional: true dependencies: - '@antfu/install-pkg': 0.1.0 - '@antfu/utils': 0.5.1 - '@iconify/utils': 1.0.32 - debug: 4.3.4 - kolorist: 1.5.1 - local-pkg: 0.4.1 - unplugin: 0.6.2_vite@2.9.9 + '@unocss/cli': 0.38.1 + '@unocss/core': 0.38.1 + '@unocss/preset-attributify': 0.38.1 + '@unocss/preset-icons': 0.38.1 + '@unocss/preset-mini': 0.38.1 + '@unocss/preset-tagify': 0.38.1 + '@unocss/preset-typography': 0.38.1 + '@unocss/preset-uno': 0.38.1 + '@unocss/preset-web-fonts': 0.38.1 + '@unocss/preset-wind': 0.38.1 + '@unocss/reset': 0.38.1 + '@unocss/transformer-compile-class': 0.38.1 + '@unocss/transformer-directives': 0.38.1 + '@unocss/transformer-variant-group': 0.38.1 + '@unocss/vite': 0.38.1_vite@2.9.9 transitivePeerDependencies: - - esbuild - - rollup - supports-color - vite - - webpack dev: true - /unplugin-vue-components/0.19.5_vite@2.9.9+vue@3.2.35: + /unpipe/1.0.0: + resolution: {integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=} + engines: {node: '>= 0.8'} + dev: true + + /unplugin-vue-components/0.19.5_vite@2.9.9+vue@3.2.37: resolution: {integrity: sha512-cIC+PdQEXmG+B1gmZGk4hws2xP+00C6pg3FD6ixEgRyW+WF+QXQW/60pc+hUhtDYs1PFE+23K3NY7yvYTnDDTA==} engines: {node: '>=14'} peerDependencies: @@ -7876,7 +7985,7 @@ packages: minimatch: 5.0.1 resolve: 1.22.0 unplugin: 0.6.3_vite@2.9.9 - vue: 3.2.35 + vue: 3.2.37 transitivePeerDependencies: - esbuild - rollup @@ -7885,29 +7994,6 @@ packages: - webpack dev: true - /unplugin/0.6.2_vite@2.9.9: - resolution: {integrity: sha512-+QONc2uBFQbeo4x5mlJHjTKjR6pmuchMpGVrWhwdGFFMb4ttFZ4E9KqhOOrNcm3Q8NNyB1vJ4s5e36IZC7UWYw==} - peerDependencies: - esbuild: '>=0.13' - rollup: ^2.50.0 - vite: ^2.3.0 - webpack: 4 || 5 - peerDependenciesMeta: - esbuild: - optional: true - rollup: - optional: true - vite: - optional: true - webpack: - optional: true - dependencies: - chokidar: 3.5.3 - vite: 2.9.9 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.4.3 - dev: true - /unplugin/0.6.3_vite@2.9.9: resolution: {integrity: sha512-CoW88FQfCW/yabVc4bLrjikN9HC8dEvMU4O7B6K2jsYMPK0l6iAnd9dpJwqGcmXJKRCU9vwSsy653qg+RK0G6A==} peerDependencies: @@ -7990,18 +8076,28 @@ packages: - supports-color dev: true - /vite-plugin-windicss/1.8.4_vite@2.9.9: - resolution: {integrity: sha512-LSZAO8BZn3x406GRbYX5t5ONXXJVdqiQtN1qrznLA/Dy5/NzZVhfcrL6N1qEYYO7HsCDT4pLAjTzObvDnM9Y8A==} + /vite/2.9.10: + resolution: {integrity: sha512-TwZRuSMYjpTurLqXspct+HZE7ONiW9d+wSWgvADGxhDPPyoIcNywY+RX4ng+QpK30DCa1l/oZgi2PLZDibhzbQ==} + engines: {node: '>=12.2.0'} + hasBin: true peerDependencies: - vite: ^2.0.1 + less: '*' + sass: '*' + stylus: '*' + peerDependenciesMeta: + less: + optional: true + sass: + optional: true + stylus: + optional: true dependencies: - '@windicss/plugin-utils': 1.8.4 - debug: 4.3.4 - kolorist: 1.5.1 - vite: 2.9.9 - windicss: 3.5.1 - transitivePeerDependencies: - - supports-color + esbuild: 0.14.38 + postcss: 8.4.14 + resolve: 1.22.0 + rollup: 2.75.5 + optionalDependencies: + fsevents: 2.3.2 dev: true /vite/2.9.9: @@ -8028,19 +8124,23 @@ packages: fsevents: 2.3.2 dev: true - /vitepress/0.22.4: - resolution: {integrity: sha512-oZUnLO/SpYdThaBKefDeOiVlr0Rie4Ppx3FzMnMyLtJnI5GlBMNjqYqMy/4+umm/iC+ZDJfI+IlDKxv5fZnYzA==} - engines: {node: '>=14.0.0'} + /vitepress/1.0.0-alpha.4: + resolution: {integrity: sha512-bOAA4KW6vYGlkbcrPLZLTKWTgXVroObU+o9xj9EENyEl6yg26WWvfN7DGA4BftjdM5O8nR93Z5khPQ3W/tFE7Q==} + engines: {node: '>=14.6.0'} hasBin: true dependencies: '@docsearch/css': 3.1.0 '@docsearch/js': 3.1.0 - '@vitejs/plugin-vue': 2.3.3_vite@2.9.9+vue@3.2.35 - prismjs: 1.25.0 - vite: 2.9.9 - vue: 3.2.35 + '@vitejs/plugin-vue': 2.3.3_vite@2.9.10+vue@3.2.37 + '@vue/devtools-api': 6.1.4 + '@vueuse/core': 8.5.0_vue@3.2.37 + body-scroll-lock: 4.0.0-beta.0 + shiki: 0.10.1 + vite: 2.9.10 + vue: 3.2.37 transitivePeerDependencies: - '@types/react' + - '@vue/composition-api' - less - react - react-dom @@ -8048,22 +8148,16 @@ packages: - stylus dev: true - /vue-demi/0.12.5_vue@3.2.35: - resolution: {integrity: sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - dependencies: - vue: 3.2.35 + /vscode-oniguruma/1.6.2: + resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==} + dev: true + + /vscode-textmate/5.2.0: + resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} + dev: true - /vue-demi/0.13.1_vue@3.2.35: - resolution: {integrity: sha512-xmkJ56koG3ptpLnpgmIzk9/4nFf4CqduSJbUM0OdPoU87NwRuZ6x49OLhjSa/fC15fV+5CbEnrxU4oyE022svg==} + /vue-demi/0.12.5_vue@3.2.37: + resolution: {integrity: sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==} engines: {node: '>=12'} hasBin: true requiresBuild: true @@ -8074,8 +8168,7 @@ packages: '@vue/composition-api': optional: true dependencies: - vue: 3.2.35 - dev: false + vue: 3.2.37 /vue-eslint-parser/9.0.2_eslint@8.17.0: resolution: {integrity: sha512-uCPQwTGjOtAYrwnU+76pYxalhjsh7iFBsHwBqDHiOPTxtICDaraO4Szw54WFTNZTAEsgHHzqFOu1mmnBOBRzDA==} @@ -8095,43 +8188,23 @@ packages: - supports-color dev: true - /vue-global-api/0.4.1_vue@3.2.35: - resolution: {integrity: sha512-283vpYOhVHJCpMkjNVEwZdgaAb+Y93zFaXGAWTI378MLoNuwQydjD/BAy1e81QYEmyA+JbxqcmMZVWcM9rbriw==} - dependencies: - eslint-config-vue-global-api: 0.4.1 - vue-demi: 0.13.1_vue@3.2.35 - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: false - - /vue-router/4.0.15_vue@3.2.35: + /vue-router/4.0.15_vue@3.2.37: resolution: {integrity: sha512-xa+pIN9ZqORdIW1MkN2+d9Ui2pCM1b/UMgwYUCZOiFYHAvz/slKKBDha8DLrh5aCG/RibtrpyhKjKOZ85tYyWg==} peerDependencies: vue: ^3.2.0 dependencies: '@vue/devtools-api': 6.1.4 - vue: 3.2.35 + vue: 3.2.37 dev: false - /vue/3.2.35: - resolution: {integrity: sha512-mc/15B0Wjd/4JMMGOcXUQAeXfjyg8MImA2EVZucNdyDPJe1nXhMNbYXOEVPEGfk/mCeyszCzl44dSAhHhQVH8g==} + /vue/3.2.37: + resolution: {integrity: sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==} dependencies: - '@vue/compiler-dom': 3.2.35 - '@vue/compiler-sfc': 3.2.35 - '@vue/runtime-dom': 3.2.35 - '@vue/server-renderer': 3.2.35_vue@3.2.35 - '@vue/shared': 3.2.35 - - /vue/3.2.36: - resolution: {integrity: sha512-5yTXmrE6gW8IQgttzHW5bfBiFA6mx35ZXHjGLDmKYzW6MMmYvCwuKybANRepwkMYeXw2v1buGg3/lPICY5YlZw==} - dependencies: - '@vue/compiler-dom': 3.2.36 - '@vue/compiler-sfc': 3.2.36 - '@vue/runtime-dom': 3.2.36 - '@vue/server-renderer': 3.2.36_vue@3.2.36 - '@vue/shared': 3.2.36 - dev: true + '@vue/compiler-dom': 3.2.37 + '@vue/compiler-sfc': 3.2.37 + '@vue/runtime-dom': 3.2.37 + '@vue/server-renderer': 3.2.37_vue@3.2.37 + '@vue/shared': 3.2.37 /w3c-hr-time/1.0.2: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} @@ -8217,12 +8290,6 @@ packages: isexe: 2.0.0 dev: true - /windicss/3.5.1: - resolution: {integrity: sha512-E1hYZATcZFci/XhGS0sJAMRxULjnK+glNukE78Ku7xeb3jxgMY55fFOdIrav+GjQCsgR+IZxPq9/DwmO6eyc4Q==} - engines: {node: '>= 12'} - hasBin: true - dev: true - /word-wrap/1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'}