Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/wlh320/hugo-theme-hulga.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'assets/sw.js')
-rw-r--r--assets/sw.js388
1 files changed, 388 insertions, 0 deletions
diff --git a/assets/sw.js b/assets/sw.js
new file mode 100644
index 0000000..042741d
--- /dev/null
+++ b/assets/sw.js
@@ -0,0 +1,388 @@
+const CACHE_VERSION = 1;
+
+const BASE_CACHE_FILES = [
+ '/css/hulga.min.css',
+ '/css/toc.min.css',
+ '/css/hulga-dark.min.css',
+ '/css/katex.min.css',
+ '/css/monokai.css',
+ '/css/monokailight.css',
+ '/js/tocbot.min.js',
+ '/js/anchor.min.js',
+ '/js/auto-render.min.js',
+ '/js/katex.min.js',
+ '/js/vanilla-back-to-top.min.js',
+ '/manifest.json',
+ '/favicon.ico',
+];
+
+const OFFLINE_CACHE_FILES = [
+ '/index.html'
+];
+
+const NOT_FOUND_CACHE_FILES = [
+ '/404.html',
+];
+
+const OFFLINE_PAGE = '/index.html';
+const NOT_FOUND_PAGE = '/404.html';
+
+const CACHE_VERSIONS = {
+ assets: 'assets-v' + CACHE_VERSION,
+ content: 'content-v' + CACHE_VERSION,
+ offline: 'offline-v' + CACHE_VERSION,
+ notFound: '404-v' + CACHE_VERSION,
+};
+
+// Define MAX_TTL's in SECONDS for specific file extensions
+const MAX_TTL = {
+ '/': 3600,
+ html: 3600,
+ json: 86400,
+ js: 86400,
+ css: 86400,
+};
+
+const CACHE_BLACKLIST = [
+ (str) => {
+ return !str.startsWith('https://blog.zilch40.wang');
+ },
+];
+
+const SUPPORTED_METHODS = [
+ 'GET',
+];
+
+/**
+ * isBlackListed
+ * @param {string} url
+ * @returns {boolean}
+ */
+function isBlacklisted(url) {
+ return (CACHE_BLACKLIST.length > 0) ? !CACHE_BLACKLIST.filter((rule) => {
+ if (typeof rule === 'function') {
+ return !rule(url);
+ } else {
+ return false;
+ }
+ }).length : false
+}
+
+/**
+ * getFileExtension
+ * @param {string} url
+ * @returns {string}
+ */
+function getFileExtension(url) {
+ let extension = url.split('.').reverse()[0].split('?')[0];
+ return (extension.endsWith('/')) ? '/' : extension;
+}
+
+/**
+ * getTTL
+ * @param {string} url
+ */
+function getTTL(url) {
+ if (typeof url === 'string') {
+ let extension = getFileExtension(url);
+ if (typeof MAX_TTL[extension] === 'number') {
+ return MAX_TTL[extension];
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+}
+
+/**
+ * installServiceWorker
+ * @returns {Promise}
+ */
+function installServiceWorker() {
+ return Promise.all(
+ [
+ caches.open(CACHE_VERSIONS.assets)
+ .then(
+ (cache) => {
+ return cache.addAll(BASE_CACHE_FILES);
+ }
+ ),
+ caches.open(CACHE_VERSIONS.offline)
+ .then(
+ (cache) => {
+ return cache.addAll(OFFLINE_CACHE_FILES);
+ }
+ ),
+ caches.open(CACHE_VERSIONS.notFound)
+ .then(
+ (cache) => {
+ return cache.addAll(NOT_FOUND_CACHE_FILES);
+ }
+ )
+ ]
+ )
+ .then(() => {
+ return self.skipWaiting();
+ });
+}
+
+/**
+ * cleanupLegacyCache
+ * @returns {Promise}
+ */
+function cleanupLegacyCache() {
+
+ let currentCaches = Object.keys(CACHE_VERSIONS)
+ .map(
+ (key) => {
+ return CACHE_VERSIONS[key];
+ }
+ );
+
+ return new Promise(
+ (resolve, reject) => {
+
+ caches.keys()
+ .then(
+ (keys) => {
+ return legacyKeys = keys.filter(
+ (key) => {
+ return !~currentCaches.indexOf(key);
+ }
+ );
+ }
+ )
+ .then(
+ (legacy) => {
+ if (legacy.length) {
+ Promise.all(
+ legacy.map(
+ (legacyKey) => {
+ return caches.delete(legacyKey)
+ }
+ )
+ )
+ .then(
+ () => {
+ resolve()
+ }
+ )
+ .catch(
+ (err) => {
+ reject(err);
+ }
+ );
+ } else {
+ resolve();
+ }
+ }
+ )
+ .catch(
+ () => {
+ reject();
+ }
+ );
+
+ }
+ );
+}
+
+function precacheUrl(url) {
+ if (!isBlacklisted(url)) {
+ caches.open(CACHE_VERSIONS.content)
+ .then((cache) => {
+ cache.match(url)
+ .then((response) => {
+ if (!response) {
+ return fetch(url)
+ } else {
+ // already in cache, nothing to do.
+ return null
+ }
+ })
+ .then((response) => {
+ if (response) {
+ return cache.put(url, response.clone());
+ } else {
+ return null;
+ }
+ });
+ })
+ }
+}
+
+
+
+self.addEventListener(
+ 'install', event => {
+ event.waitUntil(
+ Promise.all([
+ installServiceWorker(),
+ self.skipWaiting(),
+ ])
+ );
+ }
+);
+
+// The activate handler takes care of cleaning up old caches.
+self.addEventListener(
+ 'activate', event => {
+ event.waitUntil(
+ Promise.all(
+ [
+ cleanupLegacyCache(),
+ self.clients.claim(),
+ self.skipWaiting(),
+ ]
+ )
+ .catch(
+ (err) => {
+ event.skipWaiting();
+ }
+ )
+ );
+ }
+);
+
+self.addEventListener(
+ 'fetch', event => {
+
+ event.respondWith(
+ caches.open(CACHE_VERSIONS.content)
+ .then(
+ (cache) => {
+
+ return cache.match(event.request)
+ .then(
+ (response) => {
+
+ if (response) {
+
+ let headers = response.headers.entries();
+ let date = null;
+
+ for (let pair of headers) {
+ if (pair[0] === 'date') {
+ date = new Date(pair[1]);
+ }
+ }
+
+ if (date) {
+ let age = parseInt((new Date().getTime() - date.getTime()) / 1000);
+ let ttl = getTTL(event.request.url);
+
+ if (ttl && age > ttl) {
+
+ return new Promise(
+ (resolve) => {
+
+ return fetch(event.request.clone())
+ .then(
+ (updatedResponse) => {
+ if (updatedResponse) {
+ cache.put(event.request, updatedResponse.clone());
+ resolve(updatedResponse);
+ } else {
+ resolve(response)
+ }
+ }
+ )
+ .catch(
+ () => {
+ resolve(response);
+ }
+ );
+
+ }
+ )
+ .catch(
+ (err) => {
+ return response;
+ }
+ );
+ } else {
+ return response;
+ }
+
+ } else {
+ return response;
+ }
+
+ } else {
+ return null;
+ }
+ }
+ )
+ .then(
+ (response) => {
+ if (response) {
+ return response;
+ } else {
+ return fetch(event.request.clone())
+ .then(
+ (response) => {
+
+ if (response.status < 400) {
+ if (~SUPPORTED_METHODS.indexOf(event.request.method) && !isBlacklisted(event.request.url)) {
+ cache.put(event.request, response.clone());
+ }
+ return response;
+ } else {
+ return caches.open(CACHE_VERSIONS.notFound).then((cache) => {
+ return cache.match(NOT_FOUND_PAGE);
+ })
+ }
+ }
+ )
+ .then((response) => {
+ if (response) {
+ return response;
+ }
+ })
+ .catch(
+ () => {
+
+ return caches.open(CACHE_VERSIONS.offline)
+ .then(
+ (offlineCache) => {
+ return offlineCache.match(OFFLINE_PAGE)
+ }
+ )
+
+ }
+ );
+ }
+ }
+ )
+ .catch(
+ (error) => {
+ console.error(' Error in fetch handler:', error);
+ throw error;
+ }
+ );
+ }
+ )
+ );
+
+ }
+);
+
+
+self.addEventListener('message', (event) => {
+
+ if (
+ typeof event.data === 'object' &&
+ typeof event.data.action === 'string'
+ ) {
+ switch (event.data.action) {
+ case 'cache':
+ precacheUrl(event.data.url);
+ break;
+ default:
+ console.log('Unknown action: ' + event.data.action);
+ break;
+ }
+ }
+
+});