github/gitee+hexo搭建博客

人生天地间,忽如远行客

1. 工具

  • github账号

注册github账号

  • node.js

让js能作为服务端脚本语言

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 检测 node版本尽量高点,不高先升级nodejs版本,我的是v16.15.0,windows建议直接下载安装包覆盖安装地址
node -v
# windows查询node安装地址
where node
# 清除npm缓存【Linux】
npm cache clean -f
# 全局安装n【Linux】
npm install -g n
# 升级到最新稳定版
$ n stable
# 升级到最新版
$ n latest
# 升级到定制版
$ n v14.6.0
# 切换使用版本
$ n 13.10.0 (ENTER)
# 删除制定版本
$ n rm 13.10.0
# 用制定的版本执行脚本
$ n use 13.10.0 some.js
  • npm

非官方的NodeJS包管理和分发工具

nodejs对应npm版本

1
2
3
4
5
# 查看版本
npm -v
cnpm -v
# 升级到指定版本
npm install -g npm@8.5.5
  • git

分布式版本控制

1
2
3
4
5
6
7
8
9
# 检测
git --version
# 配置用户名和邮箱
git config --global user.name "github 用户名"
git config --global user.email "github 注册邮箱"
# 生成SSH密钥,免于登录,进行比较,四次回车
ssh-keygen -t rsa -C "github 注册邮箱"
# 测试是否成功
ssh -T git@github.com
  • hexo

一个快速、简洁且高效的博客框架,默认端口4000

hexo文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装
npm i hexo-cli -g
# 是否成功,出现版本号
hexo -v
# 进入创建的文件夹初始化
hexo init .
npm install
# 本地测试
# 新建博客
hexo new "博客名"
# 生成静态网页
hexo g
# 打开本地服务器
hexo s
# 输入localhost:4000
# 部署
hexo d

2. 搭建个人仓库

  • 名字要和登录名相同【特别注意】
1
用户名.github.io
  • 是公开的
1
public
  • 将博客目录下的_config.yml,加入deploy设置为个人仓库名
1
2
3
4
5
deploy:
type: git
repo: 你的地址
# github更新后为main,不能是master,gitee是master
branch: main
  • 安装hexo-deployer-git自动化部署发布工具
1
npm install hexo-deployer-git --save
  • 令牌
1
2
开发者设置 Developer settings 
个人访问令牌 Personal access tokens
  • 发布博客
1
2
3
4
5
6
7
8
9
10
11
12
# 清除已生成文件及缓存
hexo clean
# hexo 新建,简写为hexo n
hexo new ""
# 生成静态页面,简写做hexo g
hexo generate
#推送到github库,简写做hexo d
hexo deploy
# 用户名
你的用户名
# 密码
令牌密码
  • gitee

  • gitee pages需要实名

  • 公开且仓库名要是用户名,不需要是 用户名.gitee.io

  • 确定公钥,私人令牌

  • 部署到gitee,需要你每次推送后,去更新一下,如果想要自动更新,就需要开通 Gitee 的会员。

1
2
3
4
5
deploy:
type: git
repo: https://github.com/xxy8/xxy8.github.io.git
https://gitee.com/xxy8/xxy8.git,master
branch: main

3. 美化博客

美化博客根据自己风格来定,我比较喜欢next风格

  • 下载next,我用的是稳定版5.1.4

next

  • 将next复制到博客根目录的themes文件下
  • 修改博客主配置文件_config.yml文件
1
2
# theme: landscape
theme: next
  • 报错
1
2
3
{% extends '_layout.swig' %} {% import '_macro/post.swig' as post_template %} {% import '_macro/sidebar.swig' as sidebar_template %} {% block title %}{{ config.title }}{% if theme.index_with_subtitle and config.subtitle %} - {{config.subtitle }}{% endif %}{% endblock %} {% block page_class %} {% if is_home() %}page-home{% endif -%} {% endblock %} {% block content %}
{% for post in page.posts %} {{ post_template.render(post, true) }} {% endfor %}
{% include '_partials/pagination.swig' %} {% endblock %} {% block sidebar %} {{ sidebar_template.render(false) }} {% endblock %}
  • 解决方案 没有hexo-renderer-swig模块
1
npm i hexo-renderer-swig

这里可能需要等待,会出现为一片空白的情况,因为github速度限制

  • 主配置的_config.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
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
# Hexo Configuration
## Docs: https://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/

# Site
# 网站标题
title: xxy
# 网站副标题
subtitle: '一笑之语'
# 网站描述 用于SEO
description: '镜中花,水中月,无至无'
# 网站的关键词。支持多个关键词。
keywords: xxy
# 您的名字
author: xxy
# 网站使用的语言,常见的有 zh-Hans和 zh-CN,建议zh-Hans
# language: en
language: zh-Hans
# 网站时区
timezone: Asia/Shanghai

# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
# url: http://example.com
url: https://xxy8.github.io
# 文章的 永久链接 格式
permalink: :year/:month/:day/:title/
# 永久链接中各部分的默认值
permalink_defaults:
# 改写 permalink 的值来美化 URL
pretty_urls:
# 是否在永久链接中保留尾部的index.html
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
# 是否在永久链接中保留尾部的 .html, 设置为 false 时去除,对尾部的 index.html无效
trailing_html: true # Set to false to remove trailing '.html' from permalinks

# Directory 如果您刚刚开始接触 Hexo,通常没有必要修改这一部分的值。
# 资源文件夹
source_dir: source
# 公共文件夹
public_dir: public
# 标签文件夹
tag_dir: tags
# 归档文件夹
archive_dir: archives
# 分类文件夹
category_dir: categories
# Include code 文件夹,source_dir 下的子目录
code_dir: downloads/code
# 国际化(i18n)文件夹
i18n_dir: :lang
# 跳过指定文件的渲染
skip_render:

# Writing
# 新文章的文件名称
new_post_name: :title.md # File name of new posts
# 预设布局
default_layout: post
# 把标题转换为 title case
titlecase: false # Transform title into titlecase
# 在新标签中打开链接
external_link:
# 在新标签中打开链接
enable: true # Open external links in new tab
# 对整个网站(site)生效或仅对文章(post)生效
field: site # Apply to the whole site
# 需要排除的域名。主域名和子域名如 www 需分别配置
exclude: ''
# 把文件名称转换为 (1) 小写或 (2) 大写
filename_case: 0
# 显示草稿
render_drafts: false
# 启动 Asset 文件夹
post_asset_folder: false
# 把链接改为与根目录的相对位址,通常情况下,建议使用绝对地址。
relative_link: false
# 显示未来的文章
future: true
# 代码块的设置
highlight:
enable: true
line_number: true
auto_detect: false
tab_replace: ''
wrap: true
hljs: false
# 代码块的设置
prismjs:
enable: false
preprocess: true
line_number: true
tab_replace: ''

# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
per_page: 10
order_by: -date

# Category & Tag
# 默认分类
default_category: uncategorized
# 分类别名
category_map:
# 标签别名
tag_map:

# Metadata elements
## https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
meta_generator: true

# Date / Time format
## Hexo uses Moment.js to parse and display date
## You can customize the date format as defined in
## http://momentjs.com/docs/#/displaying/format/
# 日期格式
date_format: YYYY-MM-DD
# 时间格式
time_format: HH:mm:ss
## updated_option supports 'mtime', 'date', 'empty'
# 当 Front Matter 中没有指定 updated 时 updated 的取值
updated_option: 'mtime'

# Pagination
## Set per_page to 0 to disable pagination
# 每页显示的文章量 (0 = 关闭分页功能)
per_page: 10
# 分页目录
pagination_dir: page

# Include / Exclude file(s)
## include:/exclude: options only apply to the 'source/' folder
# include 和 exclude 选项只会应用到 source/ ,而 ignore 选项会应用到所有文件夹.
include:
exclude:
ignore:

# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
# theme: landscape
# 当前主题名称。值为false时禁用主题
theme: next

# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
type: git
repo: https://github.com/xxy8/xxy8.github.io.git
branch: main

  • 主题配置文件next 中的_config.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
# When running the site in a subdirectory (e.g. domain.tld/blog), remove the leading slash from link value (/archives -> archives).
# Usage: `Key: /link/ || icon`
# Key is the name of menu item. If translate for this menu will find in languages - this translate will be loaded; if not - Key name will be used. Key is case-senstive.
# Value before `||` delimeter is the target link.
# Value after `||` delimeter is the name of FontAwesome icon. If icon (with or without delimeter) is not specified, question icon will be loaded.
# 设置导航栏菜单
menu_settings:
icons: true
badges: true

menu:
home: / || home
about: /about/ || user
#tags: /tags/ || tags
categories: /categories/ || th
archives: /archives/ || archive
#schedule: /schedule/ || calendar
#sitemap: /sitemap.xml || sitemap
#commonweal: /404/ || heartbeat

# Enable/Disable menu icons.
menu_icons:
enable: true


# ---------------------------------------------------------------
# Scheme Settings
# ---------------------------------------------------------------

# Schemes 主题风格,根据自己喜欢的来
#scheme: Muse
#scheme: Mist
#scheme: Pisces
scheme: Gemini
  • 版权信息声明
1
2
3
4
5
6
7
8
9
# Creative Commons 4.0 International License.
# http://creativecommons.org/
# Available: by | by-nc | by-nc-nd | by-nc-sa | by-nd | by-sa | zero
#creative_commons: by-nc-sa
creative_commons:
license: by-nc-sa
sidebar: true
post: true
language: zh_CN
  • 展示侧边栏

侧边栏还受动画影响motion. enable为false时,侧边栏不显示,影响版本5.0.0及其以下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sidebar:
# Sidebar Position, available value: left | right (only for Pisces | Gemini).
position: left
#position: right

# Sidebar Display, available value (only for Muse | Mist):
# - post expand on posts automatically. Default.
# - always expand for all pages automatically
# - hide expand only when click on the sidebar toggle icon.
# - remove Totally remove sidebar including sidebar toggle.
#display: post
display: always
#display: hide
#display: remove
  • 侧边栏头像
1
2
3
4
5
6
7
8
avatar:
# Replace the default image and set the url here.
#头像图片地址
url: /images/tx.jpg
# If true, the avatar will be dispalyed in circle.圆形选true 方形选false
rounded: true
# If true, the avatar will be rotated with the cursor.魔性转动,打开选true
rotated: true
  • 侧边栏外链
1
2
3
4
5
6
7
social:
GitHub: 地址 || github
CSDN: 地址 || CSDN
social_icons:
enable: true
icons_only: false
transition: false
  • 友情链接
1
2
#links:
#Title: http://example.com/
  • 打赏功能
1
2
3
4
5
6
7
8
9
#reward_settings:
# If true, a donate button will be displayed in every article by default.
#enable: true
#animation: false
#comment: Q:阅读本文需要付费,你是否愿意?

#reward:
#wechatpay: /images/wechatpay.png
#alipay: /images/alipay.png
  • 返回顶部
1
2
3
4
5
# Back to top in sidebar (only for Pisces | Gemini).
b2t: false

# Scroll percent label in b2t button.
scrollpercent: false
  • 关闭动画
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enable: true
async: false
transition:
# Transition variants:
# fadeIn | fadeOut | flipXIn | flipXOut | flipYIn | flipYOut | flipBounceXIn | flipBounceXOut | flipBounceYIn | flipBounceYOut
# swoopIn | swoopOut | whirlIn | whirlOut | shrinkIn | shrinkOut | expandIn | expandOut
# bounceIn | bounceOut | bounceUpIn | bounceUpOut | bounceDownIn | bounceDownOut | bounceLeftIn | bounceLeftOut | bounceRightIn | bounceRightOut
# slideUpIn | slideUpOut | slideDownIn | slideDownOut | slideLeftIn | slideLeftOut | slideRightIn | slideRightOut
# slideUpBigIn | slideUpBigOut | slideDownBigIn | slideDownBigOut | slideLeftBigIn | slideLeftBigOut | slideRightBigIn | slideRightBigOut
# perspectiveUpIn | perspectiveUpOut | perspectiveDownIn | perspectiveDownOut | perspectiveLeftIn | perspectiveLeftOut | perspectiveRightIn | perspectiveRightOut
post_block: fadeIn
post_header: slideDownIn
post_body: slideDownIn
coll_header: slideLeftIn
# Only for Pisces | Gemini.
sidebar: slideUpIn
  • 网站图标设置
1
2
3
4
5
6
7
favicon:
small: /images/favicon-16x16-next.png
medium: /images/favicon-32x32-next.png
apple_touch_icon: /images/apple-touch-icon-next.png
safari_pinned_tab: /images/logo.svg
#android_manifest: /images/manifest.json
#ms_browserconfig: /images/browserconfig.xml
  • 底部页脚
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
footer:
# Specify the date when the site was setup.
# If not defined, current year will be used.
#since: 2015

# Icon between year and copyright info.
icon: user

# If not defined, will be used `author` from Hexo main config.
copyright: xxy
# -------------------------------------------------------------
# Hexo link (Powered by Hexo).
powered: false

theme:
# Theme & scheme info link (Theme - NexT.scheme).
enable: false
# Version info of NexT after scheme info (vX.X.X).
version: false
  • 文章设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Automatically excerpt description in homepage as preamble text.
# 自动摘录描述在主页作为序言文本
excerpt_description: true
auto_excerpt:
#enable: false
enable: true
length: 150
# Post meta display settings
post_meta:
# 是否显示每项的文字
item_text: true
# 是否显示发表时间
created_at: true
# 是否显示更新时间
updated_at: true
# 是否显示分类
categories: true
  • 好看的画布
1
canvas_nest: true
  • 标签
1
2
tags: 
- 工具
  • 预览效果摘要
1
<escape><!-- more --></escape>
  • 增加模块zh-Hans.yml
1
2
3
4
5
6
7
8
9
10
11
menu:
home: 首页
archives: 归档
categories: 分类
tags: 标签
about: 关于
search: 搜索
schedule: 日程表
sitemap: 站点地图
commonweal: 公益404
shuyu: 书宇
  • 主站配置文件
1
2
3
4
# 标签文件夹
tag_dir: tags
# 书宇文件夹
shuyu_dir: shuyu
  • 主题配置文件
1
2
3
4
5
6
7
8
9
10
menu:
home: /||home
tags: /tags/||tags
#categories: /categories/ || th
archives: /archives/||fa fa-archive
about: /about/||user
#schedule: /schedule/ || calendar
#sitemap: /sitemap.xml || sitemap
#commonweal: /404/ || heartbeat
shuyu: /shuyu/||book
  • 增加文件夹
1
hexo n page shuyu
  • 文章加密
1
2
3
4
5
6
7
8
9
10
11
{# 文章加密 #}
<script>
(function(){
if('{{ page.password }}'){
if (prompt('请输入文章密码') !== '{{ page.password }}'){
alert('密码错误!');
history.back();
}
}
})();
</script>
  • markdown文件
1
2
3
4
5
6
7
8
9
10
---
title: Hello World
date: 2022/4/13 20:46:25
categories:
- Diary
tags:
- Testing
- Another Tag
password: 你的密码
---
  • 图片下面的日志链接bug,在\themes\next\layout\_macro\sidebar.swig
1
2
3
{#   <a href="{{ url_for(theme.menu.archives).split('||')[0] | trim }}">   #}
改为
<a href="{{ url_for(config.archive_dir) | trim }}">
  • 底部分页左右标签bug,在\themes\next\layout\_partials\pagination.swig
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
{% if page.prev or page.next %}
<nav class="pagination">
{{
paginator({
prev_text: '<i class="fa fa-angle-left"></i>',
next_text: '<i class="fa fa-angle-right"></i>',
mid_size: 1
})
}}
</nav>
{% endif %}

改为

{% if page.prev or page.next %}
<nav class="pagination">
{{
paginator({
prev_text: '<i class="fa fa-hand-o-left" aria-label="' + __('accessibility.prev_page') + '"></i>',
next_text: '<i class="fa fa-hand-o-right" aria-label="' + __('accessibility.next_page') + '"></i>',
mid_size: 1,
escape : false
})
}}
</nav>
{% endif %}

  • 点击目录不跳转bug,在next里的js文件post-details.js
1
2
3
4
5
6
$('.post-toc a').on('click', function (e) {
e.preventDefault();
var targetSelector = NexT.utils.escapeSelector(this.getAttribute('href'));
<!-- 添加下面这行代码, 重新解析 URL ->
targetSelector = decodeURI(this.getAttribute('href'));
var offset = $(targetSelector).offset().top;
  • 目录只显示一级和二级bug,文章目录样式文件custom.styl文件位于themes/next/source/css/_custom
1
2
3
4
5
//文章目录默认展开
.post-toc .nav .nav-child { display: block; }
.post-toc ol {
font-size : 13px;
}
  • 主题配置文件位于themes/next/_config.yml
1
2
3
4
5
6
toc:
enable: true
# 过长自动换行
wrap: true
expand_all: true
max_depth: 6

4. 小工具

  • 本地搜索
  • 主题配置文件
1
2
3
4
5
6
7
8
9
10
11
# Local search
# Dependencies: https://github.com/flashlab/hexo-generator-search
local_search:
enable: true
# if auto, trigger search by changing input
# if manual, trigger search by pressing enter key or search button
# 选auto则搜索时输入自动出现结果,选manual则搜索时输入完成需手动点击回车或搜索按钮出结果
trigger: auto
# show top n results per article, show all results by setting to -1
# 显示每篇文章的top n个结果,通过设置为-1显示所有结果
top_n_per_article: 1
  • 在根目录下使用以下命令安装
1
$ npm install hexo-generator-searchdb --save
  • 站点配置文件
1
2
3
4
5
6
# 本地搜索
search:
path: search.xml
field: post
format: html
limit: 10000
  • 网站底部字数统计

  • 安装插件

1
npm install hexo-wordcount --save
  • 然后在 /themes/next/layout/_partials/footer.njk 的合适的地方写入
1
2
3
4
<div class="theme-info">
<div class="powered-by"></div>
<span class="post-count">博客全站共{{ totalcount(site) }}字</span>
</div>
  • 实现字数统计和阅读需要时长显示

  • 安装插件

1
npm install hexo-symbols-count-time --save
  • 在主配置文件的 _config.yml 下写入
1
2
3
4
5
6
symbols_count_time:
symbols: true # 文章字数统计
time: true # 文章阅读时长
total_symbols: true # 站点总字数统计
total_time: true # 站点总阅读时长
exclude_codeblock: false # 排除代码字数统计

5. 增加复制功能

NexT版本为v5.1.4,NexT主题的v6.3已有此功能

5.1 添加copy-code.swig

themes/next/layout/_third-party/此目录下创建copy-code.swig

  • copy-code.swig
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
{% if theme.codeblock.copy_button.enable %}
<style>
.copy-btn {
display: inline-block;
padding: 6px 12px;
font-size: 13px;
font-weight: 700;
line-height: 20px;
color: #4D4D4C;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
background-color: #F7F7F7;
background-image: linear-gradient(#F7F7F7, #F7F7F7);
border: 1px solid #d5d5d5;
border-radius: 3px;
user-select: none;
outline: 0;
}

.highlight-wrap .copy-btn {
transition: opacity .3s ease-in-out;
opacity: 0;
padding: 2px 6px;
position: absolute;
right: 4px;
top: 10px;
//防止和展开代码冲突
z-index: 9;
}

.highlight-wrap:hover .copy-btn,
.highlight-wrap .copy-btn:focus {
opacity: 1
}

.highlight-wrap {
position: relative;
}
</style>

<script>
$('.highlight').each(function (i, e) {
var $wrap = $('<div>').addClass('highlight-wrap')
$(e).after($wrap)
$wrap.append($('<button>').addClass('copy-btn').append('{{__("post.copy_button")}}').on('click', function (e) {
var code = $(this).parent().find('.code').find('.line').map(function (i, e) {
return $(e).text()
}).toArray().join('\n')
var ta = document.createElement('textarea')
document.body.appendChild(ta)
ta.style.position = 'absolute'
ta.style.top = '0px'
ta.style.left = '0px'
ta.value = code
ta.select()
ta.focus()
var result = document.execCommand('copy')
document.body.removeChild(ta)
{% if theme.codeblock.copy_button.show_result %}
if(result)$(this).text('{{__("post.copy_success")}}')
else $(this).text('{{__("post.copy_failure")}}')
{% endif %}
$(this).blur()
})).on('mouseleave', function (e) {
var $b = $(this).find('.copy-btn')
setTimeout(function () {
$b.text('{{__("post.copy_button")}}')
}, 300)
}).append(e)
})
</script>
{% endif %}

5.2 编辑_layout.swig

themes/next/layout/文件下编辑_layout.swig

1
2
3
4
 # 要加入的代码
{% include '_third-party/copy-code.swig' %}
</body>
</html>

5.3 添加按钮上显示的语言

themes/next/languages/目录下编辑zh-Hans.yml

1
2
3
4
5
post:
...
copy_button: 复制
copy_success: 复制成功
copy_failure: 复制失败

同理en.yml

1
2
3
4
5
post:
...
copy_button: Copy
copy_success: Copied
copy_failure: Copy failed

5.4 编辑主题配置

themes/next/_config.yml下添加

1
2
3
4
5
6
7
# Add copy button on codeblock
codeblock:
border_radius:
copy_button:
enable: true
# Show text copy result
show_result: true

5.5 生成测试

1
2
hexo g
hexo d

6. 展开关闭代码

6.1 添加code-unfold.swig

themes/next/layout/_third-party/此目录下创建copy-code.swig

  • code-unfold.swig
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
{% if theme.codeblock.js_retract_code_btn.enable %}
<style>
.highlight-container {
position: relative;
background-color: highlight-background;
margin-left: 0.5em;
}

.highlight-container.on .highlight-footer {
display: none;
}

.highlight-container.on .hide-btn {
display: flex;
}

.highlight-container.on .highlight-wrap {
max-height: none;
}

.highlight-container .highlight-wrap {
overflow: hidden;
max-height: 200px;
}

.highlight-container .highlight-footer {
position: absolute;
width: 100%;
left: 0;
bottom: 0;
height: 60px;
background-image: linear-gradient(-180deg, rgba(255,255,255,0), rgba(45, 41, 41, 0.1));
text-align: center;
}

.highlight-container .show-btn {
font-size: 12px;
color: #fff;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 0;
line-height: 2em;
text-decoration: none;
padding: 0 0.8em;
text-align: center;
border-radius: 4px 4px 0;
}

.highlight-container .show-btn:hover {
text-decoration: none;
}

.highlight-container .hide-btn {
color: #fff;
font-size: 12px;
width: 22px;
position: absolute;
left: -21px;
top: 0px;
line-height: 1em;
text-decoration: none;
text-align: center;
display: none;
flex-direction: column;
background-color: highlight-background;
border-radius: 4px 0 0 4px;
padding: 0.1em 0 0.6em;
transition: top ease 0.35s;
}

.highlight-container .fa-angle-up,
.highlight-container .fa-angle-down {
font-style: normal;
color: #fff;
}
.highlight-container .fa-angle-up:before {
content:"\f106"
}

.highlight-container .fa-angle-down:before {
content:"\f107"
margin-left: 0.5em;
}

.highlight-container .js_unfold_code_btn,
.highlight-container .js_retract_code_btn {
background: rgba(0, 0, 0, 0.5);
border-bottom: none !important;
}

.highlight-container .js_unfold_code_btn:hover,
.highlight-container .js_retract_code_btn:hover {
border-bottom-color: none !important;
}
</style>
<script>
var CODE_MAX_HEIGHT = 1200;
var containers = [];

// 展开
$('body').on('click', '.js_unfold_code_btn', function () {
$(this).closest('.js_highlight_container').addClass('on');
});
// 收起
$('body').on('click', '.js_retract_code_btn', function () {
var $container = $(this).closest('.js_highlight_container').removeClass('on');
var winTop = $(window).scrollTop();
var offsetTop = $container.offset().top;
$(this).css('top', 0);
if (winTop > offsetTop) {
// 设置滚动条位置
$('body, html').animate({
scrollTop: $container.offset().top - CODE_MAX_HEIGHT
}, 600);
}
});
// 滚动事件,触发动画效果
$(window).on('scroll', function () {
var scrollTop = $(window).scrollTop();
var temp = [];
for (let i = 0; i < containers.length; i++) {
var item = containers[i];
var { $container, height, $hide, hasHorizontalScrollbar } = item;
if ($container.closest('body').length === 0) {
// 如果 $container 元素已经不在页面上, 则删除该元素
// 防止pjax页面跳转之后,元素未删除
continue;
}
temp.push(item);
if (!$container.hasClass('on')) {
continue;
}
var offsetTop = $container.offset().top;
var hideBtnHeight = $hide.outerHeight();
// 减去按钮高度,减去底部滚动条高度
var maxTop = parseInt(height - (hasHorizontalScrollbar ? 17 : 0) - hideBtnHeight);
let top = parseInt(
Math.min(
Math.max(scrollTop - offsetTop, 0), // 如果小于 0 ,则取 0
maxTop,// 如果大于 height ,则取 height
)
);
// 根据 sin 曲线设置"收起代码"位置
var halfHeight = parseInt($(window).height() / 2 * Math.sin((top / maxTop) * 90 * (2 * Math.PI/360)));
$hide.css('top', Math.min(top + halfHeight, maxTop));
}
containers = temp;
});

// 添加隐藏容器
function addCodeWrap($node) {
var $container = $node.wrap('<div class="js_highlight_container highlight-container"><div class="highlight-wrap"></div></div>').closest('.js_highlight_container');

// 底部 "展开代码" 与 侧边栏 "收起代码"
var $btn = $(`
<div class="highlight-footer">
<a class="js_unfold_code_btn show-btn" href="javascript:;">展开代码<i class="fa fa-angle-down" aria-hidden="true"></i></a>
</div>
<a class="js_retract_code_btn hide-btn" href="javascript:;"><i class="fa fa-angle-up" aria-hidden="true"></i>收起代码</a>
`);

$container.append($btn);
return $container;
};

function codeUnfold () {
$('.highlight').each(function () {
// 防止重复渲染
if (this.__render__ === true) {
return true;
}
this.__render__ = true;
var $this = $(this);
var height = $(this).outerHeight();
if (height > CODE_MAX_HEIGHT) {
// 添加展开&收起容器
var $container = addCodeWrap($this, height);
containers.push({
$container,
height,
$hide: $container.find('.js_retract_code_btn'),
hasHorizontalScrollbar: this.scrollWidth > this.offsetWidth,
});
}
});
};
</script>
{% endif %}

6.2 添加jquery

  • 方案一:在themes/next/_config.yml下编辑,因为fancybox会依赖jquery,所以设置成true
1
fancybox: true
  • 方案二:在next主题全局引用jquery

6.3 编辑_layout.swig

themes/next/layout/文件下编辑_layout.swig

1
{% include '_third-party/code-unfold.swig' %}

6.4 编辑主题配置

themes/next/_config.yml下添加

1
2
3
4
# Add copy button on codeblock
codeblock:
js_retract_code_btn:
enable: true

6.4 调用js方法

D:\blog\themes\next\source\js\src目录下的bootstrap.js文件添加代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$(document).ready(function () {

$(document).trigger('bootstrap:before');

NexT.utils.isMobile() && window.FastClick.attach(document.body);

NexT.utils.lazyLoadPostsImages();

NexT.utils.registerESCKeyEvent();

NexT.utils.registerBackToTop();
//添加的代码
codeUnfold();
...

6.5 生成测试

1
2
hexo g
hexo d

7. 总结

在本次搭建博客中,对github pages能作为微服务器有了了解,也对自己的博客有了大致框架,遵循简洁实用的原则。