diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 95ada0bd..8c7fa595 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -100,7 +100,7 @@ module Jekyll def cgi_escape(input) CGI::escape(input) end - + # URI escape a string. # # input - The String to escape. @@ -158,6 +158,31 @@ module Jekyll input.to_json end + + # Group an array of items by a property + # + # input - the inputted Enumerable + # property - the property + # + # Returns an array of Hashes, each looking something like this: + # {"name" => "larry" + # "items" => [...] } # all the items where `property` == "larry" + def group_by(input, property) + if groupable?(input) + input.group_by do |item| + if item.respond_to?(:data) + item.data[property.to_s].to_s + else + item[property.to_s].to_s + end + end.inject([]) do |memo, i| + memo << {"name" => i.first, "items" => i.last} + end + else + input + end + end + private def time(input) case input @@ -170,5 +195,9 @@ module Jekyll exit(1) end end + + def groupable?(element) + element.respond_to?(:group_by) + end end end diff --git a/test/test_filters.rb b/test/test_filters.rb index 28e9612d..304c9fca 100644 --- a/test/test_filters.rb +++ b/test/test_filters.rb @@ -3,16 +3,17 @@ require 'helper' class TestFilters < Test::Unit::TestCase class JekyllFilter include Jekyll::Filters + attr_accessor :site, :context - def initialize - site = Jekyll::Site.new(Jekyll.configuration({})) - @context = Liquid::Context.new({}, {}, { :site => site }) + def initialize(opts = {}) + @site = Jekyll::Site.new(Jekyll.configuration(opts)) + @context = Liquid::Context.new({}, {}, { :site => @site }) end end context "filters" do setup do - @filter = JekyllFilter.new + @filter = JekyllFilter.new({"source" => source_dir, "destination" => dest_dir}) @sample_time = Time.utc(2013, 03, 27, 11, 22, 33) @time_as_string = "September 11, 2001 12:46:30 -0000" end @@ -109,5 +110,26 @@ class TestFilters < Test::Unit::TestCase assert_equal "[{\"name\":\"Jack\"},{\"name\":\"Smith\"}]", @filter.jsonify([{:name => 'Jack'}, {:name => 'Smith'}]) end end + + context "group_by filter" do + should "successfully group array of Jekyll::Page's" do + @filter.site.process + grouping = @filter.group_by(@filter.site.pages, "layout") + grouping.each do |g| + assert ["default", "nil", ""].include?(g["name"]), "#{g['name']} isn't a valid grouping." + case g["name"] + when "default" + assert g["items"].is_a?(Array), "The list of grouped items for 'default' is not an Array." + assert_equal 3, g["items"].size + when "nil" + assert g["items"].is_a?(Array), "The list of grouped items for 'nil' is not an Array." + assert_equal 2, g["items"].size + when "" + assert g["items"].is_a?(Array), "The list of grouped items for '' is not an Array." + assert_equal 5, g["items"].size + end + end + end + end end end