学习制作 Jekyll 模版,其实主要是学习 Liquid 语法。
参考:Liquid 官方文档。
就像 PHP、ASP、Python 等一切网络动态语言一样,Liquid 也相当于一种独立的动态语言,没什么大差别,基本功能都有。说白了就是动态生成 HTML,可以输出变量,操作数组,调用外部数据,设置 IF ELSE 判断,FOR 循环等,这些都能达到。
开始讲语法前,大概说明一下运行流程:
常用变量及属性
参考:Jekyll 语法简单笔记
site 对象
site 对象是全站都能调用的变量,全部都在_config.yml 文件中定义。常用变量如下:
site.pages: 所有 `_
site.posts: 所有文章
site.categories: 所有的 categories
site.tags: 所有的 tags
site.related_posts: 从 LSI Keywords 提取出来最相关最新的 10 篇文章
site.collections: 所有集合(与 posts 逻辑很大不同,一般用来放 members 等特殊数据)
site.documents: 所有 collections 里面的文档
site.data: _data 目录下的数据
site.[abc]: 自定义的变量(手动在_config.yml 中指定)
page 对象
page.content: 页面的内容
page.title: 标题(手动在 Front Matters 中指定)
page.excerpt: 摘要
page.url: 链接
page.date: 时间
page.id: 唯一标示
page.categories: 分类(手动在 Front Matters 中指定)
page.tags: 标签(手动在 Front Matters 中指定)
page.path: 源代码位置
page.next: 下一篇文章
page.previous: 上一篇文章
categories 对象
从 site.categories 列表中循环得到的是一个一个的 category,其中包括这些属性:
cat[0]: 返回 cat 的名称
cat[0].size: 返回这个分类里的文章数量
cat[1]: 返回一个 post_list 列表,包含这个 category 里所有的 post 对象。
cat[1].size: 返回这个 post_list 列表中的对象数量。
tag 对象
从 site.tags 列表中循环得到的是一个一个的 tag,其中包括这些属性:
tag[0]: 返回 tag 的名称
tag[0].size: 返回这个 tags 里的文章数量
tag[1]: 返回一个 post_list 列表,包含这个 tags 里所有的 post 对象。
tag[1].size: 返回这个 post_list 列表中的对象数量。
paginator 对象
paginator.per_page: 每一页的数量
paginator.posts: 这一页的数量
paginator.total_posts: 所有文章的数量
paginator.total_pages: 总的页数
paginator.page: 当前页数
paginator.previous_page: 上一页的页数
paginator.previous_page_path: 上一页的路径
paginator.next_page: 下一页的页数
paginator.next_page_path: 下一页的路径
列表读取(各种归档页面用)
循环读取 Posts
读取全站所有的 posts:
{% for post in site.posts %}
<h2> {{post.title}} </h2>
<h2> {{post.url}} </h2>
<h2> {{post.category}} </h2>
<h2> {{post.excerpt}} </h2> ︎ 文章摘要,自动生成的
{% endfor %}
只读取_posts/ 文件夹中某个 category 中的 posts,例如_posts/tech 文件夹中放的是一些 category 为 tech 的文章,那么读取方式是:
{% for post in site.categories.tech %}
<h2> {{post.title}} </h2>
{% endfor %}
注意,在_posts 中 nested 文件夹里的文章,也必须在 Front matter 中指定分类,要不然读不出来。
循环读取 categories
读取全站所有的分类:
{% for cat in site.categories %}
<h2> {{cat[0] }} </h2>
{% endfor %}
读取所有分类下的所有文章:
{% for cat in site.categories %}
{% for post in cat[1] %}
<h2> {{post.title}} </h2>
{% endfor %}
{% endfor %}
读取某个分类下所有的文章:
{% for post in site.categories.blog %}
<h2> {{post.title}} </h2>
{% endfor %}
循环读取 tags
读取全站所有的 tags:
{% for tag in site.tags %}
<h1> {{tag[0] }} </h1>
{% endfor %}
读取所有 tags 下的所有文章:
{% for tag in site.tags %}
{% for post in cat[1] %}
<h2> {{post.title}} </h2>
{% endfor %}
{% endfor %}
读取某个 tag 下所有的文章:
{% for post in site.tags.math %}
<h2> {{post.title}} </h2>
{% endfor %}
读取某 category 下所有文章并按 tag 分组读取
{% for post in site.categories.Tech %} ︎ 先读取某分类下所有的文章
{% assign tags = tags |concat: post.tags |uniq %} ︎ 把每篇文章的 tags 存到列表里,并删除重复项
{% endfor %}
{% for tag in tags %}
<h2> {{tag}} </h2> ︎ 循环输出这个 category 中的所有 tags
{% for post in site.categories.calculus %}
{% if post.tags contains tag %} ︎ 循环判断如果文章属于此 tag 则显示出来
<h4> {{post.title}} </h4>
{% endif %}
{% endfor %}
{% endfor %}
Post 读取
需要在 MD 文档里指定 layout 才能调用。比如文档里指定了 layout: post,那么系统就找到_layouts/post.html 这个文件;如果文档指定了 layout: blog,那么系统就会找到_layout/blog.html 这个文件。在 layout 里面读取 post 数据很简单,不需要 for 循环,不需要 if 判断,直接用 post 这个对象就行。因为系统已经把文章的数据传过来了。
假如我们在_posts/xx.md 文章的头信息中,定义了这些数据:
—
layout: post
title: I’m a post
category: ‘blog’
tags: [‘jekyll’, ‘wordpress’, ‘blog’]
—
(注:tags 列表等,在 yaml 中可以用 - tag 或 [‘tag’] 表示,一样的 )
以下就是这个 post.html 文件读取 post 数据的方式:
<h2> {{post.title}} </h2>
<h2> {{post.category}} </h2>
<h2> {{post.content}} </h2>
{% for tag in post.tags %}
<h2> {{tag}} </h2>
{% endfor %}
group_by 分组和 where_exp 条件筛选
官方的 group_by 做到了复杂查询的功能,比如查找某个 category 下的全部文章并按 tag 分组显示。相对自己写 for/if 实现来说,虽然官方提供了这个功能,但是你仔细阅读文档就会发现,这个 group_by 必须配合单独的静态的额外的文档才能实现。也就是说,你必须手动写个 mygroup.doc 文件,一个一个指定每篇文章的分组、分类、顺序等。那实在太麻烦了。
参考官方:Navigation