Module: Dommy::Node

Included in:
Attr, CharacterDataNode, Document, DocumentType, Element, Fragment, ProcessingInstruction, ShadowRoot
Defined in:
lib/dommy/node.rb

Overview

‘Node` — common base mixin. All node-like classes (Element, TextNode, CommentNode, CharacterDataNode, Document, Fragment, DocumentType, ShadowRoot) include this so `el.is_a?(Dommy::Node)` works.

Real classes already define ‘nodeType` / `nodeName` / `nodeValue` / `parentNode` / `isConnected` / `cloneNode` independently; this module is primarily an identity marker. Adding new shared methods later is straightforward.

Constant Summary collapse

ELEMENT_NODE =

Standardized nodeType constants — duplicated from Element so callers can refer to ‘Dommy::Node::ELEMENT_NODE` without depending on a specific subclass.

1
ATTRIBUTE_NODE =
2
TEXT_NODE =
3
CDATA_SECTION_NODE =
4
PROCESSING_INSTRUCTION_NODE =
7
COMMENT_NODE =
8
DOCUMENT_NODE =
9
DOCUMENT_TYPE_NODE =
10
DOCUMENT_FRAGMENT_NODE =
11
DOCUMENT_POSITION_DISCONNECTED =
0x01
DOCUMENT_POSITION_PRECEDING =
0x02
DOCUMENT_POSITION_FOLLOWING =
0x04
DOCUMENT_POSITION_CONTAINS =
0x08
DOCUMENT_POSITION_CONTAINED_BY =
0x10
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC =
0x20
HTML_NAMESPACE =
"http://www.w3.org/1999/xhtml"

Instance Method Summary collapse

Instance Method Details

#compare_document_position(other) ⇒ Object

Node.compareDocumentPosition(other) — a bitmask describing where ‘other` sits relative to this node: 0 for the same node, CONTAINS/CONTAINED_BY for ancestor/descendant, PRECEDING/FOLLOWING for tree order, or DISCONNECTED (with a stable IMPLEMENTATION_SPECIFIC|PRECEDING) for unrelated nodes. Generic over any node with a backing Nokogiri node.



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/dommy/node.rb', line 235

def compare_document_position(other)
  return 0 if equal?(other)
  unless respond_to?(:__dommy_backend_node__) && other.respond_to?(:__dommy_backend_node__)
    return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING
  end

  self_node = __dommy_backend_node__
  other_node = other.__dommy_backend_node__
  self_ancestors = node_ancestor_chain(self_node)
  other_ancestors = node_ancestor_chain(other_node)

  common = self_ancestors.find { |a| other_ancestors.include?(a) }
  unless common
    return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_PRECEDING
  end
  return DOCUMENT_POSITION_CONTAINED_BY | DOCUMENT_POSITION_FOLLOWING if common == self_node
  return DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING if common == other_node

  self_branch = node_branch_under(common, self_ancestors)
  other_branch = node_branch_under(common, other_ancestors)
  common.children.each do |child|
    return DOCUMENT_POSITION_FOLLOWING if child == self_branch
    return DOCUMENT_POSITION_PRECEDING if child == other_branch
  end
  DOCUMENT_POSITION_DISCONNECTED
end

#get_root_node(_options = nil) ⇒ Object

Node.getRootNode — the topmost ancestor of this node (the document, a ShadowRoot, a detached subtree root, or the node itself). Generic default for any node backed by a Nokogiri node; classes with special roots (Element’s shadow handling) override it.



266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/dommy/node.rb', line 266

def get_root_node(_options = nil)
  return self unless respond_to?(:__dommy_backend_node__) && instance_variable_defined?(:@document)

  node = __dommy_backend_node__
  node = node.parent while node.respond_to?(:parent) && node.parent
  # The topmost node of an attached subtree is the Nokogiri document, which
  # has no element wrapper — map it to the Document. A detached node's root is
  # itself.
  return @document if @document && node.equal?(@document.nokogiri_doc)

  (@document && @document.wrap_node(node)) || self
end

#is_default_namespace(namespace) ⇒ Object

Node.isDefaultNamespace(namespace) — true if ‘namespace` (null/“” → null) is the default namespace in this node’s scope.



317
318
319
320
321
# File 'lib/dommy/node.rb', line 317

def is_default_namespace(namespace)
  ns = namespace.nil? ? nil : namespace.to_s
  ns = nil if ns == ""
  lookup_namespace_uri(nil) == ns
end

#is_equal_node(other) ⇒ Object

WHATWG Node.isEqualNode — deep structural equality (type-specific data plus equal, in-order, recursively-equal children). Available on every node class that includes Node; the bridge routes “isEqualNode” here.



221
222
223
# File 'lib/dommy/node.rb', line 221

def is_equal_node(other)
  Internal::NodeEquality.equal?(self, other)
end

#is_same_node(other) ⇒ Object

Node.isSameNode — strict reference identity (deprecated alias for ‘===`).



226
227
228
# File 'lib/dommy/node.rb', line 226

def is_same_node(other)
  equal?(other)
end

#lookup_namespace_uri(prefix) ⇒ Object

Node.lookupNamespaceURI(prefix) — the namespace bound to ‘prefix` (or the default namespace for a null/empty prefix) in this node’s scope, walking up the element ancestors’ namespace declarations. HTML elements default to the XHTML namespace.



285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/dommy/node.rb', line 285

def lookup_namespace_uri(prefix)
  wanted = namespace_prefix_arg(prefix)
  nk = nearest_namespaceable_node
  while nk.respond_to?(:element?) && nk.element?
    nk.namespace_definitions.each do |d|
      return d.href if normalize_ns_prefix(d.prefix) == wanted
    end
    return nk.namespace ? nk.namespace.href : HTML_NAMESPACE if wanted.nil?

    nk = nk.parent
  end
  nil
end

#lookup_prefix(namespace) ⇒ Object

Node.lookupPrefix(namespace) — a prefix bound to ‘namespace`, or null for the default namespace.



301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/dommy/node.rb', line 301

def lookup_prefix(namespace)
  ns = namespace.to_s
  return nil if ns.empty?

  nk = nearest_namespaceable_node
  while nk.respond_to?(:element?) && nk.element?
    nk.namespace_definitions.each do |d|
      return d.prefix if d.href == ns && d.prefix
    end
    nk = nk.parent
  end
  nil
end