摘要

本文介绍了使用Hexo配置本博客和用Markdown进行博文写作的基本方法和技巧,为撰写排版更好更清晰的技术文本作准备。

前言

之前代码从来都是习惯在组里LinuxPC或者学校HPC上写的,但时常会因为不在随手可及的地方觉得不安。年前从学长手中购入MBP作为自己今后的代码生产主力,同时跑一点简单的科学代码,也想着把Linux和原笔记本上的一些代码项目移到Mac上。这自然就包括了这个Hexo博客。
尽管技术写作和笔记并没有停滞,但是一直处于比较粗浅的笔记状态,就没有敢上传到这里(还是希望比较成型后再传)。更主要的一个原因是觉得这个博客的界面配置还始终是未完成状态,自己不甚满意,平时也没有时间好好研究JavaScript和Nodejs代码,最后就没有上传笔记的动力了,导致这个个人域名完全处于浪费钱的状态。于是想趁着春节假期把博客框架好好整一整。
这篇文章内所有命令均在macOS High Sierra (10.13)或Mojave (10.14)下执行。默认Homebrew基本配置完成,包括本文所涉及的Git和Nodejs开发环境等,执行命令前需要拥有GitHub账户并完成Git全局配置。

基本配置

GitHub Pages

个人博客服务端使用Git Pages,它是GitHub专为个人、组织用户和代码项目提供的页面服务,通过Git将本地HTML和CSS文件结构部署(deploy)到Page仓库master分支来实现。创建个人页面的方法是

  1. 类似于一般代码仓库,在GitHub主页上创建名为username@github.io的仓库。以自己为例的话就是minyez@github.io的仓库。个人主页必须以此种方式命名。
  2. 进入新建的仓库,点击Setting标签,在Options下翻到GitHub Pages标签,可以看到这一部分处于激活模式。可与你的其他一般仓库(没有制作doc分支用于文档网站)进行对比。一般代码仓库也可以通过Setting->Options->GitHub Pages配置项目文档页面,需要选择doc分支承载HTML文件结构。
  3. 回到Code标签,新建hexo分支,并将其设为默认分支。之后master分支用来存储静态网页,hexo分支存储博文和主题的源文件。

安装Hexo和Git部署模块

Hexo是一个模块集成的HTML和CSS文件结构生成程序,用户可以把精力集中在博文内容上,而让Hexo管理界面风格和样式。通过node包管理器npm安装hexo

1
npm hexo install

安装完成后,在某路径下,创建本地Hexo文件夹并初始化。以my-hexo-dir为例

1
2
3
mkdir my-hexo-dir
cd my-hexo-dir
hexo init

初始化后,文件夹内结构为

1
2
3
4
5
6
7
8
.
├── _config.yml
├── node_modules
├── package-lock.json
├── package.json
├── scaffolds
├── source
└── themes

node_modules内包含在搭建网站时可能需要的模块,比如数学渲染模块hexo-renderer-mathjax和Git部署模块hexo-deployer-git,后者是我们通过Git部署GitHub Pages所必须的。安装模块通过npm完成,如

1
npm install hexo-deployer-git --save

加入save选项会更新package.json内的包依赖。 --save--save-dev选项的比较可见这篇文章

修改_config.yml中网络链接和与部署方法相关的代码块以启用git部署

1
2
3
4
5
6
7
# URL
url: http://minyez.github.io
# deploy method. By Git
deploy:
type: git
repo: https://github.com/minyez/minyez.github.io.git
branch: master

这样一来,通过Hexo发布自己个人GitHub Pages博客的必要准备已经完成了。在my-hexo-dir下键入以下命令生成静态博客

1
2
hexo g         # 使用Hexo生成HTML
hexo s -p 4000 # 生成本地网址,端口为4000

在浏览器访问https://localhost:4000 即可看到生成的Hexo博客。通过

1
hexo d

可以将静态页面推送到GitHub Pages中, 此时就能在username.github.io上看到博客了.

主题选择

本博客使用的是从PytLab处Fork来的Freemind主题。首先将仓库下载到本地themes文件夹内

1
2
cd themes
git clone https://github.com/minyez/hexo-theme-freemind freemind

下载完成后,修改根目录下_config.yml文件中的theme标签以启用Freemind

1
theme: freemind

若对其他主题感兴趣,可自行google并通过类似的方法架设。此时重新生成并访问,可以发现博客已经从Landscape变为Freemind主题。

开始写作: 从模板新建

在基本设置完成以后,我们就可以开始写作博客了。通过Hexo内建指令new创建新的博文

1
hexo new post pname

这会在source/_posts下创建Markdown文件pname.md和文件夹pname,后者用于存放md内引用的图片或代码文件。新建文件名的默认格式可通过修改_config.yml中的new_post_name来调整,例如

1
new_post_name: :year-:month-:day-:title.md # yyyy-mm-dd-pname

此时按上面指令新建pname将得到2018-02-21-pname.md和文件夹2018-02-21-pname。如果文章本身未成型,想先写一个草稿,用

1
hexo new draft dname

会在source/_draft下创建dname.md文件和dname文件夹。草稿写作完成后可用命令

1
hexo publish dname

发布,此时Hexo会将dname.mddname按照new_post_name的格式重命名后,移动到source/_post文件夹下,不需要自己手动改名。

Hexo写作

Hexo博客正文写作基于Markdown语法,网络上已经有非常多的教程和帮助文档,例如我现在在Dash中使用的cheat sheet。对于Hexo比较特别的是,为了识别博文的基本信息,我们需要一个front matter。另外,除了基本Markdown语法以外,我们还可以使用开源作者编写的Hexo渲染器及主题允许的各种特性,来丰富我们的写作手段。

Front matter

对任一篇Hexo博文,文件夹非必须,但一定会有对应的.md文件。Hexo要求博文的.md文件开头需要有一个YAML格式的front matter。根据该front matter,Hexo可识别博文的标题、创建日期、标签、分类等各种特征以及需要用到的渲染器。Front matter的基本格式为

1
2
3
4
5
6
---
title: pname # 标题
date: 2018-02-21 16:58:25 # 创建时间
tags: # 标签. 不止一个时写成[tag1, tag2]格式
categories: # 分类
---

利用hexo new post产生的博文,front matter会套用scaffold中的post.md,相当于post的初始化模板

1
2
3
4
5
---
title: {{ title }}
date: {{ date }}
tags:
---

可根据自己需要修改模板,如增加目录toc、归类categories以及首页图片feature。当存在与md文件名一致的文件夹时,md中图片和代码引用会在该文件夹中搜索,只需要把欲引用的图片代码放入文件夹,将引用路径设为文件名即可。

基于MathJax的数学公式插入

由于专业原因,可以预想到很多时候需要插入大量的公式,实现方法是使用浏览器公式引擎MathJax。推荐使用hexo-renderer-mathjax,安装很方便,对_config.yml的改动量也很小。通过npm安装

1
npm install hexo-renderer-mathjax --save

安装完就可以正常使用。如果出现无法渲染的情况,在_config.yml中加入:

1
2
Plugins:
- hexo-renderer-mathjax

输入行内公式可使用$math$,例如

1
$P=iGG, G=\frac{1}{\omega - \hat{H}_{\text{KS}}}$

效果:$P=iGG, G=\frac{1}{\omega - \hat{H}_{\text{KS}}}$

输入公式块可使用$$mathblock$$,例如

1
$$ \nabla^2 \phi = -\rho $$

效果:

$$\nabla^2 \phi = -\rho$$

此外还可以使用\begin{equation}\end{equation}来产生带编号的公式,但需要对hexo-renderer-mathjax包的内容进行修改。将node_modules/hexo-renderer-mathjax/mathjax.html中间MathJax.Hub.Config函数改为

1
2
3
4
5
6
7
8
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ["$","$"], ["\\(","\\)"] ],
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
processEscapes: true
},
TeX: {equationNumbers: { autoNumber: "AMS" }}
});

即增加TeX一行(不要忘了前面的逗号,)。

1
2
3
4
5
6
$$\begin{equation}
\begin{aligned}
a=b+&c \\
&+e+f
\end{aligned}
\end{equation}\label{eq1}$$

效果:
$$\begin{equation}
\begin{aligned}
a=b+&c \\
&+e+f
\end{aligned}
\end{equation}\label{eq1}$$

还可以用$\eqref{eq1}$来引用公式$\eqref{eq1}$。上面equation例子还需要注意的是,默认的Markdown渲染器会将两个斜线\\渲染为\,从而导致无法转行。这里根据网络上的办法,修改node_modules/marked/lib/marked.js,将

1
escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,

改为

1
escape: /^\\([`*\[\]()# +\-.!_>])/,

移除marked对花括号和反斜线的渲染。如果出现下划线渲染问题,再将em:一行从

1
em: /^_([^\s_](?:[^_]|__)+?[^\s_])_\b|^\*((?:\*\*|[^*])+?)\*(?!\*)/

改为

1
em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,

以移除对下划线_的渲染. 看一下结果

Markdown 类型 渲染结果
$a_b$ 公式 $a_b$
$a^*$ 公式 $a^*$
$a^* b^*$ 公式 $a^ b^$
$a^\ast b^\ast$ 公式 $a^\ast b^\ast$
*em* 强调文本 em
_em_ 强调文本 _em_

可以看到, 当公式里同时出现两个星号时, 公式将无法正常渲染. 一种解决方案是用\ast代替*.

由于Mathjax的CDN在17年中退役, 修改mathjax.html中CDN脚本一行

1
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>

链接自己博客内的文章

1
{% post_link md-filename-wo-extension %}

1
{% post_link compile_VASP_on_macOS %}
解决macOS上编译VASP时遇到的libparser.a未定义符号问题
1
{% post_link f2py-1 %}
Python笔记(一)——利用F2PY调用Fortran函数或子程序

图片说明

1
npm install --save hexo-image-caption

_config.yml中加入

1
2
3
image_caption:
enable: true
class_name:

并按照这一条PR修改node_modules/hexo-image-caption/index.js.

流程图

安装hexo-filter-flowchart

1
npm install --save hexo-filter-flowchart

直接使用即可. 具体语法参考flowchart.js官网

对于比较长的流程, 需要在_config.yml

Freemind特性

首页摘要

在要作为摘要的文字后面加上<!--more-->,首页将只显示<!--more-->前面的内容,同时出现”Read More”的按钮。摘要内容仍然会在正文中显示。

标签插件

使用标签插件(Tag plugins)可以使得文章的可读性更好。在这里我参考了wxpan提供的样例总结一些tag plugins用法,包括一般Hexo和Bootstrap的tag plugins。在使用插件前,需要先安装Bootstrap

1
npm install hexo-tag-bootstrap --save

标签(label)

1
2
3
4
5
6
{% label default %}
{% label warn warning %}
{% label succ success %}
{% label danger danger %}
{% label prim primary %}
{% label info info %}

效果是插入一个醒目的颜色小标签
default warn succ danger prim info

警报(alert)

1
2
3
4
{% alert warning %} 这是一个警告类型的警报 {% endalert %}
{% alert danger %} 这是一个危险类型的警报 {% endalert %}
{% alert success %} 这是一个成功类型的警报 {% endalert %}
{% alert info %} 这是一个信息类型的警报 {% endalert %}

效果是插入一个带特定背景色的文字块,左上方含有标识文本性质的符号。

这是一个警告类型的警报

这是一个危险类型的警报

这是一个成功类型的警报

这是一个信息类型的警报

徽章(badge)

1
{% badge 徽章测试 %}

效果是徽章测试

Freemind调教

若非特别指出,所有的关于Freemind的调教都是在themes/freemind文件夹内,不要与Hexo根目录混淆。

网站图标

Hexo会在根目录下source/assets/images/favicon/内寻找图片作为网站图标。另一种方法是在_config.yml内通过编辑favicon标签显示指定

网站图标设定功能在layout/_partial/head.ejs中定义

1
2
3
<% if (theme.favicon){ %>
<link href="<%- config.root %>assets/images/favicon/icon.png" rel="icon">
<% } %>

_config.yml中设置

1
favicon: True

然后将命名为icon.png的网站图标图片放入Hexo根目录下的source/assets/images/favicon下即可。也可以修改href属性,换成自己想要的路径。

Wiki型浮窗式的脚注

npm安装hexo-reference

1
npm install hexo-refernce --save

在Hexo根目录_config.yml中启用插件

1
2
Plugins:
hexo-reference

为了跟网页主体风格相一致, 稍微修改了一下其中的源码(hint.min.css)以调整浮窗文字的背景颜色, 置于主题CSS文件夹下

1
sed 's/b34e4d/1863a1/g' node_modules/hexo-reference/src/hint.min.css > themes/freemind/source/css/hint.min.css

同时修改index.js, 将href的CDN地址改为本地地址

1
2
3
cd node_modules/hexo-reference/
mv index.js index.js_bak # back up original file
sed 's/https:\/\/cdn.jsdelivr.net\/hint.css\/2.4.1\//\/css\//g' index.js_bak > index.js

测试一下效果.[1]

边栏链接及链接图标

_config.yml内编辑links标签,每一条短线对应一个链接条目

1
2
3
4
links:
- title: "Github-minyez"
url: https://github.com/minyez
icon: "fa fa-github"

其中icon对应链接旁显示的图标。本示例使用了Font Awesome提供的图标,该项目提供的全部图标可以在这里找到。

谷歌统计GA

使用谷歌账号登录谷歌统计, 在管理标签中找到用户管理。在媒体资源设置中找到自己的跟踪ID,并设置默认跟踪网址, 然后在跟踪信息-跟踪代码中,将全局网站代码粘贴到layout/_partial/after_foot.ejs底部, 并把明文的GA ID改成<%= theme.google_analytics.siteid %>.

跟踪代码块截图
跟踪代码块截图

在GA主页上, 可以通过”管理-过滤器-添加过滤条件”来排除来自特定IP的流量. GA通过浏览器工作, 而浏览器不会读取MAC地址, 因此无法通过检测MAC地址的方式排除特定设备的流量.

不蒜子站点和页面统计

不蒜子整合到Freemind中, 以支持站点访客数统计和页面访问量统计. (GA也可以完成, 但没精力读API了…) 在_config.yml中加入

1
2
3
4
5
busuanzi:
# number of page views from busuanzi
pageview: true
# number of total visitors from busuanzi
visitor: true

以提供一致的开关. 在layout/_partial/post/analytics.ejs中引入js

1
2
3
4
<% if (theme.busuanzi.pageview || theme.busuanzi.visitor){ %>
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js">
</script>
<% } %>

然后在layout/_partial/footer.ejs中加入总访客数标记

1
2
3
<% if (theme.busuanzi.visitor) { %>
| <span id="busuanzi_container_site_uv"><span id="busuanzi_value_site_uv"></span> visitors</span>
<% } %>

layout/_partial/post/meta.ejs中加入页面总访问数

1
2
3
4
5
6
7
8
9
<!-- page view by busuanzi -->
<% if (theme.busuanzi.pageview) { %>
<div class="meta-widget">
<span id="busuanzi_container_page_pv">
<i class="fa fa-eye"></i>
<span id="busuanzi_value_page_pv"></span> views
</span>
</div>
<% } %>

页面每被点击一次, 总访问数就加一.

全站字数统计

使用hexo-wordcount. 类似不蒜子, 在layout/_partial/footer.ejs加入

1
2
3
<% if (theme.wordcount.site) { %>
| <span class="post-count"><%= totalcount(site) %></span> words
<% } %>

在YAML中开启

1
2
wordcount:
site: true

修改页尾标记

layout/_partial/footer.ejs中修改.

配色修改

由于个人偏好蓝色和深绿色,需要简单修改一下博文大小标题和行间代码的配色。在source/css/highlight.css中修改行间代码的CSS样式

1
2
3
4
5
6
7
8
9
10
11
12
code {
background: #eee;
border: 1px solid #d6d6d6;
padding: 0 5px;
margin: 0 2px;
font-size: 90%;
/*text-shadow: 0 1px #fff; */ /*删去白色阴影*/
word-break: break-all;
word-wrap: break-word;
white-space: normal;
color: #458B00; /* 翠绿 */
}

source/css/style.css中修改文章中大小标题的样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
h2{
margin: 0.83em 0;
color: #104E8B; /* 二级标题藏青 */
/* color: green; */
padding-top: 40px;
margin-top: -25px;
}

h3 {
/* color: #9C4C17; */
color: #1E90FF; /* 三级标题湖蓝 */
}

h4 {
/* color: #B94A48; */
color: #CC0033; /* 四级标题红色以防标题层级过低看不到 */
}

文字两端对齐

source/css/style.css中加入

1
2
3
p {
text-align: justify
}

DISQUS评论

注册DISQUS账号,选择”I want to install disqus on my site”,使用universal code安装,将这部分代码拷贝到layout/_partial/post/comment.ejs中。接下来配置Disqus,主要是Website NameWebsite URL,前者我设置为我的shigaro。然后在Hexo根目录_config.yml下加入

1
2
# comment
disqus_shortname: shigaro

三线表

source/css/style.css中加入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* 居中三线表 */
:not(figure)>table {
border-top: 2px solid #4088b8;
border-bottom: 2px solid #4088b8;
margin: 1.5em auto 1.5em auto;
}

th {
padding: 12px 10px 12px 10px;
border-bottom: 2px solid #4088b8;
}

/* 非代码块table元素, 悬停表格主体行时灰色高量 */
:not(figure)>table>tbody>tr:hover {
background-color: #D9D9D9;
}

背景图片

layout/layout.ejs中, 修改body标签, 增加一段ejs

1
<body <%- partial('_partial/background') %>>

新建layout/_partial/background.ejs

1
2
3
<% if(theme.background) { %>
style="background:url(<%- config.root %>assets/images/<%- theme.background %>);" class="body-img-background"
<% } %>

body-img-background类的样式由source/css/style.css控制

1
2
3
4
5
6
7
8
9
10
11
/* fixed image background by minyez*/
body.body-img-background {
background-repeat: no-repeat;
background-attachment: fixed;
background-position:50% 50%;
background-size: cover;
-webkit-background-size: cover;
-o-background-size: cover;
-moz-background-size: cover;
-ms-background-size: cover;
}

然后在_config.yml中加入

1
background: background.png

再把想作为背景的图片background.png放到Hexo根目录source/assets/images/下面就可以了. 目前样式参考了这条链接.

TODO

  • Bugfix: 点击Software的category徽章后显示的文章不全. 启用根目录下category_generator并将per_page设为0即可解决.
  • 代码块复制功能.
  • Quotes页面, 存储一些摘句, 同时有一个即时搜索引擎.
  • 文章中侧边栏随正文一同滚动. 对于TOC较长的情形, 鼠标移动到侧边栏上对TOC滚动浏览.

总结

笔者基于Hexo框架和Freemind主题搭建了个人博客,根据自己的需求进行了自定义,并利用MathJax渲染器和Bootstrap特性进行了Markdown写作。

参考

LaTeX Equation Numbering Done Right in Hexo
另一个渲染器hexo-math及一个讨论其用法的Issue
如何在自己的主题下实现MathJax支持:在Hexo中渲染MathJax数学公式
代码块复制:HEXO优化之(二)—-添加复制功能
Hexo 添加背景图片并自适应

更新

2019-05-07

  1. 增加基于hexo-reference的wiki浮窗式的脚注.
  2. MathJax: 比较各种情况下*_的渲染结果. 更改CDN.

2019-05-10

  1. 增加对不蒜子统计的支持.
  2. 去掉了Archives不必要的下拉菜单, 直接进入archives页面.

2019-05-22

  1. 增加背景图片, 位置由YAML中background变量指定.

2019-05-25

  1. 利用hexo-wordcount进行全站和页面字数统计

    1. 1.这是一个脚注测试

Comments