class Kitchen::Document
Wrapper around a Nokogiri
`Document`, adding search with Kitchen
enumerators, clipboards, pantries, etc.
Attributes
@return [Config] the configuration used in this document
@return [IdTracker] the counter for duplicate IDs
@return [Element] the current element yielded from search results
Public Class Methods
Return a new instance of Document
@param nokogiri_document
[Nokogiri::XML::Document] @param config [Config]
# File lib/kitchen/document.rb, line 48 def initialize(nokogiri_document:, config: nil) @nokogiri_document = nokogiri_document @location = nil @config = config || Config.new @id_tracker = IdTracker.new # Nokogiri by default only recognizes the namespaces on the root node. Add all others. raw&.add_all_namespaces! if @config.enable_all_namespaces end
Public Instance Methods
Returns the document's clipboard with the given name.
@param name [Symbol, String] the name of the clipboard. String
values are
converted to symbols.
@return [Clipboard]
# File lib/kitchen/document.rb, line 87 def clipboard(name: :default) (@clipboards ||= {})[name.to_sym] ||= Clipboard.new end
Returns the document's counter with the given name.
@param name [Symbol, String] the name of the counter. String
values are
converted to symbols.
@return [Counter]
# File lib/kitchen/document.rb, line 107 def counter(name) (@counters ||= {})[name.to_sym] ||= Counter.new end
Create a new Element
TODO don't know if we need this
@param name [String] the tag name @param args [Array<String, Hash>]
@example div with a class
create_element("div", class: "foo") #=> <div class="foo"></div>
@example div with some content and a class
cretae_element("div", "contents", class: "foo") #=> <div class="foo">contents</div>
@example div created by block
create_element("div") {|elem| elem['class'] = 'foo'} #=> <div class="foo"></div>
@return [Element]
# File lib/kitchen/document.rb, line 127 def create_element(name, *args, &block) Kitchen::Element.new( node: @nokogiri_document.create_element(name, *args, &block), document: self, short_type: "created_element_#{SecureRandom.hex(4)}" ) end
Create a new Element
from a string
@param string [String] the element as a string
@example
create_element_from_string("<div class='foo'>bar</div>") #=> <div class="foo">bar</div>
@return [Element]
# File lib/kitchen/document.rb, line 144 def create_element_from_string(string) children = Nokogiri::XML("<foo>#{string}</foo>").search('foo').first.element_children raise('new_element must only make one top-level element') if children.many? node = children.first create_element(node.name, node.attributes).tap do |element| element.inner_html = node.children end end
Returns the locale for this document, default to `:en` if no locale detected
@return [Symbol]
# File lib/kitchen/document.rb, line 167 def locale raw.root['lang']&.to_sym || begin warn 'No `lang` attribute on this document so cannot detect its locale; defaulting to `:en`' :en end end
Returns the document's pantry with the given name.
@param name [Symbol, String] the name of the pantry. String
values are
converted to symbols.
@return [Pantry]
# File lib/kitchen/document.rb, line 97 def pantry(name: :default) (@pantries ||= {})[name.to_sym] ||= Pantry.new end
Returns an enumerator that iterates over all children of this document that match the provided selector or XPath arguments. Updates `location` during iteration.
@param selector_or_xpath_args [Array<String>] CSS selectors or XPath arguments @return [ElementEnumerator]
# File lib/kitchen/document.rb, line 65 def search(*selector_or_xpath_args) selector_or_xpath_args = [selector_or_xpath_args].flatten ElementEnumerator.new do |block| nokogiri_document.search(*selector_or_xpath_args).each do |inner_node| element = Kitchen::Element.new( node: inner_node, document: self, short_type: Utils.search_path_to_type(selector_or_xpath_args) ) self.location = element block.yield(element) end end end