diff --git a/features/permalinks.feature b/features/permalinks.feature index 9bd7c848..8e50ee72 100644 --- a/features/permalinks.feature +++ b/features/permalinks.feature @@ -23,6 +23,15 @@ Feature: Fancy permalinks Then the _site directory should exist And I should see "Totally wordpress." in "_site/2009/03/27/pretty-permalink-schema/index.html" + Scenario: Use pretty permalink schema for pages + Given I have an "index.html" page that contains "Totally index" + And I have an "awesome.html" page that contains "Totally awesome" + And I have a configuration file with "permalink" set to "pretty" + When I run jekyll + Then the _site directory should exist + And I should see "Totally index" in "_site/index.html" + And I should see "Totally awesome" in "_site/awesome/index.html" + Scenario: Use custom permalink schema with prefix Given I have a _posts directory And I have the following post: diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index d1411e3d..b3a624f3 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -4,7 +4,7 @@ module Jekyll include Convertible attr_accessor :site - attr_accessor :ext + attr_accessor :name, :ext, :basename attr_accessor :data, :content, :output # Initialize a new Page. @@ -17,14 +17,49 @@ module Jekyll def initialize(site, base, dir, name) @site = site @base = base - @dir = dir + @dir = dir @name = name self.data = {} self.process(name) self.read_yaml(File.join(base, dir), name) - #self.transform + end + + # The generated directory into which the page will be placed + # upon generation. This is derived from the permalink or, if + # permalink is absent, set to '/' + # + # Returns + def dir + url[-1, 1] == '/' ? url : File.dirname(url) + end + + # The full path and filename of the post. + # Defined in the YAML of the post body + # (Optional) + # + # Returns + def permalink + self.data && self.data['permalink'] + end + + def template + if self.site.permalink_style == :pretty && !index? + "/:name/" + else + "/:name.html" + end + end + + # The generated relative url of this page + # e.g. /about.html + # + # Returns + def url + return permalink if permalink + + @url ||= template.gsub(':name', basename) end # Extract information from the page filename @@ -33,6 +68,7 @@ module Jekyll # Returns nothing def process(name) self.ext = File.extname(name) + self.basename = name.split('.')[0..-2].first end # Add any necessary layouts to this post @@ -55,16 +91,24 @@ module Jekyll dest = File.join(dest, dest_suffix) if dest_suffix FileUtils.mkdir_p(dest) - name = @name - if self.ext != "" - name = @name.split(".")[0..-2].join('.') + self.ext + # The url needs to be unescaped in order to preserve the correct filename + path = File.join(dest, CGI.unescape(self.url)) + if self.url[/\.html$/].nil? + FileUtils.mkdir_p(path) + path = File.join(path, "index.html") end - path = File.join(dest, name) File.open(path, 'w') do |f| f.write(self.output) end end + + private + + def index? + basename == 'index' + end + end -end \ No newline at end of file +end diff --git a/test/source/about.html b/test/source/about.html new file mode 100644 index 00000000..a6a79f93 --- /dev/null +++ b/test/source/about.html @@ -0,0 +1,6 @@ +--- +title: About +permalink: /about/ +--- + +About the site diff --git a/test/source/contacts.html b/test/source/contacts.html new file mode 100644 index 00000000..1615afe2 --- /dev/null +++ b/test/source/contacts.html @@ -0,0 +1,5 @@ +--- +title: Contact Information +--- + +Contact Information diff --git a/test/test_generated_site.rb b/test/test_generated_site.rb new file mode 100644 index 00000000..b9eeee24 --- /dev/null +++ b/test/test_generated_site.rb @@ -0,0 +1,43 @@ +require File.dirname(__FILE__) + '/helper' + +class TestGeneratedSite < Test::Unit::TestCase + context "generated sites" do + setup do + clear_dest + stub(Jekyll).configuration do + Jekyll::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir}) + end + + @site = Site.new(Jekyll.configuration) + @site.process + @index = File.read(dest_dir('index.html')) + end + + should "insert site.posts into the index" do + assert @index.include?("#{@site.posts.size} Posts") + end + + should "render post.content" do + latest_post = Dir[source_dir('_posts', '*')].sort.last + post = Post.new(@site, source_dir, '', File.basename(latest_post)) + post.transform + assert @index.include?(post.content) + end + + should "hide unpublished posts" do + published = Dir[dest_dir('publish_test/2008/02/02/*.html')].map {|f| File.basename(f)} + + assert_equal 1, published.size + assert_equal "published.html", published.first + end + + should "not copy _posts directory" do + assert !File.exist?(dest_dir('_posts')) + end + + should "process other static files and generate correct permalinks" do + assert File.exists?(dest_dir('/about/index.html')) + assert File.exists?(dest_dir('/contacts.html')) + end + end +end diff --git a/test/test_page.rb b/test/test_page.rb new file mode 100644 index 00000000..1715d916 --- /dev/null +++ b/test/test_page.rb @@ -0,0 +1,87 @@ +require File.dirname(__FILE__) + '/helper' + +class TestPage < Test::Unit::TestCase + def setup_page(file) + @page = Page.new(@site, source_dir, '', file) + end + + def do_render(page) + layouts = { "default" => Layout.new(@site, source_dir('_layouts'), "simple.html")} + page.render(layouts, {"site" => {"posts" => []}}) + end + + context "A Page" do + setup do + clear_dest + stub(Jekyll).configuration { Jekyll::DEFAULTS } + @site = Site.new(Jekyll.configuration) + end + + context "processing pages" do + should "create url based on filename" do + @page = setup_page('contacts.html') + assert_equal "/contacts.html", @page.url + end + + context "with pretty url style" do + setup do + @site.permalink_style = :pretty + end + + should "return dir correctly" do + @page = setup_page('contacts.html') + assert_equal '/contacts/', @page.dir + end + + should "return dir correctly for index page" do + @page = setup_page('index.html') + assert_equal '/', @page.dir + end + end + + context "with any other url style" do + should "return dir correctly" do + @site.permalink_style = nil + @page = setup_page('contacts.html') + assert_equal '/', @page.dir + end + end + + should "respect permalink in yaml front matter" do + file = "about.html" + @page = setup_page(file) + + assert_equal "/about/", @page.permalink + assert_equal @page.permalink, @page.url + assert_equal "/about/", @page.dir + end + end + + context "rendering" do + setup do + clear_dest + end + + should "write properly" do + page = setup_page('contacts.html') + do_render(page) + page.write(dest_dir) + + assert File.directory?(dest_dir) + assert File.exists?(File.join(dest_dir, 'contacts.html')) + end + + should "write properly without html extension" do + page = setup_page('contacts.html') + page.site.permalink_style = :pretty + do_render(page) + page.write(dest_dir) + + assert File.directory?(dest_dir) + assert File.exists?(File.join(dest_dir, 'contacts', 'index.html')) + end + + end + + end +end