middleman-blog 3.3.0 → 3.4.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -2
  3. data/Gemfile-3.0 +1 -1
  4. data/features/custom_collections.feature +70 -0
  5. data/features/custom_collections_multiblog.feature +58 -0
  6. data/features/custom_permalinks_feature.feature +33 -0
  7. data/features/tags_multiblog.feature +28 -2
  8. data/fixtures/calendar-and-tag-app/config-directory-indexes.rb +0 -1
  9. data/fixtures/calendar-app/config-directory-indexes.rb +0 -1
  10. data/fixtures/custom-collections-app/config-blog-prefix.rb +13 -0
  11. data/fixtures/custom-collections-app/config-directory-indexes.rb +13 -0
  12. data/fixtures/custom-collections-app/config.rb +12 -0
  13. data/fixtures/custom-collections-app/source/blog/2011-01-01-new-article.html.markdown +8 -0
  14. data/fixtures/custom-collections-app/source/blog/2011-01-02-another-article.html.markdown +9 -0
  15. data/fixtures/custom-collections-app/source/category.html.erb +7 -0
  16. data/fixtures/custom-collections-app/source/index.html.erb +5 -0
  17. data/fixtures/custom-collections-app/source/layout.erb +13 -0
  18. data/fixtures/custom-collections-multiblog-app/config.rb +27 -0
  19. data/fixtures/custom-collections-multiblog-app/source/blog1/2011-01-01-new-article.html.markdown +7 -0
  20. data/fixtures/custom-collections-multiblog-app/source/blog1/2011-01-02-another-article.html.markdown +7 -0
  21. data/fixtures/custom-collections-multiblog-app/source/blog2/2011-01-01-new-article.html.markdown +7 -0
  22. data/fixtures/custom-collections-multiblog-app/source/blog2/2011-01-02-another-article.html.markdown +7 -0
  23. data/fixtures/custom-collections-multiblog-app/source/category1.html.erb +7 -0
  24. data/fixtures/custom-collections-multiblog-app/source/category2.html.erb +7 -0
  25. data/fixtures/custom-collections-multiblog-app/source/index.html.erb +8 -0
  26. data/fixtures/custom-collections-multiblog-app/source/layout.erb +13 -0
  27. data/fixtures/custom-permalinks-app/config-directory-indexes.rb +7 -0
  28. data/fixtures/custom-permalinks-app/config.rb +5 -0
  29. data/fixtures/custom-permalinks-app/source/blog/2011-01-01-new-article.html.markdown +7 -0
  30. data/fixtures/custom-permalinks-app/source/blog/2011-01-02-another-article.html.markdown +7 -0
  31. data/fixtures/custom-permalinks-app/source/blog/2011-01-03-third-article.html.markdown +7 -0
  32. data/fixtures/custom-permalinks-app/source/index.html.erb +3 -0
  33. data/fixtures/custom-permalinks-app/source/layout.erb +13 -0
  34. data/fixtures/indexes-app/config.rb +0 -1
  35. data/fixtures/layouts-app/config.rb +0 -2
  36. data/fixtures/multiblog-app/source/index.html.erb +1 -3
  37. data/fixtures/paginate-app/config-directory-indexes.rb +0 -1
  38. data/fixtures/tags-app/config-directory-indexes.rb +0 -1
  39. data/fixtures/tags-app/config.rb +1 -1
  40. data/fixtures/tags-multiblog-app/config.rb +1 -1
  41. data/fixtures/tags-multiblog-app/source/blog1/frontmatter_blog_tags.html.erb +9 -0
  42. data/fixtures/tags-multiblog-app/source/blog1/named_blog_tags.html.erb +5 -0
  43. data/fixtures/tags-multiblog-app/source/blog2/frontmatter_blog_tags.html.erb +9 -0
  44. data/fixtures/tags-multiblog-app/source/blog2/named_blog_tags.html.erb +5 -0
  45. data/lib/middleman-blog/blog_article.rb +7 -2
  46. data/lib/middleman-blog/blog_data.rb +37 -20
  47. data/lib/middleman-blog/custom_pages.rb +85 -0
  48. data/lib/middleman-blog/extension_3_0.rb +28 -1
  49. data/lib/middleman-blog/extension_3_1.rb +71 -1
  50. data/lib/middleman-blog/paginator.rb +2 -2
  51. data/lib/middleman-blog/template/source/feed.xml.builder +1 -1
  52. data/lib/middleman-blog/template/source/layout.erb +1 -0
  53. data/lib/middleman-blog/version.rb +1 -1
  54. data/middleman-blog.gemspec +1 -2
  55. metadata +67 -18
@@ -0,0 +1,8 @@
1
+ <% blog(:blog_name_1).articles[0...12].each do |article| %>
2
+ <li><a href="<%= article.url %>"><%= article.title %></a> <time><%= article.date.strftime('%b %e') %></time></li>
3
+ <% end %>
4
+ <% blog(:blog_name_2).articles[0...12].each do |article| %>
5
+ <li><a href="<%= article.url %>"><%= article.title %></a> <time><%= article.date.strftime('%b %e') %></time></li>
6
+ <% end %>
7
+ Category Path1: '<%= category_path("ruby-on-rails", :blog_name_1) %>'
8
+ Category Path2: '<%= category_path("javascript", :blog_name_2) %>'
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ </head>
5
+ <body>
6
+ <% if is_blog_article? %>
7
+ <%= current_article.url %>
8
+ <%= yield %>
9
+ <% else %>
10
+ <%= yield %>
11
+ <% end %>
12
+ </body>
13
+ </html>
@@ -0,0 +1,7 @@
1
+ require "middleman-blog"
2
+ activate :blog do |blog|
3
+ blog.sources = "blog/:year-:month-:day-:title.html"
4
+ blog.permalink = "blog/:category/:title.html"
5
+ end
6
+
7
+ activate :directory_indexes
@@ -0,0 +1,5 @@
1
+ require "middleman-blog"
2
+ activate :blog do |blog|
3
+ blog.sources = "blog/:year-:month-:day-:title.html"
4
+ blog.permalink = "blog/:category/:title.html"
5
+ end
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: "Newer Article"
3
+ date: 2011-01-01
4
+ category: ruby-on-rails
5
+ ---
6
+
7
+ Newer Article Content
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: "Another Article"
3
+ date: 2011-01-02
4
+ category: html5
5
+ ---
6
+
7
+ Another Article Content
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: "Parameterize me"
3
+ date: 2011-01-03
4
+ category: Ruby on Rails
5
+ ---
6
+
7
+ Another Article Content
@@ -0,0 +1,3 @@
1
+ <% blog.articles[0...12].each do |article| %>
2
+ <li><a href="<%= article.url %>"><%= article.title %></a> <time><%= article.date.strftime('%b %e') %></time></li>
3
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ </head>
5
+ <body>
6
+ <% if is_blog_article? %>
7
+ <%= current_article.url %>
8
+ <%= yield %>
9
+ <% else %>
10
+ <%= yield %>
11
+ <% end %>
12
+ </body>
13
+ </html>
@@ -2,5 +2,4 @@ activate :blog do |blog|
2
2
  blog.sources = ":year/:month/:day/:title.html"
3
3
  end
4
4
 
5
- require "middleman-more"
6
5
  activate :directory_indexes
@@ -1,5 +1,3 @@
1
1
  activate :blog do |blog|
2
2
  blog.sources = ":year/:month/:day/:title.html"
3
3
  end
4
-
5
- require "middleman-more"
@@ -1,7 +1,5 @@
1
- <p>Default blog length: <%= blog.articles.length %></p>
2
-
3
1
  <p>blog_number_1 length: <%= blog(:blog_number_1).articles.length %></p>
4
2
  <p>blog_number_1 title: <%= blog(:blog_number_1).articles[0].data.title %></p>
5
3
 
6
4
  <p>blog_number_2 length: <%= blog("blog_number_2").articles.length %></p>
7
- <p>blog_number_2 title: <%= blog("blog_number_2").articles[0].data.title %></p>
5
+ <p>blog_number_2 title: <%= blog("blog_number_2").articles[0].data.title %></p>
@@ -7,5 +7,4 @@ activate :blog do |blog|
7
7
  blog.per_page = 5
8
8
  end
9
9
 
10
- require "middleman-more"
11
10
  activate :directory_indexes
@@ -5,5 +5,4 @@ activate :blog do |blog|
5
5
  blog.tag_template = "/tag.html"
6
6
  end
7
7
 
8
- require "middleman-more"
9
8
  activate :directory_indexes
@@ -3,4 +3,4 @@ activate :blog do |blog|
3
3
  blog.sources = "blog/:year-:month-:day-:title.html"
4
4
  blog.permalink = "blog/:year-:month-:day-:title.html"
5
5
  blog.tag_template = "/tag.html"
6
- end
6
+ end
@@ -12,4 +12,4 @@ activate :blog do |blog|
12
12
  blog.sources = ":year-:month-:day-:title.html"
13
13
  blog.permalink = ":year-:month-:day-:title.html"
14
14
  blog.tag_template = "tag2.html"
15
- end
15
+ end
@@ -0,0 +1,9 @@
1
+ ---
2
+ blog: blog_name_1
3
+ ---
4
+
5
+ <% blog().tags.each do |tag, articles| %>
6
+ <section>
7
+ <h2><%= tag %> (<%= articles.size %>)</h2>
8
+ </section>
9
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% blog("blog_name_1").tags.each do |tag, articles| %>
2
+ <section>
3
+ <h2><%= tag %> (<%= articles.size %>)</h2>
4
+ </section>
5
+ <% end %>
@@ -0,0 +1,9 @@
1
+ ---
2
+ blog: blog_name_2
3
+ ---
4
+
5
+ <% blog().tags.each do |tag, articles| %>
6
+ <section>
7
+ <h2><%= tag %> (<%= articles.size %>)</h2>
8
+ </section>
9
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% blog("blog_name_2").tags.each do |tag, articles| %>
2
+ <section>
3
+ <h2><%= tag %> (<%= articles.size %>)</h2>
4
+ </section>
5
+ <% end %>
@@ -129,7 +129,6 @@ module Middleman
129
129
  # @return [String]
130
130
  def path_part(part)
131
131
  @_path_parts ||= blog_data.path_matcher.match(path).captures
132
-
133
132
  @_path_parts[blog_data.matcher_indexes[part]]
134
133
  end
135
134
 
@@ -176,8 +175,10 @@ module Middleman
176
175
 
177
176
  @_slug ||= if blog_options.sources.include?(":title")
178
177
  path_part("title")
179
- else
178
+ elsif title
180
179
  title.parameterize
180
+ else
181
+ raise "Can't generate a slug for #{path} because it has no :title in its path pattern or title/slug in its frontmatter."
181
182
  end
182
183
  end
183
184
 
@@ -194,6 +195,10 @@ module Middleman
194
195
  def next_article
195
196
  blog_data.articles.reverse.find {|a| a.date > self.date }
196
197
  end
198
+
199
+ def inspect
200
+ "#<Middleman::Blog::BlogArticle: #{data.inspect}>"
201
+ end
197
202
  end
198
203
  end
199
204
  end
@@ -7,7 +7,7 @@ module Middleman
7
7
  # A regex for matching blog article source paths
8
8
  # @return [Regex]
9
9
  attr_reader :path_matcher
10
-
10
+
11
11
  # A hash of indexes into the path_matcher captures
12
12
  # @return [Hash]
13
13
  attr_reader :matcher_indexes
@@ -18,6 +18,8 @@ module Middleman
18
18
 
19
19
  attr_reader :controller
20
20
 
21
+ DEFAULT_PERMALINK_COMPONENTS = [:year, :month, :day, :title]
22
+
21
23
  # @private
22
24
  def initialize(app, options={}, controller=nil)
23
25
  @app = app
@@ -26,7 +28,7 @@ module Middleman
26
28
 
27
29
  # A list of resources corresponding to blog articles
28
30
  @_articles = []
29
-
31
+
30
32
  matcher = Regexp.escape(options.sources).
31
33
  sub(/^\//, "").
32
34
  gsub(":year", "(\\d{4})").
@@ -105,24 +107,17 @@ module Middleman
105
107
 
106
108
  # compute output path:
107
109
  # substitute date parts to path pattern
108
- resource.destination_path = options.permalink.
109
- sub(':year', resource.date.year.to_s).
110
- sub(':month', resource.date.month.to_s.rjust(2,'0')).
111
- sub(':day', resource.date.day.to_s.rjust(2,'0')).
112
- sub(':title', resource.slug)
113
-
114
- resource.destination_path = Middleman::Util.normalize_path(resource.destination_path)
110
+ resource.destination_path = Middleman::Util.normalize_path parse_permalink_options(resource)
115
111
 
116
112
  @_articles << resource
117
113
 
118
114
  elsif resource.path =~ @subdir_matcher
119
115
  match = $~.captures
120
116
 
121
- article_path = options.sources.
122
- sub(':year', match[@matcher_indexes["year"]]).
123
- sub(':month', match[@matcher_indexes["month"]]).
124
- sub(':day', match[@matcher_indexes["day"]]).
125
- sub(':title', match[@matcher_indexes["title"]])
117
+ article_path = options.sources
118
+ %w(year month day title).each do |token|
119
+ article_path = article_path.sub(":#{token}", match[@matcher_indexes[token]]) if @matcher_indexes[token]
120
+ end
126
121
 
127
122
  article = @app.sitemap.find_resource_by_path(article_path)
128
123
  raise "Article for #{resource.path} not found" if article.nil?
@@ -133,11 +128,7 @@ module Middleman
133
128
 
134
129
  # The subdir path is the article path with the index file name
135
130
  # or file extension stripped off.
136
- resource.destination_path = options.permalink.
137
- sub(':year', article.date.year.to_s).
138
- sub(':month', article.date.month.to_s.rjust(2,'0')).
139
- sub(':day', article.date.day.to_s.rjust(2,'0')).
140
- sub(':title', article.slug).
131
+ resource.destination_path = parse_permalink_options(article).
141
132
  sub(/(\/#{@app.index_file}$)|(\.[^.]+$)|(\/$)/, match[@matcher_indexes["path"]])
142
133
 
143
134
  resource.destination_path = Middleman::Util.normalize_path(resource.destination_path)
@@ -145,9 +136,35 @@ module Middleman
145
136
 
146
137
  used_resources << resource
147
138
  end
148
-
139
+
149
140
  used_resources
150
141
  end
142
+
143
+ def parse_permalink_options(resource)
144
+ permalink = options.permalink.
145
+ sub(':year', resource.date.year.to_s).
146
+ sub(':month', resource.date.month.to_s.rjust(2, '0')).
147
+ sub(':day', resource.date.day.to_s.rjust(2, '0')).
148
+ sub(':title', resource.slug)
149
+
150
+ custom_permalink_components.each do |component|
151
+ permalink = permalink.sub(":#{component}", resource.data[component].parameterize)
152
+ end
153
+
154
+ permalink
155
+ end
156
+
157
+ def custom_permalink_components
158
+ permalink_url_components.reject { |component| DEFAULT_PERMALINK_COMPONENTS.include? component.to_sym }
159
+ end
160
+
161
+ def permalink_url_components
162
+ options.permalink.scan(/:([A-Za-z0-9]+)/).flatten
163
+ end
164
+
165
+ def inspect
166
+ "#<Middleman::Blog::BlogData: #{articles.inspect}>"
167
+ end
151
168
  end
152
169
  end
153
170
  end
@@ -0,0 +1,85 @@
1
+ module Middleman
2
+ module Blog
3
+
4
+ class CustomPages
5
+
6
+ class << self
7
+
8
+ # Return a path to the given property / value pair
9
+ #
10
+ # @param [Hash] blog_options
11
+ # @param [String|Symbol] property Frontmatter property used to collect on
12
+ # @param [String| value Frontmatter value for the given article for the given property
13
+ def link(blog_options, property, value)
14
+ link_template = blog_options.custom_collections[property][:link]
15
+ ::Middleman::Util.normalize_path(link_template.sub(":#{property}", value.parameterize))
16
+ end
17
+
18
+ end
19
+
20
+ attr_reader :property, :app, :blog_controller
21
+
22
+ def initialize(property, app, controller = nil)
23
+ @property = property
24
+ @app = app
25
+ @blog_controller = controller
26
+ end
27
+
28
+ def blog_data
29
+ if blog_controller
30
+ blog_controller.data
31
+ else
32
+ app.blog
33
+ end
34
+ end
35
+
36
+ def blog_options
37
+ if blog_controller
38
+ blog_controller.options
39
+ else
40
+ app.blog.options
41
+ end
42
+ end
43
+
44
+ def articles
45
+ blog_data.articles
46
+ end
47
+
48
+ def manipulate_resource_list(resources)
49
+ new_resources = []
50
+
51
+ articles.group_by { |a| a.data[property] }.each do |property_value, property_articles|
52
+ path = CustomPages.link(blog_options, property, property_value)
53
+ new_resources << build_resource(path, property_value, property_articles)
54
+ end
55
+
56
+ resources + new_resources
57
+ end
58
+
59
+ def build_resource(path, value, property_articles)
60
+ p = ::Middleman::Sitemap::Resource.new(app.sitemap, path)
61
+ p.proxy_to(template_for_page)
62
+ p.add_metadata :locals => {
63
+ "page_type" => property,
64
+ "#{property}" => value,
65
+ "articles" => property_articles,
66
+ "blog_controller" => blog_controller
67
+ }
68
+
69
+ prop_name = property
70
+ p.add_metadata do
71
+ instance_variable_set("@#{prop_name}", value)
72
+ @articles = property_articles
73
+ end
74
+
75
+ p
76
+ end
77
+
78
+ def template_for_page
79
+ blog_options.custom_collections[property][:template]
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
@@ -22,7 +22,8 @@ module Middleman
22
22
  :paginate,
23
23
  :per_page,
24
24
  :page_link,
25
- :publish_future_dated
25
+ :publish_future_dated,
26
+ :custom_collections
26
27
  ]
27
28
 
28
29
  KEYS.each do |name|
@@ -61,6 +62,7 @@ module Middleman
61
62
  options.per_page ||= 10
62
63
  options.page_link ||= "page/:num"
63
64
  options.publish_future_dated ||= false
65
+ options.custom_collections ||= {}
64
66
 
65
67
  # optional: :tag_template
66
68
  # optional: :year_template
@@ -82,6 +84,10 @@ module Middleman
82
84
  options.year_link = File.join(options.prefix, options.year_link)
83
85
  options.month_link = File.join(options.prefix, options.month_link)
84
86
  options.day_link = File.join(options.prefix, options.day_link)
87
+
88
+ options.custom_collections.each do |key, opts|
89
+ opts[:link] = File.join(options.prefix, opts[:link])
90
+ end
85
91
  end
86
92
 
87
93
  app.after_configuration do
@@ -141,6 +147,27 @@ module Middleman
141
147
  false
142
148
  )
143
149
  end
150
+
151
+ if options.custom_collections
152
+ require 'middleman-blog/custom_pages'
153
+ options.custom_collections.each do |property, options|
154
+ ignore options[:template]
155
+ sitemap.register_resource_list_manipulator(
156
+ :"blog_#{property}",
157
+ CustomPages.new(property, self),
158
+ false
159
+ )
160
+
161
+ m = Module.new
162
+ m.module_eval(%Q{
163
+ def #{property}_path(value, key = nil)
164
+ sitemap.find_resource_by_path(CustomPages.link(self.blog.options, :#{property}, value)).try(:url)
165
+ end
166
+ })
167
+
168
+ self.class.send(:include, m)
169
+ end
170
+ end
144
171
  end
145
172
  end
146
173
  alias :included :registered