Class: Hexp::Node::CssSelection

Inherits:
Selector
  • Object
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 Selector

#attr, #wrap

Constructor Details

- (CssSelection) initialize(node, css_selector)

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:



48
49
50
# File 'lib/hexp/node/css_selection.rb', line 48

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

Instance Method Details

- (Enumerator, CssSelection) each(&block) {|@node| ... }

Iterate over the nodes that match

Parameters:

  • block (Proc)

    a block that receives each matching nodes

Yields:

  • (@node)

Returns:

  • (Enumerator, CssSelection)

    enumerator if no block is given, or self



65
66
67
68
69
70
71
72
73
# File 'lib/hexp/node/css_selection.rb', line 65

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

  @node.children.each do |child|
    next_selection_for(child).each(&block)
  end
  yield @node if node_matches?
  self
end

- (String) inspect

Debugging representation

Returns:

  • (String)


57
58
59
# File 'lib/hexp/node/css_selection.rb', line 57

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

- (Object) rewrite(&block)

Replace / alter each node that matches



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/hexp/node/css_selection.rb', line 79

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

  new_node = H[
    @node.tag,
    @node.attributes,
    @node.children.flat_map do |child|
      next_selection_for(child).rewrite(&block)
    end
  ]
  node_matches? ? block.call(new_node) : new_node
end