@vite-pwa/vitepress 1.1.0 โ 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -10
- package/dist/index.d.mts +9 -22
- package/dist/index.mjs +157 -168
- package/dist/types.d.mts +15 -0
- package/package.json +53 -29
- package/dist/index.cjs +0 -178
- package/dist/index.d.cts +0 -24
- package/dist/index.d.ts +0 -24
- package/index.d.ts +0 -1
package/README.md
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
<p align='center'>
|
|
2
|
-
<
|
|
3
|
-
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vite-pwa/.github/main/vitepress-hero-dark.svg" />
|
|
4
|
+
<img src="https://raw.githubusercontent.com/vite-pwa/.github/main/vitepress-hero.svg" alt="@vite-pwa/vitepress - Zero-config PWA for VitePress">
|
|
5
|
+
</picture>
|
|
4
6
|
</p>
|
|
5
7
|
|
|
6
8
|
<p align='center'>
|
|
7
|
-
<a href='https://
|
|
9
|
+
<a href='https://npmx.dev/package/@vite-pwa/vitepress' target="__blank">
|
|
8
10
|
<img src='https://img.shields.io/npm/v/@vite-pwa/vitepress?color=33A6B8&label=' alt="NPM version">
|
|
9
11
|
</a>
|
|
10
|
-
<a href="https://
|
|
12
|
+
<a href="https://npmx.dev/package/@vite-pwa/vitepress" target="__blank">
|
|
11
13
|
<img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@vite-pwa/vitepress?color=476582&label=">
|
|
12
14
|
</a>
|
|
13
|
-
<a href="https://
|
|
15
|
+
<a href="https://unplugin-pwa.netlify.app/frameworks/vitepress" target="__blank">
|
|
14
16
|
<img src="https://img.shields.io/static/v1?label=&message=docs%20%26%20guides&color=2e859c" alt="Docs & Guides">
|
|
15
17
|
</a>
|
|
16
18
|
<br>
|
|
@@ -23,29 +25,35 @@ Zero-config PWA Plugin for VitePress
|
|
|
23
25
|
|
|
24
26
|
<p align="center">
|
|
25
27
|
<a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
|
|
26
|
-
<img src=
|
|
28
|
+
<img src="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg" alt="Anthony Fu SVG sponsors image"/>
|
|
27
29
|
</a>
|
|
28
30
|
</p>
|
|
29
31
|
|
|
30
32
|
## ๐ Features
|
|
31
33
|
|
|
32
|
-
- ๐ [**Documentation & guides**](https://
|
|
34
|
+
- ๐ [**Documentation & guides**](https://unplugin-pwa.netlify.app/)
|
|
33
35
|
- ๐ **Zero-Config**: sensible built-in default configs for common use cases
|
|
34
36
|
- ๐ฉ **Extensible**: expose the full ability to customize the behavior of the plugin
|
|
35
37
|
- ๐ฆพ **Type Strong**: written in [TypeScript](https://www.typescriptlang.org/)
|
|
36
38
|
- ๐ **Offline Support**: generate service worker with offline support (via Workbox)
|
|
37
|
-
- โก **Fully tree shakable**:
|
|
39
|
+
- โก **Fully tree shakable**: client virtual modules are strictly optimized for Dead Code Elimination.
|
|
40
|
+
- ๐ **Web Manifest**: auto-inject Web App Manifest and PWA assets seamlessly.
|
|
38
41
|
- ๐ฌ **Prompt for new content**: built-in support for Vanilla JavaScript, Vue 3, React, Svelte, SolidJS and Preact
|
|
39
42
|
- โ๏ธ **Stale-while-revalidate**: automatic reload when new content is available
|
|
40
43
|
- โจ **Static assets handling**: configure static assets for offline support
|
|
41
44
|
- ๐ **Development Support**: debug your custom service worker logic as you develop your application
|
|
42
|
-
-
|
|
45
|
+
- ๐ **Inspector**: visually inspect your resolved configuration, web manifest and service worker during development, via middleware or [DevFrame](https://github.com/devframes/devframe)
|
|
46
|
+
- ๐งฉ **Modular**: use the ready-to-use plugins or compose your own integration from the building blocks in `@unplugin-pwa/core` and `@unplugin-pwa/vite`
|
|
47
|
+
- ๐ฆ **Universal Bundlers**: native integration with Vite, Rolldown, Webpack (WIP), Rspack (WIP), and Rsbuild (WIP).
|
|
48
|
+
- ๐ ๏ธ **Meta-Frameworks**: seamless integration with [รฎles](https://github.com/ElMassimo/iles), [SvelteKit](https://github.com/sveltejs/kit), [VitePress](https://github.com/vuejs/vitepress), [Astro](https://github.com/withastro/astro), [Nuxt 3/4/5](https://github.com/nuxt/nuxt), [React Router](https://github.com/remix-run/react-router/), [TanStack](https://github.com/TanStack) and [Next](https://github.com/vercel/next.js/) (WIP).
|
|
43
49
|
- ๐ฅ **PWA Assets Generator**: generate all the PWA assets from a single command and a single source image
|
|
44
50
|
- ๐ **PWA Assets Integration**: serving, generating and injecting PWA Assets on the fly in your application
|
|
45
51
|
|
|
46
52
|
## ๐ฆ Install
|
|
47
53
|
|
|
48
|
-
> From
|
|
54
|
+
> From v2.0.0 `@vite-pwa/vitepress` using [@unplugin-pwa/vite](https://github.com/vite-pwa/unplugin-pwa/tree/main/packages/vite) and [@vite-pwa/workbox-build](https://github.com/vite-pwa/workbox/tree/main/packages/build). Requires Node 22.14.0 or above.
|
|
55
|
+
|
|
56
|
+
> From v0.3.0, `@vite-pwa/vitepress` requires **Vite 5** and **VitePress 1.0.0-rc.26 or above**.
|
|
49
57
|
|
|
50
58
|
> Using any version older than v0.3 requires Vite 3.1.0+.
|
|
51
59
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,24 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
|
|
8
|
-
*
|
|
9
|
-
* @see https://github.com/vite-pwa/vitepress/issues/22
|
|
10
|
-
*
|
|
11
|
-
* @default false
|
|
12
|
-
*/
|
|
13
|
-
includeAllowlist?: boolean;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
1
|
+
import { PwaOptions, VitePressExperimentalOptions } from "./types.mjs";
|
|
2
|
+
import { VitePWAStrategy } from "@unplugin-pwa/core";
|
|
3
|
+
import { SWType } from "@vite-pwa/workbox-build/types";
|
|
4
|
+
import { DefaultTheme, UserConfigExport } from "vitepress";
|
|
5
|
+
export declare function withPwa<UserStrategy extends VitePWAStrategy, T extends SWType, VPTheme = DefaultTheme.Config>(config: UserConfigExport<VPTheme>): Promise<UserConfigExport<VPTheme>>;
|
|
16
6
|
declare module 'vitepress' {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
interface UserConfig {
|
|
8
|
+
pwa?: Partial<PwaOptions<VitePWAStrategy, SWType>>;
|
|
9
|
+
}
|
|
20
10
|
}
|
|
21
|
-
|
|
22
|
-
declare function withPwa<T = DefaultTheme.Config>(config: UserConfigExport<T>): Promise<UserConfigExport<T>>;
|
|
23
|
-
|
|
24
|
-
export { type PwaOptions, withPwa };
|
|
11
|
+
export type { PwaOptions, VitePressExperimentalOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -1,176 +1,165 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { BuildPwaAssetsPlugin } from "@unplugin-pwa/vite/plugins/build-pwa-assets";
|
|
2
|
+
import { BuildRegisterSWPlugin } from "@unplugin-pwa/vite/plugins/build-register-sw";
|
|
3
|
+
import { DevPlugin } from "@unplugin-pwa/vite/plugins/dev";
|
|
4
|
+
import { DevMiddlewarePlugin } from "@unplugin-pwa/vite/plugins/dev-middleware";
|
|
5
|
+
import { DevAssetsMiddlewarePlugin } from "@unplugin-pwa/vite/plugins/dev-pwa-assets-middleware";
|
|
6
|
+
import { DevtoolsPlugin } from "@unplugin-pwa/vite/plugins/devtools";
|
|
7
|
+
import { InfoPlugin } from "@unplugin-pwa/vite/plugins/info";
|
|
8
|
+
import { InspectorPlugin } from "@unplugin-pwa/vite/plugins/inspector";
|
|
9
|
+
import { MainPlugin } from "@unplugin-pwa/vite/plugins/main";
|
|
10
|
+
import { AssetsPlugin } from "@unplugin-pwa/vite/plugins/pwa-assets";
|
|
11
|
+
import { VirtualModulesPlugin } from "@unplugin-pwa/vite/plugins/virtual-modules";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { generateRegisterSW } from "@unplugin-pwa/core/generate-register-sw";
|
|
14
|
+
import { createVitePWAContext } from "@unplugin-pwa/vite/vite-context";
|
|
15
|
+
// src/utils.ts
|
|
4
16
|
function escapeStringRegexp(value) {
|
|
5
|
-
|
|
17
|
+
return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
6
18
|
}
|
|
7
|
-
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
// src/create-context.ts
|
|
20
|
+
function createVitePressPWAContext(config) {
|
|
21
|
+
const pwa = config.pwa ?? {};
|
|
22
|
+
const ctx = Object.assign(createVitePWAContext(true, pwa), { vitepress: {
|
|
23
|
+
runtimeCachingAdded: false,
|
|
24
|
+
experimental: void 0
|
|
25
|
+
} });
|
|
26
|
+
ctx.configurePWAOptions = (_, viteResolvedConfig) => {
|
|
27
|
+
const vp = ctx.consumerOptions;
|
|
28
|
+
if (vp.experimental?.includeAllowlist) ctx.vitepress.experimental = { includeAllowlist: vp.experimental?.includeAllowlist };
|
|
29
|
+
else ctx.vitepress.experimental = { includeAllowlist: false };
|
|
30
|
+
ctx.base = config.base || "/";
|
|
31
|
+
if (!(viteResolvedConfig.command === "build")) return;
|
|
32
|
+
if (ctx.strategy === "generate-sw" && ctx.vitepress.experimental.includeAllowlist && !ctx.vitepress.runtimeCachingAdded) {
|
|
33
|
+
ctx.vitepress.runtimeCachingAdded = true;
|
|
34
|
+
ctx.resolvedOptions.generateSW ??= {};
|
|
35
|
+
const generateSW = ctx.resolvedOptions.generateSW;
|
|
36
|
+
generateSW.runtimeCaching ??= [];
|
|
37
|
+
generateSW.runtimeCaching.push({
|
|
38
|
+
urlPattern: ({ request, sameOrigin }) => {
|
|
39
|
+
return sameOrigin && request.mode === "navigate";
|
|
40
|
+
},
|
|
41
|
+
handler: "NetworkOnly",
|
|
42
|
+
options: { plugins: [{
|
|
43
|
+
handlerDidError: async () => Response.redirect("404", 302),
|
|
44
|
+
cacheWillUpdate: async () => null
|
|
45
|
+
}] }
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const outDir = config.outDir ?? ".vitepress/dist";
|
|
49
|
+
const immutableAssets = config.assetsDir ? config.assetsDir.replace(/\\/g, "/").replace(/^\.?\/|\/$/g, "") : "assets";
|
|
50
|
+
const base = config.base ?? config.vite?.base ?? "/";
|
|
51
|
+
ctx.resolvedOptions.base = base;
|
|
52
|
+
ctx.resolvedOptions.scope = base;
|
|
53
|
+
if (ctx.resolvedOptions.pwaAssets) {
|
|
54
|
+
const publicDir = typeof config.vite?.publicDir === "string" ? path.resolve(config.vite.publicDir) : path.resolve("public");
|
|
55
|
+
ctx.resolvedOptions.pwaAssets.integration = {
|
|
56
|
+
baseUrl: base,
|
|
57
|
+
publicDir,
|
|
58
|
+
outDir: path.resolve(outDir)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
outDir,
|
|
63
|
+
immutableAssets,
|
|
64
|
+
cwd: viteResolvedConfig.root
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
const consumerTransformHead = config.transformHead;
|
|
68
|
+
config.transformHead = async (vpCtx) => {
|
|
69
|
+
const head = await consumerTransformHead?.(vpCtx) ?? [];
|
|
70
|
+
const assetsGenerator = await ctx.pwaAssetsGenerator;
|
|
71
|
+
if (assetsGenerator) {
|
|
72
|
+
const htmlAssets = assetsGenerator.resolveHtmlAssets();
|
|
73
|
+
if (htmlAssets.themeColor) head.push(["meta", {
|
|
74
|
+
name: "theme-color",
|
|
75
|
+
content: htmlAssets.themeColor.content
|
|
76
|
+
}]);
|
|
77
|
+
for (const link of htmlAssets.links) head.push(["link", { ...link }]);
|
|
78
|
+
}
|
|
79
|
+
const webManifestData = ctx.webManifestData();
|
|
80
|
+
if (webManifestData) {
|
|
81
|
+
const href = webManifestData.href;
|
|
82
|
+
if (webManifestData.useCredentials) head.push(["link", {
|
|
83
|
+
rel: "manifest",
|
|
84
|
+
href,
|
|
85
|
+
crossorigin: "use-credentials"
|
|
86
|
+
}]);
|
|
87
|
+
else head.push(["link", {
|
|
88
|
+
rel: "manifest",
|
|
89
|
+
href
|
|
90
|
+
}]);
|
|
91
|
+
}
|
|
92
|
+
const registerSWData = await ctx.registerSWData();
|
|
93
|
+
if (registerSWData && registerSWData.shouldRegisterSW) {
|
|
94
|
+
if (registerSWData.mode === "inline") {
|
|
95
|
+
const content = await generateRegisterSW(ctx);
|
|
96
|
+
if (registerSWData.module) head.push([
|
|
97
|
+
"script",
|
|
98
|
+
{
|
|
99
|
+
id: "vite-pwa:vitepress:inline-sw",
|
|
100
|
+
type: "module"
|
|
101
|
+
},
|
|
102
|
+
content
|
|
103
|
+
]);
|
|
104
|
+
else head.push([
|
|
105
|
+
"script",
|
|
106
|
+
{ id: "vite-pwa:vitepress:inline-sw" },
|
|
107
|
+
content
|
|
108
|
+
]);
|
|
109
|
+
} else if (registerSWData.mode === "script-defer") head.push(["script", {
|
|
110
|
+
id: "vite-pwa:vitepress:register-sw",
|
|
111
|
+
defer: "defer",
|
|
112
|
+
src: registerSWData.registerPath
|
|
113
|
+
}]);
|
|
114
|
+
else head.push(["script", {
|
|
115
|
+
id: "vite-pwa:vitepress:register-sw",
|
|
116
|
+
src: registerSWData.registerPath
|
|
117
|
+
}]);
|
|
118
|
+
}
|
|
119
|
+
return head;
|
|
120
|
+
};
|
|
121
|
+
const consumerBuildEnd = config.buildEnd;
|
|
122
|
+
config.buildEnd = async (siteConfig) => {
|
|
123
|
+
await consumerBuildEnd?.(siteConfig);
|
|
124
|
+
if (!ctx.resolvedOptions.disable) {
|
|
125
|
+
if (ctx.strategy === "generate-sw" && ctx.vitepress.experimental.includeAllowlist) {
|
|
126
|
+
const generateSW = ctx.resolvedOptions.generateSW ?? {};
|
|
127
|
+
const allowlist = generateSW.navigateFallbackAllowlist ??= [];
|
|
128
|
+
const base = siteConfig.site.base ?? "/";
|
|
129
|
+
for (const page of siteConfig.pages) {
|
|
130
|
+
const regex = page === "index.md" ? escapeStringRegexp(base) : escapeStringRegexp(`${base}${page.replace(/\.md$/, "")}`);
|
|
131
|
+
allowlist.push(new RegExp(`^${regex}(\\.html)?$`));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
await ctx.runBuild();
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
return ctx;
|
|
34
138
|
}
|
|
35
|
-
|
|
139
|
+
// src/integration.ts
|
|
36
140
|
function withUserConfig(config) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
let api;
|
|
54
|
-
vitePlugins.push(VitePWA({ ...pwa }));
|
|
55
|
-
vitePlugins.push({
|
|
56
|
-
name: "vite-plugin-pwa:pwa-assets:vitepress",
|
|
57
|
-
apply: "serve",
|
|
58
|
-
enforce: "pre",
|
|
59
|
-
configResolved(resolvedViteConfig) {
|
|
60
|
-
if (!resolvedViteConfig.build.ssr)
|
|
61
|
-
api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
|
|
62
|
-
},
|
|
63
|
-
async handleHotUpdate({ file, server }) {
|
|
64
|
-
const pwaAssetsGenerator = await api?.pwaAssetsGenerator();
|
|
65
|
-
if (await pwaAssetsGenerator?.checkHotUpdate(file))
|
|
66
|
-
await server.restart();
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
vitePlugins.push({
|
|
70
|
-
name: "vite-plugin-pwa:vitepress",
|
|
71
|
-
apply: "build",
|
|
72
|
-
enforce: "post",
|
|
73
|
-
configResolved(resolvedViteConfig) {
|
|
74
|
-
if (!resolvedViteConfig.build.ssr)
|
|
75
|
-
api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
const vitePressConfig = config;
|
|
79
|
-
const userTransformHead = vitePressConfig.transformHead;
|
|
80
|
-
const userBuildEnd = vitePressConfig.buildEnd;
|
|
81
|
-
vitePressConfig.transformHead = async (ctx) => {
|
|
82
|
-
const head = await userTransformHead?.(ctx) ?? [];
|
|
83
|
-
const assetsGenerator = await api?.pwaAssetsGenerator();
|
|
84
|
-
if (assetsGenerator) {
|
|
85
|
-
const htmlAssets = assetsGenerator.resolveHtmlAssets();
|
|
86
|
-
if (htmlAssets.themeColor)
|
|
87
|
-
head.push(["meta", { name: "theme-color", content: htmlAssets.themeColor.content }]);
|
|
88
|
-
for (const link of htmlAssets.links)
|
|
89
|
-
head.push(["link", { ...link }]);
|
|
90
|
-
}
|
|
91
|
-
const webManifestData = api?.webManifestData();
|
|
92
|
-
if (webManifestData) {
|
|
93
|
-
const href = webManifestData.href;
|
|
94
|
-
if (webManifestData.useCredentials)
|
|
95
|
-
head.push(["link", { rel: "manifest", href, crossorigin: "use-credentials" }]);
|
|
96
|
-
else
|
|
97
|
-
head.push(["link", { rel: "manifest", href }]);
|
|
98
|
-
}
|
|
99
|
-
const registerSWData = api?.registerSWData();
|
|
100
|
-
if (registerSWData && registerSWData.shouldRegisterSW) {
|
|
101
|
-
if (registerSWData.mode === "inline") {
|
|
102
|
-
head.push([
|
|
103
|
-
"script",
|
|
104
|
-
{ id: "vite-plugin-pwa:inline-sw" },
|
|
105
|
-
`if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('${registerSWData.inlinePath}', { scope: '${registerSWData.scope}' })})}`
|
|
106
|
-
]);
|
|
107
|
-
} else {
|
|
108
|
-
if (registerSWData.mode === "script-defer") {
|
|
109
|
-
head.push([
|
|
110
|
-
"script",
|
|
111
|
-
{
|
|
112
|
-
id: "vite-plugin-pwa:register-sw",
|
|
113
|
-
defer: "defer",
|
|
114
|
-
src: registerSWData.registerPath
|
|
115
|
-
}
|
|
116
|
-
]);
|
|
117
|
-
} else {
|
|
118
|
-
head.push([
|
|
119
|
-
"script",
|
|
120
|
-
{
|
|
121
|
-
id: "vite-plugin-pwa:register-sw",
|
|
122
|
-
src: registerSWData.registerPath
|
|
123
|
-
}
|
|
124
|
-
]);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return head;
|
|
129
|
-
};
|
|
130
|
-
let allowlist;
|
|
131
|
-
if (pwa.strategies !== "injectManifest" && pwa.experimental?.includeAllowlist === true) {
|
|
132
|
-
pwa.workbox = pwa.workbox ?? {};
|
|
133
|
-
allowlist = pwa.workbox.navigateFallbackAllowlist = pwa.workbox.navigateFallbackAllowlist ?? [];
|
|
134
|
-
pwa.workbox.runtimeCaching = pwa.workbox.runtimeCaching ?? [];
|
|
135
|
-
pwa.workbox.runtimeCaching.push({
|
|
136
|
-
urlPattern: ({ request, sameOrigin }) => {
|
|
137
|
-
return sameOrigin && request.mode === "navigate";
|
|
138
|
-
},
|
|
139
|
-
handler: "NetworkOnly",
|
|
140
|
-
options: {
|
|
141
|
-
plugins: [{
|
|
142
|
-
/* this callback will be called when the fetch call fails */
|
|
143
|
-
handlerDidError: async () => Response.redirect("404", 302),
|
|
144
|
-
/* this callback will prevent caching the response */
|
|
145
|
-
cacheWillUpdate: async () => null
|
|
146
|
-
}]
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
vitePressConfig.buildEnd = async (siteConfig) => {
|
|
151
|
-
await userBuildEnd?.(siteConfig);
|
|
152
|
-
if (api && !api.disabled) {
|
|
153
|
-
if (typeof allowlist !== "undefined") {
|
|
154
|
-
const base = siteConfig.site.base ?? "/";
|
|
155
|
-
for (const page of siteConfig.pages) {
|
|
156
|
-
const regex = page === "index.md" ? escapeStringRegexp(base) : escapeStringRegexp(`${base}${page.replace(/\.md$/, "")}`);
|
|
157
|
-
allowlist.push(new RegExp(`^${regex}(\\.html)?$`));
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
await api.generateSW();
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
return vitePressConfig;
|
|
141
|
+
const ctx = createVitePressPWAContext(config);
|
|
142
|
+
const viteConf = config.vite ??= {};
|
|
143
|
+
(viteConf.plugins ??= []).push([
|
|
144
|
+
MainPlugin(ctx),
|
|
145
|
+
VirtualModulesPlugin(ctx),
|
|
146
|
+
InfoPlugin(ctx),
|
|
147
|
+
DevPlugin(ctx),
|
|
148
|
+
DevMiddlewarePlugin(ctx),
|
|
149
|
+
DevAssetsMiddlewarePlugin(ctx),
|
|
150
|
+
AssetsPlugin(ctx),
|
|
151
|
+
BuildRegisterSWPlugin(ctx),
|
|
152
|
+
BuildPwaAssetsPlugin(ctx),
|
|
153
|
+
DevtoolsPlugin(ctx),
|
|
154
|
+
InspectorPlugin(ctx)
|
|
155
|
+
]);
|
|
156
|
+
return config;
|
|
164
157
|
}
|
|
165
|
-
|
|
158
|
+
// src/index.ts
|
|
166
159
|
async function withPwa(config) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
return withUserConfig(await config);
|
|
160
|
+
if (typeof config === "function") return async (ctx) => {
|
|
161
|
+
return withUserConfig(await config(ctx));
|
|
162
|
+
};
|
|
163
|
+
return withUserConfig(await config);
|
|
174
164
|
}
|
|
175
|
-
|
|
176
165
|
export { withPwa };
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { VitePWAOptions, VitePWAStrategy } from "@unplugin-pwa/core";
|
|
2
|
+
import { SWType } from "@vite-pwa/workbox-build/types";
|
|
3
|
+
export interface VitePressExperimentalOptions {
|
|
4
|
+
/**
|
|
5
|
+
* When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/vite-pwa/vitepress/issues/22
|
|
8
|
+
*
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
includeAllowlist?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export type PwaOptions<UserStrategy extends VitePWAStrategy, T extends SWType> = VitePWAOptions<UserStrategy, T> & {
|
|
14
|
+
experimental?: VitePressExperimentalOptions;
|
|
15
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vite-pwa/vitepress",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"description": "Zero-config PWA for VitePress",
|
|
6
6
|
"author": "antfu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -17,51 +17,75 @@
|
|
|
17
17
|
"workbox",
|
|
18
18
|
"pwa",
|
|
19
19
|
"vite",
|
|
20
|
-
"
|
|
20
|
+
"unplugin-pwa"
|
|
21
21
|
],
|
|
22
|
+
"sideEffects": false,
|
|
22
23
|
"exports": {
|
|
23
|
-
".":
|
|
24
|
-
|
|
25
|
-
"
|
|
24
|
+
".": "./dist/index.mjs",
|
|
25
|
+
"./types": {
|
|
26
|
+
"types": "./dist/index.d.mts"
|
|
26
27
|
},
|
|
27
|
-
"./package.json": "./package.json"
|
|
28
|
-
"./dist/*": "./dist/*"
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
29
|
},
|
|
30
|
-
"
|
|
31
|
-
"module": "dist/index.mjs",
|
|
32
|
-
"types": "dist/index.d.ts",
|
|
30
|
+
"types": "dist/index.d.mts",
|
|
33
31
|
"files": [
|
|
34
|
-
"*.d.ts",
|
|
35
32
|
"dist"
|
|
36
33
|
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=22.14.0"
|
|
36
|
+
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@vite-pwa/assets-generator": "^1.0.0",
|
|
39
|
-
"
|
|
38
|
+
"@vite-pwa/assets-generator": "^1.0.0 || ^2.0.0",
|
|
39
|
+
"magicast": "^0.5.0",
|
|
40
|
+
"rolldown": "^1.0.0-0",
|
|
41
|
+
"vitepress": "^1.0.0 || ^2.0.0-0"
|
|
40
42
|
},
|
|
41
43
|
"peerDependenciesMeta": {
|
|
42
44
|
"@vite-pwa/assets-generator": {
|
|
43
45
|
"optional": true
|
|
46
|
+
},
|
|
47
|
+
"magicast": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"rolldown": {
|
|
51
|
+
"optional": true
|
|
44
52
|
}
|
|
45
53
|
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@unplugin-pwa/core": "^0.0.2",
|
|
56
|
+
"@unplugin-pwa/inspector": "^0.0.2",
|
|
57
|
+
"@unplugin-pwa/vite": "^0.0.2",
|
|
58
|
+
"@vite-pwa/workbox-build": "^8.0.13",
|
|
59
|
+
"@vite-pwa/workbox-swkit": "^8.0.13",
|
|
60
|
+
"@vite-pwa/workbox-window": "^8.0.13"
|
|
61
|
+
},
|
|
46
62
|
"devDependencies": {
|
|
47
|
-
"@antfu/eslint-config": "^
|
|
48
|
-
"@antfu/ni": "^0.
|
|
49
|
-
"@
|
|
50
|
-
"@types/
|
|
51
|
-
"@
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
63
|
+
"@antfu/eslint-config": "^9.5.1",
|
|
64
|
+
"@antfu/ni": "^25.0.0",
|
|
65
|
+
"@arethetypeswrong/core": "^0.18.5",
|
|
66
|
+
"@types/debug": "^4.1.13",
|
|
67
|
+
"@types/node": "24.19.2",
|
|
68
|
+
"@vite-pwa/assets-generator": "^2.0.0",
|
|
69
|
+
"@vitejs/devtools": "^0.7.6",
|
|
70
|
+
"eslint": "^10.13.0",
|
|
71
|
+
"eslint-plugin-antfu": "^3.2.3",
|
|
72
|
+
"https-localhost": "4.7.2",
|
|
73
|
+
"publint": "^0.3.25",
|
|
74
|
+
"taze": "21.1.0",
|
|
75
|
+
"tsdown": "^0.23.1",
|
|
76
|
+
"typescript": "~6.0.3",
|
|
77
|
+
"vite": "^8.3.5",
|
|
78
|
+
"vitepress": "^2.0.0-alpha.21"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public",
|
|
82
|
+
"provenance": true
|
|
60
83
|
},
|
|
61
84
|
"scripts": {
|
|
62
|
-
"build": "unbuild",
|
|
63
85
|
"lint": "eslint .",
|
|
64
|
-
"lint:fix": "
|
|
65
|
-
"
|
|
86
|
+
"lint:fix": "pnpm lint --fix",
|
|
87
|
+
"update:deps": "taze -I",
|
|
88
|
+
"build": "tsdown",
|
|
89
|
+
"test:typecheck": "tsc --noEmit"
|
|
66
90
|
}
|
|
67
91
|
}
|
package/dist/index.cjs
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const vitePluginPwa = require('vite-plugin-pwa');
|
|
4
|
-
const node_path = require('node:path');
|
|
5
|
-
|
|
6
|
-
function escapeStringRegexp(value) {
|
|
7
|
-
return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function configurePWAOptions(config) {
|
|
11
|
-
const pwa = config.pwa ?? {};
|
|
12
|
-
const assetsDir = config.assetsDir ? config.assetsDir.replace(/\\/g, "/").replace(/^\.?\/|\/$/g, "") : "assets";
|
|
13
|
-
const dontCacheBustURLsMatching = new RegExp(`^${escapeStringRegexp(assetsDir)}/`);
|
|
14
|
-
if (!pwa.outDir)
|
|
15
|
-
pwa.outDir = ".vitepress/dist";
|
|
16
|
-
if (pwa.pwaAssets) {
|
|
17
|
-
const publicDir = typeof config.vite?.publicDir === "string" ? node_path.resolve(config.vite.publicDir) : node_path.resolve("public");
|
|
18
|
-
pwa.pwaAssets.integration = {
|
|
19
|
-
baseUrl: config.base ?? config.vite?.base ?? "/",
|
|
20
|
-
publicDir,
|
|
21
|
-
outDir: node_path.resolve(pwa.outDir)
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
if (pwa.strategies === "injectManifest") {
|
|
25
|
-
pwa.injectManifest = pwa.injectManifest ?? {};
|
|
26
|
-
pwa.injectManifest.dontCacheBustURLsMatching = dontCacheBustURLsMatching;
|
|
27
|
-
} else {
|
|
28
|
-
pwa.workbox = pwa.workbox ?? {};
|
|
29
|
-
pwa.workbox.dontCacheBustURLsMatching = dontCacheBustURLsMatching;
|
|
30
|
-
if (pwa.registerType === "autoUpdate" && (pwa.injectRegister === "script" || pwa.injectRegister === "script-defer" || pwa.injectRegister === "inline")) {
|
|
31
|
-
pwa.workbox.clientsClaim = true;
|
|
32
|
-
pwa.workbox.skipWaiting = true;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return pwa;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function withUserConfig(config) {
|
|
39
|
-
let viteConf = config.vite;
|
|
40
|
-
if (!viteConf) {
|
|
41
|
-
viteConf = {};
|
|
42
|
-
config.vite = viteConf;
|
|
43
|
-
}
|
|
44
|
-
let vitePlugins = viteConf.plugins;
|
|
45
|
-
if (typeof vitePlugins === "undefined") {
|
|
46
|
-
vitePlugins = [];
|
|
47
|
-
viteConf.plugins = vitePlugins;
|
|
48
|
-
}
|
|
49
|
-
if (vitePlugins && vitePlugins.length > 0) {
|
|
50
|
-
const pwaPlugin = vitePlugins.find((i) => i && typeof i === "object" && "name" in i && i.name === "vite-plugin-pwa");
|
|
51
|
-
if (pwaPlugin)
|
|
52
|
-
throw new Error("Remove vite-plugin-pwa plugin from Vite Plugins entry in VitePress config file");
|
|
53
|
-
}
|
|
54
|
-
const pwa = configurePWAOptions(config);
|
|
55
|
-
let api;
|
|
56
|
-
vitePlugins.push(vitePluginPwa.VitePWA({ ...pwa }));
|
|
57
|
-
vitePlugins.push({
|
|
58
|
-
name: "vite-plugin-pwa:pwa-assets:vitepress",
|
|
59
|
-
apply: "serve",
|
|
60
|
-
enforce: "pre",
|
|
61
|
-
configResolved(resolvedViteConfig) {
|
|
62
|
-
if (!resolvedViteConfig.build.ssr)
|
|
63
|
-
api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
|
|
64
|
-
},
|
|
65
|
-
async handleHotUpdate({ file, server }) {
|
|
66
|
-
const pwaAssetsGenerator = await api?.pwaAssetsGenerator();
|
|
67
|
-
if (await pwaAssetsGenerator?.checkHotUpdate(file))
|
|
68
|
-
await server.restart();
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
vitePlugins.push({
|
|
72
|
-
name: "vite-plugin-pwa:vitepress",
|
|
73
|
-
apply: "build",
|
|
74
|
-
enforce: "post",
|
|
75
|
-
configResolved(resolvedViteConfig) {
|
|
76
|
-
if (!resolvedViteConfig.build.ssr)
|
|
77
|
-
api = resolvedViteConfig.plugins.find((p) => p.name === "vite-plugin-pwa")?.api;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
const vitePressConfig = config;
|
|
81
|
-
const userTransformHead = vitePressConfig.transformHead;
|
|
82
|
-
const userBuildEnd = vitePressConfig.buildEnd;
|
|
83
|
-
vitePressConfig.transformHead = async (ctx) => {
|
|
84
|
-
const head = await userTransformHead?.(ctx) ?? [];
|
|
85
|
-
const assetsGenerator = await api?.pwaAssetsGenerator();
|
|
86
|
-
if (assetsGenerator) {
|
|
87
|
-
const htmlAssets = assetsGenerator.resolveHtmlAssets();
|
|
88
|
-
if (htmlAssets.themeColor)
|
|
89
|
-
head.push(["meta", { name: "theme-color", content: htmlAssets.themeColor.content }]);
|
|
90
|
-
for (const link of htmlAssets.links)
|
|
91
|
-
head.push(["link", { ...link }]);
|
|
92
|
-
}
|
|
93
|
-
const webManifestData = api?.webManifestData();
|
|
94
|
-
if (webManifestData) {
|
|
95
|
-
const href = webManifestData.href;
|
|
96
|
-
if (webManifestData.useCredentials)
|
|
97
|
-
head.push(["link", { rel: "manifest", href, crossorigin: "use-credentials" }]);
|
|
98
|
-
else
|
|
99
|
-
head.push(["link", { rel: "manifest", href }]);
|
|
100
|
-
}
|
|
101
|
-
const registerSWData = api?.registerSWData();
|
|
102
|
-
if (registerSWData && registerSWData.shouldRegisterSW) {
|
|
103
|
-
if (registerSWData.mode === "inline") {
|
|
104
|
-
head.push([
|
|
105
|
-
"script",
|
|
106
|
-
{ id: "vite-plugin-pwa:inline-sw" },
|
|
107
|
-
`if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('${registerSWData.inlinePath}', { scope: '${registerSWData.scope}' })})}`
|
|
108
|
-
]);
|
|
109
|
-
} else {
|
|
110
|
-
if (registerSWData.mode === "script-defer") {
|
|
111
|
-
head.push([
|
|
112
|
-
"script",
|
|
113
|
-
{
|
|
114
|
-
id: "vite-plugin-pwa:register-sw",
|
|
115
|
-
defer: "defer",
|
|
116
|
-
src: registerSWData.registerPath
|
|
117
|
-
}
|
|
118
|
-
]);
|
|
119
|
-
} else {
|
|
120
|
-
head.push([
|
|
121
|
-
"script",
|
|
122
|
-
{
|
|
123
|
-
id: "vite-plugin-pwa:register-sw",
|
|
124
|
-
src: registerSWData.registerPath
|
|
125
|
-
}
|
|
126
|
-
]);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return head;
|
|
131
|
-
};
|
|
132
|
-
let allowlist;
|
|
133
|
-
if (pwa.strategies !== "injectManifest" && pwa.experimental?.includeAllowlist === true) {
|
|
134
|
-
pwa.workbox = pwa.workbox ?? {};
|
|
135
|
-
allowlist = pwa.workbox.navigateFallbackAllowlist = pwa.workbox.navigateFallbackAllowlist ?? [];
|
|
136
|
-
pwa.workbox.runtimeCaching = pwa.workbox.runtimeCaching ?? [];
|
|
137
|
-
pwa.workbox.runtimeCaching.push({
|
|
138
|
-
urlPattern: ({ request, sameOrigin }) => {
|
|
139
|
-
return sameOrigin && request.mode === "navigate";
|
|
140
|
-
},
|
|
141
|
-
handler: "NetworkOnly",
|
|
142
|
-
options: {
|
|
143
|
-
plugins: [{
|
|
144
|
-
/* this callback will be called when the fetch call fails */
|
|
145
|
-
handlerDidError: async () => Response.redirect("404", 302),
|
|
146
|
-
/* this callback will prevent caching the response */
|
|
147
|
-
cacheWillUpdate: async () => null
|
|
148
|
-
}]
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
vitePressConfig.buildEnd = async (siteConfig) => {
|
|
153
|
-
await userBuildEnd?.(siteConfig);
|
|
154
|
-
if (api && !api.disabled) {
|
|
155
|
-
if (typeof allowlist !== "undefined") {
|
|
156
|
-
const base = siteConfig.site.base ?? "/";
|
|
157
|
-
for (const page of siteConfig.pages) {
|
|
158
|
-
const regex = page === "index.md" ? escapeStringRegexp(base) : escapeStringRegexp(`${base}${page.replace(/\.md$/, "")}`);
|
|
159
|
-
allowlist.push(new RegExp(`^${regex}(\\.html)?$`));
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
await api.generateSW();
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
return vitePressConfig;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
async function withPwa(config) {
|
|
169
|
-
if (typeof config === "function") {
|
|
170
|
-
return async (ctx) => {
|
|
171
|
-
const userConfig = await config(ctx);
|
|
172
|
-
return withUserConfig(userConfig);
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
return withUserConfig(await config);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
exports.withPwa = withPwa;
|
package/dist/index.d.cts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { DefaultTheme, UserConfigExport } from 'vitepress';
|
|
2
|
-
import { VitePWAOptions } from 'vite-plugin-pwa';
|
|
3
|
-
|
|
4
|
-
interface PwaOptions extends Partial<VitePWAOptions> {
|
|
5
|
-
experimental?: {
|
|
6
|
-
/**
|
|
7
|
-
* When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
|
|
8
|
-
*
|
|
9
|
-
* @see https://github.com/vite-pwa/vitepress/issues/22
|
|
10
|
-
*
|
|
11
|
-
* @default false
|
|
12
|
-
*/
|
|
13
|
-
includeAllowlist?: boolean;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
declare module 'vitepress' {
|
|
17
|
-
interface UserConfig {
|
|
18
|
-
pwa?: PwaOptions;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
declare function withPwa<T = DefaultTheme.Config>(config: UserConfigExport<T>): Promise<UserConfigExport<T>>;
|
|
23
|
-
|
|
24
|
-
export { type PwaOptions, withPwa };
|
package/dist/index.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { DefaultTheme, UserConfigExport } from 'vitepress';
|
|
2
|
-
import { VitePWAOptions } from 'vite-plugin-pwa';
|
|
3
|
-
|
|
4
|
-
interface PwaOptions extends Partial<VitePWAOptions> {
|
|
5
|
-
experimental?: {
|
|
6
|
-
/**
|
|
7
|
-
* When using `generateSW` strategy, include the logic to handle the `workbox.navigateFallbackAllowlist` option.
|
|
8
|
-
*
|
|
9
|
-
* @see https://github.com/vite-pwa/vitepress/issues/22
|
|
10
|
-
*
|
|
11
|
-
* @default false
|
|
12
|
-
*/
|
|
13
|
-
includeAllowlist?: boolean;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
declare module 'vitepress' {
|
|
17
|
-
interface UserConfig {
|
|
18
|
-
pwa?: PwaOptions;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
declare function withPwa<T = DefaultTheme.Config>(config: UserConfigExport<T>): Promise<UserConfigExport<T>>;
|
|
23
|
-
|
|
24
|
-
export { type PwaOptions, withPwa };
|
package/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './dist'
|