记录 Hexobutterfly 搭建个人博客的过程

前世今生

关于前言

阅读本篇文章,你可以收获什么?

  • 至少把环境跑起来吧。。。不然我写这个有啥意义啊喂:weary:
  • en,你还可以对工程搭建有一丢丢的了解
  • 还可以对主题开发有一丢丢的了解,虽然了解了也没啥用:laughing:
  • 还可以get一丢丢的美化技巧:leopard:
  • 以及我的一些心路历程。。。

关于站点

尝试过自己写一个博客,springboot + vue + nuxt折腾来折腾去,耗费精力还是没有实现。

尝试过halowordpress,安装各种主题,blocksyZibll等,耗费经理还是没有实现。

尝试过在各大论坛写文章,CSDN,简书,掘金等,耗费精力还是没有坚持下去。

也尝试了很多其他的静态站点生成器:JerryVitePressVuePresshexo+next等等

关于SSG的技术选型

    1. Nanoc
    1. Middle Man App
    1. Hexo ← 宠幸他:heart:
    1. DocPad
    1. Hugo
    1. Jekyll
    1. Octopress
    1. Harp
    1. Sculpin
    1. Wintersmith

关于域名

nbchen.com,好早就用过这个名字了,年少张狂,意气风发

随着头发越掉越多,愈发觉得自己是个 臭弟弟 大帅比,就感觉要低调,谦逊。

故时常对自己 德不配位 恰到好处的 ID 感到惭愧

又因对自己第一个域名有着特殊的 XP 情感

所以在某个 大脑宕机 灵机一动的夜晚,直接买了十年

中间还用过 jiangnan.inklubandadada.site、等多个域名,特此纪念!

与自己定个十年之约 :clock10:

环境准备

工欲善其事,必先利其器

整体环境

  • 一个笔记本
  • 一个有趣的灵魂

windows环境

1
2
3
4
5
6
7
# 从官网上下载安装包,基本上next就行。
# 配置自己的github账号
git config --global user.name 'your_name'
git config --global user.email 'your_email'

# 配置ssh key连接到github
ssh-keygen -t rsa -C 'your_email'

备案相关

  • 公安备案
  • ICP备案
  • 域名备案
  • 服务器备案

安装hexo生成站点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
npm install hexo-cli -g
hexo init blog

# 其他命令:
## 一键本地启动
hexo clean && hexo g && hexo s
## 一键部署
hexo clean && hexo g && hexo d

## 创建子目录文章
hexo new post -p "数据存储/数据库/MySQL.md"
## 新建草稿(一些不想立即发布的文章)
hexo new draft "draft-name"
## 预览草稿
hexo s --drafts

安装butterfly主题

1
2
3
4
5
6
7
8
9
10
# 三种安装方式
## 1.npm安装
npm i hexo-theme-butterfly
## 2.master分支
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly
## 3. 比较新的开发分支【推荐】
git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

# 【可能遇到的问题】如果没有 pug 以及 stylus 的渲染器,需要下载安装
npm install hexo-renderer-pug hexo-renderer-stylus --save

强烈推荐的操作:(之后的教程也都是基于该步骤进行) 拷贝 butterfly 主题目录下的 _config.yml 到根目录下,命名为 _config.butterfly.yml

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

1
theme: butterfly

升级主题npm update hexo-theme-butterfly(适用于npm方式;git直接克隆后改动源码的想哭):cry:

站点配置

站点语言

修改站点配置文件 _config.yml

主题支持三种语言

  • default(en)
  • zh-CN (简体中文)
  • zh-TW (繁体中文)

网站资料

修改网站各种资料,例如标题、副标题和邮箱等个人资料,请修改博客根目录的_config.yml

1
2
3
4
5
6
7
8
9
10
11
12
# Site
title: 一个蹒跚学步的架构师
subtitle: '为何我身处人群,却时感孤独'
description: '学习是一被子的事,被子外只有学习两个字'
keywords: java,架构师
author: 一个蹒跚学步的架构师
language: zh-CN # deafult en
timezone: 'Asia/Shanghai'

# URL
## 在此处设置您的网站url。例如,如果您使用GitHub页面,请将url设置为'https://username.github.io/project'
url: https://nbchen.com

主题配置

该小节基本上是基于配置项设置自己喜欢的风格,不会涉及源码改动

导航设置

导航栏元信息:修改主题配置文件 _config.butterfly.yml

1
2
3
4
5
6
nav:
# Navigation bar logo image
logo: # 网站的 logo,支持图片,直接填入图片链接
display_title: true # 是否显示网站标题,填写 true 或者 false
# Whether to fix navigation bar
fixed: true # 是否固定状态栏,填写 true 或者 false

导航栏菜单:修改主题配置文件 _config.butterfly.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
menu:
# Home: / || fas fa-home
# List||fas fa-list:
# Music: /music/ || fas fa-music
# Movie: /movies/ || fas fa-video
首页: / || fas fa-home
归档: /archives/ || fas fa-archive
标签: /tags/ || fas fa-tags
分类: /categories/ || fas fa-folder-open
娱乐||fas fa-list:
音乐: /music/ || fas fa-music
照片: /photo/ || fa-solid fa-image
电影: /movies/ || fas fa-video
友链: /link/ || fas fa-link
闲言: /write/ || fa-solid fa-feather-pointed
留言: /talk2me/ || fas fa-comment-dots
关于: /about/ || fas fa-heart
# 留言板: /messageboard/ || fas fa-comment-dots
# 文档||fas fa-book:
# 🚀 快速开始: /posts/21cfbf15/
# 必须是 /xxx/,后面 || 分开,然后写图标名。菜单名称可自己修改

代码块设置

Butterfly 支持6种代码高亮样式:

  • darker
  • pale night
  • light
  • ocean
  • mac
  • mac light
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
code_blocks:
# 代码块主题: darker / pale night / light / ocean / false
theme: light
macStyle: true # false(默认) | true
# 代码块高度限制 (单位: px)
height_limit: 100 # false(默认) | 数值
# 代码块是否换行
word_wrap: false # false(默认) | true,需要将站点配置文件中的line_number改成false

# Toolbar
# 复制按钮是否显示
copy: true # false | true(默认)
# 代码语言是否显示
language: true # false | true(默认)
# 代码块收缩按钮 true: 自动折叠 | false: 展开 | none: 展开且隐藏按钮
shrink: false
fullpage: false

还可以自定义代码配色

修改站点配置文件 _config.yml

1
2
highlight: 
hljs: true # hljs高亮 false(默认) | true

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

1
2
3
4
5
6
7
code_blocks:
# 代码块主题: darker / pale night / light / ocean / false(自定义配色)
theme: false
inject:
head:
# 自定义代码配色的css
- <link rel="stylesheet" href="/self/duotone.css">

代码样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* 新添加的内容
-------------------------------------
--hl-color 代码框字体顔色 【必须】 (把下面 pre[class*="language-"]的 color 复制到这里来)
--hl-bg 代码框背景色 【必须】 (把下面 pre[class*="language-"]的 background复制到这里来)
--hltools-bg: #321a0f 代码框顶部工具栏背景色 【可选】(如果你关掉了 copy、lang 和 shrink,可不用配置这个)
--hltools-color: #fff 代码框顶部工具栏字体顔色 【可选】(如果你关掉了 copy、lang 和 shrink,可不用配置这个)
--hlnumber-bg: #221a0f 代码框行数背景色 【可选】(如果已经关掉 line_number,可以不用配置这个)
--hlnumber-color: #fff 代码框行数字体顔色 【可选】 (如果已经关掉 line_number,可以不用配置这个)
--hlscrollbar-bg: #d3af86 代码框滚动条顔色 【可选】(默认为主题主顔色)
--hlexpand-bg: #d3af86 代码框底部展开背景色 【可选】(如果已经关掉 highlight_height_limit,可以不用配置这个)
*/

:root {
--hl-color: #728fcb;
--hl-bg: #faf8f5;
--hltools-bg: xxxxxxx;
--hltools-color: xxxxxxx;
--hlnumber-bg: xxxxxxx;
--hlnumber-color: xxxxxxxx;
--hlscrollbar-bg: xxxxx;
--hlexpand-bg: xxxxxxx
}

社交图标

1
2
3
4
5
# 社交图标 Social media links
# 格式: icon: 链接 || 描述 || 颜色
social:
# fab fa-github: https://github.com/xxxxx || Github || '#24292e'
# fas fa-envelope: mailto:xxxxxx@gmail.com || Email || '#4a7dbe'

图片设置

站点图标

1
favicon: /img/favicon.png

头像

1
2
3
4
# 头像配置
avatar:
img: /img/butterfly-icon.png
effect: false # 头像会一直转圈

顶部图

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
# 顶部图是否显示 
disable_top_img: false # false(默认) | true

# If the banner of page not setting, it will show the default_top_img
default_top_img:

# 主页的 top_img
index_img:

# 归档页面的 top_img
archive_img:

# tag 子页面 的 默认 top_img,注意: tag 页, 不是 tags 页
tag_img:

# tag 子页面的 top_img,可配置每个 tag 的 top_img
# 格式:
# - 标签名: top_img地址
tag_per_img:
# aplayer: https://xxxxxx.png
# android: ddddddd.png

# category 子页面 的 默认 top_img,注意: category 页, 不是 categories 页
category_img:

# category 子页面的 top_img,可配置每个 category 的 top_img
# 格式:
# - 分类名: top_img地址
category_per_img:
# 随想: hdhdh.png
# 推荐: ddjdjdjd.png
# 地址背景颜色图片
footer_img: false # false(默认) | true

# 网站背景
# 默认显示白色,可设置图片或者颜色
# 图片格式 url(http://xxxxxx.com/xxx.jpg)
# 颜色(HEX值/RGB值/顔色单词/渐变色)
# 留空 不显示背景
# 留意: 如果你的网站根目录不是'/',使用本地图片时,需加上你的根目录。
# 例如:网站是 https://yoursite.com/blog,引用一张img/xx.png图片,则设置background为 `url(/blog/img/xx.png)
# background:'#49B202'
# background: url(https://i.loli.net/2019/09/09/5oDRkWVKctx2b6A.png)
background:

cover:
# 封面是否禁用
index_enable: true
aside_enable: true
archives_enable: true
# 如果封面没有设置时,默认展示的图片
default_cover:
# - xxx.jpg

文章封面

文章封面的获取顺序 Front-matter 的 cover > 配置文件的 default_cover > false

1
2
3
---
cover: # 单篇封面
---

页脚的背景图片

1
2
3
4
5
6
7
8
9
10
11
12
# 页脚的背景图片
# footer是否显示图片背景(与top_img一致)
# 留空/false 显示默认的顔色
# img链接 图片的链接,显示所配置的图片
# 顔色(
# HEX值 - #0000FF
# RGB值 - rgb(0,0,255)
# 顔色单词 - orange
# 渐变色 - linear-gradient( 135deg, #E2B0FF 10%, #9F44D3 100%)
# )
# true 显示跟 top_img 一样
footer_img: false # false(默认) | true

可以设置颜色的

站点背景

可以设置颜色和图片地址 图片格式: url(http://xxxxxx.com/xxx.jpg)

1
background: # '#b26770' # 不设置默认为蓝色

首页设置

文章元信息显示

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
# 文章元数据设置
post_meta:
# 主页页面
page:
# 日期类型: created / updated / both
date_type: created
# 日期格式: date / relative
date_format: date
# 是否显示分类
categories: true
# 是否显示标签
tags: false
# 是否显示文字标签
label: true
# 文章页面
post:
# 元数据位置: left / center
position: left
# 日期类型: created / updated / both
date_type: both
# 日期格式: date / relative
date_format: date
# 是否显示分类
categories: true
# 是否显示标签(建议不要超过5个)
tags: true
# 是否显示文字标签
label: true

首页顶部图大小

默认的显示为全屏,网站信息会居中显示

1
2
3
4
5
6
7
8
9
10
# --------------------------------------
# 首页设置
# --------------------------------------

# 首页头图的设置
# 默认: 头图全屏,站点信息在中间
# 站点信息的位置,例如: 300px/300em/300rem/10%
index_site_info_top:
# 头图的高度,例如: 300px/300em/300rem
index_top_img_height:

注意:index_top_img_height 的值不能使用百分比。
2 个都不填的话,会使用默认值

网站副标题打字机

可设置主页中显示的网站副标题或者喜欢的座右铭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 首页的副标题设置
subtitle:
# 是否启用副标题
enable: true
# 是否启用打字机效果
effect: true
# 自定义 typed.js
# https://github.com/mattboldt/typed.js/#customization
typed_option:
# 来源 - 调用第三方服务 API(仅限中文)
# 它将首先显示来源,然后显示副标题内容
# 选择: false/1/2/3
# false - 禁用此功能
# 1 - hitokoto.cn
# 2 - yijuzhan.com
# 3 - jinrishici.com
source: false
# 如果关闭打字机效果,副标题将仅显示 sub 的第一行内容
sub:
- 山高水长,怕什么来不及,慌什么到不了
- 生命只有一次, 你要活得畅快淋漓

首页卡片布局

1
2
3
4
5
6
7
8
9
# 首页文章佈局
#1:封面在左边,信息在右边
#2:封面在右边,信息在左边
#3:封面和信息左右交替
#4:封面在顶部,信息在底部
#5:封面上显示的信息
#6:砌体布局-顶部覆盖,底部信息
#7:砌体布局-封面上显示的信息
index_layout: 3

首页文章摘要

主页文章节选只支持自动摘要文章页description

1
2
3
4
5
6
7
8
9
# 在首页显示文章简介
# 1: 只显示 description
# 2: 优先选择 description,如果没有配置 description,则显示自动摘要的内容
# 3: 自动摘要(默认)
# false: 不显示文章简介
index_post_content:
method: 3
# 如果设置 method 为 2 或 3,需要配置长度
length: 500

文章设置

文章TOC

在侧边栏显示 TOC(文章目录)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# --------------------------------------
# 文章设置
# --------------------------------------

toc:
# 是否在文章中显示目录
post: true
# 是否在页面中显示目录
page: false
# 是否显示目录编号
number: true
# 是否默认展开目录
expand: false
# 是否使用简洁风格(仅适用于文章)
style_simple: false
# 是否显示滚动百分比
scroll_percent: true

文章版权

1
2
3
4
5
6
7
8
9
10
11
12
post_copyright:
# 是否启用版权声明
enable: true
# 是否进行文章 URL 解码
decode: false
# 作者链接
author_href:
# 许可证类型
license: CC BY-NC-SA 4.0
# 许可证链接
license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/

如果有文章(例如:转载文章)不需要显示版权,可以在文章 Front-matter 单独设置 copyright: false

文章打赏

在你每篇文章的结尾,可以添加赞助按钮。相关二维码可以自行配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 贊助/打赏
reward:
# 是否启用打赏
enable: true
# 打赏案例文本
text: 赛博打赏
QR_code:
- img: /img/site/wechat.png
link:
text: 微信
- img: /img/site/alipay.png
link:
text: 支付宝

文章编辑按钮

在文章标题旁边显示一个编辑按钮,点击会跳转到对应的链接去。

1
2
3
4
5
6
7
8
9
# 文章编辑
# 轻鬆在线浏览和编辑博客源代码
post_edit:
# 是否启用在线编辑
enable: false
# url: https://github.com/用户名/仓库名/edit/分支名/子目录名/
# 例如: https://github.com/jerryc127/butterfly.js.org/edit/main/source/
url:

相关文章

当文章封面设置为 false 时,或者没有获取到封面配置,相关文章背景将会显示主题色。

相关文章推荐的原理是根据文章 tags 的比重来推荐

1
2
3
4
5
6
7
8
# 相关文章
related_post:
# 是否显示相关文章
enable: true
# 显示的文章数量
limit: 6
# 选择: created / updated
date_type: created

文章分页按钮

当文章封面设置为 false 时,或者没有获取到封面配置,分页背景将会显示主题色。

可设置分页的逻辑,也可以关闭分页显示

1
2
3
4
5
# 选择: 1 / 2 / false
# 1: “下一篇文章”将链接到旧文章
# 2: “下一篇文章”将链接到新文章
# false: 禁用分页
post_pagination: 1

文章过期提醒

可设置是否显示文章过期提醒,以更新时间为基准。

1
2
3
4
5
6
7
8
9
10
11
12
# 显示文章过期通知
noticeOutdate:
# 是否启用过期通知
enable: false
# 样式: simple / flat
style: flat
# 多少天后显示通知
limit_day: 365
# 位置: top / bottom
position: top
message_prev: 已经过了
message_next: 天自上次更新,文章内容可能已过时。

文章URL设置

1.修改_config.yml

1
permalink: posts/:id # 文章的 永久链接

2.写文章时原信息添加id: 自定义URL

隐藏页面标题

有时候可能想隐藏某个页面的标题,直接在page页面添加样式

1
2
3
4
5
<style>
.page-title {
display: none;
}
</style>

页脚设置

页脚博客年份

since 是一个来展示你站点起始时间的选项。它位于页面的最底部。

1
2
3
4
5
6
7
8
9
10
11
12
13
# --------------------------------------
# 页脚设置
# --------------------------------------
footer:
owner:
# 是否启用所有者显示
enable: true
# 网站创建年份
since: 2024
# 自定义文本
custom_text:
# 主题和框架的版权声明
copyright: true

页脚自定义文本

custom_text是一个给你用来在页脚自定义文本的选项。通常你可以在这里写声明文本等,支持 HTML。

1
custom_text: Hi, welcome to my <a href="https://butterfly.js.org/">blog</a>!

对于部分人需要写 ICP 的,也可以写在 custom_text里

1
custom_text: <a href="icp链接"><img class="icp-icon" src="icp图片"><span>备案号:xxxxxx-x</span></a>

页脚徽章

用徽章显示:https://shields.io/badges

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
footer:
custom_text:
<p>
<a style="margin-inline:5px"target="_blank" href="https://hexo.io/">
<img src="https://img.shields.io/badge/Frame-Hexo-blue?style=plastic&logo=hexo" title="博客框架为 Hexo" alt="HEXO">
</a>
<a style="margin-inline:5px"target="_blank" href="https://butterfly.js.org/">
<img src="https://img.shields.io/badge/Theme-Butterfly-6513df?style=plastic&logo=bitdefender" title="主题采用 Butterfly" alt="Butterfly">
</a>
<a style="margin-inline:5px"target="_blank" href="https://github.com/">
<img src="https://img.shields.io/badge/Source-Github-d021d6?style=plastic&logo=GitHub" title="本站项目由 GitHub 托管" alt="GitHub">
</a>
<a style="margin-inline:5px"target="_blank"href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
<img src="https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=plastic&logo=Claris" alt="img" title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可">
</a>
</p>
# custom_text: <a href="https://beian.miit.gov.cn/#/Integrated/index"><span>备案号:闽ICP备2022007849号-1</span></a> <a href="https://beian.mps.gov.cn/#/query/webSearch"><img class="icp-icon" src="/img/site/icp.png"><span>闽ICP备2022007849号</span></a>


# 主题和框架的版权声明
copyright: false

侧边栏设置

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
# --------------------------------------
# 侧边栏设置
# --------------------------------------

aside:
# 是否启用侧边栏
enable: true
# 是否默认隐藏侧边栏
hide: false
# 是否在右下角显示隐藏侧边栏的按钮
button: true
# 移动设备上是否启用侧边栏
mobile: true
# 侧边栏位置:left / right
position: right
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/xxxxxx
card_announcement:
# 是否显示公告卡片
enable: true
# 公告内容
content: This is my Blog
card_recent_post:
# 是否显示最近文章卡片
enable: true
# 显示文章数量,0 表示显示所有
limit: 5
# 排序方式:date / updated
sort: date
sort_order:
card_newest_comments:
# 是否显示最新评论卡片
enable: false
sort_order:
# 显示评论数量
limit: 6
# 单位:分钟,保存数据到 localStorage
storage: 10
# 是否显示头像
avatar: true
card_categories:
# 是否显示分类卡片
enable: true
# 显示分类数量,0 表示显示所有
limit: 8
# 选择:none / true / false
expand: none
sort_order:
card_tags:
# 是否显示标签卡片
enable: true
# 显示标签数量,0 表示显示所有
limit: 40
# 是否启用颜色
color: false
# 标签排序方式:random/name/length
orderby: random
# 排序顺序:1 表示升序,-1 表示降序
order: 1
sort_order:
card_archives:
# 是否显示归档卡片
enable: true
# 归档类型:monthly / yearly
type: monthly
# 日期格式,例如:YYYY年MM月
format: MMMM YYYY
# 排序顺序:1 表示升序,-1 表示降序
order: -1
# 显示归档数量,0 表示显示所有
limit: 8
sort_order:
card_post_series:
# 是否显示系列文章卡片
enable: true
# 标题显示系列名称
series_title: false
# 排序方式:title 或 date
orderBy: 'date'
# 排序顺序:1 表示升序,-1 表示降序
order: -1
card_webinfo:
# 是否显示网站信息卡片
enable: true
# 是否显示文章数量
post_count: true
# 是否显示最后推送日期
last_push_date: true
sort_order:
# 发佈日期与当前日期的时间差
# 格式:Month/Day/Year Time 或 Year/Month/Day Time
# 如果不启用此功能,请留空
runtime_date:

右侧按钮

按钮位置

当开启 chat 聊天服务后,聊天服务的按钮可能会遮挡到右下角的按钮,可以设置按钮的位置。

非必要不建议设置,默认就行

1
2
# 右下角按钮与底部的距离(默认单位:px)
rightside_bottom:

简繁切换

主题内置了一个简单的简繁转换功能,採用一对一的形式配对。遇到一字多繁或者一字多简的情况下,会出现不能正常转换正确的简繁体,请留意。

开启后,右下角会有简繁转换按钮。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 简繁转换设置
translate:
# 是否启用简繁转换
enable: false
# 按钮文本
default:
# 网站语言(1 - 繁体中文 / 2 - 简体中文)
defaultEncoding: 2
# 转换延迟
translateDelay: 0
# 按钮在简体中文时的文本
msgToTraditionalChinese: '繁'
# 按钮在繁体中文时的文本
msgToSimplifiedChinese: '简'

阅读模式

阅读模式下会去掉除文章外的内容,避免干扰阅读。只会出现在文章页面,右下角会有阅读模式按钮。

1
2
# 阅读模式
readmode: true

夜间模式

右下角会有夜间模式按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 暗黑模式设置
darkmode:
# 是否启用暗黑模式
enable: true
# 切换暗黑/明亮模式的按钮
button: true
# 是否自动切换暗黑/明亮模式
# autoChangeMode: 1 跟随系统设置,如果系统不支持暗黑模式,则在晚上 6 点到早上 6 点之间切换暗黑模式
# autoChangeMode: 2 在晚上 6 点到早上 6 点之间切换暗黑模式
# autoChangeMode: false 不自动切换
autoChangeMode: false
# 设置明亮模式时间,值在 0 到 24 之间。如果未设置,默认值为 6 和 18
start:
end:

滚动状态百分比

1
2
# 在返回顶部按钮中显示滚动百分比
rightside_scroll_percent: false

按钮排序

可对右下角按钮进行排序

注意: 不要重复

1
2
3
4
5
6
7
8
9
10
# 不要修改以下设置,除非你知道它们的工作原理
# 选择:readmode,translate,darkmode,hideAside,toc,chat,comment
# 不要重复相同的值
rightside_item_order:
# 是否启用右侧项目顺序
enable: false
# 隐藏的默认项目:readmode,translate,darkmode,hideAside
hide:
# 显示的默认项目:toc,chat,comment
show:

全局设置

页面锚点

开启页面锚点后,当你在进行滚动时,页面链接会根据标题 ID 进行替换
(注意: 每替换一次,会留下一个历史记录。所以如果一篇文章有很多锚点的话,网页的历史记录会很多。)

1
2
3
4
5
6
# 锚点设置
anchor:
# 滚动时,URL 将根据标题 ID 更新
auto_update: false
# 点击标题滚动并更新锚点
click_to_scroll: false

图片描述

可开启图片 Figcaption 描述文字显示

优先显示图片的 title 属性,然后是 alt 属性

1
2
# 图片标题
photofigcaption: false

复制相关

可配置网站是否可以复制、复制的内容是否添加版权信息

1
2
3
4
5
6
7
8
9
# 复制设置
copy:
# 是否启用复制功能
enable: true
# 在复制的内容后添加版权信息
copyright:
enable: false
# 当复制字符数超过 limit_count 时添加版权信息
limit_count: 150

字数统计

开启字数统计功能,需要安装hexo-wordcount插件

hexo 工作目录下运行 npm install hexo-wordcount --save or yarn add hexo-wordcount

1
2
3
4
5
6
7
8
9
10
# 需要安装 hexo-wordcount 插件
wordcount:
# 是否启用字数统计
enable: false
# 在文章元信息中显示字数统计
post_wordcount: true
# 在文章元信息中显示閲读时间
min2read: true
# 在侧边栏网站信息中显示总字数
total_wordcount: true

访问人数

访问 busuanzi 的官方网站查看更多的介绍。

由于 busuanzi 的稳定性问题,偶尔会遇到无法访问的情况,请留意。

文章页的访问人数统计,是通过 busuanzi 这个插件实现的。个别评论系统自带访问人数统计功能,可以在相对应的评论系统配置中进行开启,其会代替 busuanzi 的统计。

1
2
3
4
5
6
7
8
# 不蒜子 PV / UV 统计
busuanzi:
# 网站 UV 统计
site_uv: true
# 网站 PV 统计
site_pv: true
# 页面 PV 统计
page_pv: true

如果需要修改 busuanzi 的 CDN 链接,可通过 主题配置文件 的 CDN 中的 option 进行修改

1
2
3
CDN:
option:
busuanzi: xxxxx

数学公式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 关于 per_page
# 如果设置为 true,将在每个页面加载 mathjax/katex 脚本
# 如果设置为 false,将根据你的设置加载 mathjax/katex 脚本(在页面的 front-matter 中添加 'mathjax: true' 或者 'katex: true')
math:
# 选择:mathjax, katex
# 如果不需要数学公式,保持为空
use:
per_page: true
hide_scrollbar: false

mathjax:
# 启用上下文菜单
enableMenu: true
# 选择:all / ams / none,这控制是否对公式编号以及如何编号
tags: none

katex:
# 启用复制 KaTeX 公式
copy_tex: false

Mathjax

1
2
3
npm uninstall hexo-renderer-marked --save
npm install hexo-renderer-kramed --save

katex

卸载hexo默认的 marked插件

1
2
3
4
5
6
npm un hexo-renderer-marked --save # 如果有安装这个的话,卸载
npm un hexo-renderer-kramed --save # 如果有安装这个的话,卸载

npm i hexo-renderer-markdown-it --save # 需要安装这个渲染插件
npm install katex @renbaoshuo/markdown-it-katex #需要安装这个katex插件

在 hexo 的根目录的 _config.yml 中配置

1
2
3
markdown:
plugins:
- '@renbaoshuo/markdown-it-katex'

搜索设置

主题支持三种搜索方式(algolia_search / local_search / docsearch),你可以选择一种或者多种搜索方式。

本地搜索

1.你需要安装 hexo-generator-searchdb 或者 hexo-generator-search,根据它的文档去做相应配置

2.把主题配置文件中 search 的 use 配置为 local_search

1
npm install hexo-generator-search --save

3.配置搜索

1
2
3
4
5
6
7
8
search:
# 选择:algolia_search / local_search / docsearch
# 如果不需要搜索功能,保持为空
use: local_search
placeholder:
# 本地搜索
local_search:
enable: true

分享系统

主题支持两种分享方式,一种是sharejs,一种是addtoany

1
2
3
4
5
6
7
8
9
10
11
12
13
14
share:
# 选择:sharejs / addtoany
# 如果不需要分享功能,保持为空
use: sharejs

# Share.js
# https://github.com/overtrue/share.js
sharejs:
sites: facebook,twitter,wechat,weibo,qq

# AddToAny
# https://www.addtoany.com/
addtoany:
item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link

评论系统

  • Disqus: 功能强大,但是需要科学上网

  • Gitment:第一款利用 GitHub Issues 的评论系统,但是作者弃坑了

  • Valine: 从v1.4.0后暂停更新,开始闭源,且需要结合LeanCloud

  • Waline: 从 Valine 衍生的带后端评论系统

  • 畅言:广告占位且强制用户绑定手机号

  • LiveRe来必力: 科学上网

  • Utterances: 科学上网

  • Giscus:依赖Github Discussions

  • Gittalk 评论: 要用到GitHub OAuth

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

comments:
# 最多两个评论系统,第一个将作为默认显示
# 如果不需要评论功能,保持为空
# 选择:Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/Artalk
# 两个评论系统的格式:Disqus,Waline
use: gitalk
# 按钮旁边显示评论系统名称
text: true
# 懒加载:评论系统将在评论元素进入浏览器视口时加载
# 如果设置为 true,评论计数将无效
lazyload: false
# 在文章顶部图片中显示评论计数
count: false
# 在主页显示评论计数
card_post_count: false

# Gitalk 评论插件配置
# 官方文档:https://github.com/gitalk/gitalk
gitalk:
# GitHub 应用的客户端 ID
client_id: xx
# GitHub 应用的客户端密钥
client_secret: xx
# 存储评论的仓库名称
repo: zuoer96.github.io
# 仓库拥有者的用户名
owner: zuoer96
# 管理员用户名列表
admin: zuoer96
# 其他可选配置
option:

聊天服务

不想设置在线聊天系统,所以没有整理相关内容

网页收录

如果需要搜索引擎收录网站,可能需要登录对应搜索引擎的管理平台进行提交。
各自的验证码可从各自管理平台拿到

1
2
3
4
5
6
7
8
9
10
11
site_verification:
# - name: google-site-verification
# content: NdIUXAOVyGnnBhcrip0ksCawbdAzT0hlBZDE9u4jx6k
# - name: msvalidate.01
# content: 567E47D75E8DCF1282B9623AD914701E
# - name: baidu-site-verification
# content: code-pE5rnuxcfD
# - name: google-site-verification
# content: xxxxxx
# - name: baidu-site-verification
# content: xxxxxxx
1
2
3
4
# 选择第二个验证,在设置里找到HTML标记验证里的字符串,配置到配置文件
site_verification:
- name: google-site-verification
content: xxxxx

分析统计

百度统计

1.登录百度统计的官方网站

2.找到你百度统计的统计代码

1
baidu_analytics: xxxxx

谷歌分析

1
2
3
# 谷歌分析配置-数据收集和修改-数据流
# 官方网站:https://analytics.google.com/analytics/web/
google_analytics: xxx

广告配置

谷歌广告

1
google_analytics: xxx

美化效果

自定义主题色

可以修改大部分 UI 颜色

修改 主题配置文件,比如:

颜色值必须被双引号包裹,就像”#000”而不是#000。否则将会在构建的时候报错!

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
# 主题颜色自定义
# 注意:颜色值必须用双引号,如 "#000",否则可能会导致错误!

# 主题颜色配置
# theme_color:
# 是否启用主题颜色
# enable: true
# 主颜色
# main: "#49B1F5"
# 分页器颜色
# paginator: "#00c4b6"
# 按钮悬停颜色
# button_hover: "#FF7242"
# 文本选择颜色
# text_selection: "#00c4b6"
# 链接颜色
# link_color: "#99a9bf"
# 元数据颜色
# meta_color: "#858585"
# 水平线颜色
# hr_color: "#A4D8FA"
# 代码前景色
# code_foreground: "#F47466"
# 代码背景色
# code_background: "rgba(27, 31, 35, .05)"
# 目录颜色
# toc_color: "#00c4b6"
# 引用块填充颜色
# blockquote_padding_color: "#49b1f5"
# 引用块背景颜色
# blockquote_background_color: "#49b1f5"
# 滚动条颜色
# scrollbar_color: "#49b1f5"
# 浅色模式下的主题颜色
# meta_theme_color_light: "ffffff"
# 深色模式下的主题颜色
# meta_theme_color_dark: "#0d0d0d"

文字左右对齐

可设置文字向两侧对齐,对最后一行无效

1
2
# 拉伸行使每行宽度相等
text_align_justify: false

黑色遮罩

为了避免图片过于鲜艳而导致文字无法阅读,默认为顶部图和页脚添加黑色遮罩

1
2
3
4
# 为页眉和页脚添加遮罩
mask:
header: true
footer: true

页面加载动画 preloader

当进入网页时,因为加载速度的问题,可能会导致 top_img 图片出现断层显示,或者网页加载不全而出现等待时间,开启 preloader 后,会显示加载动画,等页面加载完,加载动画会消失。

1
2
3
4
5
6
7
8
9
10
# 加载动画
preloader:
# 是否启用加载动画
enable: false
# 资源
# 1. 全屏加载
# 2. 进度条
source: 1
# pace 主题 (参见 https://codebyzach.github.io/pace/)
pace_css_url:

页面美化

会改变 olulh1-h5 的样式

field配置生效的区域

  • post 只在文章页生效
  • site 在全站生效
1
2
3
4
5
6
7
8
9
10
11
# 美化文章内容的配置
beautify:
# 是否启用美化
enable: false
# 指定美化的范围 (site 或 post)
field: post
# 指定标题前缀图标,如 '\f0c1' , 填写的是fontawesome的icon的Unicode数。
title-prefix-icon:
# 指定标题前缀图标的颜色,如 '#F47466'
title-prefix-icon-color:

全局字体

可自行设置字体的font-family

1
2
3
4
5
6
7
8
# 全局字体设置
# 除非您知道它们的工作原理,否则不要修改以下设置
font:
global-font-size:
code-font-size:
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

博客字体

可自行设置字体的font-family

如不需要配置,请留空。

如不需要使用网络字体,只需要把 font_link 留空就行

1
2
3
4
5
# 左上角网站名字 主页居中网站名字
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

打字效果

1
2
3
4
5
6
7
8
9
10
11
12
# 打字机效果
# https://github.com/disjukr/activate-power-mode
activate_power_mode:
# 是否启用打字机效果
enable: false
# 是否启用彩色效果
colorful: true
# 是否启用震动效果
shake: true
# 是否在移动设备上启用
mobile: false

背景特效

好看的綵带背景,可设置每次刷新更换綵带,或者每次点击更换綵带

  • 禁止彩带
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# canvas_ribbon
# 参见: https://github.com/hustcc/ribbon.js
canvas_ribbon:
# 是否启用 canvas_ribbon
enable: false
# ribbon 的大小
size: 150
# ribbon 的不透明度 (0 ~ 1)
alpha: 0.6
zIndex: -1
# 是否点击更改颜色
click_to_change: false
# 是否在移动设备上启用
mobile: false
  • 动态彩带
1
2
3
4
5
6
7
# Fluttering Ribbon
canvas_fluttering_ribbon:
# 是否启用 Fluttering Ribbon
enable: false
# 是否在移动设备上启用
mobile: false

  • canvas_nest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# canvas_nest
# https://github.com/hustcc/canvas-nest.js
canvas_nest:
# 是否启用 canvas_nest
enable: false
# 线条颜色,默认: '0,0,0'; RGB 值: (R,G,B).(注意: 使用 ',' 分隔.)
color: '0,0,255'
# 线条的不透明度 (0~1)
opacity: 0.7
# 背景的 z-index 属性
zIndex: -1
# 线条数量
count: 99
# 是否在移动设备上启用
mobile: false

鼠标点击效果

  • 烟花
1
2
3
4
5
6
7
8
# 鼠标点击效果: 烟花
fireworks:
# 是否启用烟花效果
enable: false
zIndex: 9999
# 是否在移动设备上启用
mobile: false

  • 爱心
1
2
3
4
5
6
7
8
# 鼠标点击效果: 心形符号
click_heart:
# 是否启用心形符号效果
enable: false
# 是否在移动设备上启用
mobile: false


  • 文字
1
2
3
4
5
6
7
8
9
10
11
12
13
# 鼠标点击效果: 文字
clickShowText:
# 是否启用文字效果
enable: false
text:
# - I
# - LOVE
# - YOU
fontSize: 15px
# 是否随机显示文字
random: false
# 是否在移动设备上启用
mobile: false

灯箱设置

图片大图查看模式

1
2
3
4
5
6
# 选择: fancybox / medium_zoom
# https://github.com/francoischalifour/medium-zoom
# https://fancyapps.com/fancybox/
# 如果不需要灯箱效果,请留空
lightbox:

其他设置

Pjax

当用户点击链接,通过 ajax 更新页面需要变化的部分,然后使用 HTML5 的 pushState 修改浏览器的 URL 地址。

这样可以不用重复加载相同的资源(css/js), 从而提升网页的加载速度。

1
2
3
4
5
6
7
8
# https://github.com/MoOx/pjax
pjax:
# 是否启用 pjax
enable: false
# 排除指定页面不使用 pjax,如 '/music/'
exclude:
# - /xxxxxx/

注意:

  • 对于一些第三方插件,有些并不支持 pjax 。你可以把网页加入到 exclude 里,这个网页会被 pjax 排除在外。点击该网页会重新加载网站
  • 使用 pjax 后,一些自己 DIY 的 js 可能会无效,跳转页面时需要重新调用,请参考Pjax 文档
  • 使用 pjax 后,一些个别页面加载的 js/css,将会改为所有页面都加载

Snackbar弹窗

比如代码块复制成功,通过弹窗提示

1
2
3
4
5
6
7
8
9
10
11
# Snackbar - Toast 通知
# https://github.com/polonel/SnackBar
# 位置: top-left / top-center / top-right / bottom-left / bottom-center / bottom-right
snackbar:
# 是否启用 Snackbar
enable: false
# 通知位置
position: bottom-left
# 浅色模式和深色模式下的通知背景颜色
bg_light: '#49b1f5'
bg_dark: '#1f1f1f'

Instantpage

当鼠标悬停到链接上超过 65 毫秒时,Instantpage 会对该链接进行预加载,可以提升访问速度。

1
2
3
# https://instant.page/
# prefetch (预加载)
instantpage: true

Pangu

如果你跟我一样,每次看到网页上的中文字和英文、数字、符号挤在一块,就会坐立难安,忍不住想在它们之间加个空格。这个外挂正是你在网路世界走跳所需要的东西,它会自动替你在网页中所有的中文字和半形的英文、数字、符号之间插入空白。

1
2
3
4
5
6
7
# Pangu - 在中文字符和英文字符之间插入空格
# https://github.com/vinta/pangu.js
pangu:
# 是否启用 Pangu
enable: false
# 指定使用 Pangu 的范围(site 或 post)
field: site

PWA

要为Butterfly配上 PWA 特性, 你需要如下几个步骤:

  • 打开 hexo 工作目录

  • npm install hexo-offline --save 或者 yarn add hexo-offline

  • hexo-offline :在根目录创建 hexo-offline.config.cjs 文件,并增加以下内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// offline config passed to workbox-build.
module.exports = {
globPatterns: ['**/*.{js,html,css,png,jpg,gif,svg,webp,eot,ttf,woff,woff2}'],
// 静态文件合集,如果你的站点使用了例如 webp 格式的文件,请将文件类型添加进去。
globDirectory: 'public',
swDest: 'public/service-worker.js',
maximumFileSizeToCacheInBytes: 10485760, // 缓存的最大文件大小,以字节为单位。
skipWaiting: true,
clientsClaim: true,
runtimeCaching: [
// 如果你需要加载 CDN 资源,请配置该选项,如果没有,可以不配置。
// CDNs - should be CacheFirst, since they should be used specific versions so should not change
{
urlPattern: /^https:\/\/cdn\.example\.com\/.*/, // 可替换成你的 URL
handler: 'CacheFirst'
}
]
}

4.在主题配置文件中开启 pwa 选项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# PWA
# 参见 https://github.com/JLHwung/hexo-offline
# ---------------
pwa:
# 是否启用 PWA
enable: false
# PWA manifest 文件路径
manifest:
# Apple Touch 图标路径
apple_touch_icon:
# 32x32 像素的 favicon 图标路径
favicon_32_32:
# 16x16 像素的 favicon 图标路径
favicon_16_16:
# mask 图标路径
mask_icon:

5.在创建source/目录中创建manifest.json文件。

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
{
"name": "string",
"short_name": "Junzhou",
"theme_color": "#49b1f5",
"background_color": "#49b1f5",
"display": "standalone",
"scope": "/",
"start_url": "/",
"icons": [
{
"src": "images/pwaicons/36.png",
"sizes": "36x36",
"type": "image/png"
},
{
"src": "images/pwaicons/48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "images/pwaicons/72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "images/pwaicons/96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "images/pwaicons/144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "images/pwaicons/192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "images/pwaicons/512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"splash_pages": null
}

你也可以通过 Web App Manifest快速创建manifest.json。(Web App Manifest 要求至少包含一个 512*512 像素的图标)

Open Graph

在 head 里增加一些 meta 资料,例如缩略图、标题、时间等等。当你分享网页到一些平台时,平台会读取 Open Graph 的内容,展示缩略图,标题等等信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
# Open graph meta tags
# https://hexo.io/docs/helpers#open-graph
Open_Graph_meta:
enable: true
option:
# twitter_card:
# twitter_image:
# twitter_id:
# twitter_site:
# google_plus:
# fb_admins:
# fb_app_id:

CSS 前缀

有些 CSS 并不是所有浏览器都支持,需要增加对应的前缀才会生效。

开启 css_prefix 后,会自动为一些 CSS 增加前缀。(会增加 20%的体积)

1
2
3
# 添加供应商前缀以确保兼容性
# 是否启用 CSS 前缀
css_prefix: true

Inject

如想添加额外的 js/css/meta 等等东西,可以在 Inject 里添加,支持添加到 head(</body>标签之前)和 bottom(</html>标签之前)。

请注意:以标准的 html 格式添加内容

1
2
3
4
5
6
inject:
head:
- <link rel="stylesheet" href="/self.css">
bottom:
- <script src="xxxx"></script>

CDN

配置文件中最后一部分 CDN,里面是主题所引用到的文件,可自行配置 CDN。(非必要请勿修改,配置后请确认链接是否能访问)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# CDN 设置
# 除非你知道它们的工作原理,否则不要修改以下设置
CDN:
# 内部和第三方脚本的 CDN 提供商
# 两者的选项:local/jsdelivr/unpkg/cdnjs/custom
# 注意: Dev 版本只能使用 'local' 作为内部脚本
# 注意:将第三方脚本设置为 'local' 时,需要安装 hexo-butterfly-extjs
internal_provider: local
third_party_provider: jsdelivr

# 是否在 URL 中添加版本号,true 或 false
version: false

# 自定义格式
# 例如:https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file}
custom_format:
  • version

如需修改版本号,可修改主题目录的 ‘plugins.yml’ 中对应插件的 version

请确保你修改的版本号,你所使用的 cdn 有收录

常用插件

  • 文章字数统计和阅读时长统计: hexo-wordcount
  • 文末添加当前文章链接和版权申明: hexo-addlink
  • 图片懒加载: hexo-lazyload-image
  • 生成baidusitemap.xml: hexo-generator-baidu-sitemap
  • 生成sitemap.xml: hexo-generator-sitemap
  • 生成RSS文件: hexo-generator-feed
  • 外链跳转:hexo-external-link
  • 自动对外部链接增加nofollow属性:hexo-autonofollow
  • 为外链添加rel=noopener external nofollow noreferrer: hexo-filter-nofollow
  • 代码高亮: hexo-prism-plugin
  • 博客压缩: hexo-neat、hexo-allminifier
  • aplayer音乐播放器:hexo-tag-aplayer
  • dplayer视频播放器:hexo-tag-dplayer
  • 添加豆瓣读书,电影,游戏页面:hexo-douban
  • 本地搜索,生成search.xml: hexo-generator-searchdb
  • 搜索系统: hexo-algolia、hexo-generator-search
  • 百度站长主动推送: hexo-baidu-url-submit
  • 开启PWA: hexo-offline、hexo-pwa
  • 看板娘:hexo-pelper-live2d
  • 博客文章加密: hexo-blog-encrypt
  • 博客展示pdf: hexo-pdf
  • 添加Steam游戏界面: hexo-steam-games
  • 添加bilibili番剧页面: hexo-bilibili-bangumi
  • 生成随机文章页面: hexo-generator-random

博客添加脑图: hexo-markmap

1
npm install hexo-markmap --save-dev

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{% markmap height [depth] %}
- Markdown
- Syntax
{% endmarkmap %}
# height: 画布高度
# depth: 可选,自动折叠层数深于 depth 的节点

{% markmap 400px %}
- links
- **inline** ~~text~~ *styles*
- multiline
text
- `inline code`
- ```js
console.log('code block');
console.log('code block');
```
- KaTeX - $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
{% endmarkmap %}

_config.yaml中配置

1
2
3
hexo_markmap:
pjax: true
katex: true

_config_butterfly.yaml中配置

1
2
3
4
5
6
7
8
9
#pjax
pjax:
enable: true

# KaTeX
katex:
enable: true
per_page: false
hide_scrollbar: true

文章置顶:hexo-generator-index-pin-top

1
2
3
4
5
6
7
npm uninstall hexo-generator-index --save
npm install hexo-generator-index-pin-top --save

在需要置顶的文章的Front-matter中加上top: true/数字即可,
数字越大,文章越靠前。

top: 1 #这里加一个top就行

文章图片:hexo-asset-img

markdown文章一般用typora,为了本地可以查看,又不影响部署后的图片显示。需要考虑2者的协调。

原理就是:![example](postname/example.jpg) --> {% asset_img example.jpg example %}

1
npm install hexo-asset-img --save

修改_config.yml

1
post_asset_folder: true # false # 启动 Asset 文件夹

原理就是渲染文章时,会将abbrlink放到文章的原信息

1.安装hexo-abbrlink

1
npm install hexo-abbrlink --save

2._config.yml

1
2
# permalink: :year/:month/:day/:title/ # 文章的 永久链接
permalink: posts/:abbrlink.html ## 或 :/abbrlink/ (此处可自定义'posts'处,如:posts:year/:abbrlink.html 或 :abbrlink.html)

3._config.butterfly.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## 短链接url配置: abbrlink config
### 见:https://github.com/Rozbo/hexo-abbrlink
abbrlink:
alg: 16 #support crc16(default) and crc32 进制
rep: dec #support dec(default) and hex 算法
drafts: false #(true)Process draft,(false)Do not process draft. false(default)
## Generate categories from directory-tree
## depth: the max_depth of directory-tree you want to generate, should > 0
auto_category:
enable: true #true(default)
depth: #3(default)
over_write: false
auto_title: false #enable auto title, it can auto fill the title by path
auto_date: false #enable auto date, it can auto fill the date by time today
force: false #enable force mode,in this mode, the plugin will ignore the cache, and calc the abbrlink for every post even it already had abbrlink.

文章页GPT总结: 待整理

后台管理博客:hexo-admin

1
2
npm install --save hexo-admin
访问: http://localhost:4000/admin

点击setting,点击setup Authentification here,设置用户名,密码,secret,将下放生成的配置复制到_config.yml

1
2
3
4
5
# hexo-admin authentification
admin:
username: xxxxx
password_hash: xxxxxx
secret: xxxxxx

设置deploy

创建hexo-deploy.bat

1
2
@echo off
call hexo clean && hexo g && hexo d

重启

效果:后台post页面发布博客,发完本地即可访问,deploy页面同步到远程服务器

单篇博文配置

Front-matter 是 markdown 文件最上方以 --- 分隔的区域,用于指定个别档案的变数。

  • Page Front-matter 用于 页面 配置
  • Post Front-matter 用于 文章页 配置

页面 Front-matter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
---
title:
date:
updated:
type:
comments:
description:
keywords:
top_img:
mathjax:
katex:
aside:
aplayer:
highlight_shrink:
random:
---

参数说明:

  • title: 【必需】页面标题
1
2
title: ' '
可以设置为空字符串,达到隐藏title的目的
  • date: 【必需】页面创建日期
  • type: 【必需】标签、分类和友情链接三个页面需要配置
  • updated: 【可选】页面更新日期
  • description: 【可选】页面描述
  • keywords: 【可选】页面关键字
  • comments: 【可选】显示页面评论模块 (默认 true)
  • top_img: 【可选】页面顶部图片
1
top_img: false # 设置false可以隐藏顶部图片效果
  • mathjax: 【可选】显示 mathjax (当设置 mathjax 的 per_page: false 时,才需要配置,默认 false)
  • katex: 【可选】显示 katex (当设置 katex 的 per_page: false 时,才需要配置,默认 false)
  • aside: 【可选】显示侧边栏 (默认 true)
  • aplayer: 【可选】在需要的页面加载 aplayer 的 js 和 css,请参考文章下面的音乐 配置
  • highlight_shrink: 【可选】配置代码框是否展开 (true/false) (默认为设置中 highlight_shrink 的配置)
  • random: 【可选】配置友情链接是否随机排序(默认为 false)

文章页 Front-matter

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
---
title:
date:
updated:
tags:
categories:
keywords:
description:
top_img:
comments:
cover:
toc:
toc_number:
toc_style_simple:
copyright:
copyright_author:
copyright_author_href:
copyright_url:
copyright_info:
mathjax:
katex:
aplayer:
highlight_shrink:
aside:
abcjs:
---

参数说明:

  • title: 【必需】文章标题
  • date: 【必需】文章创建日期
  • updated: 【可选】文章更新日期
  • tags: 【可选】文章标签
  • categories: 【可选】文章分类
1
2
3
4
5
6
7
8
9
10
分类是支持父子分类的
并列分类,了解一下:
categories:
- [Linux]
- [Tools]

并列+子分类,再了解一下:
categories:
- [Linux, Hexo]
- [Tools, PHP]
  • keywords: 【可选】文章关键字
  • description: 【可选】文章描述
  • top_img: 【可选】文章顶部图片
  • cover: 【可选】文章缩略图(如果没有设置 top_img,文章页顶部将显示缩略图,可设为 false/图片地址/留空)
  • comments: 【可选】显示文章评论模块(默认 true)
  • toc: 【可选】显示文章 TOC(默认为设置中 toc 的 enable 配置)
  • toc_number: 【可选】显示 toc_number(默认为设置中 toc 的 number 配置)
  • toc_style_simple: 【可选】显示 toc 简洁模式
  • copyright: 【可选】显示文章版权模块(默认为设置中 post_copyright 的 enable 配置)
  • copyright_author: 【可选】文章版权模块的文章作者
  • copyright_author_href: 【可选】文章版权模块的文章作者链接
  • copyright_url: 【可选】文章版权模块的文章连结链接
  • copyright_info: 【可选】文章版权模块的版权声明文字
  • mathjax: 【可选】显示 mathjax(当设置 mathjax 的 per_page: false 时,才需要配置,默认 false )
  • katex: 【可选】显示 katex (当设置 katex 的 per_page: false 时,才需要配置,默认 false )
  • aplayer: 【可选】在需要的页面加载 aplayer 的 js 和 css,请参考文章下面的音乐 配置
  • highlight_shrink: 【可选】配置代码框是否展开(true/false)(默认为设置中 highlight_shrink 的配置)
  • aside: 【可选】显示侧边栏 (默认 true)
  • abcjs: 【可选】加载 abcjs (当设置 abcjs 的 per_page: false 时,才需要配置,默认 false )

文章排版

Markdown

标题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# H1
## H2
### H3
#### H4
##### H5
###### H6

除了井号风格,也支持下划线风格(只能1级和2级)

Alt-H1
======

Alt-H2
------

强调

1
2
3
4
强调,也就是斜体,带有 *星号* 或 _下划线_。
加粗强调,又名粗体,带有**星号**或__下划线__。
加粗强调下划线斜体结合:**星号和_下划线_**。
~~删除线.~~

列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1. 有序列表

2. 有序列表

* 无序列表

3. 有序列表

1. 有序列表

4. 有序列表

段落可以和列表对齐
也可以用加号和减号缩进
+ 列表加号
+ 列表加号
+ 列表减号
- 列表减号
- 列表减号

内嵌HTML

1
<p>比如段落标签加上键盘效果 <kbd>ctrl</kbd>+<kbd>alt</kbd>+<kbd>del</kbd>.</p>

定义列表

1
2
3
4
5
6
<dl>
<dt>有序列表头</dt>
<dd>有序列表体</dd>
<dt>有序列表头</dt>
<dd>有序列表体</dd>
</dl>

链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[我是个连接](https://www.baidu.com)

[我是个连接,悬浮可以看到标题](https://www.baidu.com "我是链接标题")

[我是引用链接,需要配合下面的注引使用][任意不区分大小写的参考文本]

[我是相对路径引用](../blob/master/LICENSE)

[您可以使用数字作为参考样式的链接定义,指向下方的数字注引][1]

或者留空,[直接使用文字本身作为关联注引的]

# 以下为注引,指向上面的连接

[任意不区分大小写的参考文本]: https://www.baidu.com
[1]: https://www.baidu.com
[直接使用文字本身作为关联注引的]: https://www.baidu.com

图片

1
2
3
4
5
6
7
8
9
10
11
12
悬浮可以看到文字

内联写法:

![图片文字](https://hexo.io/icon/favicon-196x196.png "悬浮可以看到图片上的文字")

引用文本:
![图片文字][这个指向图片注引]

# 以下是注引

[这个指向图片注引]: https://hexo.io/icon/favicon-196x196.png "悬浮可以看到图片上的文字"

代码高亮

javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function $initHighlight(block, cls) {
try {
if (cls.search(/\bno\-highlight\b/) != -1)
return process(block, true, 0x0F) +
` class="${cls}"`;
} catch (e) {
/* handle exception */
}
for (var i = 0 / 2; i < classes.length; i++) {
if (checkCondition(classes[i]) === undefined)
console.log('undefined');
}

return (
<div>
<web-component>{block}</web-component>
</div>
)
}

export $initHighlight;

python

1
2
3
4
5
6
7
8
9
10
11
12
@requires_authorization
def somefunc(param1='', param2=0):
r'''A docstring'''
if param1 > param2: # interesting
print 'Gre\'ater'
return (param2 - param1 + 1 + 0b10l) or None

class SomeClass:
pass

>>> message = '''interpreter
... prompt'''

没有指定语言

1
没有指明语言,所以没有语法高亮。 但是让我们加入一个<b>标签</b>。

rust

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#[derive(Debug)]
pub enum State {
Start,
Transient,
Closed,
}

impl From<&'a str> for State {
fn from(s: &'a str) -> Self {
match s {
"start" => State::Start,
"closed" => State::Closed,
_ => unreachable!(),
}
}
}

json

1
2
3
4
5
6
7
8
9
10
11
12
[
{
"title": "apples",
"count": [12000, 20000],
"description": {"text": "...", "sensitive": false}
},
{
"title": "oranges",
"count": [17500, null],
"description": {"text": "...", "sensitive": false}
}
]

html

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<title>Title</title>

<style>body {width: 500px;}</style>

<script type="application/javascript">
function $init() {return true;}
</script>

<body>
<p checked class="title" id='title'>Title</p>
<!-- here goes the rest of the page -->
</body>

cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main(int argc, char *argv[]) {

/* An annoying "Hello World" example */
for (auto i = 0; i < 0xFFFF; i++)
cout << "Hello, World!" << endl;

char c = '\n';
unordered_map <string, vector<string> > m;
m["key"] = "\\\\"; // this is an error

return -2e3 + 12l;
}

sql

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE "topic" (
"id" serial NOT NULL PRIMARY KEY,
"forum_id" integer NOT NULL,
"subject" varchar(255) NOT NULL
);
ALTER TABLE "topic"
ADD CONSTRAINT forum_id FOREIGN KEY ("forum_id")
REFERENCES "forum" ("id");

-- Initials
insert into "topic" ("forum_id", "subject")
values (2, 'D''artagnian');

java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author John Smith <john.smith@example.com>
*/
package l2f.gameserver.model;

public abstract class L2Char extends L2Object {
public static final Short ERROR = 0x0001;

public void moveTo(int x, int y, int z) {
_ai = null;
log("Should not be called");
if (1 > 5) { // wtf!?
return;
}
}
}

css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@font-face {
font-family: Chunkfive; src: url('Chunkfive.otf');
}

body, .usertext {
color: #F0F0F0; background: #600;
font-family: Chunkfive, sans;
}

@import url(print.css);
@media print {
a[href^=http]::after {
content: attr(href)
}
}

bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

###### CONFIG
ACCEPTED_HOSTS="/root/.hag_accepted.conf"
BE_VERBOSE=false

if [ "$UID" -ne 0 ]
then
echo "Superuser rights required"
exit 2
fi

genApacheConf(){
echo -e "# Host ${HOME_DIR}$1/$2 :"
}

ini

1
2
3
4
5
6
7
8
9
10
11
12
; boilerplate
[package]
name = "some_name"
authors = ["Author"]
description = "This is \
a description"

[[lib]]
name = ${NAME}
default = True
auto = no
counter = 1_000

表格

1
2
3
4
5
|                |ASCII                          |HTML                         |
|----------------|-------------------------------|-----------------------------|
|单引号 |`'Isn't this fun?'` |'Isn't this fun?' |
|双引号 |`"Isn't this fun?"` |"Isn't this fun?" |
|破折号 |`-- is en-dash, --- is em-dash`|-- is en-dash, --- is em-dash|

冒号可用于对齐列

1
2
3
4
5
| 默认左对齐     | 居中           | 右对齐  |
| ------------- |:-------------:| -----:|
| 文本 | 文本 | 文本 |
| 文本 | 文本 | 文本 |
| 文本 | 文本 | 文本 |

外部的竖号不写也可以

1
2
3
4
Markdown | Less 	 | Pretty
--- | --- | ---
*Still* | `renders` | **nicely**
1 | 2 | 3

html的表格

笨蛋

块引用

markdown语法

1
2
3
> 这是一段块引用

> 这是一个很长的行,当它换行时仍然会被正确引用。哦,男孩,让我们继续写,以确保它足够长,可以真正为每个人包装。哦,你可以_把_ **Markdown ** 放到一个块引用中。

水平线

1
2
3
4
5
6
7
8
# 连字符
---

# 星号
***

# 下划线
___

标签外挂设置

NOTE

1
2
3
{% note [class] [no-icon] [style] %}
Any content (support inline tags too.io).
{% endnote %}

参数说明:

  • class: ( default / primary / success / info / warning / danger )
  • icon: 可配置自定义 icon (只支持 fontawesome 图标, 也可以配置 no-icon )
  • style: ( simple / modern / flat / disabled )

用法1:风格

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
{% note flat  %}
默认 提示块标签
{% endnote %}

{% note default flat %}
default 提示块标签
{% endnote %}

{% note primary flat %}
primary 提示块标签
{% endnote %}

{% note success flat %}
success 提示块标签
{% endnote %}

{% note info flat %}
info 提示块标签
{% endnote %}

{% note warning flat %}
warning 提示块标签
{% endnote %}

{% note danger flat %}
danger 提示块标签
{% endnote %}

用法2:图标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% note 'fab fa-cc-visa' simple %}
你是刷 Visa 还是 UnionPay
{% endnote %}
{% note blue 'fas fa-bullhorn' simple %}
2021 年快到了....
{% endnote %}
{% note pink 'fas fa-car-crash' simple %}
小心开车 安全至上
{% endnote %}
{% note red 'fas fa-fan' simple%}
这是三片呢?还是四片?
{% endnote %}
{% note orange 'fas fa-battery-half' simple %}
你是刷 Visa 还是 UnionPay
{% endnote %}
{% note purple 'far fa-hand-scissors' simple %}
剪刀石头布
{% endnote %}
{% note green 'fab fa-internet-explorer' simple %}
前端最讨厌的浏览器
{% endnote %}

你是刷 Visa 还是 UnionPay

2021 年快到了….

小心开车 安全至上

这是三片呢?还是四片?

你是刷 Visa 还是 UnionPay

剪刀石头布

前端最讨厌的浏览器

图库集合

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="gallery-group-main">
{% galleryGroup name description link img-url %}
{% galleryGroup name description link img-url %}
{% galleryGroup name description link img-url %}
</div>

举例:
<div class="gallery-group-main">
{% galleryGroup '壁纸' '收藏的一些壁纸' '/Gallery/wallpaper' https://i.loli.net/2019/11/10/T7Mu8Aod3egmC4Q.png %}
{% galleryGroup '漫威' '关于漫威的图片' '/Gallery/marvel' https://i.loli.net/2019/12/25/8t97aVlp4hgyBGu.jpg %}
{% galleryGroup 'OH MY GIRL' '关于OH MY GIRL的图片' '/Gallery/ohmygirl' https://i.loli.net/2019/12/25/hOqbQ3BIwa6KWpo.jpg %}
</div>

图库相册

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
{% gallery [lazyload],[rowHeight],[limit] %}
markdown 图片格式
{% endgallery %}

举例:
{% gallery %}
markdown 图片格式
{% endgallery %}

{% gallery true,220,10 %}
markdown 图片格式
{% endgallery %}

{% gallery true,,10 %}
markdown 图片格式
{% endgallery %}

{% gallery %}
![](https://i.loli.net/2019/12/25/Fze9jchtnyJXMHN.jpg)
![](https://i.loli.net/2019/12/25/ryLVePaqkYm4TEK.jpg)
![](https://i.loli.net/2019/12/25/gEy5Zc1Ai6VuO4N.jpg)
![](https://i.loli.net/2019/12/25/d6QHbytlSYO4FBG.jpg)
![](https://i.loli.net/2019/12/25/6nepIJ1xTgufatZ.jpg)
![](https://i.loli.net/2019/12/25/E7Jvr4eIPwUNmzq.jpg)
![](https://i.loli.net/2019/12/25/mh19anwBSWIkGlH.jpg)
![](https://i.loli.net/2019/12/25/2tu9JC8ewpBFagv.jpg)
{% endgallery %}

内容隐藏:Tag-hide

tag-hide 内的标签外挂 content 内都不建议有 h1 - h6 等标题。

如果你想把一些文字、内容隐藏起来,并提供按钮让用户点击显示。可以使用这个标签外挂。

1
2
3
4
5
6
7
8
9
10
行内:
{% hideInline content,display,bg,color %}
块;
{% hideBlock display,bg,color %}
content
{% endhideBlock %}
收缩
{% hideToggle display,bg,color %}
content
{% endhideToggle %}

Mermaid

1
2
3
4
{% mermaid %}
内容
{% endmermaid %}

Tabs

1
2
3
4
5
6
7
8
9
10
{% tabs Unique name, [index] %}

<!-- tab [Tab caption] [@icon] -->

Any content (support inline tags too).

<!-- endtab -->

{% endtabs %}

Button

1
2
{% btn [url],[text],[icon],[color] [style] [layout] [position] [size] %}

InlineImg

1
{% inlineImg [src] [height] %}

Label

1
{% label text color %}

Timeline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% timeline title,color %} 

<!-- timeline title -->

xxxxx

<!-- endtimeline -->
<!-- timeline title -->

xxxxx

<!-- endtimeline -->

{% endtimeline %}

参数说明:

  • color: default(留空) / blue / pink / red / purple / orange / green

可在任何界面插入类似友情链接列表效果

1
2
3
{% flink %}
xxxxxx
{% endflink %}

ABCJS乐谱

配置:

1
2
3
4
5
6
7
# abcjs (乐谱渲染)
# See https://github.com/paulrosen/abcjs
# ---------------
abcjs:
enable: true
per_page: true

用法:

1
2
3
4
{% score %}
乐谱代码
{% endscore %}

Series系列文章

在页面上显示系列文章

1
2
3
4
5
6
7
8
9
10
# 系列
series:
# 是否启用系列
enable: false
# 按标题或日期排序
orderBy: 'title'
# 排序方式。1, asc 为升序; -1, desc 为降序
order: 1
# 是否显示编号
number: true

用法:

1
2
3
4
5
6
{% series %}
{% series [series name] %}

在文章的 front-matter 上添加参数 series,并给与一个标识
使用此标签外挂,会把相同标识的文章以列表的形式展示
如果不写 series 标识,则默认为你使用此标签外挂所在的文章的 series 标识

嵌入YouTube视频

插入 YouTube 视频,可以播放

1
{% youtube video_id %}

嵌入Vimeo视频

插入响应式或指定大小的 Vimeo 视频。

1
2
{% vimeo video_id [width] [height] %}
{% vimeo 124876737 %}

站内嵌入链接

嵌入调整的链接

1
2
{% link text url [external] [title] %}
{% link Docs https://butterfly.js.org/ %}

站内嵌入文章

站内文章链接

1
2
{% post_path filename %}
{% post_link filename [title] [escape] %}

使用此标签时,您可以忽略永久链接和文件夹信息,例如语言和日期.

比如: {% post_link how-to-bake-a-cake %}.

只要帖子的文件名是 how-to-bake-a-cake.md,即使帖子位于 source/posts/2015-02-my-family-holiday 并且有固定链接 2018/en/how-to-bake-a-cake.也能起作用

您可以自定义要显示的文本,而不是显示帖子的标题。不支持在 Markdown 语法 []() 中使用 post_path。

帖子的标题和自定义文本默认转义。您可以使用转义选项来禁用转义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% raw %}{% post_link 标签外挂-Tag-Plugins %}{% endraw %}
{% post_link 标签外挂-Tag-Plugins %}

# 自定义链接显示文本 alt
{% raw %}{% post_link 标签外挂-Tag-Plugins 'Link to a post' %}{% endraw %}
{% post_link 标签外挂-Tag-Plugins 'Link to a post' %}

默认转义
{% post_link 标签外挂-Tag-Plugins 'How to use <b> tag in title' %}
{% post_link 标签外挂-Tag-Plugins 'How to use <b> tag in title' %}

不转义
{% post_link 标签外挂-Tag-Plugins '<b>bold</b> custom title' false %}
{% post_link 标签外挂-Tag-Plugins '<b>bold</b> custom title' false %}

站内嵌入图片链接

包括帖子资产

1
2
3
4
5
6
7
{% asset_path filename %}
{% asset_img filename [title] %}
{% asset_link filename [title] [escape] %}

# iframe:嵌入页面,注意这里是嵌入页面,可以是动态的,是可以用的网站
{% iframe url [width] [height] %}
{% iframe 'https://butterfly.js.org/' 100% 300px %}

站内嵌入代码

source/downloads/code 文件夹中插入代码片段。可以通过配置中的 code_dir 选项指定文件夹位置。

1
{% include_code [title] [lang:language] [from:line] [to:line] path/to/file %}

嵌入 test.js 的全部内容

1
{% include_code lang:javascript test.js %}

仅嵌入第 3 行

1
{% include_code lang:javascript from:3 to:3 test.js %}

嵌入 5 到 8 行

1
{% include_code lang:javascript from:5 to:8 test.js %}

从第5行开始嵌入

1
{% include_code lang:javascript from:5 test.js %}

将第 5 行嵌入到文件末尾

1
{% include_code lang:javascript to:8 test.js %}

嵌入代码块Code Block

1
2
3
{% codeblock [title] [lang:language] [url] [link text] [additional options] %}
code snippet
{% endcodeblock %}
Extra Options Description Default
line_number 显示行号 true
highlight 启用代码突出显示 true
first_line 指定第一行号 1
mark 行突出显示特定行,每个值用逗号分隔。使用破折号指定数字范围
例如:mark:1,4-7,10 会标记 1, 4 to 7 和 10 行。
wrap 代码块用 <table> 包裹。 true

站内嵌入Gist代码片段

1
2
{% gist gist_id [filename] %}
{% gist 996818 %}

站内嵌入jsFiddle

1
2
{% jsfiddle shorttag [tabs] [skin] [width] [height] %}
{% jsfiddle ccWP7 %}

文章嵌入引用

非常适合在您的帖子中添加引号,并带有可选的作者、来源和标题信息

1
2
3
4
5
6
7
8
9
10
11
12
13
{% blockquote [author[, source]] [link] [source_link_title] %}
content
{% endblockquote %}

示例:
{% blockquote David Levithan, Wide Awake %}
Do not just seek happiness for yourself. Seek happiness for all. Through kindness. Through mercy.
{% endblockquote %}

示例:带连接
{% blockquote Seth Godin http://sethgodin.typepad.com/seths_blog/2009/07/welcome-to-island-marketing.html Welcome to Island Marketing %}
Every interaction is both precious and an opportunity to delight.
{% endblockquote %}

文章内联嵌入引用块

1
2
3
{% pullquote [空|left|right] %}
content
{% endpullquote %}

Raw

有时候想写点前端小 demo,因为代码量实在是太少了,几行 css、几行 javascript;不想放在 codepen 作为引用,也不想单独做一个页面放到主题的 source 文件夹下,于是就有了在 md 文件里直接写的想法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% raw %}
<style>
.styled-div-right{
width: 100px;
height: 100px;
background: yellow;
}
</style>
<div class="styled-div-right">我是div</div>
<script>
(function(){
console.log('我才是正确的md里的javascript');
})();
</script>
{% endraw %}

页面定制

💥 表示动了源码,请慎重食用

标签页

1.hexo根目录执行hexo new page tags

2.在source/tags/index.md增加type: "tags"

1
2
3
4
5
6
7
8
---
title: 标签
type: "tags"
date: 2024-10-11 17:11:44
comments: false
orderby: random # 【可选】排序方式 :random - 随机排序 / name - 标签名字排序 / length - 标签数量排序
order: 1 # 【可选】排序次序: 1(升序),-1(降序)
---

分页类

1.hexo根目录执行hexo new page categories

2.在source/categories/index.md增加type: "tags"

1
2
3
4
5
---
title: 分类
date: 2024-10-11 17:15:22
type: "categories"
---

友链页

1.hexo根目录执行hexo new page link

2.在source/link/index.md增加type: "link"

1
2
3
4
5
6
---
title: 友情链接
date: 2024-10-11 17:33:48
type: link
random: true # 友链随机排序
---

编辑source/_data/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: 社交分享平台

图库页

1.hexo根目录执行hexo new page photo

2.使用标签galleryGroup表示图库首页,photo是自定义的图库名称,根据需求命名

1
2
{% galleryGroup '壁紙' '动漫壁纸' '/photo/wallpaper' https://i.loli.net/2019/11/10/T7Mu8Aod3egmC4Q.png %}
{% galleryGroup '漫威' '关于漫威的图片' '/Gallery/marvel' https://i.loli.net/2019/12/25/8t97aVlp4hgyBGu.jpg %}

3.使用标签gallery表示子图库,wallpaper是自定义的子图库名称,根据需求命名

注意: 手动创建 /photo/wallpaper/index.md,或者用命令创建 hexo new page wallpaper,然后将目录移动到photo目录下

1
2
3
4
5
6
7
8
9
10
11
12
{% gallery %}
![material-1.png](https://i.loli.net/2019/11/10/lP3rLNUBaGtSVzc.png)
![material-8.png](https://i.loli.net/2019/11/10/T7Mu8Aod3egmC4Q.png)
![material-6.png](https://i.loli.net/2019/11/10/53eTB2uiNRlXwFP.png)
![material-10.png](https://i.loli.net/2019/11/10/xthHmnbdNerWOqP.png)
![material-3.png](https://i.loli.net/2019/11/10/rJbFpE65tmxPv7R.png)
![material-4.png](https://i.loli.net/2019/11/10/bEJsXxewpOGuRD8.png)
![material-7.png](https://i.loli.net/2019/11/10/71wgohfPHqXRbG9.png)
![material-2.png](https://i.loli.net/2019/11/10/gcnavZbmepS8d4u.png)
![material-5.png](https://i.loli.net/2019/11/10/3wkO7fuQpgda6vz.png)
![material-9.png](https://i.loli.net/2019/11/10/egVhFWopA5mP2Hk.png)
{% endgallery %}

404页

主题内置了一个简单的 404 页面,可在设置中开启

本地预览时,访问出错的网站是不会跳到 404 页面的。如需本地预览,请访问 http://localhost:4000/404.html

1
2
3
4
error_404:
enable: true
subtitle: '页面没有找到'
background: /img/error-page.png

说说页

请留意,说说界面只支持原生的 markdown 格式,不支持标签外挂和数学公式

shuoshuo命名可以自定义

1.hexo根目录执行hexo new page shuoshuo

2.在source/shuoshuo/index.md增加type: "link"

1
2
3
4
5
---
title: 说说
date: 2018-06-07 22:17:49
type: 'shuoshuo'
---

编辑source/_data/shuoshuo.yml

author 和 avatar可省略,会自动去获取配置文件中的 author 和 avatar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- author: Butterfly
avatar: https://butterfly.js.org/img/avatar.png
date: 2024-06-21 23:33:26
content: |
This is a sample content for **Author 1**.
![Sample Image](https://via.placeholder.com/150)
tags:
- tags1
- tags2
- author: Butterfly
avatar: https://butterfly.js.org/img/avatar.png
date: 2024-06-20 23:33:26
content: |
This is a sample content for **Author 2**.
![Sample Image](https://via.placeholder.com/150)
tags:
- tag2
- tag3

- author: Butterfly
avatar: https://butterfly.js.org/img/avatar.png
date: 2024-06-19 23:33:26
content: |
This is a sample content for **Author 3**.

参数说明:

  • author: 【可选】作者名称
  • avatar: 【可选】作者头像
  • date: 【必需】日期
  • content: 【必需】内容( Markdown 格式或者 Html 格式
  • tags: 【可选】标签

电影页 💥

电影界面使用了插件 hexo-douban

注意:

  • hexo-douban 会主动生成页面,所以不需要自己创建。
  • 如遇到无法抓取问题,显示 INFO 0 movies have been loaded in xxx ms, because you are offline or your network is bad,请过段时间再试试,这我也无能为力。

自己搞电影页:

1.创建布局themes\butterfly\layout\includes\page\movies.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
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
//- movie page
//- 主容器
#article-container
.author-content-item.like-movie.single.share
.card-content
//- ._p('电影') 和其他 _p 函数用于返回国际化文本。
.author-content-item-tips=_p('电影')
div.author-content-item-title=_p('静下来慢慢')
span.inline-word=_p('感受着,')
div.author-content-item-title=_p('流淌的')
span.inline-word=_p('故事。')
div.author-content-bottom
.content-bottom
.tips=_p('跟 左耳 查看更多书影音')
.banner-button-group
a.banner-button(href="https://www.douban.com/")
i.fas.fa-circle-chevron-right
span.banner-button-text=_p('感受更多')
.hexo-douban-item-tip
p.gradient-text 静下来,感受电影的魅力
//- 样式文件
style.
.hexo-douban-item {
padding-bottom: 10px;
position: relative;
clear: both;
min-height: 170px;
padding: 10px 0;
border-bottom: 1px #ddd solid;
}

@media screen and (max-width: 600px) {
.hexo-douban-item {
width: 100%;
}
}

.hexo-douban-picture {
position: absolute;
left: 0;
top: 10px;
width: 100px;
}

.hexo-douban-info {
padding-left: 120px;
}

.hexo-douban-meta {
font-size: 12px;
padding-right: 10px;
}

.hexo-douban-comments {
font-size: 12px;
}
div
if site.data.movies
.hexo-douban-show#hexo-douban-item3
each i in site.data.movies
each item in i.movie_list
.hexo-douban-item
.hexo-douban-picture(title=item.name)
a(target='_blank', href=url_for(item.link), rel='external nofollow')
img(src=url_for(item.cover), data-src=url_for(item.cover), referrerpolicy='no-referrer')
.hexo-douban-info
.hexo-douban-title(title=item.name)
a(target='_blank', href=url_for(item.link), rel='external nofollow')=item.name
.hexo-douban-meta=item.date_grade
.hexo-douban-comments=item.comment

2.添加布局themes\butterfly\layout\page.pug

1
2
when 'movies'
include includes/page/movies.pug

3.添加样式source\css\movies.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
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
.author-content-item.single.like-movie {
height: 19rem;
background: url(/img/cover/movies_cover.png) no-repeat top;
background-size: cover;
color: #c2c2c2;
overflow: hidden;
border-radius: 12px;
-webkit-box-shadow: 0 21px 133px 81px #1c1c1c inset;
box-shadow: 0 21px 133px 81px #1c1c1c inset;
}

.author-content-item .card-content {
padding: 1rem 2rem;
display: flex;
flex-direction: column;
height: 100%;
}

.author-content-item .card-content .author-content-bottom {
margin-top: auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}

.author-content-bottom .banner-button-group {
border: 1px solid #535357;
border-radius: 8px;
padding-right: 3px;
padding-left: 5px;
background: #535357;
}

.banner-button-group a i,
.banner-button-group a span {
color: #c2c2c2;
padding-right: 2px;
}

.banner-button-group a:hover {
text-decoration: none !important;
}
.banner-button-group a:hover i,
.banner-button-group a:hover span {
color: #49b1f5 ;
}

.author-content-item .author-content-item-title {
font-size: 36px;
font-weight: bold;
line-height: 1;
margin-bottom: 0.5rem;
}

.hexo-douban-item-tip {
margin: 0.5rem 0 0.5rem 0;
border: 1px solid #e3e8f7;
border-radius: 8px;
background-color: #f7f7f9;
padding: 0.5rem 0.8rem;
height: 60px;
line-height: 42px;
}

.hexo-douban-item-tip .gradient-text {
background: linear-gradient(to left, #ff4500, #ffa500, #ffd700, #90ee90, #0ff, #1e90ff, #9370db, #ff69b4, #ff4500);
-webkit-background-clip: text;
color: transparent;
font-size: 16px;
font-weight: bold;
}

.hexo-douban-item {
border-bottom: none !important;
background: #fff;
border: 1px solid #e3e8f7;
box-shadow: 0 8px 16px -4px rgba(44,45,48,0.047);
border-radius: 12px;
margin: 8px 0;
height: 160px;
min-height: 160px !important;
width: 49%;
overflow: hidden;
}

#hexo-douban-item3 {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}

.hexo-douban-item .hexo-douban-picture a {
padding: 0 !important;
}

.hexo-douban-item .hexo-douban-picture img {
margin: 0px !important;
height: 100% !important;
}

.hexo-douban-tabs {
display: none;
}

.hexo-douban-title a {
border-bottom: 0px !important;
color: #363636 !important;
font-size: 20px;
font-weight: bold;
}

.hexo-douban-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.hexo-douban-title a:hover {
color: #49b1f5 !important;
background: rgba(0, 0, 0, 0) !important;
text-decoration: none !important;
}

.hexo-douban-info {
padding-left: 130px !important;
margin-right: 0.5rem;
}

.hexo-douban-meta {
font-size: 0.7rem !important;
color: rgba(60,60,67,0.8);
margin-top: 0.3rem;
line-height: 1.05;
}

.hexo-douban-comments {
line-height: 1.2;
margin-top: 0.5rem !important;
font-size: 0.8rem !important;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
}

.hexo-douban-picture {
height: 100%;
top: 0 !important;
padding: 10px 0 10px 10px;
}

.hexo-douban-picture a img {
border-radius: 8px !important;
}


4.添加样式_config.butterfly.yml

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

5.创建页面hexo new page movies

1
2
3
4
5
6
7
8
9
---
title: ''
date: 2024-10-20 09:50:22
type: 'movies'
comments: false
aside: false
top_img: false
---

6.配置页面_config.butterfly.yml

1
2
menu:
电影: /movies/ || fas fa-video

7.添加数据source\_data\movies.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 电影推荐
# name:电影名称
# link:电影链接
# cover: 封面图,可以从豆瓣页面右键复制图片链接
# date_grade: 电影评分与观看日期 ★☆
# comment: 评论
- class_name: 电影推荐
movie_list:
- name: 人生大事
link: https://movie.douban.com/subject/35460157/
cover: https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2874262709.webp
date_grade: 2022-07-05 / ★★★★★ 力荐
comment: 非常的感人,是一部非常值得看的电影
- name: 长津湖之水门桥
link: https://movie.douban.com/subject/35613853/
cover: https://img2.doubanio.com/view/photo/s_ratio_poster/public/p2846021991.jpg
date_grade: 2022-07-04 / ★★★☆☆ 一般
comment: 怎么说呢,和一直以来拍的都差不多,有的镜头还可以,不过看的还是有点生气

音乐页

感觉全局的附着音乐播放器体验一般,我只是想收藏、展示、和分享我觉得好听的歌曲,所以此处不全局展示,只在音乐页展示。

音乐界面使用了插件 hexo-tag-aplayer

1.安装

1
npm install --save hexo-tag-aplayer

2.修改_config.yml

1
2
3
aplayer:
meting: true
asset_inject: false

3.修改_config.butterfly.yml

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

4.添加下面代码到source/music/index.md

1
{% meting "[网易云歌单ID]" "netease" "playlist" "autoplay" "mutex:false" "listmaxheight:400px" "preload:none" "theme:#ad7a86"%}

更优的方案:安知鱼-音乐馆

装备页 💥

1.主题配置文件添加菜单

1
2
menu:
好物: /equipment/ || fas fa-video

2.引入自定义css和js

1
2
3
4
5
6
7
inject:
head:
# 【技巧】静态文件后面加个 ?任意内容 可以在每次更新之后用户自动重新请求.
# 例如添加 ?1 ,在修改此文件后改成 ?2 ,用户访问你的网站时,不会使用本地的缓存,而是请求新的内容。没修改的话就不用动。
- <link rel="stylesheet" href="/css/equipment.css?1">
bottom:
- <script src="/js/equipment.js?1"></script>

3.添加自定义的装备页

themes\butterfly\layout\page.pug 中添加如下修改

1
2
when 'equipment'
include includes/page/equipment.pug

4.在source/css/equipment.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
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
/* 我的装备 */
.equipment-item-content {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 -8px;
}

.equipment-item-content-item {
width: calc(25% - 12px);
border-radius: 12px;
border: var(--style-border-always);
overflow: hidden;
margin: 8px 6px;
background: var(--heo-card-bg);
box-shadow: var(--heo-shadow-border);
min-height: 400px;
position: relative;
}

@media screen and (max-width: 1200px) {
.equipment-item-content-item {
width: calc(50% - 12px);
}
}

@media screen and (max-width: 768px) {
.equipment-item-content-item {
width: 100%;
}
}

.equipment-item-content-item-info {
padding: 8px 16px 16px 16px;
margin-top: 12px;
}

.equipment-item-content-item-name {
font-size: 18px;
font-weight: bold;
line-height: 1;
margin-bottom: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: fit-content;
}

.equipment-item-content-item-specification {
font-size: 12px;
color: var(--heo-secondtext);
line-height: 1;
margin-bottom: 12px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.equipment-item-content-item-description {
line-height: 20px;
color: var(--heo-secondtext);
height: 60px;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
font-size: 14px;
}

a.equipment-item-content-item-link {
font-size: 12px;
background: var(--heo-gray-op);
padding: 4px 8px;
border-radius: 8px;
cursor: pointer;
}

a.equipment-item-content-item-link:hover {
background: var(--heo-main);
color: var(--heo-white);
}

h2.equipment-item-title {
line-height: 1;
}

.equipment-item-description {
line-height: 1;
margin: 4px 0 8px 0;
color: var(--heo-secondtext);
}

.equipment-item-content-item-cover {
width: 100%;
height: 200px;
background: var(--heo-secondbg);
display: flex;
justify-content: center;
}

img.equipment-item-content-item-image {
object-fit: cover;
height: 100%;
}

div#equipment {
margin-top: 26px;
}

.equipment-item-content-item-toolbar {
display: flex;
justify-content: space-between;
position: absolute;
bottom: 12px;
left: 0;
width: 100%;
padding: 0 16px;
}

a.bber-reply {
cursor: pointer;
}

5.在source/equipment/index.md设置type

1
2
3
4
5
6
7
---
title: 好物
date: 2024-10-13 16:37:26
aside: false
type: equipment
---

6.在 source/dataequipment.yml添加数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- class_name: 生产力
description: 提升自己生产效率的硬件设备
equipment_list:
- name: 翻新 MacBookPro
specification: M1Pro 32G / 1TB
description: 屏幕显示效果好、色彩准确、对比度强、性能强劲、续航优秀。可以用来开发和设计。
image: https://p.zhheo.com/YnW8cc2150681686120255749.png!cover
link: https://blog.zhheo.com/p/daebc472.html
- name: iPhone 13 Pro
specification: 白色 / 256G
description: 第一代支持promotion的iPhone,A15性能优秀。
image: https://p.zhheo.com/TofzQM2219061686120261484.png!cover
link: https://www.apple.com/by/iphone-13-pro/
- class_name: 出行
description: 用来出行的实物及设备
equipment_list:
- name: 航宇之星双肩包
specification: 标准版
description: 造型炫酷,包的容量非常大,还有魔术贴位置,我贴上了鸡哥的头像。
image: https://p.zhheo.com/20jaBU2179061686121157367.png!cover
link: https://detail.meizu.com/item/pasasjb.html

导航页 💥

一直想要有个导航页面,但是我想直接放到hexo+butterfly,而不是另外开一个工程,然后用子域名挂接的方式,那就开始折腾吧。

参考webstack张洪-自定义layout

1.创建导航布局themes\butterfly\layout\webstack.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
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
- var htmlClassHideAside = theme.aside.enable && theme.aside.hide ? 'hide-aside' : ''
- page.aside = is_archive() ? theme.aside.display.archive: is_category() ? theme.aside.display.category : is_tag() ? theme.aside.display.tag : page.aside
- var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : ''
- var pageType = is_post() ? 'post' : 'page'
- pageType = page.type ? pageType + ' type-' + page.type : pageType

doctype html
html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside)
head
include ./includes/head.pug
body

#body-wrap(class=pageType)

header#page-header(class='not-top-img fixed')
nav#nav
span#blog-info
a.nav-site-title(href=url_for('/'))
if theme.nav.logo
img.site-icon(src=url_for(theme.nav.logo) alt='Logo')
if theme.nav.display_title
span.site-name=config.title
if is_post()
a.nav-page-title(href=url_for('/'))
span.site-name=(page.title || config.title)
#menus
if theme.search.use
#search-button
span.site-page.social-icon.search
i.fas.fa-search.fa-fw
span= ' ' + _p('search.title')
if theme.menu
!= partial('includes/header/menu_item', {}, {cache: true})

#toggle-menu
span.site-page
i.fas.fa-bars.fa-fw

main
.nb-container
.nb-sidebar-menu
ul#nb-sidebar-menu-item.nb-sidebar-menu-item
each i in site.data.webstack
li
a.nb-sidebar-menu-a(href=`#${i.class_name}` class="smooth-scroll")
i.nb-sidebar-menu-icon
span.nb-sidebar-menu-title=i.class_name
//- //- 子菜单
//- if i.submenu && Array.isArray(i.submenu) && i.submenu.length > 0
//- ul
//- each sub in i.submenu
//- li
//- a.nb-sidebar-menu-a(href=`#${i.class_name}` class="smooth-scroll")
//- i.nb-sidebar-menu-icon
//- span.nb-sidebar-menu-title=i.class_name

if site.data.webstack
.nb-card-main
each i in site.data.webstack
div.nb-card-maodian(id=iclass_name)=i.class_name
each item in i.link_list
.nb-card
.nb-card-icon
a(target='_blank',href=url_for(item.link),rel='external nofollow')
img(src=url_for(item.icon), data-src=url_for(item.icon), referrerpolicy='no-referrer' width='40', height='40')
div
.nb-card-header=item.name
.nb-card-body=item.text

script.
// JavaScript 代码
document.addEventListener('DOMContentLoaded', function() {
const links = document.querySelectorAll('.smooth-scroll');

links.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault(); // 阻止默认链接行为
const targetId = this.getAttribute('href').substring(1); // 获取目标 ID
const targetElement = document.getElementById(targetId); // 查找目标元素

if (targetElement) {
// 平滑滚动到目标元素
targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
});

include ./includes/rightside.pug
include ./includes/additional-js.pug

2.创建导航页source\webstack\index.md

1
2
3
4
5
6
---
title: webstack
date: 2024-10-13 15:32:03
layout: webstack
---

3.配置导航页_config.butterfly.yml

1
2
3
4
5
menu:
导航: /webstack/ || fa fa-share-alt
inject:
head:
- <link rel="stylesheet" href="/css/webstack.css?1">

4.定制样式source\css\webstack.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
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
/* 容器 */
.nb-container {
width: 100%;
height: 100vh;
/* background-color: red; */
}
/* 侧边栏样式 */
.nb-sidebar-menu {
width: 250px;
background-color: #2c3e50; /* 深灰色背景 */
color: #ecf0f1; /* 浅色字体 */
height: 100vh;
position: fixed; /* 固定在左侧 */
top: 60px;
left: 0;
overflow-y: auto; /* 滚动条处理 */
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.3);
}

.nb-sidebar-menu ul {
list-style: none; /* 去除默认列表样式 */
padding: 0;
margin: 0;
}

.nb-sidebar-menu-item {
padding: 0;
}

.nb-sidebar-menu-item li {
border-bottom: 1px solid #34495e; /* 每个菜单项之间的分割线 */
}

.nb-sidebar-menu-a {
display: flex;
align-items: center;
padding: 15px 20px;
text-decoration: none;
color: #ecf0f1; /* 菜单项文字颜色 */
transition: background 0.3s ease;
}

.nb-sidebar-menu-a:hover {
background-color: #34495e; /* 悬停时背景色 */
cursor: pointer;
}

.nb-sidebar-menu-icon {
margin-right: 10px; /* 图标与文字的间距 */
font-size: 18px; /* 图标大小 */
}

.nb-sidebar-menu-title {
font-size: 16px; /* 菜单项文字大小 */
}


.nb-card-main {
margin-left: 250px; /* 根据侧边栏宽度设置左边距 */
padding: 20px;
flex: 1; /* 占满剩余空间 */
background-color: #ecf0f1; /* 主内容区背景色 */
min-height: 100vh; /* 保证主内容区至少与视口高度相同 */
display: flex; /* 使用 flex 布局 */
flex-wrap: wrap; /* 自动换行 */
gap: 20px; /* 卡片之间的间距 */
}


/* 卡片主区域 */
.nb-card-maodian {
/* background-color: red; */
width: 100%;
}

.nb-card-maodian::before {
content: "";
display: inline-block;
width: 15px;
height: 15px;
margin-right: 10px;
background-image: url(/img/webstack/tag-icon.png);
background-size: contain; /* 保持图像比例 */
background-repeat: no-repeat; /* 不重复图像 */
vertical-align: -2px;
}

.nb-card {
height: 86px;
width: 220px;
padding: 10px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
display: flex;
align-items: center;
}

.nb-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
cursor: pointer;
}

.nb-card-icon {
font-size: 40px;
margin-right: 15px;
}

.nb-card-header {
font-size: 14px;
font-weight: bold;
/* margin-bottom: 10px; */
}

.nb-card-body {
font-size: 12px;
color: #333;
}

6.添加数据source\_data\webstack.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# 常用推荐
# name:卡片名称
# link:卡片链接
# icon: 卡片图标
# text: 备注(最多26个备注,不然会超过)
- class_name: test1
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。

- class_name: 常用推荐2
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。

- class_name: 常用推荐3
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。

- class_name: 常用推荐4
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。

- class_name: 常用推荐5
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。

- class_name: 常用推荐6
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。

- class_name: 常用推荐7
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。

- class_name: test8
link_list:
- name: Dribbble
link: https://dribbble.com/
icon: /img/webstack/dribbble.png
text: 全球UI设计师作品分享平台。
- name: Behance
link: https://behance.net/
icon: /img/webstack/behance.png
text: Adobe旗下的设计师交流平台,来自世界各地的设计。


留言板

1.hexo根目录执行hexo new page talk2me

2.在source/talk2me/index.md增加type: "talk2me"

1
2
3
4
5
6
---
title: 留言板
date: 2018-01-05 00:00:00
type: talk2me
---

留言信箱

手搓模式:留言页直接写html代码

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
{% raw %}
<style>
@media screen and (max-width:530px) {
#computer {
display:none!important
}
}
@media screen and (min-width:530px) {
#mobile {
display:none!important
}
}
#article-container img {
margin:0 auto 0
}
#form-wrap {
overflow:hidden;
height:447px;
position:relative;
top:0;
transition:all 1s ease-in-out .3s;
z-index:0
}
#form-wrap:hover {
height:1050px;
top:-200px
}
#beforeimg {
position:absolute;
bottom:126px;
left:0;
background-repeat:no-repeat;
width:530px;
height:317px;
z-index:-100;
pointer-events:none
}
#afterimg {
position:absolute;
bottom:-2px;
left:0;
background-repeat:no-repeat;
width:530px;
height:259px;
z-index:100;
pointer-events:none
}
#envelope {
position:relative;
overflow:visible;
width:500px;
margin:0 auto;
transition:all 1s ease-in-out .3s;
padding-top:200px
}
#maincontent {
width:530px;
margin:20px auto 0
}
.headerimg {
width:100%;
overflow:hidden;
pointer-events:none
}
.formmain {
background:#fff;
width:95%;
max-width:800px;
margin:auto auto;
border-radius:5px;
border:1px solid;
overflow:hidden;
-webkit-box-shadow:0 0 20px 0 rgba(0, 0, 0, .12);
box-shadow:0 0 20px 0 rgba(0, 0, 0, .18);
pointer-events:none;
}
.title3 {
text-decoration:none;
color:#f6d6af
}
.comments {
border-bottom:#ddd 1px solid;
border-left:#ddd 1px solid;
padding-bottom:20px;
background-color:#eee;
margin:15px 0;
padding-left:20px;
padding-right:20px;
border-top:#ddd 1px solid;
border-right:#ddd 1px solid;
padding-top:20px;
font-family:Arial, "Microsoft YaHei", "黑體", "宋體", sans-serif
}
.bottomcontent {
text-align:center;
margin-top:40px
}
.bottomimg {
width:100%;
margin:5px auto 5px auto;
display:block;
pointer-events:none
}
.bottomhr {
font-size:12px;
text-align:center;
color:#999
}
[data-theme=dark] .formmain {
background:#323232
}
[data-theme=dark] .comments {
background:rgba(90, 90, 90, .8)
}
</style>



<div id="computer">
<div id="maincontent">
<br />
<div id="form-wrap">
<img src="https://npm.elemecdn.com/cover_img/msg/before.webp" id="beforeimg" />
<div id="envelope">
<form>
<div class="formmain">
<img class="headerimg" src="https://npm.elemecdn.com/cover_img/msg/U5bb04af32be544c4b41206d9a42fcacfd.webp" />
<div style="padding: 5px 20px;">
<center>
<h3 calss="title3">来自小嘉的留言:</h3>
</center>
<center class="comments">
有什么想问的?
<br />有什么想说的?
<br />有什么想吐槽的?
<br />
</center>
<div class="bottomcontent">
<img class="bottomimg" src="https://npm.elemecdn.com/cover_img/msg/U0968ee80fd5c4f05a02bdda9709b041eE.webp" />
</div>
<p class="bottomhr">自动书记人偶竭诚为您服务!</p>
</div>
</div>
</form>
</div>
<img id="afterimg" src="https://npm.elemecdn.com/cover_img/msg/after.webp" />
</div>
</div>
</div>
<div id="mobile">
<form>
<div class="formmain">
<img class="headerimg" src="https://npm.elemecdn.com/cover_img/msg/U5bb04af32be544c4b41206d9a42fcacfd.webp" />
<div style="padding: 5px 20px;">
<center>
<h3 class="title3">来自左耳的留言:</h3>
</center>
<center class="comments">
有什么想问的?
<br />有什么想说的?
<br />有什么想吐槽的?
<br />
</center>
<div class="bottomcontent">
<img src="https://npm.elemecdn.com/cover_img/msg/U0968ee80fd5c4f05a02bdda9709b041eE.webp" class="bottomhr" />
</div>
<p class="bottomhr" "="">自动书记人偶竭诚为您服务!</p>
</div>
</div>
</form>
</div>


{% endraw %}

1.安装npm插件

见:https://github.com/Akilarlxh/hexo-butterfly-envelope (也可以看源码学习一个插件是怎么做的,很简单的功能)

1
npm install hexo-butterfly-envelope --save

2.修改配置文件(站点/主题文件都可以)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
envelope_comment:
enable: true
cover: https://ae01.alicdn.com/kf/U5bb04af32be544c4b41206d9a42fcacfd.jpg # 信笺封面图
message: # 信笺内容,支持多行
- 有什么想问的?
- 有什么想说的?
- 有什么想吐槽的?
bottom: 自动书记人偶竭诚为您服务! # 信笺结束语,只能单行
height: # 调整信笺划出高度,默认1050px
path: # 【可选】comments 的路径名称。默认为 comments , 生成的页面为 comments/index.html
front_matter: # 【可选】comments页面的 front_matter 配置
title: 留言板
comments: false
aside: false

日志页

1.hexo根目录执行hexo new page timeline

2.在source/timeline/index.md增加type: "timeline"

1
2
3
4
5
6
---
title: 日志
date: 2024-10-17 08:28:51
type: "timeline"
---

关于页

1.hexo根目录执行hexo new page about

2.在source/about/index.md增加type: "about"

1
2
3
4
5
6
---
title: 关于
date: 2018-01-05 00:00:00
type: about
---

统计页

1.创建charts页

1
hexo new page charts

2.引入echarts

1
2
3
inject:
head:
- <script src="https://npm.elemecdn.com/echarts@4.9.0/dist/echarts.min.js"></script>

或者在页面引入脚本也可以

3.可以在 [Blogroot]\themes\butterfly\scripts\helpers\ 目录下新建 charts.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
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
const cheerio = require('cheerio')
const moment = require('moment')

hexo.extend.filter.register('after_render:html', function (locals) {
const $ = cheerio.load(locals)
const post = $('#posts-chart')
const tag = $('#tags-chart')
const category = $('#categories-chart')
const htmlEncode = false

if (post.length > 0 || tag.length > 0 || category.length > 0) {
if (post.length > 0 && $('#postsChart').length === 0) {
if (post.attr('data-encode') === 'true') htmlEncode = true
post.after(postsChart(post.attr('data-start')))
}
if (tag.length > 0 && $('#tagsChart').length === 0) {
if (tag.attr('data-encode') === 'true') htmlEncode = true
tag.after(tagsChart(tag.attr('data-length')))
}
if (category.length > 0 && $('#categoriesChart').length === 0) {
if (category.attr('data-encode') === 'true') htmlEncode = true
category.after(categoriesChart(category.attr('data-parent')))
}

if (htmlEncode) {
return $.root().html().replace(/&amp;#/g, '&#')
} else {
return $.root().html()
}
} else {
return locals
}
}, 15)

function postsChart (startMonth) {
const startDate = moment(startMonth || '2020-01')
const endDate = moment()

const monthMap = new Map()
const dayTime = 3600 * 24 * 1000
for (let time = startDate; time <= endDate; time += dayTime) {
const month = moment(time).format('YYYY-MM')
if (!monthMap.has(month)) {
monthMap.set(month, 0)
}
}
hexo.locals.get('posts').forEach(function (post) {
const month = post.date.format('YYYY-MM')
if (monthMap.has(month)) {
monthMap.set(month, monthMap.get(month) + 1)
}
})
const monthArr = JSON.stringify([...monthMap.keys()])
const monthValueArr = JSON.stringify([...monthMap.values()])

return `
<script id="postsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var postsChart = echarts.init(document.getElementById('posts-chart'), 'light');
var postsOption = {
title: {
text: '文章发布统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'axis'
},
xAxis: {
name: '日期',
type: 'category',
boundaryGap: false,
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${monthArr}
},
yAxis: {
name: '文章篇数',
type: 'value',
nameTextStyle: {
color: color
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'line',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
itemStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
areaStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
}, {
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
data: ${monthValueArr},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
postsChart.setOption(postsOption);
window.addEventListener('resize', () => {
postsChart.resize();
});
postsChart.on('click', 'series', (event) => {
if (event.componentType === 'series') window.location.href = '/archives/' + event.name.replace('-', '/');
});
</script>`
}

function tagsChart (len) {
const tagArr = []
hexo.locals.get('tags').map(function (tag) {
tagArr.push({ name: tag.name, value: tag.length, path: tag.path })
})
tagArr.sort((a, b) => { return b.value - a.value })

const dataLength = Math.min(tagArr.length, len) || tagArr.length
const tagNameArr = []
for (let i = 0; i < dataLength; i++) {
tagNameArr.push(tagArr[i].name)
}
const tagNameArrJson = JSON.stringify(tagNameArr)
const tagArrJson = JSON.stringify(tagArr)

return `
<script id="tagsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var tagsChart = echarts.init(document.getElementById('tags-chart'), 'light');
var tagsOption = {
title: {
text: 'Top ${dataLength} 标签统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {},
xAxis: {
name: '标签',
type: 'category',
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color,
interval: 0
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${tagNameArrJson}
},
yAxis: {
name: '文章篇数',
type: 'value',
splitLine: {
show: false
},
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'bar',
data: ${tagArrJson},
itemStyle: {
borderRadius: [5, 5, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 195)'
},
{
offset: 1,
color: 'rgba(1, 211, 255)'
}])
}
},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
tagsChart.setOption(tagsOption);
window.addEventListener('resize', () => {
tagsChart.resize();
});
tagsChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

function categoriesChart (dataParent) {
const categoryArr = []
let categoryParentFlag = false
hexo.locals.get('categories').map(function (category) {
if (category.parent) categoryParentFlag = true
categoryArr.push({
name: category.name,
value: category.length,
path: category.path,
id: category._id,
parentId: category.parent || '0'
})
})
categoryParentFlag = categoryParentFlag && dataParent === 'true'
categoryArr.sort((a, b) => { return b.value - a.value })
function translateListToTree (data, parent) {
let tree = []
let temp
data.forEach((item, index) => {
if (data[index].parentId == parent) {
let obj = data[index];
temp = translateListToTree(data, data[index].id);
if (temp.length > 0) {
obj.children = temp
}
if (tree.indexOf())
tree.push(obj)
}
})
return tree
}
const categoryNameJson = JSON.stringify(categoryArr.map(function (category) { return category.name }))
const categoryArrJson = JSON.stringify(categoryArr)
const categoryArrParentJson = JSON.stringify(translateListToTree(categoryArr, '0'))

return `
<script id="categoriesChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var categoriesChart = echarts.init(document.getElementById('categories-chart'), 'light');
var categoryParentFlag = ${categoryParentFlag}
var categoriesOption = {
title: {
text: '文章分类统计图',
x: 'center',
textStyle: {
color: color
}
},
legend: {
top: 'bottom',
data: ${categoryNameJson},
textStyle: {
color: color
}
},
tooltip: {
trigger: 'item'
},
series: []
};
categoriesOption.series.push(
categoryParentFlag ?
{
nodeClick :false,
name: '文章篇数',
type: 'sunburst',
radius: ['15%', '90%'],
center: ['50%', '55%'],
sort: 'desc',
data: ${categoryArrParentJson},
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
emphasis: {
focus: 'ancestor',
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
:
{
name: '文章篇数',
type: 'pie',
radius: [30, 80],
roseType: 'area',
label: {
color: color,
formatter: '{b} : {c} ({d}%)'
},
data: ${categoryArrJson},
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
)
categoriesChart.setOption(categoriesOption);
window.addEventListener('resize', () => {
categoriesChart.resize();
});
categoriesChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

更多echarts配置项

4.[Blogroot]\source\charts\index.md添加内容

1
2
3
4
5
6
<!-- 文章发布时间统计图 -->
<div id="posts-chart" data-start="2021-01" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
<!-- 文章标签统计图 -->
<div id="tags-chart" data-length="10" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
<!-- 文章分类统计图 -->
<div id="categories-chart" data-parent="true" style="border-radius: 8px; height: 300px; padding: 10px;"></div>

5.如果要在标签页、分类页则要修改PUG源码

比如:归档页使用统计图,[Blogroot]\themes\butterfly\layout\archive.pug

1
2
3
4
5
6
extends includes/layout.pug

block content
include ./includes/mixins/article-sort.pug
#archive
+ <div id="posts-chart" data-start="2021-01" style="height: 300px; padding: 10px;"></div>

pug写法:

1
#posts-chart(data-start="2021-01" style="height: 300px; padding: 10px;")。

博客部署

部署到云服务器

  • 买个服务器(备案)
  • 买个域名(解析、HTTPS、SSL)

Git钩子自动部署

  • 服务器配置

1.安装 git nginx

1
2
3
4
5
6
7
yum -y update
yum install -y git nginx

安装完后,rpm -qa | grep nginx 查看
启动nginx:systemctl start nginx
加入开机启动:systemctl enable nginx
查看nginx的状态:systemctl status nginx

2.创建博客目录

1
2
mkdir -p /data/www/blog
chmod -R 755 /data/www/blog

3.配置nginx

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
vim /etc/nginx/nginx.conf
# vim 查找: /listen 80
# 如果是root用户启动,则设置
# user root
server {
listen 443 ssl;
#填写绑定证书的域名
server_name 域名(xxx.com);
#证书文件名称
ssl_certificate 域名(xxx.com)_bundle.crt;
#私钥文件名称
ssl_certificate_key 域名(xxx.com).key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
location / {
#网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
#例如,您的网站运行目录在/etc/www下,则填写/etc/www。
root /data/www/blog;
index index.html index.htm;
}
}
server {
listen 80;
#填写绑定证书的域名
server_name 域名(xxx.com);
#把http的域名请求转成https
return 301 https://$host$request_uri;
}

4.测试index.html

1
2
3
4
5
6
7
8
9
10
11
12
vim /data/www/blog/index.html

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="UTF-8">
</head>
<body>
<p>Nginx running</p>
</body>
</html>

5.配置git

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mkdir /data/git_repo
chmod -R 755 /data/git_repo
> 初始化裸库
cd /data/git_repo
git init --bare blog.git
> 创建 Git 钩子(hook):用于指定 Git 的源代码 和 Git 配置文件
vim /data/git_repo/blog.git/hooks/post-receive

#!/bin/bash
git --work-tree=/data/www/blog --git-dir=/data/git_repo/blog.git checkout -f

# 指定分支:
git --work-tree=/data/www/blog --git-dir=/data/git_repo/public.git checkout main -f

> 保存并退出后, 给该文件添加可执行权限
chmod +x /data/git_repo/blog.git/hooks/post-receive

6.本地配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
git --version
node -v
npm -v

npm install hexo-deployer-git

# hexo配置文件配置
url: http://www.域名(xxx.com) //个人域名
......
# 一个是服务器
deploy:
type: git
repo: root@xx.xx.xx.xx:/data/git_repo/blog.git
branch: master

# 一键部署
hexo clean && hexo g && hexo d

7.免密登录

1
2
3
4
5
6
7
8
cd ~
mkdir .ssh
cd .ssh
vi authorized_keys

// 这个时候把公钥,也就是windows下的.ssh/id_rsa.pub文件内的文本内容复制粘贴到authorized_keys文件中
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

部署到Github

云服务器过期了,续费太贵,想了想还是丢到Github白嫖吧,反正也没什么人看

1.安装插件npm install hexo-deployer-git --save

2.创建Github仓库:(github用户名).github.io

3.站点配置_config.yml

1
2
3
4
5
6
# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
type: 'git'
repo: https://github.com/(github用户名)/(github用户名).github.io.git
branch: main

4.部署:hexo clean && hexo g && hexo d

5.github pages 设置 Custom domain 配置 域名

6.不想每次部署后域名都失效,在source目录新增CNAME,将域名填写即可