hexo-swpp 3.3.6 → 3.4.0-alpha.110

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.
Files changed (3) hide show
  1. package/README.md +40 -28
  2. package/dist/index.js +162 -90
  3. package/package.json +6 -8
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  使用时需要同时安装 `hexo-swpp` 和 `swpp-backends`:
6
6
 
7
7
  ```bash
8
- npm install hexo-swpp swpp-backends
8
+ npm install hexo-swpp swpp-backends@3.0.0-alpha.100
9
9
  ```
10
10
 
11
11
  当 `swpp-backends` 存在版本更新时,可以直接更新 `swpp-backends` 版本,不需要更新 `hexo-swpp` 的版本。(不过 `hexo-swpp` 有更新的话最好也跟进一下。)
@@ -18,6 +18,7 @@ npm install hexo-swpp swpp-backends
18
18
  | ~3.1 | ^1.1.0 |
19
19
  | ~3.2 | ^2.0.0 |
20
20
  | ~3.3 | ^2.1.2 |
21
+ | 4.0-alpha | ^3.0.0-alpha.100 |
21
22
 
22
23
  ## 使用
23
24
 
@@ -25,15 +26,36 @@ npm install hexo-swpp swpp-backends
25
26
 
26
27
  ```yml
27
28
  swpp:
28
- # 是否启用插件
29
+ # 是否启用,默认 false
29
30
  enable: true
30
- # 是否在发布前自动执行脚本
31
- # auto_exec: true
32
- # 构建时拉取版本文件的警告等级,缺省为 1(该功能仅在 swpp-backends 版本号 >= 2.1.2 时可用)
33
- # 0 - 表示不允许出现 404 情况;1 - 表示允许服务器返回 404 状态码;2 - 表示允许任何 404(包括 DNS 解析失败等)
34
- # warn_level: 1
35
- # 检查版本的 URL,不能以 '/' 结尾
31
+ # 配置文件名称,不带拓展名
32
+ # config_name: 'swpp.config'
33
+ # 是否生成 sw
34
+ # serviceWorker: true
35
+ # 是否向所有 HTML 插入注册 sw 的代码
36
+ # auto_register: true
37
+ # 是否生成 DOM 端的 JS 文件并在 HTML 中插入 script
38
+ # gen_dom: true
39
+ # 是否在执行 hexo deploy 时自动执行 swpp 指令
40
+ # auto_exec: false
41
+ # 检查更新的网址,默认 "https://registry.npmjs.org",注意不能以斜杠结尾
36
42
  # npm_url: 'https://registry.npmmirror.com'
43
+ #
44
+ # 排序规则。
45
+ # 该配置项是为了对 hexo 中的一些变量进行排序,避免每次生成 HTML 时由于这些变量的顺序变动导致生成结果不完全相同。
46
+ # 示例:
47
+ # ```yaml
48
+ # # 下面给出的值为插件的缺省值,用户设置该项不会直接覆盖这些值,只有用户也声明 posts、pages 或 tags 时才会覆盖对应的值。
49
+ # swpp:
50
+ # sort_rules:
51
+ # posts: 'title'
52
+ # pages: 'title'
53
+ # tags: 'name'
54
+ # ```
55
+ #
56
+ # 其中 key 值为要排序的变量的名称,value 为变量排序时的依据,
57
+ # 填 false 表示禁用该项排序,填 true 表示以 value 本身为键进行排序,填字符串表示以 value[tag] 为键进行排序。
58
+ # sort_rules:
37
59
  ```
38
60
 
39
61
  插件会在生成网站时自动生成 Service Worker、注册代码、DOM 端支持代码(如果功能开启了的话),版本更新文件需要通过 `hexo swpp` 命令手动生成。
@@ -42,35 +64,23 @@ swpp:
42
64
 
43
65
  ⚠ 注意:
44
66
 
45
- + 如果你的网站启用 `swpp` 后还没有发布过,请勿将 `warn_level` 设置为 0,这会导致构建失败。
46
67
  + 尽可能在压缩网站内容前执行 `hexo swpp`,因为部分压缩插件可能会出现同样的内容连续压缩结果不一样的问题,这会导致插件错误地更新缓存。
47
68
  + 如果你的网站发布过程不使用 `hexo deploy` 指令,则不要启用 `auto_exec` 选项。
48
69
  + 将 `npm_url` 调整为非官方 URL 后检查版本时可能会出现 404 错误。
49
70
 
50
- 插件的具体配置见 [Swpp Backends 官方文档 | 山岳库博](https://kmar.top/posts/b70ec88f/)。
71
+ SWPP v3 的文档尚未完成,敬请期待。
51
72
 
52
- ### sort
73
+ ### 指令
53
74
 
54
- `hexo-swpp` 在规则文件中添加了一个配置项——`sort`,用法如下:
55
-
56
- ```javascript
57
- module.exports.config = {
58
- sort: {
59
- posts: 'title',
60
- pages: 'title',
61
- tags: 'name'
62
- }
63
- }
64
- ```
65
-
66
- 该配置项是为了对 hexo 中的一些变量进行排序,避免每次生成 HTML 时由于这些变量的顺序变动导致生成结果不完全相同。上方代码给出的值为插件的缺省值,用户设置该项不会直接覆盖这些值,只有用户也声明 `posts`、`pages` 或 `tags` 时才会覆盖对应的值。
67
-
68
- 其中 key 值为要排序的变量的名称,value 为变量排序时的依据,填 `false` 表示禁用该项排序,填 `true` 表示以 value 本身为键进行排序,填字符串表示以 `value[tag]` 为键进行排序。
69
-
70
- ---
75
+ 1. `hexo swpp` - 构建 json 文件
76
+ 2. `hexo swpp -b` / `hexo swpp --build` - 构建 json 文件,同 `hexo swpp`
77
+ 3. `hexo swpp -t [URL]` / `hexo swpp --test [URL]` - 尝试拉取指定 URL,使用时将 `[URL]` 替换为有效的 HTTP/HTTPS 链接(需要附带协议头)
71
78
 
72
79
  ## 更新日志
73
80
 
81
+ + 3.4+
82
+ 1. 适配 `swpp-backends@3`
83
+
74
84
  + 3.3+
75
85
  1. 版本检查改为仅在执行 `hexo server` 时执行 \[3.3.0]
76
86
  2. 支持自定义版本更新检查的 URL \[3.3.0]
@@ -79,6 +89,8 @@ module.exports.config = {
79
89
  5. 修复 hexo7 中无法排序 tags 的问题 \[3.3.3]
80
90
  6. 修复 hexo7 中执行 `hexo g` 指令时排序报错的问题 \[3.3.5]
81
91
  7. 修复属性的值不支持使用`in`时报错的问题 \[3.3.6]
92
+ 8. 添加新的指令 \[3.3.7]
93
+ 9. 优化控制台输出 \[3.3.7]
82
94
 
83
95
  + 3.2+
84
96
 
package/dist/index.js CHANGED
@@ -27,12 +27,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const fs = __importStar(require("fs"));
30
- const node_fetch_1 = __importDefault(require("node-fetch"));
31
- const swpp_backends_1 = __importDefault(require("swpp-backends"));
32
30
  const path_1 = __importDefault(require("path"));
31
+ const swpp_backends_1 = require("swpp-backends");
33
32
  const logger = require('hexo-log').default();
34
- // noinspection JSUnusedGlobalSymbols
35
- function start(hexo) {
33
+ const CONSOLE_OPTIONS = [
34
+ { name: '-t, --test', desc: '尝试拉取指定链接' },
35
+ { name: '-b, --build', desc: '构建 swpp,留空参数与使用该参数效果一致' }
36
+ ];
37
+ let runtimeData;
38
+ let compilationData;
39
+ const configLoadWaitList = [];
40
+ /** 等待配置加载 */
41
+ function waitUntilConfig() {
42
+ if (runtimeData)
43
+ return Promise.resolve();
44
+ return new Promise(resolve => configLoadWaitList.push(resolve));
45
+ }
46
+ /** 运行插件 */
47
+ async function start(hexo) {
48
+ // @ts-ignore
49
+ globalThis.hexo = hexo;
36
50
  const config = hexo.config;
37
51
  const pluginConfig = config['swpp'] ?? config.theme_config['swpp'];
38
52
  if (!pluginConfig?.enable)
@@ -40,44 +54,112 @@ function start(hexo) {
40
54
  if (process.argv.find(it => 'server'.startsWith(it)))
41
55
  checkVersion(pluginConfig);
42
56
  let init = false;
43
- hexo.on('generateBefore', () => {
57
+ hexo.on('generateBefore', async () => {
44
58
  if (init)
45
59
  return;
46
60
  init = true;
47
- loadRules(hexo);
48
- sort(hexo);
49
- buildServiceWorker(hexo);
61
+ buildServiceWorker(hexo, pluginConfig);
62
+ sort(hexo, pluginConfig);
63
+ await initRules(hexo, pluginConfig);
64
+ });
65
+ hexo.extend.console.register('swpp', 'Hexo Swpp 的相关指令', {
66
+ options: CONSOLE_OPTIONS
67
+ }, async (args) => {
68
+ const test = args.t ?? args.test;
69
+ // noinspection JSUnresolvedReference
70
+ const build = args.b ?? args.build;
71
+ if (test) {
72
+ if (typeof test == 'boolean' || Array.isArray(test) || !/^(https?):\/\/(\S*?)\.(\S*?)(\S*)$/i.test(test)) {
73
+ logger.error('[SWPP][CONSOLE] --test/-t 后应跟随一个有效 URL');
74
+ }
75
+ else {
76
+ await initRules(hexo, pluginConfig);
77
+ try {
78
+ const response = await compilationData.compilationEnv.read('FETCH_NETWORK_FILE').fetch(test);
79
+ if ([200, 301, 302, 307, 308].includes(response.status)) {
80
+ logger.info('[SWPP][LINK TEST] 资源拉取成功,状态码:' + response.status);
81
+ }
82
+ else {
83
+ logger.warn('[SWPP][LINK TEST] 资源拉取失败,状态码:' + response.status);
84
+ }
85
+ }
86
+ catch (e) {
87
+ logger.warn('[SWPP][LINK TEST] 资源拉取失败', e);
88
+ }
89
+ }
90
+ }
91
+ if (build) {
92
+ if (typeof build !== 'boolean') {
93
+ logger.warn('[SWPP][CONSOLE] -build/-b 后方不应跟随参数');
94
+ }
95
+ }
96
+ if (build || !test) {
97
+ try {
98
+ await runSwpp(hexo, pluginConfig);
99
+ }
100
+ catch (e) {
101
+ logger.error('执行 SWPP 指令时出现异常');
102
+ console.error(e);
103
+ process.exit(-1);
104
+ }
105
+ }
50
106
  });
51
107
  if (pluginConfig['auto_exec']) {
52
108
  hexo.on('deployBefore', async () => {
53
- await runSwpp(hexo, pluginConfig);
109
+ try {
110
+ await runSwpp(hexo, pluginConfig);
111
+ }
112
+ catch (e) {
113
+ logger.error('执行 SWPP 指令时出现异常');
114
+ console.error(e);
115
+ process.exit(-1);
116
+ }
54
117
  });
55
118
  }
56
- else {
57
- hexo.extend.console.register('swpp', '生成前端更新需要的 json 文件及后端使用的版本文件', {}, async () => {
58
- await runSwpp(hexo, pluginConfig);
59
- });
119
+ }
120
+ async function initRules(hexo, pluginConfig) {
121
+ if (!runtimeData) {
122
+ try {
123
+ await loadConfig(hexo, pluginConfig);
124
+ configLoadWaitList.forEach(it => it());
125
+ }
126
+ catch (e) {
127
+ logger.error("[SWPP] 加载时遇到错误。");
128
+ logger.error(e);
129
+ process.exit(0x114514);
130
+ }
60
131
  }
61
132
  }
133
+ /** 运行 swpp 指令 */
62
134
  async function runSwpp(hexo, pluginConfig) {
63
135
  const config = hexo.config;
64
136
  if (!fs.existsSync(config.public_dir))
65
137
  return logger.warn(`[SWPP] 未检测到发布目录,跳过指令执行`);
66
- const rules = loadRules(hexo);
67
- if (!rules.config.json)
68
- return logger.error(`[SWPP] JSON 生成功能未开启,跳过指令执行`);
69
- const url = config.url;
70
- await Promise.all([
71
- swpp_backends_1.default.loader.loadUpdateJson(url + '/update.json', pluginConfig['warn_level'] ?? 1),
72
- swpp_backends_1.default.loader.loadVersionJson(url + '/cacheList.json', pluginConfig['warn_level'] ?? 1)
138
+ await initRules(hexo, pluginConfig);
139
+ const scanner = new swpp_backends_1.ResourcesScanner(compilationData);
140
+ const versionFile = compilationData.compilationEnv.read('SWPP_JSON_FILE');
141
+ const tracker = await scanner.scanLocalFile(config.public_dir);
142
+ const jsonBuilder = await tracker.diff();
143
+ function writeFile(path, content) {
144
+ return new Promise((resolve, reject) => {
145
+ fs.writeFile(path, content, 'utf-8', (err) => {
146
+ if (err)
147
+ reject(err);
148
+ else
149
+ resolve();
150
+ });
151
+ });
152
+ }
153
+ const json = await jsonBuilder.buildJson();
154
+ return Promise.all([
155
+ writeFile(path_1.default.join(hexo.config.public_dir, versionFile.versionPath), JSON.stringify(json)),
156
+ writeFile(path_1.default.join(hexo.config.public_dir, versionFile.trackerPath), tracker.json())
73
157
  ]);
74
- await buildVersionJson(hexo);
75
- const dif = swpp_backends_1.default.builder.analyzeVersion();
76
- await buildUpdateJson(hexo, dif);
77
158
  }
159
+ /** 检查 swpp-backends 的版本 */
78
160
  function checkVersion(pluginConfig) {
79
161
  const root = pluginConfig['npm_url'] ?? 'https://registry.npmjs.org';
80
- (0, node_fetch_1.default)(`${root}/swpp-backends/${swpp_backends_1.default.version}`)
162
+ fetch(`${root}/swpp-backends/${swpp_backends_1.swppVersion}`)
81
163
  .then(response => {
82
164
  if (![200, 301, 302, 307, 308].includes(response.status))
83
165
  return Promise.reject(response.status);
@@ -86,93 +168,89 @@ function checkVersion(pluginConfig) {
86
168
  if ('error' in json)
87
169
  return Promise.reject(json.error);
88
170
  if ('deprecated' in json) {
89
- logger.error(`[SWPP VersionChecker] 您使用的 swpp-backends@${swpp_backends_1.default.version} 已被弃用,请更新版本!`);
90
- logger.error(`\t补充信息:${json['deprecated']}`);
171
+ logger.warn(`[SWPP][VersionChecker] 您使用的 swpp-backends@${swpp_backends_1.swppVersion} 已被弃用,请更新版本!`);
172
+ logger.warn(`\t补充信息:${json['deprecated']}`);
173
+ logger.warn('请注意!!!当您看到这条消息时,表明您正在使用的后台版本存在漏洞,请务必更新版本!!!');
174
+ logger.info('可以使用 `npm update swpp-backends` 更新后台版本,或使用您自己常用的等效命令。');
91
175
  }
92
176
  else {
93
- logger.info('[SWPP VersionChecker] 版本检查通过,注意定期检查版本更新。');
177
+ logger.info('[SWPP VersionChecker] 版本检查通成功,您使用的版本目前没有被废弃,注意定期检查版本更新。');
94
178
  }
95
179
  }).catch(err => {
96
180
  const isSimple = ['number', 'string'].includes(typeof err);
97
- logger.warn(`[SWPP VersionChecker] 版本检查失败${isSimple ? ('(' + err + ')') : ''}`);
181
+ logger.warn(`[SWPP][VersionChecker] 版本检查失败${isSimple ? ('(' + err + ')') : ''}`);
98
182
  if (!isSimple)
99
183
  logger.warn(err);
100
184
  });
101
185
  }
102
- function loadRules(hexo) {
186
+ /** 加载配置文件 */
187
+ async function loadConfig(hexo, pluginConfig) {
103
188
  const themeName = hexo.config.theme;
104
- swpp_backends_1.default.event.addRulesMapEvent(rules => {
105
- if ('cacheList' in rules && !('cacheRules' in rules)) {
106
- rules.cacheRules = rules['cacheList'];
107
- delete rules['cacheList'];
108
- }
109
- if ('getCdnList' in rules && !('getRaceUrls' in rules)) {
110
- rules.getRaceUrls = rules['getCdnList'];
111
- delete rules['getCdnList'];
189
+ const loader = new swpp_backends_1.ConfigLoader();
190
+ loader.loadFromCode({
191
+ compilationEnv: {
192
+ DOMAIN_HOST: new URL(hexo.config.root, hexo.config.url)
112
193
  }
113
194
  });
114
- const result = swpp_backends_1.default.loader.loadRules('./', 'sw-rules', [`./themes/${themeName}/`, `./node_modules/hexo-${themeName}/`]);
115
- swpp_backends_1.default.builder.calcEjectValues(hexo);
116
- return result;
117
- }
118
- async function buildUpdateJson(hexo, dif) {
119
- const url = hexo.config.url;
120
- const json = swpp_backends_1.default.builder.buildUpdateJson(url, dif);
121
- fs.writeFileSync(`${hexo.config.public_dir}/update.json`, JSON.stringify(json), 'utf-8');
122
- logger.info('成功生成:update.json');
123
- }
124
- async function buildVersionJson(hexo) {
125
- const url = hexo.config.url;
126
- let protocol, domain;
127
- if (url.startsWith('https:')) {
128
- protocol = 'https://';
129
- }
130
- else {
131
- protocol = 'http://';
195
+ const configName = pluginConfig['config_name'] ?? 'swpp.config';
196
+ const configPaths = [configName, `./themes/${themeName}/${configName}`, `./node_modules/hexo-${themeName}/${configName}`];
197
+ const extnameList = ['ts', 'cts', 'mts', 'js', 'cjs', 'mjs'];
198
+ for (let path of configPaths) {
199
+ for (let extname of extnameList) {
200
+ const uri = `${path}.${extname}`;
201
+ if (fs.existsSync(uri)) {
202
+ await loader.load(path_1.default.resolve(uri));
203
+ break;
204
+ }
205
+ }
132
206
  }
133
- domain = url.substring(protocol.length, url.endsWith('/') ? url.length - 1 : url.length);
134
- // @ts-ignore
135
- const json = await swpp_backends_1.default.builder.buildVersionJson(protocol, domain, path_1.default.resolve('./', hexo.config.public_dir));
136
- fs.writeFileSync(`${hexo.config.public_dir}/cacheList.json`, JSON.stringify(json), 'utf-8');
137
- logger.info('成功生成:cacheList.json');
207
+ const result = loader.generate();
208
+ runtimeData = result.runtime;
209
+ compilationData = result.compilation;
138
210
  }
139
- function buildServiceWorker(hexo) {
140
- const rules = swpp_backends_1.default.cache.readRules();
141
- const pluginConfig = rules.config;
211
+ /** 注册生成器 */
212
+ function buildServiceWorker(hexo, hexoConfig) {
213
+ const { serviceWorker, auto_register, gen_dom } = hexoConfig;
142
214
  // 生成 sw
143
- if (pluginConfig.serviceWorker) {
144
- hexo.extend.generator.register('build_service_worker', () => {
145
- return {
146
- path: 'sw.js',
147
- data: swpp_backends_1.default.builder.buildServiceWorker()
148
- };
215
+ if (serviceWorker ?? true) {
216
+ hexo.extend.generator.register('build_service_worker', async () => {
217
+ await waitUntilConfig();
218
+ return ({
219
+ path: compilationData.compilationEnv.read('SERVICE_WORKER') + '.js',
220
+ data: new swpp_backends_1.SwCompiler().buildSwCode(runtimeData)
221
+ });
149
222
  });
150
223
  }
151
224
  // 生成注册 sw 的代码
152
- if (pluginConfig.register) {
153
- hexo.extend.injector.register('head_begin', () => pluginConfig.register.builder(hexo.config.url, hexo, pluginConfig));
225
+ if (auto_register ?? true) {
226
+ waitUntilConfig().then(() => {
227
+ hexo.extend.injector.register('head_begin', `<script>(${runtimeData.domConfig.read('registry')})()</script>`);
228
+ });
154
229
  }
155
230
  // 生成 sw-dom.js
156
- if (pluginConfig.dom) {
157
- // noinspection HtmlUnknownTarget
158
- hexo.extend.injector.register('head_end', `<script defer src="/sw-dom.js"></script>`);
159
- hexo.extend.generator.register('build_dom_js', () => {
231
+ if (gen_dom ?? true) {
232
+ hexo.extend.injector.register('head_end', () => {
233
+ // noinspection HtmlUnknownTarget
234
+ return `<script defer src="/sw-dom.js"></script>`;
235
+ });
236
+ hexo.extend.generator.register('build_dom_js', async () => {
237
+ await waitUntilConfig();
160
238
  return {
161
239
  path: 'sw-dom.js',
162
- data: swpp_backends_1.default.builder.buildDomJs()
240
+ data: runtimeData.domConfig.buildJsSource()
163
241
  };
164
242
  });
165
243
  }
166
244
  }
167
245
  /** 对 hexo 中的变量进行排序 */
168
- function sort(hexo) {
246
+ function sort(hexo, pluginConfig) {
169
247
  const version = hexo.version;
170
248
  let Locals;
171
249
  if (version.startsWith('7')) {
172
- Locals = require(path_1.default.resolve('./', 'node_modules/hexo/dist/hexo/locals')).prototype;
250
+ Locals = require(path_1.default.resolve('node_modules/hexo/dist/hexo/locals')).prototype;
173
251
  }
174
252
  else {
175
- Locals = require(path_1.default.resolve('./', 'node_modules/hexo/lib/hexo/locals')).prototype;
253
+ Locals = require(path_1.default.resolve('node_modules/hexo/lib/hexo/locals')).prototype;
176
254
  }
177
255
  const compare = (a, b) => {
178
256
  const result = a.length === b.length ? a < b : a.length < b.length;
@@ -229,8 +307,7 @@ function sort(hexo) {
229
307
  pages: 'title',
230
308
  tags: 'name'
231
309
  };
232
- // @ts-ignore
233
- Object.assign(list, swpp_backends_1.default.cache.readRules().config['sort'] ?? {});
310
+ Object.assign(list, pluginConfig.sort_rules ?? {});
234
311
  const getter = Locals.get;
235
312
  Locals.get = function (name) {
236
313
  const result = getter.call(this, name);
@@ -245,13 +322,8 @@ function sort(hexo) {
245
322
  return result;
246
323
  };
247
324
  }
248
- try {
249
- // noinspection TypeScriptUnresolvedReference
250
- // @ts-ignore
251
- start(hexo);
252
- }
253
- catch (e) {
254
- logger.error("[SWPP] 加载时遇到错误,可能是由于缺少规则文件。");
325
+ start(hexo).catch(e => {
326
+ logger.error("[SWPP] 加载时遇到严重错误!");
255
327
  logger.error(e);
256
- process.exit(114514);
257
- }
328
+ process.exit(0x19491001);
329
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-swpp",
3
- "version": "3.3.6",
3
+ "version": "3.4.0-alpha.110",
4
4
  "main": "dist/index.js",
5
5
  "types": "types/index.d.ts",
6
6
  "files": [
@@ -22,17 +22,15 @@
22
22
  },
23
23
  "homepage": "https://kmar.top/posts/73014407/",
24
24
  "devDependencies": {
25
- "@types/node": "^20.4.7",
26
- "@types/node-fetch": "^2.6.4",
27
- "hexo": "7.0.0",
28
- "typescript": "^5.1.6"
25
+ "@types/node": "^22.0.2",
26
+ "hexo": "^7.3.0",
27
+ "typescript": "^5.5.4"
29
28
  },
30
29
  "dependencies": {
31
- "hexo-log": "^4.1.0",
32
- "node-fetch": "^2.6.12"
30
+ "hexo-log": "^4.1.0"
33
31
  },
34
32
  "peerDependencies": {
35
- "swpp-backends": "^2.1.2"
33
+ "swpp-backends": "^3.0.0-ahpla.100"
36
34
  },
37
35
  "scripts": {}
38
36
  }