middleman-blog 4.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
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