Class: Loofah::Scrubber

Inherits:
Object
  • Object
show all
Defined in:
lib/loofah/scrubber.rb

Overview

A Scrubber wraps up a block (or method) that is run on an HTML node (element):

# change all <span> tags to <div> tags
span2div = Loofah::Scrubber.new do |node|
 node.name = "div" if node.name == "span"
end

Alternatively, this scrubber could have been implemented as:

class Span2Div < Loofah::Scrubber
 def scrub(node)
   node.name = "div" if node.name == "span"
 end
end
span2div = Span2Div.new

This can then be run on a document:

Loofah.html5_fragment("<span>foo</span><p>bar</p>").scrub!(span2div).to_s
# => "<div>foo</div><p>bar</p>"

Scrubbers can be run on a document in either a top-down traversal (the default) or bottom-up. Top-down scrubbers can optionally return Scrubber::STOP to terminate the traversal of a subtree.

Constant Summary collapse

CONTINUE =

Top-down Scrubbers may return CONTINUE to indicate that the subtree should be traversed.

Object.new.freeze
STOP =

Top-down Scrubbers may return STOP to indicate that the subtree should not be traversed.

Object.new.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}, &block) ⇒ Scrubber

Options may include :direction => :top_down (the default) or :direction => :bottom_up

For top_down traversals, if the block returns Loofah::Scrubber::STOP, then the traversal will be terminated for the current node's subtree.

Alternatively, a Scrubber may inherit from Loofah::Scrubber, and implement scrub, which is slightly faster than using a block.



65
66
67
68
69
70
71
72
73
# File 'lib/loofah/scrubber.rb', line 65

def initialize(options = {}, &block)
  direction = options[:direction] || :top_down
  unless [:top_down, :bottom_up].include?(direction)
    raise ArgumentError, "direction #{direction} must be one of :top_down or :bottom_up"
  end

  @direction = direction
  @block = block
end

Instance Attribute Details

#blockObject (readonly)

When a scrubber is initialized, the optional block is saved as :block. Note that, if no block is passed, then the scrub method is assumed to have been implemented.



49
50
51
# File 'lib/loofah/scrubber.rb', line 49

def block
  @block
end

#directionObject (readonly)

When a scrubber is initialized, the :direction may be specified as :top_down (the default) or :bottom_up.



44
45
46
# File 'lib/loofah/scrubber.rb', line 44

def direction
  @direction
end

Instance Method Details

#append_attribute(node, attribute, value) ⇒ Object

If the attribute is not set, add it If the attribute is set, don't overwrite the existing value



96
97
98
99
100
101
# File 'lib/loofah/scrubber.rb', line 96

def append_attribute(node, attribute, value)
  current_value = node.get_attribute(attribute) || ""
  current_values = current_value.split(/\s+/)
  updated_value = current_values | [value]
  node.set_attribute(attribute, updated_value.join(" "))
end

#scrub(node) ⇒ Object

When new is not passed a block, the class may implement scrub, which will be called for each document node.

Raises:



88
89
90
# File 'lib/loofah/scrubber.rb', line 88

def scrub(node)
  raise ScrubberNotFound, "No scrub method has been defined on #{self.class}"
end

#traverse(node) ⇒ Object

Calling traverse will cause the document to be traversed by either the lambda passed to the initializer or the scrub method, in the direction specified at new time.



80
81
82
# File 'lib/loofah/scrubber.rb', line 80

def traverse(node)
  direction == :bottom_up ? traverse_conditionally_bottom_up(node) : traverse_conditionally_top_down(node)
end