Hexo_Butterfly 主题详解 配置文件 插件 修改 笔记

我的博客折腾的差不多了,感觉有必要整理和总结一下,以笔记的形式写在这里了。里面有关于如何配置相关选项,我用到的插件,以及如何diy相关的东西。笔记里的配置文件有些直接来自官网。

我用了butterfly这个主题,这个主题非常好看,而且也不感觉花里胡哨,设置里有很多东西可调,但是有些细节需要自己调一下,比如说页面标题颜色、有些页面太空旷,需要加张图什么的。我的原则是尽量不修改模板,这样更新主题的时候比较方便,不用merge,兼容性比较好。因此我的做法是,通过前端css的覆盖来调整样式,没法调整的用js方法来动态改变,包括评论系统也是这么动态加进来的。

1. 常用插件安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
npm install -g hexo-cli
npm install hexo-deployer-rsync --save
npm install hexo-deployer-sftp --save
npm install hexo-asset-link --save # markdown显示图片用,图片要放在同名文件夹里
npm install hexo-generator-category --save
npm install hexo-generator-tag --save
npm install hexo-hide-posts --save # 文章隐藏,但是可以通过链接访问
npm install hexo-generator-search --save # 本地搜索
npm install hexo-blog-encrypt --save # 加密文章
npm install hexo-abbrlink --save # 自定义链接

npm install hexo-wordcount --save # 字数统计
npm install hexo-renderer-marked --save # 用于自己解析markdown
npm install hexo-myadmin --save # 后台管理界面

npm install hexo hexo-filter-nofollow --save # seo
npm install hexo-generator-seo-friendly-sitemap --save
npm install hexo-generator-baidu-sitemap --save
npm install hexo-submit-urls-to-search-engine --save

2. Hexo 结构

├── config.yml
├── package.json
├── scaffolds # Hexo的模板是指在新建的文章文件中默认填充的内容
├── source # Markdown和HTML文件会被解析并放到 public 文件夹,而其他文件会被拷贝过去。
| ├── _drafts # 除了_draft, _posts外,带下划线的不会被解析到public里
| └── _posts # 博客文章存放位置
| └── xxx # hexo new page xxx 生成的,里面可以是任意文件可路由到,
开头的貌似不行
└── themes # 主题 文件夹。Hexo 会根据主题来生成静态页面。
├── _config.yml
├── languages
├── layout # 布局文件夹。用于存放主题的模板文件,swig,ejis等
├── scripts # 启动时加载
└── source # 除了模板以外的 Asset,例如 CSS、JavaScript 文件等,与上面source挂在路径同

  • source中的Mardown和HTML文件都会被解析生成到public文件夹下,会自动递归解析子文件夹,

  • 网址url则是通过插件abbrlink和permalink生成。

  • 除了_draft, _posts外,带下划线的不会被解析到public里。

3. Hexo CLI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
hexo init <folder>
cd <folder>
npm install

hexo list <type> # version
hexo new xxx # 新建一篇文章,title之后可以在markdown里改
hexo new page xxx # 创建任意页面,在/source/xxx 路径下可有/xxx路由到
hexo new page tags # 创建标签页,执行这行指令后才会生成对应的index.html下同
hexo new page categories # 创建目录页,在/source文件内,需要自己添加type: "categories"
hexo new draft <title> # 新建草稿
hexo publish [layout] <filename> [-d] # hexo g 发表草稿。-d 文件生成后立即部署网站
hexo g/generate # 移动静态文件 new page categories
hexo s/server [-p port] [-g] [-s] # 搭建服务器, -g generate, -s 静态模式
hexo d/deploy [-g] # 推送博客到远程仓库
hexo clean # 清除缓存文件 (db.json) 和已生成的静态文件 (public)。

4. _config.yml 配置文件

(1) post Front-matter

1
2
3
4
5
6
7
8
9
10

# 博客文章相关的内容,yml格式
---
title: hello_world
hide: true # hexo-hide-posts 插件设置
date: yyyy-mm-dd hh:mm:ss
updated: # 更新日期
tags: ["hello world", "initial page"]
abbrlink: # 覆盖文章网址,hexo-abbrlink
---

(2) original hexo config

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
# Site
title: ''
subtitle: ''
description: ""
keywords: ''
author: devseed
language: en
email: # 配置可以留空
timezone: ''

url: ''
root: /
permalink :title/ # 文章链接前缀, permalink: posts/:abbrlink/
post_asset_folder: true # 提交资源文件夹
relative_link: false # 用相对路径,一定要false,否则加载可能出错
categories: # 目录
date_format: YYYY-MM-DD HH:mm # 显示的时间格式
theme: landscape

# Directory
source_dir: source
public_dir: public
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render: "static/*" # 这个路径里的html, js等不会被加入代码渲染,保持原样

# index
index_generator:
path: ''
per_page: 8
order_by: -updated # update更新日期,date文章日期

(3) hexo-deployer-sftp

1
2
3
4
5
6
7
8
9
10
deploy:  # 所有路径必须是绝对路径,可有多个type
- type: sftp
host: <host>
user: <user>
pass: <password>
remotePath: [remote path]
port: [port]
privateKey: [path/to/privateKey]
passphrase: [passphrase]
agent: [path/to/agent/socket]

(4) hexo-hide-posts

1
2
3
4
5
6
hide_posts: 
filter: hide # Change the filter name to fit your need
# Generators which you want to expose all posts (include hidden ones) to.
# Common generators: index, tag, category, archive, sitemap, feed, etc.
public_generators: []
noindex: true # Add "noindex" meta tag to prevent hidden posts from being indexed by search engines
1
2
3
4
search: 
path: search.xml
field: post
content: true
1
2
3
abbrlink: #abbrlink配置
alg: crc16 # suanfa:crc16(default) and crc32
rep: dec # jinzhi:dec(default) and hex

(7) hexo-myadmin

1
2
3
4
admin: # pm2 start node_modules/.bin/hexo -- server
username: myfavoritename
password_hash: '' # bcrypt hash
secret: yoursecret

(8) seo

1
2
3
4
5
6
7
8
9
10
nofollow: # 防止无关链接分散权重
enable: true
field: site
exclude: # 友链部分加在此处

baidusitemap:
path: baidusitemap.xml

sitemap:
path: sitemap.xml

5. butterfly

(1) 安装

git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/Butterfly
npm install hexo-renderer-pug hexo-renderer-stylus —save

把主題文件夾中的 _config.yml 複製到 Hexo 根目錄裏,同時重新命名為 _config.butterfly.yml。
文件根目录为source路径。

(2) _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
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
menu:
Home: / || fas fa-home
Archives: /archives/ || fas fa-archive
Tags: /tags/ || fas fa-tags
Categories: /categories/ || fas fa-folder-open

favicon: /img/favicon.ico # Favicon(網站圖標)
avatar: # Avatar (頭像)
img: /img/favicon.ico
effect: false
index_img: /img/banner.png # The banner image of home page
default_top_img: /img/banner.png

mathjax:
enable: true
per_page: false # false时須在使用的 Markdown Front-matter 加上 mathjax: true

local_search:
enable: true

wordcount:
enable: true
post_wordcount: true
min2read: true
total_wordcount: true

social: # 此项会显示在author card里面
fab fa-github: https://github.com/xxxxx || Github # "Font Awesome 5 Brands"
fas fa-envelope: mailto:[email protected] || Email

post_meta:
page: # Home Page
date_type: both # created or updated or both 主頁文章日期是創建日或者更新日或都顯示
date_format: date # date/relative 顯示日期還是相對日期
categories: true # true or false 主頁是否顯示分類
tags: false # true or false 主頁是否顯示標籤
label: true # true or false 顯示描述性文字
post:
date_type: both # created or updated or both 文章頁日期是創建日或者更新日或都顯示
date_format: date # date/relative 顯示日期還是相對日期
categories: true # true or false 文章頁是否顯示分類
tags: true # true or false 文章頁是否顯示標籤
label: true # true or false 顯示描述性文字

cover: # display the cover or not (是否顯示文章封面)
index_enable: true
aside_enable: true
archives_enable: true
position: both # the position of cover in home page, left/right/both
default_cover: /img/default.png # When cover not set, the default cover

subtitle:
enable: true
effect: true # Typewriter Effect (打字效果)
loop: true # loop (循環打字)
source: false
sub: ["by devseed"]

beautify:
enable: true
field: site # site/post
title-prefix-icon: '\f0c1'
title-prefix-icon-color: "#F47466"

background: rgba(183, 183, 254, 255)
index_site_info_top: # eg: 300px/300em/300rem/10% (主頁標題距離頂部距離)
index_top_img_height: # eg: 300px/300em/300rem (主頁top_img高度)

aside:
enable: true
hide: true
button: true
mobile: true # display on mobile
position: left # left or right
card_author:
enable: true
description:
button:
icon: fab fa-github
text: Follow Me
link: https://github.com/yurisizuku
card_announcement:
enable: false
content: This is my Blog
card_recent_post:
...

footer:
owner:
enable: true
since: 2020
custom_text:
copyright: true # Copyright of theme and framework

lazyload: # 图片延迟加载
enable: true
post: /img/loading.gif

inject: # 改变原有js/css/meta
head:
- <link rel="stylesheet" href="/hook/hook_style.css">

bottom:
- <script src="/hook/hook_style.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/marked.min.js"></script>
- <script src="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.js"></script>
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/highlightjs-line-numbers.min.js"></script>

(3) POST Front-matter

1
2
3
4
5
6
7
8
9
10
11
---
top_img: ./hello_world/flowers.jpg # 要填写生成的网址上的路径,与markdown里的图片不同
cover: ./hello_world/flowers.jpg
toc: 【可選】是否显示toc目录 (除非特定文章设置,可以不写)
toc_number: # 是否显示toc目录数字 (除非特定文章设置,可以不写)
sticky: 1 【可選】 置顶
hide: true # 需要hexo-generator-indexed插件
description:【可選】文章描述
aside: 【可選】显示侧边栏
comments: 【可選】顯示文章評論模塊(默認 true)
---

(4) PAGE Front-matter

1
2
3
4
5
6
7
8
9
10
11
---
title 【必需】頁面標題
date 【必需】頁面創建日期
type 【必需】tags、catagories、link
updated 【可選】頁面更新日期
description 【可選】頁面描述
keywords 【可選】頁面關鍵字
comments 【可選】顯示頁面評論模塊(默認 true)
aside: 【可選】显示侧边栏
top_img 【可選】頁面頂部圖片
---

(5) fancybox 增加下载按钮(js文件)

1
2
3
4
5
6
7
8
9
10
11
12
//http://fancyapps.com/fancybox/3/docs/
$('[data-fancybox]').fancybox({
protect: false,
buttons : [
'download',
"slideShow",
'zoom',
'thumbs',
'close',]
});

$('#acg_image').append('<a data-fancybox="group" class="fancybox"><img class="fade-in"/></a>'); //动态生成fancybox块

6. HOOK

在修改butterfly配置信息里没有的内容时(比如说标题颜色),为了不修改原来框架,采取

  • 覆盖的方式改css样式(ctrl+f12审查来查找元素)
  • js动态加入hook的方式来改布局(比如说插入图片,动态增加部件,动态调整等)。

为了方便管理,将hook内容(包括MiniComment)放到./source/hook中,生成的文件则到/public/hook中。这里有一点需要注意,就是如果用了cdn要清一下缓存,否则js和css文件可能不会立即生效。

hook_style.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
function remove_banner(){
var page_header = $('#page-header');
if(page_header.length > 0)
page_header[0].style.background = "transparent";
}

function add_tag_img(imgsrc){
var tag = $('.tag-cloud-list');
tag.after('<div><img src="' + imgsrc + '"/></div>');
}

function add_catogory_img(imgsrc){
var catogory = $('.category-lists');
catogory.after('<div><img src="' + imgsrc + '"/></div>');
}

function add_archive_img(imgsrc){
if($('#archive').length >= 1){
$('#pagination').prepend('<div><img src="' + imgsrc + '"/></div>');
}
}

function add_home_img(imgsrc, least, max){
if($('.recent-post-item').length <= max
&& $('.recent-post-item').length >=least){
$('#pagination').prepend('<div><img src="' + imgsrc + '"/></div>');
}
}

function add_mini_comment(){ // 加载MiniComment
var article_title = $('meta[property="og:title"]').attr('content');
if ($('meta[article_title]').length <= 0 ){
$($('meta')[0]).after('<meta article_title="">');
}
switch(article_title.toLowerCase()){
case "home":
case "archives":
case "tags":
case "catagories":
case "about": break;
case "comments":
$('meta[article_title]').attr('article_title', "Comments");
$('#page').append('<div id="mini_comment"></div>');
$('div#mini_comment').load("/hook/ui_comment.xhtml");
break;
default:
$('meta[article_title]').attr('article_title', article_title);
$('#post').append('<div id="mini_comment"></div>');
$('div#mini_comment').load("/hook/ui_comment.xhtml");
break;
}
}

remove_banner()
add_tag_img("hhttps://static.acgsoso.com/uploads/2020/10/32335eebe508ee49c3895b833ae7e0fd.jpg");
add_catogory_img("https://static.acgsoso.com/uploads/2020/10/32335eebe508ee49c3895b833ae7e0fd.jpg");
add_archive_img("https://static.acgsoso.com/uploads/2020/10/32335eebe508ee49c3895b833ae7e0fd.jpg");
add_home_img("https://static.acgsoso.com/uploads/2020/10/32335eebe508ee49c3895b833ae7e0fd.jpg", 1, 2);
add_home_img("https://static.acgsoso.com/uploads/2020/02/567df8ed23cd6f7da62b22589f8af589.jpg", 3, 4);
add_mini_comment();

hook_style.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
#nav #site-name { /*左上角网站名*/
/*text-shadow: 0.05rem 0.05rem 0.1rem #49b1f5;color: #2b36e29c;*/
text-shadow: 0.05rem 0.05rem 0.1rem #ffffff00;
font-weight: bold;
cursor: pointer;
color: #1b84c8;
}

#nav .site-page { /*网页导航标题栏*/
position: relative;
/*padding-bottom: 0.3rem;*/
text-shadow: 0.01rem 0.01rem 0.01rem #ffffff11;
font-size: 0.78em;
font-weight: bold;
cursor: pointer;
color: #1b84c8;
}

#nav .menus_items .menus_item .menus_item_child li a { /*网页导航标题栏,二级菜单*/
color: #1b84c8;
}

#nav .site-page:hover{ /*网页导航标题栏,悬浮颜色*/
color: #49b1f5;
}

#nav.show { /*顶部导航*/
height: 1.8em;
line-height: 1rem;
background: #ffffff64;
opacity: 1;
filter: blur(0.1px);
}

#nav.visible { /*导航栏悬浮框颜色*/
padding-top: 0.4em;
height: 2.2em;
line-height: 1rem;
align-content: center;
--font-color: #1b84c8;
}

#page-header{ /*取消banner部分图*/
background: transparent;
}

#page-header #site-title { /*网页标题正中央显示*/
margin: 0;
color: #4267c1ba;
}

#page-header #site-subtitle { /*网页副标题*/
font-size: 1.72em;
color: #4267c1ba;
}

#nav { /*导航栏字体大小*/
font-size: 1.6em;
}

#page-header.post-bg:before { /*取消各块baner*/
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
height: 100%;
background: transparent;
}

#page-header.not-index-bg { /*各块banner*/
height: 24em;
}

#page-header.post-bg { /*博客文章标题信息框*/
height: 24em;
}

#page-header #post-info { /*博客文章标题信息框*/
position: absolute;
bottom:1rem;
padding: 0.7%;
width: 40%;
text-align: center;
background: #43a1ddbd;
align-content: center;
left: 10%;
}

#post-info .post-title { /*博客文章标题大小*/
margin-bottom: 0.4rem;
font-size: 1.6em;
font-weight: normal;
color: var(--white);
line-height: 1.5;
}

#page .category-lists ul li { /*分类页*/
font-size: x-large;
}

#pagination .page-number { /*底部页码*/
display: inline-block;
margin: 0 0.2rem;
min-width: 1.2rem;
height: 1.2rem;
text-align: center;
line-height: 1.2rem;
cursor: pointer;
font-weight: 900;
color: blueviolet;
}

#footer-wrap { /*脚注*/
position: relative;
padding: 0.8rem 1rem;
color: rgba(255,255,255,0.9);
text-align: center;
}

#recent-posts > .recent-post-item { /*主页文章标题框大小*/
height: 16em;
}

#pagination img.prev-cover, #pagination img.next-cover { /*预览图片透明度*/
position: absolute;
width: 100%;
height: 100%;
opacity: 0.9;
}

.relatedPosts > .relatedPosts-list .cover { /*最近添加文章预览图片透明度*/
width: 100%;
height: 100%;
opacity: 0.9;
}

7. Backup

经常备份也很重要,虽然每次手动打包不难,但是每次都要进行还是有些麻烦的,因为要去除node_modules,这里面小文件太多了。因此写了个脚本,将脚本放到hexo根目录,执行即可备份到copytodir,windows下用git bash即可运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# !/bin/bash
backupdir="./blogname[$(date +%y%m%d)]"
copytodir=""
echo "$backupdir"
mkdir "$backupdir"
for file in `ls ./` ;do
if [ "$file" == "node_modules" ];then continue;fi;
if [ "$file" == "db.json" ];then continue;fi;
if [ "$file" == "public" ];then continue;fi;
if [ "$file" == "${backupdir##*/}" ];then continue;fi;
echo $file
cp -R "$file" "$backupdir"
done
$(7z a "${backupdir##*/}.7z" "$backupdir" -mx9)
rm -rf $backupdir
mv "${backupdir##*/}.7z" "$copytodir"