Filter 插件是什么?
Filters 插件是 Jekyll 插件中最为常见的一种类型,它可以将一种 Ruby 的内部方法暴露给 Liquid ,最后在页面调用。比如说,如果有阅读使用 Jekyll 搭建的静态网页的话,我们可能会注意到很多形如下面的内容:
1
2
3
{% assign foo = 10 %}
{% foo | plus: 4 %}
{{ foo }}
这就是 Liquid 语言,第一行和第二行使用 {% %}
包着的是运算式,而第三行使用 {{ }}
包着的表示将抱着的变量输出。Liquid 是一种很简单的模版语言,半天就可以学完,对 Liquid 有更多兴趣的可以去这个网站查看一下官方的文档。
所以说了这么多,Filter 到底是什么呢?其实在上面的代码中的第二行,plus
就是一个 Filter,表示把 foo
作为输入,把 foo
加 4 后重新赋值给 foo
,相当于 foo = foo + 4
。
Filter 有什么用?
Filter 实际上或许是 Jekyll 所允许的插件中第二有用的插件类型(第一有用的插件类型应该是 Hook),其受用面非常广,包括但不限于:
- 快捷计算两个日期之间的差距。
- 对文章生成目录。
- 自动混淆邮件地址。
- 计算文章字数和阅读时间。
为什么我觉得这些都可以用 JS 实现?
确实,理论上来说所有使用 Filter 插件可以做到的事情都可以使用 javascript
在运行时完成,但如果我们使用插件来使这些事情在编译时就完成了的话,无疑可以增强网站在游览器上的性能,所以还是非常有用的。
注意!Pages 上无法使用插件
GitHub Pages ( 或者其他大部分 Pages ) 考虑到安全因素,都通过 —safe 选项禁用了插件功能。因此如果你的网站部署在 Github Pages ,那么你的插件不会工作。
不过仍然有办法发布到 GitHub Pages,你只需在本地做一些转换,并把生成好的文件上传到 Github 替代 Jekyll 就可以了。
让我们开始吧
本篇将从最简单的 Filter 开始,实现一个简单的计算文章字数和阅读时间的 Filter。这个 Filter 可以帮助网页在展示文章的同时展示字数和预计的阅读时间。
根据 Jekyll 的官方文档,所有的 Jekyll 插件都要存储在项目目录下的 _plugins
文件夹,所以如果项目根目录下没有 _plugins
文件夹的话需要先手动新建一个 _plugins
文件夹。然后我们在新建的 _plugins
文件夹中新建一个 Ruby 文件叫做 jekyll_reading_time.rb
。然后打开这个文件,我们将我们的这个插件命名为 ReadingTime
。
1
2
3
module ReadingTime
end
我们需要暴露给 Liquid 的方法有两个。第一个是 count_words(html)
方法:传入网页,计算文章中的字数;第二个是 reading_time(html)
方法:传入网页,计算大概的阅读时间。reading_time(html)
方法很好写,我们只需要得到有多少字数,然后除以每分钟的阅读字数,向上取整就是阅读时间了。
1
2
3
4
5
6
7
8
9
10
11
module ReadingTime
def count_words(html)
end
def reading_time(html)
(count_words(html) / 140.0).ceil
end
end
为了计算网页的字数,我们可以首先使用 Ruby 库 nokogiri
来解析 html 为一个对象,然后递归每一个 html 对象,忽略一些肯定没有文字的对象,对其他的对象查询其中有没有文字。我们使用私有函数来处理这个过程。
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
36
37
require ‘nokogiri’
module ReadingTime
def count_words(html)
words(html)
end
def reading_time(html)
(count_words(html) / 140.0).ceil
end
private
def text_nodes(root)
ignored_tags = %w[ area audio canvas code embed footer form img map math nav object pre script svg table track video ]
texts = 0
root.children.each { |node|
if node.text?
text_array = node.text.unpack(“U*”)
text_array.each { |c|
texts = texts + 1
}
elsif not ignored_tags.include? node.name
texts = texts + text_nodes(node)
end
}
texts
end
def words(html)
fragment = Nokogiri::HTML.fragment html
text_nodes(fragment)
end
end
可以看到我们的插件整体已经成型了,只差最后一步了,就是去 Jekyll 注册这个插件。
为了向 Jekyll 注册我们的新插件,我们只需要在模块外调用 Jekyll 的注册方法。
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
36
37
38
39
require ‘nokogiri’
module ReadingTime
def count_words(html)
words(html)
end
def reading_time(html)
(count_words(html) / 140.0).ceil
end
private
def text_nodes(root)
ignored_tags = %w[ area audio canvas code embed footer form img map math nav object pre script svg table track video ]
texts = 0
root.children.each { |node|
if node.text?
text_array = node.text.unpack(“U*”)
text_array.each { |c|
texts = texts + 1
}
elsif not ignored_tags.include? node.name
texts = texts + text_nodes(node)
end
}
texts
end
def words(html)
fragment = Nokogiri::HTML.fragment html
text_nodes(fragment)
end
end
Liquid::Template.register_filter(ReadingTime)
完成了!我们的第一个插件就这样完成了!以后在编写网页的时候,如果想得到一篇文章的字数和估计的阅读时间,只需要在 html 代码中这样写就可以了:
1
2
这篇文章有 {{ post.content | count_words }} 字
大概需要 {{ post.content | reading_time }} 分钟的阅读
本文作者 Auther:Soptq
本文链接 Link: https://soptq.me/2020/03/27/jekyll-plugin-filter/
版权声明 Copyright: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处。 Content on this site is licensed under the CC BY-NC-SA 4.0 license agreement unless otherwise noted. Attribution required.
发现存在错别字或者事实错误?请麻烦您点击 这里 汇报。谢谢您!