Liquid 语法
Liquid 是 Ruby 的一个模版引擎库,Jekyll中用到的Liquid标记有两种:输出和标签。
Output 标记:变成文本输出,被2层成对的花括号包住,如: {{content}}
Tag 标记:执行命令,被成对的花括号和百分号包住,如: {% command %}
Jekyll 输出 Output
示例:
Hello {{name}}
Hello {{user.name}}
Hello {{ 'tobi' }}
Output 标记可以使用过滤器 Filters 对输出内容作简单处理。
多个 Filters 间用竖线隔开,从左到右依次执行,Filter 左边总是输入,返回值为下一个 Filter 的输入或最终结果。
Hello {{ 'tobi' | upcase }} # 转换大写输出
Hello tobi has {{ 'tobi' | size }} letters! # 字符串长度
Hello {{ '*tobi*' | markdownify | upcase }} # 将Markdown字符串转成HTML大写文本输出
Hello {{ 'now' | date: "%Y %h" }} # 按指定日期格式输出当前时间
标准过滤器 Filters
下面是常用的过滤器方法,更多的API需要查阅源代码(有注释)才能看到。
源码主要看两个 Ruby Plugin 文件:filters.rb(Jekyll) 和 standardfilters.rb(Liquid)。
date- 将时间戳转化为另一种格式 (syntax reference)capitalize- 输入字符串首字母大写 e.g.{{ 'capitalize me' | capitalize }} # => 'Capitalize me'downcase- 输入字符串转换为小写upcase- 输入字符串转换为大写first- 返回数组中第一个元素last- 返回数组数组中最后一个元素join- 用特定的字符将数组连接成字符串输出sort- 对数组元素排序map- 输入数组元素的一个属性作为参数,将每个元素的属性值映射为字符串size- 返回数组或字符串的长度 e.g.{{ array | size }}escape- 将字符串转义输出 e.g.{{ "<p>test</p>" | escape }} # => <p>test</p>escape_once- 返回转义后的HTML文本,不影响已经转义的HTML实体strip_html- 删除 HTML 标签strip_newlines- 删除字符串中的换行符(\n)newline_to_br- 用HTML<br/>替换换行符\nreplace- 替换字符串中的指定内容 e.g.{{ 'foofoo' | replace:'foo','bar' }} # => 'barbar'replace_first- 查找并替换字符串中第一处找到的目标子串 e.g.{{ 'barbar' | replace_first:'bar','foo' }} # => 'foobar'remove- 删除字符串中的指定内容 e.g.{{ 'foobarfoobar' | remove:'foo' }} # => 'barbar'remove_first- 查找并删除字符串中第一处找到的目标子串 e.g.{{ 'barbar' | remove_first:'bar' }} # => 'bar'truncate- 截取指定长度的字符串,第2个参数追加到字符串的尾部 e.g.{{ 'foobarfoobar' | truncate: 5, '.' }} # => 'foob.'truncatewords- 截取指定单词数量的字符串prepend- 在字符串前面添加字符串 e.g.{{ 'bar' | prepend:'foo' }} # => 'foobar'append- 在字符串后面追加字符串 e.g.{{ 'foo' | append:'bar' }} # => 'foobar'slice- 返回字符子串指定位置开始、指定长度的子串 e.g.{{ "hello" | slice: -4, 3 }} # => ellminus- 减法运算 e.g.{{ 4 | minus:2 }} # => 2plus- 加法运算 e.g.{{ '1' | plus:'1' }} #=> '11', {{ 1 | plus:1 }} # => 2times- 乘法运算 e.g{{ 5 | times:4 }} # => 20divided_by- 除法运算 e.g.{{ 10 | divided_by:2 }} # => 5split- 根据匹配的表达式将字符串切成数组 e.g.{{ "a~b" | split:"~" }} # => ['a','b']modulo- 求模运算 e.g.{{ 7 | modulo:4 }} # => 3
Jekyll 标签 Tag
标签用于模板中的执行语句。目前 Jekyll/Liquid 支持的标准标签库有:
| Tags | 说明 |
|---|---|
| assign | 为变量赋值 |
| capture | 用捕获到的文本为变量赋值 |
| case | 条件分支语句 case…when… |
| comment | 注释语句 |
| cycle | 通常用于在某些特定值间循环选择,如颜色、DOM类 |
| for | 循环语句 |
| if | if/else 语句 |
| include | 将另一个模板包进来,模板文件在 _includes 目录中 |
| raw | 禁用范围内的 Tag 命令,避免语法冲突 |
| unless | if 语句的否定语句 |
Comments
仅起到注释 Liquid 代码的作用。
We made 1 million dollars {% comment %} in losses {% endcomment %} this year.
Raw
临时禁止执行 Jekyll Tag 命令,在生成的内容里存在冲突的语法片段的情况下很有用。
注意:由于排版问题,去除下面示例中 { 与 % 之间的空格。
{ % raw % }
In Handlebars, {{ this }} will be HTML-escaped, but {{{ that }}} will not.
{ % endraw % }
显示 { % raw % }
{% assign openTag = '{%' %}
{{ openTag }} raw %}
content # 代码块
{{ openTag }} endraw %}
If / Else
条件语句,可以使用关键字有:if、unless、elsif、else。
{% if user %}
Hello {{ user.name }}
{% endif %}
# Same as above
{% if user != null %}
Hello {{ user.name }}
{% endif %}
{% if user.name == 'tobi' %}
Hello tobi
{% elsif user.name == 'bob' %}
Hello bob
{% endif %}
{% if user.name == 'tobi' or user.name == 'bob' %}
Hello tobi or bob
{% endif %}
{% if user.name == 'bob' and user.age > 45 %}
Hello old bob
{% endif %}
{% if user.name != 'tobi' %}
Hello non-tobi
{% endif %}
# Same as above
{% unless user.name == 'tobi' %}
Hello non-tobi
{% endunless %}
# Check for the size of an array
{% if user.payments == empty %}
you never paid !
{% endif %}
{% if user.payments.size > 0 %}
you paid !
{% endif %}
{% if user.age > 18 %}
Login here
{% else %}
Sorry, you are too young
{% endif %}
# array = 1,2,3
{% if array contains 2 %}
array includes 2
{% endif %}
# string = 'hello world'
{% if string contains 'hello' %}
string includes 'hello'
{% endif %}
Case
适用于当条件实例很多的情况。
{% case template %}
{% when 'label' %}
// {{ label.title }}
{% when 'product' %}
// {{ product.vendor | link_to_vendor }} / {{ product.title }}
{% else %}
// {{page_title}}
{% endcase %}
Cycle:
经常需要在相似的任务间选择时,可以使用 cycle 标签。
{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}
{% cycle 'one', 'two', 'three' %}
# =>
one
two
three
one
如果要对循环作分组处理,可以指定分组的名字:
{% cycle 'group 1': 'one', 'two', 'three' %}
{% cycle 'group 1': 'one', 'two', 'three' %}
{% cycle 'group 2': 'one', 'two', 'three' %}
{% cycle 'group 2': 'one', 'two', 'three' %}
# =>
one
two
one
two
For loops:
循环遍历数组:
{% for item in array %}
{{ item }}
{% endfor %}
循环迭代 Hash 散列,item[0] 是键,item[1] 是值:
{% for item in hash %}
{{ item[0] }}: {{ item[1] }}
{% endfor %}
每个循环周期,提供下面几个可用的变量:
forloop.length # => length of the entire for loop
forloop.index # => index of the current iteration
forloop.index0 # => index of the current iteration (zero based)
forloop.rindex # => how many items are still left ?
forloop.rindex0 # => how many items are still left ? (zero based)
forloop.first # => is this the first iteration ?
forloop.last # => is this the last iteration ?
还有几个属性用来限定循环过程:
limit:int : 限制循环迭代次数
offset:int : 从第n个item开始迭代
reversed : 反转循环顺序
# array = [1,2,3,4,5,6]
{% for item in array limit:2 offset:2 %}
{{ item }}
{% endfor %}
# results in 3,4
{% for item in collection reversed %}
{{item}}
{% endfor %}
{% for post in site.posts limit:20 %}
{{ post.title }}
{% endfor %}
允许自定义循环迭代次数,迭代次数可以用常数或者变量说明:
# if item.quantity is 4...
{% for i in (1..item.quantity) %}
{{ i }}
{% endfor %}
# results in 1,2,3,4
Variable Assignment :
为变量赋值,用于输出或者其他 Tag:
{% assign index = 1 %}
{% assign name = 'freestyle' %}
{% for t in collections.tags %}{% if t == name %}
<p>Freestyle!</p>
{% endif %}{% endfor %}
变量是布尔类型
{% assign freestyle = false %}
{% for t in collections.tags %}{% if t == 'freestyle' %}
{% assign freestyle = true %}
{% endif %}{% endfor %}
{% if freestyle %}
<p>Freestyle!</p>
{% endif %}
capture
允许将大量字符串合并为单个字符串并赋值给变量,而不会输出显示。
{% capture attribute_name %}{{ item.title | handleize }}-{{ i }}-color{% endcapture %}
<label for="{{ attribute_name }}">Color:</label>
<select name="attributes[{{ attribute_name }}]" id="{{ attribute_name }}">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
其他模板语句
字符转义
有时候想输出 { 了,怎么办? 使用反斜线 \ 转义即可
\{ => {
格式化时间
{{ site.time | date_to_xmlschema }} # => 2008-11-07T13:07:54-08:00
{{ site.time | date_to_rfc822 }} # => Mon, 07 Nov 2008 13:07:54 -0800
{{ site.time | date_to_string }} # => 07 Nov 2008
{{ site.time | date_to_long_string }} # => 07 November 2008
代码语法高亮
安装好 pygments.rb 的 gem 组件和 Python 2.x 后,配置文件添加:highlighter: pygments,就可以使用语法高亮命令了,支持语言多达 100 种以上。
{% highlight ruby linenos %}
# some ruby code
{% endhighlight %}
上面的示例中,使用 highlight 语句来处理代码块;并设定第一个参数 ruby 来指定高亮的语言 Ruby ,第二个参数 linenos 来开启显示代码行号的功能。
链接同域内的 post
使用 post_url Tag 可以自动生成网站内的某个 post 超链接。
这个命令语句以相关 post 的文件名为参数,在引入同域的 post 链接时,非常有用。
# 自动生成某篇文章的链接地址
{% post_url 2010-07-21-name-of-post %}
# 引入该文章的链接
[Name of Link]({% post_url 2010-07-21-name-of-post %})
Gist 命令
嵌入 GitHub Gist,也可以指定要显示的 gist 的文件名。
{% gist parkr/931c1c8d465a04042403 %}
{% gist parkr/931c1c8d465a04042403 jekyll-private-gist.markdown %}
生成摘要
配置文件中设定 excerpt_separator 取值,每篇 post 都会自动截取从开始到这个值间的内容作为这篇文章的摘要 post.excerpt 使用。
如果要禁用某篇文章的摘要,可以在该篇文章的 YAML 头部设定 excerpt_separator: "" 。
{ % for post in site.posts % }
<a href="{ { post.url } }">{ { post.title } }</a>
{ { post.excerpt | remove: 'test' } }
{ % endfor % }
删除 HTML 标签
这个在摘要作为 head 标签里的 meta="description" 内容输出时很有用
{ { post.excerpt | strip_html } }
删除指定文本
过滤器 remove 可以删除变量中的指定内容
{ { post.url | remove: 'http' } }
CGI Escape
通常用于将 URL 中的特殊字符转义为 %xx 形式
{ { "foo,bar;baz?" | cgi_escape } } # => foo%2Cbar%3Bbaz%3F
排序
# Sort an array. Optional arguments for hashes:
# 1. property name
# 2. nils order ('first' or 'last')
{ { site.pages | sort: 'title', 'last' } }
搜索指定 Key
# Select all the objects in an array where the key has the given value.
{ { site.members | where:"graduation_year","2014" } }
To JSON 格式
将 Hash 散列或数组转换为 JSON 格式
{ { site.data.projects | jsonify } }
序列化
把一个数组变成一个字符串
{ { page.tags | array_to_sentence_string } } # => foo, bar, and baz
单词的个数
{ { page.content | number_of_words } }
内容名字规范
对于博客 post ,文件命名规则必须是 YEAR-MONTH-DAY-title.MARKUP 的格式。
使用 rake post 会自动将 post 文件合适命名。
比如:
2014-11-06-memcached-code.md
2014-11-06-memcached-lib.md
2014-11-06-sphinx-config-and-use.md
2014-11-07-memcached-hash-table.md
2014-11-07-memcached-string-hash.md