middleman-blog 4.0.0 → 4.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.
- checksums.yaml +4 -4
- data/features/summary.feature +30 -4
- data/fixtures/paginate-app/source/_pager.erb +15 -0
- data/fixtures/paginate-app/source/partial-paging.html.erb +5 -0
- data/lib/middleman-blog.rb +1 -0
- data/lib/middleman-blog/blog_article.rb +15 -13
- data/lib/middleman-blog/blog_data.rb +19 -4
- data/lib/middleman-blog/commands/article.rb +78 -0
- data/lib/middleman-blog/commands/article.tt +6 -0
- data/lib/middleman-blog/extension.rb +1 -0
- data/lib/middleman-blog/truncate_html.rb +12 -1
- data/lib/middleman-blog/uri_templates.rb +1 -1
- data/lib/middleman-blog/version.rb +1 -1
- data/middleman-blog.gemspec +1 -1
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6437136847c6ca3dfc732f0585d154969a140967
|
4
|
+
data.tar.gz: 7d6a917c2f463b52a95a6b1e5c5fc73ff4e0b120
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b27cbe706b043afb84067b974bdf574bf70e006abb0c111b006c12e9a489f114255456a2152a13d68ae816b3abd9eb02c77c4efc16b5833fcc902ca45106180
|
7
|
+
data.tar.gz: 2b26df677ed97f8806102ae623b7d193820e44175b64d7a1d5bbda4b9c48897ddbf39f6f823ba66f1a6020659304010d788978dd7f668a0ece97a6e77faaecba
|
data/features/summary.feature
CHANGED
@@ -2,9 +2,9 @@ Feature: Article summary generation
|
|
2
2
|
Scenario: Article has no summary separator
|
3
3
|
Given the Server is running at "summary-app"
|
4
4
|
When I go to "/index.html"
|
5
|
-
Then I should see "Summary from article with separator
|
5
|
+
Then I should see "<p>Summary from article with separator.</p>"
|
6
6
|
Then I should not see "Extended part from article with separator."
|
7
|
-
Then I should see "Summary from article with no separator
|
7
|
+
Then I should see "<p>Summary from article with no separator.</p>"
|
8
8
|
Then I should not see "Extended part from article with no separator."
|
9
9
|
|
10
10
|
Scenario: Article has custom summary separator
|
@@ -17,7 +17,11 @@ Feature: Article summary generation
|
|
17
17
|
"""
|
18
18
|
Given the Server is running at "summary-app"
|
19
19
|
When I go to "/index.html"
|
20
|
-
Then I should see
|
20
|
+
Then I should see:
|
21
|
+
"""
|
22
|
+
<p>Summary from article with custom separator.
|
23
|
+
</p>
|
24
|
+
"""
|
21
25
|
Then I should not see "Extended part from article with custom separator."
|
22
26
|
Then I should see "Extended part from article with separator."
|
23
27
|
|
@@ -32,7 +36,7 @@ Feature: Article summary generation
|
|
32
36
|
Given the Server is running at "summary-app"
|
33
37
|
When I go to "/index.html"
|
34
38
|
Then I should see "This is my summary, and I like it"
|
35
|
-
Then I should see "Summary from article"
|
39
|
+
Then I should not see "Summary from article"
|
36
40
|
Then I should not see "Summary from article with no separator"
|
37
41
|
Then I should not see "Extended part from article"
|
38
42
|
|
@@ -54,3 +58,25 @@ Feature: Article summary generation
|
|
54
58
|
When I go to "/index.html"
|
55
59
|
Then I should see "Extended part from article with no separator."
|
56
60
|
Then I should not see "Extended part from article with separator."
|
61
|
+
|
62
|
+
Scenario: Summary limited by length only
|
63
|
+
Given a fixture app "summary-app"
|
64
|
+
And a file named "config.rb" with:
|
65
|
+
"""
|
66
|
+
activate :blog
|
67
|
+
"""
|
68
|
+
And a file named "source/index.html.erb" with:
|
69
|
+
"""
|
70
|
+
<% @i = 0 %>
|
71
|
+
<% blog.articles.each do |article| %>
|
72
|
+
<article>
|
73
|
+
<%= article.summary(7, (@i += 1).to_s) %>
|
74
|
+
</article>
|
75
|
+
<% end %>
|
76
|
+
"""
|
77
|
+
Given the Server is running at "summary-app"
|
78
|
+
When I go to "/index.html"
|
79
|
+
Then I should see "Summary1"
|
80
|
+
Then I should see "Summary2"
|
81
|
+
Then I should see "Summary3"
|
82
|
+
Then I should see "Summary4"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Paginate: <%= paginate %>
|
2
|
+
Article Count: <%= page_articles.size %>
|
3
|
+
<% if paginate %>
|
4
|
+
Page Num: <%= page_number %>
|
5
|
+
Num Pages: <%= num_pages %>
|
6
|
+
Per Page: <%= per_page %>
|
7
|
+
Page Start: <%= page_start %>
|
8
|
+
Page End: <%= page_end %>
|
9
|
+
Next Page: '<%= next_page.url if next_page %>'
|
10
|
+
Prev Page: '<%= prev_page.url if prev_page %>'
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% page_articles.each do |article| %>
|
14
|
+
<li><a href="<%= article.url %>"><%= article.title %></a> <time><%= article.date.strftime('%b %e') %></time></li>
|
15
|
+
<% end %>
|
data/lib/middleman-blog.rb
CHANGED
@@ -73,26 +73,24 @@ module Middleman
|
|
73
73
|
render layout: false
|
74
74
|
end
|
75
75
|
|
76
|
-
# The summary for this article, in HTML.
|
77
|
-
# everything before the summary separator (set via the blog option
|
78
|
-
# +summary_separator+ and defaulting to "READMORE") or the first
|
79
|
-
# +summary_length+ characters of the post.
|
76
|
+
# The summary for this article, in HTML.
|
80
77
|
#
|
81
78
|
# The blog option +summary_generator+ can be set to a +Proc+ in order to provide
|
82
79
|
# custom summary generation. The +Proc+ is provided
|
83
80
|
# the rendered content of the article (without layout), the
|
84
81
|
# desired length to trim the summary to, and the ellipsis string to use.
|
85
|
-
# Otherwise the {#default_summary_generator} will be used
|
82
|
+
# Otherwise the {#default_summary_generator} will be used, which returns either
|
83
|
+
# everything before the summary separator (set via the blog option
|
84
|
+
# +summary_separator+ and defaulting to "READMORE") if it is found,
|
85
|
+
# or the first +summary_length+ characters of the post.
|
86
86
|
#
|
87
87
|
# @param [Number] length How many characters to trim the summary to.
|
88
88
|
# @param [String] ellipsis The ellipsis string to use when content is trimmed.
|
89
89
|
# @return [String]
|
90
|
-
def summary(length=
|
90
|
+
def summary(length=nil, ellipsis='...')
|
91
91
|
rendered = render layout: false, keep_separator: true
|
92
92
|
|
93
|
-
if blog_options.
|
94
|
-
rendered.split(blog_options.summary_separator).first
|
95
|
-
elsif blog_options.summary_generator
|
93
|
+
if blog_options.summary_generator
|
96
94
|
blog_options.summary_generator.call(self, rendered, length, ellipsis)
|
97
95
|
else
|
98
96
|
default_summary_generator(rendered, length, ellipsis)
|
@@ -107,11 +105,15 @@ module Middleman
|
|
107
105
|
# @param [Integer] length The length in characters to truncate to.
|
108
106
|
# -1 or +nil+ will return the whole article.
|
109
107
|
def default_summary_generator(rendered, length, ellipsis)
|
110
|
-
if
|
111
|
-
|
112
|
-
|
108
|
+
if length && length >= 0
|
109
|
+
require 'middleman-blog/truncate_html'
|
110
|
+
TruncateHTML.truncate_at_length(rendered, length, ellipsis)
|
111
|
+
elsif blog_options.summary_separator && rendered.match(blog_options.summary_separator)
|
112
|
+
require 'middleman-blog/truncate_html'
|
113
|
+
TruncateHTML.truncate_at_separator(rendered, blog_options.summary_separator)
|
114
|
+
elsif blog_options.summary_length && blog_options.summary_length > 0
|
113
115
|
require 'middleman-blog/truncate_html'
|
114
|
-
TruncateHTML.
|
116
|
+
TruncateHTML.truncate_at_length(rendered, blog_options.summary_length, ellipsis)
|
115
117
|
else
|
116
118
|
rendered
|
117
119
|
end
|
@@ -8,6 +8,8 @@ module Middleman
|
|
8
8
|
class BlogData
|
9
9
|
include UriTemplates
|
10
10
|
|
11
|
+
DEFAULT_FILTER = proc {|a| a}
|
12
|
+
|
11
13
|
# A URITemplate for the source file path relative to :source_dir
|
12
14
|
# @return [URITemplate]
|
13
15
|
attr_reader :source_template
|
@@ -27,6 +29,11 @@ module Middleman
|
|
27
29
|
# A list of resources corresponding to blog articles
|
28
30
|
@_articles = []
|
29
31
|
|
32
|
+
@_parsed_url_cache = {
|
33
|
+
source: {},
|
34
|
+
subdir: {}
|
35
|
+
}
|
36
|
+
|
30
37
|
@source_template = uri_template options.sources
|
31
38
|
@permalink_template = uri_template options.permalink
|
32
39
|
@subdir_template = uri_template options.sources.sub(/\.[^.]+$/, "/{+path}")
|
@@ -36,7 +43,7 @@ module Middleman
|
|
36
43
|
# A list of all blog articles, sorted by descending date
|
37
44
|
# @return [Array<Middleman::Sitemap::Resource>]
|
38
45
|
def articles
|
39
|
-
@_articles.sort_by(&:date).reverse
|
46
|
+
@_articles.select(&(options.filter || DEFAULT_FILTER)).sort_by(&:date).reverse
|
40
47
|
end
|
41
48
|
|
42
49
|
# A list of all blog articles with the given language,
|
@@ -70,6 +77,14 @@ module Middleman
|
|
70
77
|
tags
|
71
78
|
end
|
72
79
|
|
80
|
+
def extract_source_params(path)
|
81
|
+
@_parsed_url_cache[:source][path] ||= extract_params(@source_template, path)
|
82
|
+
end
|
83
|
+
|
84
|
+
def extract_subdir_params(path)
|
85
|
+
@_parsed_url_cache[:subdir][path] ||= extract_params(@subdir_template, path)
|
86
|
+
end
|
87
|
+
|
73
88
|
# Updates' blog articles destination paths to be the
|
74
89
|
# permalink.
|
75
90
|
# @return [void]
|
@@ -84,7 +99,7 @@ module Middleman
|
|
84
99
|
next
|
85
100
|
end
|
86
101
|
|
87
|
-
if (params =
|
102
|
+
if (params = extract_source_params(resource.path))
|
88
103
|
article = convert_to_article(resource)
|
89
104
|
next unless publishable?(article)
|
90
105
|
|
@@ -98,7 +113,7 @@ module Middleman
|
|
98
113
|
|
99
114
|
@_articles << article
|
100
115
|
|
101
|
-
elsif (params =
|
116
|
+
elsif (params = extract_subdir_params(resource.path))
|
102
117
|
# It's not an article, but it's thhe companion files for an article
|
103
118
|
# (in a subdirectory named after the article)
|
104
119
|
# figure out the matching article for this subdirectory file
|
@@ -167,7 +182,7 @@ module Middleman
|
|
167
182
|
resource.blog_controller = controller
|
168
183
|
|
169
184
|
if !options.preserve_locale && (locale = resource.locale || resource.lang)
|
170
|
-
resource.add_metadata options: { lang: locale,
|
185
|
+
resource.add_metadata options: { lang: locale, locale: locale }, locals: { lang: locale, locale: locale }
|
171
186
|
end
|
172
187
|
|
173
188
|
resource
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'middleman-core/cli'
|
2
|
+
require 'date'
|
3
|
+
require 'middleman-blog/uri_templates'
|
4
|
+
|
5
|
+
module Middleman
|
6
|
+
module Cli
|
7
|
+
# This class provides an "article" command for the middleman CLI.
|
8
|
+
class Article < ::Thor::Group
|
9
|
+
include Thor::Actions
|
10
|
+
include Blog::UriTemplates
|
11
|
+
|
12
|
+
check_unknown_options!
|
13
|
+
|
14
|
+
# Template files are relative to this file
|
15
|
+
# @return [String]
|
16
|
+
def self.source_root
|
17
|
+
File.dirname(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
argument :title, type: :string
|
21
|
+
|
22
|
+
class_option "date",
|
23
|
+
aliases: "-d",
|
24
|
+
desc: "The date to create the post with (defaults to now)"
|
25
|
+
class_option "lang",
|
26
|
+
desc: "Deprecated, use locale"
|
27
|
+
class_option "locale",
|
28
|
+
aliases: "-l",
|
29
|
+
desc: "The locale to create the post with (defaults to I18n.default_locale if avaliable)"
|
30
|
+
class_option "blog",
|
31
|
+
aliases: "-b",
|
32
|
+
desc: "The name of the blog to create the post inside (for multi-blog apps, defaults to the only blog in single-blog apps)"
|
33
|
+
def article
|
34
|
+
config = ::Middleman::Cli.config
|
35
|
+
|
36
|
+
@title = title
|
37
|
+
@slug = safe_parameterize(title)
|
38
|
+
@date = options[:date] ? ::Time.zone.parse(options[:date]) : Time.zone.now
|
39
|
+
@lang = options[:lang] || options[:locale] || (::I18n.default_locale if defined? ::I18n )
|
40
|
+
|
41
|
+
app = ::Middleman::Application.new do
|
42
|
+
config[:mode] = :config
|
43
|
+
config[:disable_sitemap] = true
|
44
|
+
config[:watcher_disable] = true
|
45
|
+
config[:exit_before_ready] = true
|
46
|
+
end
|
47
|
+
|
48
|
+
blog_inst = if options[:blog]
|
49
|
+
app.extensions[:blog][options[:blog]]
|
50
|
+
else
|
51
|
+
app.extensions[:blog].values.first
|
52
|
+
end
|
53
|
+
|
54
|
+
unless blog_inst
|
55
|
+
msg = "Could not find an active blog instance"
|
56
|
+
msg << " named #{options[:blog]}" if options[:blog]
|
57
|
+
throw msg
|
58
|
+
end
|
59
|
+
|
60
|
+
path_template = blog_inst.data.source_template
|
61
|
+
params = date_to_params(@date).merge(lang: @lang.to_s, locale: @locale.to_s, title: @slug)
|
62
|
+
article_path = apply_uri_template path_template, params
|
63
|
+
|
64
|
+
template blog_inst.options.new_article_template, File.join(app.source_dir, article_path + blog_inst.options.default_extension)
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
def blog_instance(key)
|
70
|
+
return nil unless app.extensions[:blog]
|
71
|
+
return app.extensions[:blog][key]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Add to CLI
|
75
|
+
Base.register(self, 'article', 'article TITLE [options]', 'Create a new blog article')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -34,6 +34,7 @@ module Middleman
|
|
34
34
|
option :generate_tag_pages, true, 'Whether to generate tag pages.'
|
35
35
|
option :paginate, false, 'Whether to paginate lists of articles'
|
36
36
|
option :per_page, 10, 'Number of articles per page when paginating'
|
37
|
+
option :filter, nil, 'A proc that can be used to select articles that should be published based on user-defined criteria'
|
37
38
|
option :page_link, 'page/{num}', 'Path to append for additional pages when paginating'
|
38
39
|
option :publish_future_dated, false, 'Whether articles with a date in the future should be considered published'
|
39
40
|
option :custom_collections, {}, 'Hash of custom frontmatter properties to collect articles on and their options (link, template)'
|
@@ -7,7 +7,18 @@ end
|
|
7
7
|
# Taken and modified from http://madebydna.com/all/code/2010/06/04/ruby-helper-to-cleanly-truncate-html.html
|
8
8
|
# MIT license
|
9
9
|
module TruncateHTML
|
10
|
-
def self.
|
10
|
+
def self.truncate_at_separator(text, separator)
|
11
|
+
text = text.encode('UTF-8') if text.respond_to?(:encode)
|
12
|
+
doc = Nokogiri::HTML::DocumentFragment.parse text
|
13
|
+
length = doc.inner_text =~ Regexp.new(separator)
|
14
|
+
if length
|
15
|
+
doc.truncate(length - 1, '').inner_html
|
16
|
+
else
|
17
|
+
text
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.truncate_at_length(text, max_length, ellipsis = "...")
|
11
22
|
ellipsis_length = ellipsis.length
|
12
23
|
text = text.encode('UTF-8') if text.respond_to?(:encode)
|
13
24
|
doc = Nokogiri::HTML::DocumentFragment.parse text
|
@@ -41,7 +41,7 @@ module Middleman
|
|
41
41
|
# @param [Addressable::Template] template
|
42
42
|
# @param [String] path
|
43
43
|
def extract_params(template, path)
|
44
|
-
|
44
|
+
template.extract(path, BlogTemplateProcessor)
|
45
45
|
end
|
46
46
|
|
47
47
|
# Parameterize a string preserving any multibyte characters
|
data/middleman-blog.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: middleman-blog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Reynolds
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-04-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: middleman-core
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 2.
|
48
|
+
version: '2.3'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 2.
|
55
|
+
version: '2.3'
|
56
56
|
description: Blog engine for Middleman
|
57
57
|
email:
|
58
58
|
- me@tdreyno.com
|
@@ -244,6 +244,7 @@ files:
|
|
244
244
|
- fixtures/paginate-app/config-directory-indexes.rb
|
245
245
|
- fixtures/paginate-app/config-paginate-off.rb
|
246
246
|
- fixtures/paginate-app/config.rb
|
247
|
+
- fixtures/paginate-app/source/_pager.erb
|
247
248
|
- fixtures/paginate-app/source/blog/2011-01-01-test-article.html.markdown
|
248
249
|
- fixtures/paginate-app/source/blog/2011-01-02-test-article.html.markdown
|
249
250
|
- fixtures/paginate-app/source/blog/2011-01-03-test-article.html.markdown
|
@@ -255,6 +256,7 @@ files:
|
|
255
256
|
- fixtures/paginate-app/source/category.html.erb
|
256
257
|
- fixtures/paginate-app/source/index.html.erb
|
257
258
|
- fixtures/paginate-app/source/layout.erb
|
259
|
+
- fixtures/paginate-app/source/partial-paging.html.erb
|
258
260
|
- fixtures/paginate-app/source/tag.html.erb
|
259
261
|
- fixtures/paginate-multiblog-app/config.rb
|
260
262
|
- fixtures/paginate-multiblog-app/source/blog1/2011-01-01-test-article.html.markdown
|
@@ -333,6 +335,8 @@ files:
|
|
333
335
|
- lib/middleman-blog/blog_article.rb
|
334
336
|
- lib/middleman-blog/blog_data.rb
|
335
337
|
- lib/middleman-blog/calendar_pages.rb
|
338
|
+
- lib/middleman-blog/commands/article.rb
|
339
|
+
- lib/middleman-blog/commands/article.tt
|
336
340
|
- lib/middleman-blog/custom_pages.rb
|
337
341
|
- lib/middleman-blog/extension.rb
|
338
342
|
- lib/middleman-blog/helpers.rb
|
@@ -543,6 +547,7 @@ test_files:
|
|
543
547
|
- fixtures/paginate-app/config-directory-indexes.rb
|
544
548
|
- fixtures/paginate-app/config-paginate-off.rb
|
545
549
|
- fixtures/paginate-app/config.rb
|
550
|
+
- fixtures/paginate-app/source/_pager.erb
|
546
551
|
- fixtures/paginate-app/source/blog/2011-01-01-test-article.html.markdown
|
547
552
|
- fixtures/paginate-app/source/blog/2011-01-02-test-article.html.markdown
|
548
553
|
- fixtures/paginate-app/source/blog/2011-01-03-test-article.html.markdown
|
@@ -554,6 +559,7 @@ test_files:
|
|
554
559
|
- fixtures/paginate-app/source/category.html.erb
|
555
560
|
- fixtures/paginate-app/source/index.html.erb
|
556
561
|
- fixtures/paginate-app/source/layout.erb
|
562
|
+
- fixtures/paginate-app/source/partial-paging.html.erb
|
557
563
|
- fixtures/paginate-app/source/tag.html.erb
|
558
564
|
- fixtures/paginate-multiblog-app/config.rb
|
559
565
|
- fixtures/paginate-multiblog-app/source/blog1/2011-01-01-test-article.html.markdown
|