ast-merge v2.0.0 released!
2.0.0 - 2025-12-28
- TAG: v2.0.0
- COVERAGE: 88.47% β 2894/3271 lines in 53 files
- BRANCH COVERAGE: 67.83% β 698/1029 branches in 53 files
- 98.82% documented
Added
- RSpec Dependency Tags: Conditional test execution based on available merge gems
- New
lib/ast/merge/rspec/dependency_tags.rbprovides automatic test filtering - Tags for all merge gems:
:markly_merge,:prism_merge,:json_merge,:toml_merge, etc. - Composite tag
:any_markdown_mergefor tests that work with any markdown merger - Negated tags (e.g.,
:not_prism_merge) for testing fallback behavior AST_MERGE_DEBUG=1environment variable prints dependency summary- Eliminates need for
requirestatements inside spec files - See lib/ast/merge/rspec/README.md for full documentation
- New
- Recipe::Preset: Base class for merge configuration presets
- Provides merge configuration (signature generators, node typing, preferences) without requiring template files
Recipe::Confignow inherits fromPreset, adding template/target handlingto_hmethod converts preset to SmartMerger-compatible options hash- Enables kettle-jem and other libraries to define reusable merge presets
- Supports script loading for signature generators and node typing via
ScriptLoader
- exe/ast-merge-recipe: Shipped executable for running merge recipes
- Uses
bundler/inlinefor dependency management - Supports
--dry-run,--verbose,--parser,--base-diroptions - Uses
optparsefor proper option parsing - Loads merge gems from recipe YAML
merge_gemssection - Development mode via
KETTLE_RB_DEV=trueor--dev-rootoption - All gems sourced from gem.coop
- Uses
- PartialTemplateMerger: Section-based merging for partial templates
- Find and merge specific sections in destination documents
- Support for both
replace_mode(full replacement) and merge mode (intelligent merging) - Configurable anchor and boundary matchers for section detection
- Custom
signature_generatorandnode_typingsupport for advanced matching when_missingbehavior::skip,:append,:prepend
- Recipe: YAML-based recipe system for defining merge operations
- Load recipes from YAML files with
Recipe.load(path) - Define template, targets, injection point, merge preferences
- Support for
when_missing: skip|add|errorbehavior - Support for
replace_modeoption - Automatic path resolution relative to recipe file location
- Load recipes from YAML files with
- RecipeRunner: Execute recipes against multiple target files
- Uses PartialTemplateMerger for section-based merging
- Dry-run mode with
--dry-runflag - Results tracking with status, stats, and error reporting
- TableTennis integration for formatted output
- Support for different parsers (markly, commonmarker, prism, psych)
- RecipeScriptLoader: Load Ruby scripts referenced by recipes
- Convention: scripts in folder matching recipe basename (e.g.,
my_recipe/formy_recipe.yml) - Support for inline lambda expressions in YAML
- Script caching for performance
- Validation that scripts return callable objects
- Convention: scripts in folder matching recipe basename (e.g.,
- bin/ast-merge-recipe: CLI for running merge recipes
bin/ast-merge-recipe RECIPE_FILE [--dry-run] [--verbose]- Color-coded output with status symbols
- Summary table with counts
- NavigableStatement: New wrapper class for uniform node navigation (language-agnostic)
- Provides flat list navigation (
next,previous,index) for all nodes - Tree depth calculation with
tree_depthmethod same_or_shallower_than?for level-based boundary detection- Language-agnostic section boundaries using tree hierarchy
- Provides tree navigation (
tree_parent,tree_next,tree_previous) for parser-backed nodes synthetic?method to detect nodes without tree navigation (GapLineNode, LinkDefinitionNode, etc.)type?andtext_matches?helpers for node matchingnode_attributefor accessing parser-specific attributes with fallbackseach_followingandtake_untilfor sequential traversalfind_matchingandfind_firstclass methods for querying statement listsbuild_listclass method to create linked statement lists from raw statements
- Provides flat list navigation (
- InjectionPoint: New class for defining where content can be injected (language-agnostic)
- Supports positions:
:before,:after,:first_child,:last_child,:replace - Optional boundary for replacement ranges
replacement?,child_injection?,sibling_injection?predicatesreplaced_statementsto get all statements in a replacement range
- Supports positions:
- InjectionPointFinder: New class for finding injection points by matching criteria
findto locate a single injection point by type/text patternfind_allto locate all matching injection points- Works with any
*-mergegem (prism-merge, markly-merge, psych-merge, etc.)
- SmartMergerBase:
add_template_only_nodesnow accepts a callable filter- Boolean
true/falsestill works as before (add all or none) - Callable (Proc/Lambda) receives
(node, entry)and returns truthy to add the node - Enables selective addition of template-only nodes based on signature, type, or content
- Example use case: Add missing link reference definitions while skipping other template content
- Entry hash includes
:template_node,:signature,:template_indexfor filtering decisions
- Boolean
- ContentMatchRefiner: New match refiner for fuzzy text content matching
- Uses Levenshtein distance to pair nodes with similar (but not identical) text
- Configurable scoring weights for content similarity, length, and position
- Custom content extractor support for parser-specific text extraction
- Node type filtering to limit which types are processed
- Can be combined with other refiners (e.g., TableMatchRefiner)
- Useful for matching paragraphs, headings, comments with minor edits
- SmartMergerBase: Added validity check after FileAnalysis creation
- Checks
valid?after creating FileAnalysis and raises appropriate parse error if invalid - Catches silent failures like grammar not available or parse errors
- Documented the FileAnalysis error handling pattern for all *-merge gems
- Checks
- SmartMergerBase: Added explicit
node_typingparameter- All child SmartMergers were already using
node_typingvia**format_options - Now explicitly documented and accessible via
attr_reader :node_typing - Validates node_typing configuration via
NodeTyping.validate!if provided - Enables per-node-type merge preferences across all
*-mergegems
- All child SmartMergers were already using
- ConflictResolverBase: Added
match_refinerparameter and**optionsfor forward compatibility- All batch-strategy resolvers were storing
match_refinerlocally - Now explicitly accepted in base class with
attr_reader :match_refiner - Added
**optionscatch-all for future parameters without breaking child classes
- All batch-strategy resolvers were storing
- MergeResultBase: Added
**optionsfor forward compatibility- Allows subclasses to accept new parameters without modification
- Maintains backward compatibility with existing no-arg and keyword-arg constructors
- RBS Signatures: Added comprehensive type signatures for base classes
SmartMergerBasewith all standard options and abstract method declarationsConflictResolverBasewith strategy-based resolution methodsMergeResultBasewith unified constructor and decision trackingMatchRefinerBasewith similarity computation interfaceRegionMergeablemodule for nested content mergingNodeTypingmodule withWrapperclass for typed nodes- Type aliases:
node_typing_callable,node_typing_hash,preference_type
- Documentation: Updated README with comprehensive base class documentation
- Standard options table with all
SmartMergerBaseparameters - Forward compatibility section explaining the
**optionspattern - Complete βCreating a New Merge Gemβ example with all base classes
- Base Classes Reference table
- Standard options table with all
Changed
- BREAKING - Namespace Reorganization: Major restructuring for better organization
Ast::Merge::RegionβAst::Merge::Detector::Region(Struct moved into Detector namespace)Ast::Merge::RegionDetectorBaseβAst::Merge::Detector::BaseAst::Merge::RegionMergeableβAst::Merge::Detector::MergeableAst::Merge::FencedCodeBlockDetectorβAst::Merge::Detector::FencedCodeBlockAst::Merge::YamlFrontmatterDetectorβAst::Merge::Detector::YamlFrontmatterAst::Merge::TomlFrontmatterDetectorβAst::Merge::Detector::TomlFrontmatterAst::Merge::Recipeclass βAst::Merge::Recipe::ConfigAst::Merge::RecipeRunnerβAst::Merge::Recipe::RunnerAst::Merge::RecipeScriptLoaderβAst::Merge::Recipe::ScriptLoaderAst::Merge::RegionMergeable::RegionConfigβAst::Merge::Detector::Mergeable::ConfigAst::Merge::RegionMergeable::ExtractedRegionβAst::Merge::Detector::Mergeable::ExtractedRegion
Many paths lead to being a sponsor or a backer of this project. Are you on such a path?