lib/nanoc/base/result_data/item_rep.rb in nanoc-4.0.0b3 vs lib/nanoc/base/result_data/item_rep.rb in nanoc-4.0.0b4
- old
+ new
@@ -8,14 +8,11 @@
class ItemRep
# Contains all private methods. Mixed into {Nanoc::Int::ItemRep}.
#
# @api private
module Private
- # @return [Hash] A hash containing the assigns that will be used in the
- # next filter or layout operation. The keys (symbols) will be made
- # available during the next operation.
- attr_accessor :assigns
+ attr_accessor :content_snapshots
# @return [Boolean] true if this representation has already been
# compiled during the current or last compilation session; false
# otherwise
#
@@ -36,110 +33,29 @@
# values with the path.
#
# @api private
attr_accessor :paths
- # @return [Hash<Symbol,String>] A hash containing the paths to the
- # temporary _files_ that filters write binary content to. This is only
- # used when the item representation is binary. The keys correspond
- # with the snapshot names, and the values with the filename. When
- # writing the item representation, the file corresponding with the
- # requested snapshot (usually `:last`) will be copied from
- # `filenames[snapshot]` to `raw_paths[snapshot]`.
- #
- # @api private
- attr_reader :temporary_filenames
-
- # @return [Hash<Symbol,String>] A hash containing the content at all
- # snapshots. The keys correspond with the snapshot names, and the
- # values with the content.
- #
- # @api private
- attr_accessor :content
-
- # Writes the item rep's compiled content to the rep's output file.
- #
- # This method will send two notifications: one before writing the item
- # representation, and one after. These notifications can be used for
- # generating diffs, for example.
- #
- # @api private
- #
- # @param [Symbol, nil] snapshot The name of the snapshot to write.
- #
- # @return [void]
- def write(snapshot = :last)
- # Get raw path
- raw_path = self.raw_path(snapshot: snapshot)
- return if raw_path.nil?
-
- # Create parent directory
- FileUtils.mkdir_p(File.dirname(raw_path))
-
- # Check if file will be created
- is_created = !File.file?(raw_path)
-
- # Notify
- Nanoc::Int::NotificationCenter.post(:will_write_rep, self, snapshot)
-
- if self.binary?
- temp_path = temporary_filenames[:last]
- else
- temp_path = temp_filename
- File.open(temp_path, 'w') { |io| io.write(@content[:last]) }
- end
-
- # Check whether content was modified
- is_modified = is_created || !FileUtils.identical?(raw_path, temp_path)
-
- # Write
- FileUtils.cp(temp_path, raw_path) if is_modified
-
- # Notify
- Nanoc::Int::NotificationCenter.post(:rep_written, self, raw_path, is_created, is_modified)
- end
-
- TMP_TEXT_ITEMS_DIR = 'text_items'
-
- def temp_filename
- Nanoc::Int::TempFilenameFactory.instance.create(TMP_TEXT_ITEMS_DIR)
- end
-
# Resets the compilation progress for this item representation. This is
# necessary when an unmet dependency is detected during compilation.
#
# @api private
#
# @return [void]
def forget_progress
initialize_content
end
-
- # Returns the type of this object. Will always return `:item_rep`,
- # because this is an item rep. For layouts, this method returns
- # `:layout`.
- #
- # @api private
- #
- # @return [Symbol] :item_rep
- def type
- :item_rep
- end
end
include Private
# @return [Nanoc::Int::Item] The item to which this rep belongs
attr_reader :item
# @return [Symbol] The representation's unique name
attr_reader :name
- # @return [Boolean] true if this rep is currently binary; false otherwise
- attr_reader :binary
- alias_method :binary?, :binary
-
# @return [Array] A list of snapshots, represented as arrays where the
# first element is the snapshot name (a Symbol) and the last element is
# a Boolean indicating whether the snapshot is final or not
attr_accessor :snapshots
@@ -152,24 +68,24 @@
def initialize(item, name)
# Set primary attributes
@item = item
@name = name
- # Set binary
- @binary = @item.binary?
-
# Set default attributes
@raw_paths = {}
@paths = {}
- @assigns = {}
@snapshots = []
initialize_content
# Reset flags
@compiled = false
end
+ def binary?
+ @content_snapshots[:last].binary?
+ end
+
# Returns the compiled content from a given snapshot.
#
# @option params [String] :snapshot The name of the snapshot from which to
# fetch the compiled content. By default, the returned compiled content
# will be the content compiled right before the first layout call (if
@@ -177,20 +93,16 @@
#
# @return [String] The compiled content at the given snapshot (or the
# default snapshot if no snapshot is specified)
def compiled_content(params = {})
# Make sure we're not binary
- if item.binary?
+ if binary?
raise Nanoc::Int::Errors::CannotGetCompiledContentOfBinaryItem.new(self)
end
- # Notify
- Nanoc::Int::NotificationCenter.post(:visit_started, item)
- Nanoc::Int::NotificationCenter.post(:visit_ended, item)
-
# Get name of last pre-layout snapshot
- snapshot_name = params.fetch(:snapshot) { @content[:pre] ? :pre : :last }
+ snapshot_name = params.fetch(:snapshot) { @content_snapshots[:pre] ? :pre : :last }
is_moving = [:pre, :post, :last].include?(snapshot_name)
# Check existance of snapshot
snapshot = snapshots.find { |s| s.first == snapshot_name }
if !is_moving && (snapshot.nil? || snapshot[-1] == false)
@@ -203,26 +115,26 @@
when :post, :last
true
when :pre
snapshot.nil? || !snapshot[-1]
end
- is_usable_snapshot = @content[snapshot_name] && (self.compiled? || !is_still_moving)
+ is_usable_snapshot = @content_snapshots[snapshot_name] && (self.compiled? || !is_still_moving)
unless is_usable_snapshot
raise Nanoc::Int::Errors::UnmetDependency.new(self)
end
- @content[snapshot_name]
+ @content_snapshots[snapshot_name].string
end
# Checks whether content exists at a given snapshot.
#
# @return [Boolean] True if content exists for the snapshot with the
# given name, false otherwise
#
# @since 3.2.0
def snapshot?(snapshot_name)
- !@content[snapshot_name].nil?
+ !@content_snapshots[snapshot_name].nil?
end
alias_method :has_snapshot?, :snapshot?
# Returns the item rep’s raw path. It includes the path to the output
# directory and the full filename.
@@ -230,13 +142,10 @@
# @option params [Symbol] :snapshot (:last) The snapshot for which the
# path should be returned
#
# @return [String] The item rep’s path
def raw_path(params = {})
- Nanoc::Int::NotificationCenter.post(:visit_started, item)
- Nanoc::Int::NotificationCenter.post(:visit_ended, item)
-
snapshot_name = params[:snapshot] || :last
@raw_paths[snapshot_name]
end
# Returns the item rep’s path, as used when being linked to. It starts
@@ -247,204 +156,30 @@
# @option params [Symbol] :snapshot (:last) The snapshot for which the
# path should be returned
#
# @return [String] The item rep’s path
def path(params = {})
- Nanoc::Int::NotificationCenter.post(:visit_started, item)
- Nanoc::Int::NotificationCenter.post(:visit_ended, item)
-
snapshot_name = params[:snapshot] || :last
@paths[snapshot_name]
end
- # Runs the item content through the given filter with the given arguments.
- # This method will replace the content of the `:last` snapshot with the
- # filtered content of the last snapshot.
- #
- # This method is supposed to be called only in a compilation rule block
- # (see {Nanoc::Int::CompilerDSL#compile}).
- #
- # @see Nanoc::Int::ItemRepProxy#filter
- #
- # @param [Symbol] filter_name The name of the filter to run the item
- # representations' content through
- #
- # @param [Hash] filter_args The filter arguments that should be passed to
- # the filter's #run method
- #
- # @return [void]
- def filter(filter_name, filter_args = {})
- # Get filter class
- klass = filter_named(filter_name)
- raise Nanoc::Int::Errors::UnknownFilter.new(filter_name) if klass.nil?
-
- # Check whether filter can be applied
- if klass.from_binary? && !self.binary?
- raise Nanoc::Int::Errors::CannotUseBinaryFilter.new(self, klass)
- elsif !klass.from_binary? && self.binary?
- raise Nanoc::Int::Errors::CannotUseTextualFilter.new(self, klass)
- end
-
- begin
- # Notify start
- Nanoc::Int::NotificationCenter.post(:filtering_started, self, filter_name)
-
- # Create filter
- filter = klass.new(assigns)
-
- # Run filter
- source = self.binary? ? temporary_filenames[:last] : @content[:last]
- result = filter.setup_and_run(source, filter_args)
- if klass.to_binary?
- temporary_filenames[:last] = filter.output_filename
- else
- @content[:last] = result
- @content[:last].freeze
- end
- @binary = klass.to_binary?
-
- # Check whether file was written
- if self.binary? && !File.file?(filter.output_filename)
- raise "The #{filter_name.inspect} filter did not write anything to the required output file, #{filter.output_filename}."
- end
-
- # Create snapshot
- snapshot(@content[:post] ? :post : :pre, final: false) unless self.binary?
- ensure
- # Notify end
- Nanoc::Int::NotificationCenter.post(:filtering_ended, self, filter_name)
- end
- end
-
- # Lays out the item using the given layout. This method will replace the
- # content of the `:last` snapshot with the laid out content of the last
- # snapshot.
- #
- # This method is supposed to be called only in a compilation rule block
- # (see {Nanoc::Int::CompilerDSL#compile}).
- #
- # @see Nanoc::Int::ItemRepProxy#layout
- #
- # @param [Nanoc::Int::Layout] layout The layout to use
- #
- # @param [Symbol] filter_name The name of the filter to layout the item
- # representations' content with
- #
- # @param [Hash] filter_args The filter arguments that should be passed to
- # the filter's #run method
- #
- # @return [void]
- def layout(layout, filter_name, filter_args)
- # Check whether item can be laid out
- raise Nanoc::Int::Errors::CannotLayoutBinaryItem.new(self) if self.binary?
-
- # Create "pre" snapshot
- if @content[:post].nil?
- snapshot(:pre, final: true)
- end
-
- # Create filter
- klass = filter_named(filter_name)
- raise Nanoc::Int::Errors::UnknownFilter.new(filter_name) if klass.nil?
- filter = klass.new(assigns.merge({ layout: layout }))
-
- # Visit
- Nanoc::Int::NotificationCenter.post(:visit_started, layout)
- Nanoc::Int::NotificationCenter.post(:visit_ended, layout)
-
- begin
- # Notify start
- Nanoc::Int::NotificationCenter.post(:processing_started, layout)
- Nanoc::Int::NotificationCenter.post(:filtering_started, self, filter_name)
-
- # Layout
- @content[:last] = filter.setup_and_run(layout.raw_content, filter_args)
-
- # Create "post" snapshot
- snapshot(:post, final: false)
- ensure
- # Notify end
- Nanoc::Int::NotificationCenter.post(:filtering_ended, self, filter_name)
- Nanoc::Int::NotificationCenter.post(:processing_ended, layout)
- end
- end
-
- # Creates a snapshot of the current compiled item content.
- #
- # @param [Symbol] snapshot_name The name of the snapshot to create
- #
- # @option params [Boolean] :final (true) True if this is the final time
- # the snapshot will be updated; false if it is a non-final moving
- # snapshot (such as `:pre`, `:post` or `:last`)
- #
- # @return [void]
- def snapshot(snapshot_name, params = {})
- is_final = params.fetch(:final, true)
-
- unless self.binary?
- @content[snapshot_name] = @content[:last]
- end
-
- if snapshot_name == :pre && is_final
- snapshots << [:pre, true]
- end
-
- write(snapshot_name) if is_final
- end
-
- # Returns a recording proxy that is used for determining whether the
- # compilation has changed, and thus whether the item rep needs to be
- # recompiled.
- #
- # @api private
- #
- # @return [Nanoc::Int::ItemRepRecorderProxy] The recording proxy
- def to_recording_proxy
- Nanoc::Int::ItemRepRecorderProxy.new(self)
- end
-
- # Returns false because this item is not yet a proxy, and therefore does
- # need to be wrapped in a proxy during compilation.
- #
- # @api private
- #
- # @return [false]
- #
- # @see Nanoc::Int::ItemRepRecorderProxy#proxy?
- # @see Nanoc::Int::ItemRepProxy#proxy?
- def proxy?
- false
- end
- alias_method :is_proxy?, :proxy?
-
# Returns an object that can be used for uniquely identifying objects.
#
# @api private
#
# @return [Object] An unique reference to this object
def reference
- [type, item.identifier, name]
+ [:item_rep, item.identifier, name]
end
def inspect
"<#{self.class} name=\"#{name}\" binary=#{self.binary?} raw_path=\"#{raw_path}\" item.identifier=\"#{item.identifier}\">"
end
private
def initialize_content
- # Initialize content and filenames
- if self.binary?
- @temporary_filenames = { last: @item.raw_filename }
- @content = {}
- else
- @content = { last: @item.raw_content }
- @content[:last].freeze
- @temporary_filenames = {}
- end
- end
-
- def filter_named(name)
- Nanoc::Filter.named(name)
+ # FIXME: Where is :raw?
+ @content_snapshots = { last: @item.content }
end
end
end