# This is a possible alternate solution to Jekyll #6364. # All of these procs are translations of methods from Jekyll::Filters. # Only item_property has been modified. require "liquid" input = { "government" => ["one post", "two post"], "tech" => ["three post"], "lol" => [1,2,3] } as_liquid = -> (item) { case item when Hash pairs = item.map { |k, v| as_liquid.([k, v]) } Hash[pairs] when Array item.map { |i| as_liquid.(i) } else if item.respond_to?(:to_liquid) liquidated = item.to_liquid # prevent infinite recursion for simple types (which return `self`) if liquidated == item item else as_liquid.(liquidated) end else item end end } item_property = -> (item, property) { if item.respond_to?(:to_liquid) property.to_s.split(".").reduce(item.to_liquid) do |subvalue, attribute| p attribute liquid = as_liquid.(subvalue) liquid.respond_to?(attribute) ? liquid.public_send(attribute) : liquid[attribute] end elsif item.respond_to?(:data) item.data[property.to_s] else item[property.to_s] end } sort_input = -> (input, property, order) { interim = input.map { |item| [item_property.(item, property), item] } p interim interim.sort! do |apple_info, orange_info| apple_property = apple_info.first orange_property = orange_info.first if !apple_property.nil? && orange_property.nil? - order elsif apple_property.nil? && !orange_property.nil? + order else apple_property <=> orange_property end end .map!(&:last) } sort = -> (input, property = nil, nils = "first") { if input.nil? raise ArgumentError, "Cannot sort a null object." end if property.nil? input.sort else if nils == "first" order = - 1 elsif nils == "last" order = + 1 else raise ArgumentError, "Invalid nils order: " \ "'#{nils}' is not a valid nils order. It must be 'first' or 'last'." end sort_input.(input, property, order) end } p input p sort.(input, "last.length")