使用 Liquid 获取、操作和排序哈希对象值
Fetch, manipulate and sort hash object values with Liquid
我正在为部署在 Github 页面上的 Jekyll 站点制作词汇表模板。
条目来自 _data/glossary.yml
文件。
我希望模板按字母顺序排列条目,而不考虑 glossary.yml
.
中数据的顺序
使用 {% assign glossary = site.data.glossary | sort 'term' %}
可以 return 一个按字母顺序排序的对象,我可以用 for
循环对其进行迭代。
但是 sort
过滤器区分大小写 - 小写条目排在所有大写或大写术语之后。
Liquid 4.0.0 添加了一个 sort_natural
过滤器来满足我的要求,但是 Github Pages 目前运行的是 3.0.6,所以我需要一个解决方法。
我的问题是我怎样才能:
- 在 Liquid 模板中获取 site.data.glossary?
- 操作每个条目的第一个映射的字符串值?
- (即使用
capitalize
字符串过滤器消除 uppercase/lowercase 差异)
- 使用本地字符串过滤值对整个地图进行排序?
- 奖励:如果我仍然可以使用保留原始大小写的源字符串值,以便在生成的 html 中进行最终显示。
例如,给定以下 data/glossary.yml
:
- term: apricot
loc: plastic
- term: Apple
loc: basket
- term: Banana
loc: basket
- term: bowtie
loc: closet
- term: Cat
loc: outside
如何创建一个本地 Liquid 对象变量来排序和显示以下内容?:
- 苹果
- 购物篮
- 杏色
- 塑料
- 香蕉
- 购物篮
- 领结
- 壁橱
- 猫
- 外面
唯一的方法是使用将实现 liquid 4 的过滤器插件natural_sort。
一些剪切和过去之后你有 _plugins/natural_sort_filter.rb :
module Jekyll
module SortNatural
# Sort elements of an array ignoring case if strings
# provide optional property with which to sort an array of hashes or drops
def sort_natural(input, property = nil)
ary = InputIterator.new(input)
if property.nil?
ary.sort { |a, b| a.casecmp(b) }
elsif ary.empty? # The next two cases assume a non-empty array.
[]
elsif ary.first.respond_to?(:[]) && !ary.first[property].nil?
ary.sort { |a, b| a[property].casecmp(b[property]) }
end
end
class InputIterator
include Enumerable
def initialize(input)
@input = if input.is_a?(Array)
input.flatten
elsif input.is_a?(Hash)
[input]
elsif input.is_a?(Enumerable)
input
else
Array(input)
end
end
def join(glue)
to_a.join(glue)
end
def concat(args)
to_a.concat(args)
end
def reverse
reverse_each.to_a
end
def uniq(&block)
to_a.uniq(&block)
end
def compact
to_a.compact
end
def empty?
@input.each { return false }
true
end
def each
@input.each do |e|
yield(e.respond_to?(:to_liquid) ? e.to_liquid : e)
end
end
end
end
end
Liquid::Template.register_filter(Jekyll::SortNatural)
这个新过滤器可以这样使用:
{% assign glossary = site.data.glossary | sort_natural: 'term' %}
<ul>
{% for item in glossary %}
<li>{{ item.term }} - {{ item.loc }}</li>
{% endfor %}
</ul>
我正在为部署在 Github 页面上的 Jekyll 站点制作词汇表模板。
条目来自 _data/glossary.yml
文件。
我希望模板按字母顺序排列条目,而不考虑 glossary.yml
.
使用 {% assign glossary = site.data.glossary | sort 'term' %}
可以 return 一个按字母顺序排序的对象,我可以用 for
循环对其进行迭代。
但是 sort
过滤器区分大小写 - 小写条目排在所有大写或大写术语之后。
Liquid 4.0.0 添加了一个 sort_natural
过滤器来满足我的要求,但是 Github Pages 目前运行的是 3.0.6,所以我需要一个解决方法。
我的问题是我怎样才能:
- 在 Liquid 模板中获取 site.data.glossary?
- 操作每个条目的第一个映射的字符串值?
- (即使用
capitalize
字符串过滤器消除 uppercase/lowercase 差异)
- (即使用
- 使用本地字符串过滤值对整个地图进行排序?
- 奖励:如果我仍然可以使用保留原始大小写的源字符串值,以便在生成的 html 中进行最终显示。
例如,给定以下 data/glossary.yml
:
- term: apricot
loc: plastic
- term: Apple
loc: basket
- term: Banana
loc: basket
- term: bowtie
loc: closet
- term: Cat
loc: outside
如何创建一个本地 Liquid 对象变量来排序和显示以下内容?:
- 苹果
- 购物篮
- 杏色
- 塑料
- 香蕉
- 购物篮
- 领结
- 壁橱
- 猫
- 外面
唯一的方法是使用将实现 liquid 4 的过滤器插件natural_sort。
一些剪切和过去之后你有 _plugins/natural_sort_filter.rb :
module Jekyll
module SortNatural
# Sort elements of an array ignoring case if strings
# provide optional property with which to sort an array of hashes or drops
def sort_natural(input, property = nil)
ary = InputIterator.new(input)
if property.nil?
ary.sort { |a, b| a.casecmp(b) }
elsif ary.empty? # The next two cases assume a non-empty array.
[]
elsif ary.first.respond_to?(:[]) && !ary.first[property].nil?
ary.sort { |a, b| a[property].casecmp(b[property]) }
end
end
class InputIterator
include Enumerable
def initialize(input)
@input = if input.is_a?(Array)
input.flatten
elsif input.is_a?(Hash)
[input]
elsif input.is_a?(Enumerable)
input
else
Array(input)
end
end
def join(glue)
to_a.join(glue)
end
def concat(args)
to_a.concat(args)
end
def reverse
reverse_each.to_a
end
def uniq(&block)
to_a.uniq(&block)
end
def compact
to_a.compact
end
def empty?
@input.each { return false }
true
end
def each
@input.each do |e|
yield(e.respond_to?(:to_liquid) ? e.to_liquid : e)
end
end
end
end
end
Liquid::Template.register_filter(Jekyll::SortNatural)
这个新过滤器可以这样使用:
{% assign glossary = site.data.glossary | sort_natural: 'term' %}
<ul>
{% for item in glossary %}
<li>{{ item.term }} - {{ item.loc }}</li>
{% endfor %}
</ul>