Module: Coradoc::Reference::EdgeSearch

Defined in:
lib/coradoc/reference/edge_search.rb

Overview

Walks a CoreModel tree and yields every Edge found in it. For Phase 1, Edges are wrapped inside existing node types — CrossReferenceElement, LinkElement, Image, Include, FootnoteElement. The Phase 3 migration will move Edges to first-class attributes; this module abstracts the extraction so the rest of the resolver doesn't change.

The walker is read-only: it never mutates the input tree.

Class Method Summary collapse

Class Method Details

.each_edge(root) ⇒ Object

Yields (parent_node, edge) for every Edge found in the tree. The parent_node is the node that owns the edge — the materializer replaces the edge in-place inside parent_node's children list.



20
21
22
23
24
# File 'lib/coradoc/reference/edge_search.rb', line 20

def each_edge(root)
  return to_enum(:each_edge, root) unless block_given?

  walk(root) { |node| edges_for(node).each { |edge| yield node, edge } }
end

.edge_from_cross_reference(node) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/coradoc/reference/edge_search.rb', line 49

def edge_from_cross_reference(node)
  Edge.build(
    kind: :navigation,
    address: parse_address(node.target, hint: xref_hint(node.target)),
    source_id: node.id,
    label: node.content
  )
end

.edge_from_footnote(node) ⇒ Object



86
87
88
89
90
91
92
93
# File 'lib/coradoc/reference/edge_search.rb', line 86

def edge_from_footnote(node)
  Edge.build(
    kind: :footnote_ref,
    address: parse_address(node.target || node.id, hint: :anchor),
    source_id: node.id,
    options: { footnote_id: node.id }
  )
end

.edge_from_image(node) ⇒ Object



76
77
78
79
80
81
82
83
84
# File 'lib/coradoc/reference/edge_search.rb', line 76

def edge_from_image(node)
  Edge.build(
    kind: :image_ref,
    address: parse_address(node.src, hint: path_or_url_hint(node.src)),
    source_id: node.id,
    label: node.alt,
    options: { alt_text: node.alt }
  )
end

.edge_from_include(node) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/coradoc/reference/edge_search.rb', line 67

def edge_from_include(node)
  Edge.build(
    kind: :include,
    address: parse_address(node.target, hint: path_or_url_hint(node.target)),
    source_id: node.id,
    options: { include_options: node.options }
  )
end


58
59
60
61
62
63
64
65
# File 'lib/coradoc/reference/edge_search.rb', line 58

def edge_from_link(node)
  Edge.build(
    kind: :link,
    address: parse_address(node.target),
    source_id: node.id,
    label: node.content
  )
end

.edges_for(node) ⇒ Object

Extract every Edge the given node owns. Pure function of node.



41
42
43
44
45
46
47
# File 'lib/coradoc/reference/edge_search.rb', line 41

def edges_for(node)
  edge_extractor = EDGE_EXTRACTORS[node.class]
  return [] unless edge_extractor

  edge = edge_extractor.call(node)
  edge ? [edge] : []
end

.parse_address(target, hint: nil) ⇒ Object



114
115
116
# File 'lib/coradoc/reference/edge_search.rb', line 114

def parse_address(target, hint: nil)
  Coradoc::Reference::Address.parse(target.to_s, hint: hint)
end

.path_or_url_hint(target) ⇒ Object

File-like targets (include, image): URLs stay urls, everything else is a path — including bare filenames ("foo.png") that the anchor bareword heuristic would otherwise claim.



110
111
112
# File 'lib/coradoc/reference/edge_search.rb', line 110

def path_or_url_hint(target)
  Coradoc::Reference::Address::Url.matches?(target.to_s) ? :url : :path
end

.walk(node) {|node| ... } ⇒ Object

Walk tree, yield each Base node. Stops at inline leaves.

Yields:

  • (node)


27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/coradoc/reference/edge_search.rb', line 27

def walk(node, &block)
  return unless node.is_a?(Coradoc::CoreModel::Base)
  return unless block

  yield(node)
  return unless node.is_a?(Coradoc::CoreModel::HasChildren)

  children = node.children
  return unless children

  children.each { |child| walk(child, &block) }
end

.xref_hint(target) ⇒ Object

Xrefs are document-internal by definition (AsciiDoc): bare targets are anchors, even uppercase document-ID-shaped ones ("SEC-2"). Only an explicit "document#fragment" shape or a URL points outside the current document.



99
100
101
102
103
104
105
# File 'lib/coradoc/reference/edge_search.rb', line 99

def xref_hint(target)
  raw = target.to_s
  return :url if Coradoc::Reference::Address::Url.matches?(raw)
  return :path if raw.include?('#') && !raw.start_with?('#')

  :anchor
end