文章

Chirpy主题的个性化自定义之自定义首页

Motivation

做自定义首页的动机挺直白的,我不太喜欢首页直接贴博客的flow,而更希望是对这个个人网站的引导,所以我选择尝试自己修改一些样式来完成这个工作。
最主要的参考来自jekyll-theme-chirpy issue 711jekyll-theme-chirpy issue 855以及博客Jinchao Li - Exchange Homepage and About,大体上一致,有些细节我优化了一下,有些细节我省略了。


支持新的tab

在替换之前,我们先使用新的tab来指向所有的Blog文章和详细列表页,我们称之为“博客”。由于踩坑记录里所记,我们必须要在index.html里做文章:

  1. 在根目录下新建blogs文件夹,并放一个index.html文件,这个文件影响生成的_site/blogs/index.html,而后者就是静态网站访问的对象:
    1
    2
    3
    4
    5
    
     ---
     layout: blogs
     title: Blogs
     # Index page
     ---
    

    其中,layout属性影响布局,相当于引用_layouts/blogs.html文件;title是主标题,和_tabs文件夹下的title是一个东西,通过文件_data/locales/xx-xx.yml来实现全局国际化:

    1
    2
    3
    4
    5
    
     # The tabs of sidebar
     tabs:
     # format: <filename_without_extension>: <value>
         home: 首页
         blogs: 博客
    
  2. _config.xml文件内指定新的可分页的路径,我们这用的是/blogs/,所以在paginate属性下添加:
    1
    2
    
     paginate: 5
     paginate_path: "/blogs/:num/"
    

    :num表示具体页数。

  3. 往sidebar里强制塞一个tab,在_includes/sidebar.html里增加点东西,让它看起来像这样:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
     <!-- home -->
     <li class="nav-item{% if page.layout == 'home' %}{{ " active" }}{% endif %}">
     <a href="{{ '/' | relative_url }}" class="nav-link">
         <i class="fa-fw fas fa-home"></i>
         <span>{{ site.data.locales[include.lang].tabs.home | upcase }}</span>
     </a>
     </li>
    
     <!-- blogs -->
     <li class="nav-item{% if page.url == '/blogs/' | relative_url %}{{ " active" }}{% endif %}">
     <a href="{{ '/blogs/' | relative_url }}" class="nav-link">
         <i class="fa-fw fa-solid fa-blog"></i>
         <span>{{ site.data.locales[include.lang].tabs.blogs | upcase }}</span>
     </a>
     </li>
    

    重点是blogs块里的urlhref都要对上,<span>里用上了写死的国际化方法,这里会去读对应的文件,如果读不到就用upcase,这部分也很直白。

  4. 为了topbar的美观,修改topbar相关的文件:
    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
    
     <nav id="breadcrumb" aria-label="Breadcrumb">
       {% assign paths = page.url | split: '/' %}
       <!-- {% if paths.size == 0 or page.layout == 'home' %} -->
       {% if paths.size == 0 %}
         <!-- home page -->
         <span>{{ site.data.locales[include.lang].tabs.home | capitalize }}</span>
    
       {% else %}
         {% for item in paths %}
           {% if forloop.first %}
             <span>
               <a href="{{ '/' | relative_url }}">
                 {{ site.data.locales[include.lang].tabs.home | capitalize }}
               </a>
             </span>
    
           {% elsif forloop.last %}
             <!-- {% if page.collection == 'tabs' %} -->
             {% if page.collection == 'tabs' or item == 'blogs' %}
               <span>{{ site.data.locales[include.lang].tabs[item] | default: page.title }}</span>
             {% else %}
               <span>{{ page.title }}</span>
             {% endif %}
             <!-- {% elsif page.layout == 'category' or page.layout == 'tag' %} -->
             {% elsif page.layout == 'category' or page.layout == 'tag' or page.layout == 'home' %}
             <span>
               <a href="{{ item | relative_url }}">
                 {{ site.data.locales[include.lang].tabs[item] | default: page.title }}
               </a>
             </span>
           {% endif %}
         {% endfor %}
       {% endif %}
     </nav>
     <!-- endof #breadcrumb -->
    

    效果如下:
    topbar

  5. 修改_layouts/page.html_layouts/head.html_layouts/sidebar.html_layouts/topbar.html中的page.layout == 'home'替换成page.url == '/' or page.url == site.baseurl,这一般是样式突然变得奇怪的解法。


首页替换

为了新的首页,我们删掉了根目录下的index.html,为此,需要一个新的文件来顶替首页的渲染。我们根据教程采用了permalink+markdown的思路。

  1. _tabs目录下新建一个home.md文件:
    1
    2
    3
    4
    5
    6
    
     ---
     title: Hi there 👋
     order: 0
    
     permalink: /
     ---
    

    然后刷新就会发现sidebar上多出了一个,显然不是我们想要的效果:
    bug-sidebar

  2. 修改_includes/sidebar.html以解决sidebar出现多余内容的问题:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
     <!-- the real tabs -->
     {% for tab in site.tabs %}
     {% if tab.url == '/' | relative_url %}{% continue %}{% endif %}
     <li class="nav-item{% if tab.url == page.url %}{{ " active" }}{% endif %}">
       <a href="{{ tab.url | relative_url }}" class="nav-link">
         <i class="fa-fw {{ tab.icon }}"></i>
         {% capture tab_name %}{{ tab.url | split: '/' }}{% endcapture %}
    
         <span>{{ site.data.locales[include.lang].tabs.[tab_name] | default: tab.title | upcase }}</span>
       </a>
     </li>
     <!-- .nav-item -->
     {% endfor %}
    

    现在正常了。😀


踩坑

这里记录了过程中的一些踩坑和细节,防止你我再次掉进坑里。🤕

No.0 Jekyll的Paginator在md文件中不生效

这算是前人有总结的一个问题了,但是作死的我还是义无反顾地走了上去,然后华丽地踩坑了。😶

问题描述

Jekyll中有辅助翻页的paginator对象,内部存储了一些pageper_page等一些属性。一开始打算直接在_tabs目录下新建md文件然后引用_layouts里的布局直接解决的。但是使用md后发现一个问题,paginator变成空对象了,我翻页和填充元素还要用到它呢!😱

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
<!-- Get pinned posts -->

{% assign offset = paginator.page | minus: 1 | times: paginator.per_page %}
{% assign pinned_num = pinned.size | minus: offset %}

{% if pinned_num > 0 %}
  {% for i in (offset..pinned.size) limit: pinned_num %}
    {% assign posts = posts | push: pinned[i] %}
  {% endfor %}
{% else %}
  {% assign pinned_num = 0 %}
{% endif %}

<!-- Get default posts -->

{% assign default_beg = offset | minus: pinned.size %}

{% if default_beg < 0 %}
  {% assign default_beg = 0 %}
{% endif %}

{% assign default_num = paginator.posts | size | minus: pinned_num %}
{% assign default_end = default_beg | plus: default_num | minus: 1 %}

{% if default_num > 0 %}
  {% for i in (default_beg..default_end) %}
    {% assign posts = posts | push: default[i] %}
  {% endfor %}
{% endif %}

解决过程

没有解决过程,直接鸵鸟,因为我看到了Jekyll官网的教程Pagination

Pagination only works within HTML files
Pagination does not work from within Markdown files from your Jekyll site. Pagination works when called from within the HTML file, named index.html, which optionally may reside in and produce pagination from within a subdirectory, via the paginate_path configuration value.

好了,直接跳过自我摧残环节,后面就直接参照Jinchao Li - Exchange Homepage and About了。


No.1 错误的底部导航栏链接

问题描述

问题很简单,当我将原本的Home页下到第二个tab时,底部的导航栏静态链接出了问题(绿框框出来的部分):
bug-wrong-page-one-nav

解决过程

显然是导航栏直接写死了page_num为1时的链接,那么我们只要修改一下对应的href就行,找一下对应的文件和代码:

1
2
3
{% if paginator.total_pages > 1 %}
  {% include post-paginator.html %}
{% endif %}
1
2
3
4
5
6
7
8
9
<!-- show number -->
<li class="page-item {% if i == paginator.page %} active{% endif %}">
    <a
    class="page-link"
    href="{% if i > 1 %}{{ site.paginate_path | replace: ':num', i | relative_url }}{% else %}{{ '/' | relative_url }}{% endif %}"
    >
    {{- i -}}
    </a>
</li>

定位到显示部分发现,当i > 1时,去替换paginate_path:num占位符,否则,也就是i == 1的情况,直接用'/' | relative_url的拼接来生成链接。所以,这里只要改成'/blogs' | relative_url就行了。

修改文件时一帆风顺,到了写文档的时候出了点问题,我的Jekyll Liquid怎么没办法在文档中展示了?直到我看到了这个报错:

1
2
3
  Liquid Exception: Liquid syntax error (line 55): 'for' tag was never closed in /home/gc/repo/GiannisChen.github.io/_posts/HowTo/2023-12-14-replace-chirpy-home-page-with-own.md
             Error: Liquid syntax error (line 55): 'for' tag was never closed
             Error: Run jekyll build --trace for more information.

突然想起了新版write-a-new-post中的一句话:
Or adding render_with_liquid: false (Requires Jekyll 4.0 or higher) to the post’s YAML block.
那就没事了,恰好我有高版本的Jekyll。🥵

最后的效果:
bugfix-wrong-page-one-nav

本文由作者按照 CC BY 4.0 进行授权