Introduce serviceWorker, disabled by default

This commit is contained in:
Alex Shpak 2020-04-12 20:50:03 +02:00
parent e4e43bd9b1
commit 9719692512
9 changed files with 84 additions and 4 deletions

View file

@ -185,6 +185,10 @@ disableKinds = ['taxonomy', 'taxonomyTerm']
# Portable links meant to work with text editors and let you write markdown without {{< relref >}} shortcode # Portable links meant to work with text editors and let you write markdown without {{< relref >}} shortcode
# Theme will print warning if page referenced in markdown does not exists. # Theme will print warning if page referenced in markdown does not exists.
BookPortableLinks = true BookPortableLinks = true
# /!\ This is an experimental feature, might be removed or changed at any time
# (Optional, experimental, default false) Enables service worker that caches visited pages and resources for offline use.
BookServiceWorker = true
``` ```
### Multi-Language Support ### Multi-Language Support

View file

@ -12,20 +12,27 @@
document.addEventListener('keypress', focusSearchFieldOnKeyPress); document.addEventListener('keypress', focusSearchFieldOnKeyPress);
function focusSearchFieldOnKeyPress(e) { /**
* @param {Event} event
*/
function focusSearchFieldOnKeyPress(event) {
if (input === document.activeElement) { if (input === document.activeElement) {
return; return;
} }
const characterPressed = String.fromCharCode(e.charCode); const characterPressed = String.fromCharCode(event.charCode);
if (!isHotkey(characterPressed)) { if (!isHotkey(characterPressed)) {
return; return;
} }
input.focus(); input.focus();
e.preventDefault(); event.preventDefault();
} }
/**
* @param {String} character
* @returns {Boolean}
*/
function isHotkey(character) { function isHotkey(character) {
const dataHotkeys = input.getAttribute('data-hotkeys') || ''; const dataHotkeys = input.getAttribute('data-hotkeys') || '';
return dataHotkeys.indexOf(character) >= 0; return dataHotkeys.indexOf(character) >= 0;
@ -63,6 +70,10 @@
}); });
} }
/**
* @param {String} src
* @param {Function} callback
*/
function loadScript(src, callback) { function loadScript(src, callback) {
const script = document.createElement('script'); const script = document.createElement('script');
script.defer = true; script.defer = true;

6
assets/sw-register.js Normal file
View file

@ -0,0 +1,6 @@
if (navigator.serviceWorker) {
navigator.serviceWorker.register(
"{{ "/sw.js" | relURL }}",
{ scope: "{{ "/" | relURL }}" }
);
}

View file

@ -97,3 +97,7 @@ enableGitInfo = true
# Portable links meant to work with text editors and let you write markdown without {{< relref >}} shortcode # Portable links meant to work with text editors and let you write markdown without {{< relref >}} shortcode
# Theme will print warning if page referenced in markdown does not exists. # Theme will print warning if page referenced in markdown does not exists.
BookPortableLinks = true BookPortableLinks = true
# /!\ This is an experimental feature, might be removed or changed at any time
# (Optional, experimental, default false) Enables service worker that caches visited pages and resources for offline use.
BookServiceWorker = true

View file

@ -93,3 +93,7 @@ params:
# Portable links meant to work with text editors and let you write markdown without {{< relref >}} shortcode # Portable links meant to work with text editors and let you write markdown without {{< relref >}} shortcode
# Theme will print warning if page referenced in markdown does not exists. # Theme will print warning if page referenced in markdown does not exists.
BookPortableLinks: true BookPortableLinks: true
# /!\ This is an experimental feature, might be removed or changed at any time
# (Optional, experimental, default false) Enables service worker that caches visited pages and resources for offline use.
BookServiceWorker: true

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"Target":"book.min.284c8fc21ced13c579d9027a9d14893c56b243c6045001180391cebb4cc36ab8.css","MediaType":"text/css","Data":{"Integrity":"sha256-KEyPwhztE8V52QJ6nRSJPFayQ8YEUAEYA5HOu0zDarg="}}

View file

@ -16,11 +16,16 @@
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Integrity }}"> <link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Integrity }}">
{{- if default true .Site.Params.BookSearch }} {{- if default true .Site.Params.BookSearch }}
{{- $searchJSFile := printf "%s.search.js" .Language.Lang -}} {{- $searchJSFile := printf "%s.search.js" .Language.Lang }}
{{- $searchJS := resources.Get "search.js" | resources.ExecuteAsTemplate $searchJSFile . | resources.Minify | resources.Fingerprint }} {{- $searchJS := resources.Get "search.js" | resources.ExecuteAsTemplate $searchJSFile . | resources.Minify | resources.Fingerprint }}
<script defer src="{{ $searchJS.RelPermalink }}" integrity="{{ $searchJS.Data.Integrity }}"></script> <script defer src="{{ $searchJS.RelPermalink }}" integrity="{{ $searchJS.Data.Integrity }}"></script>
{{ end -}} {{ end -}}
{{- if .Site.Params.BookServiceWorker }}
{{- $swJS := resources.Get "sw-register.js" | resources.ExecuteAsTemplate "sw.js" . | resources.Minify | resources.Fingerprint }}
<script defer src="{{ $swJS.RelPermalink }}" integrity="{{ $swJS.Data.Integrity }}"></script>
{{ end -}}
{{- template "_internal/google_analytics_async.html" . -}} {{- template "_internal/google_analytics_async.html" . -}}
<!-- RSS --> <!-- RSS -->

44
static/sw.js Normal file
View file

@ -0,0 +1,44 @@
self.addEventListener("install", function (event) {
self.skipWaiting();
});
self.addEventListener("fetch", (event) => {
const cacheName = self.location.pathname
const request = event.request;
if (request.method !== "GET") {
return;
}
/**
* @param {Response} response
* @returns {Promise<Response>}
*/
function saveToCache(response) {
if (cacheable(response)) {
return caches
.open(cacheName)
.then((cache) => cache.put(request, response.clone()))
.then(() => response);
} else {
return response;
}
}
/**
* @param {Error} error
*/
function serveFromCache(error) {
return caches.open(cacheName).then((cache) => cache.match(request.url));
}
/**
* @param {Response} response
* @returns {Boolean}
*/
function cacheable(response) {
return response.type === "basic" && response.ok && !response.headers.has("Content-Disposition")
}
event.respondWith(fetch(request).then(saveToCache).catch(serveFromCache));
});