nanoc 4.11.0 → 4.11.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 (154) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +6 -0
  3. data/lib/nanoc.rb +4 -7
  4. data/lib/nanoc/base.rb +3 -3
  5. data/lib/nanoc/base/assertions.rb +1 -1
  6. data/lib/nanoc/base/entities.rb +2 -20
  7. data/lib/nanoc/base/entities/action_sequence.rb +60 -64
  8. data/lib/nanoc/base/entities/checksum_collection.rb +23 -21
  9. data/lib/nanoc/base/entities/dependency.rb +24 -22
  10. data/lib/nanoc/base/entities/outdatedness_reasons.rb +74 -72
  11. data/lib/nanoc/base/entities/outdatedness_status.rb +19 -17
  12. data/lib/nanoc/base/entities/props.rb +119 -117
  13. data/lib/nanoc/base/entities/site.rb +46 -50
  14. data/lib/nanoc/base/errors.rb +183 -198
  15. data/lib/nanoc/base/repos.rb +4 -2
  16. data/lib/nanoc/base/repos/action_sequence_store.rb +44 -42
  17. data/lib/nanoc/base/repos/aggregate_data_source.rb +24 -22
  18. data/lib/nanoc/base/repos/checksum_store.rb +51 -49
  19. data/lib/nanoc/base/repos/compiled_content_cache.rb +47 -45
  20. data/lib/nanoc/base/repos/compiled_content_store.rb +76 -0
  21. data/lib/nanoc/base/repos/config_loader.rb +74 -72
  22. data/lib/nanoc/base/repos/dependency_store.rb +174 -172
  23. data/lib/nanoc/base/repos/in_mem_data_source.rb +17 -15
  24. data/lib/nanoc/base/repos/item_rep_repo.rb +26 -24
  25. data/lib/nanoc/base/repos/outdatedness_store.rb +50 -48
  26. data/lib/nanoc/base/repos/prefixed_data_source.rb +21 -19
  27. data/lib/nanoc/base/repos/site_loader.rb +75 -73
  28. data/lib/nanoc/base/repos/store.rb +93 -91
  29. data/lib/nanoc/base/services.rb +7 -3
  30. data/lib/nanoc/base/services/action_provider.rb +23 -21
  31. data/lib/nanoc/base/services/action_sequence_builder.rb +42 -34
  32. data/lib/nanoc/base/services/compilation_context.rb +49 -47
  33. data/lib/nanoc/base/services/compiler.rb +177 -170
  34. data/lib/nanoc/base/services/compiler/phases.rb +8 -1
  35. data/lib/nanoc/base/services/compiler/phases/abstract.rb +44 -38
  36. data/lib/nanoc/base/services/compiler/phases/cache.rb +34 -28
  37. data/lib/nanoc/base/services/compiler/phases/mark_done.rb +17 -11
  38. data/lib/nanoc/base/services/compiler/phases/notify.rb +21 -0
  39. data/lib/nanoc/base/services/compiler/phases/recalculate.rb +37 -31
  40. data/lib/nanoc/base/services/compiler/phases/resume.rb +47 -48
  41. data/lib/nanoc/base/services/compiler/phases/write.rb +65 -59
  42. data/lib/nanoc/base/services/compiler/stage.rb +27 -8
  43. data/lib/nanoc/base/services/compiler/stages.rb +7 -1
  44. data/lib/nanoc/base/services/compiler/stages/build_reps.rb +25 -19
  45. data/lib/nanoc/base/services/compiler/stages/calculate_checksums.rb +34 -28
  46. data/lib/nanoc/base/services/compiler/stages/cleanup.rb +33 -27
  47. data/lib/nanoc/base/services/compiler/stages/compile_reps.rb +79 -69
  48. data/lib/nanoc/base/services/compiler/stages/determine_outdatedness.rb +46 -40
  49. data/lib/nanoc/base/services/compiler/stages/forget_outdated_dependencies.rb +15 -9
  50. data/lib/nanoc/base/services/compiler/stages/load_stores.rb +28 -22
  51. data/lib/nanoc/base/services/compiler/stages/postprocess.rb +16 -10
  52. data/lib/nanoc/base/services/compiler/stages/preprocess.rb +25 -19
  53. data/lib/nanoc/base/services/compiler/stages/prune.rb +23 -17
  54. data/lib/nanoc/base/services/compiler/stages/store_post_compilation_state.rb +15 -9
  55. data/lib/nanoc/base/services/compiler/stages/store_pre_compilation_state.rb +26 -20
  56. data/lib/nanoc/base/services/compiler_loader.rb +26 -24
  57. data/lib/nanoc/base/services/dependency_tracker.rb +47 -45
  58. data/lib/nanoc/base/services/executor.rb +16 -15
  59. data/lib/nanoc/base/services/filter.rb +37 -5
  60. data/lib/nanoc/base/services/instrumentor.rb +12 -10
  61. data/lib/nanoc/base/services/item_rep_builder.rb +21 -19
  62. data/lib/nanoc/base/services/item_rep_router.rb +72 -70
  63. data/lib/nanoc/base/services/item_rep_selector.rb +48 -46
  64. data/lib/nanoc/base/services/item_rep_writer.rb +58 -53
  65. data/lib/nanoc/base/services/outdatedness_checker.rb +181 -179
  66. data/lib/nanoc/base/services/outdatedness_rule.rb +23 -21
  67. data/lib/nanoc/base/services/outdatedness_rules.rb +5 -3
  68. data/lib/nanoc/base/services/outdatedness_rules/attributes_modified.rb +28 -24
  69. data/lib/nanoc/base/services/outdatedness_rules/code_snippets_modified.rb +20 -16
  70. data/lib/nanoc/base/services/outdatedness_rules/content_modified.rb +13 -9
  71. data/lib/nanoc/base/services/outdatedness_rules/item_collection_extended.rb +12 -8
  72. data/lib/nanoc/base/services/outdatedness_rules/layout_collection_extended.rb +12 -8
  73. data/lib/nanoc/base/services/outdatedness_rules/not_written.rb +10 -6
  74. data/lib/nanoc/base/services/outdatedness_rules/rules_modified.rb +39 -35
  75. data/lib/nanoc/base/services/outdatedness_rules/uses_always_outdated_filter.rb +19 -15
  76. data/lib/nanoc/base/services/pruner.rb +2 -2
  77. data/lib/nanoc/base/views.rb +7 -0
  78. data/lib/nanoc/base/views/basic_item_view.rb +1 -1
  79. data/lib/nanoc/base/views/compilation_item_rep_view.rb +2 -2
  80. data/lib/nanoc/base/views/identifiable_collection_view.rb +2 -2
  81. data/lib/nanoc/base/views/mixins/document_view_mixin.rb +1 -1
  82. data/lib/nanoc/base/views/mixins/mutable_document_view_mixin.rb +5 -5
  83. data/lib/nanoc/base/views/mutable_item_collection_view.rb +3 -3
  84. data/lib/nanoc/base/views/mutable_layout_collection_view.rb +2 -2
  85. data/lib/nanoc/base/views/view_context_for_compilation.rb +6 -6
  86. data/lib/nanoc/base/views/view_context_for_pre_compilation.rb +2 -2
  87. data/lib/nanoc/base/views/view_context_for_shell.rb +2 -2
  88. data/lib/nanoc/checking/check.rb +1 -1
  89. data/lib/nanoc/cli/commands/compile_listeners/abstract.rb +24 -7
  90. data/lib/nanoc/cli/commands/compile_listeners/debug_printer.rb +79 -15
  91. data/lib/nanoc/cli/commands/compile_listeners/diff_generator.rb +4 -7
  92. data/lib/nanoc/cli/commands/compile_listeners/file_action_printer.rb +15 -24
  93. data/lib/nanoc/cli/commands/compile_listeners/timing_recorder.rb +22 -18
  94. data/lib/nanoc/cli/commands/create-site.rb +2 -7
  95. data/lib/nanoc/cli/commands/shell.rb +1 -1
  96. data/lib/nanoc/cli/commands/show-data.rb +9 -9
  97. data/lib/nanoc/cli/logger.rb +1 -1
  98. data/lib/nanoc/data_sources/filesystem.rb +8 -8
  99. data/lib/nanoc/filters/erb.rb +1 -1
  100. data/lib/nanoc/filters/erubi.rb +1 -1
  101. data/lib/nanoc/filters/erubis.rb +1 -1
  102. data/lib/nanoc/filters/haml.rb +1 -1
  103. data/lib/nanoc/filters/sass.rb +1 -1
  104. data/lib/nanoc/filters/slim.rb +1 -1
  105. data/lib/nanoc/helpers/breadcrumbs.rb +2 -2
  106. data/lib/nanoc/helpers/capturing.rb +9 -8
  107. data/lib/nanoc/helpers/filtering.rb +2 -2
  108. data/lib/nanoc/helpers/rendering.rb +1 -1
  109. data/lib/nanoc/rule_dsl.rb +10 -0
  110. data/lib/nanoc/rule_dsl/action_provider.rb +3 -3
  111. data/lib/nanoc/rule_dsl/action_recorder.rb +3 -3
  112. data/lib/nanoc/rule_dsl/action_sequence_calculator.rb +7 -7
  113. data/lib/nanoc/rule_dsl/compilation_rule.rb +2 -2
  114. data/lib/nanoc/rule_dsl/compilation_rule_context.rb +9 -9
  115. data/lib/nanoc/rule_dsl/compiler_dsl.rb +4 -4
  116. data/lib/nanoc/rule_dsl/routing_rule.rb +3 -3
  117. data/lib/nanoc/rule_dsl/rule.rb +5 -5
  118. data/lib/nanoc/rule_dsl/rule_context.rb +3 -3
  119. data/lib/nanoc/rule_dsl/rules_collection.rb +4 -4
  120. data/lib/nanoc/spec.rb +15 -15
  121. data/lib/nanoc/version.rb +1 -1
  122. metadata +10 -111
  123. data/lib/nanoc/base/contracts_support.rb +0 -130
  124. data/lib/nanoc/base/core_ext.rb +0 -5
  125. data/lib/nanoc/base/core_ext/array.rb +0 -50
  126. data/lib/nanoc/base/core_ext/hash.rb +0 -54
  127. data/lib/nanoc/base/core_ext/string.rb +0 -16
  128. data/lib/nanoc/base/entities/code_snippet.rb +0 -53
  129. data/lib/nanoc/base/entities/configuration-schema.json +0 -122
  130. data/lib/nanoc/base/entities/configuration.rb +0 -206
  131. data/lib/nanoc/base/entities/content.rb +0 -112
  132. data/lib/nanoc/base/entities/context.rb +0 -70
  133. data/lib/nanoc/base/entities/directed_graph.rb +0 -195
  134. data/lib/nanoc/base/entities/document.rb +0 -125
  135. data/lib/nanoc/base/entities/identifiable_collection.rb +0 -141
  136. data/lib/nanoc/base/entities/identifier.rb +0 -222
  137. data/lib/nanoc/base/entities/item.rb +0 -10
  138. data/lib/nanoc/base/entities/item_collection.rb +0 -14
  139. data/lib/nanoc/base/entities/item_rep.rb +0 -91
  140. data/lib/nanoc/base/entities/layout.rb +0 -10
  141. data/lib/nanoc/base/entities/layout_collection.rb +0 -14
  142. data/lib/nanoc/base/entities/lazy_value.rb +0 -43
  143. data/lib/nanoc/base/entities/pattern.rb +0 -85
  144. data/lib/nanoc/base/entities/processing_action.rb +0 -21
  145. data/lib/nanoc/base/entities/processing_actions.rb +0 -5
  146. data/lib/nanoc/base/entities/processing_actions/filter.rb +0 -36
  147. data/lib/nanoc/base/entities/processing_actions/layout.rb +0 -36
  148. data/lib/nanoc/base/entities/processing_actions/snapshot.rb +0 -46
  149. data/lib/nanoc/base/entities/snapshot_def.rb +0 -22
  150. data/lib/nanoc/base/repos/data_source.rb +0 -168
  151. data/lib/nanoc/base/repos/snapshot_repo.rb +0 -67
  152. data/lib/nanoc/base/services/checksummer.rb +0 -274
  153. data/lib/nanoc/base/services/notification_center.rb +0 -87
  154. data/lib/nanoc/base/services/temp_filename_factory.rb +0 -52
@@ -13,24 +13,24 @@ module Nanoc
13
13
  filter = filter_for_filtering(@rep, filter_name)
14
14
 
15
15
  begin
16
- Nanoc::Int::NotificationCenter.post(:filtering_started, @rep, filter_name)
16
+ Nanoc::Core::NotificationCenter.post(:filtering_started, @rep, filter_name)
17
17
 
18
18
  # Run filter
19
- last = @compilation_context.snapshot_repo.get(@rep, :last)
19
+ last = @compilation_context.compiled_content_store.get_current(@rep)
20
20
  source = last.binary? ? last.filename : last.string
21
21
  filter_args.freeze
22
22
  result = filter.setup_and_run(source, filter_args)
23
23
  last =
24
24
  if filter.class.to_binary?
25
- Nanoc::Int::BinaryContent.new(filter.output_filename).tap(&:freeze)
25
+ Nanoc::Core::BinaryContent.new(filter.output_filename).tap(&:freeze)
26
26
  else
27
- Nanoc::Int::TextualContent.new(result).tap(&:freeze)
27
+ Nanoc::Core::TextualContent.new(result).tap(&:freeze)
28
28
  end
29
29
 
30
30
  # Store
31
- @compilation_context.snapshot_repo.set(@rep, :last, last)
31
+ @compilation_context.compiled_content_store.set_current(@rep, last)
32
32
  ensure
33
- Nanoc::Int::NotificationCenter.post(:filtering_ended, @rep, filter_name)
33
+ Nanoc::Core::NotificationCenter.post(:filtering_ended, @rep, filter_name)
34
34
  end
35
35
  end
36
36
 
@@ -45,7 +45,7 @@ module Nanoc
45
45
  filter_args.freeze
46
46
 
47
47
  # Check whether item can be laid out
48
- last = @compilation_context.snapshot_repo.get(@rep, :last)
48
+ last = @compilation_context.compiled_content_store.get_current(@rep)
49
49
  raise Nanoc::Int::Errors::CannotLayoutBinaryItem.new(@rep) if last.binary?
50
50
 
51
51
  # Create filter
@@ -58,7 +58,7 @@ module Nanoc
58
58
  @dependency_tracker.bounce(layout, raw_content: true)
59
59
 
60
60
  begin
61
- Nanoc::Int::NotificationCenter.post(:filtering_started, @rep, filter_name)
61
+ Nanoc::Core::NotificationCenter.post(:filtering_started, @rep, filter_name)
62
62
 
63
63
  # Layout
64
64
  content = layout.content
@@ -66,16 +66,17 @@ module Nanoc
66
66
  res = filter.setup_and_run(arg, filter_args)
67
67
 
68
68
  # Store
69
- last = Nanoc::Int::TextualContent.new(res).tap(&:freeze)
70
- @compilation_context.snapshot_repo.set(@rep, :last, last)
69
+ last = Nanoc::Core::TextualContent.new(res).tap(&:freeze)
70
+ @compilation_context.compiled_content_store.set_current(@rep, last)
71
71
  ensure
72
- Nanoc::Int::NotificationCenter.post(:filtering_ended, @rep, filter_name)
72
+ Nanoc::Core::NotificationCenter.post(:filtering_ended, @rep, filter_name)
73
73
  end
74
74
  end
75
75
 
76
76
  def snapshot(snapshot_name)
77
- last = @compilation_context.snapshot_repo.get(@rep, :last)
78
- @compilation_context.snapshot_repo.set(@rep, snapshot_name, last)
77
+ last = @compilation_context.compiled_content_store.get_current(@rep)
78
+ @compilation_context.compiled_content_store.set(@rep, snapshot_name, last)
79
+ Nanoc::Core::NotificationCenter.post(:snapshot_created, @rep, snapshot_name)
79
80
  end
80
81
 
81
82
  def assigns_for(rep)
@@ -92,7 +93,7 @@ module Nanoc
92
93
  return layout if layout
93
94
 
94
95
  if use_globs?
95
- pat = Nanoc::Int::Pattern.from(arg)
96
+ pat = Nanoc::Core::Pattern.from(arg)
96
97
  layout = layouts.find { |l| pat.match?(l.identifier) }
97
98
  return layout if layout
98
99
  end
@@ -103,7 +104,7 @@ module Nanoc
103
104
  def filter_for_filtering(rep, filter_name)
104
105
  klass = Nanoc::Filter.named!(filter_name)
105
106
 
106
- last = @compilation_context.snapshot_repo.get(@rep, :last)
107
+ last = @compilation_context.compiled_content_store.get_current(@rep)
107
108
  if klass.from_binary? && !last.binary?
108
109
  raise Nanoc::Int::Errors::CannotUseBinaryFilter.new(rep, klass)
109
110
  elsif !klass.from_binary? && last.binary?
@@ -25,12 +25,41 @@ module Nanoc
25
25
  # # => 'bar'
26
26
  #
27
27
  # @abstract Subclass and override {#run} to implement a custom filter.
28
- class Filter < Nanoc::Int::Context
28
+ class Filter < Nanoc::Core::Context
29
29
  # @api private
30
30
  TMP_BINARY_ITEMS_DIR = 'binary_items'
31
31
 
32
32
  extend DDPlugin::Plugin
33
33
 
34
+ include Nanoc::Core::ContractsSupport
35
+
36
+ class UnknownFilterError < Nanoc::Core::Error
37
+ include Nanoc::Core::ContractsSupport
38
+
39
+ contract C::Or[String, Symbol] => self
40
+ def initialize(filter_name)
41
+ super("The requested filter, “#{filter_name}”, does not exist.")
42
+ end
43
+ end
44
+
45
+ class OutputNotWrittenError < Nanoc::Core::Error
46
+ include Nanoc::Core::ContractsSupport
47
+
48
+ contract C::Or[String, Symbol], String => self
49
+ def initialize(filter_name, output_filename)
50
+ super("The #{filter_name.inspect} filter did not write anything to the required output file, #{output_filename}.")
51
+ end
52
+ end
53
+
54
+ class FilterReturnedNilError < Nanoc::Core::Error
55
+ include Nanoc::Core::ContractsSupport
56
+
57
+ contract C::Or[String, Symbol] => self
58
+ def initialize(filter_name)
59
+ super("The #{filter_name.inspect} filter returned nil, but is required to return a String.")
60
+ end
61
+ end
62
+
34
63
  class << self
35
64
  def define(ident, &block)
36
65
  filter_class = Class.new(::Nanoc::Filter) { identifier(ident) }
@@ -41,7 +70,7 @@ module Nanoc
41
70
 
42
71
  def named!(name)
43
72
  klass = named(name)
44
- raise Nanoc::Int::Errors::UnknownFilter.new(name) if klass.nil?
73
+ raise UnknownFilterError.new(name) if klass.nil?
45
74
 
46
75
  klass
47
76
  end
@@ -179,15 +208,16 @@ module Nanoc
179
208
  def verify(res)
180
209
  if self.class.to_binary?
181
210
  unless File.file?(output_filename)
182
- raise Nanoc::Int::Errors::OutputNotWritten.new(self.class.identifier, output_filename)
211
+ raise Nanoc::Filter::OutputNotWrittenError.new(self.class.identifier, output_filename)
183
212
  end
184
213
  elsif self.class.to_text?
185
214
  unless res
186
- raise Nanoc::Int::Errors::FilterReturnedNil.new(self.class.identifier)
215
+ raise Nanoc::Filter::FilterReturnedNilError.new(self.class.identifier)
187
216
  end
188
217
  end
189
218
  end
190
219
 
220
+ contract C::None => String
191
221
  # Returns a filename that is used to write data to. This method is only
192
222
  # used on binary items. When running a binary filter on a file, the
193
223
  # resulting file must end up in the location returned by this method.
@@ -198,9 +228,10 @@ module Nanoc
198
228
  # @return [String] The output filename
199
229
  def output_filename
200
230
  @output_filename ||=
201
- Nanoc::Int::TempFilenameFactory.instance.create(TMP_BINARY_ITEMS_DIR)
231
+ Nanoc::Core::TempFilenameFactory.instance.create(TMP_BINARY_ITEMS_DIR)
202
232
  end
203
233
 
234
+ contract C::None => String
204
235
  # Returns the filename associated with the item that is being filtered.
205
236
  # It is in the format `item <identifier> (rep <name>)`.
206
237
  #
@@ -222,6 +253,7 @@ module Nanoc
222
253
  Fiber.yield(block)
223
254
  end
224
255
 
256
+ contract C::ArrayOf[C::Named['Nanoc::BasicItemView']] => C::Any
225
257
  # Creates a dependency from the item that is currently being filtered onto
226
258
  # the given collection of items. In other words, require the given items
227
259
  # to be compiled first before this items is processed.
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Nanoc::Int
4
- # @api private
5
- class Instrumentor
6
- def self.call(key, *args)
7
- stopwatch = DDMetrics::Stopwatch.new
8
- stopwatch.start
9
- yield
10
- ensure
11
- stopwatch.stop
12
- Nanoc::Int::NotificationCenter.post(key, stopwatch.duration, *args)
3
+ module Nanoc
4
+ module Int
5
+ # @api private
6
+ class Instrumentor
7
+ def self.call(key, *args)
8
+ stopwatch = DDMetrics::Stopwatch.new
9
+ stopwatch.start
10
+ yield
11
+ ensure
12
+ stopwatch.stop
13
+ Nanoc::Core::NotificationCenter.post(key, stopwatch.duration, *args)
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -1,30 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Nanoc::Int
4
- # @api private
5
- class ItemRepBuilder
6
- attr_reader :reps
3
+ module Nanoc
4
+ module Int
5
+ # @api private
6
+ class ItemRepBuilder
7
+ attr_reader :reps
7
8
 
8
- def initialize(site, action_provider, reps)
9
- @site = site
10
- @action_provider = action_provider
11
- @reps = reps
12
- end
9
+ def initialize(site, action_provider, reps)
10
+ @site = site
11
+ @action_provider = action_provider
12
+ @reps = reps
13
+ end
13
14
 
14
- def run
15
- @site.items.each do |item|
16
- @action_provider.rep_names_for(item).each do |rep_name|
17
- @reps << Nanoc::Int::ItemRep.new(item, rep_name)
15
+ def run
16
+ @site.items.each do |item|
17
+ @action_provider.rep_names_for(item).each do |rep_name|
18
+ @reps << Nanoc::Core::ItemRep.new(item, rep_name)
19
+ end
18
20
  end
19
- end
20
21
 
21
- action_sequences = Nanoc::Int::ItemRepRouter.new(@reps, @action_provider, @site).run
22
+ action_sequences = Nanoc::Int::ItemRepRouter.new(@reps, @action_provider, @site).run
22
23
 
23
- @reps.each do |rep|
24
- rep.snapshot_defs = action_sequences[rep].snapshots_defs
25
- end
24
+ @reps.each do |rep|
25
+ rep.snapshot_defs = action_sequences[rep].snapshots_defs
26
+ end
26
27
 
27
- action_sequences
28
+ action_sequences
29
+ end
28
30
  end
29
31
  end
30
32
  end
@@ -1,96 +1,98 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Nanoc::Int
4
- # Assigns paths to reps.
5
- #
6
- # @api private
7
- class ItemRepRouter
8
- include Nanoc::Int::ContractsSupport
3
+ module Nanoc
4
+ module Int
5
+ # Assigns paths to reps.
6
+ #
7
+ # @api private
8
+ class ItemRepRouter
9
+ include Nanoc::Core::ContractsSupport
9
10
 
10
- class IdenticalRoutesError < ::Nanoc::Error
11
- def initialize(output_path, rep_a, rep_b)
12
- super("The item representations #{rep_a} and #{rep_b} are both routed to #{output_path}.")
11
+ class IdenticalRoutesError < ::Nanoc::Error
12
+ def initialize(output_path, rep_a, rep_b)
13
+ super("The item representations #{rep_a} and #{rep_b} are both routed to #{output_path}.")
14
+ end
13
15
  end
14
- end
15
16
 
16
- class RouteWithoutSlashError < ::Nanoc::Error
17
- def initialize(output_path, rep)
18
- super("The item representation #{rep} is routed to #{output_path}, which does not start with a slash, as required.")
17
+ class RouteWithoutSlashError < ::Nanoc::Error
18
+ def initialize(output_path, rep)
19
+ super("The item representation #{rep} is routed to #{output_path}, which does not start with a slash, as required.")
20
+ end
19
21
  end
20
- end
21
22
 
22
- def initialize(reps, action_provider, site)
23
- @reps = reps
24
- @action_provider = action_provider
25
- @site = site
26
- end
23
+ def initialize(reps, action_provider, site)
24
+ @reps = reps
25
+ @action_provider = action_provider
26
+ @site = site
27
+ end
27
28
 
28
- def run
29
- action_sequences = {}
30
- assigned_paths = {}
31
- @reps.each do |rep|
32
- # Sigh. We route reps twice, because the first time, the paths might not have converged
33
- # yet. This isn’t ideal, but it’s the only way to work around the divergence issues that
34
- # I can think of. For details, see
35
- # https://github.com/nanoc/nanoc/pull/1085#issuecomment-280628426.
29
+ def run
30
+ action_sequences = {}
31
+ assigned_paths = {}
32
+ @reps.each do |rep|
33
+ # Sigh. We route reps twice, because the first time, the paths might not have converged
34
+ # yet. This isn’t ideal, but it’s the only way to work around the divergence issues that
35
+ # I can think of. For details, see
36
+ # https://github.com/nanoc/nanoc/pull/1085#issuecomment-280628426.
36
37
 
37
- @action_provider.action_sequence_for(rep).paths.each do |(snapshot_names, paths)|
38
- route_rep(rep, paths, snapshot_names, {})
39
- end
38
+ @action_provider.action_sequence_for(rep).paths.each do |(snapshot_names, paths)|
39
+ route_rep(rep, paths, snapshot_names, {})
40
+ end
40
41
 
41
- seq = @action_provider.action_sequence_for(rep)
42
- action_sequences[rep] = seq
43
- seq.paths.each do |(snapshot_names, paths)|
44
- route_rep(rep, paths, snapshot_names, assigned_paths)
42
+ seq = @action_provider.action_sequence_for(rep)
43
+ action_sequences[rep] = seq
44
+ seq.paths.each do |(snapshot_names, paths)|
45
+ route_rep(rep, paths, snapshot_names, assigned_paths)
46
+ end
47
+
48
+ # TODO: verify that paths converge
45
49
  end
46
50
 
47
- # TODO: verify that paths converge
51
+ action_sequences
48
52
  end
49
53
 
50
- action_sequences
51
- end
52
-
53
- contract Nanoc::Int::ItemRep, C::IterOf[String], C::IterOf[Symbol], C::HashOf[String => Nanoc::Int::ItemRep] => C::Any
54
- def route_rep(rep, paths, snapshot_names, assigned_paths)
55
- # Encode
56
- paths = paths.map { |path| path.encode('UTF-8') }
54
+ contract Nanoc::Core::ItemRep, C::IterOf[String], C::IterOf[Symbol], C::HashOf[String => Nanoc::Core::ItemRep] => C::Any
55
+ def route_rep(rep, paths, snapshot_names, assigned_paths)
56
+ # Encode
57
+ paths = paths.map { |path| path.encode('UTF-8') }
57
58
 
58
- # Validate format
59
- paths.each do |path|
60
- unless path.start_with?('/')
61
- raise RouteWithoutSlashError.new(path, rep)
59
+ # Validate format
60
+ paths.each do |path|
61
+ unless path.start_with?('/')
62
+ raise RouteWithoutSlashError.new(path, rep)
63
+ end
62
64
  end
63
- end
64
65
 
65
- # Validate uniqueness
66
- paths.each do |path|
67
- if assigned_paths.include?(path)
68
- # TODO: Include snapshot names in error message
69
- reps = [assigned_paths[path], rep].sort_by { |r| [r.item.identifier, r.name] }
70
- raise IdenticalRoutesError.new(path, *reps)
66
+ # Validate uniqueness
67
+ paths.each do |path|
68
+ if assigned_paths.include?(path)
69
+ # TODO: Include snapshot names in error message
70
+ reps = [assigned_paths[path], rep].sort_by { |r| [r.item.identifier, r.name] }
71
+ raise IdenticalRoutesError.new(path, *reps)
72
+ end
73
+ end
74
+ paths.each do |path|
75
+ assigned_paths[path] = rep
71
76
  end
72
- end
73
- paths.each do |path|
74
- assigned_paths[path] = rep
75
- end
76
77
 
77
- # Assign
78
- snapshot_names.each do |snapshot_name|
79
- rep.raw_paths[snapshot_name] = paths.map { |path| @site.config.output_dir + path }
80
- rep.paths[snapshot_name] = paths.map { |path| strip_index_filename(path) }
78
+ # Assign
79
+ snapshot_names.each do |snapshot_name|
80
+ rep.raw_paths[snapshot_name] = paths.map { |path| @site.config.output_dir + path }
81
+ rep.paths[snapshot_name] = paths.map { |path| strip_index_filename(path) }
82
+ end
81
83
  end
82
- end
83
84
 
84
- contract String => String
85
- def strip_index_filename(basic_path)
86
- @site.config[:index_filenames].each do |index_filename|
87
- slashed_index_filename = '/' + index_filename
88
- if basic_path.end_with?(slashed_index_filename)
89
- return basic_path[0..-index_filename.length - 1]
85
+ contract String => String
86
+ def strip_index_filename(basic_path)
87
+ @site.config[:index_filenames].each do |index_filename|
88
+ slashed_index_filename = '/' + index_filename
89
+ if basic_path.end_with?(slashed_index_filename)
90
+ return basic_path[0..-index_filename.length - 1]
91
+ end
90
92
  end
91
- end
92
93
 
93
- basic_path
94
+ basic_path
95
+ end
94
96
  end
95
97
  end
96
98
  end
@@ -1,64 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Nanoc::Int
4
- # Yields item reps to compile.
5
- #
6
- # @api private
7
- class ItemRepSelector
8
- def initialize(reps)
9
- @reps = reps
10
- end
11
-
12
- class MicroGraph
3
+ module Nanoc
4
+ module Int
5
+ # Yields item reps to compile.
6
+ #
7
+ # @api private
8
+ class ItemRepSelector
13
9
  def initialize(reps)
14
- @reps = Set.new(reps)
15
- @stack = []
10
+ @reps = reps
16
11
  end
17
12
 
18
- def next
19
- if @stack.any?
20
- @stack.last
21
- elsif @reps.any?
22
- @reps.each { |rep| break rep }.tap do |rep|
23
- @reps.delete(rep)
24
- @stack.push(rep)
25
- end
26
- else
27
- nil
13
+ class MicroGraph
14
+ def initialize(reps)
15
+ @reps = Set.new(reps)
16
+ @stack = []
28
17
  end
29
- end
30
18
 
31
- def mark_ok
32
- @stack.pop
33
- end
19
+ def next
20
+ if @stack.any?
21
+ @stack.last
22
+ elsif @reps.any?
23
+ @reps.each { |rep| break rep }.tap do |rep|
24
+ @reps.delete(rep)
25
+ @stack.push(rep)
26
+ end
27
+ else
28
+ nil
29
+ end
30
+ end
34
31
 
35
- def mark_failed(dep)
36
- if @stack.include?(dep)
37
- raise Nanoc::Int::Errors::DependencyCycle.new(@stack + [dep])
32
+ def mark_ok
33
+ @stack.pop
38
34
  end
39
35
 
40
- @reps.delete(dep)
41
- @stack.push(dep)
36
+ def mark_failed(dep)
37
+ if @stack.include?(dep)
38
+ raise Nanoc::Int::Errors::DependencyCycle.new(@stack + [dep])
39
+ end
40
+
41
+ @reps.delete(dep)
42
+ @stack.push(dep)
43
+ end
42
44
  end
43
- end
44
45
 
45
- def each
46
- mg = MicroGraph.new(@reps)
46
+ def each
47
+ mg = MicroGraph.new(@reps)
47
48
 
48
- loop do
49
- rep = mg.next
50
- break if rep.nil?
49
+ loop do
50
+ rep = mg.next
51
+ break if rep.nil?
51
52
 
52
- begin
53
- yield(rep)
54
- mg.mark_ok
55
- rescue => e
56
- actual_error = e.is_a?(Nanoc::Int::Errors::CompilationError) ? e.unwrap : e
53
+ begin
54
+ yield(rep)
55
+ mg.mark_ok
56
+ rescue => e
57
+ actual_error = e.is_a?(Nanoc::Int::Errors::CompilationError) ? e.unwrap : e
57
58
 
58
- if actual_error.is_a?(Nanoc::Int::Errors::UnmetDependency)
59
- mg.mark_failed(actual_error.rep)
60
- else
61
- raise(e)
59
+ if actual_error.is_a?(Nanoc::Int::Errors::UnmetDependency)
60
+ mg.mark_failed(actual_error.rep)
61
+ else
62
+ raise(e)
63
+ end
62
64
  end
63
65
  end
64
66
  end