sinzmise-cetastories 1.7.0-1719575303618 → 1.7.0-1719903297878

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. package/404/index.html +1 -1
  2. package/404.html +1 -1
  3. package/about/index.html +1 -1
  4. package/album/index.html +1 -1
  5. package/archives/2021/12/index.html +1 -1
  6. package/archives/2021/index.html +1 -1
  7. package/archives/2022/12/index.html +1 -1
  8. package/archives/2022/index.html +1 -1
  9. package/archives/2023/01/index.html +1 -1
  10. package/archives/2023/02/index.html +1 -1
  11. package/archives/2023/03/index.html +1 -1
  12. package/archives/2023/04/index.html +1 -1
  13. package/archives/2023/07/index.html +1 -1
  14. package/archives/2023/08/index.html +1 -1
  15. package/archives/2023/09/index.html +1 -1
  16. package/archives/2023/10/index.html +1 -1
  17. package/archives/2023/11/index.html +1 -1
  18. package/archives/2023/12/index.html +1 -1
  19. package/archives/2023/index.html +1 -1
  20. package/archives/2023/page/2/index.html +1 -1
  21. package/archives/2023/page/3/index.html +1 -1
  22. package/archives/2024/01/index.html +1 -1
  23. package/archives/2024/02/index.html +1 -1
  24. package/archives/2024/03/index.html +1 -1
  25. package/archives/2024/04/index.html +1 -1
  26. package/archives/2024/05/index.html +1 -1
  27. package/archives/2024/06/index.html +1 -0
  28. package/archives/2024/index.html +1 -1
  29. package/archives/2024/page/2/index.html +1 -1
  30. package/archives/index.html +1 -1
  31. package/archives/page/2/index.html +1 -1
  32. package/archives/page/3/index.html +1 -1
  33. package/archives/page/4/index.html +1 -1
  34. package/article.json +1 -1
  35. package/atom.xml +51 -52
  36. package/baidu_verify_codeva-NA6uDlCuZg.html +1 -1
  37. package/baidusitemap.xml +74 -70
  38. package/bangumis/index.html +1 -1
  39. package/bbs/index.html +1 -1
  40. package/categories/index.html +1 -1
  41. package/categories//344/270/252/344/272/272/345/260/217/350/256/260/index.html +1 -1
  42. package/categories//344/270/252/344/272/272/345/260/217/350/256/260/page/2/index.html +1 -1
  43. package/categories//346/255/214/346/233/262/346/224/266/351/233/206/index.html +1 -1
  44. package/categories//346/270/270/346/210/217/347/233/270/345/205/263/index.html +1 -1
  45. package/categories//347/253/231/347/202/271/346/212/230/350/205/276/index.html +1 -1
  46. package/categories//347/253/231/347/202/271/346/212/230/350/205/276/page/2/index.html +1 -1
  47. package/categories//351/241/271/347/233/256/346/212/230/350/205/276/index.html +1 -1
  48. package/charts/index.html +1 -1
  49. package/comments/index.html +1 -1
  50. package/en/categories/index.html +1 -0
  51. package/en/tags/index.html +1 -0
  52. package/essay/index.html +1 -1
  53. package/fcircle/index.html +1 -1
  54. package/google8073542809160a67.html +1 -1
  55. package/index.html +1 -1
  56. package/js/randompost.js +1 -1
  57. package/link/index.html +1 -1
  58. package/music/index.html +1 -1
  59. package/package.json +1 -1
  60. package/page/2/index.html +1 -1
  61. package/page/3/index.html +1 -1
  62. package/page/4/index.html +1 -1
  63. package/posts/10021/index.html +1 -1
  64. package/posts/10045/index.html +1 -1
  65. package/posts/10996/index.html +1 -1
  66. package/posts/12779/index.html +1 -1
  67. package/posts/13624/index.html +1 -1
  68. package/posts/15748/index.html +1 -1
  69. package/posts/15842/index.html +1 -1
  70. package/posts/16107/index.html +1 -1
  71. package/posts/18063/index.html +1 -1
  72. package/posts/20412/index.html +1 -1
  73. package/posts/21375/index.html +1 -1
  74. package/posts/22945/index.html +1 -1
  75. package/posts/23021/index.html +1 -1
  76. package/posts/27531/index.html +1 -1
  77. package/posts/27762/index.html +1 -1
  78. package/posts/28536/index.html +1 -1
  79. package/posts/28733/index.html +1 -1
  80. package/posts/29196/index.html +1 -1
  81. package/posts/38917/index.html +1 -1
  82. package/posts/38964/index.html +1 -1
  83. package/posts/42487/index.html +1 -1
  84. package/posts/42580/index.html +1 -1
  85. package/posts/45875/index.html +1 -1
  86. package/posts/48762/index.html +1 -1
  87. package/posts/50710/index.html +1 -1
  88. package/posts/52677/index.html +1 -1
  89. package/posts/53662/index.html +1 -1
  90. package/posts/54386/index.html +1 -1
  91. package/posts/54481/index.html +1 -1
  92. package/posts/54787/index.html +1 -1
  93. package/posts/56467/index.html +1 -1
  94. package/posts/57692/index.html +1 -1
  95. package/posts/58203/index.html +1 -1
  96. package/posts/61417/index.html +1 -1
  97. package/posts/646/index.html +1 -1
  98. package/seas/index.html +1 -1
  99. package/sitemap.xml +160 -133
  100. package/sw.js +138 -580
  101. package/tags/Flash/347/233/270/345/205/263/index.html +1 -1
  102. package/tags/Steam/346/270/270/346/210/217/index.html +1 -1
  103. package/tags/Windows/350/275/257/344/273/266/index.html +1 -1
  104. package/tags/index.html +1 -1
  105. package/tags//344/270/252/344/272/272/345/260/217/350/256/260/index.html +1 -1
  106. package/tags//344/270/252/344/272/272/345/260/217/350/256/260/page/2/index.html +1 -1
  107. package/tags//345/205/266/345/256/203/346/270/270/346/210/217/index.html +1 -1
  108. package/tags//346/202/254/346/265/256/345/256/240/347/211/251-/347/234/213/346/235/277/345/250/230/index.html +1 -1
  109. package/tags//346/255/214/346/233/262/346/224/266/351/233/206/index.html +1 -1
  110. package/tags//346/270/270/346/210/217/347/233/270/345/205/263/index.html +1 -1
  111. package/tags//347/253/231/347/202/271/345/272/225/351/203/250/351/255/224/346/224/271/index.html +1 -1
  112. package/tags//347/253/231/347/202/271/346/212/230/350/205/276/index.html +1 -1
  113. package/tags//347/253/231/347/202/271/346/212/230/350/205/276/page/2/index.html +1 -1
  114. package/tags//350/207/252/345/273/272/351/203/250/347/275/262/index.html +1 -1
  115. package/tags//351/241/265/351/235/242/351/255/224/346/224/271/index.html +1 -1
  116. package/tags//351/241/271/347/233/256/346/212/230/350/205/276/index.html +1 -1
  117. package/update/index.html +1 -1
  118. package/cacheList.json +0 -1
  119. package/sw-dom.js +0 -73
  120. package/update.json +0 -1
package/sw.js CHANGED
@@ -1,586 +1,144 @@
1
- // noinspection JSIgnoredPromiseFromCall
2
-
3
- (() => {
4
- /** 缓存库名称 */
5
- const CACHE_NAME = 'StoriHouseCache'
6
- /** 控制信息存储地址(必须以`/`结尾) */
7
- const CTRL_PATH = 'https://id.v3/'
8
-
9
- const ejectDomain = 'blog.sinzmise.top'
10
- const ejectMirror = ['https://registry.npmmirror.com/sinzmise-cetastories/latest']
11
-
12
-
13
- /**
14
- * 读取本地版本号
15
- * @return {Promise<BrowserVersion|undefined>}
16
- */
17
- const readVersion = () => caches.match(CTRL_PATH).then(response => response?.json())
18
- /**
19
- * 写入版本号
20
- * @param version {BrowserVersion}
21
- * @return {Promise<void>}
22
- */
23
- const writeVersion = version => caches.open(CACHE_NAME)
24
- .then(cache => cache.put(CTRL_PATH, new Response(JSON.stringify(version))))
25
-
26
- self.addEventListener('install', () => {
27
- self.skipWaiting()
28
- const escape = 0
29
- if (escape) {
30
- readVersion().then(async oldVersion => {
31
- // noinspection JSIncompatibleTypesComparison
32
- if (oldVersion && oldVersion.escape !== escape) {
33
- const list = await caches.open(CACHE_NAME)
34
- .then(cache => cache.keys())
35
- .then(keys => keys?.map(it => it.url))
36
- await caches.delete(CACHE_NAME)
37
- const info = await updateJson()
38
- info.type = 'escape'
39
- info.list = list
40
- // noinspection JSUnresolvedReference
41
- const clientList = await clients.matchAll()
42
- clientList.forEach(client => client.postMessage(info))
43
- }
44
- })
45
- }
46
- })
47
-
48
- // sw 激活后立即对所有页面生效,而非等待刷新
49
- // noinspection JSUnresolvedReference
50
- self.addEventListener('activate', event => event.waitUntil(clients.claim()))
51
-
52
- /**
53
- * 基础 fetch
54
- * @param request {Request|string}
55
- * @param banCache {boolean} 是否禁用缓存
56
- * @param cors {boolean} 是否启用 cors
57
- * @param optional {RequestInit?} 额外的配置项
58
- * @return {Promise<Response>}
59
- */
60
- const baseFetcher = (request, banCache, cors, optional) => {
61
- if (!optional) optional = {}
62
- optional.cache = banCache ? 'no-store' : 'default'
63
- if (cors) {
64
- optional.mode = 'cors'
65
- optional.credentials = 'same-origin'
66
- }
67
- return fetch(request, optional)
68
- }
69
-
70
- /**
71
- * 添加 cors 配置请求指定资源
72
- * @param request {Request}
73
- * @param optional {RequestInit?} 额外的配置项
74
- * @return {Promise<Response>}
75
- */
76
- const fetchWithCache = (request, optional) =>
77
- baseFetcher(request, false, isCors(request), optional)
78
-
79
- // noinspection JSUnusedLocalSymbols
80
- /**
81
- * 添加 cors 配置请求指定资源
82
- * @param request {Request}
83
- * @param banCache {boolean} 是否禁用 HTTP 缓存
84
- * @param optional {RequestInit?} 额外的配置项
85
- * @return {Promise<Response>}
86
- */
87
- const fetchWithCors = (request, banCache, optional) =>
88
- baseFetcher(request, banCache, true, optional)
89
-
90
- /**
91
- * 判断指定 url 击中了哪一种缓存,都没有击中则返回 null
92
- * @param url {URL}
93
- */
94
- const findCache = url => {
95
- if (url.hostname === 'localhost') return
96
- for (let key in cacheRules) {
97
- const value = cacheRules[key]
98
- if (value.match(url)) return value
99
- }
100
- }
101
-
102
- // noinspection JSFileReferences
103
- let skipRequest = request => request.url.startsWith('https://i0.hdslb.com')
104
- let cacheRules = {
105
- simple: {
106
- clean: true,
107
- search: false,
108
- match: url => {
109
- const allowedHost = ejectDomain;
110
- const allowedPaths = ["/404.html", "/css/index.css"];
111
- return url.host === allowedHost && allowedPaths.includes(url.pathname);
112
- }}
113
- ,
114
- cdn: {
115
- clean: true,
116
- match: url =>
117
- [
118
- "unpkg.com",
119
- "cdn.cbd.int",
120
- "lf26-cdn-tos.bytecdntp.com",
121
- "lf6-cdn-tos.bytecdntp.com",
122
- "lf3-cdn-tos.bytecdntp.com",
123
- "lf9-cdn-tos.bytecdntp.com",
124
- "npm.onmicrosoft.cn",
125
- "cdn.staticfile.org",
126
- "npm.elemecdn.com",
127
- ].includes(url.host) && url.pathname.match(/\.(js|css|woff2|woff|ttf|cur)$/)}
128
- }
1
+ const workboxVersion = '5.1.3';
129
2
 
130
- let getSpareUrls = srcUrl => {
131
- if (srcUrl.startsWith("https://npm.elemecdn.com")) {
132
- return {
133
- timeout: 3000,
134
- list: [srcUrl, `https://cdn.cbd.int/${new URL(srcUrl).pathname}`],
135
- };
136
- }
137
- }
138
- let selfdb = () => {
139
- self.db = { //全局定义db,只要read和write,看不懂可以略过
140
- read: (key, config) => {
141
- if (!config) { config = { type: "text" } }
142
- return new Promise((resolve, reject) => {
143
- caches.open(CACHE_NAME).then(cache => {
144
- cache.match(new Request(`https://LOCALCACHE/${encodeURIComponent(key)}`)).then(function (res) {
145
- if (!res) resolve(null)
146
- res.text().then(text => resolve(text))
147
- }).catch(() => {
148
- resolve(null)
149
- })
150
- })
3
+ importScripts(`https://storage.googleapis.com/workbox-cdn/releases/${workboxVersion}/workbox-sw.js`);
4
+
5
+ workbox.core.setCacheNameDetails({
6
+ prefix: "StoriHouseCache"
7
+ });
8
+
9
+ workbox.core.skipWaiting();
10
+
11
+ workbox.core.clientsClaim();
12
+
13
+ // 注册成功后要立即缓存的资源列表
14
+ // 具体缓存列表在gulpfile.js中配置,见下文
15
+ workbox.precaching.precacheAndRoute([{"revision":"1b60856b9e22f95fefb2bc26deb5dfca","url":"./404.html"},{"revision":"b1ae1564c510dfc2702ce99145e7dbc1","url":"./index.html"},{"revision":"793e6861668298d001d2eca8ab9a5c97","url":"./js/main.js"},{"revision":"c8df2ce205bc903df4b652a22efbca8e","url":"./css/index.css"}],{
16
+ directoryIndex: null
17
+ });
18
+
19
+ // 清空过期缓存
20
+ workbox.precaching.cleanupOutdatedCaches();
21
+
22
+ // 图片资源(可选,不需要就注释掉)
23
+ workbox.routing.registerRoute(
24
+ /\.(?:png|jpg|jpeg|gif|bmp|webp|svg|ico)$/,
25
+ new workbox.strategies.CacheFirst({
26
+ cacheName: "images",
27
+ plugins: [
28
+ new workbox.expiration.ExpirationPlugin({
29
+ maxEntries: 1000,
30
+ maxAgeSeconds: 60 * 60 * 24 * 30
31
+ }),
32
+ new workbox.cacheableResponse.CacheableResponsePlugin({
33
+ statuses: [0, 200]
34
+ })
35
+ ]
36
+ })
37
+ );
38
+
39
+ // 字体文件(可选,不需要就注释掉)
40
+ workbox.routing.registerRoute(
41
+ /\.(?:eot|ttf|woff|woff2)$/,
42
+ new workbox.strategies.CacheFirst({
43
+ cacheName: "fonts",
44
+ plugins: [
45
+ new workbox.expiration.ExpirationPlugin({
46
+ maxEntries: 1000,
47
+ maxAgeSeconds: 60 * 60 * 24 * 30
48
+ }),
49
+ new workbox.cacheableResponse.CacheableResponsePlugin({
50
+ statuses: [0, 200]
51
+ })
52
+ ]
53
+ })
54
+ );
55
+
56
+ // 谷歌字体(可选,不需要就注释掉)
57
+ workbox.routing.registerRoute(
58
+ /^https:\/\/fonts\.googleapis\.com/,
59
+ new workbox.strategies.StaleWhileRevalidate({
60
+ cacheName: "google-fonts-stylesheets"
61
+ })
62
+ );
63
+ workbox.routing.registerRoute(
64
+ /^https:\/\/fonts\.gstatic\.com/,
65
+ new workbox.strategies.CacheFirst({
66
+ cacheName: 'google-fonts-webfonts',
67
+ plugins: [
68
+ new workbox.expiration.ExpirationPlugin({
69
+ maxEntries: 1000,
70
+ maxAgeSeconds: 60 * 60 * 24 * 30
71
+ }),
72
+ new workbox.cacheableResponse.CacheableResponsePlugin({
73
+ statuses: [0, 200]
151
74
  })
152
- },
153
- write: (key, value) => {
154
- return new Promise((resolve, reject) => {
155
- caches.open(CACHE_NAME).then(function (cache) {
156
- cache.put(new Request(`https://LOCALCACHE/${encodeURIComponent(key)}`), new Response(value));
157
- resolve()
158
- }).catch(() => {
159
- reject()
160
- })
75
+ ]
76
+ })
77
+ );
78
+
79
+ /* jsdelivr的CDN资源(包含代理,可选,不需要就注释掉) */
80
+ workbox.routing.registerRoute(
81
+ /^https:\/\/cdn\.jsdelivr\.net/,
82
+ new workbox.strategies.CacheFirst({
83
+ cacheName: "jsd-libs",
84
+ plugins: [
85
+ new workbox.expiration.ExpirationPlugin({
86
+ maxEntries: 1000,
87
+ maxAgeSeconds: 60 * 60 * 24 * 30
88
+ }),
89
+ new workbox.cacheableResponse.CacheableResponsePlugin({
90
+ statuses: [0, 200]
161
91
  })
162
- }
163
- }
164
- }
165
- let lfetch = async (urls, url) => {
166
- let controller = new AbortController();
167
- const PauseProgress = async (res) => {
168
- return new Response(await (res).arrayBuffer(), { status: res.status, headers: res.headers });
169
- };
170
- if (!Promise.any) {
171
- Promise.any = function (promises) {
172
- return new Promise((resolve, reject) => {
173
- promises = Array.isArray(promises) ? promises : []
174
- let len = promises.length
175
- let errs = []
176
- if (len === 0) return reject(new AggregateError('All promises were rejected'))
177
- promises.forEach((promise) => {
178
- promise.then(value => {
179
- resolve(value)
180
- }, err => {
181
- len--
182
- errs.push(err)
183
- if (len === 0) {
184
- reject(new AggregateError(errs))
185
- }
186
- })
187
- })
92
+ ]
93
+ })
94
+ );
95
+ workbox.routing.registerRoute(
96
+ /^https:\/\/jsd\.onmicrosoft\.cn/,
97
+ new workbox.strategies.CacheFirst({
98
+ cacheName: "jsd-libs-onmicrosoft",
99
+ plugins: [
100
+ new workbox.expiration.ExpirationPlugin({
101
+ maxEntries: 1000,
102
+ maxAgeSeconds: 60 * 60 * 24 * 30
103
+ }),
104
+ new workbox.cacheableResponse.CacheableResponsePlugin({
105
+ statuses: [0, 200]
188
106
  })
189
- }
190
- }
191
- return Promise.any(urls.map(urls => {
192
- return new Promise((resolve, reject) => {
193
- fetch(urls, {
194
- signal: controller.signal
107
+ ]
108
+ })
109
+ );
110
+ workbox.routing.registerRoute(
111
+ /^https:\/\/jsd\.cdn\.storisinz\.site/,
112
+ new workbox.strategies.CacheFirst({
113
+ cacheName: "jsd-libs",
114
+ plugins: [
115
+ new workbox.expiration.ExpirationPlugin({
116
+ maxEntries: 1000,
117
+ maxAgeSeconds: 60 * 60 * 24 * 30
118
+ }),
119
+ new workbox.cacheableResponse.CacheableResponsePlugin({
120
+ statuses: [0, 200]
121
+ })
122
+ ]
123
+ })
124
+ );
125
+ /* jsdelivr的CDN资源 */
126
+
127
+
128
+ workbox.routing.registerRoute(
129
+ /^https:\/\/npm\.onmicrosoft\.cn/,
130
+ new workbox.strategies.CacheFirst({
131
+ cacheName: "npm-libs-onmicrosoft",
132
+ plugins: [
133
+ new workbox.expiration.ExpirationPlugin({
134
+ maxEntries: 1000,
135
+ maxAgeSeconds: 60 * 60 * 24 * 30
136
+ }),
137
+ new workbox.cacheableResponse.CacheableResponsePlugin({
138
+ statuses: [0, 200]
195
139
  })
196
- .then(PauseProgress)
197
- .then(res => {
198
- if (res.status == 200) {
199
- controller.abort();
200
- resolve(res)
201
- } else {
202
- reject(res)
203
- }
204
- })
205
- })
206
- }))
207
- }
208
- let fullpath = (path) => {
209
- path = path.split('?')[0].split('#')[0]
210
- if (path.match(/\/$/)) {
211
- path += 'index'
212
- }
213
- if (!path.match(/\.[a-zA-Z]+$/)) {
214
- path += '.html'
215
- }
216
- return path
217
- }
218
- let generate_blog_urls = () => {
219
- const npmmirror = [
220
- // `https://unpkg.zhimg.com/${packagename}@${blogversion}`,
221
- // `https://npm.elemecdn.com/${packagename}@${blogversion}`,
222
- // `https://cdn1.tianli0.top/npm/${packagename}@${blogversion}`,
223
- // `https://cdn.afdelivr.top/npm/${packagename}@${blogversion}`,
224
- `https://registry.npmmirror.com/${packagename}/${blogversion}/files`
225
- ]
226
- for (var i in npmmirror) {
227
- npmmirror[i] += path
228
- }
229
- return npmmirror
230
- }
231
- let get_newest_version = async (ejectMirror) => {
232
- return lfetch(ejectMirror, ejectMirror[0])
233
- .then(res => res.json())
234
- .then(res.version)
235
- }
236
- let set_newest_version = async (ejectMirror) => {
237
- return lfetch(ejectMirror, ejectMirror[0])
238
- .then(res => res.json()) //JSON Parse
239
- .then(async res => {
240
- await db.write('blog_version', res.version) //写入
241
- return;
242
- })
243
- }
244
- let set_newest_time = () => {
245
- setInterval(async() => {
246
- await set_newest_version(mirror) //定时更新,一分钟一次
247
- }, 60*1000);
140
+ ]
141
+ })
142
+ );
248
143
 
249
- setTimeout(async() => {
250
- await set_newest_version(mirror)//打开五秒后更新,避免堵塞
251
- },5000)
252
- function getFileType(fileName) {
253
- suffix=fileName.split('.')[fileName.split('.').length-1]
254
- if(suffix=="html"||suffix=="htm") {
255
- return 'text/html';
256
- }
257
- if(suffix=="js") {
258
- return 'text/javascript';
259
- }
260
- if(suffix=="css") {
261
- return 'text/css';
262
- }
263
- if(suffix=="jpg"||suffix=="jpeg") {
264
- return 'image/jpeg';
265
- }
266
- if(suffix=="ico") {
267
- return 'image/x-icon';
268
- }
269
- if(suffix=="png") {
270
- return 'image/png';
271
- }
272
- return 'text/plain';
273
- }
274
- }
275
- let handle = async(req)=> {
276
- const urlStr = req.url
277
- const urlObj = new URL(urlStr);
278
- const urlPath = urlObj.pathname;
279
- const domain = urlObj.hostname;
280
- //从这里开始
281
- lxs=[]
282
- if(domain === "blog.sinzmise.top"){//这里写你需要拦截的域名
283
- var l=lfetch(generate_blog_urls('sinzmise-cetastories',await db.read('blog_version') || 'latest',fullpath(urlPath)))
284
- return l
285
- .then(res=>res.arrayBuffer())
286
- .then(buffer=>new Response(buffer,{headers:{"Content-Type":`${getFileType(fullpath(urlPath).split("/")[fullpath(urlPath).split("/").length-1].split("\\")[fullpath(urlPath).split("/")[fullpath(urlPath).split("/").length-1].split("\\").length-1])};charset=utf-8`}}));//重新定义header
287
- }
288
- else{
289
- return fetch(req);
290
- }
291
- }
292
- let isCors = () => false
293
- let isMemoryQueue = () => false
294
- const fetchFile = (request, banCache, urls = null) => {
295
- if (!urls) {
296
- urls = getSpareUrls(request.url)
297
- if (!urls) return fetchWithCors(request, banCache)
298
- }
299
- const list = urls.list
300
- const controllers = new Array(list.length)
301
- // noinspection JSCheckFunctionSignatures
302
- const startFetch = index => fetchWithCors(
303
- new Request(list[index], request),
304
- banCache,
305
- {signal: (controllers[index] = new AbortController()).signal}
306
- ).then(response => checkResponse(response) ? {r: response, i: index} : Promise.reject())
307
- return new Promise((resolve, reject) => {
308
- let flag = true
309
- const startAll = () => {
310
- flag = false
311
- Promise.any([
312
- first,
313
- ...Array.from({
314
- length: list.length - 1
315
- }, (_, index) => index + 1).map(index => startFetch(index))
316
- ]).then(res => {
317
- for (let i = 0; i !== list.length; ++i) {
318
- if (i !== res.i)
319
- controllers[i].abort()
320
- }
321
- resolve(res.r)
322
- }).catch(() => reject(`请求 ${request.url} 失败`))
323
- }
324
- const id = setTimeout(startAll, urls.timeout)
325
- const first = startFetch(0)
326
- .then(res => {
327
- if (flag) {
328
- clearTimeout(id)
329
- resolve(res.r)
330
- }
331
- }).catch(() => {
332
- if (flag) {
333
- clearTimeout(id)
334
- startAll()
335
- }
336
- return Promise.reject()
337
- })
338
- })
339
- }
340
-
341
- // 检查请求是否成功
342
- // noinspection JSUnusedLocalSymbols
343
- const checkResponse = response => response.ok || [301, 302, 307, 308].includes(response.status)
344
-
345
- /**
346
- * 删除指定缓存
347
- * @param list 要删除的缓存列表
348
- * @return {Promise<string[]>} 删除的缓存的URL列表
349
- */
350
- const deleteCache = list => caches.open(CACHE_NAME).then(cache => cache.keys()
351
- .then(keys => Promise.all(
352
- keys.map(async it => {
353
- const url = it.url
354
- if (url !== CTRL_PATH && list.match(url)) {
355
- // [debug delete]
356
- // noinspection ES6MissingAwait,JSCheckFunctionSignatures
357
- cache.delete(it)
358
- return url
359
- }
360
- return null
361
- })
362
- )).then(list => list.filter(it => it))
363
- )
364
-
365
- /**
366
- * 缓存列表
367
- * @type {Map<string, function(any)[]>}
368
- */
369
- const cacheMap = new Map()
370
-
371
- self.addEventListener('fetch', event => {
372
- let request = event.request
373
- let url = new URL(request.url)
374
- // [blockRequest call]
375
- if (request.method !== 'GET' || !request.url.startsWith('http')) return
376
- // [modifyRequest call]
377
- if (skipRequest(request)) return;
378
- let cacheKey = url.hostname + url.pathname + url.search
379
- let cache
380
- if (isMemoryQueue(request)) {
381
- cache = cacheMap.get(cacheKey)
382
- if (cache) {
383
- return event.respondWith(
384
- new Promise((resolve, reject) => {
385
- cacheMap.get(cacheKey).push(arg => arg.body ? resolve(arg) : reject(arg))
386
- })
387
- )
388
- }
389
- cacheMap.set(cacheKey, cache = [])
390
- }
391
- /** 处理拉取 */
392
- const handleFetch = promise => {
393
- event.respondWith(
394
- cache ? promise.then(response => {
395
- for (let item of cache) {
396
- item(response.clone())
397
- }
398
- }).catch(err => {
399
- for (let item of cache) {
400
- item(err)
401
- }
402
- }).then(() => {
403
- cacheMap.delete(cacheKey)
404
- return promise
405
- }) : promise
406
- )
407
- }
408
- const cacheRule = findCache(url)
409
- if (cacheRule) {
410
- let key = `https://${url.host}${url.pathname}`
411
- if (key.endsWith('/index.html')) key = key.substring(0, key.length - 10)
412
- if (cacheRule.search) key += url.search
413
- handleFetch(
414
- caches.match(key).then(
415
- cache => cache ?? fetchFile(request, true)
416
- .then(response => {
417
- if (checkResponse(response)) {
418
- const clone = response.clone()
419
- caches.open(CACHE_NAME).then(it => it.put(key, clone))
420
- // [debug put]
421
- }
422
- return response
423
- })
424
- )
425
- )
426
- } else {
427
- const urls = getSpareUrls(request.url)
428
- if (urls) handleFetch(fetchFile(request, false, urls))
429
- // [modifyRequest else-if]
430
- else handleFetch(fetchWithCache(request).catch(err => new Response(err, {status: 499})))
431
- }
432
- })
433
-
434
- self.addEventListener('message', event => {
435
- // [debug message]
436
- if (event.data === 'update')
437
- updateJson().then(info => {
438
- info.type = 'update'
439
- event.source.postMessage(info)
440
- })
441
- })
442
-
443
- /**
444
- * 根据JSON删除缓存
445
- * @returns {Promise<UpdateInfo>}
446
- */
447
- const updateJson = async () => {
448
- /**
449
- * 解析elements,并把结果输出到list中
450
- * @return boolean 是否刷新全站缓存
451
- */
452
- const parseChange = (list, elements, ver) => {
453
- for (let element of elements) {
454
- const {version, change} = element
455
- if (version === ver) return false
456
- if (change) {
457
- for (let it of change)
458
- list.push(new CacheChangeExpression(it))
459
- }
460
- }
461
- // 跨版本幅度过大,直接清理全站
462
- return true
463
- }
464
- /**
465
- * 解析字符串
466
- * @return {Promise<{
467
- * list?: VersionList,
468
- * new: BrowserVersion,
469
- * old: BrowserVersion
470
- * }>}
471
- */
472
- const parseJson = json => readVersion().then(oldVersion => {
473
- const {info, global} = json
474
- /** @type {BrowserVersion} */
475
- const newVersion = {global, local: info[0].version, escape: oldVersion?.escape ?? 0}
476
- // 新用户和刚进行过逃逸操作的用户不进行更新操作
477
- if (!oldVersion) {
478
- // noinspection JSValidateTypes
479
- newVersion.escape = 0
480
- writeVersion(newVersion)
481
- return {new: newVersion, old: oldVersion}
482
- }
483
- let list = new VersionList()
484
- let refresh = parseChange(list, info, oldVersion.local)
485
- writeVersion(newVersion)
486
- // [debug escape]
487
- // 如果需要清理全站
488
- if (refresh) {
489
- if (global !== oldVersion.global) list.force = true
490
- else list.refresh = true
491
- }
492
- return {list, new: newVersion, old: oldVersion}
493
- })
494
- const response = await fetchFile(new Request('/update.json'), false)
495
- if (!checkResponse(response))
496
- throw `加载 update.json 时遇到异常,状态码:${response.status}`
497
- const json = await response.json()
498
- const result = await parseJson(json)
499
- if (result.list) {
500
- const list = await deleteCache(result.list)
501
- result.list = list?.length ? list : null
502
- }
503
- // noinspection JSValidateTypes
504
- return result
505
- }
506
-
507
- /**
508
- * 版本列表
509
- * @constructor
510
- */
511
- function VersionList() {
512
-
513
- const list = []
514
-
515
- /**
516
- * 推送一个表达式
517
- * @param element {CacheChangeExpression} 要推送的表达式
518
- */
519
- this.push = element => {
520
- list.push(element)
521
- }
522
-
523
- /**
524
- * 判断指定 URL 是否和某一条规则匹配
525
- * @param url {string} URL
526
- * @return {boolean}
527
- */
528
- this.match = url => {
529
- if (this.force) return true
530
- // noinspection JSValidateTypes
531
- url = new URL(url)
532
- if (this.refresh) {
533
- // noinspection JSCheckFunctionSignatures
534
- return findCache(url).clean
535
- }
536
- else {
537
- for (let it of list) {
538
- if (it.match(url)) return true
539
- }
540
- }
541
- return false
542
- }
543
-
544
- }
545
-
546
- // noinspection SpellCheckingInspection
547
- /**
548
- * 缓存更新匹配规则表达式
549
- * @param json 格式{"flag": ..., "value": ...}
550
- * @see https://kmar.top/posts/bcfe8408/#23bb4130
551
- * @constructor
552
- */
553
- function CacheChangeExpression(json) {
554
- /**
555
- * 遍历所有value
556
- * @param action {function(string): boolean} 接受value并返回bool的函数
557
- * @return {boolean} 如果value只有一个则返回`action(value)`,否则返回所有运算的或运算(带短路)
558
- */
559
- const forEachValues = action => {
560
- const value = json.value
561
- if (Array.isArray(value)) {
562
- for (let it of value) {
563
- if (action(it)) return true
564
- }
565
- return false
566
- } else return action(value)
567
- }
568
- const getMatch = () => {
569
- switch (json['flag']) {
570
- case 'html':
571
- return url => url.pathname.match(/(\/|\.html)$/)
572
- case 'end':
573
- return url => forEachValues(value => url.href.endsWith(value))
574
- case 'begin':
575
- return url => forEachValues(value => url.pathname.startsWith(value))
576
- case 'str':
577
- return url => forEachValues(value => url.href.includes(value))
578
- case 'reg':
579
- // noinspection JSCheckFunctionSignatures
580
- return url => forEachValues(value => url.href.match(new RegExp(value, 'i')))
581
- default: throw `未知表达式:${JSON.stringify(json)}`
582
- }
583
- }
584
- this.match = getMatch()
585
- }
586
- })()
144
+ workbox.googleAnalytics.initialize();