Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --drafts flag #769

Merged
merged 11 commits into from
Mar 4, 2013
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bin/jekyll
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ command :build do |c|

c.option '-w', '--watch', 'Watch for changes and rebuild'
c.option '--lsi', 'Use LSI for improved related posts'
c.option '--drafts', 'Render posts in the _drafts folder'

c.action do |args, options|
options.defaults :serving => false
Expand All @@ -37,6 +38,7 @@ command :serve do |c|

c.option '-w', '--watch', 'Watch for changes and rebuild'
c.option '--lsi', 'Use LSI for improved related posts'
c.option '--drafts', 'Render posts in the _drafts folder'

c.option '-p', '--port [PORT]', 'Port to listen on'
c.option '-h', '--host [HOST]', 'Host to bind to'
Expand Down
25 changes: 25 additions & 0 deletions features/drafts.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Feature: Draft Posts
As a hacker who likes to blog
I want to be able to preview drafts locally
In order to see if they look alright before publishing

Scenario: Preview a draft
Given I have a configuration file with "permalink" set to "none"
And I have a _drafts directory
And I have the following draft:
| title | date | layout | content |
| Recipe | 3/27/2009 | default | Not baked yet. |
When I run jekyll with drafts
Then the _site directory should exist
And I should see "Not baked yet." in "_site/recipe.html"

Scenario: Don't preview a draft
Given I have a configuration file with "permalink" set to "none"
And I have an "index.html" page that contains "Totally index"
And I have a _drafts directory
And I have the following draft:
| title | date | layout | content |
| Recipe | 3/27/2009 | default | Not baked yet. |
When I run jekyll
Then the _site directory should exist
And the "_site/recipe.html" file should not exist
16 changes: 13 additions & 3 deletions features/step_definitions/jekyll_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@
FileUtils.mkdir_p(dir)
end

Given /^I have the following posts?(?: (.*) "(.*)")?:$/ do |direction, folder, table|
Given /^I have the following (draft|post)s?(?: (.*) "(.*)")?:$/ do |status, direction, folder, table|
table.hashes.each do |post|
date = Date.strptime(post['date'], '%m/%d/%Y').strftime('%Y-%m-%d')
title = post['title'].downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-')

if direction && direction == "in"
Expand All @@ -61,7 +60,14 @@
after = folder || '.'
end

path = File.join(before || '.', '_posts', after || '.', "#{date}-#{title}.#{post['type'] || 'textile'}")
ext = post['type'] || 'textile'

if "draft" == status
path = File.join(before || '.', '_drafts', after || '.', "#{title}.#{ext}")
else
date = Date.strptime(post['date'], '%m/%d/%Y').strftime('%Y-%m-%d')
path = File.join(before || '.', '_posts', after || '.', "#{date}-#{title}.#{ext}")
end

matter_hash = {}
%w(title layout tag tags category categories published author).each do |key|
Expand Down Expand Up @@ -117,6 +123,10 @@
run_jekyll
end

When /^I run jekyll with drafts$/ do
run_jekyll(:drafts => true)
end

When /^I debug jekyll$/ do
run_jekyll(:debug => true)
end
Expand Down
3 changes: 2 additions & 1 deletion features/support/env.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
JEKYLL_PATH = File.join(ENV['PWD'], 'bin', 'jekyll')

def run_jekyll(opts = {})
command = JEKYLL_PATH
command = JEKYLL_PATH.clone
command << " build"
command << " --drafts" if opts[:drafts]
command << " >> /dev/null 2>&1" if opts[:debug].nil?
system command
end
Expand Down
1 change: 1 addition & 0 deletions lib/jekyll.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def require_all(path)
require 'jekyll/layout'
require 'jekyll/page'
require 'jekyll/post'
require 'jekyll/draft'
require 'jekyll/filters'
require 'jekyll/static_file'
require 'jekyll/errors'
Expand Down
35 changes: 35 additions & 0 deletions lib/jekyll/draft.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Jekyll

class Draft < Post

# Valid post name regex (no date)
MATCHER = /^(.*)(\.[^.]+)$/

# Draft name validator. Draft filenames must be like:
# my-awesome-post.textile
#
# Returns true if valid, false if not.
def self.valid?(name)
name =~ MATCHER
end

# Get the full path to the directory containing the draft files
def get_base(source, dir)
return File.join(source, dir, '_drafts')
end

# Extract information from the post filename.
#
# name - The String filename of the post file.
#
# Returns nothing.
def process(name)
m, slug, ext = *name.match(MATCHER)
self.date = File.mtime(File.join(@base, name))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

self.slug = slug
self.ext = ext
end

end

end
8 changes: 6 additions & 2 deletions lib/jekyll/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ def self.valid?(name)
# site - The Site.
# base - The String path to the dir containing the post file.
# name - The String filename of the post file.
# categories - An Array of Strings for the categories for this post.
#
# Returns the new Post.
def initialize(site, source, dir, name)
@site = site
@base = File.join(source, dir, '_posts')
@base = self.get_base(source, dir)
@name = name

self.categories = dir.split('/').reject { |x| x.empty? }
Expand Down Expand Up @@ -66,6 +65,11 @@ def initialize(site, source, dir, name)
end
end

# Get the full path to the directory containing the post files
def get_base(source, dir)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps containing_dir, dirname or something similar here. Ruby idioms tend to disagree with get_- and set_-prefixed methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea.

return File.join(source, dir, '_posts')
end

# Read the YAML frontmatter.
#
# base - The String path to the dir containing the file.
Expand Down
40 changes: 34 additions & 6 deletions lib/jekyll/site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Site
attr_accessor :config, :layouts, :posts, :pages, :static_files,
:categories, :exclude, :include, :source, :dest, :lsi, :pygments,
:permalink_style, :tags, :time, :future, :safe, :plugins, :limit_posts,
:keep_files
:show_drafts, :keep_files

attr_accessor :converters, :generators

Expand All @@ -26,6 +26,7 @@ def initialize(config)
self.exclude = config['exclude'] || []
self.include = config['include'] || []
self.future = config['future']
self.show_drafts = config['drafts'] || nil
self.limit_posts = config['limit_posts'] || nil
self.keep_files = config['keep_files'] || []

Expand Down Expand Up @@ -138,6 +139,18 @@ def read_directories(dir = '')

self.read_posts(dir)

if self.show_drafts
self.read_drafts(dir)
end

self.posts.sort!

# limit the posts if :limit_posts option is set
if limit_posts
limit = self.posts.length < limit_posts ? self.posts.length : limit_posts
self.posts = self.posts[-limit, limit]
end

entries.each do |f|
f_abs = File.join(base, f)
f_rel = File.join(dir, f)
Expand Down Expand Up @@ -180,13 +193,28 @@ def read_posts(dir)
end
end
end
end

self.posts.sort!
# Read all the files in <source>/<dir>/_drafts and create a new Post
# object with each one.
#
# dir - The String relative path of the directory to read.
#
# Returns nothing.
def read_drafts(dir)
base = File.join(self.source, dir, '_drafts')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this is used here and in Draft. Maybe this should be a setting, like drafts_dir on Site and we can use that in all the cases where getting the drafts dir path is required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be a setting. I've attempted to refactor things to avoid the duplication, but it gets hairy and dilutes the focus of this pull request.

Besides, it's the same problem with '_posts'.

return unless File.exists?(base)
entries = Dir.chdir(base) { filter_entries(Dir['**/*']) }

# limit the posts if :limit_posts option is set
if limit_posts
limit = self.posts.length < limit_posts ? self.posts.length : limit_posts
self.posts = self.posts[-limit, limit]
# first pass processes, but does not yet render draft content
entries.each do |f|
if Draft.valid?(f)
draft = Draft.new(self, self.source, dir, f)

self.posts << draft
draft.categories.each { |c| self.categories[c] << draft }
draft.tags.each { |c| self.tags[c] << draft }
end
end
end

Expand Down