module Infoboxer::Navigation::Lookup::Node
`Lookup::Node` module provides methods for navigating through page tree in XPath-like manner.
What you need to know about it:
## Selectors
Each `lookup_*` method (and others similar) receive _list of selectors_. Examples of acceptable selectors:
“`ruby # 1. Node
class: document.lookup(Bold) # all Bolds
# 2. Class symbol document.lookup(:Bold) # same as above, useful if you don't want to include Infoboxer::Tree
# in all of your code or write things like lookup(Infoboxer::Tree::Bold
)
# 3. Getter/pattern: document.lookup(text: /something/) # finds all nodes where result of getter matches pattern
# Checks against patterns are performed with `===`, so you can # use regexps to find by text, or ranges to find by number, like document.lookup(:Heading, level: (3..4))
# Nodes
where method is not defined are ignored, so you can # rewrite above example as just document.lookup(level: 3..4) # …and receive meaningful result without any NoMethodError
# 4. Check symbol document.lookup(:bold?) # finds all nodes for which `:bold?` is defined and returns # truthy value;
# 5. Code block document.lookup{|node| node.params.has_key?(:class)} “`
You also can use any of those method without any selector, thus receiving ALL parents, ALL children, ALL siblings and so on.
## Chainable navigation
Each `lookup_*` method returns an instance of {Tree::Nodes} class, which behaves like an Array, but also defines similar set of `lookup_*` methods, so, you can brainlessly do the things like
“`ruby document.
lookup(:Paragraph){|p| p.text.length > 100}. lookup(:Wikilink, text: /^List of/). select(&:bold?)
“`
## Underscored methods
For all methods of this module you can notice “underscored” version (`lookup_children` vs `_lookup_children` and so on). Basically, underscored versions accept instance of {Lookup::Selector}, which is already preprocessed version of all selectors. It is kinda internal thing, though can be useful if you store selectors in variables – it is easier to have and use just one instance of Selector
, than list of arguments and blocks.
Public Instance Methods
Underscored version of {#lookup}
# File lib/infoboxer/navigation/lookup.rb, line 111 def _lookup(selector) Tree::Nodes[_matches?(selector) ? self : nil, *children._lookup(selector)] .flatten.compact end
Underscored version of {#lookup_children}
# File lib/infoboxer/navigation/lookup.rb, line 117 def _lookup_children(selector) @children._find(selector) end
Underscored version of {#lookup_next_siblings}
# File lib/infoboxer/navigation/lookup.rb, line 149 def _lookup_next_siblings(selector) next_siblings._find(selector) end
Underscored version of {#lookup_parents}
# File lib/infoboxer/navigation/lookup.rb, line 122 def _lookup_parents(selector) case when !parent Tree::Nodes[] when parent._matches?(selector) Tree::Nodes[parent, *parent._lookup_parents(selector)] else parent._lookup_parents(selector) end end
Underscored version of {#lookup_prev_sibling}
# File lib/infoboxer/navigation/lookup.rb, line 144 def _lookup_prev_sibling(selector) prev_siblings.reverse.detect { |n| selector === n } end
Underscored version of {#lookup_prev_siblings}
# File lib/infoboxer/navigation/lookup.rb, line 139 def _lookup_prev_siblings(selector) prev_siblings._find(selector) end
Underscored version of {#lookup_siblings}
# File lib/infoboxer/navigation/lookup.rb, line 134 def _lookup_siblings(selector) siblings._find(selector) end
Underscored version of {#matches?}
# File lib/infoboxer/navigation/lookup.rb, line 106 def _matches?(selector) selector === self end
Checks if node has any parent matching selectors.
# File lib/infoboxer/navigation/lookup.rb, line 168 def parent?(*selectors, &block) !lookup_parents(*selectors, &block).empty? end