nanoc 4.0.2 → 4.1.0a1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +17 -0
  3. data/Gemfile +50 -46
  4. data/Gemfile.lock +365 -0
  5. data/Guardfile +3 -0
  6. data/NEWS.md +21 -0
  7. data/README.md +1 -1
  8. data/lib/nanoc/base.rb +3 -15
  9. data/lib/nanoc/base/checksummer.rb +3 -14
  10. data/lib/nanoc/base/compilation/compiler.rb +112 -283
  11. data/lib/nanoc/base/compilation/compiler_dsl.rb +29 -37
  12. data/lib/nanoc/base/compilation/dependency_tracker.rb +25 -170
  13. data/lib/nanoc/base/compilation/filter.rb +3 -4
  14. data/lib/nanoc/base/compilation/item_rep_repo.rb +33 -0
  15. data/lib/nanoc/base/compilation/outdatedness_checker.rb +39 -53
  16. data/lib/nanoc/base/compilation/rule.rb +13 -24
  17. data/lib/nanoc/base/compilation/rule_context.rb +29 -15
  18. data/lib/nanoc/base/entities.rb +10 -0
  19. data/lib/nanoc/base/{source_data → entities}/code_snippet.rb +1 -4
  20. data/lib/nanoc/base/{source_data → entities}/configuration.rb +1 -1
  21. data/lib/nanoc/base/entities/content.rb +8 -9
  22. data/lib/nanoc/base/{identifiable_collection.rb → entities/identifiable_collection.rb} +0 -0
  23. data/lib/nanoc/base/entities/identifier.rb +11 -2
  24. data/lib/nanoc/base/{source_data → entities}/item.rb +0 -18
  25. data/lib/nanoc/base/{result_data → entities}/item_rep.rb +15 -13
  26. data/lib/nanoc/base/entities/rule_memory.rb +54 -0
  27. data/lib/nanoc/base/entities/rule_memory_action.rb +19 -0
  28. data/lib/nanoc/base/entities/rule_memory_actions.rb +3 -0
  29. data/lib/nanoc/base/entities/rule_memory_actions/filter.rb +22 -0
  30. data/lib/nanoc/base/entities/rule_memory_actions/layout.rb +22 -0
  31. data/lib/nanoc/base/entities/rule_memory_actions/snapshot.rb +26 -0
  32. data/lib/nanoc/base/entities/rules_collection.rb +120 -0
  33. data/lib/nanoc/base/{source_data → entities}/site.rb +11 -10
  34. data/lib/nanoc/base/repos.rb +2 -0
  35. data/lib/nanoc/base/repos/checksum_store.rb +3 -9
  36. data/lib/nanoc/base/repos/compiled_content_cache.rb +0 -5
  37. data/lib/nanoc/base/{source_data → repos}/data_source.rb +3 -6
  38. data/lib/nanoc/base/repos/dependency_store.rb +118 -0
  39. data/lib/nanoc/base/repos/rule_memory_store.rb +1 -5
  40. data/lib/nanoc/base/repos/site_loader.rb +0 -28
  41. data/lib/nanoc/base/repos/store.rb +0 -12
  42. data/lib/nanoc/base/services.rb +8 -0
  43. data/lib/nanoc/base/services/compiler_loader.rb +49 -0
  44. data/lib/nanoc/base/services/executor.rb +4 -4
  45. data/lib/nanoc/base/services/item_rep_builder.rb +30 -0
  46. data/lib/nanoc/base/services/item_rep_router.rb +55 -0
  47. data/lib/nanoc/base/services/item_rep_selector.rb +39 -0
  48. data/lib/nanoc/base/services/item_rep_writer.rb +2 -0
  49. data/lib/nanoc/base/services/postprocessor.rb +26 -0
  50. data/lib/nanoc/base/services/preprocessor.rb +26 -0
  51. data/lib/nanoc/base/services/recording_executor.rb +36 -22
  52. data/lib/nanoc/base/services/rule_memory_calculator.rb +84 -0
  53. data/lib/nanoc/base/services/rules_loader.rb +29 -0
  54. data/lib/nanoc/base/views.rb +6 -0
  55. data/lib/nanoc/base/views/config_view.rb +8 -2
  56. data/lib/nanoc/base/views/identifiable_collection_view.rb +5 -4
  57. data/lib/nanoc/base/views/item_rep_collection_view.rb +7 -6
  58. data/lib/nanoc/base/views/item_rep_view.rb +13 -12
  59. data/lib/nanoc/base/views/item_view.rb +18 -12
  60. data/lib/nanoc/base/views/layout_view.rb +1 -1
  61. data/lib/nanoc/base/views/mixins/document_view_mixin.rb +2 -1
  62. data/lib/nanoc/base/views/mutable_identifiable_collection_view.rb +1 -1
  63. data/lib/nanoc/base/views/mutable_item_collection_view.rb +4 -7
  64. data/lib/nanoc/base/views/post_compile_item_collection_view.rb +8 -0
  65. data/lib/nanoc/base/views/post_compile_item_view.rb +7 -0
  66. data/lib/nanoc/base/views/site_view.rb +3 -2
  67. data/lib/nanoc/base/views/view.rb +12 -0
  68. data/lib/nanoc/base/views/view_context.rb +12 -0
  69. data/lib/nanoc/cli/commands/compile.rb +13 -15
  70. data/lib/nanoc/cli/commands/create-site.rb +15 -0
  71. data/lib/nanoc/cli/commands/prune.rb +1 -1
  72. data/lib/nanoc/cli/commands/shell.rb +3 -3
  73. data/lib/nanoc/cli/commands/show-data.rb +5 -5
  74. data/lib/nanoc/cli/commands/show-rules.rb +2 -1
  75. data/lib/nanoc/cli/error_handler.rb +28 -30
  76. data/lib/nanoc/cli/stream_cleaners/ansi_colors.rb +1 -1
  77. data/lib/nanoc/data_sources/filesystem.rb +1 -1
  78. data/lib/nanoc/extra/checking/check.rb +8 -7
  79. data/lib/nanoc/extra/checking/checks/external_links.rb +14 -1
  80. data/lib/nanoc/extra/checking/runner.rb +1 -1
  81. data/lib/nanoc/extra/deployer.rb +3 -3
  82. data/lib/nanoc/extra/piper.rb +5 -5
  83. data/lib/nanoc/extra/pruner.rb +8 -7
  84. data/lib/nanoc/filters/relativize_paths.rb +48 -32
  85. data/lib/nanoc/filters/sass/sass_filesystem_importer.rb +0 -1
  86. data/lib/nanoc/helpers/blogging.rb +15 -7
  87. data/lib/nanoc/helpers/capturing.rb +56 -13
  88. data/lib/nanoc/helpers/link_to.rb +2 -2
  89. data/lib/nanoc/helpers/tagging.rb +5 -10
  90. data/lib/nanoc/helpers/text.rb +9 -11
  91. data/lib/nanoc/version.rb +1 -1
  92. data/nanoc-4.0.2.gem +0 -0
  93. data/tags +1175 -0
  94. data/test/base/test_compiler.rb +48 -98
  95. data/test/base/test_compiler_dsl.rb +113 -39
  96. data/test/base/test_dependency_tracker.rb +80 -79
  97. data/test/base/test_outdatedness_checker.rb +39 -26
  98. data/test/base/test_site.rb +0 -97
  99. data/test/cli/commands/test_compile.rb +2 -3
  100. data/test/extra/checking/checks/test_external_links.rb +25 -0
  101. data/test/extra/deployers/test_fog.rb +12 -6
  102. data/test/filters/test_erb.rb +1 -1
  103. data/test/filters/test_erubis.rb +1 -1
  104. data/test/filters/test_haml.rb +1 -1
  105. data/test/filters/test_less.rb +4 -4
  106. data/test/filters/test_sass.rb +1 -0
  107. data/test/filters/test_xsl.rb +7 -8
  108. data/test/helper.rb +0 -2
  109. data/test/helpers/test_blogging.rb +26 -23
  110. data/test/helpers/test_capturing.rb +131 -12
  111. data/test/helpers/test_filtering.rb +6 -6
  112. data/test/helpers/test_link_to.rb +1 -1
  113. data/test/helpers/test_rendering.rb +16 -24
  114. data/test/helpers/test_tagging.rb +13 -10
  115. data/test/helpers/test_xml_sitemap.rb +25 -21
  116. metadata +36 -14
  117. data/lib/nanoc/base/compilation/rule_memory_calculator.rb +0 -35
  118. data/lib/nanoc/base/compilation/rules_collection.rb +0 -245
  119. data/test/base/test_rule_context.rb +0 -78
data/Guardfile ADDED
@@ -0,0 +1,3 @@
1
+ guard 'rake', task: 'default' do
2
+ watch(%r{^(lib|test|spec)/})
3
+ end
data/NEWS.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Nanoc news
2
2
 
3
+ ## 4.1.0a1 (2015-12-05)
4
+
5
+ Features:
6
+
7
+ * Added `postprocess` block (#726) [Garen Torikian]
8
+ * Added `#write` compilation instruction and `path` option to `#snapshot` (#753)
9
+
10
+ Fixes:
11
+
12
+ * Fixed crash when printing non-string object (#712) [Garen Torikian]
13
+ * Removed English text from `#link_to` helper (#736) [Lucas Vuotto]
14
+
15
+ Enhancements:
16
+
17
+ * Allowed excluding URLs from external links check (#686) [Yannick Ihmels]
18
+ * Added `atom` to list of text extensions (#657) [Yannick Ihmels]
19
+ * Added `#each` to `Nanoc::ConfigView` (#705) [Garen Torikian]
20
+ * Made `#attribute_to_time` handle `DateTime` (#717) [Micha Rosenbaum]
21
+ * Added `Identifier#components` (#677)
22
+ * Added `:existing` option to `#content_for` (can be `:error`, `:overwrite` and `:append`) (#744)
23
+
3
24
  ## 4.0.2 (2015-11-30)
4
25
 
5
26
  Fixes:
data/README.md CHANGED
@@ -19,4 +19,4 @@ Contributions are greatly appreciated! Consult the [Development guidelines](http
19
19
 
20
20
  Many thanks to everyone who has contributed to Nanoc in one way or another:
21
21
 
22
- Ale Muñoz, Alexander Mankuta, Arnau Siches, Ben Armston, Bil Bas, Brian Candler, Bruno Dufour, Chris Eppstein, Christian Plessl, Colin Barrett, Croath Liu, Damien Pollet, Dan Callahan, Daniel Hofstetter, Daniel Mendler, Daniel Wollschlaeger, David Alexander, David Everitt, Dennis Sutch, Devon Luke Buchanan, Dmitry Bilunov, Eric Sunshine, Erik Hollensbe, Fabian Buch, Felix Hanley, Go Maeda, Gregory Pakosz, Grégory Karékinian, Guilherme Garnier, Jack Chu, Jake Benilov, Jasper Van der Jeugt, Jeff Forcier, Jim Mendenhall, John Nishinaga, Justin Clift, Justin Hileman, Kevin Lynagh, Louis T., Mathias Bynens, Matt Keveney, Matthew Frazier, Matthias Beyer, Matthias Reitinger, Matthias Vallentin, Michal Cichra, Nelson Chen, Nicky Peeters, Nikhil Marathe, Oliver Byford, Peter Aronoff, Raphael von der Grün, Rémi Barraquand, Remko Tronçon, Riley Goodside, Ruben Verborgh, Scott Vokes, Šime Ramov, Simon South, Spencer Whitt, Stanley Rost, Starr Horne, Stefan Bühler, Stuart Montgomery, Takashi Uchibe, Toon Willems, Tuomas Kareinen, Ursula Kallio, Vincent Driessen, Xavier Shay, Yannick Ihmels, Zaiste de Grengolada
22
+ Ale Muñoz, Alexander Mankuta, Arnau Siches, Ben Armston, Bil Bas, Brian Candler, Bruno Dufour, Chris Eppstein, Christian Plessl, Colin Barrett, Croath Liu, Damien Pollet, Dan Callahan, Daniel Hofstetter, Daniel Mendler, Daniel Wollschlaeger, David Alexander, David Everitt, Dennis Sutch, Devon Luke Buchanan, Dmitry Bilunov, Eric Sunshine, Erik Hollensbe, Fabian Buch, Felix Hanley, Garen Torikian, Go Maeda, Gregory Pakosz, Grégory Karékinian, Guilherme Garnier, Jack Chu, Jake Benilov, Jasper Van der Jeugt, Jeff Forcier, Jim Mendenhall, John Nishinaga, Justin Clift, Justin Hileman, Kevin Lynagh, Louis T., Mathias Bynens, Matt Keveney, Matthew Frazier, Matthias Beyer, Matthias Reitinger, Matthias Vallentin, Michal Cichra, Nelson Chen, Nicky Peeters, Nikhil Marathe, Oliver Byford, Peter Aronoff, Raphael von der Grün, Rémi Barraquand, Remko Tronçon, Riley Goodside, Ruben Verborgh, Scott Vokes, Šime Ramov, Simon South, Spencer Whitt, Stanley Rost, Starr Horne, Stefan Bühler, Stuart Montgomery, Takashi Uchibe, Toon Willems, Tuomas Kareinen, Ursula Kallio, Vincent Driessen, Xavier Shay, Yannick Ihmels, Zaiste de Grengolada
data/lib/nanoc/base.rb CHANGED
@@ -1,8 +1,5 @@
1
1
  module Nanoc
2
- require 'nanoc/base/core_ext'
3
-
4
2
  autoload 'Error', 'nanoc/base/error'
5
- autoload 'DataSource', 'nanoc/base/source_data/data_source'
6
3
  autoload 'Filter', 'nanoc/base/compilation/filter'
7
4
  end
8
5
 
@@ -15,29 +12,20 @@ module Nanoc::Int
15
12
  autoload 'Errors', 'nanoc/base/errors'
16
13
  autoload 'Memoization', 'nanoc/base/memoization'
17
14
  autoload 'PluginRegistry', 'nanoc/base/plugin_registry'
18
- autoload 'IdentifiableCollection', 'nanoc/base/identifiable_collection'
19
-
20
- # Load source data classes
21
- autoload 'CodeSnippet', 'nanoc/base/source_data/code_snippet'
22
- autoload 'Configuration', 'nanoc/base/source_data/configuration'
23
- autoload 'Item', 'nanoc/base/source_data/item'
24
- autoload 'Site', 'nanoc/base/source_data/site'
25
-
26
- # Load result data classes
27
- autoload 'ItemRep', 'nanoc/base/result_data/item_rep'
28
15
 
29
16
  # Load compilation classes
30
17
  autoload 'Compiler', 'nanoc/base/compilation/compiler'
31
18
  autoload 'CompilerDSL', 'nanoc/base/compilation/compiler_dsl'
32
19
  autoload 'DependencyTracker', 'nanoc/base/compilation/dependency_tracker'
20
+ autoload 'ItemRepRepo', 'nanoc/base/compilation/item_rep_repo'
33
21
  autoload 'OutdatednessChecker', 'nanoc/base/compilation/outdatedness_checker'
34
22
  autoload 'OutdatednessReasons', 'nanoc/base/compilation/outdatedness_reasons'
35
23
  autoload 'Rule', 'nanoc/base/compilation/rule'
36
24
  autoload 'RuleContext', 'nanoc/base/compilation/rule_context'
37
- autoload 'RuleMemoryCalculator', 'nanoc/base/compilation/rule_memory_calculator'
38
- autoload 'RulesCollection', 'nanoc/base/compilation/rules_collection'
39
25
  end
40
26
 
27
+ require_relative 'base/core_ext'
28
+
41
29
  require_relative 'base/entities'
42
30
  require_relative 'base/repos'
43
31
  require_relative 'base/services'
@@ -56,12 +56,10 @@ module Nanoc::Int
56
56
  end
57
57
 
58
58
  case obj
59
- when ::String
60
- digest.update(obj)
61
- when ::Symbol
59
+ when ::String, ::Symbol, ::Numeric
62
60
  digest.update(obj.to_s)
63
61
  when nil, true, false
64
- when ::Array
62
+ when ::Array, ::Nanoc::Int::IdentifiableCollection
65
63
  obj.each do |el|
66
64
  update(el, digest, visited + [obj])
67
65
  digest.update(',')
@@ -83,13 +81,9 @@ module Nanoc::Int
83
81
  end
84
82
  when Time
85
83
  digest.update(obj.to_i.to_s)
86
- when Numeric
87
- digest.update(obj.to_s)
88
84
  when Nanoc::Identifier
89
85
  update(obj.to_s, digest)
90
- when Nanoc::Int::RulesCollection
91
- update(obj.data, digest)
92
- when Nanoc::Int::CodeSnippet
86
+ when Nanoc::Int::RulesCollection, Nanoc::Int::CodeSnippet
93
87
  update(obj.data, digest)
94
88
  when Nanoc::Int::TextualContent
95
89
  update(obj.string, digest)
@@ -106,11 +100,6 @@ module Nanoc::Int
106
100
  update(obj.identifier, digest)
107
101
  when Nanoc::ItemView, Nanoc::LayoutView, Nanoc::ConfigView, Nanoc::IdentifiableCollectionView
108
102
  update(obj.unwrap, digest)
109
- when Nanoc::Int::IdentifiableCollection
110
- obj.each do |el|
111
- update(el, digest, visited + [obj])
112
- digest.update(',')
113
- end
114
103
  else
115
104
  data = begin
116
105
  Marshal.dump(obj)
@@ -38,17 +38,7 @@ module Nanoc::Int
38
38
  #
39
39
  # @api private
40
40
  class Compiler
41
- extend Nanoc::Int::Memoization
42
-
43
- class IdenticalRoutesError < ::Nanoc::Error
44
- def initialize(output_path, rep_a, rep_b)
45
- super("The item representations #{rep_a.inspect} and #{rep_b.inspect} are both routed to #{output_path}.")
46
- end
47
- end
48
-
49
- # @group Accessors
50
-
51
- # @return [Nanoc::Int::Site] The site this compiler belongs to
41
+ # @api private
52
42
  attr_reader :site
53
43
 
54
44
  # The compilation stack. When the compiler begins compiling a rep or a
@@ -58,98 +48,89 @@ module Nanoc::Int
58
48
  # @return [Array] The compilation stack
59
49
  attr_reader :stack
60
50
 
61
- # @group Public instance methods
51
+ # @api private
52
+ attr_reader :rules_collection
62
53
 
63
- # Creates a new compiler fo the given site
64
- #
65
- # @param [Nanoc::Int::Site] site The site this compiler belongs to
66
- def initialize(site)
67
- @site = site
54
+ # @api private
55
+ attr_reader :compiled_content_cache
68
56
 
69
- @stack = []
70
- end
57
+ # @api private
58
+ attr_reader :checksum_store
71
59
 
72
- # Compiles the site and writes out the compiled item representations.
73
- #
74
- # Previous versions of Nanoc (< 3.2) allowed passing items to compile, and
75
- # had a “force” option to make the compiler recompile all pages, even
76
- # when not outdated. These arguments and options are, as of Nanoc 3.2, no
77
- # longer used, and will simply be ignored when passed to {#run}.
78
- #
79
- # @overload run
80
- # @return [void]
81
- def run(*_args)
82
- # Create output directory if necessary
83
- FileUtils.mkdir_p(@site.config[:output_dir])
84
-
85
- # Compile reps
86
- load
87
- @site.freeze
60
+ # @api private
61
+ attr_reader :rule_memory_store
88
62
 
89
- # Determine which reps need to be recompiled
90
- forget_dependencies_if_outdated(items)
63
+ # @api private
64
+ attr_reader :rule_memory_calculator
91
65
 
92
- dependency_tracker.start
93
- compile_reps(reps)
94
- dependency_tracker.stop
95
- store
96
- ensure
97
- Nanoc::Int::TempFilenameFactory.instance.cleanup(
98
- Nanoc::Filter::TMP_BINARY_ITEMS_DIR)
99
- Nanoc::Int::TempFilenameFactory.instance.cleanup(
100
- Nanoc::Int::ItemRepWriter::TMP_TEXT_ITEMS_DIR)
101
- end
66
+ # @api private
67
+ attr_reader :dependency_store
68
+
69
+ # @api private
70
+ attr_reader :outdatedness_checker
71
+
72
+ # @api private
73
+ attr_reader :reps
102
74
 
103
- # @group Private instance methods
75
+ def initialize(site, rules_collection, compiled_content_cache:, checksum_store:, rule_memory_store:, rule_memory_calculator:, dependency_store:, outdatedness_checker:, reps:)
76
+ @site = site
77
+ @rules_collection = rules_collection
104
78
 
105
- # @return [Nanoc::Int::RulesCollection] The collection of rules to be used
106
- # for compiling this site
107
- def rules_collection
108
- Nanoc::Int::RulesCollection.new(self)
79
+ @compiled_content_cache = compiled_content_cache
80
+ @checksum_store = checksum_store
81
+ @rule_memory_store = rule_memory_store
82
+ @rule_memory_calculator = rule_memory_calculator
83
+ @dependency_store = dependency_store
84
+ @outdatedness_checker = outdatedness_checker
85
+ @reps = reps
86
+
87
+ @stack = []
109
88
  end
110
- memoize :rules_collection
111
89
 
112
- # Load the helper data that is used for compiling the site.
113
- #
114
- # @return [void]
115
- def load
116
- return if @loaded || @loading
117
- @loading = true
90
+ # 1. Load site
91
+ # 2. Load rules
92
+ # 3. Preprocess
93
+ # 4. Build item reps
94
+ # 5. Compile
95
+ # 6. Postprocess
118
96
 
97
+ # TODO: move elsewhere
98
+ def run_all
119
99
  # Preprocess
120
- rules_collection.load
121
- preprocess
122
- Nanoc::Int::SiteLoader.new.setup_child_parent_links(site.items)
100
+ Nanoc::Int::Preprocessor.new(site: @site, rules_collection: @rules_collection).run
101
+
102
+ # Build reps
123
103
  build_reps
124
- route_reps
125
104
 
126
- # Load auxiliary stores
127
- stores.each(&:load)
105
+ # Compile
106
+ run
128
107
 
129
- @loaded = true
130
- rescue => e
131
- unload
132
- raise e
133
- ensure
134
- @loading = false
108
+ # Postprocess
109
+ Nanoc::Int::Postprocessor.new(create_view_context, site: @site, rules_collection: @rules_collection).run
135
110
  end
136
111
 
137
- # Undoes the effects of {#load}. Used when {#load} raises an exception.
138
- #
139
- # @return [void]
140
- def unload
141
- return if @unloading
142
- @unloading = true
112
+ def run
113
+ load_stores
114
+ @site.freeze
143
115
 
144
- stores.each(&:unload)
116
+ # Determine which reps need to be recompiled
117
+ forget_dependencies_if_outdated
145
118
 
146
119
  @stack = []
120
+ dependency_tracker = Nanoc::Int::DependencyTracker.new(@dependency_store)
121
+ dependency_tracker.run do
122
+ compile_reps
123
+ end
124
+ store
125
+ ensure
126
+ Nanoc::Int::TempFilenameFactory.instance.cleanup(
127
+ Nanoc::Filter::TMP_BINARY_ITEMS_DIR)
128
+ Nanoc::Int::TempFilenameFactory.instance.cleanup(
129
+ Nanoc::Int::ItemRepWriter::TMP_TEXT_ITEMS_DIR)
130
+ end
147
131
 
148
- items.each { |item| item.reps.clear }
149
- rules_collection.unload
150
-
151
- @loaded = false
152
- @unloading = false
132
+ def load_stores
133
+ stores.each(&:load)
153
134
  end
154
135
 
155
136
  # Store the modified helper data used for compiling the site.
@@ -157,8 +138,8 @@ module Nanoc::Int
157
138
  # @return [void]
158
139
  def store
159
140
  # Calculate rule memory
160
- (reps + layouts.to_a).each do |obj|
161
- rule_memory_store[obj] = rule_memory_calculator[obj]
141
+ (@reps.to_a + @site.layouts.to_a).each do |obj|
142
+ rule_memory_store[obj] = rule_memory_calculator[obj].serialize
162
143
  end
163
144
 
164
145
  # Calculate checksums
@@ -170,26 +151,6 @@ module Nanoc::Int
170
151
  stores.each(&:store)
171
152
  end
172
153
 
173
- # Returns the dependency tracker for this site, creating it first if it
174
- # does not yet exist.
175
- #
176
- # @return [Nanoc::Int::DependencyTracker] The dependency tracker for this site
177
- def dependency_tracker
178
- dt = Nanoc::Int::DependencyTracker.new(@site.items.to_a + @site.layouts.to_a)
179
- dt.compiler = self
180
- dt
181
- end
182
- memoize :dependency_tracker
183
-
184
- # Runs the preprocessors.
185
- #
186
- # @api private
187
- def preprocess
188
- rules_collection.preprocessors.each_value do |preprocessor|
189
- preprocessor_context.instance_eval(&preprocessor)
190
- end
191
- end
192
-
193
154
  # Returns all objects managed by the site (items, layouts, code snippets,
194
155
  # site configuration and the rules).
195
156
  #
@@ -199,65 +160,10 @@ module Nanoc::Int
199
160
  [site.config, rules_collection]
200
161
  end
201
162
 
202
- # Creates the representations of all items as defined by the compilation
203
- # rules.
204
- #
205
- # @api private
206
163
  def build_reps
207
- items.each do |item|
208
- # Find matching rules
209
- matching_rules = rules_collection.item_compilation_rules_for(item)
210
- raise Nanoc::Int::Errors::NoMatchingCompilationRuleFound.new(item) if matching_rules.empty?
211
-
212
- # Create reps
213
- rep_names = matching_rules.map(&:rep_name).uniq
214
- rep_names.each do |rep_name|
215
- item.reps << Nanoc::Int::ItemRep.new(item, rep_name)
216
- end
217
- end
218
- end
219
-
220
- # Determines the paths of all item representations.
221
- #
222
- # @api private
223
- def route_reps
224
- paths_to_reps = {}
225
-
226
- reps.each do |rep|
227
- # Find matching rules
228
- rules = rules_collection.routing_rules_for(rep)
229
- raise Nanoc::Int::Errors::NoMatchingRoutingRuleFound.new(rep) if rules[:last].nil?
230
-
231
- rules.each_pair do |snapshot, rule|
232
- # Get basic path by applying matching rule
233
- basic_path = rule.apply_to(rep, executor: nil, compiler: self)
234
- next if basic_path.nil?
235
- if basic_path !~ %r{^/}
236
- raise "The path returned for the #{rep.inspect} item representation, “#{basic_path}”, does not start with a slash. Please ensure that all routing rules return a path that starts with a slash."
237
- end
238
-
239
- # Check for duplicate paths
240
- if paths_to_reps.key?(basic_path)
241
- raise IdenticalRoutesError.new(basic_path, paths_to_reps[basic_path], rep)
242
- else
243
- paths_to_reps[basic_path] = rep
244
- end
245
-
246
- # Get raw path by prepending output directory
247
- rep.raw_paths[snapshot] = @site.config[:output_dir] + basic_path
248
-
249
- # Get normal path by stripping index filename
250
- rep.paths[snapshot] = basic_path
251
- @site.config[:index_filenames].each do |index_filename|
252
- rep_path_ending = rep.paths[snapshot][-index_filename.length..-1]
253
- next unless rep_path_ending == index_filename
254
-
255
- # Strip and stop
256
- rep.paths[snapshot] = rep.paths[snapshot][0..-index_filename.length - 1]
257
- break
258
- end
259
- end
260
- end
164
+ builder = Nanoc::Int::ItemRepBuilder.new(
165
+ site, rules_collection, rule_memory_calculator, @reps)
166
+ builder.run
261
167
  end
262
168
 
263
169
  # @param [Nanoc::Int::ItemRep] rep The item representation for which the
@@ -274,87 +180,41 @@ module Nanoc::Int
274
180
  content_or_filename_assigns = { content: rep.snapshot_contents[:last].string }
275
181
  end
276
182
 
183
+ view_context = create_view_context
184
+
277
185
  # TODO: Do not expose @site (necessary for captures store though…)
278
186
  content_or_filename_assigns.merge(
279
- item: Nanoc::ItemView.new(rep.item),
280
- rep: Nanoc::ItemRepView.new(rep),
281
- item_rep: Nanoc::ItemRepView.new(rep),
282
- items: Nanoc::ItemCollectionView.new(site.items),
283
- layouts: Nanoc::LayoutCollectionView.new(site.layouts),
284
- config: Nanoc::ConfigView.new(site.config),
285
- site: Nanoc::SiteView.new(site),
187
+ item: Nanoc::ItemView.new(rep.item, view_context),
188
+ rep: Nanoc::ItemRepView.new(rep, view_context),
189
+ item_rep: Nanoc::ItemRepView.new(rep, view_context),
190
+ items: Nanoc::ItemCollectionView.new(site.items, view_context),
191
+ layouts: Nanoc::LayoutCollectionView.new(site.layouts, view_context),
192
+ config: Nanoc::ConfigView.new(site.config, view_context),
193
+ site: Nanoc::SiteView.new(site, view_context),
286
194
  )
287
195
  end
288
196
 
289
- # @return [Nanoc::Int::OutdatednessChecker] The outdatedness checker
290
- def outdatedness_checker
291
- Nanoc::Int::OutdatednessChecker.new(
292
- site: @site,
293
- checksum_store: checksum_store,
294
- dependency_tracker: dependency_tracker,
295
- )
197
+ def create_view_context
198
+ Nanoc::ViewContext.new(reps: @reps, items: @site.items)
296
199
  end
297
- memoize :outdatedness_checker
298
200
 
299
201
  private
300
202
 
301
- # @return [Array<Nanoc::Int::Item>] The site’s items
302
- def items
303
- @site.items
304
- end
305
- memoize :items
306
-
307
- # @return [Array<Nanoc::Int::ItemRep>] The site’s item representations
308
- def reps
309
- items.map(&:reps).flatten
310
- end
311
- memoize :reps
312
-
313
- # @return [Array<Nanoc::Int::Layout>] The site’s layouts
314
- def layouts
315
- @site.layouts
316
- end
317
- memoize :layouts
318
-
319
- # Compiles the given representations.
320
- #
321
- # @param [Array] reps The item representations to compile.
322
- #
323
- # @return [void]
324
- def compile_reps(reps)
325
- content_dependency_graph = Nanoc::Int::DirectedGraph.new(reps)
326
-
203
+ def compile_reps
327
204
  # Listen to processing start/stop
328
205
  Nanoc::Int::NotificationCenter.on(:processing_started, self) { |obj| @stack.push(obj) }
329
- Nanoc::Int::NotificationCenter.on(:processing_ended, self) { |_obj| @stack.pop }
206
+ Nanoc::Int::NotificationCenter.on(:processing_ended, self) { |_obj| @stack.pop }
330
207
 
331
208
  # Assign snapshots
332
- reps.each do |rep|
333
- rep.snapshot_defs = rules_collection.snapshots_defs_for(rep)
209
+ @reps.each do |rep|
210
+ rep.snapshot_defs = rule_memory_calculator.snapshots_defs_for(rep)
334
211
  end
335
212
 
336
- # Attempt to compile all active reps
337
- loop do
338
- # Find rep to compile
339
- break if content_dependency_graph.roots.empty?
340
- rep = content_dependency_graph.roots.each { |e| break e }
213
+ # Find item reps to compile and compile them
214
+ selector = Nanoc::Int::ItemRepSelector.new(@reps)
215
+ selector.each do |rep|
341
216
  @stack = []
342
-
343
- begin
344
- compile_rep(rep)
345
- content_dependency_graph.delete_vertex(rep)
346
- rescue Nanoc::Int::Errors::UnmetDependency => e
347
- other_rep = e.rep.unwrap rescue e.rep
348
- content_dependency_graph.add_edge(other_rep, rep)
349
- unless content_dependency_graph.vertices.include?(other_rep)
350
- content_dependency_graph.add_vertex(other_rep)
351
- end
352
- end
353
- end
354
-
355
- # Check whether everything was compiled
356
- unless content_dependency_graph.vertices.empty?
357
- raise Nanoc::Int::Errors::RecursiveCompilation.new(content_dependency_graph.vertices)
217
+ compile_rep(rep)
358
218
  end
359
219
  ensure
360
220
  Nanoc::Int::NotificationCenter.remove(:processing_started, self)
@@ -371,26 +231,15 @@ module Nanoc::Int
371
231
  #
372
232
  # @return [void]
373
233
  def compile_rep(rep)
374
- executor = Nanoc::Int::Executor.new(self)
375
-
376
234
  Nanoc::Int::NotificationCenter.post(:compilation_started, rep)
377
235
  Nanoc::Int::NotificationCenter.post(:processing_started, rep)
378
236
  Nanoc::Int::NotificationCenter.post(:visit_started, rep.item)
379
237
 
380
- # Calculate rule memory if we haven’t yet done do
381
- rules_collection.new_rule_memory_for_rep(rep)
382
-
383
- if !rep.item.forced_outdated? && !outdatedness_checker.outdated?(rep) && compiled_content_cache[rep]
384
- # Reuse content
238
+ if can_reuse_content_for_rep?(rep)
385
239
  Nanoc::Int::NotificationCenter.post(:cached_content_used, rep)
386
240
  rep.snapshot_contents = compiled_content_cache[rep]
387
241
  else
388
- # Recalculate content
389
- executor.snapshot(rep, :raw)
390
- executor.snapshot(rep, :pre, final: false)
391
- rules_collection.compilation_rule_for(rep).apply_to(rep, executor: executor, compiler: self)
392
- executor.snapshot(rep, :post) if rep.has_snapshot?(:post)
393
- executor.snapshot(rep, :last)
242
+ recalculate_content_for_rep(rep)
394
243
  end
395
244
 
396
245
  rep.compiled = true
@@ -406,53 +255,33 @@ module Nanoc::Int
406
255
  Nanoc::Int::NotificationCenter.post(:visit_ended, rep.item)
407
256
  end
408
257
 
409
- # Clears the list of dependencies for items that will be recompiled.
410
- #
411
- # @param [Array<Nanoc::Int::Item>] items The list of items for which to forget
412
- # the dependencies
413
- #
414
- # @return [void]
415
- def forget_dependencies_if_outdated(items)
416
- items.each do |i|
417
- if i.reps.any? { |r| outdatedness_checker.outdated?(r) }
418
- dependency_tracker.forget_dependencies_for(i)
419
- end
420
- end
258
+ # @return [Boolean]
259
+ def can_reuse_content_for_rep?(rep)
260
+ !rep.item.forced_outdated? && !outdatedness_checker.outdated?(rep) && compiled_content_cache[rep]
421
261
  end
422
262
 
423
- # Returns a preprocessor context, creating one if none exists yet.
424
- def preprocessor_context
425
- Nanoc::Int::Context.new(
426
- config: Nanoc::MutableConfigView.new(@site.config),
427
- items: Nanoc::MutableItemCollectionView.new(@site.items),
428
- layouts: Nanoc::MutableLayoutCollectionView.new(@site.layouts),
429
- )
430
- end
431
- memoize :preprocessor_context
432
-
433
- # @return [Nanoc:Int::CompiledContentCache] The compiled content cache
434
- def compiled_content_cache
435
- Nanoc::Int::CompiledContentCache.new
436
- end
437
- memoize :compiled_content_cache
438
-
439
- # @return [ChecksumStore] The checksum store
440
- def checksum_store
441
- Nanoc::Int::ChecksumStore.new(site: @site)
442
- end
443
- memoize :checksum_store
263
+ # @return [void]
264
+ def recalculate_content_for_rep(rep)
265
+ executor = Nanoc::Int::Executor.new(self)
444
266
 
445
- # @return [RuleMemoryStore] The rule memory store
446
- def rule_memory_store
447
- Nanoc::Int::RuleMemoryStore.new(site: @site)
267
+ executor.snapshot(rep, :raw)
268
+ executor.snapshot(rep, :pre, final: false)
269
+ rules_collection.compilation_rule_for(rep)
270
+ .apply_to(rep, executor: executor, site: @site, view_context: create_view_context)
271
+ executor.snapshot(rep, :post) if rep.has_snapshot?(:post)
272
+ executor.snapshot(rep, :last)
448
273
  end
449
- memoize :rule_memory_store
450
274
 
451
- # @return [RuleMemoryCalculator] The rule memory calculator
452
- def rule_memory_calculator
453
- Nanoc::Int::RuleMemoryCalculator.new(rules_collection: rules_collection)
275
+ # Clears the list of dependencies for items that will be recompiled.
276
+ #
277
+ # @return [void]
278
+ def forget_dependencies_if_outdated
279
+ @site.items.each do |i|
280
+ if @reps[i].any? { |r| outdatedness_checker.outdated?(r) }
281
+ @dependency_store.forget_dependencies_for(i)
282
+ end
283
+ end
454
284
  end
455
- memoize :rule_memory_calculator
456
285
 
457
286
  # Returns all stores that can load/store data that can be used for
458
287
  # compilation.
@@ -460,7 +289,7 @@ module Nanoc::Int
460
289
  [
461
290
  checksum_store,
462
291
  compiled_content_cache,
463
- dependency_tracker,
292
+ @dependency_store,
464
293
  rule_memory_store,
465
294
  ]
466
295
  end