From 0d1586a5c471d322a79177e3e9c2f5813c697c32 Mon Sep 17 00:00:00 2001 From: Will Norris Date: Sat, 28 Feb 2015 22:23:08 -0800 Subject: [PATCH] Improved permalinks for pages and collections This updates the default permalink style for pages and collections to match the site-wide 'permalink' setting. If the permalink setting contains a trailing slash, either explicitly or by being set to ':pretty', then pages and collections permalinks will contain trailing slashes by default as well. Similarly, if the permalink setting contains a trailing ':output_ext', so will pages and collections. If the permalink setting contains neither a trailing slash or extension, neither will pages or collections. This impacts only the default permalink structure for pages and collections. Permalinks set in the frontmatter of an individual page take precedence, as does the permalink setting for a specific collection. Fixes #2691 --- lib/jekyll/collection.rb | 4 ++- lib/jekyll/page.rb | 14 ++++------- lib/jekyll/utils.rb | 40 +++++++++++++++++++++++++++++ test/test_document.rb | 26 ++++++++++++++++++- test/test_page.rb | 54 +++++++++++++++++++++++++++++++++++++++- test/test_utils.rb | 14 +++++++++++ 6 files changed, 140 insertions(+), 12 deletions(-) diff --git a/lib/jekyll/collection.rb b/lib/jekyll/collection.rb index b09a7ed9..e8740cf6 100644 --- a/lib/jekyll/collection.rb +++ b/lib/jekyll/collection.rb @@ -170,7 +170,9 @@ module Jekyll # # Returns the URL template to render collection's documents at. def url_template - metadata.fetch('permalink', "/:collection/:path:output_ext") + metadata.fetch('permalink') do + Utils.add_permalink_suffix("/:collection/:path", site.permalink_style) + end end # Extract options for this collection from the site configuration. diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index ca824245..a4ddb698 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -63,16 +63,12 @@ module Jekyll # # Returns the template String. def template - if site.permalink_style == :pretty - if index? && html? - "/:path/" - elsif html? - "/:path/:basename/" - else - "/:path/:basename:output_ext" - end - else + if !html? "/:path/:basename:output_ext" + elsif index? + "/:path/" + else + Utils.add_permalink_suffix("/:path/:basename", site.permalink_style) end end diff --git a/lib/jekyll/utils.rb b/lib/jekyll/utils.rb index bba8b148..39302790 100644 --- a/lib/jekyll/utils.rb +++ b/lib/jekyll/utils.rb @@ -158,5 +158,45 @@ module Jekyll downcase end + # Add an appropriate suffix to template so that it matches the specified + # permalink style. + # + # template - permalink template without trailing slash or file extension + # permalink_style - permalink style, either built-in or custom + # + # The returned permalink template will use the same ending style as + # specified in permalink_style. For example, if permalink_style contains a + # trailing slash (or is :pretty, which indirectly has a trailing slash), + # then so will the returned template. If permalink_style has a trailing + # ":output_ext" (or is :none, :date, or :ordinal) then so will the returned + # template. Otherwise, template will be returned without modification. + # + # Examples: + # add_permalink_suffix("/:basename", :pretty) + # # => "/:basename/" + # + # add_permalink_suffix("/:basename", :date) + # # => "/:basename:output_ext" + # + # add_permalink_suffix("/:basename", "/:year/:month/:title/") + # # => "/:basename/" + # + # add_permalink_suffix("/:basename", "/:year/:month/:title") + # # => "/:basename" + # + # Returns the updated permalink template + def add_permalink_suffix(template, permalink_style) + case permalink_style + when :pretty + template << "/" + when :date, :ordinal, :none + template << ":output_ext" + else + template << "/" if permalink_style.to_s.end_with?("/") + template << ":output_ext" if permalink_style.to_s.end_with?(":output_ext") + end + template + end + end end diff --git a/test/test_document.rb b/test/test_document.rb index 56d6a671..f8b9db66 100644 --- a/test/test_document.rb +++ b/test/test_document.rb @@ -219,7 +219,31 @@ class TestDocument < JekyllUnitTest assert_equal "/slides/test/example-slide-1", @document.url end - should "produce the right destination" do + should "produce the right destination file" do + assert_equal @dest_file, @document.destination(dest_dir) + end + end + + context "a document in a collection with pretty permalink style" do + setup do + @site = fixture_site({ + "collections" => { + "slides" => { + "output" => true, + } + }, + }) + @site.permalink_style = :pretty + @site.process + @document = @site.collections["slides"].docs[0] + @dest_file = dest_dir("slides/example-slide-1/index.html") + end + + should "produce the right URL" do + assert_equal "/slides/example-slide-1/", @document.url + end + + should "produce the right destination file" do assert_equal @dest_file, @document.destination(dest_dir) end end diff --git a/test/test_page.rb b/test/test_page.rb index 9918442f..1e4d3da6 100644 --- a/test/test_page.rb +++ b/test/test_page.rb @@ -46,7 +46,7 @@ class TestPage < JekyllUnitTest should "create index url based on filename" do @page = setup_page('/contacts', 'index.html') - assert_equal "/contacts/index.html", @page.url + assert_equal "/contacts/", @page.url end end @@ -129,6 +129,58 @@ class TestPage < JekyllUnitTest end end + context "with date permalink style" do + setup do + @site.permalink_style = :date + end + + should "return url and destination correctly" do + @page = setup_page('contacts.html') + @dest_file = dest_dir("contacts.html") + assert_equal '/contacts.html', @page.url + assert_equal @dest_file, @page.destination(dest_dir) + end + end + + context "with custom permalink style with trailing slash" do + setup do + @site.permalink_style = "/:title/" + end + + should "return url and destination correctly" do + @page = setup_page('contacts.html') + @dest_file = dest_dir("contacts/index.html") + assert_equal '/contacts/', @page.url + assert_equal @dest_file, @page.destination(dest_dir) + end + end + + context "with custom permalink style with file extension" do + setup do + @site.permalink_style = "/:title:output_ext" + end + + should "return url and destination correctly" do + @page = setup_page('contacts.html') + @dest_file = dest_dir("contacts.html") + assert_equal '/contacts.html', @page.url + assert_equal @dest_file, @page.destination(dest_dir) + end + end + + context "with custom permalink style with no extension" do + setup do + @site.permalink_style = "/:title" + end + + should "return url and destination correctly" do + @page = setup_page('contacts.html') + @dest_file = dest_dir("contacts.html") + assert_equal '/contacts', @page.url + assert_equal @dest_file, @page.destination(dest_dir) + end + end + context "with any other permalink style" do should "return dir correctly" do @site.permalink_style = nil diff --git a/test/test_utils.rb b/test/test_utils.rb index ddb63d4b..9d4a5a4d 100644 --- a/test/test_utils.rb +++ b/test/test_utils.rb @@ -166,4 +166,18 @@ class TestUtils < JekyllUnitTest end end + context "The \`Utils.add_permalink_suffix\` method" do + should "handle built-in permalink styles" do + assert_equal "/:basename/", Utils.add_permalink_suffix("/:basename", :pretty) + assert_equal "/:basename:output_ext", Utils.add_permalink_suffix("/:basename", :date) + assert_equal "/:basename:output_ext", Utils.add_permalink_suffix("/:basename", :ordinal) + assert_equal "/:basename:output_ext", Utils.add_permalink_suffix("/:basename", :none) + end + + should "handle custom permalink styles" do + assert_equal "/:basename/", Utils.add_permalink_suffix("/:basename", "/:title/") + assert_equal "/:basename:output_ext", Utils.add_permalink_suffix("/:basename", "/:title:output_ext") + assert_equal "/:basename", Utils.add_permalink_suffix("/:basename", "/:title") + end + end end