PageSourceSearch

https://non14.net/service-worker.js

js non14.net collected 2026-10-02 11:56:08 UTC 6,207 bytes, 193 lines download raw bytes

1'use strict';
2
3const CACHE_VERSION = 'v1.0.1';
4const CACHE_NAME = 'non14-cache-' + CACHE_VERSION;
5const RUNTIME_CACHE = 'non14-runtime-' + CACHE_VERSION;
6
7const CACHE_URLS = [
8    '/',
9    '/offline.html',
10    '/assets/non/style/style.css',
11    '/assets/non/icons/android-icon-192x192.png',
12    '/assets/non/icons/favicon-96x96.png',
13    'https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.rtl.min.css',
14    'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css',
15    'https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;500;600;700;800;900&display=swap'
16];
17
18self.addEventListener('install', function (event) {
19    event.waitUntil(
20        caches.open(CACHE_NAME)
21            .then(function (cache) {
22                return cache.addAll(CACHE_URLS);
23            })
24            .then(function () {
25                return self.skipWaiting();
26            })
27            .catch(function (error) {
28                console.error('Cache install failed:', error);
29            })
30    );
31});
32
33self.addEventListener('activate', function (event) {
34    event.waitUntil(
35        caches.keys().then(function (cacheNames) {
36            return Promise.all(
37                cacheNames.map(function (cacheName) {
38                    if (cacheName !== CACHE_NAME && cacheName !== RUNTIME_CACHE) {
39                        return caches.delete(cacheName);
40                    }
41                })
42            );
43        }).then(function () {
44            return self.clients.claim();
45        })
46    );
47});
48
49self.addEventListener('fetch', function (event) {
50    if (event.request.method !== 'GET') {
51        return;
52    }
53
54    const url = new URL(event.request.url);
55
56    // Don't cache HTML pages or API calls - always fetch fresh
57    if (url.origin === location.origin && 
58        (event.request.mode === 'navigate' || 
59         url.pathname.startsWith('/api/') ||
60         url.pathname === '/' ||
61         url.pathname.match(/\/\d+$/))) {
62        return;
63    }
64
65    if (url.origin !== location.origin && !url.href.includes('cdn.')) {
66        return;
67    }
68
69    event.respondWith(
70        caches.match(event.request)
71            .then(function (response) {
72                if (response) {
73                    return response;
74                }
75
76                return fetch(event.request)
77                    .then(function (response) {
78                        if (!response || response.status !== 200 || response.type === 'error') {
79                            return response;
80                        }
81
82                        const shouldCache = 
83                            url.pathname.endsWith('.css') ||
84                            url.pathname.endsWith('.js') ||
85                            url.pathname.endsWith('.png') ||
86                            url.pathname.endsWith('.jpg') ||
87                            url.pathname.endsWith('.jpeg') ||
88                            url.pathname.endsWith('.svg') ||
89                            url.pathname.endsWith('.woff') ||
90                            url.pathname.endsWith('.woff2') ||
91                            url.href.includes('cdn.');
92
93                        if (shouldCache) {
94                            const responseToCache = response.clone();
95                            caches.open(RUNTIME_CACHE).then(function (cache) {
96                                cache.put(event.request, responseToCache);
97                            });
98                        }
99
100                        return response;
101                    })
102                    .catch(function () {
103                        if (event.request.mode === 'navigate') {
104                            return caches.match('/offline.html');
105                        }
106                        return new Response('Network error', {
107                            status: 408,
108                            headers: { 'Content-Type': 'text/plain' }
109                        });
110                    });
111            })
112    );
113});
114
115self.addEventListener('push', function (event) {
116    if (!event.data) {
117        return;
118    }
119
120    let payload;
121
122    try {
123        payload = event.data.json();
124    } catch (error) {
125        payload = {
126            title: 'New notification',
127            body: event.data.text()
128        };
129    }
130
131    const title = payload.title || 'New notification';
132    const options = {
133        body: payload.body || '',
134        icon: payload.icon || '/assets/non/icons/android-icon-192x192.png',
135        badge: payload.badge || '/assets/non/icons/favicon-96x96.png',
136        image: payload.image,
137        vibrate: payload.vibrate || [200, 100, 200],
138        requireInteraction: Boolean(payload.requireInteraction),
139        data: payload.data || {},
140        actions: payload.actions || []
141    };
142
143    if (payload.tag) {
144        options.tag = payload.tag;
145        options.renotify = Boolean(payload.renotify);
146    }
147
148    event.waitUntil(self.registration.showNotification(title, options));
149});
150
151self.addEventListener('notificationclick', function (event) {
152    event.notification.close();
153
154    const notificationData = event.notification.data || {};
155    const targetUrl = notificationData.url || notificationData.link || notificationData.navigateTo || '/';
156
157    event.waitUntil(
158        self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function (clientList) {
159            for (let i = 0; i < clientList.length; i += 1) {
160                const client = clientList[i];
161                if (client.url === targetUrl && 'focus' in client) {
162                    return client.focus();
163                }
164            }
165
166            if (self.clients.openWindow) {
167                return self.clients.openWindow(targetUrl);
168            }
169
170            return undefined;
171        })
172    );
173});
174
175self.addEventListener('notificationclose', function (event) {
176    if (!event.notification || !event.notification.data) {
177        return;
178    }
179
180    const closeEndpoint = event.notification.data.onCloseUrl;
181    if (!closeEndpoint) {
182        return;
183    }
184
185    event.waitUntil(
186        fetch(closeEndpoint, {
187            method: 'POST',
188            credentials: 'same-origin'
189        }).catch(function () {
190            return undefined;
191        })
192    );
193});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.