swpp-backends 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,41 @@
1
1
  ## 欢迎使用 SwppBackends
2
2
 
3
-   这是 Service Worker Plus Plus 的后端仓库,代码正在开发中,开发完毕后会在这里补充文档并上传到 npm。
3
+ swpp-backends(以下简称 swpp)插件的功能是为网站生成一个高度可用的 ServiceWorker(以下简称 SW),为网站优化二次加载、提供离线体验、提高可靠性,并为此附带了一些其它的功能。
4
4
 
5
-   有兴趣的可以看 [hexo-swpp | 山岳库博](https://kmar.top/posts/73014407/)。
5
+ swpp 的全拼为“ServiceWorkerPlusPlus”(或“ServiceWorker++”),但是其与已有的插件“hexo-service-worker”并没有关系,插件中所有代码均为我个人开发,这一点请不要误解。
6
+
7
+ swpp 生成的 SW 与其它插件的对比:
8
+
9
+ | | swpp | hexo-offline |
10
+ |:----------:|:-------------:|:------------:|
11
+ | 本地缓存 | ✔️ | ✔️ |
12
+ | 缓存增量更新 | ✔️ | ❌ |
13
+ | 缓存过期时间 | ❌<sup>1</sup> | ✔️ |
14
+ | 缓存大小限制 | ❌ | ✔️ |
15
+ | 预缓存 | ❌ | ✔️ |
16
+ | Request 篡改 | ✔️ | ❌ |
17
+ | URL 竞速 | ✔️ | ❌ |
18
+ | 备用 URL | ✔️ | ❌ |
19
+ | 阻塞响应 | ✔️ | ❌ |
20
+ | 逃生门 | ✔️ | ❌ |
21
+ | 跨平台 | ✔️ | ❌ |
22
+ | 高度自由 | ✔️ | ❌ |
23
+ | 更新 | 非常频繁 | 超过两年没有更新 |
24
+
25
+ <small>&emsp;注:上面提到的跨平台是指跨越框架(比如 Hexo、WordPress 等)。</small>
26
+
27
+ + ✔️:支持
28
+ + ❌:不支持
29
+
30
+ 1. 因为有增量更新,所以没提供过期的实现,没必要
31
+
32
+
33
+ 目前支持的平台:
34
+
35
+ | 平台 | 插件名 | 文档 | 作者 |
36
+ |:----:|:-----------:|:---------------------------------------------------------:|:-----------------------:|
37
+ | hexo | `hexo-swpp` | [github](https://github.com/EmptyDreams/hexo-swpp#readme) | [空梦](https://kmar.top/) |
38
+
39
+ 如果你为某一个平台做了适配,可以在 gh 上发布 issue 或者在文档页面发布评论~
40
+
41
+ 文档:[Swpp Backends 官方文档 | 山岳库博](https://kmar.top/posts/b70ec88f/)
@@ -34,7 +34,6 @@ const SwppRules_1 = require("./SwppRules");
34
34
  const crypto = __importStar(require("crypto"));
35
35
  const buffer_1 = require("buffer");
36
36
  const fast_html_parser_1 = __importDefault(require("fast-html-parser"));
37
- const css_1 = __importDefault(require("css"));
38
37
  const Utils_1 = require("./Utils");
39
38
  /**
40
39
  * 遍历指定目录及其子目录中包含的所有文件(不遍历文件夹)
@@ -316,7 +315,6 @@ async function eachAllLinkInUrl(domain, url, result, event) {
316
315
  }
317
316
  exports.eachAllLinkInUrl = eachAllLinkInUrl;
318
317
  async function eachAllLinkInHtml(domain, url, content, result, event) {
319
- const root = url.substring(0, url.lastIndexOf('/') + 1);
320
318
  const taskList = [];
321
319
  const each = (node) => {
322
320
  let subUrl = undefined;
@@ -364,48 +362,39 @@ async function eachAllLinkInHtml(domain, url, content, result, event) {
364
362
  return Promise.all(taskList);
365
363
  }
366
364
  async function eachAllLinkInCss(domain, url, content, result, event) {
367
- const root = url.substring(0, url.lastIndexOf('/') + 1);
368
- const taskList = [];
369
- const each = (any) => {
370
- if (!any)
371
- return;
372
- for (let rule of any) {
373
- if (rule.declarations)
374
- each(rule.declarations);
375
- switch (rule.type) {
376
- case 'declaration':
377
- const value = rule.value;
378
- const list = value.match(/url\(['"]?([^'")]+)['"]?\)/g)
379
- ?.map(it => it.replace(/(^url\(['"]?)|(['"]?\)$)/g, ''));
380
- if (list) {
381
- for (let url of list) {
382
- if (!/^(https?:)|(\/\/)/.test(url)) {
383
- if (url[0] === '/')
384
- url = root + url.substring(1);
385
- else
386
- url = root + url;
387
- }
388
- taskList.push(eachAllLinkInUrl(domain, url, result, event));
389
- }
390
- }
391
- break;
392
- case 'import':
393
- const url = rule.import.trim().replace(/^["']|["']$/g, '');
394
- taskList.push(eachAllLinkInUrl(domain, url, result, event));
395
- break;
396
- }
365
+ const root = url.substring(0, url.lastIndexOf('/'));
366
+ const urls = new Set();
367
+ for (let i = 0; i < content.length;) {
368
+ const left = content.indexOf('/*', i);
369
+ let sub;
370
+ if (left < 0) {
371
+ sub = content.substring(i);
372
+ i = Number.MAX_VALUE;
397
373
  }
398
- };
399
- let css;
400
- try {
401
- css = css_1.default.parse(content).stylesheet?.rules;
402
- }
403
- catch (e) {
404
- (0, Utils_1.error)('CssParser', `CSS [root=${root}] 中存在错误语法`);
374
+ else {
375
+ sub = content.substring(i, left);
376
+ const right = content.indexOf('*/', left + 2);
377
+ if (right < 0)
378
+ i = Number.MAX_VALUE;
379
+ else
380
+ i = right + 2;
381
+ }
382
+ sub.match(/(url\(.*?\))|(@import\s+['"].*?['"])|((https?:)?\/\/[^\s/$.?#].\S*)/g)
383
+ ?.map(it => it.replace(/(^url\((['"]?))|((['"]?)\)$)|(^@import\s+['"])|(['"]$)/g, ''))
384
+ ?.forEach(it => urls.add(it));
405
385
  }
406
- if (css)
407
- each(css);
408
- return Promise.all(taskList);
386
+ return Promise.all(Array.from(urls).map(it => {
387
+ switch (true) {
388
+ case it.startsWith('http'):
389
+ return it;
390
+ case it.startsWith('//'):
391
+ return 'http' + it;
392
+ case it.startsWith('/'):
393
+ return root + it;
394
+ default:
395
+ return root + '/' + it;
396
+ }
397
+ }).map(it => eachAllLinkInUrl(domain, it, result, event)));
409
398
  }
410
399
  function eachAllLinkInJavaScript(domain, _, content, result, event) {
411
400
  const taskList = [];
@@ -57,7 +57,7 @@ function buildServiceWorker() {
57
57
  if (blockRequest) {
58
58
  content = content.replace('// [blockRequest call]', `
59
59
  if (blockRequest(url))
60
- return event.respondWith(new Response(null, {status: 208}))
60
+ return event.respondWith(new Response(null, {status: 204}))
61
61
  `);
62
62
  }
63
63
  // noinspection JSUnresolvedVariable
package/dist/SwppRules.js CHANGED
@@ -104,6 +104,7 @@ function loadRules(root, fileName, selects) {
104
104
  event(rootRules);
105
105
  }
106
106
  eventList = null;
107
+ (0, Utils_1.deepFreeze)(rootRules);
107
108
  return _rules = rootRules;
108
109
  }
109
110
  exports.loadRules = loadRules;
package/dist/Utils.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.replaceDevRequest = exports.fetchFile = exports.getSource = exports.readEjectData = exports.calcEjectValues = exports.warn = exports.error = void 0;
6
+ exports.deepFreeze = exports.replaceDevRequest = exports.fetchFile = exports.getSource = exports.readEjectData = exports.calcEjectValues = exports.warn = exports.error = void 0;
7
7
  const node_fetch_1 = __importDefault(require("node-fetch"));
8
8
  const SwppRules_1 = require("./SwppRules");
9
9
  const logger = require('hexo-log').default({
@@ -190,3 +190,15 @@ async function fetchSpeed(list) {
190
190
  }
191
191
  return result.response;
192
192
  }
193
+ /** 深度冻结一个对象,这将使得无法修改对象中的任何值,也无法添加新的值 */
194
+ function deepFreeze(obj) {
195
+ if (!obj)
196
+ return;
197
+ Object.freeze(obj);
198
+ for (let key in obj) {
199
+ const value = obj[key];
200
+ if (typeof value === 'object')
201
+ deepFreeze(value);
202
+ }
203
+ }
204
+ exports.deepFreeze = deepFreeze;
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ const UpdateJsonBuilder_1 = require("./UpdateJsonBuilder");
8
8
  const VersionAnalyzer_1 = require("./VersionAnalyzer");
9
9
  // noinspection JSUnusedGlobalSymbols
10
10
  exports.default = {
11
+ version: '1.2.0',
11
12
  cache: {
12
13
  readEjectData: Utils_1.readEjectData, readUpdateJson: UpdateJsonBuilder_1.readUpdateJson,
13
14
  readRules: SwppRules_1.readRules, readMergeVersionMap: FileAnalyzer_1.readMergeVersionMap,
@@ -30,6 +31,6 @@ exports.default = {
30
31
  getSource: Utils_1.getSource, getShorthand: UpdateJsonBuilder_1.getShorthand, findCache: FileAnalyzer_1.findCache,
31
32
  fetchFile: Utils_1.fetchFile, replaceDevRequest: Utils_1.replaceDevRequest, replaceRequest: FileAnalyzer_1.replaceRequest,
32
33
  isStable: FileAnalyzer_1.isStable, isExclude: FileAnalyzer_1.isExclude, findFileHandler: FileAnalyzer_1.findFileHandler,
33
- eachAllLinkInUrl: FileAnalyzer_1.eachAllLinkInUrl
34
+ eachAllLinkInUrl: FileAnalyzer_1.eachAllLinkInUrl, deepFreeze: Utils_1.deepFreeze
34
35
  }
35
36
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swpp-backends",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "main": "dist/index.js",
5
5
  "typings": "types/index.d.ts",
6
6
  "description": "Generate a powerful ServiceWorker for your website.",
@@ -19,7 +19,6 @@
19
19
  "typescript": "^5.1.6"
20
20
  },
21
21
  "dependencies": {
22
- "css": "^3.0.0",
23
22
  "fast-html-parser": "^1.0.1",
24
23
  "hexo-log": "^4.1.0",
25
24
  "node-fetch": "^2.6.12"
package/types/Utils.d.ts CHANGED
@@ -39,3 +39,5 @@ export declare function fetchFile(link: string): Promise<import("node-fetch").Re
39
39
  * **调用该函数前必须调用过 [loadRules]**
40
40
  */
41
41
  export declare function replaceDevRequest(link: string): string[] | string;
42
+ /** 深度冻结一个对象,这将使得无法修改对象中的任何值,也无法添加新的值 */
43
+ export declare function deepFreeze(obj: any): void;
package/types/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { readEjectData, getSource, fetchFile, replaceDevRequest, calcEjectValues } from './Utils';
1
+ import { readEjectData, getSource, fetchFile, replaceDevRequest, calcEjectValues, deepFreeze } from './Utils';
2
2
  import { isExclude, isStable, loadVersionJson, readOldVersionJson, readNewVersionJson, readMergeVersionMap, buildVersionJson, eachAllLinkInUrl, findCache, findFileHandler, replaceRequest, submitCacheInfo, submitExternalUrl, registryFileHandler } from './FileAnalyzer';
3
3
  import { buildServiceWorker } from './ServiceWorkerBuilder';
4
4
  import { readRules, loadRules, addRulesMapEvent } from './SwppRules';
5
5
  import { readUpdateJson, loadUpdateJson, submitChange, getShorthand, buildNewInfo } from './UpdateJsonBuilder';
6
6
  import { refreshUrl, analyze } from './VersionAnalyzer';
7
7
  declare const _default: {
8
+ version: string;
8
9
  cache: {
9
10
  readEjectData: typeof readEjectData;
10
11
  readUpdateJson: typeof readUpdateJson;
@@ -44,6 +45,7 @@ declare const _default: {
44
45
  isExclude: typeof isExclude;
45
46
  findFileHandler: typeof findFileHandler;
46
47
  eachAllLinkInUrl: typeof eachAllLinkInUrl;
48
+ deepFreeze: typeof deepFreeze;
47
49
  };
48
50
  };
49
51
  export default _default;