middleman-blog 3.1.1 → 3.2.0
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.
- checksums.yaml +7 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +14 -17
- data/README.md +3 -3
- data/features/future_date.feature +20 -0
- data/lib/middleman-blog/blog_article.rb +35 -21
- data/lib/middleman-blog/commands/article.rb +1 -1
- data/lib/middleman-blog/extension.rb +16 -14
- data/lib/middleman-blog/template/source/feed.xml.builder +1 -1
- data/lib/middleman-blog/template/source/index.html.erb +3 -1
- data/lib/middleman-blog/template/source/layout.erb +3 -3
- data/lib/middleman-blog/truncate_html.rb +53 -0
- data/lib/middleman-blog/version.rb +1 -1
- data/middleman-blog.gemspec +1 -1
- metadata +10 -23
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
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
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
19
|
-
gem "
|
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://
|
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
|
-
[](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
|
-
[
|
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
|
23
|
-
content.sub!(
|
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
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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(
|
74
|
-
|
75
|
-
|
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
|
-
|
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] ?
|
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
|
52
|
-
options.sources
|
53
|
-
options.taglink
|
54
|
-
options.layout
|
55
|
-
options.summary_separator
|
56
|
-
options.summary_length
|
57
|
-
options.year_link
|
58
|
-
options.month_link
|
59
|
-
options.day_link
|
60
|
-
options.default_extension
|
61
|
-
options.paginate
|
62
|
-
options.per_page
|
63
|
-
options.page_link
|
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
|
-
|
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
|
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
|
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
|
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)
|
data/middleman-blog.gemspec
CHANGED
@@ -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
|
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.
|
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:
|
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
|
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
|
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:
|
221
|
+
rubygems_version: 2.0.0
|
235
222
|
signing_key:
|
236
|
-
specification_version:
|
223
|
+
specification_version: 4
|
237
224
|
summary: A blog foundation using Middleman
|
238
225
|
test_files:
|
239
226
|
- features/article_cli.feature
|