nanoc3 3.1.0a2 → 3.1.0a3

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