Class: Coradoc::Mirror::CoreModelToMirror
- Inherits:
-
Object
- Object
- Coradoc::Mirror::CoreModelToMirror
- Defined in:
- lib/coradoc/mirror/core_model_to_mirror.rb
Overview
Transforms CoreModel documents into ProseMirror-compatible Mirror nodes.
Uses a HandlerRegistry for OCP-compliant dispatch: each CoreModel type maps to a handler module/class that produces the corresponding Mirror node.
Defined Under Namespace
Classes: FootnoteData
Constant Summary collapse
- COLLECTION_ACCESSORS =
Maps element types to their children accessors.
{ CoreModel::ListBlock => :items, CoreModel::DefinitionList => :items, CoreModel::Table => :rows, CoreModel::Bibliography => :entries }.freeze
Instance Attribute Summary collapse
-
#partition_structural ⇒ Object
Read by Handlers::Structural.section to decide whether to emit generic ‘section` (legacy) or a JS SECTION_TYPE (`clause`, `annex`, etc.) when partition_structural mode is on.
-
#registry ⇒ Object
readonly
Returns the value of attribute registry.
Instance Method Summary collapse
- #call(document, partition_structural: false) ⇒ Object
- #extract_content(element) ⇒ Object
- #flush_footnotes ⇒ Object
-
#initialize(registry: Coradoc::Mirror.default_registry) ⇒ CoreModelToMirror
constructor
A new instance of CoreModelToMirror.
- #process_inline_content(element) ⇒ Object
- #register_footnote(footnote) ⇒ Object
- #resolve_footnote_reference(ref) ⇒ Object
- #text_node(text, marks: []) ⇒ Object
-
#wrap_structural(children) ⇒ Object
Partitions flat doc children into [*metadata, preface?, sections?, *bibliography, *trailing] per the @metanorma/mirror JS structural contract.
Constructor Details
#initialize(registry: Coradoc::Mirror.default_registry) ⇒ CoreModelToMirror
Returns a new instance of CoreModelToMirror.
23 24 25 26 27 28 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 23 def initialize(registry: Coradoc::Mirror.default_registry) @registry = registry @footnote_counter = 0 @footnotes = [] @partition_structural = false end |
Instance Attribute Details
#partition_structural ⇒ Object
Read by Handlers::Structural.section to decide whether to emit generic ‘section` (legacy) or a JS SECTION_TYPE (`clause`, `annex`, etc.) when partition_structural mode is on.
33 34 35 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 33 def partition_structural @partition_structural end |
#registry ⇒ Object (readonly)
Returns the value of attribute registry.
10 11 12 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 10 def registry @registry end |
Instance Method Details
#call(document, partition_structural: false) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 35 def call(document, partition_structural: false) @footnote_counter = 0 @footnotes = [] @partition_structural = partition_structural content = extract_content(document) fn_block = flush_footnotes content << fn_block if fn_block attrs = build_document_attrs(document) Node::Document.new( attrs: Node::Document::Attrs.new(title: attrs[:title], id: attrs[:id]), content: partition_structural ? wrap_structural(content) : content ) end |
#extract_content(element) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 69 def extract_content(element) children = element_children(element) if children && !children.empty? content = [] children.each { |child| handle_element(child, content) } content.compact elsif element_has_text_content?(element) process_inline_content(element) else [] end end |
#flush_footnotes ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 126 def flush_footnotes return nil if @footnotes.empty? entries = @footnotes.map do |fn| Node::FootnoteEntry.new( attrs: Node::FootnoteEntry::Attrs.new( id: fn.id, ref_id: fn.ref_id, number: fn.number ), content: fn.content ) end @footnotes = [] Node::Footnotes.new(content: entries) end |
#process_inline_content(element) ⇒ Object
83 84 85 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 83 def process_inline_content(element) Handlers::Inline.process(element, context: self) end |
#register_footnote(footnote) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 91 def register_footnote(footnote) @footnote_counter += 1 num = @footnote_counter fn_id = footnote.id || "fn-#{num}" ref_id = "fn-ref-#{num}" fn_content = footnote.content ? [text_node(footnote.content)] : [] @footnotes << FootnoteData.new( id: fn_id, ref_id: ref_id, number: num, content: fn_content ) Node::FootnoteMarker.new( attrs: Node::FootnoteMarker::Attrs.new( id: fn_id, ref_id: ref_id, number: num ) ) end |
#resolve_footnote_reference(ref) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 109 def resolve_footnote_reference(ref) target_id = ref.id entry = @footnotes.find { |fn| fn.id == target_id } if target_id if entry Node::FootnoteMarker.new( attrs: Node::FootnoteMarker::Attrs.new( id: entry.id, ref_id: "fn-ref-#{entry.number}-dup-#{@footnote_counter}", number: entry.number ) ) else text_node("[#{target_id || 'footnote'}]") end end |
#text_node(text, marks: []) ⇒ Object
87 88 89 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 87 def text_node(text, marks: []) Node::Text.new(text: text, marks: marks) end |
#wrap_structural(children) ⇒ Object
Partitions flat doc children into [*metadata, preface?, sections?, *bibliography, *trailing] per the @metanorma/mirror JS structural contract. See Partitioner for the bucketing rules.
Metadata blocks (frontmatter) are prepended verbatim so consumers like FrontmatterQuery can find them by walking content, and renderers can skip them via their type (‘frontmatter’).
58 59 60 61 62 63 64 65 66 67 |
# File 'lib/coradoc/mirror/core_model_to_mirror.rb', line 58 def wrap_structural(children) partitioned = Partitioner.partition(children) wrapped = [] wrapped.concat(partitioned[:metadata]) wrapped << Node::Preamble.new(content: partitioned[:preface]) if partitioned[:preface].any? wrapped << Node::Sections.new(content: partitioned[:sections]) if partitioned[:sections].any? wrapped.concat(partitioned[:bibliography]) wrapped.concat(partitioned[:trailing]) wrapped end |