PageSourceSearch

https://yomureader.com/sw.js

js yomureader.com collected 2026-10-02 01:51:37 UTC 3,420 bytes, 117 lines download raw bytes

1// fallow-ignore-file unused-file
2const CACHE_NAME = 'yomu-docs-shell-v1';
3const SHELL = [
4  '/',
5  '/index.html',
6  '/manifest.webmanifest',
7  '/yomu-icon.svg',
8  '/favicon-16x16.png',
9  '/favicon-32x32.png',
10  '/apple-touch-icon.png',
11  '/yomu.css',
12  '/yomu.user.js',
13];
14const CACHEABLE_PATH_SUFFIXES = [
15  '/manifest.webmanifest',
16  '/yomu.css',
17  '/yomu.user.js',
18  '/yomu-icon.svg',
19  '/favicon-16x16.png',
20  '/favicon-32x32.png',
21  '/apple-touch-icon.png',
22  '/og-image.png',
23];
24const DOC_PATHS = [
25  '/',
26  '/index.html',
27  '/getting-started',
28  '/features',
29  '/tools/',
30  '/guides/',
31  '/support',
32  '/changelog',
33];
34
35self.addEventListener('install', event => {
36  event.waitUntil(caches.open(CACHE_NAME).then(cache => cache.addAll(SHELL)).catch(() => undefined));
37  self.skipWaiting();
38});
39
40self.addEventListener('activate', event => {
41  event.waitUntil(
42    caches.keys().then(keys => Promise.all(keys
43      .filter(key => key.startsWith('yomu-docs-shell-') && key !== CACHE_NAME)
44      .map(key => caches.delete(key)))),
45  );
46  self.clients.claim();
47});
48
49self.addEventListener('fetch', event => {
50  if (event.request.method !== 'GET' || !isSameOrigin(event.request)) return;
51  if (event.request.mode === 'navigate') {
52    event.respondWith(networkFirstNavigation(event.request));
53    return;
54  }
55  if (!shouldCacheRequest(event.request)) return;
56  event.respondWith(networkFirst(event.request));
57});
58
59async function networkFirstNavigation(request) {
60  try {
61    const response = await fetch(request, { cache: 'no-store' });
62    if (!response.ok) return await cachedNavigationFallback(request);
63    cacheNavigationResponse(request, response);
64    return response;
65  } catch {
66    return await cachedNavigationFallback(request);
67  }
68}
69
70async function cachedNavigationFallback(request) {
71  const cached = await caches.match(request, { ignoreSearch: true });
72  if (cached) return cached;
73  const url = new URL(request.url);
74  if (url.pathname !== '/' && url.pathname !== '/index.html') return Response.redirect('/', 302);
75  return await caches.match('/') || await caches.match('/index.html') || Response.error();
76}
77
78async function networkFirst(request) {
79  try {
80    const response = await fetch(request);
81    cacheNetworkResponse(request, response);
82    return response;
83  } catch {
84    return await caches.match(request, { ignoreSearch: true }) || Response.error();
85  }
86}
87
88function cacheNavigationResponse(request, response) {
89  if (!response.ok) return;
90  const url = new URL(request.url);
91  if (!isDocsNavigationPath(url.pathname)) return;
92  cacheNetworkResponse(request, response);
93  if (url.pathname === '/' || url.pathname === '/index.html') cacheNetworkResponse('/', response);
94}
95
96function cacheNetworkResponse(request, response) {
97  if (!response.ok) return;
98  const copy = response.clone();
99  caches.open(CACHE_NAME).then(cache => cache.put(request, copy)).catch(() => undefined);
100}
101
102function shouldCacheRequest(request) {
103  const pathname = new URL(request.url).pathname;
104  return CACHEABLE_PATH_SUFFIXES.some(suffix => pathname.endsWith(suffix));
105}
106
107function isDocsNavigationPath(pathname) {
108  return DOC_PATHS.some(path => {
109    if (path === '/') return pathname === '/';
110    const prefix = path.endsWith('/') ? path : `${path}/`;
111    return pathname === path || pathname.startsWith(prefix);
112  });
113}
114
115function isSameOrigin(request) {
116  return new URL(request.url).origin === self.location.origin;
117}

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.