Class: HTML::Node

Inherits:
Object show all
Defined in:
actionpack/lib/action_controller/vendor/html-scanner/html/node.rb

Overview

The base class of all nodes, textual and otherwise, in an HTML document.

Direct Known Subclasses

Tag, Text

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent, line = 0, pos = 0) ⇒ Node

Create a new node as a child of the given parent.



68
69
70
71
72
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 68

def initialize(parent, line=0, pos=0)
  @parent = parent
  @children = []
  @line, @position = line, pos
end

Instance Attribute Details

#childrenObject (readonly)

The array of children of this node. Not all nodes have children.



55
56
57
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 55

def children
  @children
end

#lineObject (readonly)

The line number of the input where this node was begun



62
63
64
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 62

def line
  @line
end

#parentObject (readonly)

The parent node of this node. All nodes have a parent, except for the root node.



59
60
61
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 59

def parent
  @parent
end

#positionObject (readonly)

The byte position in the input where this node was begun



65
66
67
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 65

def position
  @position
end

Class Method Details

.parse(parent, line, pos, content, strict = true) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 132

def parse(parent, line, pos, content, strict=true)
  if content !~ /^<\S/
    Text.new(parent, line, pos, content)
  else
    scanner = StringScanner.new(content)

    unless scanner.skip(/</)
      if strict
        raise "expected <"
      else
        return Text.new(parent, line, pos, content)
      end
    end

    if scanner.skip(/!\[CDATA\[/)
      unless scanner.skip_until(/\]\]>/)
        if strict
          raise "expected ]]> (got #{scanner.rest.inspect} for #{content})"
        else
          scanner.skip_until(/\Z/)
        end
      end

      return CDATA.new(parent, line, pos, scanner.pre_match.gsub(/<!\[CDATA\[/, ''))
    end

    closing = ( scanner.scan(/\//) ? :close : nil )
    return Text.new(parent, line, pos, content) unless name = scanner.scan(/[^\s!>\/]+/)
    name.downcase!

    unless closing
      scanner.skip(/\s*/)
      attributes = {}
      while attr = scanner.scan(/[-\w:]+/)
        value = true
        if scanner.scan(/\s*=\s*/)
          if delim = scanner.scan(/['"]/)
            value = ""
            while text = scanner.scan(/[^#{delim}\\]+|./)
              case text
                when "\\" then
                  value << text
                  break if scanner.eos?
                  value << scanner.getch
                when delim
                  break
                else value << text
              end
            end
          else
            value = scanner.scan(/[^\s>\/]+/)
          end
        end
        attributes[attr.downcase] = value
        scanner.skip(/\s*/)
      end

      closing = ( scanner.scan(/\//) ? :self : nil )
    end

    unless scanner.scan(/\s*>/)
      if strict
        raise "expected > (got #{scanner.rest.inspect} for #{content}, #{attributes.inspect})"
      else
        # throw away all text until we find what we're looking for
        scanner.skip_until(/>/) or scanner.terminate
      end
    end

    Tag.new(parent, line, pos, name, attributes, closing)
  end
end

Instance Method Details

#==(node) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 119

def ==(node)
  return false unless self.class == node.class && children.size == node.children.size

  equivalent = true

  children.size.times do |i|
    equivalent &&= children[i] == node.children[i]
  end

  equivalent
end

#find(conditions) ⇒ Object

Search the children of this node for the first node for which #find returns non nil. Returns the result of the #find call that succeeded.



87
88
89
90
91
92
93
94
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 87

def find(conditions)
  conditions = validate_conditions(conditions)
  @children.each do |child|
    node = child.find(conditions)
    return node if node
  end
  nil
end

#find_all(conditions) ⇒ Object

Search for all nodes that match the given conditions, and return them as an array.



98
99
100
101
102
103
104
105
106
107
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 98

def find_all(conditions)
  conditions = validate_conditions(conditions)

  matches = []
  matches << self if match(conditions)
  @children.each do |child|
    matches.concat child.find_all(conditions)
  end
  matches
end

#match(conditions) ⇒ Object

Return false (subclasses must override this to provide specific matching behavior.) conditions may be of any type.



81
82
83
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 81

def match(conditions)
  false
end

#tag?Boolean

Returns false. Subclasses may override this if they define a kind of tag.

Returns:

  • (Boolean)


111
112
113
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 111

def tag?
  false
end

#to_sObject

Return a textual representation of the node.



75
76
77
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 75

def to_s
  @children.join()
end

#validate_conditions(conditions) ⇒ Object



115
116
117
# File 'actionpack/lib/action_controller/vendor/html-scanner/html/node.rb', line 115

def validate_conditions(conditions)
  Conditions === conditions ? conditions : Conditions.new(conditions)
end