文章目录
  1. 1. 1 frontmatter不一致
  2. 2. 2 使用mathjax支持数学公式
  3. 3. 3 php markdown中脚注的支持
  4. 4. 4 pacman系列主题中的代码内空行bug
  5. 5. 5 代码高亮的着色方案改为monokai
  6. 6. 6 tinny主题的字体修改
  7. 7. 7 主题的顶部横幅(header)宽度调整
  8. 8. 8 仍然存在的bug

这个博客是用hexo搭建的,放在github上,这篇文章记录一下搭建这个博客的过程,以及这个过程中踩过的坑。

如果只是想搭建一个普通的博客,不需要额外的,比如数学公式、脚注等支持,也不在意代码的排版和主题的选择,那么网上能找到的多数文章都可以用作参考,比如123,其中也介绍了一些额外的配置,比如rss、域名绑定、博客迁移等等。我建博客的主要步骤也是跟这几篇博客的描述基本类似,由于原先的博客是放在farbox和SAE的JustWriting(以下简称JustWriting)上,直接就是可用的markdown文本,迁移的步骤算是省了不少功夫,以下说一些碰到的坑。

1 frontmatter不一致

frontmatter不是markdown的标准,应该属于博客系统自定义的扩展,一般是用于表示该篇文章的属性信息,写在文章的开头,例如,本文的frontmatter就是,

1
2
3
4
5
6
title: 用hexo搭建这个博客
date: 2014-12-08 12:49
tags: [Hexo, Blog]
category: Blog
toc: yes
---

各个博客系统支持的frontmatter各不相同,原先在farbox和JustWriting写的时候,是可以这么写的,

1
2
3
4
5
Title: 用hexo搭建这个博客
Date: 2014-12-08 12:49
Tags: [Hexo, Blog]
Category: Blog
Toc: yes

主要差别有,frontmatter中的title、date什么的都是可以首字母大写的,例如,Title、Date,但是hexo要求必须是全部小写才可以识别,所以就一篇一篇的都改为小写。JustWriting是大小写都可以支持,farbox由于不打算继续用了就没有测试过。

还有一个是tags里面的写法,hexo要求,如果有多个的话,需要放在方括号([]),并用逗号(,)分隔,如[Hexo, Blog],而之前farbox和JustWriting是可以不需要方括号,空格分隔,如Hexo Blog。JustWriting经测试是可以支持方括号的写法,farbox没有测试。

最后的差别是,hexo需要在frontmatter结束后,用---隔开,而JustWriting和farbox不需要。

改完这些,hexo中就可以在主页正常的显示博文的标题等信息了。感觉起来,hexo要求的写法更加严谨,值得称道的是JustWriting,不仅支持了原先farbox的写法,也支持现在的hexo写法,更加宽泛。虽然这些改动在farbox上都没有测试过,我猜应该也是可以的,JustWriting和farbox非常相似,JustWriting是用php写的,猜测farbox可能也是用php实现的,两者支持的markdown语法应该是一致的。

2 使用mathjax支持数学公式

公式的支持可以安装hexo-math和hexo-renderer-mathjax来实现,好像是只要安装前者就可以实现了,但是我安装了2个。hexo-math的安装方法可以去该项目的github上去看看,在这里,按照步骤操作就可以了。hexo-renderer-mathjax的github在这里,步骤和前者一样。

安装完之后应该就能看到公式了,支持行间和行内的公式。测试一下效果,代码如下,

1
2
3
4
5
测试一下数学公式和尾注[^LaTeX]:
$$E=mc^2$$
[^LaTeX]: 支持 **LaTeX** 编辑显示支持,例如:$\sum_{i=1}^n a_i=0$和$[((n-k)/i+m)]$, 访问 [MathJax][4] 参考更多使用方法。

生成的效果可以看这里

3 php markdown中脚注的支持

老实说,之前我从来没有关注过markdown的方言,markdown就是markdown,就跟java就是java的感觉一样。后来知道了有个GFW(Github Flavored Markdown),感觉它支持代码高亮的方式好一些,于是以为自己写的就是GFW。直到这次做博客迁移的时候才发现,原来我一直写的都是php markdown,比GFW还多一些特性。而hexo默认支持的是GFW,对php markdown的一些特性不支持,而我最需要的就是php markdown中的脚注功能。

其实主流的markdown方言有以下几种,分别是(摘自pandoc的readme):markdown (pandoc’s extended markdown), markdown_strict (original unextended markdown), markdown_phpextra (PHP Markdown Extra extended markdown), markdown_github (github extended markdown),markdown_mmd (MultiMarkdown)。这也看出,原始的markdown支持的写法是很少的,所以才有了这么多各有特色的方言版本,github markdown支持多种编程语言的高亮,pandoc markdown支持的东西很多,写法比较类似tex,我用的php markdown有简易的脚注功能。以上的特性,都可以在pandoc中有选项可以支持。

说了这么多,那么问题来了,pandoc是什么?在我的理解,pandoc是一个标记语言(也可以说排版语言)转换器。可以将一种标记语言(如markdown、textile、tex、latex、html、epub等)转换到另一种标记语言,感觉很强大有木有?我就是想用pandoc对php markdown的支持来生成博客的html页面。

问题又来了,那么如何在hexo中使用pandoc来解析php markdown呢?要使用hexo-renderer-pandoc插件,项目主页在github上,这里。其readme中的介绍有些太简略了,对于我这样一个连pandoc都没听过的人,实在不太容易上手。我详细说一下使用时候的步骤,

  1. 根据pandoc的安装文档,安装pandoc,在windows下要把pandoc配到PATH环境变量下;
  2. 安装这个插件,npm install hexo-renderer-pandoc --save
  3. 删除默认的markdown插件,npm uninstall hexo-renderer-marked --save,确保是使用pandoc在解析;
  4. 修改该插件的代码,将index.js中的var args = [ '-f', 'markdown', '-t', 'html', '--mathjax', '--smart'];改为var args = [ '-f', 'markdown_phpextra', '-t', 'html', '--mathjax', '--smart'];

之后就可以用pandoc解析php markdown了,在hexo generate的时候表现的灰常好。

说一下需要特别注意的坑,如果是在windows下安装pandoc,一定需要把pandoc的可执行文件目录配置到PATH环境变量中,即,C:\Users\Administrator\AppData\Local\Pandoc(pandoc的默认安装目录)需要加到PATH中,这个坑在pandoc的官方installing中完全没提到,而在我的mint linux中只需要简单的apt-get就一次搞定,差距啊。如果没有配对的话,在hexo server的时候会出现这个错误,

1
2
3
4
5
6
7
8
9
10
11
Error: This socket is closed.
at Socket._write (net.js:637:19)
at doWrite (_stream_writable.js:226:10)
at writeOrBuffer (_stream_writable.js:216:5)
at Socket.Writable.write (_stream_writable.js:183:11)
at Socket.write (net.js:615:40)
at pandoc (E:\my_blog\node_modules\hexo-renderer-pandoc\index.js:23:15)
at C:\Users\Administrator\AppData\Roaming\npm\node_modules\hexo\lib\core\render.js:96:9
at fn (C:\Users\Administrator\AppData\Roaming\npm\node_modules\hexo\node_modules\async\lib\async.js:641:34)
at Object._onImmediate (C:\Users\Administrator\AppData\Roaming\npm\node_modules\hexo\node_modules\async\lib\async.js:557:34)
at processImmediate [as _immediateCallback] (timers.js:330:15)

模模糊糊的,也算指向了找不到pandoc的错误。测试pandoc是否在PATH中了,可以用pandoc -v来查看版本,如果已经设置对了,会看到以下这些,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
F:\>pandoc -v
pandoc 1.13.1
Compiled with texmath 0.8, highlighting-kate 0.5.8.5.
Syntax highlighting is supported for the following languages:
actionscript, ada, apache, asn1, asp, awk, bash, bibtex, boo, c, changelog,
clojure, cmake, coffee, coldfusion, commonlisp, cpp, cs, css, curry, d,
diff, djangotemplate, doxygen, doxygenlua, dtd, eiffel, email, erlang,
fortran, fsharp, gcc, gnuassembler, go, haskell, haxe, html, ini, isocpp,
java, javadoc, javascript, json, jsp, julia, latex, lex, literatecurry,
literatehaskell, lua, makefile, mandoc, markdown, matlab, maxima, metafont,
mips, modelines, modula2, modula3, monobasic, nasm, noweb, objectivec,
objectivecpp, ocaml, octave, pascal, perl, php, pike, postscript, prolog,
pure, python, r, relaxngcompact, restructuredtext, rhtml, roff, ruby, rust,
scala, scheme, sci, sed, sgml, sql, sqlmysql, sqlpostgresql, tcl, texinfo,
verilog, vhdl, xml, xorg, xslt, xul, yacc, yaml
Default user data directory: C:\Users\Administrator\AppData\Roaming\pandoc
Copyright (C) 2006-2014 John MacFarlane
Web: http://johnmacfarlane.net/pandoc
This is free software; see the source for copying conditions.
There is no warranty, not even for merchantability or fitness
for a particular purpose.

另一个坑是,hexo-renderer-pandoc插件的作者使用的是pandoc markdown,所以默认是只支持pandoc markdown,修改代码之后才可以识别php markdown的脚注,像这样[^1],示例可以参考前面的例子。

顺便说一下,hexo-renderer-pandoc插件代码的逻辑还是很清楚的(也很短),主要就几个部分,打开文件,处理文件,关闭文件,还有按文件扩展名注册文件的代码放在最后。修改的地方就是pandoc运行时候的参数,参考pandoc的User Guide就可以知道这些参数是干什么的,甚至可以通过修改参数获得更多文件的支持。var pandoc = spawn('pandoc', args);这一行是pandoc运行的命令,可以看到pandoc前面没有任何路径信息,所以要放到PATH环境变量中。

4 pacman系列主题中的代码内空行bug

hexo的主题主要有几个系列,从官方主题更改的landscape系列、light系列,还有开发者自己贡献的pacman系列,我自己比较偏好pacman和landscape系列的主题,pacman中比较喜欢icemantinny,landscape系列中比较喜欢landscape-plusmoyi,还有很多漂亮的主题,虽然有demo,但是我使用的时候都报错。最后还是选取了tinny,其实我更加喜欢landscape系列主题,但是其文章是默认在首页中显示全文的,需要手动加入<!-- more -->才能生成首页预览的效果,我比较懒,不想加了,因此选择了pacman系列的。

pacman系列主题有一个共有的问题,代码中的空行会被压缩,而landscape系列主题就没有这个问题。干说不是很好理解,看例子,比如这样一段markdown,

1
2
3
4
5
```python
import this
print 'something'
```

中间有一个空行,pacman主题默认情况下会压缩掉这个空行,生成类似这样的页面,

中间的空行不见了,而且代码行数的数字和代码的内容视觉上也没有在同一行上,而实际上,我们想要的是应该是这样的结果

1
2
3
import this
print 'something'

几乎所有,至少是我尝试过的所有的,pacman主题都有这个问题,解决方法是,在主题的source/css/_base/code.styl文件中.gist之前,加入下面两行,

1
2
3
4
5
6
7
8
9
10
11
12
.gutter pre
@extend $line-numbers
text-align right
padding-right 1.5em
// add follows
.line
height: 24px
.gist
margin 0.5em 0
background highlight-background

加入.line设置,强制指定了代码的每一行的行高都是24px,我尝试了其他的变量来替代,都不是很好,如果有更好的改法,可以联系我。这是整个格式优化中我花时间最长的一个改动,尤其对于我这种从来没做过前端,而且css、js又都不太懂的人。

5 代码高亮的着色方案改为monokai

代码高亮的着色方案在多数的hexo主题中,都是tomorrow着色,我是monokai着色的忠实粉丝,有木有办法改为monokai呢?

landscape-plus给出了一个monokai着色的方法,原来主题的颜色都是在code.styl中写死的,只要改这段即可。原本的着色方案可能是这样,

1
2
3
4
5
6
7
8
9
10
11
12
13
highlight-background = #1d1f21
highlight-current-line = #282a2e
highlight-line-numbers = #666
highlight-selection = #373b41
highlight-foreground = #c5c8c6
highlight-comment = #969896
highlight-red = #cc6666
highlight-orange = #de935f
highlight-yellow = #f0c674
highlight-green = #b5bd68
highlight-aqua = #8abeb7
highlight-blue = #81a2be
highlight-purple = #b294bb

可以看到,颜色的rgb值都被赋值在了一系列变量中,只要修改这些常数值即可,这个活儿landscape-plus已经做了,把他们的code.styl中的这一段copy过来替换原有的即可,新的着色方案是这样,

1
2
3
4
5
6
7
8
9
10
11
12
highlight-background = #272822
highlight-current-line = #3E3D32
highlight-selection = #49483E
highlight-foreground = #F8F8F2
highlight-comment = #75715E
highlight-red = #F92672
highlight-orange = #FD971F
highlight-yellow = #E6DB74
highlight-green = #A6E22E
highlight-aqua = #A1EFE4
highlight-blue = #66D9EF
highlight-purple = #AE81FF

code.styl的末尾pre那一行到结束,还有一段不同的代码引用那一种着色方案的声明,同样也用landscape-plus中的相应内容替换。替换完之后,就能发现hexo已经开始用monokai着色了。

可以看出来,这种着色方案的修改方法比较死板,如果你需要某种着色方案但并不清楚颜色的rgb值,就无解了。其实,tinny主题本身其实提供了highlightjs着色方案,按主题的readme上所说,只要在主题的_config.yml中更改配置项即可,可惜我没有试成功……可能有其他主题可以做到。

6 tinny主题的字体修改

tinny主题的作者把pacman的一些字体给改了,用了更小更紧凑的一些字体。但是我还是喜欢原先的pacman的字体,怎么办呢?通过和iceman对比文件发现,source/css/_partial/目录下的article.styl的内容有差异,用iceman的这个文件替代;还有,tinny在该目录下多了一个addByMe.styl文件,为了和iceman一致,删除之。

改完之后,基本和iceman比较相似了,感觉字体还是比较小,不知道为什么。

7 主题的顶部横幅(header)宽度调整

改完这些之后,设置自己的博客名、作者名、想说的话等等,基本已经挺好的了,还有不足的就是博客的顶部横幅,是这样,

感觉明明可以一行显示的内容,被强迫分在了两行中显示,左上角和右下角的内容如果可以合并在一行里面显示就比较好了。如果需要这样,可以调整做上角的文本的宽度,在source/css/_partial/目录下的header.styl中,大约30多行的位置,有这样一段,

1
2
3
4
#textlogo
float left
margin-left 0.5em
width 65%

可能表示左上角的文本宽度要占用整个横幅的65%,像我的博客,左上角的文本并不长,缩短这个宽度也是可以的,改为55%就变成现在这样的效果。

8 仍然存在的bug

我做的主要修改就是以上这些,如果说还有一些值得进一步折腾的话,还可以继续。比如,在顶部的横幅中,目前没有支持categories,但是tags是支持的,如果要设置categories,可以按主题中的说明,在categories目录中建立一个index.md的文件,内容是,

1
2
3
layout: categories
title: categories
---

但是,我这样操作了,但是网页的内容还是tags的,所以我把categories从顶部横幅中去掉了。还有一个问题是,代码中的区块注释没有显示对颜色,但是单行注释是没有问题的。错误的颜色如下,

第一行显示对了颜色,为灰色,但是第二行一直到最后一行都是白色,颜色错误。除此之外,也有整个注释区块都是白色的错误情况,至今没有找到很好的解决办法,试了一些别的主题,多数都有这个问题,只有一些个别的主题,似乎是用动态调用highlightjs的方法解决了这个问题,但是其主题的代码结构和普通的差异很大,不太会改。

以上是我折腾这个博客的过程,到此为止,已经花了两个周末多了,不能再往下花时间了。基本上,如果使用pandoc,hexo可以变的非常灵活,任何的markdown方言都不在话下。

感谢文中所有提到的开源项目的贡献者。

文章目录
  1. 1. 1 frontmatter不一致
  2. 2. 2 使用mathjax支持数学公式
  3. 3. 3 php markdown中脚注的支持
  4. 4. 4 pacman系列主题中的代码内空行bug
  5. 5. 5 代码高亮的着色方案改为monokai
  6. 6. 6 tinny主题的字体修改
  7. 7. 7 主题的顶部横幅(header)宽度调整
  8. 8. 8 仍然存在的bug

欢迎来到Valleylord的博客!

本博的文章尽量原创。