Concatenate arrays in liquid

2020-04-10 04:33发布

问题:

I am trying to concatenate three arrays in liquid/jekyll but in the final array (publications) I get only the elements of the first one (papers)

{% assign papers = (site.publications | where:"type","paper" | sort: 'date') | reverse %}
{% assign posters = (site.publications | where:"type","poster" | sort: 'date') | reverse %}
{% assign abstracts = (site.publications | where:"type","abstract" | sort: 'date') | reverse %}
{% assign publications = papers | concat: posters | concat: abstracts %}

What am I missing?

回答1:

New answer

Jekyll now uses Liquid 4.x. So we can use the concat filter !

Old answer

concat filter is not part of current liquid gem (3.0.6) used by jekyll 3.2.1.

It will only be available in liquid 4 (https://github.com/Shopify/liquid/blob/v4.0.0.rc3/lib/liquid/standardfilters.rb#L218).

I will probably be available for Jekyll 4.

In the meantime, this plugin can do the job :

=begin
  Jekyll filter to concatenate arrays
  Usage:
    {% assign result = array-1 | concatArray: array-2 %}
=end
module Jekyll
  module ConcatArrays

    # copied from https://github.com/Shopify/liquid/blob/v4.0.0.rc3/lib/liquid/standardfilters.rb
    def concat(input, array)
      unless array.respond_to?(:to_ary)
        raise ArgumentError.new("concat filter requires an array argument")
      end
      InputIterator.new(input).concat(array)
    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 concat(args)
        to_a.concat(args)
      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::ConcatArrays)


标签: jekyll liquid