commonmarker-merge 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +87 -0
- data/CITATION.cff +20 -0
- data/CODE_OF_CONDUCT.md +134 -0
- data/CONTRIBUTING.md +227 -0
- data/FUNDING.md +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +930 -0
- data/REEK +0 -0
- data/RUBOCOP.md +71 -0
- data/SECURITY.md +21 -0
- data/lib/commonmarker/merge/backend.rb +336 -0
- data/lib/commonmarker/merge/debug_logger.rb +26 -0
- data/lib/commonmarker/merge/file_analysis.rb +51 -0
- data/lib/commonmarker/merge/freeze_node.rb +32 -0
- data/lib/commonmarker/merge/smart_merger.rb +139 -0
- data/lib/commonmarker/merge/version.rb +12 -0
- data/lib/commonmarker/merge.rb +108 -0
- data/lib/commonmarker-merge.rb +4 -0
- data/sig/commonmarker/merge/conflict_resolver.rbs +48 -0
- data/sig/commonmarker/merge/debug_logger.rbs +36 -0
- data/sig/commonmarker/merge/file_aligner.rbs +27 -0
- data/sig/commonmarker/merge/file_analysis.rbs +95 -0
- data/sig/commonmarker/merge/freeze_node.rbs +65 -0
- data/sig/commonmarker/merge/merge_result.rbs +59 -0
- data/sig/commonmarker/merge/smart_merger.rbs +53 -0
- data/sig/commonmarker/merge.rbs +223 -0
- data.tar.gz.sig +0 -0
- metadata +331 -0
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Hard dependency - ensures commonmarker gem is installed
|
|
4
|
+
require "commonmarker"
|
|
5
|
+
|
|
6
|
+
# External gems
|
|
7
|
+
require "version_gem"
|
|
8
|
+
|
|
9
|
+
# Shared merge infrastructure (includes tree_haver)
|
|
10
|
+
require "markdown/merge"
|
|
11
|
+
|
|
12
|
+
# This gem
|
|
13
|
+
require_relative "merge/version"
|
|
14
|
+
|
|
15
|
+
module Commonmarker
|
|
16
|
+
# Smart merging for Markdown files using CommonMarker AST.
|
|
17
|
+
#
|
|
18
|
+
# Commonmarker::Merge provides intelligent merging of Markdown files by:
|
|
19
|
+
# - Parsing Markdown into AST using CommonMarker via tree_haver
|
|
20
|
+
# - Matching structural elements (headings, paragraphs, lists, etc.) between files
|
|
21
|
+
# - Preserving frozen sections marked with HTML comments
|
|
22
|
+
# - Resolving conflicts based on configurable preferences
|
|
23
|
+
#
|
|
24
|
+
# This is a thin wrapper around Markdown::Merge that:
|
|
25
|
+
# - Provides hard dependency on the commonmarker gem
|
|
26
|
+
# - Sets commonmarker-specific defaults (freeze token, inner_merge_code_blocks)
|
|
27
|
+
# - Maintains API compatibility for existing users
|
|
28
|
+
#
|
|
29
|
+
# @example Basic merge
|
|
30
|
+
# merger = Commonmarker::Merge::SmartMerger.new(template, destination)
|
|
31
|
+
# result = merger.merge
|
|
32
|
+
# puts result.content if result.success?
|
|
33
|
+
#
|
|
34
|
+
# @example With freeze blocks
|
|
35
|
+
# # In your Markdown file:
|
|
36
|
+
# # <!-- commonmarker-merge:freeze -->
|
|
37
|
+
# # ## Custom Section
|
|
38
|
+
# # This content is preserved during merges.
|
|
39
|
+
# # <!-- commonmarker-merge:unfreeze -->
|
|
40
|
+
#
|
|
41
|
+
# @see SmartMerger Main entry point for merging
|
|
42
|
+
# @see Markdown::Merge::SmartMerger Underlying implementation
|
|
43
|
+
module Merge
|
|
44
|
+
# Base error class for Commonmarker::Merge
|
|
45
|
+
# Inherits from Markdown::Merge::Error for consistency across merge gems.
|
|
46
|
+
class Error < Markdown::Merge::Error; end
|
|
47
|
+
|
|
48
|
+
# Raised when a Markdown file has parsing errors.
|
|
49
|
+
# Inherits from Markdown::Merge::ParseError for consistency across merge gems.
|
|
50
|
+
class ParseError < Markdown::Merge::ParseError; end
|
|
51
|
+
|
|
52
|
+
# Raised when the template file has syntax errors.
|
|
53
|
+
class TemplateParseError < ParseError; end
|
|
54
|
+
|
|
55
|
+
# Raised when the destination file has syntax errors.
|
|
56
|
+
class DestinationParseError < ParseError; end
|
|
57
|
+
|
|
58
|
+
# Default freeze token for commonmarker-merge
|
|
59
|
+
# @return [String]
|
|
60
|
+
DEFAULT_FREEZE_TOKEN = "commonmarker-merge"
|
|
61
|
+
|
|
62
|
+
# Default inner_merge_code_blocks setting for commonmarker-merge
|
|
63
|
+
# @return [Boolean]
|
|
64
|
+
DEFAULT_INNER_MERGE_CODE_BLOCKS = false
|
|
65
|
+
|
|
66
|
+
# Re-export shared classes from markdown-merge
|
|
67
|
+
FileAligner = Markdown::Merge::FileAligner
|
|
68
|
+
ConflictResolver = Markdown::Merge::ConflictResolver
|
|
69
|
+
MergeResult = Markdown::Merge::MergeResult
|
|
70
|
+
TableMatchAlgorithm = Markdown::Merge::TableMatchAlgorithm
|
|
71
|
+
TableMatchRefiner = Markdown::Merge::TableMatchRefiner
|
|
72
|
+
CodeBlockMerger = Markdown::Merge::CodeBlockMerger
|
|
73
|
+
NodeTypeNormalizer = Markdown::Merge::NodeTypeNormalizer
|
|
74
|
+
|
|
75
|
+
autoload :DebugLogger, "commonmarker/merge/debug_logger"
|
|
76
|
+
autoload :FreezeNode, "commonmarker/merge/freeze_node"
|
|
77
|
+
autoload :FileAnalysis, "commonmarker/merge/file_analysis"
|
|
78
|
+
autoload :SmartMerger, "commonmarker/merge/smart_merger"
|
|
79
|
+
autoload :Backend, "commonmarker/merge/backend"
|
|
80
|
+
|
|
81
|
+
class << self
|
|
82
|
+
# Eagerly load and register backend when this module is loaded
|
|
83
|
+
# This ensures the backend is available for tree_haver before any parsing happens
|
|
84
|
+
def ensure_backend_loaded!
|
|
85
|
+
Backend # Access constant to trigger autoload
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Ensure backend is loaded and registered
|
|
92
|
+
Commonmarker::Merge.ensure_backend_loaded!
|
|
93
|
+
|
|
94
|
+
# Register with ast-merge's MergeGemRegistry for RSpec dependency tags
|
|
95
|
+
# Only register if MergeGemRegistry is loaded (i.e., in test environment)
|
|
96
|
+
if defined?(Ast::Merge::RSpec::MergeGemRegistry)
|
|
97
|
+
Ast::Merge::RSpec::MergeGemRegistry.register(
|
|
98
|
+
:commonmarker_merge,
|
|
99
|
+
require_path: "commonmarker/merge",
|
|
100
|
+
merger_class: "Commonmarker::Merge::SmartMerger",
|
|
101
|
+
test_source: "# Test\n\nParagraph",
|
|
102
|
+
category: :markdown,
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
Commonmarker::Merge::Version.class_eval do
|
|
107
|
+
extend VersionGem::Basic
|
|
108
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Type signatures for Commonmarker::Merge::ConflictResolver
|
|
2
|
+
#
|
|
3
|
+
# Resolves conflicts between matching Markdown elements.
|
|
4
|
+
# Determines which version to use based on configured preference.
|
|
5
|
+
|
|
6
|
+
module Commonmarker
|
|
7
|
+
module Merge
|
|
8
|
+
class ConflictResolver
|
|
9
|
+
# Decision constants
|
|
10
|
+
DECISION_DESTINATION: Symbol
|
|
11
|
+
DECISION_TEMPLATE: Symbol
|
|
12
|
+
DECISION_ADDED: Symbol
|
|
13
|
+
DECISION_FROZEN: Symbol
|
|
14
|
+
|
|
15
|
+
# Merge preference
|
|
16
|
+
attr_reader preference: Symbol
|
|
17
|
+
|
|
18
|
+
# Template file analysis
|
|
19
|
+
attr_reader template_analysis: FileAnalysis
|
|
20
|
+
|
|
21
|
+
# Destination file analysis
|
|
22
|
+
attr_reader dest_analysis: FileAnalysis
|
|
23
|
+
|
|
24
|
+
# Initialize a conflict resolver
|
|
25
|
+
def initialize: (
|
|
26
|
+
preference: Symbol,
|
|
27
|
+
template_analysis: FileAnalysis,
|
|
28
|
+
dest_analysis: FileAnalysis
|
|
29
|
+
) -> void
|
|
30
|
+
|
|
31
|
+
# Resolve a conflict between template and destination nodes
|
|
32
|
+
def resolve: (
|
|
33
|
+
untyped template_node,
|
|
34
|
+
untyped dest_node,
|
|
35
|
+
template_index: Integer,
|
|
36
|
+
dest_index: Integer
|
|
37
|
+
) -> Hash[Symbol, untyped]
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# Check if two nodes have identical content
|
|
42
|
+
def content_identical?: (untyped template_node, untyped dest_node) -> bool
|
|
43
|
+
|
|
44
|
+
# Convert a node to its source text
|
|
45
|
+
def node_to_text: (untyped node, FileAnalysis analysis) -> String
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Type signatures for Commonmarker::Merge::DebugLogger
|
|
2
|
+
#
|
|
3
|
+
# Debug logging utility for Commonmarker::Merge operations.
|
|
4
|
+
# Extends Ast::Merge::DebugLogger module.
|
|
5
|
+
|
|
6
|
+
module Commonmarker
|
|
7
|
+
module Merge
|
|
8
|
+
module DebugLogger
|
|
9
|
+
# Configured environment variable name
|
|
10
|
+
def self.env_var_name: () -> String
|
|
11
|
+
def self.env_var_name=: (String) -> String
|
|
12
|
+
|
|
13
|
+
# Configured log prefix
|
|
14
|
+
def self.log_prefix: () -> String
|
|
15
|
+
def self.log_prefix=: (String) -> String
|
|
16
|
+
|
|
17
|
+
# Check if debug mode is enabled
|
|
18
|
+
def self.enabled?: () -> bool
|
|
19
|
+
|
|
20
|
+
# Log a debug message with optional context
|
|
21
|
+
def self.debug: (String message, ?Hash[Symbol, untyped] context) -> void
|
|
22
|
+
|
|
23
|
+
# Log an info message
|
|
24
|
+
def self.info: (String message) -> void
|
|
25
|
+
|
|
26
|
+
# Log a warning message
|
|
27
|
+
def self.warning: (String message) -> void
|
|
28
|
+
|
|
29
|
+
# Time a block and log the duration
|
|
30
|
+
def self.time: [T] (String operation) { () -> T } -> T
|
|
31
|
+
|
|
32
|
+
# Extract node information for logging
|
|
33
|
+
def self.extract_node_info: (untyped node) -> Hash[Symbol, untyped]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Type signatures for Commonmarker::Merge::FileAligner
|
|
2
|
+
#
|
|
3
|
+
# Aligns Markdown block elements between template and destination files.
|
|
4
|
+
# Uses structural signatures to match elements.
|
|
5
|
+
|
|
6
|
+
module Commonmarker
|
|
7
|
+
module Merge
|
|
8
|
+
class FileAligner
|
|
9
|
+
# Template file analysis
|
|
10
|
+
attr_reader template_analysis: FileAnalysis
|
|
11
|
+
|
|
12
|
+
# Destination file analysis
|
|
13
|
+
attr_reader dest_analysis: FileAnalysis
|
|
14
|
+
|
|
15
|
+
# Initialize a file aligner
|
|
16
|
+
def initialize: (FileAnalysis template_analysis, FileAnalysis dest_analysis) -> void
|
|
17
|
+
|
|
18
|
+
# Perform alignment between template and destination statements
|
|
19
|
+
def align: () -> Array[Hash[Symbol, untyped]]
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# Build a map from signatures to statement indices
|
|
24
|
+
def build_signature_map: (Array[untyped] statements, FileAnalysis analysis) -> Hash[Array[untyped], Array[Integer]]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Type signatures for Commonmarker::Merge::FileAnalysis
|
|
2
|
+
#
|
|
3
|
+
# File analysis for Markdown files using CommonMarker.
|
|
4
|
+
# Parses Markdown and extracts block elements and freeze blocks.
|
|
5
|
+
|
|
6
|
+
module Commonmarker
|
|
7
|
+
module Merge
|
|
8
|
+
class FileAnalysis
|
|
9
|
+
# Default freeze token for identifying freeze blocks
|
|
10
|
+
DEFAULT_FREEZE_TOKEN: String
|
|
11
|
+
|
|
12
|
+
# The root document node
|
|
13
|
+
attr_reader document: untyped
|
|
14
|
+
|
|
15
|
+
# Source Markdown content
|
|
16
|
+
attr_reader source: String
|
|
17
|
+
|
|
18
|
+
# Lines of source code
|
|
19
|
+
attr_reader lines: Array[String]
|
|
20
|
+
|
|
21
|
+
# Token used to mark freeze blocks
|
|
22
|
+
attr_reader freeze_token: String
|
|
23
|
+
|
|
24
|
+
# Custom signature generator
|
|
25
|
+
attr_reader signature_generator: (^(untyped) -> (Array[untyped] | nil | untyped))?
|
|
26
|
+
|
|
27
|
+
# All statements (nodes and freeze blocks)
|
|
28
|
+
attr_reader statements: Array[untyped]
|
|
29
|
+
|
|
30
|
+
# Initialize file analysis
|
|
31
|
+
def initialize: (
|
|
32
|
+
String source,
|
|
33
|
+
?freeze_token: String,
|
|
34
|
+
?signature_generator: (^(untyped) -> (Array[untyped] | nil | untyped))?,
|
|
35
|
+
?options: Hash[Symbol, untyped]
|
|
36
|
+
) -> void
|
|
37
|
+
|
|
38
|
+
# Check if parse was successful
|
|
39
|
+
def valid?: () -> bool
|
|
40
|
+
|
|
41
|
+
# Get freeze blocks
|
|
42
|
+
def freeze_blocks: () -> Array[FreezeNode]
|
|
43
|
+
|
|
44
|
+
# Get a specific line (1-indexed)
|
|
45
|
+
def line_at: (Integer line_number) -> String?
|
|
46
|
+
|
|
47
|
+
# Get a normalized line
|
|
48
|
+
def normalized_line: (Integer line_number) -> String?
|
|
49
|
+
|
|
50
|
+
# Get signature at index
|
|
51
|
+
def signature_at: (Integer index) -> Array[untyped]?
|
|
52
|
+
|
|
53
|
+
# Generate signature for a node
|
|
54
|
+
def generate_signature: (untyped node) -> Array[untyped]?
|
|
55
|
+
|
|
56
|
+
# Compute default signature for a node
|
|
57
|
+
def compute_node_signature: (untyped node) -> Array[untyped]?
|
|
58
|
+
|
|
59
|
+
# Compute signature for CommonMarker node
|
|
60
|
+
def compute_commonmarker_signature: (untyped node) -> Array[untyped]?
|
|
61
|
+
|
|
62
|
+
# Extract all text content from a node
|
|
63
|
+
def extract_text_content: (untyped node) -> String
|
|
64
|
+
|
|
65
|
+
# Get source text for a range of lines
|
|
66
|
+
def source_range: (Integer start_line, Integer end_line) -> String
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
# Count children of a node
|
|
71
|
+
def count_children: (untyped node) -> Integer
|
|
72
|
+
|
|
73
|
+
# Get node name
|
|
74
|
+
def node_name: (untyped node) -> String?
|
|
75
|
+
|
|
76
|
+
# Extract all nodes and integrate freeze blocks
|
|
77
|
+
def extract_and_integrate_all_nodes: () -> Array[untyped]
|
|
78
|
+
|
|
79
|
+
# Collect top-level nodes from document
|
|
80
|
+
def collect_top_level_nodes: () -> Array[untyped]
|
|
81
|
+
|
|
82
|
+
# Find freeze markers in source
|
|
83
|
+
def find_freeze_markers: () -> Array[Hash[Symbol, untyped]]
|
|
84
|
+
|
|
85
|
+
# Build freeze blocks from markers
|
|
86
|
+
def build_freeze_blocks: (Array[Hash[Symbol, untyped]] markers) -> Array[FreezeNode]
|
|
87
|
+
|
|
88
|
+
# Create a freeze block from start and end markers
|
|
89
|
+
def create_freeze_block: (Hash[Symbol, untyped] start_marker, Hash[Symbol, untyped] end_marker) -> FreezeNode
|
|
90
|
+
|
|
91
|
+
# Integrate nodes with freeze blocks
|
|
92
|
+
def integrate_nodes_with_freeze_blocks: (Array[FreezeNode] freeze_blocks) -> Array[untyped]
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Type signatures for Commonmarker::Merge::FreezeNode
|
|
2
|
+
#
|
|
3
|
+
# Represents a frozen block of Markdown content that should be
|
|
4
|
+
# preserved during merges. Marked with HTML comments.
|
|
5
|
+
|
|
6
|
+
module Commonmarker
|
|
7
|
+
module Merge
|
|
8
|
+
class FreezeNode < Ast::Merge::FreezeNode
|
|
9
|
+
# Regex pattern for HTML comment freeze markers
|
|
10
|
+
HTML_COMMENT_PATTERN: Regexp
|
|
11
|
+
|
|
12
|
+
# Build regex pattern for freeze markers
|
|
13
|
+
def self.pattern_for: (Symbol pattern_type, ?String? token) -> Regexp
|
|
14
|
+
|
|
15
|
+
# Start line number (1-indexed)
|
|
16
|
+
attr_reader start_line: Integer
|
|
17
|
+
|
|
18
|
+
# End line number (1-indexed)
|
|
19
|
+
attr_reader end_line: Integer
|
|
20
|
+
|
|
21
|
+
# Raw Markdown content within the freeze block
|
|
22
|
+
attr_reader content: String
|
|
23
|
+
|
|
24
|
+
# The start marker comment
|
|
25
|
+
attr_reader start_marker: String
|
|
26
|
+
|
|
27
|
+
# The end marker comment
|
|
28
|
+
attr_reader end_marker: String
|
|
29
|
+
|
|
30
|
+
# Parsed nodes within the freeze block
|
|
31
|
+
attr_reader nodes: Array[untyped]
|
|
32
|
+
|
|
33
|
+
# Initialize a new FreezeNode
|
|
34
|
+
def initialize: (
|
|
35
|
+
start_line: Integer,
|
|
36
|
+
end_line: Integer,
|
|
37
|
+
content: String,
|
|
38
|
+
start_marker: String,
|
|
39
|
+
end_marker: String,
|
|
40
|
+
?nodes: Array[untyped],
|
|
41
|
+
?reason: String?
|
|
42
|
+
) -> void
|
|
43
|
+
|
|
44
|
+
# Generate a signature for matching this freeze block
|
|
45
|
+
def signature: () -> Array[Symbol | String]
|
|
46
|
+
|
|
47
|
+
# Get the full text including markers
|
|
48
|
+
def full_text: () -> String
|
|
49
|
+
|
|
50
|
+
# Get line count of the freeze block
|
|
51
|
+
def line_count: () -> Integer
|
|
52
|
+
|
|
53
|
+
# Check if block contains a specific node type
|
|
54
|
+
def contains_type?: (Symbol `type`) -> bool
|
|
55
|
+
|
|
56
|
+
# String representation for debugging
|
|
57
|
+
def inspect: () -> String
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# Extract reason from the start marker comment
|
|
62
|
+
def extract_reason_from_marker: (String? marker) -> String?
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Type signatures for Commonmarker::Merge::MergeResult
|
|
2
|
+
#
|
|
3
|
+
# Represents the result of a Markdown merge operation.
|
|
4
|
+
# Contains merged content and metadata about the operation.
|
|
5
|
+
|
|
6
|
+
module Commonmarker
|
|
7
|
+
module Merge
|
|
8
|
+
class MergeResult < Ast::Merge::MergeResult
|
|
9
|
+
# The merged Markdown content
|
|
10
|
+
attr_reader content: String?
|
|
11
|
+
|
|
12
|
+
# List of conflicts encountered during merge
|
|
13
|
+
attr_reader conflicts: Array[Hash[Symbol, untyped]]
|
|
14
|
+
|
|
15
|
+
# List of frozen blocks preserved during merge
|
|
16
|
+
attr_reader frozen_blocks: Array[Hash[Symbol, untyped]]
|
|
17
|
+
|
|
18
|
+
# Statistics about the merge operation
|
|
19
|
+
attr_reader stats: Hash[Symbol, untyped]
|
|
20
|
+
|
|
21
|
+
# Initialize a new MergeResult
|
|
22
|
+
def initialize: (
|
|
23
|
+
content: String?,
|
|
24
|
+
?conflicts: Array[Hash[Symbol, untyped]],
|
|
25
|
+
?frozen_blocks: Array[Hash[Symbol, untyped]],
|
|
26
|
+
?stats: Hash[Symbol, untyped]
|
|
27
|
+
) -> void
|
|
28
|
+
|
|
29
|
+
# Check if merge was successful
|
|
30
|
+
def success?: () -> bool
|
|
31
|
+
|
|
32
|
+
# Check if there are unresolved conflicts
|
|
33
|
+
def conflicts?: () -> bool
|
|
34
|
+
|
|
35
|
+
# Check if any frozen blocks were preserved
|
|
36
|
+
def has_frozen_blocks?: () -> bool
|
|
37
|
+
|
|
38
|
+
# Get count of nodes added during merge
|
|
39
|
+
def nodes_added: () -> Integer
|
|
40
|
+
|
|
41
|
+
# Get count of nodes removed during merge
|
|
42
|
+
def nodes_removed: () -> Integer
|
|
43
|
+
|
|
44
|
+
# Get count of nodes modified during merge
|
|
45
|
+
def nodes_modified: () -> Integer
|
|
46
|
+
|
|
47
|
+
# Get count of frozen blocks preserved
|
|
48
|
+
def frozen_count: () -> Integer
|
|
49
|
+
|
|
50
|
+
# String representation for debugging
|
|
51
|
+
def inspect: () -> String
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# Default statistics hash
|
|
56
|
+
def default_stats: () -> Hash[Symbol, untyped]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Type signatures for Commonmarker::Merge::SmartMerger
|
|
2
|
+
#
|
|
3
|
+
# Orchestrates the smart merge process for Markdown files.
|
|
4
|
+
# Main entry point for intelligent Markdown merging.
|
|
5
|
+
|
|
6
|
+
module Commonmarker
|
|
7
|
+
module Merge
|
|
8
|
+
class SmartMerger
|
|
9
|
+
# Analysis of the template file
|
|
10
|
+
attr_reader template_analysis: FileAnalysis
|
|
11
|
+
|
|
12
|
+
# Analysis of the destination file
|
|
13
|
+
attr_reader dest_analysis: FileAnalysis
|
|
14
|
+
|
|
15
|
+
# Aligner for finding matches and differences
|
|
16
|
+
attr_reader aligner: FileAligner
|
|
17
|
+
|
|
18
|
+
# Resolver for handling conflicting content
|
|
19
|
+
attr_reader resolver: ConflictResolver
|
|
20
|
+
|
|
21
|
+
# Initialize a SmartMerger
|
|
22
|
+
def initialize: (
|
|
23
|
+
String template_content,
|
|
24
|
+
String dest_content,
|
|
25
|
+
?signature_generator: (^(untyped) -> (Array[untyped] | nil | untyped))?,
|
|
26
|
+
?signature_match_preference: Symbol,
|
|
27
|
+
?add_template_only_nodes: bool,
|
|
28
|
+
?freeze_token: String,
|
|
29
|
+
?options: Hash[Symbol, untyped]
|
|
30
|
+
) -> void
|
|
31
|
+
|
|
32
|
+
# Perform the merge operation
|
|
33
|
+
def merge: () -> MergeResult
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# Process alignment entries and build result
|
|
38
|
+
def process_alignment: (Array[Hash[Symbol, untyped]] alignment) -> [Array[String], Hash[Symbol, untyped], Array[Hash[Symbol, untyped]], Array[Hash[Symbol, untyped]]]
|
|
39
|
+
|
|
40
|
+
# Process a matched node pair
|
|
41
|
+
def process_match: (Hash[Symbol, untyped] entry, Hash[Symbol, untyped] stats) -> [String?, Hash[Symbol, untyped]?]
|
|
42
|
+
|
|
43
|
+
# Process a template-only node
|
|
44
|
+
def process_template_only: (Hash[Symbol, untyped] entry, Hash[Symbol, untyped] stats) -> String?
|
|
45
|
+
|
|
46
|
+
# Process a destination-only node
|
|
47
|
+
def process_dest_only: (Hash[Symbol, untyped] entry, Hash[Symbol, untyped] stats) -> [String?, Hash[Symbol, untyped]?]
|
|
48
|
+
|
|
49
|
+
# Convert a node to its source text
|
|
50
|
+
def node_to_source: (untyped node, FileAnalysis analysis) -> String
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|