middleman-blog 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 307641a41396030f5930374adc6ccd8016e4fcd3
4
+ data.tar.gz: 4fceaaa05d6742597a5f281192da389ab70da601
5
+ SHA512:
6
+ metadata.gz: a06536de8efae6ee8df31ec992d7f8c19b3f82506eff011050eb5ec39dd4fc0f7989bdcad6985787de2381f593ded44f5e9e564f8a38c5a0b4eddb66a0213149
7
+ data.tar.gz: bb6d528615b52afcd59c976f8d1f93fe7fadc521d989894f270db7cb45524af94686e535732d22cea399a0b7485dc9ce79f5b9ccf380c1dcc28336513dd3def8
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ rvm:
2
2
  - 1.8.7
3
3
  - 1.9.2
4
4
  - 1.9.3
5
+ - 2.0.0
5
6
  - jruby-18mode
6
7
  - jruby-19mode
7
8
 
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ 3.2.0
2
+ ====
3
+
4
+ * The `summary` method on articles is now HTML-aware, and can be provided with
5
+ a different summary length or ellipsis string: `summary(1000, '…')`.
6
+ Nokogiri is required to use the summary.
7
+ * The `summary_generator` option now recieves the rendered article (without
8
+ layout) instead of the template source.
9
+ * Set `summary_length` to false to always use the full article as a summary.
10
+ * Future-dated articles can still be generated if `publish_future_dated` is true.
11
+ * The `summary_separator` option no longer needs to have a capturing group, or
12
+ even be a regexp.
13
+
1
14
  3.1.1
2
15
  ====
3
16
  * Correctly handle time zone, allow setting time zone with `set :time_zone`. #76
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source :rubygems
1
+ source 'http://rubygems.org'
2
2
 
3
- git "git://github.com/middleman/middleman.git" do
3
+ git "git://github.com/middleman/middleman.git", :branch => "master" do
4
4
  # gem "middleman"
5
5
  gem "middleman-core"
6
6
  gem "middleman-more"
@@ -9,20 +9,17 @@ end
9
9
  # Specify your gem's dependencies in middleman-blog.gemspec
10
10
  gemspec
11
11
 
12
- group :development do
13
- gem "rake", "~> 0.9.2"
14
- gem "rdoc", "~> 3.9"
15
- gem "yard", "~> 0.8.0"
16
- end
12
+ gem "rake", "~> 0.9.2"
13
+ gem "rdoc", "~> 3.9"
14
+ gem "yard", "~> 0.8.0"
15
+
16
+ gem "cucumber", "~> 1.2.0"
17
+ gem "fivemat"
18
+ gem "aruba", "~> 0.4.11"
19
+ gem "rspec", "~> 2.7"
20
+ gem "timecop", "~> 0.4.0"
21
+ gem "nokogiri"
17
22
 
18
- group :test do
19
- gem "cucumber", "~> 1.2.0"
20
- gem "fivemat"
21
- gem "aruba", "~> 0.4.11"
22
- gem "rspec", "~> 2.7"
23
- gem "timecop", "~> 0.4.0"
24
-
25
- platforms :ruby do
26
- gem "redcarpet", "~> 2.1.1"
27
- end
23
+ platforms :ruby do
24
+ gem "redcarpet", "~> 2.1.1"
28
25
  end
data/README.md CHANGED
@@ -20,7 +20,7 @@ activate :blog
20
20
 
21
21
  # Learn More
22
22
 
23
- See [the blog extension guide](http://beta.middlemanapp.com/extensions/blog/) for detailed information on configuring and using the blog extension.
23
+ See [the blog extension guide](http://middlemanapp.com/blogging/) for detailed information on configuring and using the blog extension.
24
24
 
25
25
  Up-to-date generated code documentation is available on RubyDoc:
26
26
  http://rubydoc.info/github/middleman/middleman-blog
@@ -41,7 +41,7 @@ The best way to get quick responses to your issues and swift fixes to your bugs
41
41
 
42
42
  # Build & Dependency Status
43
43
 
44
- [![Build Status](http://travis-ci.org/middleman/middleman-blog.png)](http://travis-ci.org/middleman/middleman-blog)
44
+ [![Build Status](https://travis-ci.org/middleman/middleman-blog.png)](https://travis-ci.org/middleman/middleman-blog)
45
45
 
46
46
  # How to Run Cucumber Tests
47
47
 
@@ -52,7 +52,7 @@ The best way to get quick responses to your issues and swift fixes to your bugs
52
52
 
53
53
  # Donate
54
54
 
55
- [![Click here to lend your support to Middleman](https://www.pledgie.com/campaigns/15807.png)](http://www.pledgie.com/campaigns/15807)
55
+ Please, [help support the Middleman team with a donation](https://spb.io/s/4dXbHBorC3).
56
56
 
57
57
  # License
58
58
 
@@ -34,3 +34,23 @@ Feature: Future-dated blog articles
34
34
  Then I should see "This is a future-dated article"
35
35
  When I go to "/2012/06/19/future-article/example.txt"
36
36
  Then I should see "Example Text"
37
+
38
+ Scenario: Future-dated articles show up when publish_future_dated is true
39
+ Given a fixture app "future-date-app"
40
+ And a file named "config.rb" with:
41
+ """
42
+ set :environment, :production
43
+ Time.zone = "Pacific Time (US & Canada)"
44
+ activate :blog do |blog|
45
+ blog.sources = "blog/:year-:month-:day-:title.html"
46
+ blog.publish_future_dated = true
47
+ end
48
+ """
49
+ Given the date is 2012-06-18
50
+ And the Server is running at "future-date-app"
51
+ When I go to "/2011/01/01/new-article.html"
52
+ Then I should see "Newer Article Content"
53
+ When I go to "/2012/06/19/future-article.html"
54
+ Then I should see "This is a future-dated article"
55
+ When I go to "/2012/06/19/future-article/example.txt"
56
+ Then I should see "Example Text"
@@ -19,8 +19,8 @@ module Middleman
19
19
  content = super(opts, locs, &block)
20
20
 
21
21
  unless opts[:keep_separator]
22
- if content =~ app.blog.options.summary_separator
23
- content.sub!($1, "")
22
+ if content.match(app.blog.options.summary_separator)
23
+ content.sub!(app.blog.options.summary_separator, "")
24
24
  end
25
25
  end
26
26
 
@@ -34,9 +34,16 @@ module Middleman
34
34
  end
35
35
 
36
36
  # Whether or not this article has been published
37
+ #
38
+ # An article is considered published in the following scenarios:
39
+ #
40
+ # 1. frontmatter does not set published to false and either
41
+ # 2. published_future_dated is true or
42
+ # 3. article date is after the current time
37
43
  # @return [Boolean]
38
44
  def published?
39
- data["published"] != false and date <= Time.current
45
+ (data["published"] != false) and
46
+ (app.blog.options.publish_future_dated || date <= Time.current)
40
47
  end
41
48
 
42
49
  # The body of this article, in HTML. This is for
@@ -52,29 +59,36 @@ module Middleman
52
59
  # everything before the summary separator (set via :summary_separator
53
60
  # and defaulting to "READMORE") or the first :summary_length
54
61
  # characters of the post.
62
+ #
63
+ # :summary_generator can be set to a Proc in order to provide
64
+ # custom summary generation. The Proc is provided a parameter
65
+ # which is the rendered content of the article (without layout), the
66
+ # desired length to trim the summary to, and the ellipsis string to use.
67
+ #
68
+ # @param [Number] length How many characters to trim the summary to.
69
+ # @param [Number] length The ellipsis string to use when content is trimmed.
55
70
  # @return [String]
56
- def summary
57
- @_summary ||= begin
58
- source = app.template_data_for_file(source_file).dup
59
-
60
- summary_source = if app.blog.options.summary_generator
61
- app.blog.options.summary_generator.call(self, source)
62
- else
63
- default_summary_generator(source)
64
- end
65
-
66
- md = metadata.dup
67
- locs = md[:locals]
68
- opts = md[:options].merge({:template_body => summary_source})
69
- app.render_individual_file(source_file, locs, opts)
71
+ def summary(length=app.blog.options.summary_length, ellipsis='...')
72
+ rendered = render(:layout => false, :keep_separator => true)
73
+
74
+ if app.blog.options.summary_separator && rendered.match(app.blog.options.summary_separator)
75
+ rendered.split(app.blog.options.summary_separator).first
76
+ elsif app.blog.options.summary_generator
77
+ app.blog.options.summary_generator.call(self, rendered, length, ellipsis)
78
+ else
79
+ default_summary_generator(rendered, length, ellipsis)
70
80
  end
71
81
  end
72
82
 
73
- def default_summary_generator(source)
74
- if source =~ app.blog.options.summary_separator
75
- source.split(app.blog.options.summary_separator).first
83
+ def default_summary_generator(rendered, length, ellipsis)
84
+ require 'middleman-blog/truncate_html'
85
+
86
+ if rendered =~ app.blog.options.summary_separator
87
+ rendered.split(app.blog.options.summary_separator).first
88
+ elsif length
89
+ TruncateHTML.truncate_html(rendered, length, ellipsis)
76
90
  else
77
- source.match(/(.{1,#{app.blog.options.summary_length}}.*?)(\n|\Z)/m).to_s
91
+ rendered
78
92
  end
79
93
  end
80
94
 
@@ -33,7 +33,7 @@ module Middleman
33
33
  if shared_instance.respond_to? :blog
34
34
  @title = title
35
35
  @slug = title.parameterize
36
- @date = options[:date] ? DateTime.parse(options[:date]) : DateTime.now
36
+ @date = options[:date] ? Time.zone.parse(options[:date]) : Time.zone.now
37
37
 
38
38
  article_path = shared_instance.blog.options.sources.
39
39
  sub(':year', @date.year.to_s).
@@ -21,7 +21,8 @@ module Middleman
21
21
  :tag_template,
22
22
  :paginate,
23
23
  :per_page,
24
- :page_link
24
+ :page_link,
25
+ :publish_future_dated
25
26
  ]
26
27
 
27
28
  KEYS.each do |name|
@@ -48,19 +49,20 @@ module Middleman
48
49
  options = Options.new(options_hash)
49
50
  yield options if block_given?
50
51
 
51
- options.permalink ||= "/:year/:month/:day/:title.html"
52
- options.sources ||= ":year-:month-:day-:title.html"
53
- options.taglink ||= "tags/:tag.html"
54
- options.layout ||= "layout"
55
- options.summary_separator ||= /(READMORE)/
56
- options.summary_length ||= 250
57
- options.year_link ||= "/:year.html"
58
- options.month_link ||= "/:year/:month.html"
59
- options.day_link ||= "/:year/:month/:day.html"
60
- options.default_extension ||= ".markdown"
61
- options.paginate ||= false
62
- options.per_page ||= 10
63
- options.page_link ||= "page/:num"
52
+ options.permalink ||= "/:year/:month/:day/:title.html"
53
+ options.sources ||= ":year-:month-:day-:title.html"
54
+ options.taglink ||= "tags/:tag.html"
55
+ options.layout ||= "layout"
56
+ options.summary_separator ||= /(READMORE)/
57
+ options.summary_length ||= 250
58
+ options.year_link ||= "/:year.html"
59
+ options.month_link ||= "/:year/:month.html"
60
+ options.day_link ||= "/:year/:month/:day.html"
61
+ options.default_extension ||= ".markdown"
62
+ options.paginate ||= false
63
+ options.per_page ||= 10
64
+ options.page_link ||= "page/:num"
65
+ options.publish_future_dated ||= false
64
66
 
65
67
  # optional: :tag_template
66
68
  # optional: :year_template
@@ -16,7 +16,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
16
16
  xml.published article.date.to_time.iso8601
17
17
  xml.updated article.date.to_time.iso8601
18
18
  xml.author { xml.name "Article Author" }
19
- xml.summary article.summary, "type" => "html"
19
+ # xml.summary article.summary, "type" => "html"
20
20
  xml.content article.body, "type" => "html"
21
21
  end
22
22
  end
@@ -12,7 +12,9 @@ per_page: 10
12
12
 
13
13
  <% page_articles.each_with_index do |article, i| %>
14
14
  <h2><%= link_to article.title, article %> <span><%= article.date.strftime('%b %e') %></span></h2>
15
- <p><%= article.summary %></p>
15
+ <!-- use article.summary(250) if you have Nokogiri available to show just
16
+ the first 250 characters -->
17
+ <%= article.body %>
16
18
  <% end %>
17
19
 
18
20
  <% if paginate %>
@@ -14,21 +14,21 @@
14
14
  <h2>Recent Articles</h2>
15
15
  <ol>
16
16
  <% blog.articles[0...10].each do |article| %>
17
- <li><a href="<%= article.url %>"><%= article.title %></a> <span><%= article.date.strftime('%b %e') %></span></li>
17
+ <li><%= link_to article.title, article %> <span><%= article.date.strftime('%b %e') %></span></li>
18
18
  <% end %>
19
19
  </ol>
20
20
 
21
21
  <h2>Tags</h2>
22
22
  <ol>
23
23
  <% blog.tags.each do |tag, articles| %>
24
- <li><a href="<%= tag_path tag %>"><%= tag %> (<%= articles.size %>)</a></li>
24
+ <li><%= link_to tag, tag_path(tag) %> (<%= articles.size %>)</a></li>
25
25
  <% end %>
26
26
  </ol>
27
27
 
28
28
  <h2>By Year</h2>
29
29
  <ol>
30
30
  <% blog.articles.group_by {|a| a.date.year }.each do |year, articles| %>
31
- <li><a href="<%= blog_year_path year %>"><%= year %> (<%= articles.size %>)</a></li>
31
+ <li><%= link_to year, blog_year_path(year) %> (<%= articles.size %>)</a></li>
32
32
  <% end %>
33
33
  </ol>
34
34
  </aside>
@@ -0,0 +1,53 @@
1
+ begin
2
+ require "nokogiri"
3
+ rescue LoadError
4
+ raise "Nokogiri is required for blog post summaries. Add 'nokogiri' to your Gemfile."
5
+ end
6
+
7
+ # Taken and modified from http://madebydna.com/all/code/2010/06/04/ruby-helper-to-cleanly-truncate-html.html
8
+ # MIT license
9
+ module TruncateHTML
10
+ def self.truncate_html(text, max_length, ellipsis = "...")
11
+ ellipsis_length = ellipsis.length
12
+ doc = Nokogiri::HTML::DocumentFragment.parse text
13
+ content_length = doc.inner_text.length
14
+ actual_length = max_length - ellipsis_length
15
+ if content_length > actual_length
16
+ doc.truncate(actual_length, ellipsis).inner_html
17
+ else
18
+ text
19
+ end
20
+ end
21
+ end
22
+
23
+ module NokogiriTruncator
24
+ module NodeWithChildren
25
+ def truncate(max_length, ellipsis)
26
+ return self if inner_text.length <= max_length
27
+ truncated_node = self.dup
28
+ truncated_node.children.remove
29
+
30
+ self.children.each do |node|
31
+ remaining_length = max_length - truncated_node.inner_text.length
32
+ break if remaining_length <= 0
33
+ truncated_node.add_child node.truncate(remaining_length, ellipsis)
34
+ end
35
+ truncated_node
36
+ end
37
+ end
38
+
39
+ module TextNode
40
+ def truncate(max_length, ellipsis)
41
+ # Don't break in the middle of a word
42
+ trimmed_content = content.match(/(.{1,#{max_length}}[\w]*)/m).to_s
43
+ trimmed_content << ellipsis if trimmed_content.length < content.length
44
+
45
+ Nokogiri::XML::Text.new(trimmed_content, parent)
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ Nokogiri::HTML::DocumentFragment.send(:include, NokogiriTruncator::NodeWithChildren)
52
+ Nokogiri::XML::Element.send(:include, NokogiriTruncator::NodeWithChildren)
53
+ Nokogiri::XML::Text.send(:include, NokogiriTruncator::TextNode)
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  module Blog
3
- VERSION = "3.1.1"
3
+ VERSION = "3.2.0"
4
4
  end
5
5
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0")
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency("middleman-core", ["~> 3.0.1"])
21
+ s.add_dependency("middleman-core", ["~> 3.0"])
22
22
  s.add_dependency("maruku", ["~> 0.6.0"])
23
23
  s.add_dependency("tzinfo", ["~> 0.3.0"])
24
24
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-blog
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
5
- prerelease:
4
+ version: 3.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Thomas Reynolds
@@ -10,28 +9,25 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2012-09-21 00:00:00.000000000 Z
12
+ date: 2013-03-11 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: middleman-core
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
18
  - - ~>
21
19
  - !ruby/object:Gem::Version
22
- version: 3.0.1
20
+ version: '3.0'
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
25
  - - ~>
29
26
  - !ruby/object:Gem::Version
30
- version: 3.0.1
27
+ version: '3.0'
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: maruku
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
32
  - - ~>
37
33
  - !ruby/object:Gem::Version
@@ -39,7 +35,6 @@ dependencies:
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
39
  - - ~>
45
40
  - !ruby/object:Gem::Version
@@ -47,7 +42,6 @@ dependencies:
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: tzinfo
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
46
  - - ~>
53
47
  - !ruby/object:Gem::Version
@@ -55,7 +49,6 @@ dependencies:
55
49
  type: :runtime
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
53
  - - ~>
61
54
  - !ruby/object:Gem::Version
@@ -202,38 +195,32 @@ files:
202
195
  - lib/middleman-blog/template/source/index.html.erb
203
196
  - lib/middleman-blog/template/source/layout.erb
204
197
  - lib/middleman-blog/template/source/tag.html.erb
198
+ - lib/middleman-blog/truncate_html.rb
205
199
  - lib/middleman-blog/version.rb
206
200
  - lib/middleman_extension.rb
207
201
  - middleman-blog.gemspec
208
202
  homepage: https://github.com/middleman/middleman-blog
209
203
  licenses: []
204
+ metadata: {}
210
205
  post_install_message:
211
206
  rdoc_options: []
212
207
  require_paths:
213
208
  - lib
214
209
  required_ruby_version: !ruby/object:Gem::Requirement
215
- none: false
216
210
  requirements:
217
- - - ! '>='
211
+ - - '>='
218
212
  - !ruby/object:Gem::Version
219
213
  version: '0'
220
- segments:
221
- - 0
222
- hash: -3637459157260692446
223
214
  required_rubygems_version: !ruby/object:Gem::Requirement
224
- none: false
225
215
  requirements:
226
- - - ! '>='
216
+ - - '>='
227
217
  - !ruby/object:Gem::Version
228
218
  version: '0'
229
- segments:
230
- - 0
231
- hash: -3637459157260692446
232
219
  requirements: []
233
220
  rubyforge_project: middleman-blog
234
- rubygems_version: 1.8.24
221
+ rubygems_version: 2.0.0
235
222
  signing_key:
236
- specification_version: 3
223
+ specification_version: 4
237
224
  summary: A blog foundation using Middleman
238
225
  test_files:
239
226
  - features/article_cli.feature