diff --git a/features/embed_filters.feature b/features/embed_filters.feature index 27f5f1df..889a1fc7 100644 --- a/features/embed_filters.feature +++ b/features/embed_filters.feature @@ -73,3 +73,35 @@ Feature: Embed filters Then the _site directory should exist And I should see exactly "Page-2, Page-1" in "_site/page-1.html" And I should see exactly "Page-2, Page-1" in "_site/page-2.html" + + Scenario: Sort pages by the title + Given I have a _layouts directory + And I have the following page: + | title | layout | content | + | Dog | default | Run | + And I have the following page: + | title | layout | content | + | Bird | default | Fly | + And I have the following page: + | layout | content | + | default | Jump | + And I have a default layout that contains "{% assign sorted_pages = site.pages | sort: 'title' %}The rule of {{ sorted_pages.size }}: {% for p in sorted_pages %}{{ p.content | strip_html | strip_newlines }}, {% endfor %}" + When I run jekyll build + Then the _site directory should exist + And I should see exactly "The rule of 3: Jump, Fly, Run," in "_site/bird.html" + + Scenario: Sort pages by the title ordering pages without title last + Given I have a _layouts directory + And I have the following page: + | title | layout | content | + | Dog | default | Run | + And I have the following page: + | title | layout | content | + | Bird | default | Fly | + And I have the following page: + | layout | content | + | default | Jump | + And I have a default layout that contains "{% assign sorted_pages = site.pages | sort: 'title', 'last' %}The rule of {{ sorted_pages.size }}: {% for p in sorted_pages %}{{ p.content | strip_html | strip_newlines }}, {% endfor %}" + When I run jekyll build + Then the _site directory should exist + And I should see exactly "The rule of 3: Fly, Run, Jump," in "_site/bird.html" diff --git a/features/support/env.rb b/features/support/env.rb index 80020690..29875629 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -28,7 +28,11 @@ def run_jekyll(args) end def slug(title) - title.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') + if title + title.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') + else + Time.now.strftime("%s%9N") # nanoseconds since the Epoch + end end def location(folder, direction) diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 997a0f5d..10c1aa41 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -190,6 +190,40 @@ module Jekyll input.select { |object| object[key] == value } end + # Sort an array of objects + # + # input - the object array + # key - key within each object to filter by + # nils ('first' | 'last') - nils appear before or after non-nil values + # + # Returns the filtered array of objects + def sort(input, key = nil, nils = "first") + if key.nil? + input.sort + else + case + when nils == "first" + order = - 1 + when nils == "last" + order = + 1 + else + Jekyll.logger.error "Invalid nils order:", + "'#{nils}' is not a valid nils order. It must be 'first' or 'last'." + exit(1) + end + + input.sort { |a, b| + if !a[key].nil? && b[key].nil? + - order + elsif a[key].nil? && !b[key].nil? + + order + else + a[key] <=> b[key] + end + } + end + end + private def time(input) case input diff --git a/site/docs/templates.md b/site/docs/templates.md index 12ae5d41..820e108a 100644 --- a/site/docs/templates.md +++ b/site/docs/templates.md @@ -210,6 +210,23 @@ common tasks easier.
+Sort
+Sort an array. Optional arguments for hashes: 1. property name 2. nils order (first or last).
+
+ {% raw %}{{ page.tags | sort }}{% endraw %}
+
+ {% raw %}{{ site.posts | sort: 'author' }}{% endraw %}
+
+ {% raw %}{{ site.pages | sort: 'title', 'last' }}{% endraw %}
+