更新日志
新增「文章时效性显示」、「随机文章跳转」与「代码块美化」相关内容。
新增「顶部阅读进度条」与「建站时间显示」相关内容。
Hexo 的 Fluid 主题是一个很好的主题,功能基本完整,页面简洁,加载浏览都很流畅。但是我对这个主题的页面仍有想修改的地方,特此记录。
同时为了保证在更新主题是不会影响我的修改,因此本文中所有修改都是非侵入式(不修改主题源代码)的。
文章时效性提示
在 source/custom/js
目录下新建 outdate-notice.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
| window.onload = function () {
//不同的日期显示不同的样式,200 天为黄色提示,400天为红色提示,可以自己定义。
let warningDay = 200;
let errorDay = 600;
// 确保能够获取到文章时间以及在文章详情页
let times = document.getElementsByTagName('time');
if (times.length === 0) { return; }
let posts = document.getElementsByClassName('post-content');
if (posts.length === 0) { return; }
// 获取系统当前的时间
let pubTime = new Date(times[0].dateTime); /* 文章发布时间戳 */
let now = Date.now() /* 当前时间戳 */
let interval = parseInt(now - pubTime)
let days = parseInt(interval / 86400000)
/* 发布时间超过指定时间(毫秒) */
//note warning 以及 note danger 是 Next 主题的自定义模板语法,如果使用其他主题,请自行更改样式以达到最佳显示效果
if (interval > warningDay * 3600 * 24 * 1000 && interval < errorDay * 3600 * 24 * 1000) {
posts[0].innerHTML = '<div class="note note-warning">' +
'<h5>文章时效性提示</h5><p>这是一篇发布于 ' + days + ' 天前的文章,部分信息可能已发生改变,请注意甄别。</p>' +
'</div>' + posts[0].innerHTML;
} else if (interval >= errorDay * 3600 * 24 * 1000) {
posts[0].innerHTML = '<div class="note note-danger">' +
'<h5>文章时效性提示</h5><p>这是一篇发布于 ' + days + ' 天前的文章,部分信息可能已发生改变,请注意甄别。</p>' +
'</div>' + posts[0].innerHTML;
}
}; |
在之前创建的 scripts/injector.js
中新增: 1 2 3 4
| // 注入文章时效性提示
hexo.extend.injector.register(
'body_end', `<script src="custom/js/outdate-notice.js"></script>`, 'post'
); |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 代码块美化
在 scripts
目录下新建 code-pretty.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
| "use strict";
// 获取唯一 ID
function getUuid() {
return Math.random().toString(36).substring(2, 8) + Date.now().toString(36);
}
hexo.extend.filter.register(
"after_post_render",
(data) => {
const { line_number, lib } = hexo.theme.config.code.highlight;
let reg;
if (lib === "highlightjs") {
if (line_number) {
reg = /(<figure class="highlight.+?>)(.+?hljs (.*?)".+?)(<\/figure>)/gims;
} else {
reg = /(<div class="code-wrapper.+?>)(.+?hljs (.*?)".+?)(<\/div>)/gims;
}
} else if (lib === "prismjs") {
reg = /(<div class="code-wrapper.+?>)(.+?data-language="(.*?)".+?)(<\/div>)/gims;
}
data.content = data.content.replace(reg, (match, begin, inner, lang, end, offset, string) => {
const collapseId = `collapse-${getUuid()}`;
const collapseBtn = `<i class="iconfont icon-code" type="button" data-toggle="collapse" data-target="#${collapseId}"></i>`;
const collapseDiv = `<div class="collapse show" id="${collapseId}">${inner}</div>`;
const langSpan = `<span>${lang.toUpperCase()}</span>`;
return begin + collapseBtn + langSpan + collapseDiv + end;
});
return data;
},
10000 // 应该在完成其他渲染后执行,因此将优先级设大一点
); |
如果需要修改代码块右上角图标,请更换 collapseBtn
的 icon 部分 "iconfont icon-code"
。
再在 custom/css
中新建 code-pretty.styl
文件 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
| .markdown-body .highlight table,
.markdown-body .code-wrapper pre {
border-radius: 0 0 0.5rem 0.5rem;
}
.markdown-body .highlight,
.markdown-body .code-wrapper {
background-color: #e6ebf1;
border-radius: 0.625rem;
// 折叠图标
> i {
color: #777777;
margin-left: 10px;
line-height: 2rem;
transform: none;
transition: color 0.2s ease-in-out, transform 0.2s ease-in-out;
// &.collapsed {
// transform: rotate(-90deg);
// }
}
// 代码语言
> span {
color: #777777;
margin-left: 10px;
font-weight: bold;
}
}
.copy-btn {
font-size: 1rem;
color: darkslategrey;
> i {
font-size: 1rem !important;
font-weight: bold;
}
}
[data-user-color-scheme='dark'] {
.copy-btn {
color: #c4c6c9;
transition: color 0.2s ease-in-out;
}
}
[data-user-color-scheme='dark'] {
.markdown-body .highlight,
.markdown-body .code-wrapper {
background-color: #696969;
transition: background-color 0.2s ease-in-out;
> i {
color: #c4c6c9;
}
> span {
color: #c4c6c9;
transition: color 0.2s ease-in-out;
}
}
} |
在 _config.fluid.yml
中的 custom_css
配置项中添加: 1 2
| custom_css:
- custom/css/code-pretty |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 浏览器恶搞标签
在 source
目录下新建 custom/js
目录,再在其中新建 label-page.js
文件,内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // 浏览器搞笑标题
var OriginTitle = document.title;
var titleTime;
document.addEventListener('visibilitychange', function () {
if (document.hidden) {
document.title = '(´;ω;`) 你不要我了吗 - ' + OriginTitle;
clearTimeout(titleTime);
} else {
document.title = OriginTitle;
titleTime = setTimeout(function () {
document.title = OriginTitle;
}, 2000);
}
}); |
随后在 _config.fluid.yml
中的 custom_js
配置项中添加: 1 2
| custom_js:
- /custom/js/label-page.js # 浏览器恶搞标题 |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 背景动态线条
简单版
添加背景动态线条只需要在 _config.fluid.yml
中新增 custom_html
配置项并添加如下内容:
1 2
| custom_html:
- <script type="text/javascript" color="255,255,255" opacity="1.0" zIndex="-1" count="110" src="https://cdn.jsdelivr.net/npm/canvas-nest.js@1.0.1/dist/canvas-nest.js"></script> |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 修改版
由于 canvas-nest.js
的 2.0.0
以后所有版本都与 Fluid 主题有冲突,而 1.0.1
版本不能修改点的颜色,只能修改线条颜色,因此还可以选择将 1.0.1
版本的 js
文件下载到本地进行修改。
下载源文件到本地 source/custom/js
目录下,分别修改以下内容:
- 在
c: get_attribute(script, "color", "0,0,0"),
后新增一行
1
| p: get_attribute(script, "pointColor", "0,0,0"), //pointColor |
- 在
context.strokeStyle = "rgba(" + config.c + "," + (d + 0.2) + ")"
后新增一行
1
| context.fillStyle = "rgba(" + config.p + ")", |
然后在 _config.fluid.yml
中新增 custom_html
配置项并添加如下内容:
1 2
| custom_html:
- <script type="text/javascript" color="255,255,255" pointColor="252,228,236" opacity="1.0" zIndex="-1" count="110" src="/custom/js/canvas-nest.js"></script> |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 顶部阅读进度条
在 source/custom/js
目录下新建 read-progress-bar.js
文件:
1 2 3 4 5 6 7 8 9 10 11 12
| document.addEventListener('DOMContentLoaded', function () {
var winHeight = window.innerHeight,
docHeight = document.documentElement.scrollHeight,
progressBar = document.querySelector('#content_progress');
progressBar.max = docHeight - winHeight;
progressBar.value = window.scrollY;
document.addEventListener('scroll', function () {
progressBar.max = document.documentElement.scrollHeight - window.innerHeight;
progressBar.value = window.scrollY;
});
}); |
再在 source/custom/css
目录下新建 read-progress-bar.css
文件: 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
| #content_progress {
/* Positioning */
position: fixed;
left: 0;
top: 0;
z-index: 32766;
width: 100%;
height: 6px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
background-color: transparent;
color: #ffffff80; /* 使用半透明白色,适配夜间模式 */
}
#content_progress::-webkit-progress-bar {
background-color: transparent;
}
#content_progress::-webkit-progress-value {
background-color: #ffffff80;
}
#content_progress::-moz-progress-bar {
background-color: #ffffff80;
} |
接着在 scripts
目录下新建 injector.js
文件: 1 2 3 4
| // 注入阅读进度条
hexo.extend.injector.register(
'head_begin', '<progress id="content_progress" value="0"></progress>', 'post'
); |
最后在 _config.fluid.yml
中的 custom_js
和 custom_css
配置项中添加: 1 2 3 4
| custom_js:
- custom/js/read-progress-bar.js
custom_css:
- custom/css/read-progress-bar.css |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 建站时间
在 source/custom/js
目录下新建 create-time.js
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var now = new Date();
function createtime() {
var grt = new Date("08/19/2024 12:00:00");//在此处修改你的建站时间,格式:月/日/年 时:分:秒
now.setTime(now.getTime() + 250);
days = (now - grt) / 1000 / 60 / 60 / 24; dnum = Math.floor(days);
hours = (now - grt) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours);
if (String(hnum).length == 1) { hnum = "0" + hnum; } minutes = (now - grt) / 1000 / 60 - (24 * 60 * dnum) - (60 * hnum);
mnum = Math.floor(minutes); if (String(mnum).length == 1) { mnum = "0" + mnum; }
seconds = (now - grt) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
snum = Math.round(seconds); if (String(snum).length == 1) { snum = "0" + snum; }
document.getElementById("timeDate").innerHTML = "本站已创建 " + dnum + " 天 ";
document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
}
setInterval("createtime()", 250); |
在 _config.fluid.yml
中的 custom_js
配置项中添加: 1 2
| custom_js:
- custom/js/create-time.js |
最后在 _config.fluid.yml
中修改 footer/content
配置项,新增一行 1
| <br><span id="timeDate">天数载入中</span><span id="times">...</span><br> |
即将 footer/content
配置项修改为如下形式: 1 2 3 4 5 6 7
| footer:
content: '
<a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a>
<i class="iconfont icon-love"></i>
<a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a>
<br><span id="timeDate">天数载入中</span><span id="times">...</span><br>
' |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 随机文章跳转
该方法需要先生成 sitemap。
先在 source/custom/js
目录下新建 random-post.js
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function randomPost() {
fetch('/sitemap.xml').then(res => res.text()).then(str => (new window.DOMParser()).parseFromString(str, "text/xml")).then(data => {
let ls = data.querySelectorAll('url loc');
let locationHref, locSplit;
do {
locationHref = ls[Math.floor(Math.random() * ls.length)].innerHTML
locSplit = locationHref.split('/')[3] || ''
// } while (locSplit == '' || locSplit == 'tags');
//若所有文章都如 https://…….com/posts/2022/07/…… 格式,主域名后字符是 posts,则循环条件改为:
} while (locSplit !== 'posts');
location.href = locationHref
})
} |
在 _config.fluid.yml
中的 custom_js
配置项中添加: 1 2
| custom_js:
- custom/js/random-post.js |
随后在喜欢的位置放上 javascript:randomPost();
的跳转链接,例如在导航栏: 1 2
| menu:
- { key: "random", name: "随机文章", link: "javascript:randomPost();", icon: "iconfont icon-random" } |
使用 hexo cl
+ hexo d -g
重新生成并部署即可。 新增标签语法
参看另一篇文章
参考资料
本篇文章内容参考了类似的大量文章内容,特此感谢(排名不分先后) - Hexo博客美化 - 龙泽雨的博客 - Hexo-Fluid搭建与魔改纪录 - 弥冬のBlog - Hexo-3-Fluid主题魔改 - 遥望 - Hexo博客Fluid主题魔改记录 - KEVIN’S BLOG - 网页动态背景——随鼠标变换的动态线条 - 孤独的飞行者 - 博客园 - 建议添加“文章时效性”提示 · Issue #1051 · fluid-dev/hexo-theme-fluid - Hexo-Fluid 博客美化和修改 | Kiyan’s Blog - 使用 Hexo 过滤器实现 Fluid 主题的代码折叠 | Kiyan’s Blog - 利用 SiteMap 随机访问站内页面::木木木木木