Jekyll配置个人网站

 

这里记录怎么利用Github Pages以及jekyll构建个人网站。

Jekyll

Jekyll是一个生成静态网站的工具,好像是Github Page的官方工具,用来把markdown文件转换为网页文件。

安装Jekyll

Jekyll是使用编程语言ruby写的,所以首先要安装ruby,同时它的包管理工具gem也会安装上。在MacOS上,安装了命令行工具后这些都自动安装了,但是这个自带的ruby都在系统库,每次安装都要sudo很麻烦,所以还是用brew安装一个:

brew install ruby

然后在.zshrc里改PATH加上路径opt/homebrew/opt/ruby/bin。可以用which ruby检查是是不是brew的ruby。有了ruby后,用以下命令安装Jekyll:

# 你可能需要换源
# gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
gem install jekyll --pre  # 安装最新版
# 在macos上,用brew的ruby安装的,安装路径在opt/homebrew/lib/ruby/gems/3.3.0/bin里,也得改PATH
# 可以通过gem env查看gem会把包安装在哪

然后就可以使用jekyll命令了:

jekyll

我的环境版本:

  • jekyll 4.3.3
  • bundle 2.5.9
  • ruby 3.3.1

准备主题

要写博客,首先要准备一个主题,然后基于这个主题去做个性化的设置。主题可以在jekyllthemes网站上找,然后把对应的github仓库clone到本地。如果要做学术主页,AcademicPages就很好。不过我是想写博客记笔记,所以挑了一个复杂一些的主题。这里建议检查选择主题对公式、代码的支持怎么样,有的主题太简陋了,不支持公式,而且代码的渲染很丑。还要看看对中文的支持怎么样,有的主题英文好看,但是用中文会很丑。

我找了两个对中文、公式、代码支持比较好的主题:chirpyTeXt。最后选择了TeXt。

把github仓库clone到本地后,使用下面的命令安装依赖(会根据当前目录的Gemfile安装):

bundle
# ruby安装依赖是真的慢
# bundle也可以换源
# bundle config mirror.https://rubygems.org https://gems.ruby-china.com

这里可以修改_config.yml里的一些信息,比如替换名字、链接之类的。 最后运行:

bundle exec jekyll serve
# 这个会生成网页,都在_site文件夹里

就会出来一个链接,点这个链接就能看到网页了。到这里说明主题可以成功使用。

把主题发布到github上

接下来要把主题放到github.io上,其实只要把clone的主题push到自己的github.io仓库上就可以了,github会自动编译的(这个过程可能会由于远程的环境和本地环境不同而导致bug,这个就得自己解决了)。

写博客

主要要改的是_config.yaml和_posts里的md文件。

_config.yaml是用来设置的,比如设置博客的标题、自己的邮箱等等,选择主题之类的东西,这个是全局的设置。

写博客只需要在_posts文件夹里加一个markdown文件就可以了,一个markdown对应一篇博客,文件名格式是YYYY-MM-DD-youre-title.md,这个格式是必须的,因为会把它转化为url的一部分。然后运行:

bundle exec jekyll build
# bundle exec jekyll serve会动态检查_post里面的文件修改并编译

就可以把它转换成html文件,生成的文件都在_site文件夹里。

Jekyll markdown

Jekyll的markdown和一般的markdown有一些区别。原因在于Jekyll使用kramdown(一个ruby的库)来把markdown转换成html,这个kramdown本身和markdown语法有点区别(markdown的标准语法这么没牌面吗)。除此之外,Jekyll在markdown的基础上加了liquid这个模板语言,于是转换过程是markdown+liquid → markdown → html。

这里介绍一些比较重要的krmarkdown语法,其余的边用边搜吧:

  • 开头需要加一些属性告诉jekyll:

      ---
      title:  "Post example"
      tag: algorithm
      ---
    

    这个叫YAML Front Matter。

  • 使用markdown的代码块```python会没有语法高亮,原因是liquid导致的,具体原理不清楚。解决办法是开头加上render_with_liquid: false。另外注意要用小写,比如```C++不行,但是```c++可以。

    这个的缺点是没有行号。有点奇怪,我一开始没有高亮,加了这个语句后就有了,但是删了以后还是有。

  • 高亮语句
      重要提示: 重要、紧急、致命提示信息
      {: .success}
    

    这里success可以换成error、warning、info。

  • mathjax的|要用\|才会渲染成|

这里有两个比较完善的教程:

网站原理

liquid是一个模板语言,用来定义html的模板。这些主题用liquid写好了网站长什么样,而写好的markdown博客只是把模板里的变量替换掉,变成html文件。YAML Front Matter或者_config.yml里面的设置是一些变量,比如一个markdown文件对应到liquid模板里是page变量,而_config.yml是site变量,site变量是全局的。

每个页面的变量以及页面之间的继承关系可以看https://kitian616.github.io/jekyll-TeXt-theme/docs/zh/layouts

个性化设置

参考这个主题的官方教程: https://kitian616.github.io/jekyll-TeXt-theme/docs/zh/quick-start

基础改动

  • 导航栏:改_data/navigable.yml

  • 底栏:改_data/local.yml

  • 新增的文件、文件夹都会被编译到_site文件夹里面成为网页的一部分

    • assets也会被放到_site里面,但是以_开头命名的文件不会
    • 分页只能对index.html进行分页
  • 摘要字数设置

    博客列表会显示博客开头的一部分字作为摘要。修改_include/article-list.html里面的第一行设置摘要字数(我把350改成200): html 另一种控制方式是在markdown里面加<!—more—>,它前面的内容会被作为摘要。

添加一键复制代码

参考这里。但是这样做了之后每次添加代码块都要在外面加一层:

<div class="copyable" markdown="1">
</div>

这样太麻烦,我选择用javascript自动给代码块加这个,需要修改的是_includes/scripts/lib/copy-to-clipboard.js里面开头的一段。原本这段代码是:

var snippets = document.querySelectorAll('pre');
[].forEach.call(snippets, function(snippet) {
    if (snippet.closest('.highlight') !== null) {
    	snippet.firstChild.insertAdjacentHTML('beforebegin', '<button class="btn" data-clipboard-snippet><i class="far fa-copy"></i></button>');
    }
});

考虑到代码块对应的html长这样:

<div class="language-sh highlighter-rouge">
    <div class="highlight">
        <pre class="highlight">
            <code>代码</code>
        </pre>
    </div>
</div>

我们需要给pre的父元素添加按钮,并在外层添加带有copyable类的div块,代码需要改成:

var snippets = document.querySelectorAll('pre');
[].forEach.call(snippets, function(snippet) {
    snippet.parentNode.insertAdjacentHTML('beforebegin', '<button class="btn" data-clipboard-snippet><i class="far fa-copy"></i></button>');
    snippet.style.overflow = 'scroll';  // 让代码块有滚动条

    target = snippet.parentNode.parentNode;
    var wrapperHTML = '<div class="copyable" markdown="1">' + target.outerHTML + '</div>';
    target.outerHTML = wrapperHTML;
});

这里我把if判断null也去掉了,因为既然出现了代码块,肯定会有父节点的。

logo替换

准备好自己的log,把原本的一些图片替换掉,具体要替换下面3个位置的图片:

  1. assets里的一堆图片

  2. assets/logo里面的图片

  3. _include/svg/logo.svg(影响的是网页header)。

    assets里面的一堆图片可以在favicon生成,只需要上传一个图片,会生成相应的各种尺寸图片。浏览器标签页的logo叫favicon,如果想要看到它更新需要在设置里删掉浏览器缓存的图片。

添加评论

TODO

代码主题替换

TODO

问题记录

bundle安装依赖报错

  • 解决办法是直接把Gemfile.lock删了,没啥影响,因为这个是运行bundle自动生成的,等会运行bundle会生成一个。

  • Gemfile里的版本问题

    把里面的~>换成>=,前者表示更高的小版本可以,后者表示更新的版本都可以。这样修改了对依赖的版本约束,新版jekyll的也能用了。但是会出现一些deprecated warning。

deprecated warning

全都是因为sass里的除法:

($button-height-xl - map-get($base, font-size-xl)) / 2

在外面套一个calc函数就可以了,注意percentage里面不能用calc,比较好的解决办法是把percentage(xxx)换成calc(xxx * 100%),这里xxx表示一个表达式。

公式渲染失败

原因是mathjax加载太慢,先尝试把cdn的源换掉:

sources: unpkg  # bootcdn (default), unpkg

但是换掉之后也挺慢的,这2个cdn好像都不太行。现在用的是2.7.4版本的mathjax,据说3.0版本以上性能提升很大,所以想办法升级到3.0吧,并且把mathjax弄到本地。

引入mathjax的代码在_includes/markdown-enhancements/mathjax.html里面最后一行:

<script type="text/javascript" src="" async></script>

而_sources.mathjax的链接是_data/variables.yml里面的,所以在assets文件夹放mathjax,再把这个链接改了就行。

我把mathjax存放在/assets/third-party/mathjax,把链接也改成这个,但是发现这样无法渲染行内公式,原因是mathjax的配置问题。在_includes/markdown-enhancements/mathjax.html这个文件里面有一部分javascript是用来设置mathjax,里面包含了行内公式的支持。但是它指定了<script type="text/x-mathjax-config">这里的type,3.0版本不能这么指定。另外原本的mathjax 2的配置语法也不能用了,要改成新的。

总之要改成:

<script>
    MathJax = {
        tex: {
            inlineMath: [['$', '$'], ['\\(', '\\)']] // 支持 $...$ 和 \(...\) 作为行内公式分隔符
        },
        svg: {
            fontCache: 'global' // 使用全局字体缓存
        }
    };</script>

换成3.2.2版本的mathjax后渲染确实变快了。

无法显示liquid语言

在写markdown文件里面添加代码块,如果代码块里面有liquid语法会导致渲染失败,解决办法是在markdown文件开头加上 render_with_liquid: false

cdn太慢

侧边目录加载慢、归档页面加载慢都是因为相关功能依赖于jquery,而jquery是通过cdn获取的。mermaid加载也慢,也是cdn的锅。为了加速,我把这些第三方库都放到assets/third-party里,然后相应的把_data/variables.yml里面的链接都改成本地地址就可以了。