Class: Nokolexbor::Node
- Inherits:
-
Object
- Object
- Nokolexbor::Node
- Includes:
- Enumerable
- Defined in:
- lib/nokolexbor/node.rb
Direct Known Subclasses
Constant Summary collapse
- ELEMENT_NODE =
1- ATTRIBUTE_NODE =
2- TEXT_NODE =
3- CDATA_SECTION_NODE =
4- ENTITY_REF_NODE =
5- ENTITY_NODE =
6- PI_NODE =
7- COMMENT_NODE =
8- DOCUMENT_NODE =
9- DOCUMENT_TYPE_NODE =
10- DOCUMENT_FRAG_NODE =
11- NOTATION_NODE =
12- LOOKS_LIKE_XPATH =
%r{^(\./|/|\.\.|\.$)}
Instance Attribute Summary collapse
-
#document ⇒ Document
readonly
The associated Document of this node.
Instance Method Summary collapse
-
#<<(node_or_tags) ⇒ Node
Add
node_or_tagsas a child of this Node. -
#add_class(names) ⇒ Node
Ensure CSS classes are present on
self. -
#add_next_sibling(node_or_tags) ⇒ Node, NodeSet
(also: #next=)
Insert
node_or_tagsafter this Node (as a sibling). -
#add_previous_sibling(node_or_tags) ⇒ Node, NodeSet
(also: #previous=)
Insert
node_or_tagsbefore this Node (as a sibling). -
#after(node_or_tags) ⇒ Node
Insert
node_or_tagsafter this Node (as a sibling). -
#ancestors(selector = nil) ⇒ NodeSet
Get a list of ancestor Node of this Node.
-
#append_class(names) ⇒ Node
Add CSS classes to
self, regardless of duplication. -
#at(*args) ⇒ Node?
(also: #%)
Like #search, but returns the first match.
-
#at_css(*args) ⇒ Node?
Like #css, but returns the first match.
-
#at_xpath(*args) ⇒ Node?
Like #xpath, but returns the first match.
-
#attributes ⇒ Hash{String => Attribute}
Fetch this node’s attributes.
-
#before(node_or_tags) ⇒ Node
Insert
node_or_tagsbefore this Node (as a sibling). -
#cdata? ⇒ Boolean
True if this is a CDATA.
-
#children=(node) ⇒ Object
(also: #inner_html=)
Set the content of this Node.
-
#classes ⇒ Array
Fetch CSS class names of a Node.
-
#comment? ⇒ Boolean
True if this is a Comment.
-
#css(*args) ⇒ NodeSet
Search this object for CSS
rules. -
#css_path ⇒ Object
Get the path to this node as a CSS expression.
-
#document? ⇒ Boolean
True if this is a Document.
-
#each {|String, String| ... } ⇒ Object
Iterate over each attribute name and value pair of this Node.
-
#element? ⇒ Boolean
(also: #elem?)
True if this is an Element.
-
#fragment(tags) ⇒ DocumentFragment
Create a DocumentFragment containing
tagsthat is relative to this context node. -
#fragment? ⇒ Boolean
True if this is a DocumentFragment.
-
#kwattr_add(attribute_name, keywords) ⇒ Node
Ensure that values are present in a keyword attribute.
-
#kwattr_append(attribute_name, keywords) ⇒ Node
Add keywords to a Node’s keyword attribute, regardless of duplication.
-
#kwattr_remove(attribute_name, keywords) ⇒ Node
Remove keywords from a keyword attribute.
-
#kwattr_values(attribute_name) ⇒ Array<String>
Fetch values from a keyword attribute of a Node.
-
#matches?(selector) ⇒ Boolean
True if this Node matches
selector. -
#nokogiri_at_css(*args) ⇒ Node?
Like #nokogiri_css, but returns the first match.
-
#nokogiri_css(*args) ⇒ NodeSet
Search this object for CSS
rules. -
#parent=(parent_node) ⇒ Object
Set the parent Node of this Node.
-
#prepend_child(node) ⇒ Node, NodeSet
Add
nodeas the first child of this Node. -
#processing_instruction? ⇒ Boolean
True if this is a ProcessingInstruction.
-
#remove_class(names = nil) ⇒ Node
Remove CSS classes from this node.
-
#replace(node) ⇒ Node, NodeSet
Replace this Node with
node. -
#search(*args) ⇒ NodeSet
(also: #/)
Search this object for
paths. -
#swap(node) ⇒ Node
Swap this Node for
node. -
#text? ⇒ Boolean
True if this is a Text.
-
#traverse { ... } ⇒ Object
Traverse self and all children.
-
#value?(value) ⇒ Boolean
True if this Node’s attributes include <value>.
-
#wrap(node) ⇒ Node
Wrap this Node with another node.
-
#write_to(io, *options) ⇒ Object
(also: #write_html_to)
Serialize Node and write to
io. -
#xpath(*args) ⇒ NodeSet
Search this node for XPath
paths.
Instance Attribute Details
Instance Method Details
#<<(node_or_tags) ⇒ Node
Add node_or_tags as a child of this Node.
208 209 210 211 |
# File 'lib/nokolexbor/node.rb', line 208 def <<() add_child() self end |
#add_class(names) ⇒ Node
Ensure CSS classes are present on self. Any CSS classes in names that already exist in the “class” attribute are not added. Note that any existing duplicates in the “class” attribute are not removed. Compare with #append_class.
This is a convenience function and is equivalent to:
node.kwattr_add("class", names)
481 482 483 |
# File 'lib/nokolexbor/node.rb', line 481 def add_class(names) kwattr_add("class", names) end |
#add_next_sibling(node_or_tags) ⇒ Node, NodeSet Also known as: next=
Insert node_or_tags after this Node (as a sibling).
165 166 167 168 169 170 |
# File 'lib/nokolexbor/node.rb', line 165 def add_next_sibling() raise ArgumentError, "A document may not have multiple root nodes." if parent&.document? && !(.comment? || .processing_instruction?) add_sibling(:next, ) end |
#add_previous_sibling(node_or_tags) ⇒ Node, NodeSet Also known as: previous=
Insert node_or_tags before this Node (as a sibling).
151 152 153 154 155 156 |
# File 'lib/nokolexbor/node.rb', line 151 def add_previous_sibling() raise ArgumentError, "A document may not have multiple root nodes." if parent&.document? && !(.comment? || .processing_instruction?) add_sibling(:previous, ) end |
#after(node_or_tags) ⇒ Node
Insert node_or_tags after this Node (as a sibling).
191 192 193 194 |
# File 'lib/nokolexbor/node.rb', line 191 def after() add_next_sibling() self end |
#ancestors(selector = nil) ⇒ NodeSet
Get a list of ancestor Node of this Node
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/nokolexbor/node.rb', line 73 def ancestors(selector = nil) return NodeSet.new(@document) unless respond_to?(:parent) return NodeSet.new(@document) unless parent parents = [parent] while parents.last.respond_to?(:parent) break unless (ctx_parent = parents.last.parent) parents << ctx_parent end return NodeSet.new(@document, parents) unless selector root = parents.last search_results = root.search(selector) NodeSet.new(@document, parents.find_all do |parent| search_results.include?(parent) end) end |
#append_class(names) ⇒ Node
Add CSS classes to self, regardless of duplication. Compare with #add_class.
This is a convenience function and is equivalent to:
node.kwattr_append("class", names)
497 498 499 |
# File 'lib/nokolexbor/node.rb', line 497 def append_class(names) kwattr_append("class", names) end |
#at(*args) ⇒ Node? Also known as: %
Like #search, but returns the first match.
422 423 424 425 426 427 428 429 430 |
# File 'lib/nokolexbor/node.rb', line 422 def at(*args) paths, handler, ns, binds = extract_params(args) if paths.size == 1 && !LOOKS_LIKE_XPATH.match?(paths.first) return at_css(paths.first) end at_xpath(*(paths + [ns, handler, binds].compact)) end |
#at_css(*args) ⇒ Node?
Like #css, but returns the first match.
This method uses Lexbor as the selector engine. Its performance is much higher than #at_xpath or #nokogiri_at_css.
346 347 348 |
# File 'lib/nokolexbor/node.rb', line 346 def at_css(*args) at_css_impl(args.join(', ')) end |
#at_xpath(*args) ⇒ Node?
Like #xpath, but returns the first match.
It works the same way as Nokogiri::Node#at_xpath.
398 399 400 |
# File 'lib/nokolexbor/node.rb', line 398 def at_xpath(*args) xpath(*args).first end |
#attributes ⇒ Hash{String => Attribute}
Fetch this node’s attributes.
248 249 250 251 252 |
# File 'lib/nokolexbor/node.rb', line 248 def attributes attribute_nodes.each_with_object({}) do |node, hash| hash[node.name] = node end end |
#before(node_or_tags) ⇒ Node
Insert node_or_tags before this Node (as a sibling).
179 180 181 182 |
# File 'lib/nokolexbor/node.rb', line 179 def before() add_previous_sibling() self end |
#cdata? ⇒ Boolean
Returns true if this is a CDATA.
31 32 33 |
# File 'lib/nokolexbor/node.rb', line 31 def cdata? type == CDATA_SECTION_NODE end |
#children=(node) ⇒ Object Also known as: inner_html=
Set the content of this Node.
284 285 286 287 |
# File 'lib/nokolexbor/node.rb', line 284 def children=(node) children.remove add_child(node) end |
#classes ⇒ Array
Fetch CSS class names of a Node.
This is a convenience function and is equivalent to:
node.kwattr_values("class")
451 452 453 |
# File 'lib/nokolexbor/node.rb', line 451 def classes kwattr_values("class") end |
#comment? ⇒ Boolean
Returns true if this is a Comment.
26 27 28 |
# File 'lib/nokolexbor/node.rb', line 26 def comment? type == COMMENT_NODE end |
#css(*args) ⇒ NodeSet
Search this object for CSS rules. rules must be one or more CSS selectors.
This method uses Lexbor as the selector engine. Its performance is much higher than #xpath or #nokogiri_css.
334 335 336 |
# File 'lib/nokolexbor/node.rb', line 334 def css(*args) css_impl(args.join(', ')) end |
#css_path ⇒ Object
Get the path to this node as a CSS expression
62 63 64 65 66 |
# File 'lib/nokolexbor/node.rb', line 62 def css_path path.split(%r{/}).filter_map do |part| part.empty? ? nil : part.gsub(/\[(\d+)\]/, ':nth-of-type(\1)') end.join(" > ") end |
#document? ⇒ Boolean
Returns true if this is a Document.
57 58 59 |
# File 'lib/nokolexbor/node.rb', line 57 def document? is_a?(Nokolexbor::Document) end |
#each {|String, String| ... } ⇒ Object
Iterate over each attribute name and value pair of this Node.
304 305 306 307 308 |
# File 'lib/nokolexbor/node.rb', line 304 def each attributes.each do |name, node| yield [name, node.value] end end |
#element? ⇒ Boolean Also known as: elem?
Returns true if this is an Element.
51 52 53 |
# File 'lib/nokolexbor/node.rb', line 51 def element? type == ELEMENT_NODE end |
#fragment(tags) ⇒ DocumentFragment
Create a DocumentFragment containing tags that is relative to this context node.
314 315 316 |
# File 'lib/nokolexbor/node.rb', line 314 def fragment() Nokolexbor::DocumentFragment.new(document, , self) end |
#fragment? ⇒ Boolean
Returns true if this is a DocumentFragment.
46 47 48 |
# File 'lib/nokolexbor/node.rb', line 46 def fragment? type == DOCUMENT_FRAG_NODE end |
#kwattr_add(attribute_name, keywords) ⇒ Node
Ensure that values are present in a keyword attribute.
Any values in keywords that already exist in the Node’s attribute values are not added. Note that any existing duplicates in the attribute values are not removed. Compare with #kwattr_append.
A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the HTML “class” attribute used to contain CSS classes. But other keyword attributes exist, for instance the “rel” attribute.
576 577 578 579 580 581 582 |
# File 'lib/nokolexbor/node.rb', line 576 def kwattr_add(attribute_name, keywords) keywords = keywordify(keywords) current_kws = kwattr_values(attribute_name) new_kws = (current_kws + (keywords - current_kws)).join(" ") set_attr(attribute_name, new_kws) self end |
#kwattr_append(attribute_name, keywords) ⇒ Node
Add keywords to a Node’s keyword attribute, regardless of duplication. Compare with #kwattr_add.
A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the HTML “class” attribute used to contain CSS classes. But other keyword attributes exist, for instance the “rel” attribute.
605 606 607 608 609 610 611 |
# File 'lib/nokolexbor/node.rb', line 605 def kwattr_append(attribute_name, keywords) keywords = keywordify(keywords) current_kws = kwattr_values(attribute_name) new_kws = (current_kws + keywords).join(" ") set_attr(attribute_name, new_kws) self end |
#kwattr_remove(attribute_name, keywords) ⇒ Node
Remove keywords from a keyword attribute. Any matching keywords that exist in the named attribute are removed, including any multiple entries.
If no keywords remain after this operation, or if keywords is nil, the attribute is deleted from the node.
A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the HTML “class” attribute used to contain CSS classes. But other keyword attributes exist, for instance the “rel” attribute.
637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 |
# File 'lib/nokolexbor/node.rb', line 637 def kwattr_remove(attribute_name, keywords) if keywords.nil? remove_attr(attribute_name) return self end keywords = keywordify(keywords) current_kws = kwattr_values(attribute_name) new_kws = current_kws - keywords if new_kws.empty? remove_attr(attribute_name) else set_attr(attribute_name, new_kws.join(" ")) end self end |
#kwattr_values(attribute_name) ⇒ Array<String>
Fetch values from a keyword attribute of a Node.
A “keyword attribute” is a node attribute that contains a set of space-delimited values. Perhaps the most familiar example of this is the HTML “class” attribute used to contain CSS classes. But other keyword attributes exist, for instance the “rel” attribute.
@#kwattr_append @#kwattr_remove
548 549 550 |
# File 'lib/nokolexbor/node.rb', line 548 def kwattr_values(attribute_name) keywordify(attr(attribute_name) || []) end |
#matches?(selector) ⇒ Boolean
Returns true if this Node matches selector.
241 242 243 |
# File 'lib/nokolexbor/node.rb', line 241 def matches?(selector) ancestors.last.css(selector).any? { |node| node == self } end |
#nokogiri_at_css(*args) ⇒ Node?
Like #nokogiri_css, but returns the first match.
This method uses libxml2 as the selector engine. It works the same way as Nokogiri::Node#at_css.
372 373 374 |
# File 'lib/nokolexbor/node.rb', line 372 def nokogiri_at_css(*args) nokogiri_css(*args).first end |
#nokogiri_css(*args) ⇒ NodeSet
Search this object for CSS rules. rules must be one or more CSS selectors. It supports a mixed syntax of CSS selectors and XPath.
This method uses libxml2 as the selector engine. It works the same way as Nokogiri::Node#css.
358 359 360 361 362 |
# File 'lib/nokolexbor/node.rb', line 358 def nokogiri_css(*args) rules, handler, ns, _ = extract_params(args) nokogiri_css_internal(self, rules, handler, ns) end |
#parent=(parent_node) ⇒ Object
Set the parent Node of this Node.
292 293 294 |
# File 'lib/nokolexbor/node.rb', line 292 def parent=(parent_node) parent_node.add_child(self) end |
#prepend_child(node) ⇒ Node, NodeSet
Add node as the first child of this Node.
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/nokolexbor/node.rb', line 220 def prepend_child(node) if (first = children.first) # Mimic the error add_child would raise. raise "Document already has a root node" if document? && !(node.comment? || node.processing_instruction?) first.add_sibling(:previous, node) else add_child(node) end end |
#processing_instruction? ⇒ Boolean
Returns true if this is a ProcessingInstruction.
36 37 38 |
# File 'lib/nokolexbor/node.rb', line 36 def processing_instruction? type == PI_NODE end |
#remove_class(names = nil) ⇒ Node
Remove CSS classes from this node. Any CSS class names in css_classes that exist in this node’s “class” attribute are removed, including any multiple entries.
If no CSS classes remain after this operation, or if css_classes is nil, the “class” attribute is deleted from the node.
This is a convenience function and is equivalent to:
node.kwattr_remove("class", css_classes)
527 528 529 |
# File 'lib/nokolexbor/node.rb', line 527 def remove_class(names = nil) kwattr_remove("class", names) end |
#replace(node) ⇒ Node, NodeSet
Replace this Node with node.
261 262 263 264 265 |
# File 'lib/nokolexbor/node.rb', line 261 def replace(node) ret = add_sibling(:previous, node) remove ret end |
#search(*args) ⇒ NodeSet Also known as: /
Search this object for paths. paths must be one or more XPath or CSS selectors.
405 406 407 408 409 410 411 412 413 |
# File 'lib/nokolexbor/node.rb', line 405 def search(*args) paths, handler, ns, binds = extract_params(args) if paths.size == 1 && !LOOKS_LIKE_XPATH.match?(paths.first) return css(paths.first) end xpath(*(paths + [ns, handler, binds].compact)) end |
#swap(node) ⇒ Node
Swap this Node for node.
274 275 276 277 |
# File 'lib/nokolexbor/node.rb', line 274 def swap(node) replace(node) self end |
#text? ⇒ Boolean
Returns true if this is a Text.
41 42 43 |
# File 'lib/nokolexbor/node.rb', line 41 def text? type == TEXT_NODE end |
#traverse { ... } ⇒ Object
Traverse self and all children.
233 234 235 236 |
# File 'lib/nokolexbor/node.rb', line 233 def traverse(&block) children.each { |j| j.traverse(&block) } yield(self) end |
#value?(value) ⇒ Boolean
Returns true if this Node’s attributes include <value>.
297 298 299 |
# File 'lib/nokolexbor/node.rb', line 297 def value?(value) values.include?(value) end |
#wrap(node) ⇒ Node
Wrap this Node with another node.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/nokolexbor/node.rb', line 122 def wrap(node) case node when String new_parent = fragment(node).child when DocumentFragment new_parent = node.child when Node new_parent = node.dup else raise ArgumentError, "Requires a String or Node argument, and cannot accept a #{node.class}" end if parent add_sibling(:next, new_parent) else new_parent.remove end new_parent.add_child(self) self end |
#write_to(io, *options) ⇒ Object Also known as: write_html_to
Serialize Node and write to io.
655 656 657 |
# File 'lib/nokolexbor/node.rb', line 655 def write_to(io, *) io.write(to_html(*)) end |
#xpath(*args) ⇒ NodeSet
Search this node for XPath paths. paths must be one or more XPath queries.
It works the same way as Nokogiri::Node#xpath.
385 386 387 388 389 |
# File 'lib/nokolexbor/node.rb', line 385 def xpath(*args) paths, handler, ns, binds = extract_params(args) xpath_internal(self, paths, handler, ns, binds) end |