From f4fcfbdaa02e11777fa776ed9e29341f4efefb79 Mon Sep 17 00:00:00 2001 From: Kelly-Ann Green Date: Mon, 9 Jul 2018 01:25:32 -0400 Subject: [PATCH] Update item_property to return numbers as numbers instead of strings (#6608) Merge pull request 6608 --- lib/jekyll/filters.rb | 25 ++++++++++++++++--------- test/test_filters.rb | 16 ++++++++++++---- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 2a390f06..ed8c3163 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -299,16 +299,16 @@ module Jekyll # We also utilize the Schwartzian transform to make this more efficient. def sort_input(input, property, order) input.map { |item| [item_property(item, property), item] } - .sort! do |apple_info, orange_info| - apple_property = apple_info.first - orange_property = orange_info.first + .sort! do |a_info, b_info| + a_property = a_info.first + b_property = b_info.first - if !apple_property.nil? && orange_property.nil? + if !a_property.nil? && b_property.nil? - order - elsif apple_property.nil? && !orange_property.nil? + elsif a_property.nil? && !b_property.nil? + order else - apple_property <=> orange_property + a_property <=> b_property || a_property.to_s <=> b_property.to_s end end .map!(&:last) @@ -317,15 +317,22 @@ module Jekyll def item_property(item, property) if item.respond_to?(:to_liquid) property.to_s.split(".").reduce(item.to_liquid) do |subvalue, attribute| - subvalue[attribute] + parse_sort_input(subvalue[attribute]) end elsif item.respond_to?(:data) - item.data[property.to_s] + parse_sort_input(item.data[property.to_s]) else - item[property.to_s] + parse_sort_input(item[property.to_s]) end end + # return numeric values as numbers for proper sorting + def parse_sort_input(property) + number_like = %r!\A\s*-?(?:\d+\.?\d*|\.\d+)\s*\Z! + return property.to_f if property =~ number_like + property + end + def as_liquid(item) case item when Hash diff --git a/test/test_filters.rb b/test/test_filters.rb index a3dd142a..ef9cbaaa 100644 --- a/test/test_filters.rb +++ b/test/test_filters.rb @@ -1074,10 +1074,6 @@ class TestFilters < JekyllUnitTest end should "return sorted strings" do assert_equal %w(10 2), @filter.sort(%w(10 2)) - assert_equal( - [{ "a" => "10" }, { "a" => "2" }], - @filter.sort([{ "a" => "10" }, { "a" => "2" }], "a") - ) assert_equal %w(FOO Foo foo), @filter.sort(%w(foo Foo FOO)) assert_equal %w(_foo foo foo_), @filter.sort(%w(foo_ _foo foo)) # Cyrillic @@ -1090,6 +1086,18 @@ class TestFilters < JekyllUnitTest assert_equal [{ "a" => 1 }, { "a" => 2 }, { "a" => 3 }, { "a" => 4 }], @filter.sort([{ "a" => 4 }, { "a" => 3 }, { "a" => 1 }, { "a" => 2 }], "a") end + should "return sorted by property array with numeric strings sorted as numbers" do + assert_equal([{ "a" => ".5" }, { "a" => "0.65" }, { "a" => "10" }], + @filter.sort([{ "a" => "10" }, { "a" => ".5" }, { "a" => "0.65" }], "a")) + end + should "return sorted by property array with numeric strings first" do + assert_equal([{ "a" => ".5" }, { "a" => "0.6" }, { "a" => "twelve" }], + @filter.sort([{ "a" => "twelve" }, { "a" => ".5" }, { "a" => "0.6" }], "a")) + end + should "return sorted by property array with numbers and strings " do + assert_equal([{ "a" => "1" }, { "a" => "1abc" }, { "a" => "20" }], + @filter.sort([{ "a" => "20" }, { "a" => "1" }, { "a" => "1abc" }], "a")) + end should "return sorted by property array with nils first" do ary = [{ "a" => 2 }, { "b" => 1 }, { "a" => 1 }] assert_equal [{ "b" => 1 }, { "a" => 1 }, { "a" => 2 }], @filter.sort(ary, "a")