nanoc 4.0.0b3 → 4.0.0b4

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +4 -2
  4. data/NEWS.md +10 -0
  5. data/TODO.md +15 -0
  6. data/lib/nanoc/base.rb +4 -27
  7. data/lib/nanoc/base/checksummer.rb +69 -19
  8. data/lib/nanoc/base/compilation/compiler.rb +14 -12
  9. data/lib/nanoc/base/compilation/compiler_dsl.rb +2 -0
  10. data/lib/nanoc/base/compilation/filter.rb +4 -2
  11. data/lib/nanoc/base/compilation/outdatedness_checker.rb +7 -7
  12. data/lib/nanoc/base/compilation/rule.rb +5 -6
  13. data/lib/nanoc/base/compilation/rule_context.rb +16 -34
  14. data/lib/nanoc/base/compilation/rule_memory_calculator.rb +3 -3
  15. data/lib/nanoc/base/compilation/rules_collection.rb +4 -10
  16. data/lib/nanoc/base/context.rb +2 -0
  17. data/lib/nanoc/base/core_ext/array.rb +0 -10
  18. data/lib/nanoc/base/core_ext/hash.rb +0 -10
  19. data/lib/nanoc/base/core_ext/pathname.rb +0 -9
  20. data/lib/nanoc/base/core_ext/string.rb +0 -10
  21. data/lib/nanoc/base/entities.rb +5 -0
  22. data/lib/nanoc/base/entities/content.rb +86 -0
  23. data/lib/nanoc/base/entities/document.rb +56 -0
  24. data/lib/nanoc/base/{source_data → entities}/identifier.rb +12 -1
  25. data/lib/nanoc/base/entities/layout.rb +8 -0
  26. data/lib/nanoc/base/{pattern.rb → entities/pattern.rb} +0 -0
  27. data/lib/nanoc/base/errors.rb +2 -1
  28. data/lib/nanoc/base/result_data/item_rep.rb +13 -278
  29. data/lib/nanoc/base/services.rb +5 -0
  30. data/lib/nanoc/base/services/executor.rb +141 -0
  31. data/lib/nanoc/base/services/item_rep_writer.rb +40 -0
  32. data/lib/nanoc/base/{notification_center.rb → services/notification_center.rb} +0 -0
  33. data/lib/nanoc/base/services/recording_executor.rb +41 -0
  34. data/lib/nanoc/base/{temp_filename_factory.rb → services/temp_filename_factory.rb} +0 -0
  35. data/lib/nanoc/base/source_data/code_snippet.rb +0 -6
  36. data/lib/nanoc/base/source_data/data_source.rb +4 -3
  37. data/lib/nanoc/base/source_data/item.rb +23 -213
  38. data/lib/nanoc/base/source_data/site.rb +0 -1
  39. data/lib/nanoc/base/views.rb +18 -0
  40. data/lib/nanoc/base/views/config.rb +1 -1
  41. data/lib/nanoc/base/views/item.rb +8 -73
  42. data/lib/nanoc/base/views/item_rep.rb +9 -0
  43. data/lib/nanoc/base/views/item_rep_collection.rb +17 -0
  44. data/lib/nanoc/base/views/layout.rb +1 -40
  45. data/lib/nanoc/base/views/mixins/document.rb +76 -0
  46. data/lib/nanoc/base/views/mixins/mutable_document.rb +22 -0
  47. data/lib/nanoc/base/views/mutable_identifiable_collection.rb +1 -1
  48. data/lib/nanoc/base/views/mutable_item.rb +1 -18
  49. data/lib/nanoc/base/views/mutable_item_collection.rb +6 -2
  50. data/lib/nanoc/base/views/mutable_layout.rb +1 -8
  51. data/lib/nanoc/cli/commands/compile.rb +1 -2
  52. data/lib/nanoc/cli/commands/create-site.rb +5 -5
  53. data/lib/nanoc/cli/commands/show-data.rb +11 -1
  54. data/lib/nanoc/data_sources/filesystem.rb +17 -10
  55. data/lib/nanoc/helpers/capturing.rb +1 -2
  56. data/lib/nanoc/helpers/filtering.rb +13 -1
  57. data/lib/nanoc/helpers/rendering.rb +4 -2
  58. data/lib/nanoc/version.rb +1 -1
  59. data/test/base/core_ext/array_spec.rb +0 -7
  60. data/test/base/core_ext/hash_spec.rb +0 -13
  61. data/test/base/core_ext/pathname_spec.rb +0 -33
  62. data/test/base/core_ext/string_spec.rb +0 -10
  63. data/test/base/test_compiler_dsl.rb +3 -3
  64. data/test/base/test_data_source.rb +2 -2
  65. data/test/base/test_item.rb +5 -129
  66. data/test/base/test_item_rep.rb +26 -558
  67. data/test/base/test_layout.rb +2 -26
  68. data/test/base/test_rule.rb +3 -3
  69. data/test/base/test_rule_context.rb +34 -15
  70. data/test/data_sources/test_filesystem.rb +2 -2
  71. data/test/data_sources/test_filesystem_unified.rb +39 -33
  72. data/test/extra/checking/checks/test_html.rb +0 -1
  73. data/test/extra/checking/checks/test_mixed_content.rb +3 -3
  74. data/test/extra/deployers/test_fog.rb +24 -24
  75. data/test/filters/test_less.rb +4 -4
  76. data/test/filters/test_sass.rb +10 -5
  77. data/test/filters/test_xsl.rb +6 -0
  78. data/test/helpers/test_capturing.rb +0 -1
  79. data/test/helpers/test_filtering.rb +5 -19
  80. data/test/helpers/test_tagging.rb +6 -6
  81. metadata +18 -11
  82. data/lib/nanoc/base/compilation/item_rep_proxy.rb +0 -109
  83. data/lib/nanoc/base/compilation/item_rep_recorder_proxy.rb +0 -97
  84. data/lib/nanoc/base/source_data/layout.rb +0 -111
  85. data/test/base/checksummer_spec.rb +0 -256
  86. data/test/base/test_item_rep_recorder_proxy.rb +0 -17
@@ -3,41 +3,23 @@ module Nanoc::Int
3
3
  # It provides access to the item representation that is being compiled or
4
4
  # routed.
5
5
  #
6
- # The following variables will be available in this rules context:
7
- #
8
- # * `rep` ({Nanoc::Int::ItemRep}) - The current item rep
9
- # * `item` ({Nanoc::Int::Item}) - The current item
10
- # * `site` ({Nanoc::Int::Site}) - The site
11
- # * `config` ({Hash}) - The site configuration
12
- # * `items` ({Array}<{Nanoc::Int::Item}>) - A list of all items
13
- # * `layouts` ({Array}<{Nanoc::Int::Layout}>) - A list of all layouts
14
- #
15
6
  # @api private
16
7
  class RuleContext < Nanoc::Int::Context
17
- # @option params [Nanoc::Int::ItemRep] :rep The item representation that will
18
- # be processed in this rule context
19
- #
20
- # @option params [Nanoc::Int::Compiler] :compiler The compiler that is being
21
- # used to compile the site
22
- #
23
- # @raise [ArgumentError] if the `:rep` or the `:compiler` option is
24
- # missing
8
+ # @option params [Nanoc::Int::ItemRep] :rep
9
+ # @option params [Nanoc::Int::Compiler] :compiler
25
10
  def initialize(params = {})
26
- rep = params.fetch(:rep) do
27
- raise ArgumentError, 'Required :rep option is missing'
28
- end
29
- compiler = params.fetch(:compiler) do
30
- raise ArgumentError, 'Required :compiler option is missing'
31
- end
11
+ rep = params.fetch(:rep)
12
+ compiler = params.fetch(:compiler)
13
+ @_executor = params.fetch(:executor)
32
14
 
33
15
  super({
34
- rep: rep,
35
- item_rep: rep,
36
- item: rep.item,
37
- site: compiler.site,
38
- config: compiler.site.config,
39
- items: compiler.site.items,
40
- layouts: compiler.site.layouts
16
+ item: Nanoc::ItemView.new(rep.item),
17
+ rep: Nanoc::ItemRepView.new(rep),
18
+ item_rep: Nanoc::ItemRepView.new(rep),
19
+ items: Nanoc::ItemCollectionView.new(compiler.site.items),
20
+ layouts: Nanoc::LayoutCollectionView.new(compiler.site.layouts),
21
+ config: Nanoc::ConfigView.new(compiler.site.config),
22
+ site: Nanoc::SiteView.new(compiler.site),
41
23
  })
42
24
  end
43
25
 
@@ -54,7 +36,7 @@ module Nanoc::Int
54
36
  #
55
37
  # @return [void]
56
38
  def filter(filter_name, filter_args = {})
57
- rep.filter(filter_name, filter_args)
39
+ @_executor.filter(rep.unwrap, filter_name, filter_args)
58
40
  end
59
41
 
60
42
  # Layouts the current representation (calls {Nanoc::Int::ItemRep#layout} with
@@ -66,8 +48,8 @@ module Nanoc::Int
66
48
  # should be laid out with
67
49
  #
68
50
  # @return [void]
69
- def layout(layout_identifier)
70
- rep.layout(layout_identifier)
51
+ def layout(layout_identifier, extra_filter_args = nil)
52
+ @_executor.layout(rep.unwrap, layout_identifier, extra_filter_args)
71
53
  end
72
54
 
73
55
  # Creates a snapshot of the current compiled item content. Calls
@@ -79,7 +61,7 @@ module Nanoc::Int
79
61
  #
80
62
  # @return [void]
81
63
  def snapshot(snapshot_name)
82
- rep.snapshot(snapshot_name)
64
+ @_executor.snapshot(rep.unwrap, snapshot_name)
83
65
  end
84
66
  end
85
67
  end
@@ -19,10 +19,10 @@ module Nanoc::Int
19
19
  # @return [Array] The caluclated rule memory for the given object
20
20
  def [](obj)
21
21
  result =
22
- case obj.type
23
- when :item_rep
22
+ case obj
23
+ when Nanoc::Int::ItemRep
24
24
  @rules_collection.new_rule_memory_for_rep(obj)
25
- when :layout
25
+ when Nanoc::Int::Layout
26
26
  @rules_collection.new_rule_memory_for_layout(obj)
27
27
  else
28
28
  raise "Do not know how to calculate the rule memory for #{obj.inspect}"
@@ -170,12 +170,6 @@ module Nanoc::Int
170
170
  :rules
171
171
  end
172
172
 
173
- # @return [String] The checksum for this object. If its contents change,
174
- # the checksum will change as well.
175
- def __nanoc_checksum
176
- Nanoc::Int::Checksummer.calc(self)
177
- end
178
-
179
173
  def inspect
180
174
  "<#{self.class}>"
181
175
  end
@@ -185,10 +179,10 @@ module Nanoc::Int
185
179
  #
186
180
  # @return [Array] The rule memory for the given item representation
187
181
  def new_rule_memory_for_rep(rep)
188
- recording_proxy = rep.to_recording_proxy
189
- compilation_rule_for(rep).apply_to(recording_proxy, compiler: @compiler)
190
- recording_proxy.rule_memory << [:write, rep.path]
191
- make_rule_memory_serializable(recording_proxy.rule_memory)
182
+ executor = Nanoc::Int::RecordingExecutor.new
183
+ compilation_rule_for(rep).apply_to(rep, executor: executor, compiler: @compiler)
184
+ executor.record_write(rep, rep.path)
185
+ make_rule_memory_serializable(executor.rule_memory)
192
186
  end
193
187
  memoize :new_rule_memory_for_rep
194
188
 
@@ -1,6 +1,8 @@
1
1
  module Nanoc::Int
2
2
  # Provides a context and a binding for use in filters such as the ERB and
3
3
  # Haml ones.
4
+ #
5
+ # @api private
4
6
  class Context
5
7
  # Creates a new context based off the contents of the hash.
6
8
  #
@@ -33,16 +33,6 @@ module Nanoc::ArrayExtensions
33
33
  end
34
34
  end
35
35
  end
36
-
37
- # Calculates the checksum for this array. Any change to this array will
38
- # result in a different checksum.
39
- #
40
- # @return [String] The checksum for this array
41
- #
42
- # @api private
43
- def __nanoc_checksum
44
- Nanoc::Int::Checksummer.calc(self)
45
- end
46
36
  end
47
37
 
48
38
  # @api private
@@ -35,16 +35,6 @@ module Nanoc::HashExtensions
35
35
  end
36
36
  end
37
37
  end
38
-
39
- # Calculates the checksum for this hash. Any change to this hash will result
40
- # in a different checksum.
41
- #
42
- # @return [String] The checksum for this hash
43
- #
44
- # @api private
45
- def __nanoc_checksum
46
- Nanoc::Int::Checksummer.calc(self)
47
- end
48
38
  end
49
39
 
50
40
  # @api private
@@ -1,14 +1,5 @@
1
1
  # @api private
2
2
  module Nanoc::PathnameExtensions
3
- # Calculates the checksum for the file referenced to by this pathname. Any
4
- # change to the file contents will result in a different checksum.
5
- #
6
- # @return [String] The checksum for this file
7
- #
8
- # @api private
9
- def __nanoc_checksum
10
- Nanoc::Int::Checksummer.calc(self)
11
- end
12
3
  end
13
4
 
14
5
  # @api private
@@ -6,16 +6,6 @@ module Nanoc::StringExtensions
6
6
  def __nanoc_cleaned_identifier
7
7
  "/#{self}/".gsub(/^\/+|\/+$/, '/')
8
8
  end
9
-
10
- # Calculates the checksum for this string. Any change to this string will
11
- # result in a different checksum.
12
- #
13
- # @return [String] The checksum for this string
14
- #
15
- # @api private
16
- def __nanoc_checksum
17
- Nanoc::Int::Checksummer.calc(self)
18
- end
19
9
  end
20
10
 
21
11
  # @api private
@@ -0,0 +1,5 @@
1
+ require_relative 'entities/content'
2
+ require_relative 'entities/document'
3
+ require_relative 'entities/identifier'
4
+ require_relative 'entities/layout'
5
+ require_relative 'entities/pattern'
@@ -0,0 +1,86 @@
1
+ module Nanoc
2
+ module Int
3
+ # Abstract content.
4
+ #
5
+ # The filename is the full filename on the default filesystem. It can be
6
+ # nil. It is used by filters such as Sass, which look up items on the
7
+ # filesystem.
8
+ #
9
+ # @abstract
10
+ #
11
+ # @api private
12
+ class Content
13
+ # @return [String, nil]
14
+ attr_reader :filename
15
+
16
+ # @param [String, nil] filename
17
+ def initialize(filename)
18
+ if filename && !filename.start_with?('/')
19
+ raise ArgumentError, 'Content filename is not absolute'
20
+ end
21
+
22
+ @filename = filename
23
+ end
24
+
25
+ def freeze
26
+ super
27
+ @filename.freeze
28
+ end
29
+
30
+ # @param [String] content The uncompiled item content (if it is textual
31
+ # content) or the path to the filename containing the content (if this
32
+ # is binary content).
33
+ #
34
+ # @option params [Boolean] :binary (false) Whether or not this item is
35
+ # binary
36
+ #
37
+ # @option params [String] :filename (nil) Absolute path to the file
38
+ # containing this content (if any)
39
+ def self.create(content, params = {})
40
+ if content.nil?
41
+ raise ArgumentError, 'Cannot create nil content'
42
+ elsif content.is_a?(Nanoc::Int::Content)
43
+ content
44
+ elsif params.fetch(:binary, false)
45
+ Nanoc::Int::BinaryContent.new(content)
46
+ else
47
+ Nanoc::Int::TextualContent.new(content, filename: params[:filename])
48
+ end
49
+ end
50
+
51
+ # @abstract
52
+ #
53
+ # @return [Boolean]
54
+ def binary?
55
+ raise NotImplementedError
56
+ end
57
+ end
58
+
59
+ # @api private
60
+ class TextualContent < Content
61
+ # @return [String]
62
+ attr_reader :string
63
+
64
+ def initialize(string, params = {})
65
+ super(params[:filename])
66
+ @string = string
67
+ end
68
+
69
+ def freeze
70
+ super
71
+ @string.freeze
72
+ end
73
+
74
+ def binary?
75
+ false
76
+ end
77
+ end
78
+
79
+ # @api private
80
+ class BinaryContent < Content
81
+ def binary?
82
+ true
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,56 @@
1
+ module Nanoc
2
+ module Int
3
+ # @api private
4
+ class Document
5
+ # @return [Nanoc::Int::Content]
6
+ attr_reader :content
7
+
8
+ # @return [Hash]
9
+ attr_reader :attributes
10
+
11
+ # @return [Nanoc::Identifier]
12
+ attr_accessor :identifier
13
+
14
+ # @param [String, Nanoc::Int::Content] content
15
+ #
16
+ # @param [Hash] attributes
17
+ #
18
+ # @param [String, Nanoc::Identifier] identifier
19
+ def initialize(content, attributes, identifier)
20
+ @content = Nanoc::Int::Content.create(content)
21
+ @attributes = attributes.__nanoc_symbolize_keys_recursively
22
+ @identifier = Nanoc::Identifier.from(identifier)
23
+ end
24
+
25
+ # @return [void]
26
+ def freeze
27
+ super
28
+ attributes.__nanoc_freeze_recursively
29
+ content.freeze
30
+ end
31
+
32
+ # @abstract
33
+ #
34
+ # @return Unique reference to this object
35
+ def reference
36
+ raise NotImplementedError
37
+ end
38
+
39
+ def inspect
40
+ "<#{self.class} identifier=\"#{identifier}\">"
41
+ end
42
+
43
+ def hash
44
+ self.class.hash ^ identifier.hash
45
+ end
46
+
47
+ def eql?(other)
48
+ self.class == other.class && identifier == other.identifier
49
+ end
50
+
51
+ def ==(other)
52
+ self.eql?(other)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -84,7 +84,7 @@ module Nanoc
84
84
  extname = File.extname(@string)
85
85
  string =
86
86
  if extname.size > 0
87
- @string[0..-extname.size-1]
87
+ @string[0..-extname.size - 1]
88
88
  else
89
89
  @string
90
90
  end
@@ -106,6 +106,17 @@ module Nanoc
106
106
  with_ext('')
107
107
  end
108
108
 
109
+ # @return [String] The extension, without a leading dot.
110
+ def ext
111
+ unless full?
112
+ raise Nanoc::Int::Errors::Generic,
113
+ 'Cannot use #ext on identifier that does not include the file extension'
114
+ end
115
+
116
+ s = File.extname(@string)
117
+ s && s[1..-1]
118
+ end
119
+
109
120
  def to_s
110
121
  @string
111
122
  end
@@ -0,0 +1,8 @@
1
+ module Nanoc::Int
2
+ # @api private
3
+ class Layout < ::Nanoc::Int::Document
4
+ def reference
5
+ [:layout, identifier]
6
+ end
7
+ end
8
+ end
File without changes
@@ -153,7 +153,8 @@ module Nanoc::Int
153
153
  #
154
154
  # @param [Symbol] snapshot The requested snapshot
155
155
  def initialize(item_rep, snapshot)
156
- @item_rep, @snapshot = item_rep, snapshot
156
+ @item_rep = item_rep
157
+ @snapshot = snapshot
157
158
  super("The “#{item_rep.inspect}” item rep does not have a snapshot “#{snapshot.inspect}”")
158
159
  end
159
160
  end
@@ -10,10 +10,7 @@ module Nanoc::Int
10
10
  #
11
11
  # @api private
12
12
  module Private
13
- # @return [Hash] A hash containing the assigns that will be used in the
14
- # next filter or layout operation. The keys (symbols) will be made
15
- # available during the next operation.
16
- attr_accessor :assigns
13
+ attr_accessor :content_snapshots
17
14
 
18
15
  # @return [Boolean] true if this representation has already been
19
16
  # compiled during the current or last compilation session; false
@@ -38,72 +35,6 @@ module Nanoc::Int
38
35
  # @api private
39
36
  attr_accessor :paths
40
37
 
41
- # @return [Hash<Symbol,String>] A hash containing the paths to the
42
- # temporary _files_ that filters write binary content to. This is only
43
- # used when the item representation is binary. The keys correspond
44
- # with the snapshot names, and the values with the filename. When
45
- # writing the item representation, the file corresponding with the
46
- # requested snapshot (usually `:last`) will be copied from
47
- # `filenames[snapshot]` to `raw_paths[snapshot]`.
48
- #
49
- # @api private
50
- attr_reader :temporary_filenames
51
-
52
- # @return [Hash<Symbol,String>] A hash containing the content at all
53
- # snapshots. The keys correspond with the snapshot names, and the
54
- # values with the content.
55
- #
56
- # @api private
57
- attr_accessor :content
58
-
59
- # Writes the item rep's compiled content to the rep's output file.
60
- #
61
- # This method will send two notifications: one before writing the item
62
- # representation, and one after. These notifications can be used for
63
- # generating diffs, for example.
64
- #
65
- # @api private
66
- #
67
- # @param [Symbol, nil] snapshot The name of the snapshot to write.
68
- #
69
- # @return [void]
70
- def write(snapshot = :last)
71
- # Get raw path
72
- raw_path = self.raw_path(snapshot: snapshot)
73
- return if raw_path.nil?
74
-
75
- # Create parent directory
76
- FileUtils.mkdir_p(File.dirname(raw_path))
77
-
78
- # Check if file will be created
79
- is_created = !File.file?(raw_path)
80
-
81
- # Notify
82
- Nanoc::Int::NotificationCenter.post(:will_write_rep, self, snapshot)
83
-
84
- if self.binary?
85
- temp_path = temporary_filenames[:last]
86
- else
87
- temp_path = temp_filename
88
- File.open(temp_path, 'w') { |io| io.write(@content[:last]) }
89
- end
90
-
91
- # Check whether content was modified
92
- is_modified = is_created || !FileUtils.identical?(raw_path, temp_path)
93
-
94
- # Write
95
- FileUtils.cp(temp_path, raw_path) if is_modified
96
-
97
- # Notify
98
- Nanoc::Int::NotificationCenter.post(:rep_written, self, raw_path, is_created, is_modified)
99
- end
100
-
101
- TMP_TEXT_ITEMS_DIR = 'text_items'
102
-
103
- def temp_filename
104
- Nanoc::Int::TempFilenameFactory.instance.create(TMP_TEXT_ITEMS_DIR)
105
- end
106
-
107
38
  # Resets the compilation progress for this item representation. This is
108
39
  # necessary when an unmet dependency is detected during compilation.
109
40
  #
@@ -113,17 +44,6 @@ module Nanoc::Int
113
44
  def forget_progress
114
45
  initialize_content
115
46
  end
116
-
117
- # Returns the type of this object. Will always return `:item_rep`,
118
- # because this is an item rep. For layouts, this method returns
119
- # `:layout`.
120
- #
121
- # @api private
122
- #
123
- # @return [Symbol] :item_rep
124
- def type
125
- :item_rep
126
- end
127
47
  end
128
48
 
129
49
  include Private
@@ -134,10 +54,6 @@ module Nanoc::Int
134
54
  # @return [Symbol] The representation's unique name
135
55
  attr_reader :name
136
56
 
137
- # @return [Boolean] true if this rep is currently binary; false otherwise
138
- attr_reader :binary
139
- alias_method :binary?, :binary
140
-
141
57
  # @return [Array] A list of snapshots, represented as arrays where the
142
58
  # first element is the snapshot name (a Symbol) and the last element is
143
59
  # a Boolean indicating whether the snapshot is final or not
@@ -154,13 +70,9 @@ module Nanoc::Int
154
70
  @item = item
155
71
  @name = name
156
72
 
157
- # Set binary
158
- @binary = @item.binary?
159
-
160
73
  # Set default attributes
161
74
  @raw_paths = {}
162
75
  @paths = {}
163
- @assigns = {}
164
76
  @snapshots = []
165
77
  initialize_content
166
78
 
@@ -168,6 +80,10 @@ module Nanoc::Int
168
80
  @compiled = false
169
81
  end
170
82
 
83
+ def binary?
84
+ @content_snapshots[:last].binary?
85
+ end
86
+
171
87
  # Returns the compiled content from a given snapshot.
172
88
  #
173
89
  # @option params [String] :snapshot The name of the snapshot from which to
@@ -179,16 +95,12 @@ module Nanoc::Int
179
95
  # default snapshot if no snapshot is specified)
180
96
  def compiled_content(params = {})
181
97
  # Make sure we're not binary
182
- if item.binary?
98
+ if binary?
183
99
  raise Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem.new(self)
184
100
  end
185
101
 
186
- # Notify
187
- Nanoc::Int::NotificationCenter.post(:visit_started, item)
188
- Nanoc::Int::NotificationCenter.post(:visit_ended, item)
189
-
190
102
  # Get name of last pre-layout snapshot
191
- snapshot_name = params.fetch(:snapshot) { @content[:pre] ? :pre : :last }
103
+ snapshot_name = params.fetch(:snapshot) { @content_snapshots[:pre] ? :pre : :last }
192
104
  is_moving = [:pre, :post, :last].include?(snapshot_name)
193
105
 
194
106
  # Check existance of snapshot
@@ -205,12 +117,12 @@ module Nanoc::Int
205
117
  when :pre
206
118
  snapshot.nil? || !snapshot[-1]
207
119
  end
208
- is_usable_snapshot = @content[snapshot_name] && (self.compiled? || !is_still_moving)
120
+ is_usable_snapshot = @content_snapshots[snapshot_name] && (self.compiled? || !is_still_moving)
209
121
  unless is_usable_snapshot
210
122
  raise Nanoc::Int::Errors::UnmetDependency.new(self)
211
123
  end
212
124
 
213
- @content[snapshot_name]
125
+ @content_snapshots[snapshot_name].string
214
126
  end
215
127
 
216
128
  # Checks whether content exists at a given snapshot.
@@ -220,7 +132,7 @@ module Nanoc::Int
220
132
  #
221
133
  # @since 3.2.0
222
134
  def snapshot?(snapshot_name)
223
- !@content[snapshot_name].nil?
135
+ !@content_snapshots[snapshot_name].nil?
224
136
  end
225
137
  alias_method :has_snapshot?, :snapshot?
226
138
 
@@ -232,9 +144,6 @@ module Nanoc::Int
232
144
  #
233
145
  # @return [String] The item rep’s path
234
146
  def raw_path(params = {})
235
- Nanoc::Int::NotificationCenter.post(:visit_started, item)
236
- Nanoc::Int::NotificationCenter.post(:visit_ended, item)
237
-
238
147
  snapshot_name = params[:snapshot] || :last
239
148
  @raw_paths[snapshot_name]
240
149
  end
@@ -249,180 +158,17 @@ module Nanoc::Int
249
158
  #
250
159
  # @return [String] The item rep’s path
251
160
  def path(params = {})
252
- Nanoc::Int::NotificationCenter.post(:visit_started, item)
253
- Nanoc::Int::NotificationCenter.post(:visit_ended, item)
254
-
255
161
  snapshot_name = params[:snapshot] || :last
256
162
  @paths[snapshot_name]
257
163
  end
258
164
 
259
- # Runs the item content through the given filter with the given arguments.
260
- # This method will replace the content of the `:last` snapshot with the
261
- # filtered content of the last snapshot.
262
- #
263
- # This method is supposed to be called only in a compilation rule block
264
- # (see {Nanoc::Int::CompilerDSL#compile}).
265
- #
266
- # @see Nanoc::Int::ItemRepProxy#filter
267
- #
268
- # @param [Symbol] filter_name The name of the filter to run the item
269
- # representations' content through
270
- #
271
- # @param [Hash] filter_args The filter arguments that should be passed to
272
- # the filter's #run method
273
- #
274
- # @return [void]
275
- def filter(filter_name, filter_args = {})
276
- # Get filter class
277
- klass = filter_named(filter_name)
278
- raise Nanoc::Int::Errors::UnknownFilter.new(filter_name) if klass.nil?
279
-
280
- # Check whether filter can be applied
281
- if klass.from_binary? && !self.binary?
282
- raise Nanoc::Int::Errors::CannotUseBinaryFilter.new(self, klass)
283
- elsif !klass.from_binary? && self.binary?
284
- raise Nanoc::Int::Errors::CannotUseTextualFilter.new(self, klass)
285
- end
286
-
287
- begin
288
- # Notify start
289
- Nanoc::Int::NotificationCenter.post(:filtering_started, self, filter_name)
290
-
291
- # Create filter
292
- filter = klass.new(assigns)
293
-
294
- # Run filter
295
- source = self.binary? ? temporary_filenames[:last] : @content[:last]
296
- result = filter.setup_and_run(source, filter_args)
297
- if klass.to_binary?
298
- temporary_filenames[:last] = filter.output_filename
299
- else
300
- @content[:last] = result
301
- @content[:last].freeze
302
- end
303
- @binary = klass.to_binary?
304
-
305
- # Check whether file was written
306
- if self.binary? && !File.file?(filter.output_filename)
307
- raise "The #{filter_name.inspect} filter did not write anything to the required output file, #{filter.output_filename}."
308
- end
309
-
310
- # Create snapshot
311
- snapshot(@content[:post] ? :post : :pre, final: false) unless self.binary?
312
- ensure
313
- # Notify end
314
- Nanoc::Int::NotificationCenter.post(:filtering_ended, self, filter_name)
315
- end
316
- end
317
-
318
- # Lays out the item using the given layout. This method will replace the
319
- # content of the `:last` snapshot with the laid out content of the last
320
- # snapshot.
321
- #
322
- # This method is supposed to be called only in a compilation rule block
323
- # (see {Nanoc::Int::CompilerDSL#compile}).
324
- #
325
- # @see Nanoc::Int::ItemRepProxy#layout
326
- #
327
- # @param [Nanoc::Int::Layout] layout The layout to use
328
- #
329
- # @param [Symbol] filter_name The name of the filter to layout the item
330
- # representations' content with
331
- #
332
- # @param [Hash] filter_args The filter arguments that should be passed to
333
- # the filter's #run method
334
- #
335
- # @return [void]
336
- def layout(layout, filter_name, filter_args)
337
- # Check whether item can be laid out
338
- raise Nanoc::Int::Errors::CannotLayoutBinaryItem.new(self) if self.binary?
339
-
340
- # Create "pre" snapshot
341
- if @content[:post].nil?
342
- snapshot(:pre, final: true)
343
- end
344
-
345
- # Create filter
346
- klass = filter_named(filter_name)
347
- raise Nanoc::Int::Errors::UnknownFilter.new(filter_name) if klass.nil?
348
- filter = klass.new(assigns.merge({ layout: layout }))
349
-
350
- # Visit
351
- Nanoc::Int::NotificationCenter.post(:visit_started, layout)
352
- Nanoc::Int::NotificationCenter.post(:visit_ended, layout)
353
-
354
- begin
355
- # Notify start
356
- Nanoc::Int::NotificationCenter.post(:processing_started, layout)
357
- Nanoc::Int::NotificationCenter.post(:filtering_started, self, filter_name)
358
-
359
- # Layout
360
- @content[:last] = filter.setup_and_run(layout.raw_content, filter_args)
361
-
362
- # Create "post" snapshot
363
- snapshot(:post, final: false)
364
- ensure
365
- # Notify end
366
- Nanoc::Int::NotificationCenter.post(:filtering_ended, self, filter_name)
367
- Nanoc::Int::NotificationCenter.post(:processing_ended, layout)
368
- end
369
- end
370
-
371
- # Creates a snapshot of the current compiled item content.
372
- #
373
- # @param [Symbol] snapshot_name The name of the snapshot to create
374
- #
375
- # @option params [Boolean] :final (true) True if this is the final time
376
- # the snapshot will be updated; false if it is a non-final moving
377
- # snapshot (such as `:pre`, `:post` or `:last`)
378
- #
379
- # @return [void]
380
- def snapshot(snapshot_name, params = {})
381
- is_final = params.fetch(:final, true)
382
-
383
- unless self.binary?
384
- @content[snapshot_name] = @content[:last]
385
- end
386
-
387
- if snapshot_name == :pre && is_final
388
- snapshots << [:pre, true]
389
- end
390
-
391
- write(snapshot_name) if is_final
392
- end
393
-
394
- # Returns a recording proxy that is used for determining whether the
395
- # compilation has changed, and thus whether the item rep needs to be
396
- # recompiled.
397
- #
398
- # @api private
399
- #
400
- # @return [Nanoc::Int::ItemRepRecorderProxy] The recording proxy
401
- def to_recording_proxy
402
- Nanoc::Int::ItemRepRecorderProxy.new(self)
403
- end
404
-
405
- # Returns false because this item is not yet a proxy, and therefore does
406
- # need to be wrapped in a proxy during compilation.
407
- #
408
- # @api private
409
- #
410
- # @return [false]
411
- #
412
- # @see Nanoc::Int::ItemRepRecorderProxy#proxy?
413
- # @see Nanoc::Int::ItemRepProxy#proxy?
414
- def proxy?
415
- false
416
- end
417
- alias_method :is_proxy?, :proxy?
418
-
419
165
  # Returns an object that can be used for uniquely identifying objects.
420
166
  #
421
167
  # @api private
422
168
  #
423
169
  # @return [Object] An unique reference to this object
424
170
  def reference
425
- [type, item.identifier, name]
171
+ [:item_rep, item.identifier, name]
426
172
  end
427
173
 
428
174
  def inspect
@@ -432,19 +178,8 @@ module Nanoc::Int
432
178
  private
433
179
 
434
180
  def initialize_content
435
- # Initialize content and filenames
436
- if self.binary?
437
- @temporary_filenames = { last: @item.raw_filename }
438
- @content = {}
439
- else
440
- @content = { last: @item.raw_content }
441
- @content[:last].freeze
442
- @temporary_filenames = {}
443
- end
444
- end
445
-
446
- def filter_named(name)
447
- Nanoc::Filter.named(name)
181
+ # FIXME: Where is :raw?
182
+ @content_snapshots = { last: @item.content }
448
183
  end
449
184
  end
450
185
  end