nanoc3 3.2.0a3 → 3.2.0a4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/.gemtest +0 -0
  2. data/LICENSE +1 -1
  3. data/NEWS.md +23 -4
  4. data/README.md +7 -0
  5. data/lib/nanoc3/base/compilation/checksum_store.rb +17 -90
  6. data/lib/nanoc3/base/compilation/compiled_content_cache.rb +5 -0
  7. data/lib/nanoc3/base/compilation/compiler.rb +112 -175
  8. data/lib/nanoc3/base/compilation/compiler_dsl.rb +54 -11
  9. data/lib/nanoc3/base/compilation/dependency_tracker.rb +32 -65
  10. data/lib/nanoc3/base/compilation/filter.rb +4 -3
  11. data/lib/nanoc3/base/compilation/item_rep_proxy.rb +19 -4
  12. data/lib/nanoc3/base/compilation/item_rep_recorder_proxy.rb +90 -0
  13. data/lib/nanoc3/base/compilation/outdatedness_checker.rb +152 -15
  14. data/lib/nanoc3/base/compilation/outdatedness_reasons.rb +12 -9
  15. data/lib/nanoc3/base/compilation/rule.rb +3 -1
  16. data/lib/nanoc3/base/compilation/rule_memory_calculator.rb +42 -0
  17. data/lib/nanoc3/base/compilation/rule_memory_store.rb +53 -0
  18. data/lib/nanoc3/base/compilation/rules_collection.rb +205 -0
  19. data/lib/nanoc3/base/core_ext/array.rb +20 -0
  20. data/lib/nanoc3/base/core_ext/hash.rb +30 -0
  21. data/lib/nanoc3/base/core_ext/pathname.rb +26 -0
  22. data/lib/nanoc3/base/core_ext/string.rb +12 -0
  23. data/lib/nanoc3/base/core_ext.rb +1 -0
  24. data/lib/nanoc3/base/directed_graph.rb +11 -3
  25. data/lib/nanoc3/base/errors.rb +0 -4
  26. data/lib/nanoc3/base/memoization.rb +72 -0
  27. data/lib/nanoc3/base/result_data/item_rep.rb +64 -25
  28. data/lib/nanoc3/base/source_data/code_snippet.rb +9 -0
  29. data/lib/nanoc3/base/source_data/configuration.rb +20 -0
  30. data/lib/nanoc3/base/source_data/item.rb +29 -4
  31. data/lib/nanoc3/base/source_data/layout.rb +20 -1
  32. data/lib/nanoc3/base/source_data/site.rb +49 -26
  33. data/lib/nanoc3/base/store.rb +10 -1
  34. data/lib/nanoc3/base.rb +6 -1
  35. data/lib/nanoc3/cli/base.rb +20 -7
  36. data/lib/nanoc3/cli/commands/compile.rb +0 -2
  37. data/lib/nanoc3/cli/commands/create_site.rb +16 -7
  38. data/lib/nanoc3/cli/commands/debug.rb +3 -3
  39. data/lib/nanoc3/cli/commands/view.rb +1 -0
  40. data/lib/nanoc3/cli/commands/watch.rb +2 -1
  41. data/lib/nanoc3/data_sources/deprecated/delicious.rb +0 -2
  42. data/lib/nanoc3/data_sources/deprecated/last_fm.rb +0 -2
  43. data/lib/nanoc3/data_sources/deprecated/twitter.rb +0 -2
  44. data/lib/nanoc3/data_sources/filesystem.rb +17 -3
  45. data/lib/nanoc3/data_sources/filesystem_unified.rb +17 -17
  46. data/lib/nanoc3/extra/auto_compiler.rb +5 -1
  47. data/lib/nanoc3/extra/core_ext/time.rb +1 -1
  48. data/lib/nanoc3/extra/file_proxy.rb +11 -1
  49. data/lib/nanoc3/extra/validators/links.rb +1 -1
  50. data/lib/nanoc3/filters/asciidoc.rb +3 -3
  51. data/lib/nanoc3/filters/colorize_syntax.rb +106 -27
  52. data/lib/nanoc3/filters/erb.rb +16 -6
  53. data/lib/nanoc3/filters/erubis.rb +5 -1
  54. data/lib/nanoc3/filters/haml.rb +2 -1
  55. data/lib/nanoc3/filters/less.rb +3 -6
  56. data/lib/nanoc3/filters/mustache.rb +3 -0
  57. data/lib/nanoc3/filters/redcarpet.rb +27 -0
  58. data/lib/nanoc3/filters/sass.rb +1 -5
  59. data/lib/nanoc3/filters/slim.rb +25 -0
  60. data/lib/nanoc3/filters/typogruby.rb +23 -0
  61. data/lib/nanoc3/filters.rb +6 -0
  62. data/lib/nanoc3/helpers/blogging.rb +22 -26
  63. data/lib/nanoc3/helpers/rendering.rb +1 -1
  64. data/lib/nanoc3/helpers/xml_sitemap.rb +11 -2
  65. data/lib/nanoc3.rb +24 -3
  66. data/nanoc3.gemspec +4 -3
  67. data/tasks/clean.rake +11 -0
  68. data/tasks/doc.rake +14 -0
  69. data/tasks/test.rake +38 -0
  70. data/test/base/core_ext/array_spec.rb +55 -0
  71. data/test/base/core_ext/hash_spec.rb +82 -0
  72. data/test/base/core_ext/pathname_spec.rb +29 -0
  73. data/test/base/core_ext/string_spec.rb +39 -0
  74. data/test/base/test_checksum_store.rb +37 -0
  75. data/test/base/test_code_snippet.rb +33 -0
  76. data/test/base/test_compiler.rb +303 -0
  77. data/test/base/test_compiler_dsl.rb +156 -0
  78. data/test/base/test_context.rb +33 -0
  79. data/test/base/test_data_source.rb +48 -0
  80. data/test/base/test_dependency_tracker.rb +264 -0
  81. data/test/base/test_directed_graph.rb +285 -0
  82. data/test/base/test_filter.rb +85 -0
  83. data/test/base/test_item.rb +164 -0
  84. data/test/base/test_item_rep.rb +555 -0
  85. data/test/base/test_layout.rb +44 -0
  86. data/test/base/test_memoization.rb +53 -0
  87. data/test/base/test_notification_center.rb +36 -0
  88. data/test/base/test_outdatedness_checker.rb +365 -0
  89. data/test/base/test_plugin.rb +32 -0
  90. data/test/base/test_rule.rb +21 -0
  91. data/test/base/test_rule_context.rb +67 -0
  92. data/test/base/test_site.rb +144 -0
  93. data/test/cli/commands/test_compile.rb +12 -0
  94. data/test/cli/commands/test_create_item.rb +12 -0
  95. data/test/cli/commands/test_create_layout.rb +28 -0
  96. data/test/cli/commands/test_create_site.rb +24 -0
  97. data/test/cli/commands/test_help.rb +12 -0
  98. data/test/cli/commands/test_info.rb +12 -0
  99. data/test/cli/commands/test_update.rb +12 -0
  100. data/test/cli/test_logger.rb +12 -0
  101. data/test/data_sources/test_filesystem.rb +420 -0
  102. data/test/data_sources/test_filesystem_unified.rb +562 -0
  103. data/test/data_sources/test_filesystem_verbose.rb +359 -0
  104. data/test/extra/core_ext/test_enumerable.rb +32 -0
  105. data/test/extra/core_ext/test_time.rb +17 -0
  106. data/test/extra/deployers/test_rsync.rb +234 -0
  107. data/test/extra/test_auto_compiler.rb +417 -0
  108. data/test/extra/test_file_proxy.rb +21 -0
  109. data/test/extra/test_vcs.rb +24 -0
  110. data/test/extra/validators/test_links.rb +53 -0
  111. data/test/extra/validators/test_w3c.rb +49 -0
  112. data/test/filters/test_asciidoc.rb +22 -0
  113. data/test/filters/test_bluecloth.rb +20 -0
  114. data/test/filters/test_coderay.rb +46 -0
  115. data/test/filters/test_colorize_syntax.rb +149 -0
  116. data/test/filters/test_erb.rb +101 -0
  117. data/test/filters/test_erubis.rb +72 -0
  118. data/test/filters/test_haml.rb +98 -0
  119. data/test/filters/test_kramdown.rb +20 -0
  120. data/test/filters/test_less.rb +59 -0
  121. data/test/filters/test_markaby.rb +26 -0
  122. data/test/filters/test_maruku.rb +20 -0
  123. data/test/filters/test_mustache.rb +27 -0
  124. data/test/filters/test_rainpress.rb +31 -0
  125. data/test/filters/test_rdiscount.rb +33 -0
  126. data/test/filters/test_rdoc.rb +18 -0
  127. data/test/filters/test_redcarpet.rb +63 -0
  128. data/test/filters/test_redcloth.rb +35 -0
  129. data/test/filters/test_relativize_paths.rb +231 -0
  130. data/test/filters/test_rubypants.rb +20 -0
  131. data/test/filters/test_sass.rb +103 -0
  132. data/test/filters/test_slim.rb +37 -0
  133. data/test/filters/test_typogruby.rb +23 -0
  134. data/test/helper.rb +161 -0
  135. data/test/helpers/test_blogging.rb +756 -0
  136. data/test/helpers/test_breadcrumbs.rb +83 -0
  137. data/test/helpers/test_capturing.rb +43 -0
  138. data/test/helpers/test_filtering.rb +108 -0
  139. data/test/helpers/test_html_escape.rb +34 -0
  140. data/test/helpers/test_link_to.rb +251 -0
  141. data/test/helpers/test_rendering.rb +90 -0
  142. data/test/helpers/test_tagging.rb +89 -0
  143. data/test/helpers/test_text.rb +26 -0
  144. data/test/helpers/test_xml_sitemap.rb +105 -0
  145. data/test/tasks/test_clean.rb +69 -0
  146. metadata +96 -27
  147. data/lib/nanoc3/base/compilation/checksummer.rb +0 -68
@@ -132,7 +132,7 @@ module Nanoc3
132
132
 
133
133
  # Calculate characteristics of old content
134
134
  if File.file?(raw_path)
135
- hash_old = Nanoc3::Checksummer.checksum_for_file(raw_path)
135
+ hash_old = Pathname.new(raw_path).checksum
136
136
  size_old = File.size(raw_path)
137
137
  end
138
138
 
@@ -142,7 +142,7 @@ module Nanoc3
142
142
  if self.binary?
143
143
  # Calculate characteristics of new content
144
144
  size_new = File.size(temporary_filenames[:last])
145
- hash_new = Nanoc3::Checksummer.checksum_for_file(temporary_filenames[:last]) if size_old == size_new
145
+ hash_new = Pathname.new(temporary_filenames[:last]).checksum if size_old == size_new
146
146
 
147
147
  # Check whether content was modified
148
148
  is_modified = (size_old != size_new || hash_old != hash_new)
@@ -263,6 +263,8 @@ module Nanoc3
263
263
  #
264
264
  # @return [Boolean] True if content exists for the snapshot with the
265
265
  # given name, false otherwise
266
+ #
267
+ # @since 3.2.0
266
268
  def has_snapshot?(snapshot_name)
267
269
  !@content[snapshot_name].nil?
268
270
  end
@@ -321,33 +323,36 @@ module Nanoc3
321
323
  raise Nanoc3::Errors::CannotUseTextualFilter.new(self, klass)
322
324
  end
323
325
 
324
- # Notify start
325
- Nanoc3::NotificationCenter.post(:filtering_started, self, filter_name)
326
+ begin
327
+ # Notify start
328
+ Nanoc3::NotificationCenter.post(:filtering_started, self, filter_name)
326
329
 
327
- # Create filter
328
- filter = klass.new(assigns)
330
+ # Create filter
331
+ filter = klass.new(assigns)
329
332
 
330
- # Run filter
331
- source = self.binary? ? temporary_filenames[:last] : @content[:last]
332
- result = filter.run(source, filter_args)
333
- if klass.to_binary?
334
- temporary_filenames[:last] = filter.output_filename
335
- else
336
- @content[:last] = result
337
- end
338
- @binary = klass.to_binary?
333
+ # Run filter
334
+ source = self.binary? ? temporary_filenames[:last] : @content[:last]
335
+ result = filter.run(source, filter_args)
336
+ if klass.to_binary?
337
+ temporary_filenames[:last] = filter.output_filename
338
+ else
339
+ @content[:last] = result
340
+ @content[:last].freeze
341
+ end
342
+ @binary = klass.to_binary?
339
343
 
340
- # Check whether file was written
341
- if self.binary? && !File.file?(filter.output_filename)
342
- raise RuntimeError,
343
- "The #{filter_name.inspect} filter did not write anything to the required output file, #{filter.output_filename}."
344
- end
344
+ # Check whether file was written
345
+ if self.binary? && !File.file?(filter.output_filename)
346
+ raise RuntimeError,
347
+ "The #{filter_name.inspect} filter did not write anything to the required output file, #{filter.output_filename}."
348
+ end
345
349
 
346
- # Create snapshot
347
- snapshot(@content[:post] ? :post : :pre, :final => false) unless self.binary?
348
- ensure
349
- # Notify end
350
- Nanoc3::NotificationCenter.post(:filtering_ended, self, filter_name)
350
+ # Create snapshot
351
+ snapshot(@content[:post] ? :post : :pre, :final => false) unless self.binary?
352
+ ensure
353
+ # Notify end
354
+ Nanoc3::NotificationCenter.post(:filtering_ended, self, filter_name)
355
+ end
351
356
  end
352
357
 
353
358
  # Lays out the item using the given layout. This method will replace the
@@ -421,6 +426,39 @@ module Nanoc3
421
426
  write(snapshot_name) if params[:final]
422
427
  end
423
428
 
429
+ # Returns a recording proxy that is used for determining whether the
430
+ # compilation has changed, and thus whether the item rep needs to be
431
+ # recompiled.
432
+ #
433
+ # @api private
434
+ #
435
+ # @return [Nanoc3::ItemRepRecorderProxy] The recording proxy
436
+ def to_recording_proxy
437
+ Nanoc3::ItemRepRecorderProxy.new(self)
438
+ end
439
+
440
+ # Returns false because this item is not yet a proxy, and therefore does
441
+ # need to be wrapped in a proxy during compilation.
442
+ #
443
+ # @api private
444
+ #
445
+ # @return [false]
446
+ #
447
+ # @see Nanoc3::ItemRepRecorderProxy#is_proxy?
448
+ # @see Nanoc3::ItemRepProxy#is_proxy?
449
+ def is_proxy?
450
+ false
451
+ end
452
+
453
+ # Returns an object that can be used for uniquely identifying objects.
454
+ #
455
+ # @api private
456
+ #
457
+ # @return [Object] An unique reference to this object
458
+ def reference
459
+ [ type, self.item.identifier, self.name ]
460
+ end
461
+
424
462
  def inspect
425
463
  "<#{self.class}:0x#{self.object_id.to_s(16)} name=#{self.name} binary=#{self.binary?} raw_path=#{self.raw_path} item.identifier=#{self.item.identifier}>"
426
464
  end
@@ -434,6 +472,7 @@ module Nanoc3
434
472
  @content = {}
435
473
  else
436
474
  @content = { :last => @item.raw_content }
475
+ @content[:last].freeze
437
476
  @temporary_filenames = {}
438
477
  end
439
478
  end
@@ -43,6 +43,15 @@ module Nanoc3
43
43
  [ :code_snippet, filename ]
44
44
  end
45
45
 
46
+ def inspect
47
+ "<#{self.class}:0x#{self.object_id.to_s(16)} filename=#{self.filename}>"
48
+ end
49
+
50
+ # TODO document
51
+ def checksum
52
+ @data.checksum
53
+ end
54
+
46
55
  end
47
56
 
48
57
  end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ module Nanoc3
4
+
5
+ # TODO document
6
+ class Configuration < ::Hash
7
+
8
+ # TODO document
9
+ def initialize(hash)
10
+ self.replace(hash)
11
+ end
12
+
13
+ # TODO document
14
+ def reference
15
+ :config
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -7,6 +7,8 @@ module Nanoc3
7
7
  # store the modification time to speed up compilation.
8
8
  class Item
9
9
 
10
+ extend Nanoc3::Memoization
11
+
10
12
  # @return [Hash] This item's attributes
11
13
  attr_accessor :attributes
12
14
 
@@ -78,10 +80,10 @@ module Nanoc3
78
80
 
79
81
  # Get rest of params
80
82
  @attributes = attributes.symbolize_keys
81
- @identifier = identifier.cleaned_identifier
83
+ @identifier = identifier.cleaned_identifier.freeze
82
84
 
83
85
  # Set mtime
84
- @attributes.merge(:mtime => params[:mtime]) if params[:mtime]
86
+ @attributes.merge!(:mtime => params[:mtime]) if params[:mtime]
85
87
 
86
88
  @parent = nil
87
89
  @children = []
@@ -164,6 +166,12 @@ module Nanoc3
164
166
  # Get captured content (hax)
165
167
  # TODO [in nanoc 4.0] remove me
166
168
  if key.to_s =~ /^content_for_(.*)$/
169
+ # Warn
170
+ unless @_content_for_warning_issued
171
+ warn 'WARNING: Accessing captured content should happen using the #content_for method defined in the Capturing helper instead of using item[:content_for_something]. The latter way of accessing captured content will be removed in nanoc 4.0.'
172
+ @_content_for_warning_issued = true
173
+ end
174
+
167
175
  # Include capturing helper if necessary
168
176
  unless @_Nanoc3_Helpers_Capturing_included
169
177
  self.class.send(:include, ::Nanoc3::Helpers::Capturing)
@@ -210,16 +218,33 @@ module Nanoc3
210
218
  [ type, self.identifier ]
211
219
  end
212
220
 
213
- # Prevents all further modifications to itself, its items, its layouts etc.
221
+ # Prevents all further modifications to its attributes.
214
222
  #
215
223
  # @return [void]
216
224
  def freeze
217
- attributes.freeze
225
+ attributes.freeze_recursively
226
+ children.freeze
227
+ identifier.freeze
228
+ raw_filename.freeze if raw_filename
229
+ raw_content.freeze if raw_content
218
230
  end
231
+
219
232
  def inspect
220
233
  "<#{self.class}:0x#{self.object_id.to_s(16)} identifier=#{self.identifier} binary?=#{self.binary?}>"
221
234
  end
222
235
 
236
+ # TODO document
237
+ def checksum
238
+ if binary?
239
+ Pathname.new(raw_filename).checksum
240
+ else
241
+ attributes = @attributes.dup
242
+ attributes.delete(:file)
243
+ @raw_content.checksum + ',' + attributes.checksum
244
+ end
245
+ end
246
+ memoize :checksum
247
+
223
248
  # @deprecated Access the modification time using `item[:mtime]` instead.
224
249
  def mtime
225
250
  self[:mtime]
@@ -6,6 +6,8 @@ module Nanoc3
6
6
  # identifier and a modification time (to speed up compilation).
7
7
  class Layout
8
8
 
9
+ extend Nanoc3::Memoization
10
+
9
11
  # @return [String] The raw content of this layout
10
12
  attr_reader :raw_content
11
13
 
@@ -34,7 +36,7 @@ module Nanoc3
34
36
  def initialize(raw_content, attributes, identifier, params=nil)
35
37
  @raw_content = raw_content
36
38
  @attributes = attributes.symbolize_keys
37
- @identifier = identifier.cleaned_identifier
39
+ @identifier = identifier.cleaned_identifier.freeze
38
40
 
39
41
  # Set mtime
40
42
  params ||= {}
@@ -61,6 +63,15 @@ module Nanoc3
61
63
  :layout
62
64
  end
63
65
 
66
+ # Prevents all further modifications to the layout.
67
+ #
68
+ # @return [void]
69
+ def freeze
70
+ attributes.freeze_recursively
71
+ identifier.freeze
72
+ raw_content.freeze
73
+ end
74
+
64
75
  # Returns an object that can be used for uniquely identifying objects.
65
76
  #
66
77
  # @api private
@@ -74,6 +85,14 @@ module Nanoc3
74
85
  "<#{self.class}:0x#{self.object_id.to_s(16)} identifier=#{self.identifier}>"
75
86
  end
76
87
 
88
+ # TODO document
89
+ def checksum
90
+ attributes = @attributes.dup
91
+ attributes.delete(:file)
92
+ @raw_content.checksum + ',' + attributes.checksum
93
+ end
94
+ memoize :checksum
95
+
77
96
  # @deprecated Access the modification time using `layout[:mtime]` instead.
78
97
  def mtime
79
98
  self[:mtime]
@@ -51,6 +51,8 @@ module Nanoc3
51
51
  # Compiles the site.
52
52
  #
53
53
  # @return [void]
54
+ #
55
+ # @since 3.2.0
54
56
  def compile
55
57
  compiler.run
56
58
  end
@@ -167,20 +169,6 @@ module Nanoc3
167
169
  #
168
170
  # @return [Hash] The site configuration
169
171
  def config
170
- # Add reference to config if necessary
171
- if !@config.respond_to?(:reference)
172
- def @config.reference
173
- :config
174
- end
175
- end
176
-
177
- # Add data to config if necessary
178
- if !@config.respond_to?(:data)
179
- def @config.data
180
- self.inspect
181
- end
182
- end
183
-
184
172
  @config
185
173
  end
186
174
 
@@ -190,12 +178,7 @@ module Nanoc3
190
178
  #
191
179
  # @return [void]
192
180
  def setup_child_parent_links
193
- # Clear all links
194
- @items.each do |item|
195
- item.parent = nil
196
- item.children = []
197
- end
198
-
181
+ teardown_child_parent_links
199
182
  @items.each do |item|
200
183
  # Get parent
201
184
  parent_identifier = item.identifier.sub(/[^\/]+\/$/, '')
@@ -208,13 +191,23 @@ module Nanoc3
208
191
  end
209
192
  end
210
193
 
194
+ # Removes all child-parent links.
195
+ #
196
+ # @api private
197
+ #
198
+ # @return [void]
199
+ def teardown_child_parent_links
200
+ @items.each do |item|
201
+ item.parent = nil
202
+ item.children = []
203
+ end
204
+ end
205
+
211
206
  # Prevents all further modifications to itself, its items, its layouts etc.
212
207
  #
213
208
  # @return [void]
214
209
  def freeze
215
- super
216
-
217
- config.freeze
210
+ config.freeze_recursively
218
211
  items.each { |i| i.freeze }
219
212
  layouts.each { |l| l.freeze }
220
213
  code_snippets.each { |cs| cs.freeze }
@@ -233,8 +226,8 @@ module Nanoc3
233
226
  #
234
227
  # @return [void]
235
228
  def load
236
- return if @data_loaded
237
- @data_loaded = true
229
+ return if @loaded || @loading
230
+ @loading = true
238
231
 
239
232
  # Load all data
240
233
  load_code_snippets
@@ -247,6 +240,33 @@ module Nanoc3
247
240
  # Load compiler too
248
241
  # FIXME this should not be necessary
249
242
  compiler.load
243
+
244
+ @loaded = true
245
+ rescue => e
246
+ unload
247
+ raise e
248
+ ensure
249
+ @loading = false
250
+ end
251
+
252
+ # Undoes the effects of {#load}. Used when {#load} raises an exception.
253
+ #
254
+ # @api private
255
+ def unload
256
+ return if @unloading
257
+ @unloading = true
258
+
259
+ @items_loaded = false
260
+ @items = []
261
+ @layouts_loaded = false
262
+ @layouts = []
263
+ @code_snippets_loaded = false
264
+ @code_snippets = []
265
+
266
+ compiler.unload
267
+
268
+ @loaded = false
269
+ @unloading = false
250
270
  end
251
271
 
252
272
  private
@@ -319,7 +339,10 @@ module Nanoc3
319
339
  end
320
340
 
321
341
  # Merge data sources with default data source config
322
- @config[:data_sources].map! { |ds| DEFAULT_DATA_SOURCE_CONFIG.merge(ds) }
342
+ @config[:data_sources] = @config[:data_sources].map { |ds| DEFAULT_DATA_SOURCE_CONFIG.merge(ds) }
343
+
344
+ # Convert to proper configuration
345
+ @config = Nanoc3::Configuration.new(@config)
323
346
  end
324
347
 
325
348
  end
@@ -6,6 +6,10 @@ module Nanoc3
6
6
  # filesystem, such as checksums, cached compiled content and dependency
7
7
  # graphs.
8
8
  #
9
+ # Each store has a version number. When attempting to load data from a store
10
+ # that has an incompatible version number, no data will be loaded, but
11
+ # {#version_mismatch_detected} will be called.
12
+ #
9
13
  # @abstract Subclasses must implement {#data} and {#data=}, and may
10
14
  # implement {#no_data_found} and {#version_mismatch_detected}.
11
15
  #
@@ -83,6 +87,12 @@ module Nanoc3
83
87
  end
84
88
  end
85
89
 
90
+ # Undoes the effects of {#load}. Used when {#load} raises an exception.
91
+ #
92
+ # @api private
93
+ def unload
94
+ end
95
+
86
96
  # Stores the data contained in memory to the filesystem. This method will
87
97
  # use the {#data} method to fetch the data that should be written.
88
98
  #
@@ -117,7 +127,6 @@ module Nanoc3
117
127
  private
118
128
 
119
129
  def pstore
120
- require 'pstore'
121
130
  @pstore ||= PStore.new(self.filename)
122
131
  end
123
132
 
data/lib/nanoc3/base.rb CHANGED
@@ -9,12 +9,14 @@ module Nanoc3
9
9
  autoload 'Context', 'nanoc3/base/context'
10
10
  autoload 'DirectedGraph', 'nanoc3/base/directed_graph'
11
11
  autoload 'Errors', 'nanoc3/base/errors'
12
+ autoload 'Memoization', 'nanoc3/base/memoization'
12
13
  autoload 'NotificationCenter', 'nanoc3/base/notification_center'
13
14
  autoload 'PluginRegistry', 'nanoc3/base/plugin_registry'
14
15
  autoload 'Store', 'nanoc3/base/store'
15
16
 
16
17
  # Load source data classes
17
18
  autoload 'CodeSnippet', 'nanoc3/base/source_data/code_snippet'
19
+ autoload 'Configuration', 'nanoc3/base/source_data/configuration'
18
20
  autoload 'DataSource', 'nanoc3/base/source_data/data_source'
19
21
  autoload 'Item', 'nanoc3/base/source_data/item'
20
22
  autoload 'Layout', 'nanoc3/base/source_data/layout'
@@ -24,7 +26,6 @@ module Nanoc3
24
26
  autoload 'ItemRep', 'nanoc3/base/result_data/item_rep'
25
27
 
26
28
  # Load compilation classes
27
- autoload 'Checksummer', 'nanoc3/base/compilation/checksummer'
28
29
  autoload 'ChecksumStore', 'nanoc3/base/compilation/checksum_store'
29
30
  autoload 'CompiledContentCache', 'nanoc3/base/compilation/compiled_content_cache'
30
31
  autoload 'Compiler', 'nanoc3/base/compilation/compiler'
@@ -32,10 +33,14 @@ module Nanoc3
32
33
  autoload 'DependencyTracker', 'nanoc3/base/compilation/dependency_tracker'
33
34
  autoload 'Filter', 'nanoc3/base/compilation/filter'
34
35
  autoload 'ItemRepProxy', 'nanoc3/base/compilation/item_rep_proxy'
36
+ autoload 'ItemRepRecorderProxy', 'nanoc3/base/compilation/item_rep_recorder_proxy'
35
37
  autoload 'OutdatednessChecker', 'nanoc3/base/compilation/outdatedness_checker'
36
38
  autoload 'OutdatednessReasons', 'nanoc3/base/compilation/outdatedness_reasons'
37
39
  autoload 'Rule', 'nanoc3/base/compilation/rule'
38
40
  autoload 'RuleContext', 'nanoc3/base/compilation/rule_context'
41
+ autoload 'RuleMemoryCalculator', 'nanoc3/base/compilation/rule_memory_calculator'
42
+ autoload 'RuleMemoryStore', 'nanoc3/base/compilation/rule_memory_store'
43
+ autoload 'RulesCollection', 'nanoc3/base/compilation/rules_collection'
39
44
 
40
45
  # Deprecated; use PluginRepository instead
41
46
  # TODO [in nanoc 4.0] remove me
@@ -27,9 +27,11 @@ module Nanoc3::CLI
27
27
  'rack/cache' => 'rack-cache',
28
28
  'rainpress' => 'rainpress',
29
29
  'rdiscount' => 'rdiscount',
30
+ 'redcarpet' => 'redcarpet',
30
31
  'redcloth' => 'redcloth',
31
32
  'rubypants' => 'rubypants',
32
33
  'sass' => 'sass',
34
+ 'systemu' => 'systemu',
33
35
  'w3c_validators' => 'w3c_validators'
34
36
  }
35
37
 
@@ -65,6 +67,8 @@ module Nanoc3::CLI
65
67
  end
66
68
 
67
69
  # @return [Boolean] true if debug output is enabled, false if not
70
+ #
71
+ # @since 3.2.0
68
72
  def debug?
69
73
  @debug
70
74
  end
@@ -147,10 +151,10 @@ module Nanoc3::CLI
147
151
  $stderr.puts
148
152
  $stderr.puts '=== COMPILATION STACK:'
149
153
  $stderr.puts
150
- if ((self.site && self.site.compiler.stack) || []).empty?
154
+ if stack.empty?
151
155
  $stderr.puts " (empty)"
152
156
  else
153
- self.site.compiler.stack.reverse.each do |obj|
157
+ stack.reverse.each do |obj|
154
158
  if obj.is_a?(Nanoc3::ItemRep)
155
159
  $stderr.puts " - [item] #{obj.item.identifier} (rep #{obj.name})"
156
160
  else # layout
@@ -160,7 +164,6 @@ module Nanoc3::CLI
160
164
  end
161
165
 
162
166
  # Backtrace
163
- require 'enumerator'
164
167
  $stderr.puts
165
168
  $stderr.puts '=== BACKTRACE:'
166
169
  $stderr.puts
@@ -177,7 +180,9 @@ module Nanoc3::CLI
177
180
  case error
178
181
  when LoadError
179
182
  # Get gem name
180
- lib_name = error.message.match(/no such file to load -- ([^\s]+)/)[1]
183
+ matches = error.message.match(/no such file to load -- ([^\s]+)/)
184
+ return nil if matches.empty?
185
+ lib_name = matches[1]
181
186
  gem_name = GEM_NAMES[$1]
182
187
 
183
188
  # Build message
@@ -187,8 +192,10 @@ module Nanoc3::CLI
187
192
  when RuntimeError
188
193
  if error.message =~ /^can't modify frozen/
189
194
  "You attempted to modify immutable data. Some data, such as " \
190
- "item/layout attributes and raw item/layout content, can no " \
191
- "longer be modified once compilation has started."
195
+ "item/layout attributes and raw item/layout content, can not " \
196
+ "be modified once compilation has started. (This was " \
197
+ "unintentionally possible in 3.1.x and before, but has been " \
198
+ "disabled in 3.2.x in order to allow compiler optimisations.)"
192
199
  end
193
200
  end
194
201
  end
@@ -261,7 +268,7 @@ module Nanoc3::CLI
261
268
  gem_info = defined?(Gem) ? "with RubyGems #{Gem::VERSION}" : "without RubyGems"
262
269
  engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
263
270
 
264
- puts "nanoc #{Nanoc3::VERSION} (c) 2007-2010 Denis Defreyne."
271
+ puts "nanoc #{Nanoc3::VERSION} (c) 2007-2011 Denis Defreyne."
265
272
  puts "Running #{engine} #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) on #{RUBY_PLATFORM} #{gem_info}"
266
273
  exit 0
267
274
  when :verbose
@@ -280,6 +287,12 @@ module Nanoc3::CLI
280
287
  end
281
288
  end
282
289
 
290
+ protected
291
+
292
+ def stack
293
+ (self.site && self.site.compiler.stack) || []
294
+ end
295
+
283
296
  end
284
297
 
285
298
  end
@@ -166,7 +166,6 @@ module Nanoc3::CLI::Commands
166
166
  # Check whether there’s a different
167
167
  return if old_content == new_content
168
168
 
169
- require 'thread'
170
169
  @diff_threads << Thread.new do
171
170
  # Generate diff
172
171
  diff = diff_strings(old_content, new_content)
@@ -182,7 +181,6 @@ module Nanoc3::CLI::Commands
182
181
 
183
182
  # TODO move this elsewhere
184
183
  def diff_strings(a, b)
185
- require 'tempfile'
186
184
  require 'open3'
187
185
 
188
186
  # Create files
@@ -82,6 +82,9 @@ EOS
82
82
 
83
83
  # A few helpful tips about the Rules file:
84
84
  #
85
+ # * The string given to #compile and #route are matching patterns for
86
+ # identifiers--not for paths. Therefore, you can’t match on extension.
87
+ #
85
88
  # * The order of rules is important: for each item, only the first matching
86
89
  # rule is applied.
87
90
  #
@@ -95,8 +98,12 @@ compile '/stylesheet/' do
95
98
  end
96
99
 
97
100
  compile '*' do
98
- filter :erb
99
- layout 'default'
101
+ if item.binary?
102
+ # don’t filter binary items
103
+ else
104
+ filter :erb
105
+ layout 'default'
106
+ end
100
107
  end
101
108
 
102
109
  route '/stylesheet/' do
@@ -105,10 +112,10 @@ end
105
112
 
106
113
  route '*' do
107
114
  if item.binary?
108
- # /foo/ -> /foo.ext
115
+ # Write item with identifier /foo/ to /foo.ext
109
116
  item.identifier.chop + '.' + item[:extension]
110
117
  else
111
- # /foo/ -> /foo/index.html
118
+ # Write item with identifier /foo/ to /foo/index.html
112
119
  item.identifier + 'index.html'
113
120
  end
114
121
  end
@@ -180,18 +187,20 @@ a:hover {
180
187
  line-height: 20px;
181
188
  }
182
189
 
183
- #main ul {
190
+ #main ul, #main ol {
184
191
  margin: 20px;
185
192
  }
186
193
 
187
194
  #main li {
188
- list-style-type: square;
189
-
190
195
  font-size: 15px;
191
196
 
192
197
  line-height: 20px;
193
198
  }
194
199
 
200
+ #main ul li {
201
+ list-style-type: square;
202
+ }
203
+
195
204
  #sidebar {
196
205
  position: absolute;
197
206
 
@@ -51,7 +51,7 @@ module Nanoc3::CLI::Commands
51
51
  puts
52
52
  items.sort_by { |i| i.identifier }.each do |item|
53
53
  puts "item #{item.identifier} depends on:"
54
- predecessors = dependency_tracker.direct_predecessors_of(item).sort_by { |i| i.identifier }
54
+ predecessors = dependency_tracker.objects_causing_outdatedness_of(item).sort_by { |i| i.identifier }
55
55
  predecessors.each do |pred|
56
56
  puts " [ #{format '%6s', pred.type} ] #{pred.identifier}"
57
57
  end
@@ -82,7 +82,7 @@ module Nanoc3::CLI::Commands
82
82
  items.sort_by { |i| i.identifier }.each do |item|
83
83
  item.reps.sort_by { |r| r.name.to_s }.each do |rep|
84
84
  puts "item #{item.identifier}, rep #{rep.name}:"
85
- outdatedness_reason = compiler.outdatedness_reason_for(rep)
85
+ outdatedness_reason = compiler.outdatedness_checker.outdatedness_reason_for(rep)
86
86
  if outdatedness_reason
87
87
  puts " is outdated: #{outdatedness_reason.message}"
88
88
  else
@@ -97,7 +97,7 @@ module Nanoc3::CLI::Commands
97
97
  puts
98
98
  layouts.each do |layout|
99
99
  puts "layout #{layout.identifier}:"
100
- outdatedness_reason = compiler.outdatedness_reason_for(layout)
100
+ outdatedness_reason = compiler.outdatedness_checker.outdatedness_reason_for(layout)
101
101
  if outdatedness_reason
102
102
  puts " is outdated: #{outdatedness_reason.message}"
103
103
  else
@@ -72,6 +72,7 @@ module Nanoc3::CLI::Commands
72
72
  use Rack::CommonLogger
73
73
  use Rack::ShowExceptions
74
74
  use Rack::Lint
75
+ use Rack::Head
75
76
  use Adsf::Rack::IndexFileFinder, :root => site.config[:output_dir]
76
77
  run Rack::File.new(site.config[:output_dir])
77
78
  end.to_app