lib/nanoc/helpers/capturing.rb in nanoc-4.0.2 vs lib/nanoc/helpers/capturing.rb in nanoc-4.1.0a1

- old
+ new

@@ -38,10 +38,14 @@ def [](item, name) @store[item.identifier] ||= {} @store[item.identifier][name] end + + def reset_for(item) + @store[item.identifier] = {} + end end class ::Nanoc::Int::Site # @api private def captures_store @@ -53,20 +57,32 @@ require 'set' @captures_store_compiled_items ||= Set.new end end - # @overload content_for(name, &block) + # @overload content_for(name, params = {}, &block) # # Captures the content inside the block and stores it so that it can be # referenced later on. The same method, {#content_for}, is used for # getting the captured content as well as setting it. When capturing, # the content of the block itself will not be outputted. # + # By default, capturing content with the same name will raise an error if the newly captured + # content differs from the previously captured content. This behavior can be changed by + # providing a different `:existing` option to this method: + # + # * `:error`: When content already exists and is not identical, raise an error. + # + # * `:overwrite`: Overwrite the previously captured content with the newly captured content. + # + # * `:append`: Append the newly captured content to the previously captured content. + # # @param [Symbol, String] name The base name of the attribute into which # the content should be stored # + # @option params [Symbol] existing Can be either `:error`, `:overwrite`, or `:append` + # # @return [void] # # @overload content_for(item, name) # # Fetches the capture with the given name from the given item and @@ -78,42 +94,69 @@ # # @return [String] The stored captured content def content_for(*args, &block) if block_given? # Set content # Get args - if args.size != 1 - raise ArgumentError, 'expected 1 argument (the name ' \ - "of the capture) but got #{args.size} instead" + case args.size + when 1 + name = args[0] + params = {} + when 2 + name = args[0] + params = args[1] + else + raise ArgumentError, 'expected 1 or 2 argument (the name ' \ + "of the capture, and optionally params) but got #{args.size} instead" end name = args[0] + existing_behavior = params.fetch(:existing, :error) - # Capture and store + # Capture content = capture(&block) - @site.unwrap.captures_store[@item, name.to_sym] = content + + # Prepare for store + store = @site.unwrap.captures_store + case existing_behavior + when :overwrite + store[@item, name.to_sym] = '' + when :append + store[@item, name.to_sym] ||= '' + when :error + if store[@item, name.to_sym] && store[@item, name.to_sym] != content + raise "a capture named #{name.inspect} for #{@item.identifier} already exists" + else + store[@item, name.to_sym] = '' + end + else + raise ArgumentError, 'expected :existing_behavior param to #content_for to be one of ' \ + ":overwrite, :append, or :error, but #{existing_behavior.inspect} was given" + end + + # Store + @site.unwrap.captures_store_compiled_items << @item.unwrap + store[@item, name.to_sym] << content else # Get content # Get args if args.size != 2 raise ArgumentError, 'expected 2 arguments (the item ' \ "and the name of the capture) but got #{args.size} instead" end - item = args[0] - item = item.unwrap if item.respond_to?(:unwrap) + item = args[0].is_a?(Nanoc::ItemView) ? args[0].unwrap : args[0] name = args[1] # Create dependency - current_item = @site.unwrap.compiler.dependency_tracker.top - if item != current_item + if @item.nil? || item != @item.unwrap Nanoc::Int::NotificationCenter.post(:visit_started, item) Nanoc::Int::NotificationCenter.post(:visit_ended, item) # This is an extremely ugly hack to get the compiler to recompile the # item from which we use content. For this, we need to manually edit # the content attribute to reset it. :( # FIXME: clean this up - unless @site.unwrap.captures_store_compiled_items.include? item - @site.unwrap.captures_store_compiled_items << item + unless @site.unwrap.captures_store_compiled_items.include?(item) + @site.unwrap.captures_store.reset_for(item) item.forced_outdated = true - item.reps.each do |r| + @site.unwrap.compiler.reps[item].each do |r| r.snapshot_contents = { last: item.content } raise Nanoc::Int::Errors::UnmetDependency.new(r) end end end