lib/html_surgeon/change_set.rb
module HtmlSurgeon
class ChangeSet
attr_reader :node_set, :base, :change_list, :run_time, :refinement_callbacks, :changed_nodes
def self.create(node_set, base)
new_class.new node_set, base
end
def self.new_class
Class.new(ChangeSet) do
Changes.change_classes.each do |klass|
include klass::ChangeSetMethods
end
end
end
def initialize(node_set, base)
@node_set = node_set
@changed_nodes = []
@base = base
@change_list = []
@id = SecureRandom.uuid
@run_time = nil
@refinement_callbacks = []
end
delegate :audit?, :html, to: :base
delegate :size, to: :changed_nodes, prefix: true
# TODO: #preview, like run but in another doc, does not change it yet.
# chainable fluid ID setter
def id(custom_id = nil)
if custom_id
@id = custom_id
self
else
@id
end
end
def run
@run_time = Time.now.utc
node_set.each do |node|
apply_on_node(node)
end
self
end
def changes
change_list.map &:log
end
def select(&block)
refinement_callbacks << [:select, block]
self
end
def reject(&block)
refinement_callbacks << [:reject, block]
self
end
# CHANGES
private
def chain_add_change(change)
change_list << change
self
end
def apply_on_node(node)
refinement_callbacks.each do |(type, refinement)|
case type
when :select
return false unless refinement.call(node)
when :reject
return false if refinement.call(node)
end
end
applied = do_apply_on_node(node)
changed_nodes << node if applied
end
def do_apply_on_node(node)
map = change_list.map do |change|
change.apply(node)
end
map.any? { |result| !!result }
end
end
end