@azerion/bunosaurus-plugin-pwa 0.0.0-stage → 4.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 +6 -2
- package/lib/index.d.ts +10 -0
- package/lib/index.js +113 -0
- package/lib/options.d.ts +9 -0
- package/lib/options.js +45 -0
- package/lib/registerSw.d.ts +18 -0
- package/lib/registerSw.js +191 -0
- package/lib/renderReloadPopup.d.ts +8 -0
- package/lib/renderReloadPopup.js +22 -0
- package/lib/sw.d.ts +7 -0
- package/lib/sw.js +109 -0
- package/lib/theme/PwaReloadPopup/index.d.ts +9 -0
- package/lib/theme/PwaReloadPopup/index.js +54 -0
- package/lib/theme/PwaReloadPopup/styles.module.css +39 -0
- package/package.json +46 -4
- package/src/index.ts +150 -0
- package/src/options.ts +63 -0
- package/src/plugin-pwa.d.ts +90 -0
- package/src/registerSw.ts +242 -0
- package/src/renderReloadPopup.tsx +28 -0
- package/src/sw.ts +135 -0
- package/src/theme/PwaReloadPopup/index.tsx +59 -0
- package/src/theme/PwaReloadPopup/styles.module.css +39 -0
- package/src/types.d.ts +8 -0
package/src/sw.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {PrecacheController, type PrecacheEntry} from 'workbox-precaching';
|
|
9
|
+
|
|
10
|
+
function parseSwParams() {
|
|
11
|
+
const params = JSON.parse(
|
|
12
|
+
new URLSearchParams(self.location.search).get('params')!,
|
|
13
|
+
);
|
|
14
|
+
if (params.debug) {
|
|
15
|
+
console.log('[Docusaurus-PWA][SW]: Service Worker params:', params);
|
|
16
|
+
}
|
|
17
|
+
return params;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Doc advises against dynamic imports in SW
|
|
21
|
+
// https://developers.google.com/web/tools/workbox/guides/using-bundlers#code_splitting_and_dynamic_imports
|
|
22
|
+
// https://x.com/sebastienlorber/status/1280155204575518720
|
|
23
|
+
// but looks it's working fine as it's inlined by webpack, need to double check
|
|
24
|
+
async function runSWCustomCode(params: {offlineMode: boolean; debug: boolean}) {
|
|
25
|
+
if (process.env.PWA_SW_CUSTOM) {
|
|
26
|
+
const customSW = await import(process.env.PWA_SW_CUSTOM);
|
|
27
|
+
if (typeof customSW.default === 'function') {
|
|
28
|
+
customSW.default(params);
|
|
29
|
+
} else if (params.debug) {
|
|
30
|
+
console.warn(
|
|
31
|
+
'[Docusaurus-PWA][SW]: swCustom should have a default export function',
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Gets different possible variations for a request URL. Similar to
|
|
39
|
+
* https://git.io/JvixK
|
|
40
|
+
*/
|
|
41
|
+
function getPossibleURLs(url: string) {
|
|
42
|
+
const urlObject = new URL(url, self.location.href);
|
|
43
|
+
|
|
44
|
+
if (urlObject.origin !== self.location.origin) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Ignore search params and hash
|
|
49
|
+
urlObject.search = '';
|
|
50
|
+
urlObject.hash = '';
|
|
51
|
+
|
|
52
|
+
return [
|
|
53
|
+
// /blog.html
|
|
54
|
+
urlObject.href,
|
|
55
|
+
// /blog/ => /blog/index.html
|
|
56
|
+
// /blog => /blog/index.html
|
|
57
|
+
`${urlObject.href}${urlObject.pathname.endsWith('/') ? '' : '/'}index.html`,
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
(async () => {
|
|
62
|
+
const params = parseSwParams();
|
|
63
|
+
|
|
64
|
+
const precacheManifest = (
|
|
65
|
+
self as typeof globalThis & {__WB_MANIFEST: (string | PrecacheEntry)[]}
|
|
66
|
+
).__WB_MANIFEST;
|
|
67
|
+
const controller = new PrecacheController({
|
|
68
|
+
// Safer to turn this true?
|
|
69
|
+
fallbackToNetwork: true,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (params.offlineMode) {
|
|
73
|
+
controller.addToCacheList(precacheManifest);
|
|
74
|
+
if (params.debug) {
|
|
75
|
+
console.log('[Docusaurus-PWA][SW]: addToCacheList', {precacheManifest});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await runSWCustomCode(params);
|
|
80
|
+
|
|
81
|
+
self.addEventListener('install', (event) => {
|
|
82
|
+
if (params.debug) {
|
|
83
|
+
console.log('[Docusaurus-PWA][SW]: install event', {event});
|
|
84
|
+
}
|
|
85
|
+
(event as ExtendableEvent).waitUntil(
|
|
86
|
+
controller.install(event as ExtendableEvent),
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
self.addEventListener('activate', (event) => {
|
|
91
|
+
if (params.debug) {
|
|
92
|
+
console.log('[Docusaurus-PWA][SW]: activate event', {event});
|
|
93
|
+
}
|
|
94
|
+
(event as ExtendableEvent).waitUntil(
|
|
95
|
+
controller.activate(event as ExtendableEvent),
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
self.addEventListener('fetch', async (event) => {
|
|
100
|
+
if (params.offlineMode) {
|
|
101
|
+
const requestURL = (event as FetchEvent).request.url;
|
|
102
|
+
const possibleURLs = getPossibleURLs(requestURL);
|
|
103
|
+
for (const possibleURL of possibleURLs) {
|
|
104
|
+
const cacheKey = controller.getCacheKeyForURL(possibleURL);
|
|
105
|
+
if (cacheKey) {
|
|
106
|
+
const cachedResponse = caches.match(cacheKey) as Promise<Response>;
|
|
107
|
+
if (params.debug) {
|
|
108
|
+
console.log('[Docusaurus-PWA][SW]: serving cached asset', {
|
|
109
|
+
requestURL,
|
|
110
|
+
possibleURL,
|
|
111
|
+
possibleURLs,
|
|
112
|
+
cacheKey,
|
|
113
|
+
cachedResponse,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
(event as FetchEvent).respondWith(cachedResponse);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
self.addEventListener('message', async (event) => {
|
|
124
|
+
if (params.debug) {
|
|
125
|
+
console.log('[Docusaurus-PWA][SW]: message event', {event});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const type = (event as MessageEvent).data?.type;
|
|
129
|
+
|
|
130
|
+
if (type === 'SKIP_WAITING') {
|
|
131
|
+
// lib def bug, see https://github.com/microsoft/TypeScript/issues/14877
|
|
132
|
+
(self as typeof globalThis & ServiceWorkerGlobalScope).skipWaiting();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
})();
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {type ReactNode, useState} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import Translate, {translate} from '@docusaurus/Translate';
|
|
11
|
+
import type {Props} from '@theme/PwaReloadPopup';
|
|
12
|
+
|
|
13
|
+
import styles from './styles.module.css';
|
|
14
|
+
|
|
15
|
+
export default function PwaReloadPopup({onReload}: Props): ReactNode {
|
|
16
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
isVisible && (
|
|
20
|
+
<div className={clsx('alert', 'alert--secondary', styles.popup)}>
|
|
21
|
+
<p>
|
|
22
|
+
<Translate
|
|
23
|
+
id="theme.PwaReloadPopup.info"
|
|
24
|
+
description="The text for PWA reload popup">
|
|
25
|
+
New version available
|
|
26
|
+
</Translate>
|
|
27
|
+
</p>
|
|
28
|
+
<div className={styles.buttonContainer}>
|
|
29
|
+
<button
|
|
30
|
+
className="button button--link"
|
|
31
|
+
type="button"
|
|
32
|
+
onClick={() => {
|
|
33
|
+
setIsVisible(false);
|
|
34
|
+
onReload();
|
|
35
|
+
}}>
|
|
36
|
+
<Translate
|
|
37
|
+
id="theme.PwaReloadPopup.refreshButtonText"
|
|
38
|
+
description="The text for PWA reload button">
|
|
39
|
+
Refresh
|
|
40
|
+
</Translate>
|
|
41
|
+
</button>
|
|
42
|
+
|
|
43
|
+
<button
|
|
44
|
+
aria-label={translate({
|
|
45
|
+
id: 'theme.PwaReloadPopup.closeButtonAriaLabel',
|
|
46
|
+
message: 'Close',
|
|
47
|
+
description:
|
|
48
|
+
'The ARIA label for close button of PWA reload popup',
|
|
49
|
+
})}
|
|
50
|
+
className="close"
|
|
51
|
+
type="button"
|
|
52
|
+
onClick={() => setIsVisible(false)}>
|
|
53
|
+
<span aria-hidden="true">×</span>
|
|
54
|
+
</button>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.popup {
|
|
9
|
+
position: fixed;
|
|
10
|
+
bottom: 16px;
|
|
11
|
+
right: 16px;
|
|
12
|
+
width: 344px;
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: space-between;
|
|
16
|
+
z-index: 999;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.popup p {
|
|
20
|
+
margin: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@media screen and (width <= 500px) {
|
|
24
|
+
.popup {
|
|
25
|
+
width: 100%;
|
|
26
|
+
bottom: 0;
|
|
27
|
+
right: 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.buttonContainer {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.buttonContainer :global(.close) {
|
|
37
|
+
margin: 0;
|
|
38
|
+
padding: 0;
|
|
39
|
+
}
|
package/src/types.d.ts
ADDED