- 引言
- 公式显示
- 图片显示
- 置顶功能
- 添加存档页
- 站内搜索功能
- rss and sitemap
- google analytics and search console
- 字体
- 代码显示
- 表格样式
- 其他插件
- future post
- Reference
引言
忙里偷闲,折腾了一下现在用的 Jekyll 模板,添加了一些小功能,我本来使用的模板是基于 Moon 这个主题,不过自从 github page 搭上以来,也很少去动它,这次主要是有一个解决公式显示问题的契机,顺道就把整个 Jekyll 的运行和各部分的功能与分工了解了下,并且对博客做了些改进。本文就是关于 Jekyll 博客系统一些改进的记录和备忘。
公式显示
多行公式的显示问题是这次折腾的开始。我遇到的问题是 latex 多行公式环境 {align}
在最后渲染的网页无法正常的显示出来。但在网页查看 html 源码时,发现是有对应的公式部分的,只不过公式前后出现了 % <![CDATA[
和 %]]
。由于 Jekyll 使用的是 kramdown 作为 markdown 转 html 引擎,我开始怀疑这是 kramdown 的锅。结果使用 kramdown 直接生成 html 可以正常的显示多行公式,html 中也有对应的 CDATA
部分。调试好久,才发现问题在于,Jekyll 生成的 html 中 % <![CDATA[
之后没有换行!如果这里有换行,对应的 mathjax 就可以正常渲染了。进一步排查,发现 Moon 主题默认使用了Jekyll-compress-html 这一插件,这一插件只需在 _layout
中添加 compress.html
并且在其他 html 文件开头添加以下 header 即可使用。
------------
layout:compress
------------
由于该插件不需在 _config.yml
的 gems
中声明,所以比较隐蔽,但其效果可破坏性很强。其会默认把所有的换行都压缩成一行。因为毕竟大部分 html 语法都不依赖换行。但万一哪个倒霉的 feature 依赖换行,就被坑了。Mathjax 成功渲染公式强烈依赖于 CDATA
之后的换行就是一个例子。本来我打算把这个插件去了就算了,结果发现了以下更好的解决方案。
通过查阅 compress html 插件的文档,最简单的做法就是在 _config.yml
中设置 compress 的行为,具体的我们这里只需添加以下内容即可。
compress_html:
blanklines: true
这样一个选项设置,就会使该插件不在将多行 html 源码合并,而只是删去空行。这样多行 latex 公式就可以在最后生成的网页中正常的被 Mathjax 渲染和显示了。
顺便我又打开了 mathjax 支持的公式自动编号功能,可以参考相关文档。
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
TeX: { equationNumbers: { autoNumber: "all" } }
});
</script>
其中的 autoNumber
有两个模式。all
对应了所有 display 格式的公式都进行编号,而 AMS
则完全按照 latex 标准来,只对额外声明环境的公式标号,比如 begin{equation}
这种。当然你总是可以通过 \notag
命令来取消指定公式的编号,或者用 \tag{}
额外改变指定公式的编号。此外在 \label{}
之后, mathjax 还支持全文的 \eqref{}
来引用,可以说相当强大了。
图片显示
这是一个 Moon 模板特有的需要修改的地方。由于原模板把图片的缩放等信息写死在了外部的 css 里,因此 markdown 中插入图片后,即使直接使用 html 的 <img>
标签进行缩放比例设置也无济于事--图总是占据整个宽度。但我并不希望所有图片总是铺满全屏那么大,怪傻的。要修改这一 feature,只需将 _sass/elements.sass
中 img 的属性表里的
width: auto;
height: auto;
这两行去掉。之后就可以愉快的调整博客中的图片大小和比例了。
此外,再提一句关于图片的标题的实现,可以参考这个回答。具体的,我们利用了 css 的 + 选择器,来选择和 img 相邻的 em 标签。这样 markdown 中图片语法紧邻的斜体句,就可以单独的被 css 定义成居中,从而实现标题效果。当然也可以直接通过 html 的 figure 和 figurecaption 标签来实现图片标题。
置顶功能
另一个需求是想实现一个置顶博客的功能。因为 Moon 这个模板没用分页(不是不能加分页,而是我很喜欢这种不分页流水般的整体感),所以我希望可以置顶一个导航贴。这点可以利用 liquid 的 if statement 在 _layouts/post-list.html
实现。具体的,在 Moon 模板的修改体现为以下内容。
<!-- 置顶博客显示部分 -->
{% for post in site.posts %}
{% if post.top == true %}
<ul>
<li class="wow fadeInLeft" data-wow-duration="1.5s">
<a class="zoombtn" href="{{ site.url }}{{ post.url }}">{{ post.title }}</a>
<p>{{ post.excerpt }}</p>
<a href="{{ site.url }}{{ post.url }}" class="btn zoombtn">Read More</a>
</li>
</ul>
{% endif %}
{% endfor %}
<!-- 其他博客显示部分 -->
{% for post in site.posts %}
{% if post.project == null %}
{% if post.top == null %}
<ul>
<li class="wow fadeInLeft" data-wow-duration="1.5s">
<a class="zoombtn" href="{{ site.url }}{{ post.url }}">{{ post.title }}</a>
<p>{{ post.excerpt }}</p>
<a href="{{ site.url }}{{ post.url }}" class="btn zoombtn">Read More</a>
</li>
</ul>
{% endif %}
{% endif %}
{% endfor %}
这样做之后,对于想要置顶的博客,只需在对应的 md 文件的头信息中添加一条 top:true
即可。
添加存档页
原来的 moon 模版只有基于标签的存档页,而没有基于发布时间的存档页。这样的页面,基于 liquid 的语法很容易构建。唯一需要注意的就是 liquid 模版中对于日期的处理。无论是在模版变量双花括号还是模板控制段百分号加花括号中,都是以 post.date|date: "%b"
的形式来格式化或拿到日期对象的相应属性的。具体存档页面的实现细节可以查看源文件。
站内搜索功能
该功能直接引入利用 google 站内搜索的 form 即可。代码如下:
<form method="GET" action="https://www.google.com/search">
<input type="text" name="as_q" placeholder="Search">
<input type="hidden" name="as_sitesearch" value="http://re-ra.xyz">
</form>
该代码参考了 [1]。进一步的我又将搜索框的代码改成了支持 css :hover
动作的动态型的。但这又涉及到了 ios 对 :hover
支持的坑爹之处,具体细节可以查看 stackoverflow 上的讨论和解决方案,我现在暂时用了添加空白的 onclick=""
属性的方案。这篇博客给出了几种点击态效果的兼容性,包括 focus
,hover
和 active
移动端支持坑很多。
rss and sitemap
这两部分 Moon 模板已经整合好了,只是我以前一直没注意,分别对应文件 /feed.xml
和 /sitemap.xml
,实现这两者的插件分别是 jekyll-feed 和 jekyll-sitemap。两者的配置都不难,可以参考其官方 repo。对于 rss 文件,还可以在导航栏上添加对应的 rss 订阅链接。在 moon 模板中,导航栏是又独立出来的 _data
文件夹中的配置控制的,因此非常容易调整。关于 _data
文件夹在 Jekyll 中的作用,可以参考官方文档。
google analytics and search console
GA 我倒是早就开了,因为 Moon 主题都已经集成好了,把对应 GA id 填入 _config.yml
的 analytics
即可。不过最近我才发现 search console 虽然和 GA 的统计功能有所重合,但是还是有很大区别,比如可以直接提交 sitemap,更多的关注内外链和搜索等。而且如果网站本来就配置好了 GA 的话,开启 search console 只需在 google search console 官网直接添加自己网站的网址即可,都不需要任何认证,因为 google 会自动发现 GA 关联进行认证。因此还是推荐 google analytics 和 search console 服务都打开,多统计一些信息总没什么坏处,而且还可能有玄学的 SEO 加成。关于 search console 使用的详细介绍及其和 GA 的对比,可以参考 [2]。
字体
要想修改的话,相关内容在 _sass/variables.sass
中的 $font1
。我最后还是用了 Moon 模板自带的,其中没有中文字体,个人还是觉得没特殊展示需求,就依赖各浏览器的默认渲染是最稳妥的,因此最后就没改。确实想改字体的话可以参考 [3],算是现代前端字体的较佳实践了。
代码显示
对于 Moon 模板的代码高亮显示的部分,也一直不太满意。这次直接在 terminal 通过默认 highlighter rouge 的以下命令来导出其他主题的 css 配置。
$ rougify style [stylename] > [output.css]
rouge 自带的 css 模板可以通过以下命令来查看。
$ rougify help style
我选择了 github 主题的 css 来作为该博客的代码高亮主题。当然生成的 css 和原主题对应的 _sass/syntax.scss
还有些许不同。不过我就几乎直接用新的 css 替换了,当然也保留了原 scss 关于 pre 和 highlight class 字体的一些配置。至于是不是落下了什么,就以后走着瞧吧。
最后还需要去 _sass/variables.scss
去修改 $font2
属性,这对应了代码使用的字体,我也选择了 github 方案,也即 "SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;
(字体设置可以直接用网站调试工具查看 github 对应 css style 的 font-family)。这些调整之后,似乎代码高亮部分比以前顺眼了一些。
更多关于代码显示的 css 配置,主要是一些 <pre>
和 <code>
标签的属性配置,包括代码显示的换行与否 white-space
,滚动条添加 overflow
,大小限制 max-weight
等行为,以及 tab 对应的空格数目 tab-size
等,这些设置可以参考 [4]。
表格样式
原来的 Moon 模版似乎也没有 table 的 css 配置,所以表格显示起来也很丑。还是老办法,作为审美不行的人的自我修养,老老实实选取了 github 方案。css 如下,方案来自该 gist。
table {
padding: 0; }
table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
table tr:nth-child(2n) {
background-color: #f8f8f8; }
table tr th {
font-weight: bold;
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px; }
table tr td {
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px; }
table tr th :first-child, table tr td :first-child {
margin-top: 0; }
table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }
表格完成后,还有一个自适应的问题,在移动端窄屏幕上显示时,表格横向往往会溢出,又不好看。刚开始想像 pre 标签一样,在 table 的 css 加上 max-width
限制和 overflow-x:auto
的滚动条完事。结果发现不 work,似乎需要在 table 外层套的 div 上加上相关 css 才行。然而 kramdown 渲染出的 html,表格不默认套一层 div。后来我在 kramdown 的 repo 找到了这个 issue。其中给出了一个解决方案,就是在 md 文件里手动在表格上下加 div 标签,但这里边也有些讲究,格式很重要,不然中间部分的表格会默认为 html 的一部分,从而 kramdown 不再去渲染。具体写法如下:
<div class="table-wrapper" markdown="block">
| some | table | here |
</div>
需要注意这里标签和表格之间要有一行空行才行,此外似乎 markdown="block"
的属性也不能缺。至此,在 css 文件中补上以下内容,表格的移动自适应就大功告成。但要记得每次做大表格时,手动加上前后两行 div。
.table-wrapper {
overflow-x:auto;
}
其他插件
前边的叙述中,我们提到了 jekyll 关于压缩 html,生成 rss 和 sitemap 的插件。Jekyll 的插件自然挺丰富的,不过如果是托管在 github page 的 jekyll,我劝你还是别折腾了。因为 github 只支持7个 jekyll 插件,其他的并不支持,具体 github page 支持的插件可以参考 [5]。
当然另一方面,使用 github 自带的 Jekyll 生成网页只是实现 github page 方式中的一种。你也可以选择本地生成好网站并推送到 github page 对应的 repo,或者利用 Travis 等连续集成服务,推送提交后在 Travis 服务器渲染生成网站并提交回该 repo 的其他分支等。使用以上工作流,则不受 github 默认支持的 Jekyll 插件的限制。
future post
对了,最后提醒一下,如果 post 设定的时间是未来时间,那么 Jekyll 默认生成的网站不包括该篇内容。这是 feature 不是 bug。但又没有办法到指定时间,重新 trigger Jekyll 来定时生成对应内容,这 feature 用途可能也不大。相关讨论可以参考 Jekyll 官方库的这个 issue。
Reference
- 实践:为jekyll构建的博客添加基础功能
- a-beginners-guide-to-the-google-search-console
- 如何优雅的选择字体(font-family)
- 使用 pre 标签的注意事项
- Supporting jekyll plugins on github pages
- Documentation of Jekyll
- 48 个你需要知道的 Jekyll 使用技巧
- Jekyll 使用 rouge 主题
EOF