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.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.

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

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, @block = direction, 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.


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

def block
  @block
end

#directionObject (readonly)

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


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

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


93
94
95
96
97
98
# File 'lib/loofah/scrubber.rb', line 93

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:


85
86
87
# File 'lib/loofah/scrubber.rb', line 85

def scrub(node)
  raise ScrubberNotFound, "No scrub method has been defined on #{self.class.to_s}"
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.

77
78
79
# File 'lib/loofah/scrubber.rb', line 77

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