sinzmise-cetastories 1.7.0-1718289999298 → 1.7.0-1718455396962

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) 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/index.html +1 -1
  28. package/archives/2024/page/2/index.html +1 -1
  29. package/archives/index.html +1 -1
  30. package/archives/page/2/index.html +1 -1
  31. package/archives/page/3/index.html +1 -1
  32. package/archives/page/4/index.html +1 -1
  33. package/atom.xml +21 -21
  34. package/baidu_verify_codeva-NA6uDlCuZg.html +1 -1
  35. package/baidusitemap.xml +68 -68
  36. package/bangumis/index.html +1 -1
  37. package/bbs/index.html +1 -1
  38. package/cacheList.json +1 -1
  39. package/categories/index.html +1 -1
  40. package/categories//344/270/252/344/272/272/345/260/217/350/256/260/index.html +1 -1
  41. package/categories//344/270/252/344/272/272/345/260/217/350/256/260/page/2/index.html +1 -1
  42. package/categories//346/255/214/346/233/262/346/224/266/351/233/206/index.html +1 -1
  43. package/categories//346/270/270/346/210/217/347/233/270/345/205/263/index.html +1 -1
  44. package/categories//347/253/231/347/202/271/346/212/230/350/205/276/index.html +1 -1
  45. package/categories//347/253/231/347/202/271/346/212/230/350/205/276/page/2/index.html +1 -1
  46. package/categories//351/241/271/347/233/256/346/212/230/350/205/276/index.html +1 -1
  47. package/charts/index.html +1 -1
  48. package/comments/index.html +1 -1
  49. package/essay/index.html +1 -1
  50. package/fcircle/index.html +1 -1
  51. package/google8073542809160a67.html +1 -1
  52. package/index.html +1 -1
  53. package/js/fps.js +1 -1
  54. package/link/index.html +1 -1
  55. package/music/index.html +1 -1
  56. package/package.json +1 -1
  57. package/page/2/index.html +1 -1
  58. package/page/3/index.html +1 -1
  59. package/page/4/index.html +1 -1
  60. package/posts/10021/index.html +1 -1
  61. package/posts/10045/index.html +1 -1
  62. package/posts/10996/index.html +1 -1
  63. package/posts/12779/index.html +1 -1
  64. package/posts/13624/index.html +1 -1
  65. package/posts/15748/index.html +1 -1
  66. package/posts/15842/index.html +1 -1
  67. package/posts/16107/index.html +1 -1
  68. package/posts/18063/index.html +1 -1
  69. package/posts/20412/index.html +1 -1
  70. package/posts/21375/index.html +1 -1
  71. package/posts/22945/index.html +1 -1
  72. package/posts/23021/index.html +1 -1
  73. package/posts/27531/index.html +1 -1
  74. package/posts/27762/index.html +1 -1
  75. package/posts/28536/index.html +1 -1
  76. package/posts/28733/index.html +1 -1
  77. package/posts/29196/index.html +1 -1
  78. package/posts/38917/index.html +1 -1
  79. package/posts/38964/index.html +1 -1
  80. package/posts/42487/index.html +1 -1
  81. package/posts/42580/index.html +1 -1
  82. package/posts/45875/index.html +1 -1
  83. package/posts/48762/index.html +1 -1
  84. package/posts/50710/index.html +1 -1
  85. package/posts/52677/index.html +1 -1
  86. package/posts/53662/index.html +1 -1
  87. package/posts/54386/index.html +1 -1
  88. package/posts/54481/index.html +1 -1
  89. package/posts/54787/index.html +1 -1
  90. package/posts/56467/index.html +1 -1
  91. package/posts/57692/index.html +1 -1
  92. package/posts/58203/index.html +1 -1
  93. package/posts/61417/index.html +1 -1
  94. package/posts/646/index.html +1 -1
  95. package/seas/index.html +1 -1
  96. package/sitemap.xml +117 -117
  97. package/sw-dom.js +73 -1
  98. package/sw.js +586 -1
  99. package/tags/Flash/347/233/270/345/205/263/index.html +1 -1
  100. package/tags/Steam/346/270/270/346/210/217/index.html +1 -1
  101. package/tags/Windows/350/275/257/344/273/266/index.html +1 -1
  102. package/tags/index.html +1 -1
  103. package/tags//344/270/252/344/272/272/345/260/217/350/256/260/index.html +1 -1
  104. package/tags//344/270/252/344/272/272/345/260/217/350/256/260/page/2/index.html +1 -1
  105. package/tags//345/205/266/345/256/203/346/270/270/346/210/217/index.html +1 -1
  106. 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
  107. package/tags//346/255/214/346/233/262/346/224/266/351/233/206/index.html +1 -1
  108. package/tags//346/270/270/346/210/217/347/233/270/345/205/263/index.html +1 -1
  109. package/tags//347/253/231/347/202/271/345/272/225/351/203/250/351/255/224/346/224/271/index.html +1 -1
  110. package/tags//347/253/231/347/202/271/346/212/230/350/205/276/index.html +1 -1
  111. package/tags//347/253/231/347/202/271/346/212/230/350/205/276/page/2/index.html +1 -1
  112. package/tags//350/207/252/345/273/272/351/203/250/347/275/262/index.html +1 -1
  113. package/tags//351/241/265/351/235/242/351/255/224/346/224/271/index.html +1 -1
  114. package/tags//351/241/271/347/233/256/346/212/230/350/205/276/index.html +1 -1
  115. package/update/index.html +1 -1
  116. package/update.json +1 -1
package/sw-dom.js CHANGED
@@ -1 +1,73 @@
1
- document.addEventListener("DOMContentLoaded",(()=>{if(!navigator.serviceWorker?.controller)return;const e=e=>{const t=e.endsWith("js")?"script":"link",o="link"===t?"href":"src";for(let n of document.getElementsByTagName(t)){const r=n[o];if(e.length>r?e.endsWith(r):r.endsWith(e)){const e=document.createElement(t),o=n.text||n.textContent||n.innerHTML||"";return Array.from(n.attributes).forEach((t=>e.setAttribute(t.name,t.value))),e.appendChild(document.createTextNode(o)),n.parentNode.replaceChildren(e,n),!0}}},t="updated",o=()=>{caches.match("https://id.v3/").then((function(e){e?e.json().then((function(e){var t="light"===document.documentElement.getAttribute("data-theme")?GLOBAL_CONFIG.Snackbar.bgLight:GLOBAL_CONFIG.Snackbar.bgDark,o=GLOBAL_CONFIG.Snackbar.position;Snackbar.show({text:`已刷新缓存,更新为${GLOBAL_CONFIG.uiversion}版本最新内容`,backgroundColor:t,duration:3e4,pos:o,actionText:"查看更新日志",actionTextColor:"#fff",onActionClick:function(e){location.assign("/update/")}})})):console.info("未找到匹配的缓存响应")})).catch((function(e){console.error("缓存匹配出错:",e)}))};var n;sessionStorage.getItem(t)?(o(),sessionStorage.removeItem(t)):(n="update",navigator.serviceWorker.controller.postMessage(n)),navigator.serviceWorker.addEventListener("message",(n=>{const r=n.data;sessionStorage.setItem(t,r.type);const a=r.list?.filter((e=>/\.(js|css)$/.test(e)));if(a)window.Pjax?.isSupported?.()&&a.forEach(e),location.reload();else{const e=r.new,n=r.old;!n||e.global===n.global&&e.local===n.local||o(),sessionStorage.removeItem(t)}}))}));
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ if (!navigator.serviceWorker?.controller) return
3
+ /** 发送信息到 sw */
4
+ const postMessage2SW = type => navigator.serviceWorker.controller.postMessage(type)
5
+ const pjaxUpdate = url => {
6
+ const type = url.endsWith('js') ? 'script' : 'link'
7
+ const name = type === 'link' ? 'href' : 'src'
8
+ for (let item of document.getElementsByTagName(type)) {
9
+ const itUrl = item[name]
10
+ if (url.length > itUrl ? url.endsWith(itUrl) : itUrl.endsWith(url)) {
11
+ const newEle = document.createElement(type)
12
+ const content = item.text || item.textContent || item.innerHTML || ''
13
+ // noinspection JSUnresolvedReference
14
+ Array.from(item.attributes).forEach(attr => newEle.setAttribute(attr.name, attr.value))
15
+ newEle.appendChild(document.createTextNode(content))
16
+ item.parentNode.replaceChildren(newEle, item)
17
+ return true
18
+ }
19
+ }
20
+ }
21
+ const SESSION_KEY = 'updated'
22
+ // noinspection JSFileReferences
23
+ const onSuccess = () => {
24
+ caches.match('https://id.v3/').then(function(response) {
25
+ if (response) {
26
+ // 如果找到了匹配的缓存响应
27
+ response.json().then(function(data) {
28
+ var snackbarBg =
29
+ document.documentElement.getAttribute('data-theme') === 'light' ?
30
+ GLOBAL_CONFIG.Snackbar.bgLight :
31
+ GLOBAL_CONFIG.Snackbar.bgDark
32
+ var snackbarPos = GLOBAL_CONFIG.Snackbar.position
33
+ Snackbar.show({
34
+ text: `已刷新缓存,更新为${GLOBAL_CONFIG.uiversion}版本最新内容`,
35
+ backgroundColor: snackbarBg,
36
+ duration: 30000,
37
+ pos: snackbarPos,
38
+ actionText: '查看更新日志',
39
+ actionTextColor: '#fff',
40
+ onActionClick: function(e) {
41
+ location.assign("/update/");
42
+ },
43
+ })
44
+ });
45
+ } else {
46
+ console.info('未找到匹配的缓存响应');
47
+ }
48
+ }).catch(function(error) {
49
+ console.error('缓存匹配出错:', error);
50
+ });
51
+ };
52
+ if (sessionStorage.getItem(SESSION_KEY)) {
53
+ onSuccess()
54
+ sessionStorage.removeItem(SESSION_KEY)
55
+ } else postMessage2SW('update')
56
+ navigator.serviceWorker.addEventListener('message', event => {
57
+ const data = event.data
58
+ sessionStorage.setItem(SESSION_KEY, data.type)
59
+ const list = data.list?.filter(url => /\.(js|css)$/.test(url))
60
+ if (list) {
61
+ // noinspection JSUnresolvedReference
62
+ if (window.Pjax?.isSupported?.())
63
+ list.forEach(pjaxUpdate)
64
+ location.reload()
65
+ } else {
66
+ const newVersion = data.new, oldVersion = data.old
67
+ if (oldVersion && (newVersion.global !== oldVersion.global || newVersion.local !== oldVersion.local)) {
68
+ onSuccess()
69
+ }
70
+ sessionStorage.removeItem(SESSION_KEY)
71
+ }
72
+ })
73
+ })
package/sw.js CHANGED
@@ -1 +1,586 @@
1
- (()=>{const t="StoriHouseCache",e="https://id.v3/",n=()=>caches.match(e).then((t=>t?.json())),s=n=>caches.open(t).then((t=>t.put(e,new Response(JSON.stringify(n)))));self.addEventListener("install",(()=>{self.skipWaiting()})),self.addEventListener("activate",(t=>t.waitUntil(clients.claim())));const r=(t,e,n,s)=>(s||(s={}),s.cache=e?"no-store":"default",n&&(s.mode="cors",s.credentials="same-origin"),fetch(t,s)),c=(t,e,n)=>r(t,e,!0,n),a=t=>{if("localhost"!==t.hostname)for(let e in o){const n=o[e];if(n.match(t))return n}};let o={simple:{clean:!0,search:!1,match:t=>"blog.sinzmise.top"===t.host&&["/404.html","/css/index.css"].includes(t.pathname)},cdn:{clean:!0,match:t=>["unpkg.com","cdn.cbd.int","lf26-cdn-tos.bytecdntp.com","lf6-cdn-tos.bytecdntp.com","lf3-cdn-tos.bytecdntp.com","lf9-cdn-tos.bytecdntp.com","npm.onmicrosoft.cn","cdn.staticfile.org","npm.elemecdn.com"].includes(t.host)&&t.pathname.match(/\.(js|css|woff2|woff|ttf|cur)$/)}},i=t=>{if(t.startsWith("https://npm.elemecdn.com"))return{timeout:3e3,list:[t,`https://cdn.cbd.int/${new URL(t).pathname}`]}},l=()=>!1;const h=(t,e,n=null)=>{if(!n&&!(n=i(t.url)))return c(t,e);const s=n.list,r=new Array(s.length),a=n=>c(new Request(s[n],t),e,{signal:(r[n]=new AbortController).signal}).then((t=>u(t)?{r:t,i:n}:Promise.reject()));return new Promise(((e,c)=>{let o=!0;const i=()=>{o=!1,Promise.any([h,...Array.from({length:s.length-1},((t,e)=>e+1)).map((t=>a(t)))]).then((t=>{for(let e=0;e!==s.length;++e)e!==t.i&&r[e].abort();e(t.r)})).catch((()=>c(`请求 ${t.url} 失败`)))},l=setTimeout(i,n.timeout),h=a(0).then((t=>{o&&(clearTimeout(l),e(t.r))})).catch((()=>(o&&(clearTimeout(l),i()),Promise.reject())))}))},u=t=>t.ok||[301,302,307,308].includes(t.status),f=new Map;self.addEventListener("fetch",(e=>{let n=e.request,s=new URL(n.url);if("GET"!==n.method||!n.url.startsWith("http"))return;if((t=>t.url.startsWith("https://i0.hdslb.com"))(n))return;let c,o=s.hostname+s.pathname+s.search;const m=t=>{e.respondWith(c?t.then((t=>{for(let e of c)e(t.clone())})).catch((t=>{for(let e of c)e(t)})).then((()=>(f.delete(o),t))):t)},d=a(s);if(d){let e=`https://${s.host}${s.pathname}`;e.endsWith("/index.html")&&(e=e.substring(0,e.length-10)),d.search&&(e+=s.search),m(caches.match(e).then((s=>s??h(n,!0).then((n=>{if(u(n)){const s=n.clone();caches.open(t).then((t=>t.put(e,s)))}return n})))))}else{const t=i(n.url);m(t?h(n,!1,t):((t,e)=>r(t,!1,l(t),e))(n).catch((t=>new Response(t,{status:499}))))}})),self.addEventListener("message",(t=>{"update"===t.data&&m().then((e=>{e.type="update",t.source.postMessage(e)}))}));const m=async()=>{const r=await h(new Request("/update.json"),!1);if(!u(r))throw`加载 update.json 时遇到异常,状态码:${r.status}`;const c=await r.json(),a=await(t=>n().then((e=>{const{info:n,global:r}=t,c={global:r,local:n[0].version,escape:e?.escape??0};if(!e)return c.escape=0,s(c),{new:c,old:e};let a=new d,o=((t,e,n)=>{for(let s of e){const{version:e,change:r}=s;if(e===n)return!1;if(r)for(let e of r)t.push(new p(e))}return!0})(a,n,e.local);return s(c),o&&(r!==e.global?a.force=!0:a.refresh=!0),{list:a,new:c,old:e}})))(c);if(a.list){const n=await(n=>caches.open(t).then((t=>t.keys().then((s=>Promise.all(s.map((async s=>{const r=s.url;return r!==e&&n.match(r)?(t.delete(s),r):null}))))).then((t=>t.filter((t=>t)))))))(a.list);a.list=n?.length?n:null}return a};function d(){const t=[];this.push=e=>{t.push(e)},this.match=e=>{if(this.force)return!0;if(e=new URL(e),this.refresh)return a(e).clean;for(let n of t)if(n.match(e))return!0;return!1}}function p(t){const e=e=>{const n=t.value;if(Array.isArray(n)){for(let t of n)if(e(t))return!0;return!1}return e(n)};this.match=(()=>{switch(t.flag){case"html":return t=>t.pathname.match(/(\/|\.html)$/);case"end":return t=>e((e=>t.href.endsWith(e)));case"begin":return t=>e((e=>t.pathname.startsWith(e)));case"str":return t=>e((e=>t.href.includes(e)));case"reg":return t=>e((e=>t.href.match(new RegExp(e,"i"))));default:throw`未知表达式:${JSON.stringify(t)}`}})()}})();
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
+ }
129
+
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
+ })
151
+ })
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
+ })
161
+ })
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
+ })
188
+ })
189
+ }
190
+ }
191
+ return Promise.any(urls.map(urls => {
192
+ return new Promise((resolve, reject) => {
193
+ fetch(urls, {
194
+ signal: controller.signal
195
+ })
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);
248
+
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
+ })()