middleman-blog 3.3.0 → 3.4.1

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