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
path: root/assets
diff options
context:
space:
mode:
authorzilch40 <wlh233@live.com>2020-11-16 15:31:39 +0300
committerzilch40 <wlh233@live.com>2020-11-16 15:31:39 +0300
commit871470c4cd13a02e947680864574a84eae246cf0 (patch)
tree8414d26b020681fa0b05384c28bccc08d69e4e4b /assets
parent88fb497815279a64bbfe38e7cdd1676a2b683b77 (diff)
add PWA support && tweak some pages
Diffstat (limited to 'assets')
-rw-r--r--assets/css/common.scss10
-rw-r--r--assets/css/hulga-dark.scss11
-rw-r--r--assets/js/pwa.js39
-rw-r--r--assets/sw.js388
4 files changed, 440 insertions, 8 deletions
diff --git a/assets/css/common.scss b/assets/css/common.scss
index 05e63b9..82ba77b 100644
--- a/assets/css/common.scss
+++ b/assets/css/common.scss
@@ -32,7 +32,9 @@
border-color: $primary;
color: $white;
}
-
+a {
+ color: $primary;
+}
/* fixed footer */
body {
display: flex;
@@ -49,9 +51,6 @@ body {
position: relative;
z-index: 1;
}
-a {
- color: $primary;
-}
/* link */
// u
@@ -101,6 +100,9 @@ a {
.post-meta {
opacity: 0.9;
}
+.counter-tag {
+ border-left: 1px solid $white;
+}
/* posts */
.post-box {
diff --git a/assets/css/hulga-dark.scss b/assets/css/hulga-dark.scss
index 2594cfb..9263319 100644
--- a/assets/css/hulga-dark.scss
+++ b/assets/css/hulga-dark.scss
@@ -8,7 +8,7 @@
// $archblue: #1793d0;
{{ if .Site.Params.primaryColor }}
-$primary: {{ .Site.Params.primaryColor }};
+$primary: lighten({{ .Site.Params.primaryColor }}, 5);
{{end}}
// Import only what you need from Bulma
@@ -32,9 +32,12 @@ $pagination-border-color: $border;
@import "../sass/dark/overrides";
// dark override
-.sidebar {
- height: 100%;
-}
.footer {
background: #282f2f;
}
+.counter-tag {
+ border-left: 1px solid #282f2f;
+}
+.tag:not(body) {
+ background-color: rgba($black-bis, 0.2);
+} \ No newline at end of file
diff --git a/assets/js/pwa.js b/assets/js/pwa.js
new file mode 100644
index 0000000..74b3c68
--- /dev/null
+++ b/assets/js/pwa.js
@@ -0,0 +1,39 @@
+{{ $swfile := resources.Get "/sw.js" }}
+{{ $sw := $swfile | resources.Minify }}
+if('serviceWorker' in navigator) {
+ const PREFETCH = true;
+ const PREFETCH_LINK_RELS = ['index','next', 'prev', 'prefetch'];
+ function prefetchCache() {
+ if(navigator.serviceWorker.controller) {
+ let links = document.querySelectorAll(
+ PREFETCH_LINK_RELS.map((rel) => {
+ return 'link[rel='+rel+']';
+ }).join(',')
+ );
+ if(links.length > 0) {
+ Array.from(links)
+ .map((link) => {
+ let href = link.getAttribute('href');
+ navigator.serviceWorker.controller.postMessage({
+ action : 'cache',
+ url : href,
+ });
+ });
+ }
+ }
+ }
+
+ navigator.serviceWorker
+ .register('{{ $sw.Permalink | relURL }}', { scope: '/' })
+ .then(() => {
+ console.log('Service Worker Registered');
+ });
+
+ navigator.serviceWorker
+ .ready
+ .then(() => {
+ if(PREFETCH) {
+ prefetchCache();
+ }
+ });
+} \ No newline at end of file
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;
+ }
+ }
+
+});