added 2026-10-07 07:45:31
This commit is contained in:
@@ -4,3 +4,4 @@
|
|||||||
- [Gitea Create Repo API: Curl POST](/gitea-create-repo-api-curl-post.md)
|
- [Gitea Create Repo API: Curl POST](/gitea-create-repo-api-curl-post.md)
|
||||||
- [Mount LUKS drive to Windows Subsystem for Linux Bare](/mount-luks-drive-to-windwos-subsystem-for-linux-bare.md)
|
- [Mount LUKS drive to Windows Subsystem for Linux Bare](/mount-luks-drive-to-windwos-subsystem-for-linux-bare.md)
|
||||||
- [Convert .mkv to .mp4 with FFMPEG at higher quality](/convert-mkv-to-mp4-with-ffmpeg-at-higher-quality.md)
|
- [Convert .mkv to .mp4 with FFMPEG at higher quality](/convert-mkv-to-mp4-with-ffmpeg-at-higher-quality.md)
|
||||||
|
- [GOHUGO PWA](/gohugo-pwa.md)
|
||||||
|
|||||||
+252
@@ -0,0 +1,252 @@
|
|||||||
|
# GOHUGO PWA SETUP
|
||||||
|
|
||||||
|
## layouts/partials/custom_head.html
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- A partial to be overwritten by the user.
|
||||||
|
Simply place a custom_head.html into
|
||||||
|
your local /layouts/partials-directory -->
|
||||||
|
|
||||||
|
<div id="sw-update" hidden>
|
||||||
|
<span>A new version is available.</span>
|
||||||
|
<button id="sw-update-button" type="button">
|
||||||
|
Reload
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#sw-update {
|
||||||
|
position: fixed;
|
||||||
|
right: 1rem;
|
||||||
|
bottom: 1rem;
|
||||||
|
z-index: 1000;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
color: white;
|
||||||
|
background: #222;
|
||||||
|
border-radius: 0.4rem;
|
||||||
|
box-shadow: 0 0.25rem 1rem rgb(0 0 0 / 25%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sw-update button {
|
||||||
|
margin-left: 0.75rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
let refreshing = false;
|
||||||
|
|
||||||
|
navigator.serviceWorker.addEventListener("controllerchange", () => {
|
||||||
|
if (refreshing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshing = true;
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
navigator.serviceWorker.register("/sw.js").then((registration) => {
|
||||||
|
function showUpdatePrompt(worker) {
|
||||||
|
const prompt = document.querySelector("#sw-update");
|
||||||
|
const button = document.querySelector("#sw-update-button");
|
||||||
|
|
||||||
|
prompt.hidden = false;
|
||||||
|
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
worker.postMessage({
|
||||||
|
type: "SKIP_WAITING"
|
||||||
|
});
|
||||||
|
}, { once: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle an update that was already waiting.
|
||||||
|
if (registration.waiting) {
|
||||||
|
showUpdatePrompt(registration.waiting);
|
||||||
|
}
|
||||||
|
|
||||||
|
registration.addEventListener("updatefound", () => {
|
||||||
|
const worker = registration.installing;
|
||||||
|
|
||||||
|
if (!worker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.addEventListener("statechange", () => {
|
||||||
|
if (
|
||||||
|
worker.state === "installed" &&
|
||||||
|
navigator.serviceWorker.controller
|
||||||
|
) {
|
||||||
|
showUpdatePrompt(worker);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ask the browser to check for a newer sw.js.
|
||||||
|
registration.update();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## layouts/partials/custom_body.html
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="/main.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## static/main.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
navigator.serviceWorker.register('/sw.js')
|
||||||
|
.then(req => {
|
||||||
|
console.log('Registered!', reg);
|
||||||
|
}).catch(err => {
|
||||||
|
console.log('Registration failed: ', err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## static/manifest.webmanifest
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Pat K",
|
||||||
|
"short_name": "PK",
|
||||||
|
"start_url": "/",
|
||||||
|
"scope": "/",
|
||||||
|
"background_color": "#000000",
|
||||||
|
"theme_color": "#2e1e3c",
|
||||||
|
"display": "standalone",
|
||||||
|
"id": "5801e2e4fab6956ac349d7c724329b869cbffb19e87e545cd5bf6ffb2cc4a3e7",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "icons/192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "icons/512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## static/icons
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ffmpeg -i example.png -vf "scale=192:192" icon-192.png
|
||||||
|
ffmpeg -i example.png -vf "scale=512:512" icon-512.png
|
||||||
|
```
|
||||||
|
|
||||||
|
## hugo.toml
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[outputs]
|
||||||
|
home = ["HTML", "SW"]
|
||||||
|
|
||||||
|
[outputFormats.SW]
|
||||||
|
mediaType = "text/javascript"
|
||||||
|
baseName = "sw"
|
||||||
|
isPlainText = true
|
||||||
|
notAlternative = true
|
||||||
|
```
|
||||||
|
|
||||||
|
## themes/hugo-bearblog/layouts/index.sw.js
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const CACHE_NAME = "patk-{{ now.Unix }}";
|
||||||
|
|
||||||
|
const PRECACHE = [
|
||||||
|
"/index.html",
|
||||||
|
"/manifest.webmanifest",
|
||||||
|
"/main.js",
|
||||||
|
"/robots.txt",
|
||||||
|
"/icons/192.png",
|
||||||
|
"/icons/512.png",
|
||||||
|
"/404.html",
|
||||||
|
"/sitemap.xml",
|
||||||
|
{{- range hugo.Sites }}
|
||||||
|
{{- range .Pages }}
|
||||||
|
{{ printf "%q" .RelPermalink }},
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
];
|
||||||
|
|
||||||
|
self.addEventListener("install", (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.open(CACHE_NAME).then((cache) => {
|
||||||
|
return cache.addAll(PRECACHE);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// self.skipWaiting(); // remove if want to changes to occur without pressing reload button
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener("activate", (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.keys().then((keys) => {
|
||||||
|
return Promise.all(
|
||||||
|
keys
|
||||||
|
.filter((key) => key !== CACHE_NAME)
|
||||||
|
.map((key) => caches.delete(key))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
self.clients.claim();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener("fetch", (event) => {
|
||||||
|
event.respondWith(
|
||||||
|
caches.match(event.request).then((cachedResponse) => {
|
||||||
|
return cachedResponse || fetch(event.request);
|
||||||
|
// return fetch(event.request) || cachedResponse; // switch if you want to fetch resources first and serve cached if offline; current serve cache then request online fetch if error or not available
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener("message", (event) => {
|
||||||
|
if (event.data?.type === "SKIP_WAITING") {
|
||||||
|
self.skipWaiting();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Makefile
|
||||||
|
|
||||||
|
- Make file requires tabs not space indentation
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
.PHONY: help cl gen serve pub dev
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Usage: make <option>"
|
||||||
|
@echo "gen ..... generate site"
|
||||||
|
@echo "serve ... generate site and http serve 8080"
|
||||||
|
@echo "dev ..... hugo serve"
|
||||||
|
@echo "pub ..... generate and publish to griffin nginx-blog/config/www"
|
||||||
|
|
||||||
|
cl:
|
||||||
|
@clear
|
||||||
|
|
||||||
|
gen:
|
||||||
|
hugo --cleanDestinationDir
|
||||||
|
|
||||||
|
serve: gen
|
||||||
|
cd /opt/websites/patk/public && \
|
||||||
|
python3 -m http.server -b 0.0.0.0 8080 && \
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
dev: cl
|
||||||
|
hugo serve
|
||||||
|
|
||||||
|
pub: cl gen
|
||||||
|
rsync -azvP --delete public/ griffin-wsl:/opt/docker/volumes/nginx-blog/config/www
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user