个人博客搭建

安装Portainer CE 监控面板

1
2
3
4
5
6
7
8
9
10
11
12
# 拉取最新镜像
sudo docker pull portainer/portainer-ce:latest
# 创建数据存储卷
sudo docker volume create portainer_data
# 部署容器
sudo docker run -d \
-p 8000:8000 -p 9443:9443 -p 9000:9000 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest

安装FileBrowser文件管理器

1
2
mkdir -p /opt/jetson-server/filebrowser
touch /opt/jetson-server/filebrowser/database.db
1
2
3
4
5
6
7
8
9
docker run -d \
--name filebrowser \
--restart=always \
-p 18080:80 \
-v /opt/jetson-server:/srv \
-v /opt/jetson-server/filebrowser:/config \
-e FILEBROWSER_USERNAME=white \
-e FILEBROWSER_PASSWORD=yourpassword \
filebrowser/filebrowser

安装git 9.0.2

1
2
3
4
apt install git
/**/安装git
git --version
/**/查看git的版本

安装node.js环境 20.20.1

1
2
3
4
5
6
7
8
# 下载npm软件包
sudo apt install npm
# 下载noede.js环境
sudo apt install nodejs
# 验证环境中是否存在正确的 npm 版本
npm -v
# 验证环境中是否存在正确的 node 版本
node -v

arm 架构的apt中可能版本较旧,建议去nodejs下载地址下载所需版本,然后手动解压安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 解压 .tar.gz 文件
sudo tar -xzvf node-v20.20.1-linux-arm64.tar.gz

# 解压 .tar.xz 文件
sudo tar -xvf node-v20.20.1-linux-arm64.tar.xz

# 移动到 /usr/local
sudo mv node-v20.20.1-linux-arm64 /usr/local/nodejs

# 配置环境变量
echo 'export NODE_HOME=/usr/local/nodejs' >> ~/.bashrc
echo 'export PATH=$NODE_HOME/bin:$PATH' >> ~/.bashrc

# 立即生效
source ~/.bashrc

# 切换 npm 国内源(淘宝镜像)
npm config set registry https://registry.npmmirror.com

安装Hexo框架

1
2
# 安装hexo
npm install hexo-cli -g

初始化Hexo

1
2
3
4
5
6
# 安装hexo
sudo npm install hexo -g
# 此处可以是任意你喜欢的名字
mkdir blog
# 初始化部署hexo
hexo init blog

让Hexo在后台运行

1
npm install -g pm2
1
2
3
4
5
6
7
8
9
10
11
12
cat > hexo_run.js << 'EOF'
//run
const { exec } = require('child_process')
exec('hexo server',(error, stdout, stderr) => {
if(error){
console.log('exec error: ${error}')
return
}
console.log('stdout: ${stdout}');
console.log('stderr: ${stderr}');
})
EOF
1
pm2 start hexo_run.js

安装butterfly主题

1
2
# 下载稳定版butterfly主题
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

不用删除themes\butterfly\.gitthemes\butterfly\.github目录,之后通过配置 .gitmodules解决部署问题

修改 Hexo 根目录下的 _config.yml,把主题改为 butterfly

1
theme: butterfly

如果你没有 pug 以及 stylus 的渲染器,请下载安装:

1
npm install hexo-renderer-pug hexo-renderer-stylus --save

在 hexo 的根目录创建一个文件 _config.butterfly.yml,并把主题目录的 _config.yml 内容复制到 _config.butterfly.yml 去。这边我建议用cp命令,直接将主题的config内容复制到hexo根目录上

以后只需要在 _config.butterfly.yml 进行配置就行。如果使用了 _config.butterfly.yml, 配置主题的 _config.yml 将不会有效果。

Hexo 会自动合并主题中的 _config.yml 和 _config.butterfly.yml 里的配置,如果存在同名配置,会使用 _config.butterfly.yml 的配置,其优先度较高。

1
cp themes/butterfly/_config.yml  _config.butterfly.yml

配置博客

配置网站页面

打开hexo根目录的_config.yml

1
2
3
4
5
6
7
8
# Site
title: 一只白色
subtitle: White's Blog
description: '欢迎来到我的个人博客,这里记录日常,分享技术...'
keywords:
author: White
language: zh-CN
timezone: ''

副标题循环打字效果

_config.butterfly.yml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# The subtitle on homepage
subtitle:
# 是否开启:true:开启,false:不开启
enable: true
# 打字效果
effect: true
# 定制 typed.js
# https://github.com/mattboldt/typed.js/#customization
typed_option:
# source 调用第三方服务
# source: false 关闭调用
# source: 1 调用一言网的一句话(简体) https://hitokoto.cn/
# source: 2 调用一句网(简体) https://yijuzhan.com/
# source: 3 调用今日诗词(简体) https://www.jinrishici.com/
# subtitle 会先显示 source , 再显示 sub 的内容
source: false
# 如果关闭打字效果,subtitle 只会显示 sub 的第一行文字
sub:
- 你在抱怨什么呢
- 为明天到来的事,说人生像是没有意义
- 没有选择会是唯一的路
- 这不是你自己的问题,人终归要好好去生活

修改永久链接格式

修改hexo根目录的_config.yml

1
2
3
4
5
6
url: https://www.whitee.cn
permalink: :category/:id/ # 改成 '分类/id/' 格式
permalink_defaults: # 没有设置参数时使用的默认参数
pretty_urls:
trailing_index: true # 设置为 false 可从永久链接中移除结尾的“index.html”
trailing_html: true # 设置为 false 可从永久链接中移除结尾的“.html”

当我们发布文章时,在文章头部信息中添加id信息

1
2
3
4
5
6
7
---
title: 测试文章
date: 2021-04-22 11:02:53
id: blog001 # 此处对应url中的id部分
categories: []
tags: []
---

同时在_config.yml中修改category_map, 将很多category是中文的映射成英文

1
2
3
4
5
6
7
8
# Category & Tag
default_category: uncategorized
category_map:
Android: android
SQL: sql
工具: kits
数据库: database
tag_map:

目录配置

打开hexo根目录的_config.butterfly.yml

1
2
3
4
5
6
7
8
9
10
11
menu:
首页: / || fas fa-home # 目录
时光档案: /archives/ || fas fa-archive #档案
标签: /tags/ || fas fa-tags #标签
分类: /categories/ || fas fa-folder-open #分类
列表||fa fa-list || hide:
音乐: /music/ || fas fa-music
照片: /picture/ || fas fa-images
电影: /movies/ || fas fa-video
友链: /link/ || fas fa-link #友情链接
关于: /about/ || fas fa-heart #关于

社交设置

Butterfly 支持 font-awesome v6 图标。

修改主题配置文件_config.butterfly.yml

书写格式:图标名:url || 描述性文字

1
2
3
social:
fas fa-code-branch: https://gitee.com/whiteMf3 || Gitee || '#24292e'
fas fa-envelope: mailto:zyp0011@qq.com || Email || "#000000"

头像设置

1
2
3
4
favicon: /img/favicon.png #网站图标
avatar:
img: /img/avatar.png
effect: true # 头像会一直转圈

字体设置

  • 全局字体
1
2
3
4
5
6
7
# Global font settings
# Don't modify the following settings unless you know how they work (非必要不要修改)
font:
global_font_size: 16px
code_font_size: 14px
font_family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Lato, Roboto, "PingFang SC", "Microsoft JhengHei", "Microsoft YaHei", sans-serif
code_font_family: consolas, Menlo, "PingFang SC", "Microsoft JhengHei", "Microsoft YaHei", sans-serif

实际显示效果大概如下:

字体 平台 风格
-apple-system macOS/iPhone 苹果系统默认字体,非常舒服
BlinkMacSystemFont Chrome(mac) 同上
Segoe UI Windows Windows 10/11 默认界面字体
Helvetica Neue macOS 简洁现代
Lato Web字体 偏圆润、文艺
Roboto Android Google 官方字体
PingFang SC macOS 中文 苹方,清晰现代
Microsoft YaHei Windows 中文 微软雅黑,最常见
Microsoft JhengHei 繁体中文 微软正黑体
sans-serif 兜底字体 系统默认无衬线字体
  • Blog标题字体
1
2
3
4
5
# Font settings for the site title and site subtitle
# 左上角网站名字 主页居中网站名字
blog_title_font:
font_link: https://fonts.googleapis.com/css?family=Titillium+Web&display=swap
font-family: Titillium Web, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft JhengHei', 'Microsoft YaHei', sans-serif

效果:

字体 平台 特点
Consolas Windows 程序员最爱的等宽字体之一
Menlo macOS 苹果开发字体
PingFang SC 中文显示
Microsoft YaHei 中文显示
sans-serif 兜底

各类图片名称

  • 站点图标:favicon
  • 头像:avatar
  • 主页封面图片:index_img
  • 归档页顶部的图片:archive_img
  • 标签页顶部的图片:tag_img
  • 分类页顶部的图片:category_img
  • 文章封面:cover
  • 文章详情页的顶部图片:default_top_img
    • 3个参数均可影响,系统会优先选择优先级高的进行展示,优先级:Banner中的cover参数 > Banner中的top_img参数 > default_top_img

以上名称均在主题配置文件_config.butterfly.yml

标签、分类等页面 top_img 设置

_config.butterfly.yml中的如下配置

配置 解释
index_img 主页的 top_img,也就是主页遮罩图片
default_top_img 默认的 top_img,当页面(包括文章页)的 top_img 没有配置时,会显示 default_top_img
archive_img 归档页面的 top_img
tag_img tag 子页面的默认 top_img
tag_per_img tag 子页面的 top_img,可配置每个 tag 的 top_img
category_img category 子页面的默认 top_img
category_per_img category 子页面的 top_img,可配置每个 category 的 top_img
(tags/categories/自建页面) 和 文章页 的 top_img 需到对应的 md 页面设置 front-matter 中的 top_img
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Note: tag page, not tags page
tag_img: /img/tags.jpg

# The banner image of tag page, you can set the banner image for each tag
# Format:
# - tag name: xxxxx
tag_per_img:

# Note: category page, not categories page
category_img: /img/categories.jpg

# The banner image of category page, you can set the banner image for each category
# Format:
# - category name: xxxxx
category_per_img:
旅行: /img/category_trip.png
笔记: /img/category_note.png

页面顶部大图配置(Banner)

_config.butterfly.yml 配置:

1
2
3
4
index_img:        # 首页,一般不配
archive_img: # 归档页,直接配
tag_img: # 标签页,是给特定tag配置的默认背景
category_img: # 分类页,是给特定category配置的默认背景

标签 / 分类单独背景

1
2
3
4
tag_per_img:
- java: /img/java.jpg
- linux: /img/linux.jpg
category_per_img:

tags(不是tag) 页面背景配置的方法(categories同理)

1
2
# 找到这个文件
source/tags/index.md
1
2
3
4
5
# 在文件头部添加上这个
---
title: 标签
top_img: /img/tags.jpg
---

背景图和顶部脚步图设置

1
2
3
4
5
6
# 设置的是博客封面图和每篇文章头图
default_top_img: /img/default_top_img.png
# 设置为false使[页脚背景变透明设置]生效
footer_img: false
# 设置的是博客背景图,这里我们留空,自定义背景特效
background:

自定义文章卡片大小

首页一篇文章大概是这样:

1
2
3
4
#recent-posts
└── .recent-post-item ← 每一张卡片
├── .post_cover ← 左侧/顶部图片
└── .recent-post-info ← 文字区域(标题+摘要+meta)

将下面CSS样式加入博客根目录下的 source/css/custom.css 中

1
2
3
4
5
/* 首页卡片压缩 */
#recent-posts .recent-post-item {
height: 150px !important; /* 固定默认高度 */
min-height: 150px !important; /* 固定最小高度 */
}

自定义背景特效

修改_config.butterfly.yml中的如下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# canvas_ribbon (静止彩带背景)
# 见: https://github.com/hustcc/ribbon.js
canvas_ribbon:
enable: false
size: 150
alpha: 0.6
zIndex: -1
click_to_change: false # 是否每次点击都更换彩带
mobile: false # 是否在手机端显示

# Fluttering Ribbon (动态彩带)
canvas_fluttering_ribbon:
enable: false
mobile: false

# canvas_nest(星空粒子特效,会飘动)
# https://github.com/hustcc/canvas-nest.js
canvas_nest:
enable: false
color: '0,0,255' # 线条的颜色,默认: '0,0,0';RGB 值:(R,G,B)。(注意:用 ',' 分隔)
opacity: 0.7 # 线条的透明度 (0~1),默认: 0.5
zIndex: -1 # 背景的 z-index 属性,默认: -1
count: 99 # 线条的数量,默认: 99
mobile: false

代码块样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
code_blocks:
# 代码主题: darker / pale night / light / ocean / false
theme: light
# 左上角显示Mac窗口样式的圆点
macStyle: false
# 代码块高度限制 (unit: px),代码块限超过限制高度后会有展开按钮
height_limit: 400
# 代码自动换行,关闭滚动条
word_wrap: false

# Toolbar
# 是否展示复制按钮
copy: true
# 是否展示代码块所用语言
language: true
# true: 代码块默认不展开 / false: 代码块默认展开 | none: 展开并隐藏折叠按钮
shrink: false
# 是否展示代码块全屏按钮
fullpage: true

主题目录

1
2
3
hexo new page tags
hexo new page categories
hexo new page link

分别找到 source/tags/index.md、source/categories/index.md 、source/link/index.md 文件并编辑

1
2
3
4
5
6
7
---
title: 标签
date: 2018-01-05 00:00:00
type: 'tags'
orderby: random
order: 1
---
1
2
3
4
5
---
title: 分类
date: 2018-01-05 00:00:00
type: 'categories'
---
1
2
3
4
5
---
title: 友链
date: 2018-06-07 22:17:49
type: 'link'
---

数据来源

1
2
3
mkdir _data # 创建一个名为data的文件夹
touch link.yml # 创建一个名为link.yml的文件
vi link.yml # 编辑link.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- class_name: 友情链接
class_desc: 那些人,那些事
link_list:
- name: Hexo
link: https://hexo.io/zh-tw/
avatar: https://d33wubrfki0l68.cloudfront.net/6657ba50e702d84afb32fe846bed54fba1a77add/827ae/logo.svg
descr: 快速、简单且强大的网志框架

- class_name: 网站
class_desc: 值得推荐的网站
link_list:
- name: Youtube
link: https://www.youtube.com/
avatar: https://i.loli.net/2020/05/14/9ZkGg8v3azHJfM1.png
descr: 视频网站
- name: Weibo
link: https://www.weibo.com/
avatar: https://i.loli.net/2020/05/14/TLJBum386vcnI1P.png
descr: 中国最大社交分享平台
- name: Twitter
link: https://twitter.com/
avatar: https://i.loli.net/2020/05/14/5VyHPQqR6LWF39a.png
descr: 社交分享平台

音乐页面

需要根据 butterfly 版本选择

一、插件的安装与配置

1.安装hexo-tag-aplayer插件

执行命令:

1
npm install hexo-tag-aplayer --save

2.配置插件

找到项目文件夹根目录下的 _config.yml文件,添加如下代码:

1
2
3
aplayer:
meting: true
asset_inject: false

之后打开 _config.butterfly.yml文件,进行修改,这是为了引入刚才下载的插件。

1
2
3
4
# Inject the css and script (aplayer/meting)
aplayerInject:
enable: true
per_page: true

二、音乐页面配置

1.创建页面

如果还没有创建音乐页面,那就用以下命令创建:

1
hexo new page music

运行之后就会在source文件夹下生成一个music文件夹,打开music文件夹下的index.md文件,添加如下代码:

1
{% meting "18007803073" "netease" "playlist" "autoplay" "mutex:false" "listmaxheight:400px" "preload:none" "theme:#ad7a86"%}

MetingJS 是基于Meting API 的 APlayer 衍生播放器,引入 MetingJS 后,播放器将支持对于 QQ音乐、网易云音乐、虾米、酷狗、百度等平台的音乐播放。

server:netease(网易云音乐),tencent(QQ音乐),kugou(酷狗音乐),xiami(虾米音乐),baidu(百度音乐)。

type:song(歌曲),playlist(歌单),album(专辑),search(搜索关键字),artist(歌手)。添加单曲选的歌曲,歌单选择playlist,可以自行尝试。

id:就是在网页版上自己歌单的ID号,但是需要注意的是歌单中不能包含VIP音乐,不然无法播放。建议使用网易云音乐。

有关 {% meting %} 的选项列表如下:

选项 默认值 描述
id 必须值 歌曲 id / 播放列表 id / 相册 id / 搜索关键字
server 必须值 音乐平台: netease, tencent, kugou, xiami, baidu
type 必须值 song, playlist, album, search, artist
fixed false 开启固定模式
mini false 开启迷你模式
loop all 列表循环模式:all, one,none
order list 列表播放模式: list, random
volume 0.7 播放器音量
lrctype 0 歌词格式类型
listfolded false 指定音乐播放列表是否折叠
storagename metingjs LocalStorage 中存储播放器设定的键名
autoplay true 自动播放,移动端浏览器暂时不支持此功能
mutex true 该选项开启时,如果同页面有其他 aplayer 播放,该播放器会暂停
listmaxheight 340px 播放列表的最大长度
preload auto 音乐文件预载入模式,可选项: none, metadata, auto
theme #ad7a86 播放器风格色彩设置

2.全局吸底Aplayer模式

_config.butterfly.yml文件中修改如下:

1
2
3
4
inject:
head:
bottom:
- <div class="aplayer no-destroy" data-id="18007803073" data-server="netease" data-type="playlist" data-fixed="true" data-autoplay="true" data-lrcType="-1"> </div>

其中里面的参数都可以根据自己需要进行修改

如果想切换页面时,音乐不会中断,就在_config.butterfly.yml文件中 pjax修改为true

1
2
3
pjax:
enable: ture
exclude:

创建音乐页面

1
hexo new page music

在 _config.butterfly.yml 中注入必要的库

1
2
3
4
5
6
inject:
head:
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
bottom:
- <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/meting/dist/Meting.min.js"></script>

编辑 source/music/index.md

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
title: 音乐
date: 2026-06-01 13:36:09
top_img: /img/music.png
---

<meting-js
server="netease"
type="playlist"
id="18007803073"
autoplay="false"
mutex="true"
list-max-height="400px"
theme="#ad7a86">
</meting-js>
1
2
3
4
5
6
7
8
配置说明:
- server: 音乐平台(netease 网易云、tencent QQ音乐、kugou 酷狗)
- type: 类型(playlist 歌单、song 单曲、album 专辑)
- id: 歌单ID或歌曲ID
- autoplay: 是否自动播放(建议 false,避免浏览器限制)
- mutex: 是否互斥播放(true 只允许一个播放器播放)
- list-max-height: 播放列表最大高度
- theme: 主题颜色

创建新文章

如果资源只给特定的文章使用,可以将 config.yml 文件中的 post_asset_folder 选项设为 true,然后在每一次通过命令创建新文章时自动创建一个与文章 title 同名的文件夹,然后就可以把有关的资源放在这个关联文件夹中,再通过相对路径来引用它们

1
post_asset_folder: true

创建新文章

1
hexo new post <title>

文章封面卡片

主题文章卡片支持 7 种布局

1
index_layout: 3
配置值 解释
1 封面在左,信息在右
2 封面在右,信息在左
3 封面和信息左右交替显示
4 封面在上,信息在下
5 信息显示在封面上
6 瀑布流布局 - 封面在上,信息在下
7 瀑布流布局 - 信息显示在封面上

文章封面

1
2
3
4
5
6
7
8
9
10
11
cover:
# 主页是否显示文章封面
index_enable: true
# 侧栏是否显示文章封面
aside_enable: true
# 归档页面是否显示文章页面
archives_enable: true
default_cover:
- https://maodoo.oss-cn-beijing.aliyuncs.com/20241210172528345.jpg
- https://maodoo.oss-cn-beijing.aliyuncs.com/20241210172459243.png
#从这两个图片之中随机选取图片

文章标题区域显示

主题配置文件 (_config.butterfly.yml) 里,找到 post_meta 部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
post_meta:
page: # 首页
date_type: both # 日期显示方式,可选 created / updated / both
date_format: relative # 日期格式,可选 relative / default
categories: true # ✔️ 是否显示文章分类
tags: true # ✔️ 是否显示文章标签
categories: true # ✔️ 是否显示小图标/标签样式
label: true
post: # 文章页
position: left # 信息对齐方式
date_type: both
date_format: date
categories: true
tags: true
label: true

文章中 Front-matter 参数

参数 作用 解释
title 文章标题 作为文章标题展示
date 发布时间 会展示在标题旁边,并为归档页起到排序作用
tags 标签 文章的标签
categories 分类 文章的分类
cover 封面 首页文章卡片封面
top_img 顶图 文章顶部 Banner 大图
sticky 置顶 文章置顶,sticky 数值越大越靠前,butterfly 会先按 sticky 再按 date 排序
description 摘要 首页文章摘要、SEO 描述、社交分享摘要、Butterfly 卡片摘要,不存在则会截取正文前几行

文章 Front-matter 中的description

在文章顶部的的 Front-matter 里设置 description 字段,修改(_config.butterfly.yml)中的 index_post_content 参数,可以控制首页文章摘要

1
2
3
4
5
6
7
8
9
# Display the article introduction on homepage
# 1: description
# 2: 如果 description 存在, 展示 description, 否则展示 自动截取
# 3: 自动截取 (默认)
# false: 不展示文章描述
index_post_content:
method: 2
# 如果设置了 method 为 2 或 3, 截取长度就需要配置
length: 500

图片点击放大

_config.butterfly.fly修改以下内容

1
2
3
4
5
# Choose: fancybox / medium_zoom
# https://github.com/francoischalifour/medium-zoom
# https://fancyapps.com/fancybox/
# Leave it empty if you don't need lightbox
lightbox: fancybox

展示动态图片

优先使用链接形式的文件,本地文件似乎不可用

新增2个 js 文件和1个 css 文件

文件 说明
scripts/livephoto.js 注册 {% livephoto %} 标签
source/js/live-photo.js LivePhoto 样式
source/css/livephoto.css LivePhoto JS 逻辑

两个 js 文件的作用不同

文件 运行时机 作用
scripts/livephoto.js Hexo 构建时(服务端) 注册 {% livephoto %} 标签,把 Markdown 里的标签转成 HTML
source/js/live-photo.js 浏览器加载页面时(客户端) 处理 LivePhoto 的交互逻辑(悬停播放、点击播放、懒加载等)

livephoto.js 的配置文件中可以定义以下选项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const config = {
enable: true
autoplay: true // 是否自动播放(当进入视口时)
hover_to_play: true // 是否启用悬停播放
click_to_play: true // 是否启用点击播放
lazy_load: true // 是否启用懒加载
threshold: 0.8 // 触发自动播放的可见比例
badge: true // 是否显示Live标识
badge_text: 'Live' // 标识文字
badge_position: 'bottom-left' // 标识位置: bottom-left, bottom-right, top-left, top-right
loading_animation: true // 是否显示加载动画
preload: 'auto' // 视频预加载策略: auto, metadata, none
keep_observing: false // 是否持续观察元素
hover_delay: 300 // 悬停延迟(毫秒)
weixin_disable_autoplay: true // 是否禁用微信内置浏览器的自动播放
};

基本语法:

1
{% livephoto 图片路径 视频路径 %}

高级用法:

1
{% livephoto 图片路径 视频路径 "图片描述" "可选标题" "可选宽度" "可选高度" %}

一行显示两张动图:

1
2
3
4
<div style="display:flex;justify-content:center;gap:16px;flex-wrap:wrap;align-items:center;">
{% livephoto 图片路径 视频路径 %}
{% livephoto 图片路径 视频路径 %}
</div>

九宫格展示图片

myblog/source/css/下的custom.css中添加如下样式

由于在版权样式中的页脚背景变透明设置中已经引用了custom.css,所以直接添加就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* <div class="image-grid-nine">这个容器生效 */
.image-grid-nine {
display: grid; /* 使用grid布局,自动排列、分行、对齐 */
grid-template-columns: repeat(3, 1fr); /* 创建3列,三列平均分配宽度 */
gap: 10px; /* 图片之间间隔 10px */
margin: 10px 0; /* 图片上下留白,左右为0 */
}

/* 对 image-grid-nine 内部所有图片生效 */
.image-grid-nine img {
width: 100%; /* 图片占满自己的网格单元 */
aspect-ratio: 1 / 1; /* 强制图片显示为正方形 */
object-fit: cover; /* 图片自动裁剪填满区域,不会拉伸变形 */
border-radius: 12px; /* 圆角 */
display: block; /* 默认的inline参数会有底部空隙和对齐问题 */
transition: all 0.3s ease; /* 给动画增加过渡效果 */
}

/* 鼠标放上去时 */
.image-grid-nine img:hover {
transform: scale(1.03); /* 图片放大 1.03 倍 */
}

Markdown 这样写就可以

1
2
3
4
5
6
7
8
9
10
11
<div class="image-grid-nine">
<img src="1.jpg">
<img src="2.jpg">
<img src="3.jpg">
<img src="4.jpg">
<img src="5.jpg">
<img src="6.jpg">
<img src="7.jpg">
<img src="8.jpg">
<img src="9.jpg">
</div>

文章插入图片

  • 1
    ![](image.jpg "图片标题")
  • 1
    {% asset_img image.jpg 这是一张图片 %}
  • 1
    <img src="路径" alt="替代文本,图片无法加载时显示" style="zoom:50%;" width="200" height="200" title="图片标题,鼠标悬停在图片上时显示">

由于使用了post_asset_folder: true会给每个文章单独的资源文件夹

在hexo中,按理说应该是使用![](image.jpg),但网页中却无法正常显示。此时应该使用这样的方式来引入图片:

1
{% asset_img image.jpg 这是一张图片 %}

插件hexo-renderer-marked解决了这个问题。

可以只用npm install hexo-renderer-marked --save命令直接安装,之后在_config.yaml中更改配置如下:

1
2
3
4
post_asset_folder: true
marked:
prependRoot: true
postAsset: true

之后就可以在文章中愉快的插入图片了。

推荐写:

1
2
![](image.jpg)
![](./image.jpg)

不要写:

1
2
![](/image.jpg)
![](/mypost/image.jpg)

安装搜索插件

1
npm install hexo-generator-searchdb --save

_config.yml 改成:

1
2
3
4
5
search:
enable: true
path: search.xml
field: post
format: html
  • enable: true 必须有
  • limit 可以先去掉(避免兼容问题)

_config.butterfly.yml 改成:

1
2
3
4
5
6
search:
use: local_search

local_search:
enable: true
preload: false

强制清理缓存(很多人死在这一步)

1
2
3
4
hexo clean
rm -rf node_modules/.cache
hexo g
hexo s

图片懒加载插件

1
npm install hexo-lazyload-image --save

_config.yml 配置:

1
2
3
lazyload:
enable: true
loadingImg: /img/loading.gif

需要在/source/img目录下放置好loading.gif文件

字数统计插件

1
npm install hexo-wordcount --save

_config.butterfly.yml 配置:

1
2
3
4
5
6
7
8
9
# Need to install the hexo-wordcount plugin
wordcount:
enable: true
# Display the word count of the article in post meta
post_wordcount: true
# Display the time to read the article in post meta
min2read: true
# Display the total word count of the website in aside's webinfo
total_wordcount: true

统计访问人数 (UV 和 PV)

Butterfly很贴心地集成了不蒜子计数工具,可以统计网 站的访问数据(人数,次数等)

修改主题配置文件_config.butterfly.yml

1
2
3
4
busuanzi:
site_uv: true # 本站总访客数
site_pv: true # 本站总访问量
page_pv: true # 本文总阅读量

修改侧边栏

_config.butterfly.yml 配置:

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
aside:
enable: true
hide: false
button: true # 显示右下角用于隐藏侧边栏的按钮
mobile: true # 手机上是否显示
position: left # 侧边栏左右配置
display: # 是否展示归档、标签、分类数据
archive: true
tag: true
category: true
card_author: # 关于博主的一些信息
enable: true
description:
button:
enable: true
icon: fab fa-github
text: Follow Me
link: https://github.com/whiteMf3
card_announcement: # 公告信息
enable: false
content: 欢迎来到我的博客
card_recent_post: # 最新文章
enable: true
# If set 0 will show all
limit: 5
# Sort: date / updated
sort: date
sort_order:
card_newest_comments: # 最新评论
enable: false
sort_order:
limit: 6
# Unit: mins, save data to localStorage
storage: 10
avatar: true
card_categories:
enable: true
# If set 0 will show all
limit: 8
# Choose: none / true / false
expand: none
sort_order:
card_tags:
enable: true
# If set 0 will show all
limit: 40
color: false
custom_colors:
# Order of tags, random/name/length
orderby: random
# Sort of order. 1, asc for ascending; -1, desc for descending
order: 1
sort_order:
card_archives:
enable: true
# Type: monthly / yearly
type: monthly
# Eg: YYYY年MM月
format: MMMM YYYY
# Sort of order. 1, asc for ascending; -1, desc for descending
order: -1
# If set 0 will show all
limit: 8
sort_order:
card_post_series:
enable: true
# The title shows the series name
series_title: false
# Order by title or date
orderBy: 'date'
# Sort of order. 1, asc for ascending; -1, desc for descending
order: -1
card_webinfo: # 网站信息
enable: true
post_count: true
last_push_date: true
sort_order:
# Time difference between publish date and now
# Formal: Month/Day/Year Time or Year/Month/Day Time
# Leave it empty if you don't enable this feature
runtime_date:

版权样式

1
2
3
4
5
6
# 复制设置
copy:
enable: true # 是否开启网站复制权限
copyright: # 复制的内容后面加上版权信息
enable: false # 是否开启复制版权信息添加
limit_count: 50 # 字数限制,当复制文字大于这个字数限制时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 页脚设置
footer:
# 页脚导航(底部小菜单)
nav:
- title: 首页
link: /
- title: 关于
link: /about/
# 站点归属信息(年份 + 名称)如果你想自定义名字,一般是在 Hexo _config.yml 里的 <author: 你的名字>
owner:
enable: true
since: 2025
# Copyright of theme and framework
copyright:
enable: true
version: false
# 自定义文本,会显示在最下面一行(可以填入备案号等信息)
custom_text: <a href="https://beian.miit.gov.cn/#/Integrated/index"><img class="icp-icon" src="http://cdn.whitee.cn/img/icp.png">皖ICP备2026020001号-1</a>

页脚背景变透明设置

在你的博客目录里找到(如果没有就新建):

1
source/css/custom.css

然后加上:

1
2
3
4
5
6
7
8
#footer {
background: transparent !important;
box-shadow: none !important;
}

#footer::before {
background: transparent !important;
}

打开 _config.butterfly.yml,找到:

1
2
3
inject:
head:
bottom:

如果你没有自定义 CSS 引入,可以加:

1
2
3
inject:
head:
- <link rel="stylesheet" href="/css/custom.css">

如果你用了背景图,是这种配置,那透明 footer 才会有“嵌入感”。否则你只会看到白底(看起来像没变化)

1
background: /img/bg.jpg

页脚文字颜色设置

custom.css中加上以下配置

1
2
3
4
5
6
7
8
9
10
11
/* 页脚所有文字统一颜色 */
#footer,
#footer *,
#footer a {
color: #666666 !important;/* 网页安全色 */
}

/* 链接悬停恢复 Butterfly 默认颜色 */
#footer a:hover {
color: #49b1f5 !important;
}

新增自定义页面

进入博客根目录

1. 创建 scripts 目录

1
mkdir scripts

2. 创建中间件脚本

文件:/scripts/serve-static.js

1
2
3
4
5
6
7
8
9
const serveStatic = require('serve-static');
const path = require('path');

hexo.extend.filter.register('server_middleware', function(app) {
const staticDir = path.join(hexo.public_dir, 'static');
app.use('/static', serveStatic(staticDir, {
extensions: ['html']
}));
}, 1);

3. 修改_config.yml

1
2
skip_render:
- static/**

4.按照格式添加文件

在根目录创建文件存放目录

1
mkdir -p /source/static/custom
1
2
3
4
5
6
7
8
source
└── static
└── custom
├── index.html
├── css
│ └── hovertree.css
├── img
└── music

编辑 _config.butterfly.yml

1
2
menu:
自定义名称: /static/custom/ || fas fa-cube

之后就能通过首页右上角访问自定义的页面了

5.以后的用法

以后要加任何独立页面,只需要在 source/static/ 下建文件夹,结构随意:

1
2
3
4
5
6
7
8
9
10
11
12
13
source/static/
├── image/ ← 现有的 3D 相册
│ ├── index.html
│ ├── css/
│ ├── img/
│ └── music/
├── game/ ← 新加的小游戏
│ ├── index.html
│ └── assets/
├── tool/ ← 新加的工具页
│ └── index.html
└── demo/ ← 新加的演示页
└── index.html

Mermaid

使用 mermaid 标签可以绘制 Flowchart(流程图)、Sequence diagram(时序图 )、Class Diagram(类别图)、State Diagram(状态图)、Gantt(甘特图)和 Pie Chart(圆形图)

修改_config.butterfly.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Mermaid
# 设置enable为true
mermaid:
enable: true
# 设置为true可以用代码块绘制图形,hexo 版本需要 7.0 或以上, _config.yml 要添加 exclude_languages: ['mermaid']
code_write: true
# built-in themes: default / forest / dark / neutral
theme:
light: default
dark: dark
# Enable "Open in New Tab" button to view diagram in a separate window
open_in_new_tab: true
# Enable zoom and pan interactions on diagrams
zoom_pan: true

修改_config.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
syntax_highlighter: 'highlight.js'
highlight:
line_number: true
auto_detect: false
tab_replace: ''
wrap: true
hljs: false
exclude_languages: ['mermaid']
prismjs:
preprocess: true
line_number: true
tab_replace: ''
exclude_languages: ['mermaid']

自动生成sitemap

在Hexo根目录执行

1
npm install hexo-generator-sitemap --save

配置 _config.yml

1
2
3
4
sitemap:
path: sitemap.xml
tags: false # 不包含标签页
categories: false # 不包含分类页

以后每次 hexo generate 后,sitemap 会被放到最终网站的根目录

注意 _config.yml配置中有个非常重要的地方,就是URL一定要配置成你的真实域名

1
url: https://www.example.com

如果不想让某篇文章进入 sitemap,这个插件支持在文章 Front Matter 中做作如下设置,这样这篇文章就不会进入 sitemap

1
2
3
4
5
---
title: 测试文章
date: 2026-08-13
sitemap: false
---