使用Liquid获取,操作和排序哈希对象值

时间:2016-07-10 04:15:01

标签: ruby jekyll liquid

我正在为Github Pages上部署的Jekyll网站制作词汇表模板 条目是从_data/glossary.yml文件中提取的 我希望模板按字母顺序排列条目,而不管glossary.yml中的数据顺序如何。

使用{% assign glossary = site.data.glossary | sort 'term' %}会返回按字母顺序排序的对象,我可以使用for循环进行迭代。
但是sort过滤器区分大小写 - 小写条目在所有大写或大写术语之后排序。

Liquid 4.0.0添加了一个sort_natural过滤器,可以满足我的需求,但Github Pages目前运行3.0.6,所以我需要一个解决方法。

我的问题是如何:

  1. 在Liquid模板中获取site.data.glossary?
  2. 操纵每个条目的第一个地图的字符串值?
    • (即使用capitalize字符串过滤器来消除大写/小写的差异)
  3. 使用本地字符串过滤值对整个地图进行排序?
  4. Bonus:如果我仍然可以使用源字符串值保留其原始案例,以便在生成的html中进行最终显示。
  5. 例如,给定以下data/glossary.yml

    - term: apricot
      loc: plastic
    
    - term: Apple
      loc: basket
    
    - term: Banana
      loc: basket
    
    - term: bowtie
      loc: closet
    
    - term: Cat
      loc: outside
    

    如何创建一个本地Liquid对象变量来排序并显示以下内容?:

    • 苹果
      • 塑料
    • 香蕉
    • 领结
      • 壁橱

1 个答案:

答案 0 :(得分:2)

唯一的方法是使用一个过滤器插件来实现液体4 natural_sort

有些剪切和过去之后你有 _plugins / natural_sort_filter.rb

scratch

这个新过滤器可以像这样使用:

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)