Class: Hexp::Node::CssSelection

Inherits:
Selection show all
Includes:
Enumerable
Defined in:
lib/hexp/node/css_selection.rb

Overview

Select nodes using CSS selectors

The main interface to this is #select, although there’s nothing stopping you from using this class directly.

This class is Enumerable, and calling #each without a block will give you an Enumerator, so you have all Ruby’s tasty list operations at your disposal.

Only a subset of the / CSS 3 selector syntax is supported. Parsing a selector that contains unsupported elements should raise an exception.

  • tag selector : div, a, section

  • class selector : .big, .user_profile

  • id selector : #main_content, #sidebar

  • attribute selectors : [href], [class~=foo], [lang|=en]

Attribute selectors support all the operators of the CSS 3 spec , so have a look there for more details.

Of course you can combine all these.

Examples:

link = H[:a, {class: 'foo bar', lang: 'fr-be', href: 'http://example.com'}, "Hello, World"]
node = H[:div, {class: 'wrap'}, link]
node.select('div.wrap a.foo.bar[lang|=fr][href^=http]') do |a|
  p a.text
end

Instance Method Summary collapse

Methods inherited from Selection

#attr, #wrap

Constructor Details

#initialize(node, css_selector) ⇒ CssSelection

Create a new CssSelection based on a root node and a selector

The selector can be unparsed (a plain String), or parsed. This class works recursively by passing a subset of the parsed selector to a subset of the tree, hence why this matters.

Parameters:



51
52
53
# File 'lib/hexp/node/css_selection.rb', line 51

def initialize(node, css_selector)
  @node, @css_selector = node.to_hexp, css_selector.freeze
end

Instance Method Details

#each {|Each| ... } ⇒ Enumerator, CssSelection

Iterate over the nodes that match

Yield Parameters:

Returns:

  • (Enumerator, CssSelection)

    Enumerator if no block is given, or self



73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/hexp/node/css_selection.rb', line 73

def each(&block)
  return to_enum(:each) unless block_given?

  walk = MutableTreeWalk.new(@node)

  until walk.end?
    if comma_sequence.matches_path?(walk.path)
      yield walk.current
    end
    walk.next!
  end

  self
end

#inspectString

Debugging representation

Returns:

  • (String)


60
61
62
# File 'lib/hexp/node/css_selection.rb', line 60

def inspect
  "#<#{self.class} @node=#{@node.inspect} @css_selector=#{@css_selector.inspect} matches=#{node_matches?}>"
end

#rewrite {|Each| ... } ⇒ Hexp::Node

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Replace / alter each node that matches

Yield Parameters:

Returns:



96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/hexp/node/css_selection.rb', line 96

def rewrite(&block)
  return @node if @node.text?

  walk = MutableTreeWalk.new(@node)

  until walk.end?
    if comma_sequence.matches_path?(walk.path)
      walk.replace!(block.call(walk.current))
    end
    walk.next!
  end

  walk.result
end