Liquid 是一门开源的模板语言,何为模板语言呢?
我的理解是:
在 HTML 的基础之上,通过一些逻辑语法、变量等控制页面上动态变化的部分,最终生成符合预期的静态文件。
举个例子:
模板语言就像一台甜品加工机器,每个模板语言写好的文件就像一个模子,数据就是制作甜品的原材料;注入不同的 “原材料”,再加上特定的 “模子”,最终就能得到一个特定样式、内容不同的 “甜品” 啦。🎂
接下来就大致介绍一下 Liquid。
Liquid 代码分为三类:Object、Tags、Filters。
1. Object
Object 就是在文档需要展示内容的位置,用双花括号 {{ }}
包裹对象或变量名。
数据:
1
2
3
4
5
{
"post": {
"title": "Template language: Liquid"
}
}
输入:{{ post.title }}
输出:Template language: Liquid
2. Tags
Tags 主要用于模板的逻辑控制,包括循环、判断等,由单括号加百分号标识:{% %}
。
一下列举一些常用的 Tags。
2.1. 控制流
控制流标记(control flow tag)能够根据编程逻辑改变 Liquid 输出的信息。
2.1.1. if
只有当某个条件为 true 时才执行一段代码。
1
2
3
4
5
{% if post.title == 'Template language: Liquid' %}
Template language: Liquid
{% endif %}
输出: Template language: Liquid
2.1.2. unless
与 if 相对 – 只有当某个条件不成立时才执行一段代码。
1
2
3
4
5
{% unless post.title == 'Liquid' %}
Template language: Liquid
{% endunless %}
输出: Template language: Liquid
和下面代码结果一致,注意判断条件:
1
2
3
4
5
{% if post.title != 'Liquid' %}
Template language: Liquid
{% endif %}
输出: Template language: Liquid
2.1.3. elsif / else
为 if 或 unless 添加更多状态判断。
1
2
3
4
5
6
7
8
9
{% if post.title == 'Liquid' %}
Liquid
{% elsif post.title == 'Template language: Liquid' %}
Template language: Liquid
{% else %}
Nothing
{% endif %}
输出: Template language: Liquid
2.1.4. case / when
case / when 和 JavaScript 的 switch 语法是类似的:
1
2
3
4
5
6
7
8
9
10
{% case post.title %}
{% when 'Liquid' %}
Liquid
{% when 'Template language: Liquid' %}
Template language: Liquid
{% else %}
Nothing
{% endcase %}
输出: Template language: Liquid
2.2. 循环
2.2.1. for
重复输出一段代码。
1
2
3
4
5
{% for i in (1..5) %}
{{ i }}
{% endfor %}
输出:1 2 3 4 5
break
、continue
关键字同样适用:
1
2
3
4
5
6
7
8
9
{% for i in (1..5) %}
{% if i == 4 %}
{% break %}
{% else %}
{{ i }}
{% endif %}
{% endfor %}
输出:1 2 3
1
2
3
4
5
6
7
8
9
{% for i in (1..5) %}
{% if i == 4 %}
{% continue %}
{% else %}
{{ i }}
{% endif %}
{% endfor %}
输出:1 2 3 5
limit
- 限制循环次数
1
2
3
4
5
{% for i in (1..5) limit:2 %}
{{ i }}
{% endfor %}
输出:1 2
offset
- 从指定索引号开始执行循环。
1
2
3
4
5
{% for i in (1..5) limit:2 %}
{{ i }}
{% endfor %}
输出:3 4 5
reversed
- 反转循环的执行顺序。
1
2
3
4
5
{% for i in (1..5) reversed %}
{{ i }}
{% endfor %}
输出:5 4 3 2 1
还有一部分不常用的循环标记,例如:cycle
、tablerow
等,可点击 此处 查看。
2.3. 变量
顾名思义,用于创建新的 Liquid 变量。
2.3.1. assign
创建一个新的变量。
1
2
3
4
{% assign title = 'Template language: Liquid' %}
{{ title }}
输出:Template language: Liquid
2.3.2. capture
capture 开始与结束标记之间的所有字符串赋值给一个新的变量。
1
2
3
4
5
6
7
{% capture title %}
Template language: Liquid
{% endcapture %}
{{ title }}
输出:Template language: Liquid
字符串可以包含变量拼接而成:
1
2
3
4
5
6
7
8
9
{% assign value = 'Liquid' %}
{% capture title %}
Template language: {{ value }}
{% endcapture %}
{{ title }}
输出:Template language: Liquid
2.4. 模板
模板标记用来处理不需要解析的文档内容,以及使用特定的逻辑处理内容。
2.4.1. comment
comment
- 注释标记,通过 {% comment %} {% endcomment %}
包裹需要注释的内容,包括 Liquid 代码:
1
2
3
4
{% comment %}
{% assign title = 'test' %}
{{ title }}
{% endcomment %}
2.4.2. raw
raw
- 原始内容标记,与 comment 相同的是 raw 也不会解析包裹的 Liqudi 代码;不同的是,包裹的内容会原封不动地在文档中展示出来,而不是被隐藏。
这在本文中展示 Liquid 标记起到了重要的作用,因为本文是基于 Liquid 解析的,因此当示例中包含 Liquid 代码时将会被自动解析,这显然不在预期结果之内。
使用 raw
标记便能禁止解析其包裹的代码,并将其包裹的原始内容直接输出。
用法,和其他 Tags 用法一样:
使用 {% %}
包裹 raw
为开始标签;{% %}
包裹 endraw
为结束标签。
❗注:但经过实际验证 raw 标签不能嵌套,否则会报出语法错误
3. Filters
过滤器 | 描述 |
---|---|
abs | 返回一个数字的绝对值 |
append | 返回两个字符串拼接之后的值 |
at_least | 将数字限制在最小值 |
at_most | 将数字限制在最大值 |
capitalize | 将字符串首字母转为大写 |
ceil | 将一个浮点数向上取整并返回一个最接近的整数 |
compact | 删除数组中的所有空值 |
concat | 返回两个数组合并后的值 |
date | 将时间戳转换为指定的日期格式 |
default | 设定默认值 |
divided_by | 返回两个数相除后的结果 |
downcase | 返回一个字符串,字符串中的所有字符转为小写形式 |
escape | 返回一个由十六进制转义序列替换的字符串(字符的 16 进制格式值,当该值小于等于 0xFF 时,用一个 2 位转移序列: %xx 表示. 大于的话则使用 4 位序列:%uxxxx 表示) |
escape_once | 转义一个字符串并且不修改已经转义过的实体 |
first | 返回数组的第一项 |
floor | 将一个浮点数通过舍弃小数部分得到最近的整数 |
join | 将数组中的各个字符串合并为一个字符串,并将 split 参数作为字符串之间的分隔符 |
last | 返回数组中的最后一项 |
lstrip | 删除字符串左侧的所有空白符(制表符、空格和换行符) |
map | 从对象中提取指定名称的属性的值,并用这些值构建一个数组 |
minus | 返回两个数相减后的结果 |
modulo | 返回除法运算的余数 |
newline_to_br | 将所有换行符(\n) 替换为 HTML 的 <br> 标签 |
plus | 返回两个数相加后的结果 |
prepend | 在一个字符串前面附加另一个字符串 |
remove | 从一个字符串中删除所有出现的另一个子字符串 |
remove_first | 从一个字符串中仅仅删除第一次出现的另一个子字符串 |
replace | 将参数中给出的第一个参数全部替换为第二个参数 |
replace_first | 将字符串中出现的第一个参数替换为第二个参数 |
reverse | 将数组中的所有项的顺序反转。reverse 不能操作字符串 |
round | 将浮点数舍入到最近的整数,或者,如果传入的参数是一个数值的话,将浮点数舍入到参数指定的小数位 |
rstrip | 将字符串右侧的所有空白字符(制表符 - tab、空格符 - space 和 回车符 - newline)删除 |
size | 返回字符串中所包含的字符数或者数组中所包含的条目数量 |
slice | 只传入一个参数时将返回此参数作为下标所对应的单个字符。第二个参数是可选的,用于指定返回的子字符串的长度 |
sort | 对数组中的所有进行排序。排序后的数组是按照区分大小写的顺序排列的 |
sort_natural | 对数组进行排序,并且大小写无关 |
split | 根据参数传入的分隔符将字符串分解为数组 |
strip | 删除字符串左右两侧的所有空白符号(包括制表符、空格、换行符) |
strip_html | 从字符串中删除所有 HTML 标签 |
strip_newlines | 从字符串中删除所有换行字符 |
times | 返回两个数相乘后的结果 |
truncate | 将字符串截短为指定的字符个数。如果指定的字符数量小于字符串的长度,则会在字符串末尾添加一个省略号(…) 并将此省略号计入字符个数中 |
truncatewords | 将字符串截短为指定的单词个数。如果指定的单词数量小于字符串中包含的单词个数,则会在字符串末尾添加一个省略号(…) |
uniq | 删除数组中的所有冗余项 |
upcase | 返回一个字符串,字符串中的所有字符转为大写形式 |
url_decode | 将字符串中被 url_encode 编码的字符进行解码 |
url_encode | 将字符串中非 URL 安全的字符转换为百分号编码 |
4. Jekyll 增加的标签和过滤器
Jekyll 默认使用 Liquid 模板语言,支持所有标准的 Liquid 标签和过滤器。Jekyll 甚至增加了几个过滤器和标签,方便使用。
4.1. Jekyll Tags
4.1.1. highlight
highlight
- 用于高亮代码块
代码示例:
1
2
3
4
5
{% highlight ruby linenos %}
def foo
puts 'foo'
end
{% endhighlight %}
效果:
1
2
3
def foo
puts 'foo'
end
4.1.2. link
link
- 可以正确生成指定路径的永久链接,可以在 Markdown 的链接中使用 link
。
代码示例:
1
2
3
{% link _drafts/2015-02-06-jekyll_liquid.md %}
[本文链接]({% link _drafts/2015-02-06-jekyll_liquid.md %})
效果:
-
/posts/jekyll_liquid
4.1.3. post_url
post_url
- 指定已发布的一篇文章生成对应的链接,同样可以在 Markdown 的链接中使用 post_url
。
代码示例:
1
2
3
{% post_url 2015-02-06-jekyll_liquid %}
[本文链接]({% post_url 2015-02-06-jekyll_liquid %})
效果:
-
/posts/jekyll_liquid
4.2. Jekyll Filter
描述 | 过滤器 | 输出 |
---|---|---|
将日期转化为 XML 模式 (ISO 8601) 的格式 | {{ site.time | date_to_xmlschema }} |
2008-11-17T13:07:54-08:00 |
将日期转化为 RFC-822 格式 | {{ site.time | date_to_rfc822 }} |
Mon, 17 Nov 2008 13:07:54 -0800 |
将日期转化为短格式 | {{ site.time | date_to_string }} |
17 Nov 2008 |
将日期转化为长格式 | {{ site.time | date_to_long_string }} |
17 November 2008 |
选取键值对应的所有对象,返回一个数组 | {{ site.members | where:"graduation_year","2014" }} |
|
选取表达式正确的所有对象,返回一个数组 | {{ site.members | where_exp:"item","item.graduation_year == 2014" }} /{{ site.members | where_exp:"item","item.projects contains 'foo'" }} |
|
根据所给属性将对象分组,返回一个数组 | {{ site.members | group_by:"graduation_year" }} |
[{"name"=>"2013", "items"=>[...]},{"name"=>"2014", "items"=>[...]}] |
对一些字符串转码,已方便显示在 XML | {{ page.content | xml_escape }} |
|
CGI 转码,用于 URL 中,将所有的特殊字符转化为 %XX 的形式 | {{ “foo,bar;baz?” | cgi_escape }} |
foo%2Cbar%3Bbaz%3F |
URI 转码 | {{ “'foo, bar \\baz?'” | uri_escape }} |
foo,%20bar%20%5Cbaz? |
统计文章中的字数 | {{ page.content | number_of_words }} |
1337 |
将数组转换为句子,列举标签时尤其有用 | {{ page.tags | array_to_sentence_string }} |
foo, bar, and baz |
将 Markdown 格式的字符串转换为 HTML | {{ page.excerpt | markdownify }} |
|
将 Sass / SCSS 格式的字符串转换为 CSS | {{ some_scss | scssify }} /{{ some_sass | sassify }} |
|
将字符串转换为小写字母 URL “slug” | {{ "The \_config.yml file" | slugify }} /{{ "The \_config.yml file" | slugify: 'pretty' }} |
the-config-yml-file / the-_config.yml-file |
将 Hash / 数组 格式的字符串转换为 JSON | {{ site.data.projects | jsonify }} |
|
对数组排序,可选参数为:1.排序属性;2.顺序(正序或倒序) | {{ page.tags | sort }} /{{ site.posts | sort: 'author' }} /{{ site.pages | sort: 'title', 'last' }} |
|
从数组中选取一个随意值。可选参数为:选取个数 | {{ site.pages | sample }} /{{ site.pages | sample:2 }} |
|
从一个数组中 Push, pop, shift, and unshift 元素 | {{ page.tags | push: 'Spokane' }} /{{ page.tags | pop }} /{{ page.tags | shift }} /{{ page.tags | unshift: "Olympia" }} |
['Seattle', 'Tacoma', 'Spokane'] / ['Seattle'] / ['Tacoma'] / ['Olympia', 'Seattle', 'Tacoma'] |
将对象转换为其字符串表示形式,用于调试 | {{ some_var | inspect }} |