Class: Coradoc::Mirror::MirrorToCoreModel

Inherits:
Object
  • Object
show all
Defined in:
lib/coradoc/mirror/mirror_to_core_model.rb

Overview

Transforms ProseMirror-compatible Mirror nodes back into CoreModel.

Dispatch is delegated to ReverseBuilder (node-level) and MarkReverseBuilder (mark-level) — adding a new node or mark type is done by registering a new Builder class, with no edit to this file (OCP). ReverseBuilder and MarkReverseBuilder are autoloaded from coradoc/mirror.rb; referencing them here triggers load of the registry files, which is where the built-in builders self-register.

Instance Method Summary collapse

Instance Method Details

#apply_mark(inner, mark) ⇒ Object

Mark dispatch goes through MarkReverseBuilder so adding a new mark type is purely additive (OCP parity with node dispatch). Unknown marks pass inner through unchanged.



62
63
64
65
66
67
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 62

def apply_mark(inner, mark)
  builder_class = MarkReverseBuilder.lookup(mark.type)
  return inner unless builder_class

  builder_class.new.build(inner, mark)
end

#build_content(node) ⇒ Object

── Shared helpers (single source of truth — used by every ReverseBuilder::Base subclass via delegation) ──



48
49
50
51
52
53
54
55
56
57
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 48

def build_content(node)
  return [] unless node.content

  node.content.flat_map do |child|
    result = build_node(child)
    next [] if result.nil?

    result.is_a?(Array) ? result : [result]
  end
end

#build_inline_children(node) ⇒ Object



69
70
71
72
73
74
75
76
77
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 69

def build_inline_children(node)
  return [] unless node.content

  node.content.filter_map do |child|
    next unless child.is_a?(Node)

    build_node(child)
  end
end

#build_node(node) ⇒ Object

Raises:



18
19
20
21
22
23
24
25
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 18

def build_node(node)
  builder_class = ReverseBuilder.lookup(node.type)
  raise Error, "Unknown mirror node type: #{node.type}" unless builder_class

  result = builder_class.new(self).build(node)
  propagate_source_line(result, node)
  result
end

#call(mirror_node) ⇒ Object



14
15
16
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 14

def call(mirror_node)
  build_node(mirror_node)
end

#extract_text(node) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 79

def extract_text(node)
  return node.text.to_s if node.is_a?(Node::Text)
  return '' unless node.content

  node.content.filter_map do |child|
    child.is_a?(Node) ? extract_text(child) : ''
  end.join
end

#inline_content(element) ⇒ Object



88
89
90
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 88

def inline_content(element)
  element.is_a?(CoreModel::InlineElement) ? element.content : element.to_s
end

#propagate_source_line(result, node) ⇒ Object

Copy parser-attached source_line from the Mirror node onto every CoreModel node the builder produced. Single touchpoint for the entire Mirror → CoreModel direction — builders stay focused on per-type mapping and don't repeat this concern (DRY).



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/coradoc/mirror/mirror_to_core_model.rb', line 31

def propagate_source_line(result, node)
  return unless node.is_a?(Node)

  line = node.source_line
  return unless line

  Array(result).each do |built|
    next unless built.is_a?(CoreModel::Base)
    next if built.source_line

    built.source_line = line
  end
end