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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a954456dd37131a13ebabbdb3cb2cd2876f31c83
4
- data.tar.gz: 9fe2db291d746b24bef90d3acfd16e966f1381c0
3
+ metadata.gz: 6437136847c6ca3dfc732f0585d154969a140967
4
+ data.tar.gz: 7d6a917c2f463b52a95a6b1e5c5fc73ff4e0b120
5
5
  SHA512:
6
- metadata.gz: 97feb50f6597a1123b1e9f06d5a95d7a1479997b921da68ff15d84ba484607bb664de385f7fef4f6547dd972871bc3ff62521f346dcc2d00e4e48f88b7e4248a
7
- data.tar.gz: 6be516bced8dba93bd1320f5b00e69d31466fd41286cb71422e3afc1a03fbda4814ff23f512e610bb27698f056ea3d0ec77ad70c7c39f9299a711f8eb6d73ffc
6
+ metadata.gz: 6b27cbe706b043afb84067b974bdf574bf70e006abb0c111b006c12e9a489f114255456a2152a13d68ae816b3abd9eb02c77c4efc16b5833fcc902ca45106180
7
+ data.tar.gz: 2b26df677ed97f8806102ae623b7d193820e44175b64d7a1d5bbda4b9c48897ddbf39f6f823ba66f1a6020659304010d788978dd7f668a0ece97a6e77faaecba
@@ -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 "Summary from article with custom separator."
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 %>
@@ -0,0 +1,5 @@
1
+ ---
2
+ pageable: true
3
+ ---
4
+
5
+ <%= partial 'pager' %>
@@ -3,5 +3,6 @@ require "middleman-blog/version"
3
3
 
4
4
  ::Middleman::Extensions.register(:blog) do
5
5
  require "middleman-blog/extension"
6
+ require "middleman-blog/commands/article"
6
7
  ::Middleman::BlogExtension
7
8
  end
@@ -73,26 +73,24 @@ module Middleman
73
73
  render layout: false
74
74
  end
75
75
 
76
- # The summary for this article, in HTML. The summary is either
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=blog_options.summary_length, ellipsis='...')
90
+ def summary(length=nil, ellipsis='...')
91
91
  rendered = render layout: false, keep_separator: true
92
92
 
93
- if blog_options.summary_separator && rendered.match(blog_options.summary_separator)
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 blog_options.summary_separator && rendered =~ blog_options.summary_separator
111
- rendered.split(blog_options.summary_separator).first
112
- elsif length && length >= 0
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.truncate_html(rendered, length, ellipsis)
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 = extract_params(@source_template, resource.path))
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 = extract_params(@subdir_template, resource.path))
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, lang: locale }, locals: { lang: locale, locale: 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
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: <%= @title %>
3
+ date: <%= @date.strftime('%F %R %Z') %>
4
+ tags:
5
+ ---
6
+
@@ -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.truncate_html(text, max_length, ellipsis = "...")
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
- params = template.extract(path, BlogTemplateProcessor)
44
+ template.extract(path, BlogTemplateProcessor)
45
45
  end
46
46
 
47
47
  # Parameterize a string preserving any multibyte characters
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  module Blog
3
- VERSION = "4.0.0"
3
+ VERSION = "4.0.1"
4
4
  end
5
5
  end
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.add_dependency("middleman-core", [">= 4.0.0"])
21
21
  s.add_dependency("tzinfo", [">= 0.3.0"])
22
- s.add_dependency("addressable", ["~> 2.4.0"])
22
+ s.add_dependency("addressable", ["~> 2.3"])
23
23
  end
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.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: 2015-12-16 00:00:00.000000000 Z
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.4.0
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.4.0
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