Hexo折腾史

推荐博客

搭建Hexo

全局安装hexo命令

1
npm install -g hexo-cli

初始化Hexo

hexo init

安装主题(两种方式)

git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

把主题放置在主目录中,更容易定制主题

npm i hexo-theme-butterfly

虽然配置容易,但主题会放在node_modules中,定制主题不方便

本地部署(本地测试)

hexo server

远程仓库配置

  1. 新建Github远程仓库
  2. git push -u origin main

部署到Github

两种方式都可以,可以只用一种,也可以都用

不需要push,可以单独deploy

这样部署不仅方便,而且就不需要push源文件到main分支就可以查看效果(避免过多提交代码)

  1. npm i hexo-deployer-git

  2. 修改_config.yml配置

    1
    2
    3
    4
    deploy:
    type: git
    repo: https://github.com/<username>/<project>
    branch: gh-pages
  3. hexo clean && hexo deploy

源文件在main分支中,部署生成的静态文件在gh-pages分支中

Github Actions配置workflow,push后通过自动部署

这个方式对于特定情形非常有用:电脑不在身边,只用手机端修改很少的代码,push即可自动部署

添加.github/workflows/main.yml文件,填入如下内容(注意node版本):

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
name: Push部署

on:
push:
branches:
- main
workflow_dispatch:

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 检查分支
uses: actions/checkout@v2
with:
ref: main
fetch-depth: 0

- name: 安装 Node
uses: actions/setup-node@v1
with:
node-version: "16.x"

- name: 设置时区
run: sudo timedatectl set-timezone 'Asia/Shanghai'

- name: 安装 Hexo
run: |
npm install hexo-cli -g

- name: 缓存 Hexo
id: cache-npm
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-

- name: 安装依赖
if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
run: |
npm install --save

- name: 修改post文件时间
run: |
find source/_posts -name '*.md' | while read file; do touch -d "$(git log -1 --format="@%ct" "$file")" "$file"; done

- name: 生成静态文件
run: |
hexo clean
hexo generate
hexo algolia

- name: 部署到Github
uses: JamesIves/github-pages-deploy-action@v4
with:
repository-name: BUGHERE/bughere.github.io
branch: gh-pages
folder: public
commit-message: "${{ github.event.head_commit.message }} Updated By Github Actions"
  • 因为Github Page静态文件在gh-pages分支中,所以在Github设置Github Page分支:Settings-Pages-Source

其中遇到了更新时间错误问题【配置文件已解决】:在使用 Github Actions 自动化部署 hexo 博客时会发现所有文章的更新时间都变成了此次提交修改的时间,但实际上这些文章是没有任何修改的。参考文献:修复 CI 构建博客造成的更新时间错误0o酱详细版

一些语法

关于Hexo的分类和标签

只有文章支持分类和标签,您可以在 Front-matter 中设置。在其他系统中,分类和标签听起来很接近,但是在 Hexo 中两者有着明显的差别:分类具有顺序性和层次性,也就是说 Foo, Bar 不等于 Bar, Foo;而标签没有顺序和层次。

1
2
3
4
5
categories:
- Diary
tags:
- PS3
- Games

子分类

下面的设置会使分类 Life 成为 Diary 的子分类,而不是并列分类。因此,有必要为您的文章选择尽可能准确的分类

1
2
3
categories:
- Diary
- Life

为文章添加多个分类

此时这篇文章同时包括三个分类: PlayStationGames 分别都是父分类 Diary 的子分类,同时 Life 是一个没有子分类的分类。

1
2
3
4
categories:
- [Diary, PlayStation]
- [Diary, Games]
- [Life]

Katex

局部使用Katex:使用Katex记得在每个post的Front-matter中填写katex: true,确保开启katex语法

全局使用Katex:在_config.butterfly.yml中:

1
2
katex:
per_page: true

标签外挂

使用mermaid绘制图标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% mermaid %}
graph LR
subgraph 1
direction LR
a(workspace) --add--> b(index) --commit--> c(repository) --push--> d(remote)
d --pull--> a
d --clone--> c
c --checkout--> a
end
subgraph 2
a(workspace) --stash --> e(stash)
e -- stash pop --> a
end
{% endmermaid %}

在线编辑网站:链接

tabs

Butterfly官方教程

hideToggle

隐藏收纳一部分文章内容

Butterfly官方教程中的Toggle

更多功能DIY

修改配置后,查看博客可能并不会立刻看到相关功能,甚至可能会有些错误。这个原因可能是浏览器缓存,加载了原来的渲染,这时候可以清除缓存或者使用其它浏览器和设备查看博客,或者静候一段时间。

Chrome 清除某个特定网站下的缓存:打开开发者工具(F12),选择 Network——Disable cache 即可。需要清除某网站缓存时 F12 打开开发者工具就会自动清除这个网站的缓存,而不必清除所有网站的缓存了。

关于使用hexo server调试代码时,对于source里的博客内容修改,不需要重新运行hexo server命令。但如果是修改主题里的内容,比如修改_config.butterfly.yml配置,则需要重新运行hexo server命令

自定义css和js文件

参考Hexo博客添加自定义css和js文件

接入Algolia搜索功能

参考Hexo + Butterfly 键入搜索功能

  1. 注册Algolia账号

  2. 在"Data Resources→Indices"中新建索引

  3. 执行npm install hexo-algoliasearch

  4. 查看API Key信息,“左下角Settings→Team and Access→API Keys”

  5. 修改_config.yml配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    algolia:
    appId: "***"
    apiKey: "***"
    adminApiKey: "***"
    chunkSize: 5000
    indexName: "blog"
    fields:
    - content:strip
    - excerpt:strip
    - gallery
    - permalink
    - photos
    - slug
    - tags
    - title
  6. 执行hexo algolia更新Algolia索引

DIY加载动画

pug代码格式是html的简化,为了是通过更简洁的代码生成对应的html代码。

而styl格式也是类似的,为了用更简洁的代码生成对应的css代码

有时候加载太快了,看不到加载动画。这时为了看到加载动画,我们可以手动调整浏览器的网速,打开F12-网络,在菜单栏找到默认的”No throttling“字样(不节流),改成”Slow 3G“就可以了

参考Akilar

主要调整了程序配置入口的代码,以及用到的两种文件:pugstyl,分别对应htmlcss文件

  • pug资源目录:themes/butterfly/layout/includes/loading/load_style
  • styl资源目录:themes/butterfly/source/css/_load_style
  • pug的配置入口位置:themes/butterfly/layout/includes/loading/fullpage-loading.pug
  • styl的配置入口位置:themes/butterfly/source/css/_layout/loading.styl

后续增加新的加载动画也只要在这些地方修改:(1)资源目录添加资源(2)配置入口增加配置

需要注意Butterfly版本,版本更新后,文件结构有所调整

4.10版本的fullpage-loading.pug文件大概如下:

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
if theme.preloader.enable
case theme.preloader.load_style
when 'gear'
include ./load_style/gear.pug
when 'scarecrow'
include ./load_style/scarecrow.pug
when 'image'
include ./load_style/image.pug
when 'spincat'
include ./load_style/spincat.pug
default
include ./load_style/default.pug

script(async).
(()=>{
const $loadingBox = document.getElementById('loading-box')
const $body = document.body
const preloader = {
endLoading: () => {
$body.style.overflow = ''
$loadingBox.classList.add('loaded')
},
initLoading: () => {
$body.style.overflow = 'hidden'
$loadingBox.classList.remove('loaded')
}
}

preloader.initLoading()
window.addEventListener('load',() => { preloader.endLoading() })
setTimeout(function(){preloader.endLoading();}, 5000); // 超时关闭动画
$loadingBox.addEventListener('click',()=> {preloader.endLoading()}) // 点击关闭动画

if (!{theme.pjax && theme.pjax.enable}) {
document.addEventListener('pjax:send', () => { preloader.initLoading() })
document.addEventListener('pjax:complete', () => { preloader.endLoading() })
}
})()

接入Twikoo评论

用Vercel+MongoDB免费部署

Twikoo备份

用国内域名加速Vercel

置顶和隐藏文章【已弃用】

0o酱的hexo-generator-index-custom插件

随机跳转文章

Hexo的Butterfly魔改教程:随机网页跳转(无缝版)

首页顶部文章轮播图【已弃用】

教程:hexo-swiper 文章置顶插件

首页顶部轮播图和文章推荐卡片

【Hexo博客 | 如何为博客添加顶部轮播图和文章推荐卡片】(https://blog.justlovesmile.top/posts/6a0d6454.html)

轮播图内容修改:themes\butterfly\layout\includes\sticky.pug
轮播图底部分类内容修改:themes\butterfly\layout\includes\hometop.pug
文章推荐卡片内容修改:source_data\slider.yml(不知道为什么叫slider)

分类条

展示在首页和分类页

修改分类:themes\butterfly\layout\includes\categoryBar.pug

Butterfly魔改:动态分类条,可以根据页面变化而改变的分类列表展示方式

由于它这里js写的是直接按照url划分’/',得到最后一个元素,当作分类,所以这里不支持子分类,所以我这里的分类条的高亮不是动态跟随的

由于本站设置了category_ui: index # 留空或 index,分类页的post ui和主页post ui是一样的

所以这里category.pug需要写在这里

1
2
3
4
5
6
if theme.category_ui == 'index'
include ./includes/mixins/post-ui.pug
#recent-posts.recent-posts.category_ui
include includes/categoryBar.pug
+postUI
include includes/pagination.pug

说说和清单页面

使用Memos【已弃用】

Memos Github地址

可以找到api目录的yaml文件

通过swagger editor就可以查看api文档了

后端部署

zeabur市场上提供好的memos模板,可以点击即用,但是这个需要付费

fork一份memos官方GitHub仓库到自己仓库,部署上去即可

但考虑到zeabur需要7天登陆上去手动续期,于是不用zeabur了

参考九弦

免费用户的replit仓库只能设置public,所以不要写一些过于私密的内容。对我来说,够用了

好像也可以用Railway部署,没试过,不知道咋样

后续,2024年1月,replit域名失效了,查看replit推文,如下所示

On January 1st, 2024, repl.co domains will transition to replit.dev and will only be accessible when someone is in the editor. If you are currently “hosting” anything on repl.co, we strongly recommend that you migrate to Deployments before the new year.

说是不提供免费的repl.co域名了,只提供replit.dev域名,并且需要有人在editor页面

现在的replit.dev域名又臭又长,像这样:https://66b4d66d-5794-4c83-9907-5519995b7d8e-00-15cwgy9gwbwnv.pike.replit.dev/

我寻思绑定个自己的域名呗,结果也是这次的更新把免费部署的绑定域名功能取消了,参考这篇帖子,主要内容如下:

Welcome to Ask @Coconutf! The reason that traditional custom domain linking on Replit was removed is because traditional repl.co hosting is being removed from Replit. It has been replaced by deployments 1 (replit.app). You can link a custom domain to deployments. Repls require a paid plan/connected credit card to host but will still be able to have custom domains (so long as the repl hosts a website).

害,replit不香了

前端部署参考哔哔点啥 2.0 By Memos

用这个实现说说和清单功能,舒服了,舒服了

可以把大佬云端的bb-lmm-mk.js文件放到本地加载,这样就可以编辑自定义功能了。比如,我就在memos请求url中加了一个tag属性,对说说和清单页面分别获取memos内容。

静态部署(前端+后端)【使用中】

思来想去,白嫖党还是不整这些东西了吧。整半天,到时候又收费了,难搞。

自己折腾半天瀑布流,才发现icat大佬已经弄好啦

直接弄个静态部署的说说页面,参考Butterfly的魔改教程:即刻短文页以及大佬的颜色

清单页面参考Butterfly的魔改教程:待办清单

大佬整理了自己的颜色和图标,我们无法直接使用

对于颜色部分,我直接用了大佬的颜色配置;图标部分,我用fontawesome图标替换了大佬的图标,修改essay.pug文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.icat-bber-bottom
.icat-bber-info
.icat-bber-info-time
- var datedata = new Date(item.date).toISOString()
<i class="fa-regular fa-clock"></i>
time.datatime(datetime= item.date)= datedata
if item.link
a.icat-bber-content-link(target="_blank", title="跳转到短文指引的链接", href=item.link, rel="external nofollow")
<i class="fa-solid fa-link"></i>
| 链接
if item.from
.icat-bber-info-from
<i class="fa-solid fa-location-dot"></i>
span=item.from
.icat-bber-reply(onclick="icatessay.commentText(" + `'${item.content}'` + ")")
<i class="fa-regular fa-message"></i>

我没有打开pjax,感觉没必要

其次,如果要使用快速评论功能的话,需要在配置文件中关闭评论功能的懒加载,否则无法跳转到评论区域,具体原因如下所示。其中,因为没有加载出评论区,所以变量n为空,无法执行后续逻辑

1
2
3
4
5
6
commentText: function (e) {
if (e == "undefined" || e == "null") e = "好棒!";
var n = document.getElementsByClassName("el-textarea__inner")[0],
t = document.createEvent("HTMLEvents");
if (!n) return;
...

顺便一提,如果用memos动态部署,而memos加载太慢的话,会导致视窗height=0。需要修改essay_page.css的代码,调整加载瀑布流的作用时间:

1
2
3
4
5
6
7
reflashEssayWaterFall: function () {
document.querySelector("#waterfall") &&
setTimeout(function () {
waterfall("#waterfall");
document.getElementById("waterfall").classList.add("show");
}, 1000);
},

这个部署方式用了很多inject,后面看下有没办法优化下

友链

参考Butterfly官方文档

藏宝阁

参考博客

实现后,我发现我还是更喜欢他的作品推荐卡片的样式

于是进行了小小的修改:
collect.pug

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
#article-container
.collect
- let collectPageContent = page.content
if site.data.collect
- let result = ""
each i in site.data.collect
- let className = i.class_name ? `<h2 ${i.class_desc?'':'style="margin-bottom:12px"'}>${i.class_name} (${i.link_list.length})</h2>` : ""
- let classDesc = i.class_desc ? `<div class="collect-desc">${i.class_desc}</div>` : ""
- let listResult = ""
each j in i.link_list
- let background = j.img ? `background-image: url(${j.img});` : 'background-color: #cfd9df;'
- let w = j.width || '150px'
- let h = j.height || '200px'
-
listResult += `
<div title="${j.name}" referrerPolicy="no-referrer" class="collect_box" style="${background} width:${w}; height:${h};">
<div class="collect_mask">
<span>${j.text ? j.text : ''}</span>
${j.url?'<a href="' + j.url + '">查看详情</a>' : ''}
</div>
<div class="collect_top">
<i class="${j.icon?j.icon:'fa-solid fa-film'}"></i>
<span>${j.tip?j.tip:''}</span>
</div>
<div class="collect_content">
<span>${j.name?j.name:'未知'}</span>
<div>${j.score?toStar(j.score):toStar(0)}</div>
</div>
</div>
`
-
- result += `${className}${classDesc} <div class="collect-list">${listResult}</div>`
- collectPageContent = collectPageContent + result
!= collectPageContent

collect.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
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
.collect
h2
margin-bottom: 0
.collect-desc
margin-bottom: 10px
.collect-list
display: flex
gap: 18px
flex-wrap: wrap
.collect_box
//--w: calc(100% / 6 - 15px)
//width: var(--w)
display: flex
justify-content: space-between
flex-direction: column
background-position: center
background-size: cover
border-radius: 12px
position: relative
overflow: hidden
padding: 10px
color: #fff !important
//margin: 10px auto
&::after
content: ''
position: absolute
height: 100%
width: 100%
left: 0
top: 0
background: rgba(0,0,0,0.1)
transition: .5s
z-index: 0
&:hover
.collect_mask
opacity: 1
pointer-events: auto
.collect_top
display: flex
z-index: 1
align-items: center
justify-content: space-between
.collect_mask
position: absolute
pointer-events: none
z-index: 2
transition: .5s
opacity: 0
width: 100%
height: 100%
left: 0
top: 0
padding: 20px
background: #333
span
display: block
height: calc(100% - 40px)
overflow: auto
a
text-align: center
background: #fff
color: #333 !important
border-radius: 5px
position: absolute
width: calc(100% - 40px)
bottom: 20px
left: 20px
&:hover
text-decoration: none !important
color: white !important
background: #49b1f5

.collect_content
z-index: 1
span
font-size: 18px
font-weight: bold

[data-theme='dark']
.collect .collect-list .collect_box
color: #ddd !important
&:hover
&::after
background: rgba(0,0,0,0.2)
&::after
background: rgba(0,0,0,0.5)
.collect .collect-list
@media screen and (max-width: 1100px)
gap: 15px
.collect_box
--w: calc(20% - 12px)
@media screen and (max-width: 900px)
gap: 16px
.collect_box
--w: calc(25% - 12px)
@media screen and (max-width: 768px)
gap: 15px
.collect_box
--w: calc(100% / 3 - 10px)
@media screen and (max-width: 500px)
gap: 16px
.collect_box
--w: calc(50% - 8px)

语雀同款链接卡片

参考:语雀同款链接卡片

语法:

1
2
3
4
5
6
 * {% link url,title,favicon,desc %}
* {% link 链接,标题,图标,介绍 %}
* {% link 链接,标题, ,介绍 %} # 改了点代码,实现默认图标

# 例子
{% link https://bughere.github.io/solution/blog/solution-blog-loading-animation-love-death-robots/, 爱死机加载动画, https://bughere.github.io/img/favicon/BHE.png, 自己做的一个动画 %}

图床

采用 GitHub + jsd + PicGo 的方式部署

参考使用Github+picGo搭建图床,保姆级教程来了

文中使用typora插件,但我现在vscode用的多,所以我选择vscode插件:PicGo

其实就是,Github提供仓库,只要把图片push放进去就行了,用不用picGo都无所谓,picGo就是一个帮忙push的可视化插件

用的话,用这个加速:https://cdn.jsdelivr.net/gh/BUGHERE/BlogImages@main/collect/fan/240106-01.jpg