sinzmise-cetastories-en 1.7.0-1719905274967 → 1.7.0-1719906897661

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. package/404.html +72 -0
  2. package/BingSiteAuth.xml +4 -0
  3. package/archives/2023/12/index.html +72 -0
  4. package/archives/2023/index.html +72 -0
  5. package/archives/index.html +72 -0
  6. package/article.json +1 -0
  7. package/{en/atom.xml → atom.xml} +9 -9
  8. package/baidu_verify_codeva-NA6uDlCuZg.html +72 -0
  9. package/{en/baidusitemap.xml → baidusitemap.xml} +1 -1
  10. package/bangumis/index.html +72 -0
  11. package/cacheList.json +1 -0
  12. package/categories/Test/index.html +72 -0
  13. package/categories/index.html +72 -0
  14. package/css/custom2.css +1 -0
  15. package/css/plane.css +1 -0
  16. package/google8073542809160a67.html +72 -0
  17. package/images/favicon.ico +0 -0
  18. package/images/siteicon/16.png +0 -0
  19. package/images/siteicon/32.png +0 -0
  20. package/images/siteicon/apple-icon-180.png +0 -0
  21. package/images/siteicon/manifest-icon-192.maskable.png +0 -0
  22. package/images/siteicon/manifest-icon-512.maskable.png +0 -0
  23. package/img/512.png +0 -0
  24. package/img/avatar.png +0 -0
  25. package/img/bili.jpg +0 -0
  26. package/img/dark.jpg +0 -0
  27. package/img/friend_404.gif +0 -0
  28. package/img/icon-dark.png +0 -0
  29. package/img/icon-light.png +0 -0
  30. package/img/icons/api.svg +1 -0
  31. package/img/icons/diary.svg +1 -0
  32. package/img/icons/homepage.svg +1 -0
  33. package/img/icons/navi.svg +1 -0
  34. package/img/icons/pan.svg +1 -0
  35. package/img/icons/rtalk.svg +1 -0
  36. package/img/light.jpg +0 -0
  37. package/img/link.png +0 -0
  38. package/img/load-dark.png +0 -0
  39. package/img/load-light.png +0 -0
  40. package/img/longnian.webp +0 -0
  41. package/img/longnian1.webp +0 -0
  42. package/img/longnian2.webp +0 -0
  43. package/img/longnian3.webp +0 -0
  44. package/img/siteicon/android-chrome-144x144.png +0 -0
  45. package/img/siteicon/android-chrome-192x192.png +0 -0
  46. package/img/siteicon/android-chrome-256x256.png +0 -0
  47. package/img/siteicon/android-chrome-36x36.png +0 -0
  48. package/img/siteicon/android-chrome-384x384.png +0 -0
  49. package/img/siteicon/android-chrome-48x48.png +0 -0
  50. package/img/siteicon/android-chrome-512x512.png +0 -0
  51. package/img/siteicon/android-chrome-72x72.png +0 -0
  52. package/img/siteicon/android-chrome-96x96.png +0 -0
  53. package/img/siteicon/apple-splash-1125-2436.jpg +0 -0
  54. package/img/siteicon/apple-splash-1136-640.jpg +0 -0
  55. package/img/siteicon/apple-splash-1170-2532.jpg +0 -0
  56. package/img/siteicon/apple-splash-1179-2556.jpg +0 -0
  57. package/img/siteicon/apple-splash-1242-2208.jpg +0 -0
  58. package/img/siteicon/apple-splash-1242-2688.jpg +0 -0
  59. package/img/siteicon/apple-splash-1284-2778.jpg +0 -0
  60. package/img/siteicon/apple-splash-1290-2796.jpg +0 -0
  61. package/img/siteicon/apple-splash-1334-750.jpg +0 -0
  62. package/img/siteicon/apple-splash-1536-2048.jpg +0 -0
  63. package/img/siteicon/apple-splash-1620-2160.jpg +0 -0
  64. package/img/siteicon/apple-splash-1668-2224.jpg +0 -0
  65. package/img/siteicon/apple-splash-1668-2388.jpg +0 -0
  66. package/img/siteicon/apple-splash-1792-828.jpg +0 -0
  67. package/img/siteicon/apple-splash-2048-1536.jpg +0 -0
  68. package/img/siteicon/apple-splash-2048-2732.jpg +0 -0
  69. package/img/siteicon/apple-splash-2160-1620.jpg +0 -0
  70. package/img/siteicon/apple-splash-2208-1242.jpg +0 -0
  71. package/img/siteicon/apple-splash-2224-1668.jpg +0 -0
  72. package/img/siteicon/apple-splash-2388-1668.jpg +0 -0
  73. package/img/siteicon/apple-splash-2436-1125.jpg +0 -0
  74. package/img/siteicon/apple-splash-2532-1170.jpg +0 -0
  75. package/img/siteicon/apple-splash-2556-1179.jpg +0 -0
  76. package/img/siteicon/apple-splash-2688-1242.jpg +0 -0
  77. package/img/siteicon/apple-splash-2732-2048.jpg +0 -0
  78. package/img/siteicon/apple-splash-2778-1284.jpg +0 -0
  79. package/img/siteicon/apple-splash-2796-1290.jpg +0 -0
  80. package/img/siteicon/apple-splash-640-1136.jpg +0 -0
  81. package/img/siteicon/apple-splash-750-1334.jpg +0 -0
  82. package/img/siteicon/apple-splash-828-1792.jpg +0 -0
  83. package/img/siteicon/apple-touch-icon.png +0 -0
  84. package/img/siteicon/favicon-16x16.png +0 -0
  85. package/img/siteicon/favicon-32x32.png +0 -0
  86. package/img/siteicon/favicon.ico +0 -0
  87. package/img/siteicon/mstile-150x150.png +0 -0
  88. package/img/siteicon/safari-pinned-tab.svg +247 -0
  89. package/img/theta.svg +1 -0
  90. package/index.html +72 -0
  91. package/js/autoload.js +1 -0
  92. package/js/clock.js +1 -0
  93. package/js/kslink.js +1 -0
  94. package/js/newyear.js +1 -0
  95. package/js/plane.js +1 -0
  96. package/js/txmap.js +1 -0
  97. package/js/waifu-tips.json +1 -0
  98. package/manifest.json +1 -0
  99. package/package.json +1 -1
  100. package/posts/46521/index.html +72 -0
  101. package/sitemap.xml +101 -0
  102. package/sw-dom.js +73 -0
  103. package/sw.js +580 -138
  104. package/tags/Test/index.html +72 -0
  105. package/tags/index.html +72 -0
  106. package/test.json +1 -0
  107. package/update.json +1 -0
  108. package/en/404.html +0 -72
  109. package/en/archives/2023/12/index.html +0 -72
  110. package/en/archives/2023/index.html +0 -72
  111. package/en/archives/index.html +0 -72
  112. package/en/article.json +0 -1
  113. package/en/bangumis/index.html +0 -72
  114. package/en/categories/Test/index.html +0 -72
  115. package/en/categories/index.html +0 -72
  116. package/en/img/friend_404.gif +0 -0
  117. package/en/index.html +0 -72
  118. package/en/posts/46521/index.html +0 -72
  119. package/en/sitemap.xml +0 -56
  120. package/en/tags/Test/index.html +0 -72
  121. package/en/tags/index.html +0 -72
  122. /package/{en/assets → assets}/algolia/algoliasearch.js +0 -0
  123. /package/{en/assets → assets}/algolia/algoliasearch.min.js +0 -0
  124. /package/{en/assets → assets}/algolia/algoliasearchLite.js +0 -0
  125. /package/{en/assets → assets}/algolia/algoliasearchLite.min.js +0 -0
  126. /package/{en/css → css}/404.css +0 -0
  127. /package/{en/css → css}/anzhiyu-var.css +0 -0
  128. /package/{en/css → css}/bywind-var.css +0 -0
  129. /package/{en/css → css}/categoryBar.css +0 -0
  130. /package/{en/css → css}/console.css +0 -0
  131. /package/{en/css → css}/custom.css +0 -0
  132. /package/{en/css → css}/essay_page.css +0 -0
  133. /package/{en/css → css}/footer.css +0 -0
  134. /package/{en/css → css}/heo-var.css +0 -0
  135. /package/{en/css → css}/icat-var.css +0 -0
  136. /package/{en/css → css}/iconfont.css +0 -0
  137. /package/{en/css → css}/iconfont.ttf +0 -0
  138. /package/{en/css → css}/iconfont.woff +0 -0
  139. /package/{en/css → css}/iconfont.woff2 +0 -0
  140. /package/{en/css → css}/index.css +0 -0
  141. /package/{en/css → css}/orlike.css +0 -0
  142. /package/{en/css → css}/rightmenu.css +0 -0
  143. /package/{en/css → css}/var.css +0 -0
  144. /package/{en/img → img}/404.jpg +0 -0
  145. /package/{en/img → img}/favicon.png +0 -0
  146. /package/{en/img → img}/footer-social-link.svg +0 -0
  147. /package/{en/js → js}/about.js +0 -0
  148. /package/{en/js → js}/categoryBar.js +0 -0
  149. /package/{en/js → js}/comments.js +0 -0
  150. /package/{en/js → js}/console.js +0 -0
  151. /package/{en/js → js}/custom/fixed_card_widget.js +0 -0
  152. /package/{en/js → js}/custom.js +0 -0
  153. /package/{en/js → js}/day.js +0 -0
  154. /package/{en/js → js}/fps.js +0 -0
  155. /package/{en/js → js}/hometop.js +0 -0
  156. /package/{en/js → js}/lunar.js +0 -0
  157. /package/{en/js → js}/main.js +0 -0
  158. /package/{en/js → js}/nav.js +0 -0
  159. /package/{en/js → js}/orlike.js +0 -0
  160. /package/{en/js → js}/owobig.js +0 -0
  161. /package/{en/js → js}/random-friends-post.js +0 -0
  162. /package/{en/js → js}/randompost.js +0 -0
  163. /package/{en/js → js}/rightmenu.js +0 -0
  164. /package/{en/js → js}/sakura.js +0 -0
  165. /package/{en/js → js}/search/algolia.js +0 -0
  166. /package/{en/js → js}/search/local-search.js +0 -0
  167. /package/{en/js → js}/tw_cn.js +0 -0
  168. /package/{en/js → js}/utils.js +0 -0
  169. /package/{en/js → js}/waterfall/waterfall.js +0 -0
  170. /package/{en/js → js}/welcome.js +0 -0
  171. /package/{en/lib → lib}/tag_plugins.css +0 -0
  172. /package/{en/robots.txt → robots.txt} +0 -0
package/sw.js CHANGED
@@ -1,144 +1,586 @@
1
- const workboxVersion = '5.1.3';
1
+ // noinspection JSIgnoredPromiseFromCall
2
+
3
+ (() => {
4
+ /** 缓存库名称 */
5
+ const CACHE_NAME = 'StoriHouseCache'
6
+ /** 控制信息存储地址(必须以`/`结尾) */
7
+ const CTRL_PATH = 'https://id.v3/'
8
+
9
+ const ejectDomain = 'en.blog.sinzmise.top'
10
+ const ejectMirror = ['https://registry.npmmirror.com/sinzmise-cetastories-en/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
+ }
2
129
 
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([],{
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]
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
+ })
74
151
  })
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]
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
+ })
91
161
  })
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]
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
+ })
106
188
  })
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]
189
+ }
190
+ }
191
+ return Promise.any(urls.map(urls => {
192
+ return new Promise((resolve, reject) => {
193
+ fetch(urls, {
194
+ signal: controller.signal
139
195
  })
140
- ]
141
- })
142
- );
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);
143
248
 
144
- workbox.googleAnalytics.initialize();
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-en',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
+ })()