Class: Markdown::Merge::OutputBuilder
- Inherits:
-
Object
- Object
- Markdown::Merge::OutputBuilder
- Defined in:
- lib/markdown/merge/output_builder.rb
Overview
Builds markdown output from merge operations.
Handles markdown-specific concerns like:
- Extracting source from original nodes
- Reconstructing consumed link reference definitions
- Preserving gap lines (blank line spacing)
- Automatic structural spacing (blank lines between tables, headings, etc.)
- Assembling final merged content
Unlike Emitter classes used in JSON/YAML/etc, OutputBuilder focuses on source preservation and reconstruction rather than generation from scratch.
Instance Method Summary collapse
-
#add_gap_line(count: 1) ⇒ Object
Add gap lines (blank line preservation).
-
#add_link_definition(node) ⇒ Object
Add a reconstructed link definition.
-
#add_node_source(node, analysis) ⇒ Object
Add a node's source content.
-
#add_raw(text) ⇒ Object
Add raw text content.
-
#blank_line_terminated? ⇒ Boolean
Check whether the current output already ends with a blank-line separator.
-
#clear ⇒ Object
Clear all content.
-
#empty? ⇒ Boolean
Check if builder has any content.
-
#initialize(preserve_formatting: true, auto_spacing: true) ⇒ OutputBuilder
constructor
Initialize a new OutputBuilder.
-
#to_s ⇒ String
Get final content.
Constructor Details
#initialize(preserve_formatting: true, auto_spacing: true) ⇒ OutputBuilder
Initialize a new OutputBuilder
28 29 30 31 32 33 34 35 36 |
# File 'lib/markdown/merge/output_builder.rb', line 28 def initialize(preserve_formatting: true, auto_spacing: true) @parts = [] @length = 0 @preserve_formatting = preserve_formatting @auto_spacing = auto_spacing @last_node_type = nil # Track previous node type for spacing decisions @last_end_line = nil # Track previous node's end line for adjacency detection @last_analysis = nil # Track previous node's analysis for same-source detection end |
Instance Method Details
#add_gap_line(count: 1) ⇒ Object
Add gap lines (blank line preservation)
91 92 93 |
# File 'lib/markdown/merge/output_builder.rb', line 91 def add_gap_line(count: 1) append_part("\n" * count) if count > 0 end |
#add_link_definition(node) ⇒ Object
Add a reconstructed link definition
83 84 85 86 |
# File 'lib/markdown/merge/output_builder.rb', line 83 def add_link_definition(node) formatted = LinkDefinitionFormatter.format(node) append_part(formatted) if formatted && !formatted.empty? end |
#add_node_source(node, analysis) ⇒ Object
Add a node's source content
Automatically inserts structural blank lines when transitioning between certain node types (tables, headings, code blocks, etc.) if auto_spacing is enabled. Skips auto-spacing when nodes are adjacent in the same source — the original formatting is preserved by the source extraction.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/markdown/merge/output_builder.rb', line 47 def add_node_source(node, analysis) # Determine node type for spacing decisions current_type = MarkdownStructure.node_type(node) # Auto-spacing logic: # - Skip for gap_line and freeze_block (they handle their own spacing) # - Skip if last node was a gap_line (we already have spacing) # - Skip if nodes are adjacent in the same source (original spacing is correct) # - Otherwise, check MarkdownStructure.needs_blank_between? which handles # contiguous types (like link_definitions that shouldn't have blanks between them) # Skip auto-spacing when nodes are adjacent lines in the same source. # The original source formatting is correct — no blank line was there. if !(%i[gap_line freeze_block].include?(current_type) || @last_node_type == :gap_line) && @auto_spacing && @last_node_type && current_type && MarkdownStructure.needs_blank_between?(@last_node_type, current_type) && !same_source_adjacent?( node, analysis ) && !(@parts.empty? || blank_line_terminated?) # Only add spacing if we don't already have adequate blank lines # Check the last part to see if it already ends with blank line(s) add_gap_line(count: 1) end content = extract_source(node, analysis) return unless content && !content.empty? range = append_part(content) # Update last node type (track all node types for proper spacing) @last_node_type = current_type @last_end_line = node_end_line(node) @last_analysis = analysis range end |
#add_raw(text) ⇒ Object
Add raw text content
98 99 100 |
# File 'lib/markdown/merge/output_builder.rb', line 98 def add_raw(text) append_part(text) if text && !text.empty? end |
#blank_line_terminated? ⇒ Boolean
Check whether the current output already ends with a blank-line separator.
This looks across part boundaries so a trailing blank line represented as separate content + gap parts still counts as an existing separator.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/markdown/merge/output_builder.rb', line 122 def blank_line_terminated? trailing_newlines = 0 @parts.reverse_each do |part| next if part.nil? || part.empty? idx = part.length - 1 while idx >= 0 && part[idx] == "\n" trailing_newlines += 1 idx -= 1 end break if idx >= 0 end trailing_newlines >= 2 end |
#clear ⇒ Object
Clear all content
141 142 143 144 |
# File 'lib/markdown/merge/output_builder.rb', line 141 def clear @parts.clear @length = 0 end |
#empty? ⇒ Boolean
Check if builder has any content
112 113 114 |
# File 'lib/markdown/merge/output_builder.rb', line 112 def empty? @parts.empty? end |
#to_s ⇒ String
Get final content
105 106 107 |
# File 'lib/markdown/merge/output_builder.rb', line 105 def to_s @parts.join end |