关于本站

构建与托管

本站使用 HEXO 构建生成静态网站文件,托管在云服务器创建的 Plesk 面板中。

Plesk 中配置了 Webhook,当我提交变更到我的 Github 私有仓库以后,触发 Actions 构建网站,变更的内容将自动同步到 Plesk 网站文件夹进行更新。

2024-02-06 因为虚拟主机宿主机多次被 DDoS 攻击 ,所以我把网站托管换到了 CloudFlare Pages。

为什么用 HEXO?

很多年前当我还是一个大学生的时候,捣鼓 VPS、建站是一件很酷的事情。当时我用的是 BandWagon Host,使用 NGinx、PHP、MySQL 等配套软件安装 WordPress 建立了自己的个人博客。当时还经历过数据库被勒索,丢失了我写的几篇文章(其实也没有什么,很初级的内容)。

重点在于,像 WordPress 这样依赖数据库的博客非常需要维护,对比之下,静态生成的博客如 HEXO、HUGO 只需关心自己的博客文章文件即可,同时 Markdown 格式又允许使用不同的设备随时编写、记录,没有什么迁移负担。

换到 HEXO 以后,整个博客站点托管在 GitHub,可以很方便地通过它的 Actions 自动生成新的网站文件,也不用担心丢失。

个性化

主题

使用 Icarus 主题。

2025-01-18 换上了自己写的主题。

大屏设备可以获得最佳阅读体验。谢谢有读者喜欢我的主题,因为是从头开始搓,所以陆陆续续一直在优化/修 bug。估摸着跑个一年到时候开源的话应该是比较 ok 的状态了。

想做的主题:

  • 小而美 审美嘛因人而异,主要是想要用尽可能少的资源来做,目前的主题风格是参考 The Medium Blog
  • 可访问性好 希望在各种设备都可访问,例如:禁用 JavaScript,RSS 阅读器,老旧设备,小屏设备(我的一代 iPhone SE)

封面图片

有的来自 Unsplash,有的是我自己拍的,有的则是我自己用 Figma 绘制并导出的 SVG 文件。矢量图形清晰度非常完美,体积也极小。使用 Figma 后,整理素材更简单了。

字体

本站共计使用两种开源/免费字体:

  1. Source Serif
    The quick brown fox jumps over the lazy dog
  2. Source Han Serif CN
    敏捷的棕色狐狸跳过了懒狗

以及系统字体:

font-family
1
font-family: SF Pro Text, SF Pro Icons, Helvetica Neue, Helvetica, Arial, sans-serif;

字体文件由脚本收集所有用到字符简化而成,提高加载速度。

generate-font-files.js
1
2
3
4
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
const fs = require("fs");
const _ = require("lodash");
const Fontmin = require("fontmin");

const directory = "source/_posts";
const scriptDirectory = "custom-scripts/font";
const fontFileDirectory = `${scriptDirectory}/files`;

const files = fs.readdirSync(directory).filter((item) => item !== ".DS_Store");
const fonts = fs
.readdirSync(fontFileDirectory)
.filter((item) => item !== "index.js");

const getLetters = () => {
const letterMap = {};

_.forEach(files, (file) => {
const fileContent = fs.readFileSync(`${directory}/${file}`, "utf8");
const letters = _.toArray(fileContent);
_.forEach(letters, (letter) => {
if (!letterMap[letter]) {
letterMap[letter] = 1;
}
});
});
return Object.keys(letterMap).join("");
};

const currentLetters = getLetters();

const lettersText = fs.existsSync(`${scriptDirectory}/letters.txt`)
? fs.readFileSync(`${scriptDirectory}/letters.txt`, "utf8")
: "";

if (currentLetters === lettersText) {
return;
}

fs.writeFileSync(`${scriptDirectory}/letters.txt`, getLetters());

const generateFontFile = (letters) => {
_.forEach(fonts, (font) => {
const task = new Fontmin()
.src(`${fontFileDirectory}/${font}`)
.dest("themes/icarus/source/fonts")
.use(
Fontmin.glyph({
text: letters,
hinting: false,
})
)
.use(Fontmin.ttf2woff2());

task.run(function (err, files) {
if (err) {
throw err;
}
});
});
};

generateFontFile(currentLetters);

插件

懒加载

使用了 hexo-lazyload-element 处理图片、视频、iframe 资源的懒加载,提升页面性能的同时避免消耗不必要的流量。

WebP 图片

部分图片是上传到七牛云并使用 ?imageMogr2/format/webp 参数加载 WebP 图片格式资源。但是对于一些设备(iOS13 以下,MacOS Mojave 以下)需要做兼容。

2024/02/22 更新:更换了图床,全站都没有再使用七牛云的资源了。

checkwebp.js
1
2
3
4
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/*! modernizr 3.6.0 (Custom Build) | MIT *
* https://modernizr.com/download/?-webp-setclasses !*/
!(function (e, n, A) {
function o(e) {
var n = u.className,
A = Modernizr._config.classPrefix || "";
if ((c && (n = n.baseVal), Modernizr._config.enableJSClass)) {
var o = new RegExp("(^|\\s)" + A + "no-js(\\s|$)");
n = n.replace(o, "$1" + A + "js$2");
}
Modernizr._config.enableClasses &&
((n += " " + A + e.join(" " + A)),
c ? (u.className.baseVal = n) : (u.className = n));
}
function t(e, n) {
return typeof e === n;
}
function a() {
var e, n, A, o, a, i, l;
for (var f in r)
if (r.hasOwnProperty(f)) {
if (
((e = []),
(n = r[f]),
n.name &&
(e.push(n.name.toLowerCase()),
n.options && n.options.aliases && n.options.aliases.length))
)
for (A = 0; A < n.options.aliases.length; A++)
e.push(n.options.aliases[A].toLowerCase());
for (o = t(n.fn, "function") ? n.fn() : n.fn, a = 0; a < e.length; a++)
(i = e[a]),
(l = i.split(".")),
1 === l.length
? (Modernizr[l[0]] = o)
: (!Modernizr[l[0]] ||
Modernizr[l[0]] instanceof Boolean ||
(Modernizr[l[0]] = new Boolean(Modernizr[l[0]])),
(Modernizr[l[0]][l[1]] = o)),
s.push((o ? "" : "no-") + l.join("-"));
}
}
function i(e, n) {
if ("object" == typeof e) for (var A in e) f(e, A) && i(A, e[A]);
else {
e = e.toLowerCase();
var t = e.split("."),
a = Modernizr[t[0]];
if ((2 == t.length && (a = a[t[1]]), "undefined" != typeof a))
return Modernizr;
(n = "function" == typeof n ? n() : n),
1 == t.length
? (Modernizr[t[0]] = n)
: (!Modernizr[t[0]] ||
Modernizr[t[0]] instanceof Boolean ||
(Modernizr[t[0]] = new Boolean(Modernizr[t[0]])),
(Modernizr[t[0]][t[1]] = n)),
o([(n && 0 != n ? "" : "no-") + t.join("-")]),
Modernizr._trigger(e, n);
}
return Modernizr;
}
var s = [],
r = [],
l = {
_version: "3.6.0",
_config: {
classPrefix: "",
enableClasses: !0,
enableJSClass: !0,
usePrefixes: !0,
},
_q: [],
on: function (e, n) {
var A = this;
setTimeout(function () {
n(A[e]);
}, 0);
},
addTest: function (e, n, A) {
r.push({ name: e, fn: n, options: A });
},
addAsyncTest: function (e) {
r.push({ name: null, fn: e });
},
},
Modernizr = function () {};
(Modernizr.prototype = l), (Modernizr = new Modernizr());
var f,
u = n.documentElement,
c = "svg" === u.nodeName.toLowerCase();
!(function () {
var e = {}.hasOwnProperty;
f =
t(e, "undefined") || t(e.call, "undefined")
? function (e, n) {
return n in e && t(e.constructor.prototype[n], "undefined");
}
: function (n, A) {
return e.call(n, A);
};
})(),
(l._l = {}),
(l.on = function (e, n) {
this._l[e] || (this._l[e] = []),
this._l[e].push(n),
Modernizr.hasOwnProperty(e) &&
setTimeout(function () {
Modernizr._trigger(e, Modernizr[e]);
}, 0);
}),
(l._trigger = function (e, n) {
if (this._l[e]) {
var A = this._l[e];
setTimeout(function () {
var e, o;
for (e = 0; e < A.length; e++) (o = A[e])(n);
}, 0),
delete this._l[e];
}
}),
Modernizr._q.push(function () {
l.addTest = i;
}),
Modernizr.addAsyncTest(function () {
function e(e, n, A) {
function o(n) {
var o = n && "load" === n.type ? 1 == t.width : !1,
a = "webp" === e;
i(e, a && o ? new Boolean(o) : o), A && A(n);
}
var t = new Image();
(t.onerror = o), (t.onload = o), (t.src = n);
}
var n = [
{
uri: "data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=",
name: "webp",
},
{
uri: "data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA==",
name: "webp.alpha",
},
{
uri: "data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA",
name: "webp.animation",
},
{
uri: "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=",
name: "webp.lossless",
},
],
A = n.shift();
e(A.name, A.uri, function (A) {
if (A && "load" === A.type)
for (var o = 0; o < n.length; o++) e(n[o].name, n[o].uri);
});
}),
a(),
o(s),
delete l.addTest,
delete l.addAsyncTest;
for (var p = 0; p < Modernizr._q.length; p++) Modernizr._q[p]();
e.Modernizr = Modernizr;
})(window, document);

Modernizr.on("webp", function (result) {
if (result) {
// supported
} else {
// not-supported
const webpImages = document.querySelectorAll("img");
Array.prototype.filter
.call(
webpImages,
(item) =>
item.getAttribute("src") && item.getAttribute("src").includes("")
)
.forEach((img) => {
const currentSrc = img.getAttribute("src");
img.src = currentSrc.replace("?imageMogr2/format/webp", "");
});

const galleryItems = document.querySelectorAll(".gallery-item");
Array.prototype.filter
.call(
galleryItems,
(item) =>
item.getAttribute("href") && item.getAttribute("href").includes("")
)
.forEach((img) => {
const currentSrc = img.getAttribute("href");
img.href = currentSrc.replace("?imageMogr2/format/webp", "");
});

const lazyloadItems = document.querySelectorAll(".lazyload-wrap");
Array.prototype.filter
.call(
lazyloadItems,
(item) =>
item.dataset &&
item.dataset.content.includes("%3FimageMogr2%2Fformat%2Fwebp")
)
.forEach((item) => {
const currentSrc = item.dataset.content;
item.dataset.content = currentSrc.replace(
"?%3FimageMogr2%2Fformat%2Fwebp",
""
);
});
}
});

RSS

使用 hexo-generator-feed 生成 /feed.xml 便于 RSS 阅读器订阅。

你可以使用以下地址订阅内容。

RSS
1
https://cn.thelynan.com/feed.xml

评论区

使用 Gitalk

广告

使用 Google AdSense,在边栏 Widget 内(小屏设备则在文章最底部),对阅读影响比较小。如果它能覆盖我的 OSS 费用就好啦。

有时候会弹全屏广告,体验不好,关了关了。

彩蛋

CSS 动画

例如

🎢

iframe 交互

页面和 iframe 之间使用了 postMessage 方式进行通信,丰富静态页面的功能。

单独设置的文章背景

例如关西旅行的枫叶背景。

暂时是这些,未来可能会有一些新的想法加入进来。

详细更新内容可见:新特性

1
2
3
4
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
---
title: 关于本站
date: 2022-01-01 00:00
tags: [HEXO]
cover: https://r2-assets.thelynan.com/u/easter-eggs-banner-xzczVz.svg
ogImage: "https://r2-assets.thelynan.com/uPic/ester eggs.jpg"
hide:
recent: true
translations: ["en"]
appendRawMarkdown: true
---

## 构建与托管

本站使用 [HEXO](https://hexo.io/index.html) 构建生成静态网站文件,~~托管在云服务器创建的 [Plesk](https://www.plesk.com/) 面板中。~~

~~在 [Plesk](https://www.plesk.com/) 中配置了 Webhook,当我提交变更到我的 Github 私有仓库以后,触发 Actions 构建网站,变更的内容将自动同步到 [Plesk](https://www.plesk.com/) 网站文件夹进行更新。~~

<div class="new-updates">
2024-02-06 因为虚拟主机宿主机多次被 DDoS 攻击 <span style="display: inline-block; width: 14px; height: 14px; background-image: url('https://r2-assets.thelynan.com/uPic/3zffxN_1700142351761.png'); background-size: cover;"></span>,所以我把网站托管换到了 CloudFlare Pages。
</div>

### 为什么用 HEXO?

很多年前当我还是一个大学生的时候,捣鼓 VPS、建站是一件很酷的事情。当时我用的是 [BandWagon Host](https://bwh1.net/),使用 NGinx、PHP、MySQL 等配套软件安装 [WordPress](https://wordpress.com/) 建立了自己的个人博客。当时还经历过数据库被勒索,丢失了我写的几篇文章(其实也没有什么,很初级的内容)。

重点在于,像 WordPress 这样依赖数据库的博客**非常需要维护**,对比之下,静态生成的博客如 HEXO、HUGO 只需关心自己的博客文章文件即可,同时 Markdown 格式又允许使用不同的设备随时编写、记录,没有什么迁移负担。

换到 HEXO 以后,整个博客站点托管在 [GitHub](https://github.com/),可以很方便地通过它的 Actions 自动生成新的网站文件,也不用担心丢失。

## 个性化

### 主题

~~使用 [Icarus](https://github.com/ppoffice/hexo-theme-icarus) 主题。~~

<div class="new-updates">
2025-01-18 换上了自己写的主题。
</div>

大屏设备可以获得最佳阅读体验。谢谢有读者喜欢我的主题,因为是从头开始搓,所以陆陆续续一直在优化/修 bug。估摸着跑个一年到时候开源的话应该是比较 ok 的状态了。

想做的主题:

- **小而美** 审美嘛因人而异,主要是想要用尽可能少的资源来做,目前的主题风格是参考 [The Medium Blog](https://medium.com/blog)
- **可访问性好** 希望在各种设备都可访问,例如:禁用 JavaScript,RSS 阅读器,老旧设备,小屏设备(我的一代 iPhone SE)

### 封面图片

有的来自 [Unsplash](https://unsplash.com/),有的是我自己拍的,有的则是我自己用 [Figma](https://www.figma.com/) 绘制并导出的 SVG 文件。矢量图形清晰度非常完美,体积也极小。使用 Figma 后,整理素材更简单了。

### 字体

本站共计使用两种开源/免费字体:

1. **[Source Serif](https://github.com/adobe-fonts/source-serif)**
<span style="font-family: 'source-serif';">The quick brown fox jumps over the lazy dog</span>
2. **[Source Han Serif CN](https://fonts.adobe.com/fonts/source-han-serif-simplified-chinese-subset)**
<span style="font-family: 'source han serif cn';">敏捷的棕色狐狸跳过了懒狗</span>

以及系统字体:

```css font-family
font-family: SF Pro Text, SF Pro Icons, Helvetica Neue, Helvetica, Arial, sans-serif;
```

字体文件由脚本收集所有用到字符简化而成,提高加载速度。

```javascript generate-font-files.js folded
const fs = require("fs");
const _ = require("lodash");
const Fontmin = require("fontmin");

const directory = "source/_posts";
const scriptDirectory = "custom-scripts/font";
const fontFileDirectory = `${scriptDirectory}/files`;

const files = fs.readdirSync(directory).filter((item) => item !== ".DS_Store");
const fonts = fs
.readdirSync(fontFileDirectory)
.filter((item) => item !== "index.js");

const getLetters = () => {
const letterMap = {};

_.forEach(files, (file) => {
const fileContent = fs.readFileSync(`${directory}/${file}`, "utf8");
const letters = _.toArray(fileContent);
_.forEach(letters, (letter) => {
if (!letterMap[letter]) {
letterMap[letter] = 1;
}
});
});
return Object.keys(letterMap).join("");
};

const currentLetters = getLetters();

const lettersText = fs.existsSync(`${scriptDirectory}/letters.txt`)
? fs.readFileSync(`${scriptDirectory}/letters.txt`, "utf8")
: "";

if (currentLetters === lettersText) {
return;
}

fs.writeFileSync(`${scriptDirectory}/letters.txt`, getLetters());

const generateFontFile = (letters) => {
_.forEach(fonts, (font) => {
const task = new Fontmin()
.src(`${fontFileDirectory}/${font}`)
.dest("themes/icarus/source/fonts")
.use(
Fontmin.glyph({
text: letters,
hinting: false,
})
)
.use(Fontmin.ttf2woff2());

task.run(function (err, files) {
if (err) {
throw err;
}
});
});
};

generateFontFile(currentLetters);
```

## 插件

### 懒加载

使用了 [hexo-lazyload-element](https://github.com/LynanBreeze/hexo-lazyload-element) 处理图片、视频、iframe 资源的懒加载,提升页面性能的同时避免消耗不必要的流量。

### WebP 图片

~~部分图片是上传到七牛云并使用 `?imageMogr2/format/webp` 参数加载 WebP 图片格式资源。但是对于一些设备(iOS13 以下,MacOS Mojave 以下)需要做兼容。~~

2024/02/22 更新:更换了图床,全站都没有再使用七牛云的资源了。

```javascript checkwebp.js folded
/*! modernizr 3.6.0 (Custom Build) | MIT *
* https://modernizr.com/download/?-webp-setclasses !*/
!(function (e, n, A) {
function o(e) {
var n = u.className,
A = Modernizr._config.classPrefix || "";
if ((c && (n = n.baseVal), Modernizr._config.enableJSClass)) {
var o = new RegExp("(^|\\s)" + A + "no-js(\\s|$)");
n = n.replace(o, "$1" + A + "js$2");
}
Modernizr._config.enableClasses &&
((n += " " + A + e.join(" " + A)),
c ? (u.className.baseVal = n) : (u.className = n));
}
function t(e, n) {
return typeof e === n;
}
function a() {
var e, n, A, o, a, i, l;
for (var f in r)
if (r.hasOwnProperty(f)) {
if (
((e = []),
(n = r[f]),
n.name &&
(e.push(n.name.toLowerCase()),
n.options && n.options.aliases && n.options.aliases.length))
)
for (A = 0; A < n.options.aliases.length; A++)
e.push(n.options.aliases[A].toLowerCase());
for (o = t(n.fn, "function") ? n.fn() : n.fn, a = 0; a < e.length; a++)
(i = e[a]),
(l = i.split(".")),
1 === l.length
? (Modernizr[l[0]] = o)
: (!Modernizr[l[0]] ||
Modernizr[l[0]] instanceof Boolean ||
(Modernizr[l[0]] = new Boolean(Modernizr[l[0]])),
(Modernizr[l[0]][l[1]] = o)),
s.push((o ? "" : "no-") + l.join("-"));
}
}
function i(e, n) {
if ("object" == typeof e) for (var A in e) f(e, A) && i(A, e[A]);
else {
e = e.toLowerCase();
var t = e.split("."),
a = Modernizr[t[0]];
if ((2 == t.length && (a = a[t[1]]), "undefined" != typeof a))
return Modernizr;
(n = "function" == typeof n ? n() : n),
1 == t.length
? (Modernizr[t[0]] = n)
: (!Modernizr[t[0]] ||
Modernizr[t[0]] instanceof Boolean ||
(Modernizr[t[0]] = new Boolean(Modernizr[t[0]])),
(Modernizr[t[0]][t[1]] = n)),
o([(n && 0 != n ? "" : "no-") + t.join("-")]),
Modernizr._trigger(e, n);
}
return Modernizr;
}
var s = [],
r = [],
l = {
_version: "3.6.0",
_config: {
classPrefix: "",
enableClasses: !0,
enableJSClass: !0,
usePrefixes: !0,
},
_q: [],
on: function (e, n) {
var A = this;
setTimeout(function () {
n(A[e]);
}, 0);
},
addTest: function (e, n, A) {
r.push({ name: e, fn: n, options: A });
},
addAsyncTest: function (e) {
r.push({ name: null, fn: e });
},
},
Modernizr = function () {};
(Modernizr.prototype = l), (Modernizr = new Modernizr());
var f,
u = n.documentElement,
c = "svg" === u.nodeName.toLowerCase();
!(function () {
var e = {}.hasOwnProperty;
f =
t(e, "undefined") || t(e.call, "undefined")
? function (e, n) {
return n in e && t(e.constructor.prototype[n], "undefined");
}
: function (n, A) {
return e.call(n, A);
};
})(),
(l._l = {}),
(l.on = function (e, n) {
this._l[e] || (this._l[e] = []),
this._l[e].push(n),
Modernizr.hasOwnProperty(e) &&
setTimeout(function () {
Modernizr._trigger(e, Modernizr[e]);
}, 0);
}),
(l._trigger = function (e, n) {
if (this._l[e]) {
var A = this._l[e];
setTimeout(function () {
var e, o;
for (e = 0; e < A.length; e++) (o = A[e])(n);
}, 0),
delete this._l[e];
}
}),
Modernizr._q.push(function () {
l.addTest = i;
}),
Modernizr.addAsyncTest(function () {
function e(e, n, A) {
function o(n) {
var o = n && "load" === n.type ? 1 == t.width : !1,
a = "webp" === e;
i(e, a && o ? new Boolean(o) : o), A && A(n);
}
var t = new Image();
(t.onerror = o), (t.onload = o), (t.src = n);
}
var n = [
{
uri: "data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=",
name: "webp",
},
{
uri: "data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA==",
name: "webp.alpha",
},
{
uri: "data:image/webp;base64,UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA",
name: "webp.animation",
},
{
uri: "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=",
name: "webp.lossless",
},
],
A = n.shift();
e(A.name, A.uri, function (A) {
if (A && "load" === A.type)
for (var o = 0; o < n.length; o++) e(n[o].name, n[o].uri);
});
}),
a(),
o(s),
delete l.addTest,
delete l.addAsyncTest;
for (var p = 0; p < Modernizr._q.length; p++) Modernizr._q[p]();
e.Modernizr = Modernizr;
})(window, document);

Modernizr.on("webp", function (result) {
if (result) {
// supported
} else {
// not-supported
const webpImages = document.querySelectorAll("img");
Array.prototype.filter
.call(
webpImages,
(item) =>
item.getAttribute("src") && item.getAttribute("src").includes("")
)
.forEach((img) => {
const currentSrc = img.getAttribute("src");
img.src = currentSrc.replace("?imageMogr2/format/webp", "");
});

const galleryItems = document.querySelectorAll(".gallery-item");
Array.prototype.filter
.call(
galleryItems,
(item) =>
item.getAttribute("href") && item.getAttribute("href").includes("")
)
.forEach((img) => {
const currentSrc = img.getAttribute("href");
img.href = currentSrc.replace("?imageMogr2/format/webp", "");
});

const lazyloadItems = document.querySelectorAll(".lazyload-wrap");
Array.prototype.filter
.call(
lazyloadItems,
(item) =>
item.dataset &&
item.dataset.content.includes("%3FimageMogr2%2Fformat%2Fwebp")
)
.forEach((item) => {
const currentSrc = item.dataset.content;
item.dataset.content = currentSrc.replace(
"?%3FimageMogr2%2Fformat%2Fwebp",
""
);
});
}
});
```

### RSS

使用 [hexo-generator-feed](https://github.com/hexojs/hexo-generator-feed) 生成 `/feed.xml` 便于 RSS 阅读器订阅。

你可以使用以下地址订阅内容。

```html RSS
https://cn.thelynan.com/feed.xml
```

### 评论区

使用 [Gitalk](https://github.com/gitalk/gitalk)。

### 广告

~~使用 [Google AdSense](https://www.google.com/adsense),在边栏 Widget 内(小屏设备则在文章最底部),对阅读影响比较小。如果它能覆盖我的 OSS 费用就好啦。~~

有时候会弹全屏广告,体验不好,关了关了。

## 彩蛋

### CSS 动画

例如

<span style="display: inline-block;animation: tilt-shaking ease infinite 0.3s;"><span style="margin-top: 3px; font-size: 18px; font-weight: bold; transform: rotate(30deg);display: inline-block;"></span><span style="margin-top: -2px; font-size: 14px; font-weight: bold; transform: rotate(-17deg); display: inline-block;"></span><span style="margin-top: 3px; font-weight: bold; font-size: 19px;transform: rotate(25deg); display: inline-block;"></span></span><span style="font-size: 24px; margin-left: -13px">🎢</span>

### iframe 交互

页面和 iframe 之间使用了 [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) 方式进行通信,丰富静态页面的功能。

<iframe src="/static/image-comparison/index.html?src1=https://r2-assets.thelynan.com/u/65546b9bc458853aefcd0334.jpg&src2=https://r2-assets.thelynan.com/u/65546bb0c458853aefcd392e.jpg" scrolling="no" border="0" frameborder="no" framespacing="0" style="width: 100%; height: 100%; aspect-ratio: 1.3333333333" referrerpolicy="" data-placeholderimg="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAASABgDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAQGBwj/xAAmEAABBAEDAQkAAAAAAAAAAAACAAEDBAUGBxFhEhMUITFBUXGC/8QAFwEBAAMAAAAAAAAAAAAAAAAABAECA//EABoRAAIDAQEAAAAAAAAAAAAAAAABAgMxIUH/2gAMAwEAAhEDEQA/AIm2W/tyEY4rExEzce62Oxv7BYxRhBNwbN8rjnB4DI4mJ5O5Ly6Kz6eguzmQzG7MRenKmF8nxlHWl02SG/Y1Zd8XYMiFy5ZFM0vWiqY0GjZu2zIkLDJlJyEUTUJnaIG/LKlUDMb3Ak7fToiAtFeGraPkkIhYjJ26uiImwwO9P//Z"></iframe>

![](https://r2-assets.thelynan.com/u/65bf4f63871b83018a2c46d9.gif)

### 单独设置的文章背景

例如[关西旅行](/journey-to-japan-2023/)的枫叶背景。

暂时是这些,未来可能会有一些新的想法加入进来。

详细更新内容可见:[**新特性**](/new-features/)

<link rel='stylesheet' href="/css/animations.css" />