always include file extension on destination files

This ensures that destination files for HTML posts, pages and
collections always include the proper file extension (as defined by
output_ext) regardless of permalink structure.  This allows for URLs
that contain no extension or trailing slash to still result in proper
destination files with .html extensions.

Because this change relies so heavily on output_ext accurately
identifying the extension of the destination file, this change also
removes the feature test that tested support for permalinks with a .htm
extension.  In order to support alternate file extensions, a future
patch or plugin will need to modify the output_ext value, at which point
everything else should work as expected.
This commit is contained in:
Will Norris 2015-02-21 19:51:28 -08:00
parent 8917ef011c
commit 669c803912
10 changed files with 64 additions and 18 deletions

View File

@ -83,13 +83,3 @@ Feature: Fancy permalinks
Then the _site directory should exist Then the _site directory should exist
And the _site/custom/posts directory should exist And the _site/custom/posts directory should exist
And I should see "bla bla" in "_site/custom/posts/some.html" And I should see "bla bla" in "_site/custom/posts/some.html"
Scenario: Use per-post ending in .htm
Given I have a _posts directory
And I have the following post:
| title | date | permalink | content |
| Some post | 2013-04-14 | /custom/posts/some.htm | bla bla |
When I run jekyll build
Then the _site directory should exist
And the _site/custom/posts directory should exist
And I should see "bla bla" in "_site/custom/posts/some.htm"

View File

@ -4,7 +4,7 @@ module Jekyll
class Document class Document
include Comparable include Comparable
attr_reader :path, :site, :extname attr_reader :path, :site, :extname, :output_ext
attr_accessor :content, :collection, :output attr_accessor :content, :collection, :output
YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
@ -19,6 +19,7 @@ module Jekyll
@site = relations[:site] @site = relations[:site]
@path = path @path = path
@extname = File.extname(path) @extname = File.extname(path)
@output_ext = Jekyll::Renderer.new(site, self).output_ext
@collection = relations[:collection] @collection = relations[:collection]
@has_yaml_header = nil @has_yaml_header = nil
end end
@ -130,7 +131,7 @@ module Jekyll
{ {
collection: collection.label, collection: collection.label,
path: cleaned_relative_path, path: cleaned_relative_path,
output_ext: Jekyll::Renderer.new(site, self).output_ext, output_ext: output_ext,
name: Utils.slugify(basename_without_ext), name: Utils.slugify(basename_without_ext),
title: Utils.slugify(data['slug']) || Utils.slugify(basename_without_ext) title: Utils.slugify(data['slug']) || Utils.slugify(basename_without_ext)
} }
@ -164,6 +165,7 @@ module Jekyll
dest = site.in_dest_dir(base_directory) dest = site.in_dest_dir(base_directory)
path = site.in_dest_dir(dest, URL.unescape_path(url)) path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if url.end_with?("/") path = File.join(path, "index.html") if url.end_with?("/")
path << output_ext unless path.end_with?(output_ext)
path path
end end

View File

@ -142,6 +142,7 @@ module Jekyll
def destination(dest) def destination(dest)
path = site.in_dest_dir(dest, URL.unescape_path(url)) path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if url.end_with?("/") path = File.join(path, "index.html") if url.end_with?("/")
path << output_ext unless path.end_with?(output_ext)
path path
end end

View File

@ -280,6 +280,7 @@ module Jekyll
# The url needs to be unescaped in order to preserve the correct filename # The url needs to be unescaped in order to preserve the correct filename
path = site.in_dest_dir(dest, URL.unescape_path(url)) path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if self.url.end_with?("/") path = File.join(path, "index.html") if self.url.end_with?("/")
path << output_ext unless path.end_with?(output_ext)
path path
end end

View File

@ -0,0 +1,7 @@
---
layout: ~
title: Extensionless Permalink
permalink: /:title
---
{{ page.url }}

View File

@ -1,6 +1,6 @@
--- ---
title: Deal with dots title: Deal with dots
permalink: /deal.with.dots/ permalink: /deal.with.dots
--- ---
Let's test if jekyll deals properly with dots. Let's test if jekyll deals properly with dots.

View File

@ -212,11 +212,16 @@ class TestDocument < JekyllUnitTest
}) })
@site.process @site.process
@document = @site.collections["slides"].docs[0] @document = @site.collections["slides"].docs[0]
@dest_file = dest_dir("slides/test/example-slide-1.html")
end end
should "produce the right URL" do should "produce the right URL" do
assert_equal "/slides/test/example-slide-1", @document.url assert_equal "/slides/test/example-slide-1", @document.url
end end
should "produce the right destination" do
assert_equal @dest_file, @document.destination(dest_dir)
end
end end
context "documents in a collection with custom title permalinks" do context "documents in a collection with custom title permalinks" do
@ -238,14 +243,26 @@ class TestDocument < JekyllUnitTest
should "produce the right URL if they have a slug" do should "produce the right URL if they have a slug" do
assert_equal "/slides/so-what-is-jekyll-exactly", @document.url assert_equal "/slides/so-what-is-jekyll-exactly", @document.url
end end
should "produce the right destination file if they have a slug" do
dest_file = dest_dir("slides/so-what-is-jekyll-exactly.html")
assert_equal dest_file, @document.destination(dest_dir)
end
should "produce the right URL if they don't have a slug" do should "produce the right URL if they don't have a slug" do
assert_equal "/slides/example-slide-5", @document_without_slug.url assert_equal "/slides/example-slide-5", @document_without_slug.url
end end
should "produce the right destination file if they don't have a slug" do
dest_file = dest_dir("slides/example-slide-5.html")
assert_equal dest_file, @document_without_slug.destination(dest_dir)
end
should "produce the right URL if they have a wild slug" do should "produce the right URL if they have a wild slug" do
assert_equal "/slides/well-so-what-is-jekyll-then", @document_with_strange_slug.url assert_equal "/slides/well-so-what-is-jekyll-then", @document_with_strange_slug.url
end end
should "produce the right destination file if they have a wild slug" do
dest_file = dest_dir("/slides/well-so-what-is-jekyll-then.html")
assert_equal dest_file, @document_with_strange_slug.destination(dest_dir)
end
end end
context "documents in a collection" do context "documents in a collection" do

View File

@ -14,7 +14,7 @@ class TestGeneratedSite < JekyllUnitTest
end end
should "ensure post count is as expected" do should "ensure post count is as expected" do
assert_equal 47, @site.posts.size assert_equal 48, @site.posts.size
end end
should "insert site.posts into the index" do should "insert site.posts into the index" do

View File

@ -57,7 +57,11 @@ class TestPage < JekyllUnitTest
should "deal properly with dots" do should "deal properly with dots" do
@page = setup_page('deal.with.dots.html') @page = setup_page('deal.with.dots.html')
@dest_file = dest_dir("deal.with.dots.html")
assert_equal "deal.with.dots", @page.basename assert_equal "deal.with.dots", @page.basename
assert_equal "/deal.with.dots", @page.url
assert_equal @dest_file, @page.destination(dest_dir)
end end
should "make properties accessible through #[]" do should "make properties accessible through #[]" do
@ -83,14 +87,18 @@ class TestPage < JekyllUnitTest
end end
end end
context "with pretty url style" do context "with pretty permalink style" do
setup do setup do
@site.permalink_style = :pretty @site.permalink_style = :pretty
end end
should "return dir correctly" do should "return dir, url, and destination correctly" do
@page = setup_page('contacts.html') @page = setup_page('contacts.html')
@dest_file = dest_dir("contacts/index.html")
assert_equal '/contacts/', @page.dir assert_equal '/contacts/', @page.dir
assert_equal '/contacts/', @page.url
assert_equal @dest_file, @page.destination(dest_dir)
end end
should "return dir correctly for index page" do should "return dir correctly for index page" do
@ -121,7 +129,7 @@ class TestPage < JekyllUnitTest
end end
end end
context "with any other url style" do context "with any other permalink style" do
should "return dir correctly" do should "return dir correctly" do
@site.permalink_style = nil @site.permalink_style = nil
@page = setup_page('contacts.html') @page = setup_page('contacts.html')
@ -179,7 +187,7 @@ class TestPage < JekyllUnitTest
page.write(dest_dir) page.write(dest_dir)
assert File.directory?(dest_dir) assert File.directory?(dest_dir)
assert File.exist?(File.join(dest_dir, '+', 'plus+in+url')) assert File.exist?(File.join(dest_dir, '+', 'plus+in+url.html'))
end end
should "write even when permalink has '%# +'" do should "write even when permalink has '%# +'" do

View File

@ -659,6 +659,26 @@ class TestPost < JekyllUnitTest
assert File.exist?(File.join(dest_dir, 'foo-bar', 'index.html')) assert File.exist?(File.join(dest_dir, 'foo-bar', 'index.html'))
end end
should "write properly with extensionless site permalink" do
post = setup_post("2008-10-18-foo-bar.markdown")
post.site.permalink_style = ":title"
do_render(post)
post.write(dest_dir)
assert File.directory?(dest_dir)
assert File.exist?(File.join(dest_dir, 'foo-bar.html'))
end
should "write properly with extensionless post permalink" do
post = setup_post("2015-02-20-extensionless-permalink.markdown")
do_render(post)
post.write(dest_dir)
assert File.directory?(dest_dir)
assert File.exist?(File.join(dest_dir, 'extensionless-permalink.html'))
assert_equal "<p>/extensionless-permalink</p>\n", post.content
end
should "insert data" do should "insert data" do
post = setup_post("2008-11-21-complex.markdown") post = setup_post("2008-11-21-complex.markdown")
do_render(post) do_render(post)