ast-merge 4.0.1 → 4.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6af6467980a8e2076bd454a35bea42e18064fed0651704754f459353a85087a
4
- data.tar.gz: 1d89bad2aa237d11aafd957f68391d8ca83248cc0f7946bad54e788cc1fa05c2
3
+ metadata.gz: 72301b52fa4f37e5f4224041c08fe9ace0117f84521e37b8b1c8b354bc5af500
4
+ data.tar.gz: 16c3d01ce0e56c17998fcf7e0e4629832fc52db44dc64d07b897004e9981f6ea
5
5
  SHA512:
6
- metadata.gz: a45b949a5b6b835ba26d0422eb855daa9a62e513131bf06627abe8b68dba2daae28dd835f51fce43758c36f652fb44851885adcec3f82a64519bc2baed6f77f9
7
- data.tar.gz: c2a7c05cedc23b3552f5eaef980cc890cf034060efe82f51f0c7acc98cba5b5df3bc2441a96bcde188c48391baebe5474dd76f735e5a2dbda053ff85b07a6748
6
+ metadata.gz: e0ab85926e6944d30500a5ced0144c86fa966d6a18252cda9c6c8091e4827e62b8743119be97944c30145d9a1e64f8c2fad52c5e9fd6f50d09b3ff70417ce64d
7
+ data.tar.gz: f57d3ce4c7cdb62dbbe59493581bbe2fb721a62ea029bf327a527edd2e76d394be554b34ad97fe68a82f009abf56e39225994835f03315663b8c3b137e56a459
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,56 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [4.0.3] - 2026-01-19
34
+
35
+ - TAG: [v4.0.3][4.0.3t]
36
+ - COVERAGE: 97.30% -- 2739/2815 lines in 53 files
37
+ - BRANCH COVERAGE: 89.84% -- 893/994 branches in 53 files
38
+ - 98.81% documented
39
+
40
+ ### Added
41
+
42
+ - **`Ast::Merge::RSpec::MergeGemRegistry.register_known_gems`**: Selective registration of known merge gems for RSpec dependency tags
43
+ - Allows test suites to explicitly register only the merge gems they need, avoiding overhead of registering all known gems
44
+ - Usage in `spec/config/tree_haver.rb`: `MergeGemRegistry.register_known_gems(:prism_merge, :commonmarker_merge)`
45
+ - Enables proper RSpec tag-based test skipping for optional merge gem dependencies
46
+ - Example: Tests tagged with `:prism_merge` are automatically skipped when prism-merge isn't available
47
+
48
+ ### Changed
49
+
50
+ - Upgrade to [tree_haver v5.0.2](https://github.com/kettle-rb/tree_haver/releases/tag/v5.0.2)
51
+ - **RSpec dependency tag load order pattern**: Merge gems now load tree_haver and dependency tags early via `spec/config/tree_haver.rb`
52
+ - Ensures `TreeHaver::RSpec::DependencyTags` is loaded before gems register themselves
53
+ - Pattern: Load tree_haver/rspec → Load ast/merge/rspec → Register known gems → Load library
54
+ - Applied to markdown-merge and markly-merge; other merge gems should follow this pattern
55
+
56
+ ## [4.0.2] - 2026-01-12
57
+
58
+ - TAG: [v4.0.2][4.0.2t]
59
+ - COVERAGE: 97.30% -- 2739/2815 lines in 53 files
60
+ - BRANCH COVERAGE: 89.84% -- 893/994 branches in 53 files
61
+ - 98.81% documented
62
+
63
+ ### Added
64
+
65
+ - **`Recipe::Runner` target file override**: Accept `target_files` parameter to override recipe targets
66
+ - `Runner.new(recipe, target_files: ["file1.md", "file2.md"])` - Process only specified files
67
+ - Paths are expanded relative to `base_dir`
68
+ - When not specified, falls back to recipe's configured targets
69
+ - **`exe/ast-merge-recipe` file arguments**: Accept target files on command line
70
+ - `ast-merge-recipe recipe.yml file1.md file2.md` - Override recipe targets
71
+ - Updated help text and banner to document new usage
72
+ - **`bin/update_gem_family_section` file arguments**: Accept target files on command line
73
+ - `bin/update_gem_family_section vendor/my-gem/README.md` - Process specific file(s)
74
+ - If no files specified, defaults to `README.md` + `vendor/*/README.md`
75
+ - Added `--skip-fix` option to skip the formatting fix step
76
+
77
+ ### Changed
78
+
79
+ - **`bin/update_gem_family_section`**: Refactored to use `OptionParser` for clean option handling
80
+ - Consistent with `bin/fix_readme_formatting` style
81
+ - Properly separates options from file arguments
82
+
33
83
  ## [4.0.1] - 2026-01-11
34
84
 
35
85
  - TAG: [v4.0.1][4.0.1t]
@@ -637,7 +687,11 @@ Please file a bug if you notice a violation of semantic versioning.
637
687
 
638
688
  - Initial release
639
689
 
640
- [Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v4.0.1...HEAD
690
+ [Unreleased]: https://github.com/kettle-rb/ast-merge/compare/v4.0.3...HEAD
691
+ [4.0.3]: https://github.com/kettle-rb/ast-merge/compare/v4.0.2...v4.0.3
692
+ [4.0.3t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.3
693
+ [4.0.2]: https://github.com/kettle-rb/ast-merge/compare/v4.0.1...v4.0.2
694
+ [4.0.2t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.2
641
695
  [4.0.1]: https://github.com/kettle-rb/ast-merge/compare/v4.0.0...v4.0.1
642
696
  [4.0.1t]: https://github.com/kettle-rb/ast-merge/releases/tag/v4.0.1
643
697
  [4.0.0]: https://github.com/kettle-rb/ast-merge/compare/v3.1.0...v4.0.0
data/README.md CHANGED
@@ -62,7 +62,7 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
62
62
 
63
63
  | Gem | Version | CI | | Language<br>/ Format | Parser Backend(s) | Description |
64
64
  |------------------------------------------|----------------------------------------------------------------|--------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|-------------|
65
- | [tree_haver][tree_haver] | [![Version][tree_haver-gem-i]][tree_haver-gem] | [![Version][tree_haver-ci-i]][tree_haver-ci] | Multi | MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus, Parslet | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
65
+ | [tree_haver][tree_haver] | [![Version][tree_haver-gem-i]][tree_haver-gem] | [![Version][tree_haver-ci-i]][tree_haver-ci] | Multi | Supported Backends: MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus, Parslet | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
66
66
  | [ast-merge][ast-merge] | [![Version][ast-merge-gem-i]][ast-merge-gem] | [![Version][ast-merge-ci-i]][ast-merge-ci] | Text | internal | **Infrastructure**: Shared base classes and merge logic for all `*-merge` gems |
67
67
  | [bash-merge][bash-merge] | [![Version][bash-merge-gem-i]][bash-merge-gem] | [![Version][bash-merge-ci-i]][bash-merge-ci] | Bash | [tree-sitter-bash][ts-bash] (via tree_haver) | Smart merge for Bash scripts |
68
68
  | [commonmarker-merge][commonmarker-merge] | [![Version][commonmarker-merge-gem-i]][commonmarker-merge-gem] | [![Version][commonmarker-merge-ci-i]][commonmarker-merge-ci] | Markdown | [Commonmarker][commonmarker] (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
@@ -80,18 +80,18 @@ The `*-merge` gem family provides intelligent, AST-based merging for various fil
80
80
 
81
81
  tree_haver supports multiple parsing backends, but not all backends work on all Ruby platforms:
82
82
 
83
- | Platform 👉️<br> TreeHaver Backend 👇️ | MRI | JRuby | TruffleRuby | Notes |
84
- |------------------------------------------------|:---:|:-----:|:-----------:|-----------------------------------------------------|
85
- | **MRI** ([ruby_tree_sitter][ruby_tree_sitter]) | ✅ | ❌ | ❌ | C extension, MRI only |
86
- | **Rust** ([tree_stump][tree_stump]) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
87
- | **FFI** | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
88
- | **Java** ([jtreesitter][jtreesitter]) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
89
- | **Prism** | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
90
- | **Psych** | ✅ | ✅ | ✅ | YAML parsing, stdlib |
91
- | **Citrus** | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
92
- | **Parslet** | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
93
- | **Commonmarker** | ✅ | ❌ | ❓ | Rust extension for Markdown |
94
- | **Markly** | ✅ | ❌ | ❓ | C extension for Markdown |
83
+ | Platform 👉️<br> TreeHaver Backend 👇️ | MRI | JRuby | TruffleRuby | Notes |
84
+ |-------------------------------------------------|:---:|:-----:|:-----------:|----------------------------------------------------------------------------|
85
+ | **MRI** ([ruby_tree_sitter][ruby_tree_sitter]) | ✅ | ❌ | ❌ | C extension, MRI only |
86
+ | **Rust** ([tree_stump][tree_stump]) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
87
+ | **FFI** ([ffi][ffi]) | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
88
+ | **Java** ([jtreesitter][jtreesitter]) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
89
+ | **Prism** ([prism][prism]) | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
90
+ | **Psych** ([psych][psych]) | ✅ | ✅ | ✅ | YAML parsing, stdlib |
91
+ | **Citrus** ([citrus][citrus]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
92
+ | **Parslet** ([parslet][parslet]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
93
+ | **Commonmarker** ([commonmarker][commonmarker]) | ✅ | ❌ | ❓ | Rust extension for Markdown (via [commonmarker-merge][commonmarker-merge]) |
94
+ | **Markly** ([markly][markly]) | ✅ | ❌ | ❓ | C extension for Markdown (via [markly-merge][markly-merge]) |
95
95
 
96
96
  **Legend**: ✅ = Works, ❌ = Does not work, ❓ = Untested
97
97
 
@@ -185,6 +185,7 @@ tree_haver supports multiple parsing backends, but not all backends work on all
185
185
  [kettle-jem-ci]: https://github.com/kettle-rb/kettle-jem/actions/workflows/current.yml
186
186
  [prism]: https://github.com/ruby/prism
187
187
  [psych]: https://github.com/ruby/psych
188
+ [ffi]: https://github.com/ffi/ffi
188
189
  [ts-json]: https://github.com/tree-sitter/tree-sitter-json
189
190
  [ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
190
191
  [ts-bash]: https://github.com/tree-sitter/tree-sitter-bash
@@ -199,6 +200,8 @@ tree_haver supports multiple parsing backends, but not all backends work on all
199
200
  [ruby_tree_sitter]: https://github.com/Faveod/ruby-tree-sitter
200
201
  [tree_stump]: https://github.com/joker1007/tree_stump
201
202
  [jtreesitter]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
203
+ [citrus]: https://github.com/mjackson/citrus
204
+ [parslet]: https://github.com/kschiess/parslet
202
205
 
203
206
  ### Architecture: tree\_haver + ast-merge
204
207
 
@@ -208,24 +211,24 @@ The `*-merge` gem family is built on a two-layer architecture:
208
211
 
209
212
  [tree\_haver][tree_haver] provides cross-Ruby parsing capabilities:
210
213
 
211
- - **Universal Backend Support**: Automatically selects the best parsing backend for your Ruby implementation (MRI, JRuby, TruffleRuby)
212
- - **10 Backend Options**: MRI C extensions, Rust bindings, FFI, Java (JRuby), language-specific parsers (Prism, Psych, Commonmarker, Markly), and pure Ruby fallback (Citrus)
213
- - **Unified API**: Write parsing code once, run on any Ruby implementation
214
- - **Grammar Discovery**: Built-in `GrammarFinder` for platform-aware grammar library discovery
215
- - **Thread-Safe**: Language registry with thread-safe caching
214
+ - **Universal Backend Support**: Automatically selects the best parsing backend for your Ruby implementation (MRI, JRuby, TruffleRuby)
215
+ - **10 Backend Options**: MRI C extensions, Rust bindings, FFI, Java (JRuby), language-specific parsers (Prism, Psych, Commonmarker, Markly), and pure Ruby fallback (Citrus)
216
+ - **Unified API**: Write parsing code once, run on any Ruby implementation
217
+ - **Grammar Discovery**: Built-in `GrammarFinder` for platform-aware grammar library discovery
218
+ - **Thread-Safe**: Language registry with thread-safe caching
216
219
 
217
220
  #### Layer 2: ast-merge (Merge Infrastructure)
218
221
 
219
222
  Ast::Merge builds on tree\_haver to provide:
220
223
 
221
- - **Base Classes**: `FreezeNode`, `MergeResult` base classes with unified constructors
222
- - **Shared Modules**: `FileAnalysisBase`, `FileAnalyzable`, `MergerConfig`, `DebugLogger`
223
- - **Freeze Block Support**: Configurable marker patterns for multiple comment syntaxes (preserve sections during merge)
224
- - **Node Typing System**: `NodeTyping` for canonical node type identification across different parsers
225
- - **Conflict Resolution**: `ConflictResolverBase` with pluggable strategies
226
- - **Error Classes**: `ParseError`, `TemplateParseError`, `DestinationParseError`
227
- - **Region Detection**: `RegionDetectorBase`, `FencedCodeBlockDetector` for text-based analysis
228
- - **RSpec Shared Examples**: Test helpers for implementing new merge gems
224
+ - **Base Classes**: `FreezeNode`, `MergeResult` base classes with unified constructors
225
+ - **Shared Modules**: `FileAnalysisBase`, `FileAnalyzable`, `MergerConfig`, `DebugLogger`
226
+ - **Freeze Block Support**: Configurable marker patterns for multiple comment syntaxes (preserve sections during merge)
227
+ - **Node Typing System**: `NodeTyping` for canonical node type identification across different parsers
228
+ - **Conflict Resolution**: `ConflictResolverBase` with pluggable strategies
229
+ - **Error Classes**: `ParseError`, `TemplateParseError`, `DestinationParseError`
230
+ - **Region Detection**: `RegionDetectorBase`, `FencedCodeBlockDetector` for text-based analysis
231
+ - **RSpec Shared Examples**: Test helpers for implementing new merge gems
229
232
 
230
233
  ### Creating a New Merge Gem
231
234
 
@@ -372,10 +375,10 @@ merger = MyFormat::SmartMerger.new(
372
375
 
373
376
  This is particularly useful for:
374
377
 
375
- - Paragraphs with minor edits (typos, rewording)
376
- - Headings with slight changes
377
- - Comments with updated text
378
- - Any text-based node that may have been slightly modified
378
+ - Paragraphs with minor edits (typos, rewording)
379
+ - Headings with slight changes
380
+ - Comments with updated text
381
+ - Any text-based node that may have been slightly modified
379
382
 
380
383
  ### Namespace Reference
381
384
 
@@ -391,11 +394,11 @@ The `Ast::Merge` module is organized into several namespaces, each with detailed
391
394
 
392
395
  **Key Classes by Namespace:**
393
396
 
394
- - **Detector**: `Region`, `Base`, `Mergeable`, `FencedCodeBlock`, `YamlFrontmatter`, `TomlFrontmatter`
395
- - **Recipe**: `Config`, `Runner`, `ScriptLoader`
396
- - **Comment**: `Line`, `Block`, `Empty`, `Parser`, `Style`
397
- - **Text**: `SmartMerger`, `FileAnalysis`, `LineNode`, `WordNode`, `Section`
398
- - **RSpec**: Shared examples and dependency tags for testing `*-merge` implementations
397
+ - **Detector**: `Region`, `Base`, `Mergeable`, `FencedCodeBlock`, `YamlFrontmatter`, `TomlFrontmatter`
398
+ - **Recipe**: `Config`, `Runner`, `ScriptLoader`
399
+ - **Comment**: `Line`, `Block`, `Empty`, `Parser`, `Style`
400
+ - **Text**: `SmartMerger`, `FileAnalysis`, `LineNode`, `WordNode`, `Section`
401
+ - **RSpec**: Shared examples and dependency tags for testing `*-merge` implementations
399
402
 
400
403
  ## 💡 Info you can shake a stick at
401
404
 
@@ -447,18 +450,13 @@ The maintainers of this and thousands of other packages are working with Tidelif
447
450
 
448
451
  [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
449
452
 
450
- - 💡Subscribe for support guarantees covering *all* your FLOSS dependencies
451
-
452
- - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
453
-
454
- - 💡Tidelift pays maintainers to maintain the software you depend on\!<br/>📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers
455
- Alternatively:
456
-
457
- - [![Live Chat on Discord][✉️discord-invite-img-ftb]][🖼️galtzo-discord]
458
-
459
- - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork]
460
-
461
- - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
453
+ - 💡Subscribe for support guarantees covering *all* your FLOSS dependencies
454
+ - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
455
+ - 💡Tidelift pays maintainers to maintain the software you depend on\!<br/>📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers
456
+ Alternatively:
457
+ - [![Live Chat on Discord][✉️discord-invite-img-ftb]][🖼️galtzo-discord]
458
+ - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork]
459
+ - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
462
460
 
463
461
  </details>
464
462
 
@@ -537,17 +535,17 @@ merger = SomeFormat::Merge::SmartMerger.new(
537
535
 
538
536
  Control which source wins when both files have the same structural element:
539
537
 
540
- - **`:template`** - Template values replace destination values
541
- - **`:destination`** (default) - Destination values are preserved
542
- - **Hash** - Per-node-type preference (see Advanced Configuration)
538
+ - **`:template`** - Template values replace destination values
539
+ - **`:destination`** (default) - Destination values are preserved
540
+ - **Hash** - Per-node-type preference (see Advanced Configuration)
543
541
 
544
542
  ### Template-Only Nodes
545
543
 
546
544
  Control whether to add nodes that only exist in the template:
547
545
 
548
- - **`true`** - Add all template-only nodes
549
- - **`false`** (default) - Skip template-only nodes
550
- - **Callable** - Filter which template-only nodes to add
546
+ - **`true`** - Add all template-only nodes
547
+ - **`false`** (default) - Skip template-only nodes
548
+ - **Callable** - Filter which template-only nodes to add
551
549
 
552
550
  #### Callable Filter
553
551
 
@@ -577,10 +575,10 @@ merger = Markly::Merge::SmartMerger.new(
577
575
 
578
576
  The `entry` hash contains:
579
577
 
580
- - `:template_node` - The node being considered for addition
581
- - `:signature` - The node's signature (Array or other value)
582
- - `:template_index` - Index in the template statements
583
- - `:dest_index` - Always `nil` for template-only nodes
578
+ - `:template_node` - The node being considered for addition
579
+ - `:signature` - The node's signature (Array or other value)
580
+ - `:template_index` - Index in the template statements
581
+ - `:dest_index` - Always `nil` for template-only nodes
584
582
 
585
583
  ## 🔧 Basic Usage
586
584
 
@@ -606,11 +604,11 @@ end
606
604
 
607
605
  ### Available Shared Examples
608
606
 
609
- - `"Ast::Merge::FreezeNode"` - Tests for FreezeNode implementations
610
- - `"Ast::Merge::MergeResult"` - Tests for MergeResult implementations
611
- - `"Ast::Merge::DebugLogger"` - Tests for DebugLogger implementations
612
- - `"Ast::Merge::FileAnalysisBase"` - Tests for FileAnalysis implementations
613
- - `"Ast::Merge::MergerConfig"` - Tests for SmartMerger implementations
607
+ - `"Ast::Merge::FreezeNode"` - Tests for FreezeNode implementations
608
+ - `"Ast::Merge::MergeResult"` - Tests for MergeResult implementations
609
+ - `"Ast::Merge::DebugLogger"` - Tests for DebugLogger implementations
610
+ - `"Ast::Merge::FileAnalysisBase"` - Tests for FileAnalysis implementations
611
+ - `"Ast::Merge::MergerConfig"` - Tests for SmartMerger implementations
614
612
 
615
613
  ## 🎛️ Advanced Configuration
616
614
 
@@ -622,9 +620,9 @@ This is useful for hand-edited customizations you never want overwritten.
622
620
 
623
621
  A freeze block consists of:
624
622
 
625
- - A **start marker** comment (e.g., `# mytoken:freeze`)
626
- - The protected content
627
- - An **end marker** comment (e.g., `# mytoken:unfreeze`)
623
+ - A **start marker** comment (e.g., `# mytoken:freeze`)
624
+ - The protected content
625
+ - An **end marker** comment (e.g., `# mytoken:unfreeze`)
628
626
 
629
627
  ```ruby
630
628
  # In a Ruby file with prism-merge:
@@ -669,13 +667,13 @@ preferences for different types of nodes (e.g., prefer template for linter confi
669
667
 
670
668
  1. **Define a `node_typing`**: A Hash mapping node type symbols to callables that receive a node and return either:
671
669
 
672
- - The original node (no special handling)
673
- - A wrapped node with a `merge_type` attribute (via `Ast::Merge::NodeTyping::Wrapper`)
670
+ - The original node (no special handling)
671
+ - A wrapped node with a `merge_type` attribute (via `Ast::Merge::NodeTyping::Wrapper`)
674
672
 
675
673
  2. **Use a Hash-based preference**: Instead of a simple `:destination` or `:template` Symbol, pass a Hash with:
676
674
 
677
- - `:default` key for the fallback preference
678
- - Custom keys matching the `merge_type` values from your `node_typing`
675
+ - `:default` key for the fallback preference
676
+ - Custom keys matching the `merge_type` values from your `node_typing`
679
677
 
680
678
  ```ruby
681
679
  # Example: Prefer template for lint gem configs, destination for everything else
@@ -793,7 +791,7 @@ Support us with a monthly donation and help us continue our activities. \[[Becom
793
791
  NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
794
792
 
795
793
  <!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
796
- No backers yet. Be the first\!
794
+ No backers yet. Be the first!
797
795
  <!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
798
796
 
799
797
  ### Open Collective for Organizations
@@ -803,7 +801,7 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
803
801
  NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
804
802
 
805
803
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
806
- No sponsors yet. Be the first\!
804
+ No sponsors yet. Be the first!
807
805
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
808
806
 
809
807
  [kettle-readme-backers]: https://github.com/kettle-rb/ast-merge/blob/main/exe/kettle-readme-backers
@@ -903,7 +901,7 @@ is a *breaking change* to an API, and for that reason the bike shedding is endle
903
901
  To get a better understanding of how SemVer is intended to work over a project's lifetime,
904
902
  read this article from the creator of SemVer:
905
903
 
906
- - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
904
+ - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
907
905
 
908
906
  </details>
909
907
 
@@ -1108,7 +1106,7 @@ Thanks for RTFM. ☺️
1108
1106
  [📌gitmoji]: https://gitmoji.dev
1109
1107
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1110
1108
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1111
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.647-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1109
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.815-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1112
1110
  [🔐security]: SECURITY.md
1113
1111
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1114
1112
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
data/exe/ast-merge-recipe CHANGED
@@ -171,9 +171,10 @@ class AstMergeRecipeCLI
171
171
 
172
172
  def parse_options(argv)
173
173
  @option_parser = OptionParser.new do |opts|
174
- opts.banner = "Usage: #{File.basename($0)} RECIPE_FILE [options]"
174
+ opts.banner = "Usage: #{File.basename($0)} RECIPE_FILE [FILES...] [options]"
175
175
  opts.separator("")
176
176
  opts.separator("Run a YAML-based merge recipe against target files.")
177
+ opts.separator("If FILES are specified, they override the recipe's targets.")
177
178
  opts.separator("")
178
179
  opts.separator("Options:")
179
180
 
@@ -225,9 +226,15 @@ class AstMergeRecipeCLI
225
226
  opts.on("-h", "--help", "Show this help message") do
226
227
  puts opts
227
228
  puts
229
+ puts "Arguments:"
230
+ puts " RECIPE_FILE Path to the YAML recipe file (required)"
231
+ puts " [FILES...] Target files to process (optional, overrides recipe targets)"
232
+ puts
228
233
  puts "Examples:"
229
234
  puts " #{File.basename($0)} .merge-recipes/gem_family_section.yml --dry-run"
230
235
  puts " #{File.basename($0)} recipe.yml --verbose --parser=commonmarker"
236
+ puts " #{File.basename($0)} recipe.yml vendor/my-gem/README.md"
237
+ puts " #{File.basename($0)} recipe.yml README.md vendor/*/README.md"
231
238
  puts
232
239
  puts "Recipe YAML format:"
233
240
  puts " See lib/ast/merge/recipe/README.md for full documentation"
@@ -241,10 +248,8 @@ class AstMergeRecipeCLI
241
248
  # First non-option argument is the recipe file
242
249
  @options[:recipe_file] = remaining.shift
243
250
 
244
- # Warn about extra arguments
245
- if remaining.any?
246
- $stderr.puts Colors.yellow("WARNING: Ignoring extra arguments: #{remaining.join(", ")}")
247
- end
251
+ # Remaining arguments are target files (override recipe targets)
252
+ @options[:target_files] = remaining if remaining.any?
248
253
  end
249
254
 
250
255
  def validate_options!
@@ -271,14 +276,19 @@ class AstMergeRecipeCLI
271
276
  recipe = Ast::Merge::Recipe::Config.load(@options[:recipe_file])
272
277
  print_recipe_info(recipe)
273
278
 
274
- # Create runner
275
- runner = Ast::Merge::Recipe::Runner.new(
276
- recipe,
279
+ # Build runner options
280
+ runner_opts = {
277
281
  dry_run: @options[:dry_run],
278
282
  base_dir: @options[:base_dir],
279
283
  parser: @options[:parser],
280
284
  verbose: @options[:verbose],
281
- )
285
+ }
286
+
287
+ # If target files specified on command line, override recipe targets
288
+ runner_opts[:target_files] = @options[:target_files] if @options[:target_files]
289
+
290
+ # Create runner
291
+ runner = Ast::Merge::Recipe::Runner.new(recipe, **runner_opts)
282
292
 
283
293
  # Run and display results
284
294
  puts Colors.cyan("Processing files...")
@@ -40,6 +40,9 @@ module Ast
40
40
  # @return [Symbol] Parser to use (:markly, :commonmarker, :prism, :psych, etc.)
41
41
  attr_reader :parser
42
42
 
43
+ # @return [Array<String>, nil] Target files override (from command line)
44
+ attr_reader :target_files
45
+
43
46
  # @return [Array<Result>] Results from the last run
44
47
  attr_reader :results
45
48
 
@@ -50,12 +53,14 @@ module Ast
50
53
  # @param base_dir [String, nil] Base directory for path resolution
51
54
  # @param parser [Symbol] Which parser to use
52
55
  # @param verbose [Boolean] Enable verbose output
53
- def initialize(recipe, dry_run: false, base_dir: nil, parser: :markly, verbose: false)
56
+ # @param target_files [Array<String>, nil] Override recipe targets with these files
57
+ def initialize(recipe, dry_run: false, base_dir: nil, parser: :markly, verbose: false, target_files: nil, **options)
54
58
  @recipe = recipe
55
59
  @dry_run = dry_run
56
60
  @base_dir = base_dir || Dir.pwd
57
61
  @parser = parser
58
62
  @verbose = verbose
63
+ @target_files = target_files
59
64
  @results = []
60
65
  end
61
66
 
@@ -66,10 +71,17 @@ module Ast
66
71
  @results = []
67
72
 
68
73
  template_content = load_template
69
- # Let the recipe expand targets from its own location
70
- target_files = recipe.expand_targets
71
74
 
72
- target_files.each do |target_path|
75
+ # Use command-line targets if provided, otherwise expand from recipe
76
+ files_to_process = if @target_files && !@target_files.empty?
77
+ # Expand paths relative to base_dir
78
+ @target_files.map { |f| File.expand_path(f, @base_dir) }
79
+ else
80
+ # Let the recipe expand targets from its own location
81
+ recipe.expand_targets
82
+ end
83
+
84
+ files_to_process.each do |target_path|
73
85
  result = process_file(target_path, template_content)
74
86
  @results << result
75
87
  yield result if block_given?
@@ -84,6 +84,21 @@ module Ast
84
84
  end
85
85
  end
86
86
 
87
+ # NOTE: Known merge gems (KNOWN_GEMS) are NOT automatically registered here.
88
+ # Each test suite should explicitly register only the gems it needs in its
89
+ # spec/config/tree_haver.rb file using:
90
+ #
91
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(:gem1, :gem2, ...)
92
+ #
93
+ # This avoids wasting time registering gems that aren't needed for a particular
94
+ # test suite. Only the gems that are actually required for testing should be registered.
95
+ #
96
+ # Example for a gem that needs to test with optional markdown backends:
97
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(
98
+ # :commonmarker_merge,
99
+ # :markly_merge
100
+ # )
101
+
87
102
  # Configure RSpec with dependency-based exclusion filters
88
103
  RSpec.configure do |config|
89
104
  deps = Ast::Merge::RSpec::DependencyTags
@@ -253,6 +253,48 @@ module Ast
253
253
  end
254
254
  end
255
255
 
256
+ # Register one or more known gems for RSpec dependency tag support
257
+ #
258
+ # This allows test suites to explicitly register only the merge gems they need
259
+ # for their tests, avoiding the overhead of registering all known gems.
260
+ #
261
+ # @param gem_names [Array<Symbol>] list of gem names from KNOWN_GEMS to register
262
+ # @return [void]
263
+ #
264
+ # @example In spec/config/tree_haver.rb
265
+ # # Only register the markdown merge gems that markly-merge tests depend on
266
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(:prism_merge)
267
+ #
268
+ # @example Register multiple gems
269
+ # Ast::Merge::RSpec::MergeGemRegistry.register_known_gems(
270
+ # :commonmarker_merge,
271
+ # :markly_merge
272
+ # )
273
+ def register_known_gems(*gem_names)
274
+ gem_names.each do |tag_name|
275
+ tag_sym = tag_name.to_sym
276
+
277
+ # Skip if not in KNOWN_GEMS
278
+ unless KNOWN_GEMS.key?(tag_sym)
279
+ warn("Unknown gem: #{tag_name}. Available: #{KNOWN_GEMS.keys.join(", ")}")
280
+ next
281
+ end
282
+
283
+ # Skip if already registered
284
+ next if registered?(tag_sym)
285
+
286
+ metadata = KNOWN_GEMS[tag_sym]
287
+ register(
288
+ tag_sym,
289
+ require_path: metadata[:require_path],
290
+ merger_class: metadata[:merger_class],
291
+ test_source: metadata[:test_source],
292
+ category: metadata[:category],
293
+ skip_instantiation: metadata[:skip_instantiation],
294
+ )
295
+ end
296
+ end
297
+
256
298
  # Get all registered gem tag names (including pre-configured known gems)
257
299
  #
258
300
  # @return [Array<Symbol>] list of registered tag names
@@ -5,7 +5,7 @@ module Ast
5
5
  # Version information for Ast::Merge
6
6
  module Version
7
7
  # Current version of the ast-merge gem
8
- VERSION = "4.0.1"
8
+ VERSION = "4.0.3"
9
9
  end
10
10
  VERSION = Version::VERSION # traditional location
11
11
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ast-merge
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -66,7 +66,7 @@ dependencies:
66
66
  version: '5.0'
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 5.0.1
69
+ version: 5.0.2
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '5.0'
77
77
  - - ">="
78
78
  - !ruby/object:Gem::Version
79
- version: 5.0.1
79
+ version: 5.0.2
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: kettle-dev
82
82
  requirement: !ruby/object:Gem::Requirement
@@ -382,10 +382,10 @@ licenses:
382
382
  - MIT
383
383
  metadata:
384
384
  homepage_uri: https://ast-merge.galtzo.com/
385
- source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v4.0.1
386
- changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v4.0.1/CHANGELOG.md
385
+ source_code_uri: https://github.com/kettle-rb/ast-merge/tree/v4.0.3
386
+ changelog_uri: https://github.com/kettle-rb/ast-merge/blob/v4.0.3/CHANGELOG.md
387
387
  bug_tracker_uri: https://github.com/kettle-rb/ast-merge/issues
388
- documentation_uri: https://www.rubydoc.info/gems/ast-merge/4.0.1
388
+ documentation_uri: https://www.rubydoc.info/gems/ast-merge/4.0.3
389
389
  funding_uri: https://github.com/sponsors/pboling
390
390
  wiki_uri: https://github.com/kettle-rb/ast-merge/wiki
391
391
  news_uri: https://www.railsbling.com/tags/ast-merge
@@ -414,7 +414,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
414
414
  - !ruby/object:Gem::Version
415
415
  version: '0'
416
416
  requirements: []
417
- rubygems_version: 4.0.3
417
+ rubygems_version: 4.0.4
418
418
  specification_version: 4
419
419
  summary: "☯️ Shared infrastructure for the *-merge gem family"
420
420
  test_files: []
metadata.gz.sig CHANGED
Binary file