-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsw.js
More file actions
107 lines (95 loc) · 3.82 KB
/
Copy pathsw.js
File metadata and controls
107 lines (95 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Paniniyam Service Worker — offline cache
// Bump CACHE_VERSION whenever static assets change significantly
const CACHE_VERSION = 'v2';
const CACHE_NAME = `paniniyam-${CACHE_VERSION}`;
const CDN_DATA = 'https://cdn.jsdelivr.net/gh/asklabls/paniniyam-data@master';
const CDN_FORMS = 'https://cdn.jsdelivr.net/gh/asklabls/paniniyam@main/forms';
// ── Precached on install ───────────────────────────────────────────────────────
// Small, always-needed files. Core data files that power the sutra reader.
const PRECACHE = [
'/',
'/css/style.css',
'/js/app.js',
'/js/sanscript.js',
'/js/shabda.js',
'/img/favicon.ico',
'/img/apple-touch-icon.png',
'/img/kofi.png',
'/img/icon-192.png',
'/img/icon-512.png',
'/privacy_policy.html',
'/terms.html',
'/copyright.html',
'/contact.html',
// Core data — needed for navigation + search to work offline
`${CDN_DATA}/sutraani/data.txt`,
`${CDN_DATA}/dhatu/data.txt`,
`${CDN_DATA}/ganapath/data.txt`,
`${CDN_DATA}/shivasutra/data.txt`,
`${CDN_DATA}/unaadi/data.txt`,
`${CDN_DATA}/fit/data.txt`,
`${CDN_DATA}/linganushasanam/data.txt`,
`${CDN_DATA}/shiksha/data.txt`,
`${CDN_DATA}/sutraani/vartika.txt`,
// Forms
`${CDN_FORMS}/pratyaya.txt`,
`${CDN_FORMS}/concepts_index.json`,
];
// ── Install: precache static shell + core data ─────────────────────────────────
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(PRECACHE))
.then(() => self.skipWaiting())
);
});
// ── Activate: remove old caches ────────────────────────────────────────────────
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys()
.then(keys => Promise.all(
keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k))
))
.then(() => self.clients.claim())
);
});
// ── Fetch: cache-first for hits, network-then-cache for misses ─────────────────
self.addEventListener('fetch', event => {
const req = event.request;
const url = new URL(req.url);
// Only cache GET requests
if (req.method !== 'GET') return;
// Skip: R2 private data (Pravachanam, Siddhi etc.) — too personal/large
if (url.hostname.includes('r2.dev') || url.hostname.includes('pub-19119053')) return;
// Skip: audio files — too large (~6 MB per pada)
if (url.pathname.includes('/audio/')) return;
// Skip: per-dhatu form files — 2229 files, let browser cache handle these
if (url.pathname.match(/\/forms\/dhatu\/.+\.json$/)) return;
// Skip: SVG diagrams — many files, too large to pre-warm
if (url.pathname.includes('/visuals/')) return;
event.respondWith(
caches.match(req).then(cached => {
// Cache hit → return immediately, revalidate in background
if (cached) {
// Background revalidate for CDN data (keeps cache fresh)
if (url.hostname.includes('jsdelivr.net') || url.hostname.includes('cdn.')) {
fetch(req).then(res => {
if (res.ok) caches.open(CACHE_NAME).then(c => c.put(req, res));
}).catch(() => {});
}
return cached;
}
// Cache miss → fetch, cache successful responses, return
return fetch(req).then(res => {
if (res.ok) {
const clone = res.clone();
caches.open(CACHE_NAME).then(c => c.put(req, clone));
}
return res;
}).catch(() => {
// Network totally unavailable and no cache — return offline page for navigation
if (req.mode === 'navigate') return caches.match('/');
});
})
);
});