Class: Ast::Merge::PartialTemplateMergerBase Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/ast/merge/partial_template_merger_base.rb

Overview

This class is abstract.

Subclass and implement parser-specific methods

Base class for merging a partial template into a specific section of a destination document.

Unlike the full SmartMerger which merges entire documents, PartialTemplateMergerBase:

  1. Finds a specific section in the destination (using InjectionPoint)
  2. Replaces/merges only that section with the template
  3. Leaves the rest of the destination unchanged

This is an abstract base class. Subclasses must implement:

  • #create_analysis(content) - Create a FileAnalysis for the given content
  • #create_smart_merger(template, section) - Create a SmartMerger for the section merge
  • #find_section_end(statements, injection_point) - Find where the section ends
  • #node_to_text(node, analysis) - Convert a node to source text

See Also:

  • For markdown implementation

Defined Under Namespace

Classes: Result

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(template:, destination:, anchor:, boundary: nil, preference: :template, add_missing: true, when_missing: :skip, replace_mode: false, signature_generator: nil, node_typing: nil, match_refiner: nil) ⇒ PartialTemplateMergerBase

Initialize a PartialTemplateMergerBase.

Parameters:

  • template (String)

    The template content (the section to merge in)

  • destination (String)

    The destination content

  • anchor (Hash)

    Anchor matcher: { type: :heading, text: /pattern/ }

  • boundary (Hash, nil) (defaults to: nil)

    Boundary matcher (defaults to same type as anchor)

  • preference (Symbol, Hash) (defaults to: :template)

    Which content wins (:template, :destination, or per-type hash)

  • add_missing (Boolean, Proc) (defaults to: true)

    Whether to add template nodes not in destination

  • when_missing (Symbol) (defaults to: :skip)

    What to do if section not found (:skip, :append, :prepend)

  • replace_mode (Boolean) (defaults to: false)

    If true, template replaces section entirely (no merge)

  • signature_generator (Proc, nil) (defaults to: nil)

    Custom signature generator for SmartMerger

  • node_typing (Hash, nil) (defaults to: nil)

    Node typing configuration for per-type preferences

  • match_refiner (Object, nil) (defaults to: nil)

    Match refiner for fuzzy matching (e.g., ContentMatchRefiner)



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ast/merge/partial_template_merger_base.rb', line 100

def initialize(
  template:,
  destination:,
  anchor:,
  boundary: nil,
  preference: :template,
  add_missing: true,
  when_missing: :skip,
  replace_mode: false,
  signature_generator: nil,
  node_typing: nil,
  match_refiner: nil
)
  @template = template
  @destination = destination
  @anchor = normalize_matcher(anchor)
  @boundary = boundary ? normalize_matcher(boundary) : nil
  @preference = preference
  @add_missing = add_missing
  @when_missing = when_missing
  @replace_mode = replace_mode
  @signature_generator = signature_generator
  @node_typing = node_typing
  @match_refiner = match_refiner
end

Instance Attribute Details

#add_missingBoolean, Proc (readonly)

Returns Whether to add template-only nodes.

Returns:

  • (Boolean, Proc)

    Whether to add template-only nodes



73
74
75
# File 'lib/ast/merge/partial_template_merger_base.rb', line 73

def add_missing
  @add_missing
end

#anchorHash (readonly)

Returns Anchor matcher configuration.

Returns:

  • (Hash)

    Anchor matcher configuration



64
65
66
# File 'lib/ast/merge/partial_template_merger_base.rb', line 64

def anchor
  @anchor
end

#boundaryHash? (readonly)

Returns Boundary matcher configuration.

Returns:

  • (Hash, nil)

    Boundary matcher configuration



67
68
69
# File 'lib/ast/merge/partial_template_merger_base.rb', line 67

def boundary
  @boundary
end

#destinationString (readonly)

Returns The destination content.

Returns:

  • (String)

    The destination content



61
62
63
# File 'lib/ast/merge/partial_template_merger_base.rb', line 61

def destination
  @destination
end

#match_refinerObject? (readonly)

Returns Match refiner for fuzzy matching unmatched nodes.

Returns:

  • (Object, nil)

    Match refiner for fuzzy matching unmatched nodes



85
86
87
# File 'lib/ast/merge/partial_template_merger_base.rb', line 85

def match_refiner
  @match_refiner
end

#node_typingHash? (readonly)

Returns Node typing configuration for per-type preferences.

Returns:

  • (Hash, nil)

    Node typing configuration for per-type preferences



82
83
84
# File 'lib/ast/merge/partial_template_merger_base.rb', line 82

def node_typing
  @node_typing
end

#preferenceSymbol, Hash (readonly)

Returns Merge preference (:template, :destination, or per-type hash).

Returns:

  • (Symbol, Hash)

    Merge preference (:template, :destination, or per-type hash)



70
71
72
# File 'lib/ast/merge/partial_template_merger_base.rb', line 70

def preference
  @preference
end

#signature_generatorProc? (readonly)

Returns Custom signature generator for node matching.

Returns:

  • (Proc, nil)

    Custom signature generator for node matching



79
80
81
# File 'lib/ast/merge/partial_template_merger_base.rb', line 79

def signature_generator
  @signature_generator
end

#templateString (readonly)

Returns The template content (the section to inject).

Returns:

  • (String)

    The template content (the section to inject)



58
59
60
# File 'lib/ast/merge/partial_template_merger_base.rb', line 58

def template
  @template
end

#when_missingSymbol (readonly)

Returns What to do when section not found (:skip, :append, :prepend).

Returns:

  • (Symbol)

    What to do when section not found (:skip, :append, :prepend)



76
77
78
# File 'lib/ast/merge/partial_template_merger_base.rb', line 76

def when_missing
  @when_missing
end

Instance Method Details

#mergeResult

Perform the partial template merge.

Returns:

  • (Result)

    The merge result



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/ast/merge/partial_template_merger_base.rb', line 129

def merge
  # Parse destination and find injection point
  d_analysis = create_analysis(destination)
  d_statements = Navigable::Statement.build_list(d_analysis.statements)

  finder = Navigable::InjectionPointFinder.new(d_statements)
  injection_point = finder.find(
    type: anchor[:type],
    text: anchor[:text],
    position: :replace,
    boundary_type: boundary&.dig(:type),
    boundary_text: boundary&.dig(:text),
    boundary_same_or_shallower: boundary&.dig(:same_or_shallower) || false,
  )

  if injection_point.nil?
    return handle_missing_section(d_analysis)
  end

  # Found the section - now merge
  perform_section_merge(d_analysis, d_statements, injection_point)
end