hexo-swpp 2.8.9 → 3.0.0-alpha
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 +1 -11
- package/dist/index.js +193 -0
- package/package.json +33 -34
- package/types/index.d.ts +7 -0
- package/index.js +0 -59
- package/lib/configLoader.js +0 -236
- package/lib/jsonBuilder.js +0 -531
- package/lib/sort.js +0 -35
- package/lib/sw-dom.js +0 -51
- package/lib/sw-template.js +0 -265
- package/lib/swBuilder.js +0 -193
- package/lib/utils.js +0 -50
package/README.md
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
1
|
  该插件用于在 hexo 中自动构建可用的 ServiceWorker,插件内自带了一个缺省的 sw.js,也支持使用自定义的 sw。
|
|
2
2
|
|
|
3
|
-
 &emsp
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
  插件版本:A.B.C:
|
|
8
|
-
|
|
9
|
-
+ A:重大功能更新时变化
|
|
10
|
-
+ B:修改配置文件或功能更新时变化
|
|
11
|
-
+ C:BUG 修复时变化
|
|
12
|
-
|
|
13
|
-
  所以 C 修改时务必更新版本,A、B 修改时可酌情追更,由于本人不会维护旧版本的代码,所以仍然建议使用最新版本的插件。
|
|
3
|
+
  三代版本仍在开发中,有兴趣的可以先看一看 v2 分支。
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const fs = __importStar(require("fs"));
|
|
30
|
+
const swpp_backends_1 = __importDefault(require("swpp-backends"));
|
|
31
|
+
const path_1 = __importDefault(require("path"));
|
|
32
|
+
const logger = require('hexo-log').default();
|
|
33
|
+
// noinspection JSUnusedGlobalSymbols
|
|
34
|
+
function start(hexo) {
|
|
35
|
+
const { config } = hexo;
|
|
36
|
+
if (!(config['swpp']?.enable || hexo.theme.config['swpp']?.enable))
|
|
37
|
+
return;
|
|
38
|
+
const themeName = config.theme;
|
|
39
|
+
swpp_backends_1.default.event.addRulesMapEvent(rules => {
|
|
40
|
+
if ('cacheList' in rules && !('cacheRules' in rules)) {
|
|
41
|
+
rules.cacheRules = rules['cacheList'];
|
|
42
|
+
delete rules['cacheList'];
|
|
43
|
+
}
|
|
44
|
+
if ('getCdnList' in rules && !('getRaceUrls' in rules)) {
|
|
45
|
+
rules.getRaceUrls = rules['getCdnList'];
|
|
46
|
+
delete rules['getCdnList'];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const rules = swpp_backends_1.default.loader.loadRules('./', 'sw-rules', [`./themes/${themeName}/`, `./node_modules/hexo-${themeName}/`]);
|
|
50
|
+
swpp_backends_1.default.builder.calcEjectValues(hexo);
|
|
51
|
+
sort(hexo);
|
|
52
|
+
buildServiceWorker(hexo);
|
|
53
|
+
if (rules.config.json) {
|
|
54
|
+
hexo.extend.console.register('swpp', '生成前端更新需要的 json 文件及后端使用的版本文件', {}, async () => {
|
|
55
|
+
if (!fs.existsSync(hexo.config.public_dir))
|
|
56
|
+
return logger.warn(`[SWPP] 未检测到发布目录,跳过指令执行`);
|
|
57
|
+
const url = hexo.config.url;
|
|
58
|
+
await swpp_backends_1.default.loader.loadUpdateJson(url + '/update.json');
|
|
59
|
+
const versionJson = await swpp_backends_1.default.loader.loadVersionJson(url + '/cacheList.json');
|
|
60
|
+
let forceRefreshCache = false;
|
|
61
|
+
if ('update' in rules) {
|
|
62
|
+
const update = rules.update;
|
|
63
|
+
const { flag, change, refresh, force } = update;
|
|
64
|
+
if (!flag) {
|
|
65
|
+
logger.error(`[SWPP Console] 规则文件的 update 项目必须包含 flag 值!`);
|
|
66
|
+
throw 'update.flag 缺失';
|
|
67
|
+
}
|
|
68
|
+
swpp_backends_1.default.event.submitCacheInfo({ updateFlag: flag });
|
|
69
|
+
if (flag !== versionJson.external.flag) {
|
|
70
|
+
if (change)
|
|
71
|
+
swpp_backends_1.default.event.submitChange(...change);
|
|
72
|
+
if (refresh)
|
|
73
|
+
refresh.forEach(swpp_backends_1.default.event.refreshUrl);
|
|
74
|
+
if (force)
|
|
75
|
+
forceRefreshCache = true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
await buildVersionJson(hexo);
|
|
79
|
+
const dif = swpp_backends_1.default.builder.analyze(swpp_backends_1.default.cache.readNewVersionJson());
|
|
80
|
+
if (forceRefreshCache)
|
|
81
|
+
dif.force = true;
|
|
82
|
+
await buildUpdateJson(hexo, dif);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function buildUpdateJson(hexo, dif) {
|
|
87
|
+
const url = hexo.config.url;
|
|
88
|
+
const json = swpp_backends_1.default.builder.buildNewInfo(url, dif);
|
|
89
|
+
fs.writeFileSync(`${hexo.config.public_dir}/update.json`, JSON.stringify(json), 'utf-8');
|
|
90
|
+
}
|
|
91
|
+
async function buildVersionJson(hexo) {
|
|
92
|
+
const url = hexo.config.url;
|
|
93
|
+
let protocol, domain;
|
|
94
|
+
if (url.startsWith('https:')) {
|
|
95
|
+
protocol = 'https://';
|
|
96
|
+
domain = url.substring(protocol.length + 1);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
protocol = 'http://';
|
|
100
|
+
domain = url.substring(protocol.length + 1);
|
|
101
|
+
}
|
|
102
|
+
// @ts-ignore
|
|
103
|
+
const json = await swpp_backends_1.default.builder.buildVersionJson(protocol, domain, path_1.default.resolve('./', hexo.config.public_dir));
|
|
104
|
+
fs.writeFileSync(`${hexo.config.public_dir}/cacheList.json`, JSON.stringify(json), 'utf-8');
|
|
105
|
+
}
|
|
106
|
+
function buildServiceWorker(hexo) {
|
|
107
|
+
const rules = swpp_backends_1.default.cache.readRules();
|
|
108
|
+
const pluginConfig = rules.config;
|
|
109
|
+
// 生成 sw
|
|
110
|
+
if (pluginConfig.serviceWorker) {
|
|
111
|
+
hexo.extend.generator.register('build_service_worker', () => {
|
|
112
|
+
return {
|
|
113
|
+
path: 'sw.js',
|
|
114
|
+
data: swpp_backends_1.default.builder.buildServiceWorker()
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// 生成注册 sw 的代码
|
|
119
|
+
if (pluginConfig.register) {
|
|
120
|
+
hexo.extend.injector.register('head_begin', () => pluginConfig.register.builder(hexo.config.url, hexo, pluginConfig));
|
|
121
|
+
}
|
|
122
|
+
// 生成 sw-dom.js
|
|
123
|
+
if (pluginConfig.dom) {
|
|
124
|
+
// noinspection HtmlUnknownTarget
|
|
125
|
+
hexo.extend.injector.register('body_begin', () => `<script src="/sw-dom.js"></script>`);
|
|
126
|
+
hexo.extend.generator.register('build_dom_js', () => {
|
|
127
|
+
const template = fs.readFileSync(path_1.default.resolve('./', 'node_modules/swpp-backends/dist/resources/sw-dom.js'), 'utf-8').replaceAll(`// \${onSuccess}`, `(${pluginConfig.dom.onsuccess.toString()})()`);
|
|
128
|
+
return {
|
|
129
|
+
path: 'sw-dom.js',
|
|
130
|
+
data: template
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** 对 hexo 中的变量进行排序 */
|
|
136
|
+
function sort(hexo) {
|
|
137
|
+
const version = hexo.version;
|
|
138
|
+
let Locals;
|
|
139
|
+
if (version.startsWith('7')) {
|
|
140
|
+
Locals = require(path_1.default.resolve('./', 'node_modules/hexo/dist/hexo/locals')).prototype;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
Locals = require(path_1.default.resolve('./', 'node_modules/hexo/lib/hexo/locals')).prototype;
|
|
144
|
+
}
|
|
145
|
+
const compare = (a, b) => {
|
|
146
|
+
const result = a.length === b.length ? a < b : a.length < b.length;
|
|
147
|
+
return result ? -1 : 1;
|
|
148
|
+
};
|
|
149
|
+
const sort = (obj, value) => {
|
|
150
|
+
if (!obj)
|
|
151
|
+
return;
|
|
152
|
+
const target = obj.data ?? obj;
|
|
153
|
+
if (!target.sort)
|
|
154
|
+
return;
|
|
155
|
+
if (typeof value === 'boolean') {
|
|
156
|
+
if (value)
|
|
157
|
+
target.sort(compare);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
target.sort((a, b) => compare(a[value], b[value]));
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const list = {
|
|
164
|
+
posts: 'title',
|
|
165
|
+
pages: 'title',
|
|
166
|
+
tags: 'name'
|
|
167
|
+
};
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
Object.assign(list, swpp_backends_1.default.cache.readRules().config['sort']);
|
|
170
|
+
const getter = Locals.get;
|
|
171
|
+
Locals.get = function (name) {
|
|
172
|
+
const result = getter.call(this, name);
|
|
173
|
+
if (name in list)
|
|
174
|
+
sort(result, list[name]);
|
|
175
|
+
if ('forEach' in result) {
|
|
176
|
+
result.forEach((it) => {
|
|
177
|
+
for (let tag in list)
|
|
178
|
+
sort(it[tag], list[tag]);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return result;
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
// noinspection TypeScriptUnresolvedReference
|
|
186
|
+
// @ts-ignore
|
|
187
|
+
start(hexo);
|
|
188
|
+
}
|
|
189
|
+
catch (e) {
|
|
190
|
+
logger.error("[SWPP] 加载时遇到错误,可能是由于缺少规则文件。");
|
|
191
|
+
logger.error(e);
|
|
192
|
+
process.exit(114514);
|
|
193
|
+
}
|
package/package.json
CHANGED
|
@@ -1,35 +1,34 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "hexo-swpp",
|
|
3
|
-
"version": "
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
"homepage": "https://kmar.top/posts/73014407/"
|
|
1
|
+
{
|
|
2
|
+
"name": "hexo-swpp",
|
|
3
|
+
"version": "3.0.0-alpha",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "types/index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"types"
|
|
9
|
+
],
|
|
10
|
+
"keywords": [
|
|
11
|
+
"hexo",
|
|
12
|
+
"sw",
|
|
13
|
+
"ServiceWorker",
|
|
14
|
+
"json",
|
|
15
|
+
"auto"
|
|
16
|
+
],
|
|
17
|
+
"author": "kmar",
|
|
18
|
+
"license": "AGPL-3.0",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/EmptyDreams/hexo-swpp.git"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://kmar.top/posts/73014407/",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^20.4.7",
|
|
26
|
+
"hexo": "7.0.0-rc2",
|
|
27
|
+
"typescript": "^5.1.6"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"hexo-log": "^4.1.0",
|
|
31
|
+
"swpp-backends": "0.0.5-alpha"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {}
|
|
35
34
|
}
|
package/types/index.d.ts
ADDED
package/index.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// noinspection JSUnresolvedVariable
|
|
2
|
-
|
|
3
|
-
"use strict"
|
|
4
|
-
|
|
5
|
-
const config = hexo.config
|
|
6
|
-
const enable = (config.swpp ?? hexo.theme.config.swpp)?.enable
|
|
7
|
-
|
|
8
|
-
if (enable) {
|
|
9
|
-
try {
|
|
10
|
-
const configLoader = require('./lib/configLoader')
|
|
11
|
-
const rules = configLoader.load(hexo)
|
|
12
|
-
const ejectValues = calcEjectValues(hexo, rules)
|
|
13
|
-
// 排序
|
|
14
|
-
require('./lib/sort')(rules.config)
|
|
15
|
-
// 生成 update.json
|
|
16
|
-
require('./lib/jsonBuilder')(hexo, config, rules, ejectValues?.obj)
|
|
17
|
-
// 生成 sw.js
|
|
18
|
-
require('./lib/swBuilder')(hexo, config, rules, ejectValues?.str)
|
|
19
|
-
} catch (e) {
|
|
20
|
-
const logger = require('hexo-log')()
|
|
21
|
-
logger.error('[SWPP Index] 加载过程中遇到了错误:')
|
|
22
|
-
process.exit(114514)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 计算导出的键值表
|
|
28
|
-
* @param hexo
|
|
29
|
-
* @param rules
|
|
30
|
-
* @return {?{str: string, obj: *}}
|
|
31
|
-
*/
|
|
32
|
-
function calcEjectValues(hexo, rules) {
|
|
33
|
-
if (!('ejectValues' in rules)) return null
|
|
34
|
-
const { getSource } = require('./lib/utils')
|
|
35
|
-
const obj = rules.ejectValues(hexo, rules)
|
|
36
|
-
const nodeObj = {}
|
|
37
|
-
let result = ''
|
|
38
|
-
for (let key in obj) {
|
|
39
|
-
if (!key.match(/^[A-Za-z0-9]+$/)) {
|
|
40
|
-
logger.error(`[SWPP EjectValues] 变量名 [${key}] 仅允许包含英文字母和阿拉伯数字!`)
|
|
41
|
-
throw "变量名异常:" + key
|
|
42
|
-
}
|
|
43
|
-
const data = obj[key]
|
|
44
|
-
const type = typeof data.value
|
|
45
|
-
nodeObj[key] = data.value
|
|
46
|
-
switch (type) {
|
|
47
|
-
case 'undefined': break
|
|
48
|
-
case 'boolean': case 'number': case 'string': case 'bigint':
|
|
49
|
-
result += ` ${data.prefix} eject${key[0].toUpperCase()}${key.substring(1)} = ${getSource(data.value)}`
|
|
50
|
-
break
|
|
51
|
-
default:
|
|
52
|
-
logger.error(`[SWPP EjectValues] 不支持导出 ${type} 类型的数据。`)
|
|
53
|
-
throw `不支持的键值:key=${key}, value type=${type}`
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return {
|
|
57
|
-
obj: nodeObj, str: result
|
|
58
|
-
}
|
|
59
|
-
}
|
package/lib/configLoader.js
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
// 配置加载器
|
|
2
|
-
|
|
3
|
-
const logger = require('hexo-log')()
|
|
4
|
-
|
|
5
|
-
// 加载 sw-rules.js
|
|
6
|
-
module.exports.load = hexo => {
|
|
7
|
-
const rules = loadRules(hexo)
|
|
8
|
-
const handle = (obj, def, list) => {
|
|
9
|
-
for (let key in def) {
|
|
10
|
-
const defValue = def[key]
|
|
11
|
-
const value = obj[key]
|
|
12
|
-
switch (typeof value) {
|
|
13
|
-
case 'undefined':
|
|
14
|
-
obj[key] = defValue
|
|
15
|
-
break
|
|
16
|
-
case 'object':
|
|
17
|
-
const defA = Array.isArray(defValue)
|
|
18
|
-
const objA = Array.isArray(value)
|
|
19
|
-
if (defA !== objA) {
|
|
20
|
-
logger.error(`[ConfigLoader] ${list.join('.')} 值与标准值类型不相同!已经使用默认配置项替代。`)
|
|
21
|
-
obj[key] = defValue
|
|
22
|
-
break
|
|
23
|
-
}
|
|
24
|
-
if (!defA) {
|
|
25
|
-
list.push(key)
|
|
26
|
-
handle(value, defValue, list)
|
|
27
|
-
list.pop()
|
|
28
|
-
}
|
|
29
|
-
break
|
|
30
|
-
case 'boolean':
|
|
31
|
-
break
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (!('config' in rules)) {
|
|
36
|
-
logger.error("[ConfigLoader] 未在 sw-rules.js 中查询到配置项!")
|
|
37
|
-
throw '配置项缺失!'
|
|
38
|
-
}
|
|
39
|
-
handle(rules.config, defConfig, [])
|
|
40
|
-
return rules
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 存储缺省配置
|
|
44
|
-
const defConfig = {
|
|
45
|
-
// sw 有关配置项
|
|
46
|
-
serviceWorker: {
|
|
47
|
-
/**
|
|
48
|
-
* 逃生门
|
|
49
|
-
* @type number
|
|
50
|
-
* @see https://kmar.top/posts/73014407/#6c7c33f0
|
|
51
|
-
*/
|
|
52
|
-
escape: 0,
|
|
53
|
-
/**
|
|
54
|
-
* 缓存库名称
|
|
55
|
-
* 发布网站后 **切勿修改** 该配置项!
|
|
56
|
-
* @type string
|
|
57
|
-
*/
|
|
58
|
-
cacheName: 'kmarBlogCache',
|
|
59
|
-
/**
|
|
60
|
-
* 是否启用调试,启用后会在 sw 中插入一些辅助调试的代码,不建议开启
|
|
61
|
-
* @type boolean
|
|
62
|
-
*/
|
|
63
|
-
debug: false
|
|
64
|
-
},
|
|
65
|
-
// 与 SW 注册有关的配置项
|
|
66
|
-
register: {
|
|
67
|
-
/**
|
|
68
|
-
* sw 注册成功时的动作
|
|
69
|
-
* @type ?VoidFunction
|
|
70
|
-
* */
|
|
71
|
-
onsuccess: undefined,
|
|
72
|
-
/**
|
|
73
|
-
* sw 注册失败时的动作
|
|
74
|
-
* @type ?VoidFunction
|
|
75
|
-
*/
|
|
76
|
-
onerror: undefined,
|
|
77
|
-
/**
|
|
78
|
-
* 生成注册 SW 的 HTML 代码片段
|
|
79
|
-
* @param root {string} 网页根目录的 URL
|
|
80
|
-
* @param hexoConfig {Object} Hexo 配置项
|
|
81
|
-
* @param pluginConfig {Object} SW 配置项
|
|
82
|
-
* @return {string} 一个 HTML 标签的字符串形式
|
|
83
|
-
*/
|
|
84
|
-
builder: (root, hexoConfig, pluginConfig) => {
|
|
85
|
-
const {onerror, onsuccess} = pluginConfig.register
|
|
86
|
-
return `<script>
|
|
87
|
-
(() => {
|
|
88
|
-
const sw = navigator.serviceWorker
|
|
89
|
-
const error = ${onerror.toString()}
|
|
90
|
-
if (!sw?.register('${new URL(root).pathname}sw.js')
|
|
91
|
-
${onsuccess ? '?.then(' + onsuccess + ')' : ''}
|
|
92
|
-
?.catch(error)
|
|
93
|
-
) error()
|
|
94
|
-
})()
|
|
95
|
-
</script>`
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
// 与 DOM 端有关的配置项
|
|
99
|
-
dom: {
|
|
100
|
-
/**
|
|
101
|
-
* 版本更新完成后的动作
|
|
102
|
-
* @type VoidFunction
|
|
103
|
-
*/
|
|
104
|
-
onsuccess: () => {}
|
|
105
|
-
},
|
|
106
|
-
/**
|
|
107
|
-
* 与插件生成的版本文件相关的配置项
|
|
108
|
-
* 该功能目前无法关闭
|
|
109
|
-
*/
|
|
110
|
-
json: {
|
|
111
|
-
/**
|
|
112
|
-
* 更新缓存时允许更新的最大 HTML 页面数量,需要更新的 HTML 文件数量超过这个值后会清除所有 HTML 缓存
|
|
113
|
-
* @type number
|
|
114
|
-
*/
|
|
115
|
-
maxHtml: 15,
|
|
116
|
-
/**
|
|
117
|
-
* 版本文件(update.json)字符数量限制,插件将保证版本文件的字符数量不超过该值
|
|
118
|
-
* @type number
|
|
119
|
-
*/
|
|
120
|
-
charLimit: 1024,
|
|
121
|
-
/**
|
|
122
|
-
* 文件缓存匹配采取精确模式
|
|
123
|
-
* 关闭时更新缓存时仅匹配文件名称,如 https://kmar.top/simple/a/index.html 仅匹配 /a/index.html
|
|
124
|
-
* 开启后更新缓存时将会匹配完整名称,如 https://kmar.top/simple/a/index.html 将匹配 /simple/a/index.html
|
|
125
|
-
* 两种方式各有优劣,开启后会增加 update.json 的空间占用,但会提升精确度
|
|
126
|
-
* 如果网站内没有多级目录结构,就可以放心大胆的关闭了
|
|
127
|
-
* key 值为文件拓展名,default 用于指代所有未列出的拓展名以及没有拓展名的文件
|
|
128
|
-
*/
|
|
129
|
-
precisionMode: {
|
|
130
|
-
default: false
|
|
131
|
-
},
|
|
132
|
-
/**
|
|
133
|
-
* 是否合并指定项目
|
|
134
|
-
* 例如当 tags 为 true 时(假设标签目录为 https://kmar.top/tags/...)
|
|
135
|
-
* 如果标签页存在更新,则直接匹配 https://kmar.top/tags/ 目录下的所有文件
|
|
136
|
-
* **推荐将此项开启**
|
|
137
|
-
*/
|
|
138
|
-
merge: {
|
|
139
|
-
index: true,
|
|
140
|
-
tags: true,
|
|
141
|
-
archives: true,
|
|
142
|
-
categories: true,
|
|
143
|
-
/**
|
|
144
|
-
* 这里填写目录名称列表(不带两边的斜杠)
|
|
145
|
-
* @type string[]
|
|
146
|
-
*/
|
|
147
|
-
custom: []
|
|
148
|
-
},
|
|
149
|
-
/**
|
|
150
|
-
* 生成版本文件时忽略的文件
|
|
151
|
-
* 注:匹配的时候不附带域名,只有 pathname,匹配的内容一定是博客本地的文件
|
|
152
|
-
* @type RegExp[]
|
|
153
|
-
*/
|
|
154
|
-
exclude: [
|
|
155
|
-
/sw\.js$/
|
|
156
|
-
]
|
|
157
|
-
},
|
|
158
|
-
/**
|
|
159
|
-
* 外部文件更新监听
|
|
160
|
-
* @see https://kmar.top/posts/73014407/#c60b3060
|
|
161
|
-
*/
|
|
162
|
-
external: {
|
|
163
|
-
/**
|
|
164
|
-
* 拉取网络文件时的超时时间
|
|
165
|
-
* @type number
|
|
166
|
-
*/
|
|
167
|
-
timeout: 1500,
|
|
168
|
-
/**
|
|
169
|
-
* 匹配 JS 代码中的 URL
|
|
170
|
-
* @see https://kmar.top/posts/73014407/#c60b3060
|
|
171
|
-
*/
|
|
172
|
-
js: [],
|
|
173
|
-
/**
|
|
174
|
-
* 某些外链只要 URL 不变其内容就一定不会变
|
|
175
|
-
* 可以通过正则表达式排除这些外链的文件内容监控,加快构建速度
|
|
176
|
-
* 注意:当某一个文件被跳过拉取后,这个文件中包含的 URL 也会被跳过
|
|
177
|
-
* @type RegExp[]
|
|
178
|
-
*/
|
|
179
|
-
skip: [],
|
|
180
|
-
/**
|
|
181
|
-
* 在构建过程中替换部分链接,该替换结果不会影响文件内容
|
|
182
|
-
* 该设置项是为了应对构建服务器在国外,但是网站内部分缓存资源无法在国外访问导致拉取时超时的问题
|
|
183
|
-
* @type Object[]
|
|
184
|
-
* @see https://kmar.top/posts/73014407/#4ea71e00
|
|
185
|
-
*/
|
|
186
|
-
replace: []
|
|
187
|
-
},
|
|
188
|
-
/**
|
|
189
|
-
* 对 Hexo 中的变量进行排序
|
|
190
|
-
* 默认插件对 posts、tags、categories、pages 四个变量进行排序
|
|
191
|
-
* 排序规则为优先按照字符串长度排序,若长度一致按照字典序排序
|
|
192
|
-
*/
|
|
193
|
-
sort: {}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// 加载 sw-rules.js 文件
|
|
197
|
-
const loadRules = hexo => {
|
|
198
|
-
// noinspection JSUnresolvedReference
|
|
199
|
-
const themeName = hexo.config.theme
|
|
200
|
-
// noinspection JSUnresolvedReference
|
|
201
|
-
const rulesFileName = (hexo.config.swpp?.rules ?? hexo.theme.config.swpp?.rules) ?? 'sw-rules'
|
|
202
|
-
const nodePath = require('path')
|
|
203
|
-
const fs = require('fs')
|
|
204
|
-
const rootList = ['./', `./themes/${themeName}/`, `./node_modules/hexo-theme-${themeName}/`]
|
|
205
|
-
const fileNameList = [`${rulesFileName}.cjs`, `${rulesFileName}.js`]
|
|
206
|
-
|
|
207
|
-
/** 尝试在指定目录下查询 rules 文件 */
|
|
208
|
-
function findRules(root) {
|
|
209
|
-
for (let name of fileNameList) {
|
|
210
|
-
const path = nodePath.resolve(root, name)
|
|
211
|
-
if (fs.existsSync(path))
|
|
212
|
-
return path
|
|
213
|
-
}
|
|
214
|
-
return null
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const paths = {
|
|
218
|
-
root: findRules(rootList[0]),
|
|
219
|
-
themes: findRules(rootList[1]),
|
|
220
|
-
modules: findRules(rootList[2])
|
|
221
|
-
}
|
|
222
|
-
if (!(paths.root || paths.themes || paths.modules)) {
|
|
223
|
-
const tip = "未找到 sw-rules 文件"
|
|
224
|
-
logger.error(`[sw-rules]: ${tip}`)
|
|
225
|
-
throw tip
|
|
226
|
-
}
|
|
227
|
-
let result = {}
|
|
228
|
-
if (paths.themes)
|
|
229
|
-
result = require(paths.themes)
|
|
230
|
-
else if (paths.modules) {
|
|
231
|
-
result = require(paths.modules)
|
|
232
|
-
}
|
|
233
|
-
if ('afterTheme' in result)
|
|
234
|
-
logger.error("[sw-rules]: 主题目录下的 sw-rules.js 中不应当包含 afterTheme 函数!")
|
|
235
|
-
return paths.root ? { ...result, ...require(paths.root) } : result
|
|
236
|
-
}
|