diff options
| -rw-r--r-- | index.html | 32 | ||||
| -rw-r--r-- | serviceWorker.js | 52 |
2 files changed, 80 insertions, 4 deletions
@@ -63,7 +63,9 @@ </noscript> <div id='warnings'></div> - <div id='content'></div> + <div id='content'> + rendering content... + </div> <div> tempo is licensed under creative-commons. <br> @@ -79,6 +81,17 @@ </a> </div> <script> + if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker.register('/serviceWorker.js') + .then(reg => console.log('Service Worker registered')) + .catch(err => console.log('SW registration failed', err)) + }) + } else { + console.log('[warn] no service worker support') + } + </script> + <script> function escapeHTML(str) { if (!str) return '' const a = [] @@ -334,7 +347,7 @@ const defPattern = /^def\s+(\S+)/gm while ((match = defPattern.exec(text)) !== null) { - console.log('defined:', match[1]) + // console.log('defined:', match[1]) definedSymbols.add(match[1].replace(/^\\/g, '').replace(/\\$/g, '')) } @@ -371,15 +384,26 @@ parser.tokenize() const html = parser.render() + // store first 4kb of website in local storage document.getElementById('content').innerHTML = html - + try { + localStorage.setItem('rendered', html.substring(0, 32768)) + } catch (err) { + console.log('[warn] localStorage caching failed. subsequent loads will not benefit from first-paint rendering.') + } } catch (err) { console.error("failed to load tempo file:", err) document.getElementById('content').innerHTML = "<p>error loading content.</p>" } } - loadMarkdown().then(e => document.querySelector('script').remove()) + const title = document.title + const previousRender = localStorage.getItem('rendered') + if (previousRender) { + document.title = 'contents are stale...' + content.innerHTMl = previousRender + } + loadMarkdown().then(e => document.title = title) </script> <script> diff --git a/serviceWorker.js b/serviceWorker.js new file mode 100644 index 0000000..ba9ca7a --- /dev/null +++ b/serviceWorker.js @@ -0,0 +1,52 @@ +const CACHE_NAME = 'offline-cache-v1' +const ASSETS = [ + '/', + '/index.html', + '/styles.css', + '/styles3.css', + '/tempo.md', + '/bell.png', + '/bell.svg', + '/by-sa.png', + '/cc-by-sa-legalcode.txt', + '/symbols.txt' +] + +self.addEventListener('install', e => { + console.log('installing sw') + e.waitUntil(caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS))) + self.skipWaiting() +}) + +self.addEventListener('activate', e => { + console.log('sw activated') + e.waitUntil(self.clients.claim()) +}) + +self.addEventListener('fetch', e => { + const url = new URL(e.request.url) + const isTarget = ASSETS.includes(url.pathname) || url.pathname.startsWith('/fonts/') + + if (!isTarget) return + + e.respondWith( + caches.open(CACHE_NAME).then(async cache => { + const cachedResponse = await cache.match(e.request) + + if (cachedResponse) console.log(`cache ${url.pathname}`) + else console.log(`fetch ${url.pathname}`) + + const networkFetch = fetch(e.request).then(networkResponse => { + if (networkResponse.ok) { + console.log(`updating ${url.pathname}`) + cache.put(e.request, networkResponse.clone()) + } + return networkResponse + }).catch(err => { + console.error(`failed ${url.pathname}:`, err) + }) + + return cachedResponse || networkFetch + }) + ) +})
\ No newline at end of file |
