nanoc3 3.1.0a2 → 3.1.0a3

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 (46) hide show
  1. data/LICENSE +1 -1
  2. data/NEWS.md +12 -2
  3. data/README.md +2 -0
  4. data/lib/nanoc3/base/code_snippet.rb +6 -2
  5. data/lib/nanoc3/base/compiler.rb +9 -6
  6. data/lib/nanoc3/base/compiler_dsl.rb +15 -9
  7. data/lib/nanoc3/base/data_source.rb +14 -14
  8. data/lib/nanoc3/base/dependency_tracker.rb +9 -9
  9. data/lib/nanoc3/base/directed_graph.rb +6 -7
  10. data/lib/nanoc3/base/errors.rb +48 -13
  11. data/lib/nanoc3/base/filter.rb +62 -16
  12. data/lib/nanoc3/base/item.rb +63 -20
  13. data/lib/nanoc3/base/item_rep.rb +117 -48
  14. data/lib/nanoc3/base/layout.rb +18 -5
  15. data/lib/nanoc3/base/notification_center.rb +8 -8
  16. data/lib/nanoc3/base/plugin_registry.rb +9 -9
  17. data/lib/nanoc3/base/rule.rb +8 -8
  18. data/lib/nanoc3/base/rule_context.rb +5 -5
  19. data/lib/nanoc3/base/site.rb +33 -29
  20. data/lib/nanoc3/cli/base.rb +1 -1
  21. data/lib/nanoc3/cli/commands/create_site.rb +12 -14
  22. data/lib/nanoc3/cli.rb +0 -1
  23. data/lib/nanoc3/data_sources/filesystem.rb +12 -2
  24. data/lib/nanoc3/data_sources/filesystem_unified.rb +22 -19
  25. data/lib/nanoc3/extra/auto_compiler.rb +12 -3
  26. data/lib/nanoc3/extra/chick.rb +12 -6
  27. data/lib/nanoc3/extra/deployers/rsync.rb +30 -27
  28. data/lib/nanoc3/extra/deployers.rb +0 -1
  29. data/lib/nanoc3/extra/file_proxy.rb +2 -15
  30. data/lib/nanoc3/extra/validators/links.rb +242 -0
  31. data/lib/nanoc3/extra/validators/w3c.rb +49 -25
  32. data/lib/nanoc3/extra/validators.rb +2 -2
  33. data/lib/nanoc3/extra/vcs.rb +1 -1
  34. data/lib/nanoc3/extra.rb +4 -1
  35. data/lib/nanoc3/helpers/blogging.rb +57 -29
  36. data/lib/nanoc3/helpers/breadcrumbs.rb +1 -1
  37. data/lib/nanoc3/helpers/capturing.rb +4 -2
  38. data/lib/nanoc3/helpers/filtering.rb +2 -1
  39. data/lib/nanoc3/helpers/link_to.rb +13 -6
  40. data/lib/nanoc3/helpers/rendering.rb +4 -3
  41. data/lib/nanoc3/helpers/tagging.rb +7 -6
  42. data/lib/nanoc3/helpers/text.rb +2 -2
  43. data/lib/nanoc3/tasks/validate.rake +62 -5
  44. data/lib/nanoc3.rb +2 -2
  45. metadata +23 -11
  46. data/lib/nanoc3/base/core_ext/enumerable.rb +0 -41
@@ -0,0 +1,242 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc3::Extra::Validators
4
+
5
+ # A validator that verifies that all links (`<a href="…">…</a>`) point to a
6
+ # location that exists.
7
+ class Links
8
+
9
+ # @param [String] dir The directory that will be searched for HTML files
10
+ # to validate
11
+ #
12
+ # @param [Array<String>] index_filenames An array of index filenames that
13
+ # will be appended to URLs by web servers if a directory is requested
14
+ # instead of a file
15
+ #
16
+ # @option params [Boolean] :internal (false) True if internal links should
17
+ # be checked; false if they should not
18
+ #
19
+ # @option params [Boolean] :external (false) True if external links should
20
+ # be checked; false if they should not
21
+ def initialize(dir, index_filenames, params={})
22
+ @dir = dir
23
+ @index_filenames = index_filenames
24
+ @include_internal = params.has_key?(:internal) && params[:internal]
25
+ @include_external = params.has_key?(:external) && params[:external]
26
+ end
27
+
28
+ # Starts the validator. The results will be printed to stdout.
29
+ #
30
+ # @return [void]
31
+ def run
32
+ require 'nokogiri'
33
+
34
+ @delegate = self
35
+ links = all_broken_hrefs
36
+ if links.empty?
37
+ puts "No broken links found!"
38
+ else
39
+ links.each_pair do |href, origins|
40
+ puts "Broken link: #{href} -- referenced from:"
41
+ origins.each do |origin|
42
+ puts " #{origin}"
43
+ end
44
+ puts
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def all_broken_hrefs
52
+ broken_hrefs = {}
53
+
54
+ internal_hrefs = {}
55
+ external_hrefs = {}
56
+
57
+ # Split into internal and external hrefs
58
+ all_hrefs_per_filename.each_pair do |filename, hrefs|
59
+ hrefs.each do |href|
60
+ if is_external_href?(href)
61
+ external_hrefs[href] ||= []
62
+ external_hrefs[href] << filename
63
+ else
64
+ internal_hrefs[href] ||= []
65
+ internal_hrefs[href] << filename
66
+ end
67
+ end
68
+ end
69
+
70
+ # Validate hrefs
71
+ validate_internal_hrefs(internal_hrefs, broken_hrefs) if @include_internal
72
+ validate_external_hrefs(external_hrefs, broken_hrefs) if @include_external
73
+
74
+ # Done
75
+ broken_hrefs
76
+ end
77
+
78
+ def all_files
79
+ Dir[@dir + '/**/*.html']
80
+ end
81
+
82
+ def all_hrefs_per_filename
83
+ hrefs = {}
84
+ all_files.each do |filename|
85
+ hrefs[filename] ||= all_hrefs_in_file(filename)
86
+ end
87
+ hrefs
88
+ end
89
+
90
+ def all_hrefs_in_file(filename)
91
+ doc = Nokogiri::HTML(::File.read(filename))
92
+ doc.css('a').map { |l| l[:href] }.compact
93
+ end
94
+
95
+ def is_external_href?(href)
96
+ !!(href =~ %r{^[a-z\-]+:})
97
+ end
98
+
99
+ def is_valid_internal_href?(href, origin)
100
+ # Skip hrefs that point to self
101
+ # FIXME this is ugly and won’t always be correct
102
+ return true if href == '.'
103
+
104
+ # Remove target
105
+ path = href.sub(/#.*$/, '')
106
+ return true if path.empty?
107
+
108
+ # Make absolute
109
+ if path[0, 1] == '/'
110
+ path = @dir + path
111
+ else
112
+ path = ::File.expand_path(path, ::File.dirname(origin))
113
+ end
114
+
115
+ # Check whether file exists
116
+ return true if File.file?(path)
117
+
118
+ # Check whether directory with index file exists
119
+ return true if File.directory?(path) && @index_filenames.any? { |fn| File.file?(File.join(path, fn)) }
120
+
121
+ # Nope :(
122
+ return false
123
+ end
124
+
125
+ def is_valid_external_href?(href)
126
+ require 'net/http'
127
+ require 'uri'
128
+
129
+ # Parse
130
+ uri = URI.parse(href)
131
+
132
+ # Skip non-HTTP URLs
133
+ return true if uri.scheme != 'http'
134
+
135
+ # Get status
136
+ status = fetch_http_status_for(uri)
137
+ is_valid = (status && status >= 200 && status <= 299)
138
+
139
+ # Notify
140
+ @delegate.send(:external_href_validated, href, is_valid)
141
+
142
+ # Done
143
+ is_valid
144
+ end
145
+
146
+ def validate_internal_hrefs(hrefs, broken_hrefs)
147
+ hrefs.each_pair do |href, filenames|
148
+ filenames.each do |filename|
149
+ if !is_valid_internal_href?(href, filename)
150
+ broken_hrefs[href] = filenames
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ class EachPairEnumerator
157
+
158
+ def initialize(hash)
159
+ @hash = hash
160
+ @unprocessed_keys = @hash.keys.dup
161
+ @mutex = Mutex.new
162
+ end
163
+
164
+ def next_pair
165
+ @mutex.synchronize do
166
+ key = @unprocessed_keys.shift
167
+ return (key ? [ key, @hash[key] ] : nil)
168
+ end
169
+ end
170
+
171
+ end
172
+
173
+ def validate_external_hrefs(hrefs, broken_hrefs)
174
+ @mutex = Mutex.new
175
+
176
+ enum = EachPairEnumerator.new(hrefs)
177
+
178
+ threads = []
179
+ 10.times do
180
+ threads << Thread.new do
181
+ loop do
182
+ # Get next pair
183
+ pair = enum.next_pair
184
+ break if pair.nil?
185
+ href, filenames = pair[0], pair[1]
186
+
187
+ # Validate
188
+ if !is_valid_external_href?(href)
189
+ @mutex.synchronize do
190
+ broken_hrefs[href] = filenames
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+ threads.each { |t| t.join }
197
+ end
198
+
199
+ def fetch_http_status_for(url, params={})
200
+ 5.times do |i|
201
+ begin
202
+ res = request_url_once(url)
203
+
204
+ if res.code =~ /^3..$/
205
+ url = URI.parse(res['location'])
206
+ return nil if i == 5
207
+ else
208
+ return res.code.to_i
209
+ end
210
+ rescue
211
+ nil
212
+ end
213
+ end
214
+ end
215
+
216
+ def request_url_once(url)
217
+ path = (url.path.nil? || url.path.empty? ? '/' : url.path)
218
+ req = Net::HTTP::Head.new(path)
219
+ res = Net::HTTP.start(url.host, url.port) { |h| h.request(req) }
220
+ res
221
+ end
222
+
223
+ def external_href_validated(href, is_valid)
224
+ texts = {
225
+ true => 'ok',
226
+ false => ' ERROR '
227
+ }
228
+
229
+ colors = {
230
+ true => "\e[32m",
231
+ false => "\e[41m\e[37m",
232
+ :off => "\033[0m"
233
+ }
234
+
235
+ @mutex.synchronize do
236
+ puts href + ': ' + colors[is_valid] + texts[is_valid] + colors[:off]
237
+ end
238
+ end
239
+
240
+ end
241
+
242
+ end
@@ -2,55 +2,79 @@
2
2
 
3
3
  module Nanoc3::Extra::Validators
4
4
 
5
- # Nanoc3::Extra::Validators::W3C is a validator that uses the W3C web
6
- # service to validate HTML and CSS files.
5
+ # A validator that uses the W3C web service to validate HTML and CSS files.
7
6
  class W3C
8
7
 
9
- def initialize(site, type)
10
- @site = site
11
- @type = type
8
+ # @param [String] dir The directory that will be searched for HTML and/or
9
+ # CSS files to validate
10
+ #
11
+ # @param [Array<Symbol>] types A list of types to check. Allowed types are
12
+ # `:html` and `:css`.
13
+ def initialize(dir, types)
14
+ @dir = dir
15
+ @types = types
12
16
  end
13
17
 
18
+ # Starts the validator. The results will be printed to stdout.
19
+ #
20
+ # @return [void]
14
21
  def run
15
22
  # Load validator
16
23
  require 'w3c_validators'
17
24
 
18
- # Make sure config is loaded
19
- @site.load_data
20
-
21
25
  # Find all files
22
- files = extensions.map { |extension| Dir["#{@site.config[:output_dir]}/**/*.#{extension}"] }.flatten
26
+ filenames = []
27
+ extensions = types_to_extensions(@types)
28
+ extensions.each { |extension| filenames.concat(Dir[@dir + '/**/*.' + extension]) }
23
29
 
24
30
  # Validate each file
25
- files.each do |file|
26
- validation_started(file)
27
- results = validator.validate_file(file)
28
- validation_ended(file, results.errors)
31
+ filenames.each do |filename|
32
+ validation_started(filename)
33
+
34
+ extension = File.extname(filename)[1..-1]
35
+ results = validator_for(extension).validate_file(filename)
36
+
37
+ validation_ended(filename, results.errors)
29
38
  end
30
39
  end
31
40
 
32
41
  private
33
42
 
34
- def extensions
35
- case @type
36
- when :html
37
- [ 'html', 'htm' ]
38
- when :css
39
- [ 'css' ]
43
+ # Returns all extensions for the given types
44
+ def types_to_extensions(types)
45
+ extensions = []
46
+ types.each { |type| extensions.concat(type_to_extensions(type)) }
47
+ extensions
48
+ end
49
+
50
+ # Returns all extensions for the given type
51
+ def type_to_extensions(type)
52
+ case type
53
+ when :html
54
+ [ 'html', 'htm' ]
55
+ when :css
56
+ [ 'css' ]
57
+ else
58
+ raise RuntimeError, "unknown type: #{type}"
40
59
  end
41
60
  end
42
61
 
43
- def validator_class
44
- case @type
45
- when :html
62
+ # Returns the validator class for the given extension
63
+ def validator_class_for(extension)
64
+ case extension
65
+ when 'html', 'htm'
46
66
  ::W3CValidators::MarkupValidator
47
- when :css
67
+ when 'css'
48
68
  ::W3CValidators::CSSValidator
69
+ else
70
+ raise RuntimeError, "unknown extension: #{extension}"
49
71
  end
50
72
  end
51
73
 
52
- def validator
53
- @validator ||= validator_class.new
74
+ # Returns the validator for the given extension
75
+ def validator_for(extension)
76
+ @validators ||= {}
77
+ @validators[extension] ||= validator_class_for(extension).new
54
78
  end
55
79
 
56
80
  def validation_started(file)
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Nanoc3::Extra
4
4
 
5
- # Nanoc3::Extra::Validators is the name for all validators.
6
5
  module Validators
7
6
 
8
- autoload 'W3C', 'nanoc3/extra/validators/w3c'
7
+ autoload 'W3C', 'nanoc3/extra/validators/w3c'
8
+ autoload 'Links', 'nanoc3/extra/validators/links'
9
9
 
10
10
  end
11
11
 
@@ -8,7 +8,7 @@ module Nanoc3::Extra
8
8
  # the disk.
9
9
  #
10
10
  # @abstract Subclass and override {#add}, {#remove} and {#move} to implement
11
- # a custom VCS.
11
+ # a custom VCS.
12
12
  class VCS
13
13
 
14
14
  extend Nanoc3::PluginRegistry::PluginMethods
data/lib/nanoc3/extra.rb CHANGED
@@ -5,13 +5,16 @@ module Nanoc3::Extra
5
5
  autoload 'AutoCompiler', 'nanoc3/extra/auto_compiler'
6
6
  autoload 'CHiCk', 'nanoc3/extra/chick'
7
7
  autoload 'Deployers', 'nanoc3/extra/deployers'
8
- autoload 'FileProxy', 'nanoc3/extra/file_proxy'
9
8
  autoload 'Validators', 'nanoc3/extra/validators'
10
9
 
11
10
  # Deprecated; use {Nanoc3::Context} instead
12
11
  # TODO [in nanoc 4.0] remove me
13
12
  Context = ::Nanoc3::Context
14
13
 
14
+ # Deprecated
15
+ # TODO [in nanoc 4.0] remove me
16
+ autoload 'FileProxy', 'nanoc3/extra/file_proxy'
17
+
15
18
  end
16
19
 
17
20
  require 'nanoc3/extra/core_ext'
@@ -10,13 +10,16 @@ module Nanoc3::Helpers
10
10
  #
11
11
  # * `kind` — Set to `"article"`
12
12
  #
13
- # * `created_at` — The article’s publication timestamp. This timestamp can
14
- # be in any format parseable by `Time.parse`.
13
+ # * `created_at` — The article’s publication timestamp
15
14
  #
16
15
  # Some functions in this blogging helper, such as the {#atom_feed} function,
17
16
  # require additional attributes to be set; these attributes are described in
18
17
  # the documentation for these functions.
19
18
  #
19
+ # All “time” item attributes, site configuration attributes or method
20
+ # parameters can either be a `Time` instance or a string in any format
21
+ # parseable by `Time.parse`.
22
+ #
20
23
  # The two main functions are {#sorted_articles} and {#atom_feed}.
21
24
  module Blogging
22
25
 
@@ -35,7 +38,10 @@ module Nanoc3::Helpers
35
38
  # @return [Array] A sorted array containing all articles
36
39
  def sorted_articles
37
40
  require 'time'
38
- articles.sort_by { |a| t = a[:created_at] ; t.is_a?(String) ? Time.parse(t) : t }.reverse
41
+ articles.sort_by do |a|
42
+ time = a[:created_at]
43
+ time.is_a?(String) ? Time.parse(time) : time
44
+ end.reverse
39
45
  end
40
46
 
41
47
  # Returns a string representing the atom feed containing recent articles,
@@ -58,10 +64,9 @@ module Nanoc3::Helpers
58
64
  # non-outputted items in a feed; such items could have their custom feed
59
65
  # path set to the blog path instead, for example.
60
66
  #
61
- # The feed will also include dates on which the articles were updated.
62
- # These are generated automatically; the way this happens depends on the
63
- # used data source (the filesystem data source checks the file mtimes, for
64
- # instance).
67
+ # * `updated_at` The time when the article was last modified. If this
68
+ # attribute is not present, the `created_at` attribute will be used as
69
+ # the time when the article was last modified.
65
70
  #
66
71
  # The site configuration will need to have the following attributes:
67
72
  #
@@ -69,7 +74,10 @@ module Nanoc3::Helpers
69
74
  # example, if the site is at “http://example.com/”, the `base_url`
70
75
  # would be “http://example.com”.
71
76
  #
72
- # The feed item will need to have the following attributes:
77
+ # The feed item will need to know about the feed title, the feed author
78
+ # name, and the URI corresponding to the author. These can be specified
79
+ # using parameters, as attributes in the feed item, or in the site
80
+ # configuration.
73
81
  #
74
82
  # * `title` — The title of the feed, which is usually also the title of
75
83
  # the blog.
@@ -107,19 +115,28 @@ module Nanoc3::Helpers
107
115
  # <%= atom_feed :limit => 5 %>
108
116
  #
109
117
  # @option params [Number] :limit (5) The maximum number of articles to
110
- # show
118
+ # show
111
119
  #
112
120
  # @option params [Array] :articles (sorted_articles) A list of articles to
113
- # include in the feed
121
+ # include in the feed
114
122
  #
115
123
  # @option params [Proc] :content_proc (->{ |article|
116
- # article.compiled_content(:snapshot => :pre) }) A proc that returns the
117
- # content of the given article, which is passed as a parameter. This
118
- # function may not return nil.
124
+ # article.compiled_content(:snapshot => :pre) }) A proc that returns the
125
+ # content of the given article, which is passed as a parameter. This
126
+ # function may not return nil.
119
127
  #
120
128
  # @option params [proc] :excerpt_proc (->{ |article| article[:excerpt] })
121
- # A proc that returns the excerpt of the given article, passed as a
122
- # parameter. This function should return nil if there is no excerpt.
129
+ # A proc that returns the excerpt of the given article, passed as a
130
+ # parameter. This function should return nil if there is no excerpt.
131
+ #
132
+ # @option params [String] :title The feed’s title, if it is not given in
133
+ # the item attributes.
134
+ #
135
+ # @option params [String] :author_name The name of the feed’s author, if
136
+ # it is not given in the item attributes.
137
+ #
138
+ # @option params [String] :author_uri The URI of the feed’s author, if it
139
+ # is not given in the item attributes.
123
140
  #
124
141
  # @return [String] The generated feed content
125
142
  def atom_feed(params={})
@@ -138,14 +155,17 @@ module Nanoc3::Helpers
138
155
  end
139
156
 
140
157
  # Check feed item attributes
141
- if @item[:title].nil?
142
- raise RuntimeError.new('Cannot build Atom feed: feed item has no title')
158
+ title = params[:title] || @item[:title] || @site.config[:title]
159
+ if title.nil?
160
+ raise RuntimeError.new('Cannot build Atom feed: no title in params, item or site config')
143
161
  end
144
- if @item[:author_name].nil?
145
- raise RuntimeError.new('Cannot build Atom feed: feed item has no author_name')
162
+ author_name = params[:author_name] || @item[:author_name] || @site.config[:author_name]
163
+ if author_name.nil?
164
+ raise RuntimeError.new('Cannot build Atom feed: no author_name in params, item or site config')
146
165
  end
147
- if @item[:author_uri].nil?
148
- raise RuntimeError.new('Cannot build Atom feed: feed item has no author_uri')
166
+ author_uri = params[:author_uri] || @item[:author_uri] || @site.config[:author_uri]
167
+ if author_uri.nil?
168
+ raise RuntimeError.new('Cannot build Atom feed: no author_uri in params, item or site config')
149
169
  end
150
170
 
151
171
  # Check article attributes
@@ -157,7 +177,10 @@ module Nanoc3::Helpers
157
177
  end
158
178
 
159
179
  # Get sorted relevant articles
160
- sorted_relevant_articles = relevant_articles.sort_by { |a| Time.parse(a[:created_at]) }.reverse.first(limit)
180
+ sorted_relevant_articles = relevant_articles.sort_by do |a|
181
+ time = a[:created_at]
182
+ time.is_a?(String) ? Time.parse(time) : time
183
+ end.reverse.first(limit)
161
184
 
162
185
  # Get most recent article
163
186
  last_article = sorted_relevant_articles.first
@@ -173,10 +196,11 @@ module Nanoc3::Helpers
173
196
 
174
197
  # Add primary attributes
175
198
  xml.id root_url
176
- xml.title @item[:title]
199
+ xml.title title
177
200
 
178
201
  # Add date
179
- xml.updated Time.parse(last_article[:created_at]).to_iso8601_time
202
+ time = last_article[:created_at]
203
+ xml.updated((time.is_a?(String) ? Time.parse(time) : time).to_iso8601_time)
180
204
 
181
205
  # Add links
182
206
  xml.link(:rel => 'alternate', :href => root_url)
@@ -184,8 +208,8 @@ module Nanoc3::Helpers
184
208
 
185
209
  # Add author information
186
210
  xml.author do
187
- xml.name @item[:author_name]
188
- xml.uri @item[:author_uri]
211
+ xml.name author_name
212
+ xml.uri author_uri
189
213
  end
190
214
 
191
215
  # Add articles
@@ -200,8 +224,10 @@ module Nanoc3::Helpers
200
224
  xml.title a[:title], :type => 'html'
201
225
 
202
226
  # Add dates
203
- xml.published Time.parse(a[:created_at]).to_iso8601_time
204
- xml.updated a.mtime.to_iso8601_time
227
+ create_time = a[:created_at]
228
+ update_time = a[:updated_at] || a[:created_at]
229
+ xml.published ((create_time.is_a?(String) ? Time.parse(create_time) : create_time).to_iso8601_time)
230
+ xml.updated ((update_time.is_a?(String) ? Time.parse(update_time) : update_time).to_iso8601_time)
205
231
 
206
232
  # Add link
207
233
  xml.link(:rel => 'alternate', :href => url)
@@ -263,7 +289,9 @@ module Nanoc3::Helpers
263
289
  require 'time'
264
290
 
265
291
  hostname, base_dir = %r{^.+?://([^/]+)(.*)$}.match(@site.config[:base_url])[1..2]
266
- formatted_date = Time.parse(item[:created_at]).to_iso8601_date
292
+
293
+ time = item[:created_at]
294
+ formatted_date = (time.is_a?(String) ? Time.parse(time) : time).to_iso8601_date
267
295
 
268
296
  'tag:' + hostname + ',' + formatted_date + ':' + base_dir + (item.path || item.identifier)
269
297
  end
@@ -13,7 +13,7 @@ module Nanoc3::Helpers
13
13
  # will contain a `nil` element.
14
14
  #
15
15
  # @return [Array] The breadcrumbs, starting with the root item and ending
16
- # with the item itself
16
+ # with the item itself
17
17
  def breadcrumbs_trail
18
18
  trail = []
19
19
  current_identifier = @item.identifier
@@ -13,11 +13,13 @@ module Nanoc3::Helpers
13
13
  # the sidebar layout.
14
14
  #
15
15
  # @example Capturing content into a `content_for_summary` attribute
16
+ #
16
17
  # <% content_for :summary do %>
17
18
  # <p>On this item, nanoc is introduced, blah blah.</p>
18
19
  # <% end %>
19
20
  #
20
21
  # @example Showing captured content in a sidebar
22
+ #
21
23
  # <div id="sidebar">
22
24
  # <h3>Summary</h3>
23
25
  # <%= @item[:content_for_summary] || '(no summary)' %>
@@ -28,8 +30,8 @@ module Nanoc3::Helpers
28
30
  # attribute named `content_for_` followed by the given name. The
29
31
  # content of the block itself will not be outputted.
30
32
  #
31
- # @param [Symbol, String] The base name of the attribute into which
32
- # the content should be stored
33
+ # @param [Symbol, String] The base name of the attribute into which the
34
+ # content should be stored
33
35
  #
34
36
  # @return [void]
35
37
  def content_for(name, &block)
@@ -16,13 +16,14 @@ module Nanoc3::Helpers
16
16
  # work correctly.
17
17
  #
18
18
  # @example Running a filter on a part of an item or layout
19
+ #
19
20
  # <p>Lorem ipsum dolor sit amet...</p>
20
21
  # <% filter :rubypants do %>
21
22
  # <p>Consectetur adipisicing elit...</p>
22
23
  # <% end %>
23
24
  #
24
25
  # @param [Symbol] filter_name The name of the filter to run on the
25
- # contents of the block
26
+ # contents of the block
26
27
  #
27
28
  # @param [Hash] argument Arguments to pass to the filter
28
29
  #