Class: HTML::Node

Inherits:
Object
  • Object
show all
Defined in:
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.



72
73
74
75
76
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 72

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.



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

def children
  @children
end

#lineObject (readonly)

The line number of the input where this node was begun



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

def line
  @line
end

#parentObject (readonly)

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



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

def parent
  @parent
end

#positionObject (readonly)

The byte position in the input where this node was begun



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

def position
  @position
end

Class Method Details

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



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
204
205
206
207
208
209
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 138

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(/[\w:-]+/)
    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



125
126
127
128
129
130
131
132
133
134
135
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 125

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.



93
94
95
96
97
98
99
100
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 93

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.



104
105
106
107
108
109
110
111
112
113
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 104

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.



87
88
89
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 87

def match(conditions)
  false
end

#tag?Boolean

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

Returns:

  • (Boolean)


117
118
119
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 117

def tag?
  false
end

#to_sObject

Return a textual representation of the node.



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

def to_s
  s = ""
  @children.each { |child| s << child.to_s }
  s
end

#validate_conditions(conditions) ⇒ Object



121
122
123
# File 'lib/action_controller/vendor/html-scanner/html/node.rb', line 121

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