middleman-blog-drafts 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ # Ignore bundler lock file
2
+ Gemfile.lock
3
+ /tmp
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in middleman-blog-drafts.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem "rake", "~> 0.9.2"
8
+ gem "rdoc", "~> 3.9"
9
+ gem "yard", "~> 0.8.0"
10
+ gem "guard-cucumber"
11
+ end
12
+
13
+ group :test do
14
+ gem "cucumber", "~> 1.2.0"
15
+ gem "fivemat"
16
+ gem "aruba", "~> 0.4.11"
17
+ gem "rspec", "~> 2.7"
18
+ end
data/Guardfile ADDED
@@ -0,0 +1,7 @@
1
+ guard 'cucumber' do
2
+ watch(%r{^features/.+\.feature$})
3
+ watch(%r{^features/support/.+$}) { 'features' }
4
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
5
+ watch(%r{^fixtures/.+$})
6
+ watch(%r{^lib/.+$})
7
+ end
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'cucumber/rake/task'
5
+
6
+ Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t|
7
+ t.cucumber_opts = "--color --tags ~@wip --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}"
8
+ end
9
+
10
+ require 'rake/clean'
11
+
12
+ task :test => ["cucumber"]
13
+
14
+ task :default => :test
@@ -0,0 +1,5 @@
1
+ Feature: Building the site
2
+ Scenario: Unpublished articles don't get built
3
+ Given a fixture app "draft-date-app"
4
+ When I run `middleman build`
5
+ Then the build directory should be empty
@@ -0,0 +1,7 @@
1
+ Feature: New draft CLI command
2
+ Scenario: Create a new blog draft article with the CLI
3
+ Given a fixture app "drafts-app"
4
+ And I run `middleman draft "My New Article"`
5
+ Then the exit status should be 0
6
+ Then the following files should exist:
7
+ | source/drafts/my-new-article.html.markdown |
@@ -0,0 +1,10 @@
1
+ Feature: Derive draft date from today
2
+ Scenario: Drafts without dates
3
+ Given the Server is running at "draft-date-app"
4
+ When I go to "/drafts/new-draft.html"
5
+ Then I should see the current date
6
+
7
+ Scenario: Drafts without dates and using data store
8
+ Given the Server is running at "draft-date-app"
9
+ When I go to "/drafts/other-draft.html"
10
+ Then I should see the current date
@@ -0,0 +1,17 @@
1
+ Feature: Publish draft CLI command
2
+ Scenario: Publish a new blog draft article with the CLI
3
+ Given a fixture app "drafts-app"
4
+ And I run `middleman draft "My New Article"`
5
+ And I run `middleman publish source/drafts/my-new-article.html.markdown --date 2012-03-07`
6
+ Then the exit status should be 0
7
+ And the following files should exist:
8
+ | source/blog/2012-03-07-my-new-article.html.markdown |
9
+ And the following files should not exist:
10
+ | source/drafts/my-new-article.html.markdown |
11
+
12
+ Scenario: Viewing a published article
13
+ Given a fixture app "draft-date-app"
14
+ And I run `middleman publish source/drafts/new-draft.html.erb --date 2012-03-07`
15
+ When the Server is running at "draft-date-app"
16
+ And I go to "/2012/03/07/new-draft.html"
17
+ Then I should see '2012-03-07'
@@ -0,0 +1,7 @@
1
+ Then /^I should see the current date/ do
2
+ step %Q{I should see "Date: #{Time.now.in_time_zone.iso8601}"}
3
+ end
4
+
5
+ Then /^the build directory should be empty/ do
6
+ in_current_dir { Dir['build/**/*'].should be_empty }
7
+ end
@@ -0,0 +1,4 @@
1
+ PROJECT_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__)))
2
+ require "middleman-core"
3
+ require "middleman-core/step_definitions"
4
+ require File.join(PROJECT_ROOT_PATH, 'lib', 'middleman-blog-drafts')
@@ -0,0 +1,3 @@
1
+ require 'middleman-blog'
2
+ activate :blog
3
+ activate :drafts
@@ -0,0 +1,2 @@
1
+ <h1>New Draft Title</h1>
2
+ <p>Date: <%= current_article.date.iso8601 %></p>
@@ -0,0 +1,2 @@
1
+ <h1>Other Draft Title</h1>
2
+ <p>Date: <%= current_article.data.date.iso8601 %></p>
@@ -0,0 +1,8 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ </head>
5
+ <body>
6
+ <%= yield%>
7
+ </body>
8
+ </html>
@@ -0,0 +1,5 @@
1
+ require 'middleman-blog'
2
+ activate :blog do |c|
3
+ c.prefix = 'blog'
4
+ end
5
+ activate :drafts
@@ -0,0 +1,84 @@
1
+ module Middleman
2
+ module Blog
3
+ module Drafts
4
+ # An extension to let {Middleman::Blog::BlogData} know about all draft
5
+ # articles in the site.
6
+ module BlogDataExtensions
7
+ def drafts(app=nil, options=nil)
8
+ @_drafts ||= Middleman::Blog::Drafts::Data.new(self, app, options)
9
+ end
10
+
11
+ # A draft BlogArticle for the given path, or nil if one doesn't exist.
12
+ # @return [Middleman::Sitemap::Resource]
13
+ def draft(path)
14
+ article = drafts.options.app.sitemap.find_resource_by_path(path.to_s)
15
+ if article && article.is_a?(BlogArticle)
16
+ article
17
+ else
18
+ nil
19
+ end
20
+ end
21
+ end
22
+
23
+ # A store of all the draft articles in the site. Accessed via "blog.drafts" in
24
+ # templates.
25
+ class Data
26
+ attr_reader :options, :path_matcher, :matcher_indexes
27
+
28
+ # @private
29
+ def initialize(blog_data, app, options)
30
+ @blog_data = blog_data
31
+ @options = options
32
+ @app = app
33
+
34
+ # A list of resources corresponding to draft articles
35
+ @_drafts = []
36
+
37
+ matcher = Regexp.escape(options.sources).
38
+ sub(/^\//, "").
39
+ sub(":title", "([^/]+)")
40
+
41
+ @path_matcher = /^#{matcher}/
42
+
43
+ # Build a hash of part name to capture index, e.g. {"year" => 0}
44
+ @matcher_indexes = {}
45
+ options.sources.scan(/:title/).
46
+ each_with_index do |key, i|
47
+ @matcher_indexes[key[1..-1]] = i
48
+ end
49
+ # The path always appears at the end.
50
+ @matcher_indexes["path"] = @matcher_indexes.size
51
+ end
52
+
53
+ # Updates' blog draft articles destination paths to be the
54
+ # permalink.
55
+ # @return [void]
56
+ def manipulate_resource_list(resources)
57
+ @_drafts = []
58
+ used_resources = []
59
+
60
+ resources.each do |resource|
61
+ if resource.path =~ @path_matcher
62
+ resource.extend BlogArticle
63
+ resource.extend DraftArticle
64
+
65
+ next unless @app.environment == :development
66
+
67
+ # compute output path:
68
+ resource.destination_path = options.permalink.
69
+ sub(':title', resource.slug)
70
+
71
+ resource.destination_path = Middleman::Util.normalize_path(resource.destination_path)
72
+
73
+ @_drafts << resource
74
+ end
75
+
76
+ used_resources << resource
77
+ end
78
+
79
+ used_resources
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,43 @@
1
+ require 'middleman-core/cli'
2
+
3
+ module Middleman
4
+ module Cli
5
+ # This class provides a "draft" command for the middleman CLI.
6
+ class Draft < Thor
7
+ include Thor::Actions
8
+
9
+ check_unknown_options!
10
+
11
+ namespace :draft
12
+
13
+ # Template files are relative to this file
14
+ # @return [String]
15
+ def self.source_root
16
+ File.dirname(__FILE__)
17
+ end
18
+
19
+ # Tell Thor to exit with a nonzero exit code on failure
20
+ def self.exit_on_failure?
21
+ true
22
+ end
23
+
24
+ desc "draft TITLE", "Create a new draft for a blog article"
25
+ def draft(title)
26
+ shared_instance = ::Middleman::Application.server.inst
27
+
28
+ # This only exists when the config.rb sets it!
29
+ if shared_instance.blog.respond_to? :drafts
30
+ @title = title
31
+ @slug = title.parameterize
32
+
33
+ draft_path = shared_instance.blog.drafts.options.sources.
34
+ sub(':title', @slug)
35
+
36
+ template "draft.tt", File.join(shared_instance.source_dir, draft_path + shared_instance.blog.options.default_extension)
37
+ else
38
+ raise Thor::Error.new "You need to activate the drafts extension in config.rb before you can create an article"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: '<%= @title %>'
3
+ # date: TBD When publishing
4
+ tags:
5
+ ---
6
+
7
+ # <%= @title %>
8
+
9
+ Write a draft post :-)
@@ -0,0 +1,57 @@
1
+ require 'middleman-core/cli'
2
+
3
+ module Middleman
4
+ module Cli
5
+ # This class provides a "publish" command for the middleman CLI.
6
+ class Publish < Thor
7
+ include Thor::Actions
8
+
9
+ check_unknown_options!
10
+
11
+ namespace :publish
12
+
13
+ # Template files are relative to this file
14
+ # @return [String]
15
+ def self.source_root
16
+ File.dirname(__FILE__)
17
+ end
18
+
19
+ # Tell Thor to exit with a nonzero exit code on failure
20
+ def self.exit_on_failure?
21
+ true
22
+ end
23
+
24
+ desc "publish DRAFT_PATH", "Publish a draft"
25
+ method_option "date",
26
+ :aliases => "-d",
27
+ :desc => "The date to create the post with (defaults to now)"
28
+ def publish(draft_path)
29
+ shared_instance = ::Middleman::Application.server.inst
30
+
31
+ # This only exists when the config.rb sets it!
32
+ if shared_instance.blog.respond_to? :drafts
33
+ @slug = draft_path.split('/').last.split('.').first.parameterize
34
+ @date = options[:date] ? DateTime.parse(options[:date]) : DateTime.now
35
+
36
+ draft_path = File.expand_path draft_path
37
+ extension = File.extname draft_path
38
+
39
+ article_path = shared_instance.blog.options.sources.
40
+ sub(':year', @date.year.to_s).
41
+ sub(':month', @date.month.to_s.rjust(2,'0')).
42
+ sub(':day', @date.day.to_s.rjust(2,'0')).
43
+ sub(':title', @slug)
44
+ article_path = File.join(shared_instance.source_dir, article_path + extension)
45
+
46
+ data, content = shared_instance.frontmatter_manager.data(draft_path)
47
+ data = data.dup.tap { |d| d[:date] = Date.parse @date.strftime('%F') }
48
+
49
+ create_file article_path, "#{YAML::dump(data).sub(/^--- !ruby.*$/, '---')}---\n#{content}"
50
+ remove_file draft_path
51
+ else
52
+ raise Thor::Error.new "You need to activate the drafts extension in config.rb before you can publish an article"
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,38 @@
1
+ module Middleman
2
+ module Blog
3
+ module Drafts
4
+ module DraftArticle
5
+ # The "slug" of the draft article that shows up in its URL.
6
+ # @return [String]
7
+ def slug
8
+ @_slug ||= path_part("title")
9
+ end
10
+
11
+ # Retrieve a section of the source path
12
+ # @param [String] The part of the path, e.g. "title"
13
+ # @return [String]
14
+ def path_part(part)
15
+ @_path_parts ||= app.blog.drafts.path_matcher.match(path).captures
16
+
17
+ @_path_parts[app.blog.drafts.matcher_indexes[part]]
18
+ end
19
+
20
+ # Returns current date as we can't guess when the article will be published
21
+ #
22
+ # We need this in place or the layout used for blog posts might blow up
23
+ #
24
+ # @return [TimeWithZone]
25
+ def date
26
+ Time.now.in_time_zone
27
+ end
28
+
29
+ # Extends resource data adding the date field
30
+ #
31
+ # @return [Thor::CoreExt::HashWithIndifferentAccess]
32
+ def data
33
+ super.dup.merge(date: date)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,54 @@
1
+ module Middleman
2
+ module Blog
3
+ module Drafts
4
+ class Options
5
+ attr_accessor :sources, :layout, :permalink
6
+
7
+ def initialize(options={})
8
+ options.each do |k,v|
9
+ self.send(:"#{k}=", v)
10
+ end
11
+ end
12
+ end
13
+
14
+ class << self
15
+ # Called when user `activate`s your extension
16
+ def registered(app, options_hash={}, &block)
17
+ require 'middleman-blog/extension'
18
+ require 'middleman-blog/blog_data'
19
+ require 'middleman-blog-drafts/draft_article'
20
+ require 'middleman-blog-drafts/blog_data_extensions'
21
+
22
+ options = Options.new(options_hash)
23
+ yield options if block_given?
24
+
25
+ options.sources ||= "drafts/:title.html"
26
+ options.permalink ||= "/drafts/:title.html"
27
+
28
+ ::Middleman::Blog::BlogData.send :include, BlogDataExtensions
29
+ app.send :include, Helpers
30
+
31
+ app.after_configuration do
32
+ options.layout = blog.options.layout
33
+ blog.drafts(self, options)
34
+
35
+ sitemap.register_resource_list_manipulator(
36
+ :blog_drafts,
37
+ blog.drafts,
38
+ false
39
+ )
40
+ end
41
+ end
42
+ alias :included :registered
43
+ end
44
+
45
+ module Helpers
46
+ # Get a {Resource} with mixed in {BlogArticle} methods representing the current article.
47
+ # @return [Middleman::Sitemap::Resource]
48
+ def current_article
49
+ super || blog.draft(current_resource.path)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,7 @@
1
+ module Middleman
2
+ module Blog
3
+ module Drafts
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require "middleman-core"
2
+
3
+ require "middleman-blog-drafts/commands/draft"
4
+ require "middleman-blog-drafts/commands/publish"
5
+ require "middleman-blog-drafts/version"
6
+
7
+ ::Middleman::Extensions.register(:drafts) do
8
+ require 'middleman-blog-drafts/extension'
9
+ ::Middleman::Blog::Drafts
10
+ end
@@ -0,0 +1 @@
1
+ require "middleman-blog-drafts"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "middleman-blog-drafts/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "middleman-blog-drafts"
7
+ s.version = Middleman::Blog::Drafts::VERSION
8
+ s.authors = ["Fabio Rehm"]
9
+ s.email = ["fgrehm@gmail.com"]
10
+ s.description = %q{middleman-blog extension for working with draft articles}
11
+ s.summary = s.description
12
+ s.homepage = "https://github.com/fgrehm/middleman-draft-articles"
13
+
14
+ s.files = `git ls-files`.split($/)
15
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_runtime_dependency("middleman-core", [">= 3.0.9"])
20
+ s.add_runtime_dependency("middleman-blog")
21
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-blog-drafts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Fabio Rehm
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-19 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ prerelease: false
16
+ name: middleman-core
17
+ version_requirements: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.9
22
+ none: false
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ! '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 3.0.9
28
+ none: false
29
+ type: :runtime
30
+ - !ruby/object:Gem::Dependency
31
+ prerelease: false
32
+ name: middleman-blog
33
+ version_requirements: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ none: false
39
+ requirement: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ none: false
45
+ type: :runtime
46
+ description: middleman-blog extension for working with draft articles
47
+ email:
48
+ - fgrehm@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - Guardfile
56
+ - Rakefile
57
+ - features/build.feature
58
+ - features/draft_cli.feature
59
+ - features/draft_date.feature
60
+ - features/publish_cli.feature
61
+ - features/step_definitions/drafts_steps.rb
62
+ - features/support/env.rb
63
+ - fixtures/draft-date-app/config.rb
64
+ - fixtures/draft-date-app/source/drafts/new-draft.html.erb
65
+ - fixtures/draft-date-app/source/drafts/other-draft.html.erb
66
+ - fixtures/draft-date-app/source/layout.erb
67
+ - fixtures/drafts-app/config.rb
68
+ - lib/middleman-blog-drafts.rb
69
+ - lib/middleman-blog-drafts/blog_data_extensions.rb
70
+ - lib/middleman-blog-drafts/commands/draft.rb
71
+ - lib/middleman-blog-drafts/commands/draft.tt
72
+ - lib/middleman-blog-drafts/commands/publish.rb
73
+ - lib/middleman-blog-drafts/draft_article.rb
74
+ - lib/middleman-blog-drafts/extension.rb
75
+ - lib/middleman-blog-drafts/version.rb
76
+ - lib/middleman_extension.rb
77
+ - middleman-blog-drafts.gemspec
78
+ homepage: https://github.com/fgrehm/middleman-draft-articles
79
+ licenses: []
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ segments:
90
+ - 0
91
+ hash: -3659966068752668471
92
+ none: false
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ segments:
99
+ - 0
100
+ hash: -3659966068752668471
101
+ none: false
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.23
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: middleman-blog extension for working with draft articles
108
+ test_files:
109
+ - features/build.feature
110
+ - features/draft_cli.feature
111
+ - features/draft_date.feature
112
+ - features/publish_cli.feature
113
+ - features/step_definitions/drafts_steps.rb
114
+ - features/support/env.rb
115
+ has_rdoc: