json-merge 1.0.0 → 1.1.1

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.
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  | 📍 NOTE |
2
2
  | --- |
3
- | RubyGems (the [GitHub org](https://github.com/rubygems/), not the website) [suffered](https://joel.drapper.me/p/ruby-central-security-measures/) a [hostile takeover](https://pup-e.com/blog/goodbye-rubygems/) in September 2025. |
4
- | Ultimately [4 maintainers](https://www.reddit.com/r/ruby/s/gOk42POCaV) were [hard removed](https://bsky.app/profile/martinemde.com/post/3m3occezxxs2q) and a reason has been given for only 1 of those, while 2 others resigned in protest. |
5
- | It is a [complicated story](https://joel.drapper.me/p/ruby-central-takeover/) which is difficult to [parse quickly](https://joel.drapper.me/p/ruby-central-fact-check/). |
6
- | Simply put - there was active policy for adding or removing maintainers/owners of [rubygems](https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/rubygems/POLICIES.md?plain=1#L187-L196) and [bundler](https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/bundler/playbooks/TEAM_CHANGES.md), and those [policies were not followed](https://www.reddit.com/r/ruby/comments/1ove9vp/rubycentral_hates_this_one_fact/). |
7
- | I'm adding notes like this to gems because I [don't condone theft](https://joel.drapper.me/p/ruby-central/) of repositories or gems from their rightful owners. |
3
+ | RubyGems (the [GitHub org][rubygems-org], not the website) [suffered][draper-security] a [hostile takeover][ellen-takeover] in September 2025. |
4
+ | Ultimately [4 maintainers][simi-removed] were [hard removed][martin-removed] and a reason has been given for only 1 of those, while 2 others resigned in protest. |
5
+ | It is a [complicated story][draper-takeover] which is difficult to [parse quickly][draper-lies]. |
6
+ | Simply put - there was active policy for adding or removing maintainers/owners of [rubygems][rubygems-maint-policy] and [bundler][bundler-maint-policy], and those [policies were not followed][policy-fail]. |
7
+ | I'm adding notes like this to gems because I [don't condone theft][draper-theft] of repositories or gems from their rightful owners. |
8
8
  | If a similar theft happened with my repos/gems, I'd hope some would stand up for me. |
9
- | Disenfranchised former-maintainers have started [gem.coop](https://gem.coop). |
9
+ | Disenfranchised former-maintainers have started [gem.coop][gem-coop]. |
10
10
  | Once available I will publish there exclusively; unless RubyCentral makes amends with the community. |
11
- | The ["Technology for Humans: Joel Draper"](https://youtu.be/_H4qbtC5qzU?si=BvuBU90R2wAqD2E6) podcast episode by [reinteractive](https://reinteractive.com/ruby-on-rails) is the most cogent summary I'm aware of. |
12
- | See [here](https://github.com/gem-coop/gem.coop/issues/12), [here](https://gem.coop) and [here](https://martinemde.com/2025/10/05/announcing-gem-coop.html) for more info on what comes next. |
13
- | What I'm doing: A (WIP) proposal for [bundler/gem scopes](https://github.com/galtzo-floss/bundle-namespace), and a (WIP) proposal for a federated [gem server](https://github.com/galtzo-floss/gem-server). |
11
+ | The ["Technology for Humans: Joel Draper"][reinteractive-podcast] podcast episode by [reinteractive][reinteractive] is the most cogent summary I'm aware of. |
12
+ | See [here][gem-naming], [here][gem-coop] and [here][martin-ann] for more info on what comes next. |
13
+ | What I'm doing: A (WIP) proposal for [bundler/gem scopes][gem-scopes], and a (WIP) proposal for a federated [gem server][gem-server]. |
14
14
 
15
15
  [rubygems-org]: https://github.com/rubygems/
16
16
  [draper-security]: https://joel.drapper.me/p/ruby-central-security-measures/
@@ -31,7 +31,7 @@
31
31
  [rubygems-maint-policy]: https://github.com/ruby/rubygems/blob/b1ab33a3d52310a84d16b193991af07f5a6a07c0/doc/rubygems/POLICIES.md?plain=1#L187-L196
32
32
  [policy-fail]: https://www.reddit.com/r/ruby/comments/1ove9vp/rubycentral_hates_this_one_fact/
33
33
 
34
- [![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0](https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg)](https://discord.gg/3qme4XHNKN) [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5](https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg)](https://www.ruby-lang.org/) [![kettle-rb Logo by Aboling0, CC BY-SA 4.0](https://logos.galtzo.com/assets/images/kettle-rb/avatar-192px.svg)](https://github.com/kettle-rb)
34
+ [![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-i]][🖼️galtzo-discord] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![kettle-rb Logo by Aboling0, CC BY-SA 4.0][🖼️kettle-rb-i]][🖼️kettle-rb]
35
35
 
36
36
  [🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg
37
37
  [🖼️galtzo-discord]: https://discord.gg/3qme4XHNKN
@@ -42,20 +42,21 @@
42
42
 
43
43
  # ☯️ Json::Merge
44
44
 
45
- [![Version](https://img.shields.io/gem/v/json-merge.svg)](https://bestgems.org/gems/json-merge) [![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/kettle-rb/json-merge.svg)](http://github.com/kettle-rb/json-merge/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-259D6C.svg)](https://opensource.org/licenses/MIT) [![Downloads Rank](https://img.shields.io/gem/rd/json-merge.svg)](https://bestgems.org/gems/json-merge) [![Open Source Helpers](https://www.codetriage.com/kettle-rb/json-merge/badges/users.svg)](https://www.codetriage.com/kettle-rb/json-merge) [![CodeCov Test Coverage](https://codecov.io/gh/kettle-rb/json-merge/graph/badge.svg)](https://codecov.io/gh/kettle-rb/json-merge) [![Coveralls Test Coverage](https://coveralls.io/repos/github/kettle-rb/json-merge/badge.svg?branch=main)](https://coveralls.io/github/kettle-rb/json-merge?branch=main) [![QLTY Test Coverage](https://qlty.sh/gh/kettle-rb/projects/json-merge/coverage.svg)](https://qlty.sh/gh/kettle-rb/projects/json-merge/metrics/code?sort=coverageRating) [![QLTY Maintainability](https://qlty.sh/gh/kettle-rb/projects/json-merge/maintainability.svg)](https://qlty.sh/gh/kettle-rb/projects/json-merge) [![CI Heads](https://github.com/kettle-rb/json-merge/actions/workflows/heads.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/heads.yml) [![CI Runtime Dependencies @ HEAD](https://github.com/kettle-rb/json-merge/actions/workflows/dep-heads.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/dep-heads.yml) [![CI Current](https://github.com/kettle-rb/json-merge/actions/workflows/current.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/current.yml) [![CI Truffle Ruby](https://github.com/kettle-rb/json-merge/actions/workflows/truffle.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/truffle.yml) [![Deps Locked](https://github.com/kettle-rb/json-merge/actions/workflows/locked_deps.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/locked_deps.yml) [![Deps Unlocked](https://github.com/kettle-rb/json-merge/actions/workflows/unlocked_deps.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/unlocked_deps.yml) [![CI Supported](https://github.com/kettle-rb/json-merge/actions/workflows/supported.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/supported.yml) [![CI Test Coverage](https://github.com/kettle-rb/json-merge/actions/workflows/coverage.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/coverage.yml) [![CI Style](https://github.com/kettle-rb/json-merge/actions/workflows/style.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/style.yml) [![CodeQL](https://github.com/kettle-rb/json-merge/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/kettle-rb/json-merge/security/code-scanning) [![Apache SkyWalking Eyes License Compatibility Check](https://github.com/kettle-rb/json-merge/actions/workflows/license-eye.yml/badge.svg)](https://github.com/kettle-rb/json-merge/actions/workflows/license-eye.yml)
45
+ [![Version][👽versioni]][👽dl-rank] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
46
46
 
47
- `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know](https://discord.gg/3qme4XHNKN), as I may have missed the [discord notification](https://discord.gg/3qme4XHNKN).
47
+ `if ci_badges.map(&:color).detect { it != "green"}` ☝️ [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord].
48
48
 
49
49
  -----
50
+
50
51
  `if ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
51
52
 
52
- [![OpenCollective Backers](https://opencollective.com/kettle-rb/backers/badge.svg?style=flat)](https://opencollective.com/kettle-rb#backer) [![OpenCollective Sponsors](https://opencollective.com/kettle-rb/sponsors/badge.svg?style=flat)](https://opencollective.com/kettle-rb#sponsor) [![Sponsor Me on Github](https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github)](https://github.com/sponsors/pboling) [![Liberapay Goal Progress](https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat)](https://liberapay.com/pboling/donate) [![Donate on PayPal](https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal)](https://www.paypal.com/paypalme/peterboling) [![Buy me a coffee](https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat)](https://www.buymeacoffee.com/pboling) [![Donate on Polar](https://img.shields.io/badge/polar-donate-a51611.svg?style=flat)](https://polar.sh/pboling) [![Donate at ko-fi.com](https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat)](https://ko-fi.com/O5O86SNP4)
53
+ [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate at ko-fi.com][🖇kofi-img]][🖇kofi]
53
54
 
54
55
  ## 🌻 Synopsis
55
56
 
56
- Json::Merge is a standalone Ruby module that intelligently merges two versions of a JSON file using tree-sitter AST analysis. It's like a smart "git merge" specifically designed for JSON configuration files. Built on top of [ast-merge](https://github.com/kettle-rb/ast-merge), it shares the same architecture as [prism-merge](https://github.com/kettle-rb/prism-merge) for Ruby source files.
57
+ Json::Merge is a standalone Ruby module that intelligently merges two versions of a JSON file using tree-sitter AST analysis. It's like a smart "git merge" specifically designed for JSON configuration files. Built on top of [ast-merge][ast-merge], it shares the same architecture as [prism-merge][prism-merge] for Ruby source files.
57
58
 
58
- For JSONC (JSON with Comments) support, see the [jsonc-merge](https://github.com/kettle-rb/jsonc-merge) gem.
59
+ For JSONC (JSON with Comments) support, see the [jsonc-merge][jsonc-merge] gem.
59
60
 
60
61
  ### Key Features
61
62
 
@@ -68,9 +69,10 @@ For JSONC (JSON with Comments) support, see the [jsonc-merge](https://github.com
68
69
  - **Customizable**:
69
70
  - `signature_generator` - callable custom signature generators
70
71
  - `preference` - setting of `:template`, `:destination`, or a Hash for per-node-type preferences
71
- - `node_splitter` - Hash mapping node types to callables for per-node-type merge customization (see [ast-merge](https://github.com/kettle-rb/ast-merge) docs)
72
+ - `node_splitter` - Hash mapping node types to callables for per-node-type merge customization (see [ast-merge][ast-merge] docs)
72
73
  - `add_template_only_nodes` - setting to retain nodes that do not exist in destination
73
74
  - `match_refiners` - array of refiners for fuzzy matching (e.g., `ObjectMatchRefiner`)
75
+
74
76
  ### Supported Node Types
75
77
 
76
78
  | Node Type | Signature Format | Matching Behavior |
@@ -85,7 +87,7 @@ For JSONC (JSON with Comments) support, see the [jsonc-merge](https://github.com
85
87
 
86
88
  ### Example
87
89
 
88
- ``` ruby
90
+ ```ruby
89
91
  require "json/merge"
90
92
 
91
93
  template = File.read("template.json")
@@ -99,30 +101,55 @@ File.write("merged.json", result.to_json)
99
101
 
100
102
  ### The `*-merge` Gem Family
101
103
 
102
- This gem is part of a family of gems that provide intelligent merging for various file formats:
103
-
104
- | Gem | Language<br>/ Format | Parser Backend(s) | Description |
105
- |------------------------------------------|----------------------|-----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
106
- | [tree_haver][tree_haver] | Multi | MRI C, Rust, FFI, Java, Prism, Psych, Commonmarker, Markly, Citrus | **Foundation**: Cross-Ruby adapter for parsing libraries (like Faraday for HTTP) |
107
- | [ast-merge][ast-merge] | Text | internal | **Infrastructure**: Shared base classes and merge logic for all `*-merge` gems |
108
- | [bash-merge][bash-merge] | Bash | [tree-sitter-bash][ts-bash] (via tree_haver) | Smart merge for Bash scripts |
109
- | [commonmarker-merge][commonmarker-merge] | Markdown | [Commonmarker][commonmarker] (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
110
- | [dotenv-merge][dotenv-merge] | Dotenv | internal | Smart merge for `.env` files |
111
- | [json-merge][json-merge] | JSON | [tree-sitter-json][ts-json] (via tree_haver) | Smart merge for JSON files |
112
- | [jsonc-merge][jsonc-merge] | JSONC | [tree-sitter-jsonc][ts-jsonc] (via tree_haver) | ⚠️ Proof of concept; Smart merge for JSON with Comments |
113
- | [markdown-merge][markdown-merge] | Markdown | [Commonmarker][commonmarker] / [Markly][markly] (via tree_haver) | **Foundation**: Shared base for Markdown mergers with inner code block merging |
114
- | [markly-merge][markly-merge] | Markdown | [Markly][markly] (via tree_haver) | Smart merge for Markdown (CommonMark via cmark-gfm C) |
115
- | [prism-merge][prism-merge] | Ruby | [Prism][prism] (`prism` std lib gem) | Smart merge for Ruby source files |
116
- | [psych-merge][psych-merge] | YAML | [Psych][psych] (`psych` std lib gem) | Smart merge for YAML files |
117
- | [rbs-merge][rbs-merge] | RBS | [tree-sitter-bash][ts-rbs] (via tree_haver), [RBS][rbs] (`rbs` std lib gem) | Smart merge for Ruby type signatures |
118
- | [toml-merge][toml-merge] | TOML | [Citrus + toml-rb][toml-rb] (default, via tree_haver), [tree-sitter-toml][ts-toml] (via tree_haver) | Smart merge for TOML files |
104
+ The `*-merge` gem family provides intelligent, AST-based merging for various file formats. At the foundation is [tree_haver][tree_haver], which provides a unified cross-Ruby parsing API that works seamlessly across MRI, JRuby, and TruffleRuby.
105
+
106
+ | Gem | Version / CI | Language<br>/ Format | Parser Backend(s) | Description |
107
+ |------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------:|----------------------|-------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
108
+ | [tree_haver][tree_haver] | [![Version][tree_haver-gem-i]][tree_haver-gem] <br/> [![CI][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) |
109
+ | [ast-merge][ast-merge] | [![Version][ast-merge-gem-i]][ast-merge-gem] <br/> [![CI][ast-merge-ci-i]][ast-merge-ci] | Text | internal | **Infrastructure**: Shared base classes and merge logic for all `*-merge` gems |
110
+ | [bash-merge][bash-merge] | [![Version][bash-merge-gem-i]][bash-merge-gem] <br/> [![CI][bash-merge-ci-i]][bash-merge-ci] | Bash | [tree-sitter-bash][ts-bash] (via tree_haver) | Smart merge for Bash scripts |
111
+ | [commonmarker-merge][commonmarker-merge] | [![Version][commonmarker-merge-gem-i]][commonmarker-merge-gem] <br/> [![CI][commonmarker-merge-ci-i]][commonmarker-merge-ci] | Markdown | [Commonmarker][commonmarker] (via tree_haver) | Smart merge for Markdown (CommonMark via comrak Rust) |
112
+ | [dotenv-merge][dotenv-merge] | [![Version][dotenv-merge-gem-i]][dotenv-merge-gem] <br/> [![CI][dotenv-merge-ci-i]][dotenv-merge-ci] | Dotenv | internal | Smart merge for `.env` files |
113
+ | [json-merge][json-merge] | [![Version][json-merge-gem-i]][json-merge-gem] <br/> [![CI][json-merge-ci-i]][json-merge-ci] | JSON | [tree-sitter-json][ts-json] (via tree_haver) | Smart merge for JSON files |
114
+ | [jsonc-merge][jsonc-merge] | [![Version][jsonc-merge-gem-i]][jsonc-merge-gem] <br/> [![CI][jsonc-merge-ci-i]][jsonc-merge-ci] | JSONC | [tree-sitter-jsonc][ts-jsonc] (via tree_haver) | ⚠️ Proof of concept; Smart merge for JSON with Comments |
115
+ | [markdown-merge][markdown-merge] | [![Version][markdown-merge-gem-i]][markdown-merge-gem] <br/> [![CI][markdown-merge-ci-i]][markdown-merge-ci] | Markdown | [Commonmarker][commonmarker] / [Markly][markly] (via tree_haver), [Parslet][parslet] | **Foundation**: Shared base for Markdown mergers with inner code block merging |
116
+ | [markly-merge][markly-merge] | [![Version][markly-merge-gem-i]][markly-merge-gem] <br/> [![CI][markly-merge-ci-i]][markly-merge-ci] | Markdown | [Markly][markly] (via tree_haver) | Smart merge for Markdown (CommonMark via cmark-gfm C) |
117
+ | [prism-merge][prism-merge] | [![Version][prism-merge-gem-i]][prism-merge-gem] <br/> [![CI][prism-merge-ci-i]][prism-merge-ci] | Ruby | [Prism][prism] (`prism` std lib gem) | Smart merge for Ruby source files |
118
+ | [psych-merge][psych-merge] | [![Version][psych-merge-gem-i]][psych-merge-gem] <br/> [![CI][psych-merge-ci-i]][psych-merge-ci] | YAML | [Psych][psych] (`psych` std lib gem) | Smart merge for YAML files |
119
+ | [rbs-merge][rbs-merge] | [![Version][rbs-merge-gem-i]][rbs-merge-gem] <br/> [![CI][rbs-merge-ci-i]][rbs-merge-ci] | RBS | [tree-sitter-bash][ts-rbs] (via tree_haver), [RBS][rbs] (`rbs` std lib gem) | Smart merge for Ruby type signatures |
120
+ | [toml-merge][toml-merge] | [![Version][toml-merge-gem-i]][toml-merge-gem] <br/> [![CI][toml-merge-ci-i]][toml-merge-ci] | TOML | [Parslet + toml][toml], [Citrus + toml-rb][toml-rb], [tree-sitter-toml][ts-toml] (all via tree_haver) | Smart merge for TOML files |
121
+
122
+ #### Backend Platform Compatibility
123
+
124
+ tree_haver supports multiple parsing backends, but not all backends work on all Ruby platforms:
125
+
126
+ | Platform 👉️<br> TreeHaver Backend 👇️ | MRI | JRuby | TruffleRuby | Notes |
127
+ |-------------------------------------------------|:---:|:-----:|:-----------:|----------------------------------------------------------------------------|
128
+ | **MRI** ([ruby_tree_sitter][ruby_tree_sitter]) | ✅ | ❌ | ❌ | C extension, MRI only |
129
+ | **Rust** ([tree_stump][tree_stump]) | ✅ | ❌ | ❌ | Rust extension via magnus/rb-sys, MRI only |
130
+ | **FFI** ([ffi][ffi]) | ✅ | ✅ | ❌ | TruffleRuby's FFI doesn't support `STRUCT_BY_VALUE` |
131
+ | **Java** ([jtreesitter][jtreesitter]) | ❌ | ✅ | ❌ | JRuby only, requires grammar JARs |
132
+ | **Prism** ([prism][prism]) | ✅ | ✅ | ✅ | Ruby parsing, stdlib in Ruby 3.4+ |
133
+ | **Psych** ([psych][psych]) | ✅ | ✅ | ✅ | YAML parsing, stdlib |
134
+ | **Citrus** ([citrus][citrus]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
135
+ | **Parslet** ([parslet][parslet]) | ✅ | ✅ | ✅ | Pure Ruby PEG parser, no native dependencies |
136
+ | **Commonmarker** ([commonmarker][commonmarker]) | ✅ | ❌ | ❓ | Rust extension for Markdown (via [commonmarker-merge][commonmarker-merge]) |
137
+ | **Markly** ([markly][markly]) | ✅ | ❌ | ❓ | C extension for Markdown (via [markly-merge][markly-merge]) |
138
+
139
+ **Legend**: ✅ = Works, ❌ = Does not work, ❓ = Untested
140
+
141
+ **Why some backends don't work on certain platforms**:
142
+
143
+ - **JRuby**: Runs on the JVM; cannot load native C/Rust extensions (`.so` files)
144
+ - **TruffleRuby**: Has C API emulation via Sulong/LLVM, but it doesn't expose all MRI internals that native extensions require (e.g., `RBasic.flags`, `rb_gc_writebarrier`)
145
+ - **FFI on TruffleRuby**: TruffleRuby's FFI implementation doesn't support returning structs by value, which tree-sitter's C API requires
119
146
 
120
147
  **Example implementations** for the gem templating use case:
121
148
 
122
- | Gem | Purpose | Description |
123
- | --- | --- | --- |
124
- | [kettle-dev](https://github.com/kettle-rb/kettle-dev) | Gem Development | Gem templating tool using `*-merge` gems |
125
- | [kettle-jem](https://github.com/kettle-rb/kettle-jem) | Gem Templating | Gem template library with smart merge support |
149
+ | Gem | Purpose | Description |
150
+ |--------------------------|-----------------|-----------------------------------------------|
151
+ | [kettle-dev][kettle-dev] | Gem Development | Gem templating tool using `*-merge` gems |
152
+ | [kettle-jem][kettle-jem] | Gem Templating | Gem template library with smart merge support |
126
153
 
127
154
  [tree_haver]: https://github.com/kettle-rb/tree_haver
128
155
  [ast-merge]: https://github.com/kettle-rb/ast-merge
@@ -139,37 +166,100 @@ This gem is part of a family of gems that provide intelligent merging for variou
139
166
  [commonmarker-merge]: https://github.com/kettle-rb/commonmarker-merge
140
167
  [kettle-dev]: https://github.com/kettle-rb/kettle-dev
141
168
  [kettle-jem]: https://github.com/kettle-rb/kettle-jem
169
+ [tree_haver-gem]: https://bestgems.org/gems/tree_haver
170
+ [ast-merge-gem]: https://bestgems.org/gems/ast-merge
171
+ [prism-merge-gem]: https://bestgems.org/gems/prism-merge
172
+ [psych-merge-gem]: https://bestgems.org/gems/psych-merge
173
+ [json-merge-gem]: https://bestgems.org/gems/json-merge
174
+ [jsonc-merge-gem]: https://bestgems.org/gems/jsonc-merge
175
+ [bash-merge-gem]: https://bestgems.org/gems/bash-merge
176
+ [rbs-merge-gem]: https://bestgems.org/gems/rbs-merge
177
+ [dotenv-merge-gem]: https://bestgems.org/gems/dotenv-merge
178
+ [toml-merge-gem]: https://bestgems.org/gems/toml-merge
179
+ [markdown-merge-gem]: https://bestgems.org/gems/markdown-merge
180
+ [markly-merge-gem]: https://bestgems.org/gems/markly-merge
181
+ [commonmarker-merge-gem]: https://bestgems.org/gems/commonmarker-merge
182
+ [kettle-dev-gem]: https://bestgems.org/gems/kettle-dev
183
+ [kettle-jem-gem]: https://bestgems.org/gems/kettle-jem
184
+ [tree_haver-gem-i]: https://img.shields.io/gem/v/tree_haver.svg
185
+ [ast-merge-gem-i]: https://img.shields.io/gem/v/ast-merge.svg
186
+ [prism-merge-gem-i]: https://img.shields.io/gem/v/prism-merge.svg
187
+ [psych-merge-gem-i]: https://img.shields.io/gem/v/psych-merge.svg
188
+ [json-merge-gem-i]: https://img.shields.io/gem/v/json-merge.svg
189
+ [jsonc-merge-gem-i]: https://img.shields.io/gem/v/jsonc-merge.svg
190
+ [bash-merge-gem-i]: https://img.shields.io/gem/v/bash-merge.svg
191
+ [rbs-merge-gem-i]: https://img.shields.io/gem/v/rbs-merge.svg
192
+ [dotenv-merge-gem-i]: https://img.shields.io/gem/v/dotenv-merge.svg
193
+ [toml-merge-gem-i]: https://img.shields.io/gem/v/toml-merge.svg
194
+ [markdown-merge-gem-i]: https://img.shields.io/gem/v/markdown-merge.svg
195
+ [markly-merge-gem-i]: https://img.shields.io/gem/v/markly-merge.svg
196
+ [commonmarker-merge-gem-i]: https://img.shields.io/gem/v/commonmarker-merge.svg
197
+ [kettle-dev-gem-i]: https://img.shields.io/gem/v/kettle-dev.svg
198
+ [kettle-jem-gem-i]: https://img.shields.io/gem/v/kettle-jem.svg
199
+ [tree_haver-ci-i]: https://github.com/kettle-rb/tree_haver/actions/workflows/current.yml/badge.svg
200
+ [ast-merge-ci-i]: https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml/badge.svg
201
+ [prism-merge-ci-i]: https://github.com/kettle-rb/prism-merge/actions/workflows/current.yml/badge.svg
202
+ [psych-merge-ci-i]: https://github.com/kettle-rb/psych-merge/actions/workflows/current.yml/badge.svg
203
+ [json-merge-ci-i]: https://github.com/kettle-rb/json-merge/actions/workflows/current.yml/badge.svg
204
+ [jsonc-merge-ci-i]: https://github.com/kettle-rb/jsonc-merge/actions/workflows/current.yml/badge.svg
205
+ [bash-merge-ci-i]: https://github.com/kettle-rb/bash-merge/actions/workflows/current.yml/badge.svg
206
+ [rbs-merge-ci-i]: https://github.com/kettle-rb/rbs-merge/actions/workflows/current.yml/badge.svg
207
+ [dotenv-merge-ci-i]: https://github.com/kettle-rb/dotenv-merge/actions/workflows/current.yml/badge.svg
208
+ [toml-merge-ci-i]: https://github.com/kettle-rb/toml-merge/actions/workflows/current.yml/badge.svg
209
+ [markdown-merge-ci-i]: https://github.com/kettle-rb/markdown-merge/actions/workflows/current.yml/badge.svg
210
+ [markly-merge-ci-i]: https://github.com/kettle-rb/markly-merge/actions/workflows/current.yml/badge.svg
211
+ [commonmarker-merge-ci-i]: https://github.com/kettle-rb/commonmarker-merge/actions/workflows/current.yml/badge.svg
212
+ [kettle-dev-ci-i]: https://github.com/kettle-rb/kettle-dev/actions/workflows/current.yml/badge.svg
213
+ [kettle-jem-ci-i]: https://github.com/kettle-rb/kettle-jem/actions/workflows/current.yml/badge.svg
214
+ [tree_haver-ci]: https://github.com/kettle-rb/tree_haver/actions/workflows/current.yml
215
+ [ast-merge-ci]: https://github.com/kettle-rb/ast-merge/actions/workflows/current.yml
216
+ [prism-merge-ci]: https://github.com/kettle-rb/prism-merge/actions/workflows/current.yml
217
+ [psych-merge-ci]: https://github.com/kettle-rb/psych-merge/actions/workflows/current.yml
218
+ [json-merge-ci]: https://github.com/kettle-rb/json-merge/actions/workflows/current.yml
219
+ [jsonc-merge-ci]: https://github.com/kettle-rb/jsonc-merge/actions/workflows/current.yml
220
+ [bash-merge-ci]: https://github.com/kettle-rb/bash-merge/actions/workflows/current.yml
221
+ [rbs-merge-ci]: https://github.com/kettle-rb/rbs-merge/actions/workflows/current.yml
222
+ [dotenv-merge-ci]: https://github.com/kettle-rb/dotenv-merge/actions/workflows/current.yml
223
+ [toml-merge-ci]: https://github.com/kettle-rb/toml-merge/actions/workflows/current.yml
224
+ [markdown-merge-ci]: https://github.com/kettle-rb/markdown-merge/actions/workflows/current.yml
225
+ [markly-merge-ci]: https://github.com/kettle-rb/markly-merge/actions/workflows/current.yml
226
+ [commonmarker-merge-ci]: https://github.com/kettle-rb/commonmarker-merge/actions/workflows/current.yml
227
+ [kettle-dev-ci]: https://github.com/kettle-rb/kettle-dev/actions/workflows/current.yml
228
+ [kettle-jem-ci]: https://github.com/kettle-rb/kettle-jem/actions/workflows/current.yml
142
229
  [prism]: https://github.com/ruby/prism
143
230
  [psych]: https://github.com/ruby/psych
231
+ [ffi]: https://github.com/ffi/ffi
144
232
  [ts-json]: https://github.com/tree-sitter/tree-sitter-json
233
+ [ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
145
234
  [ts-bash]: https://github.com/tree-sitter/tree-sitter-bash
235
+ [ts-rbs]: https://github.com/joker1007/tree-sitter-rbs
146
236
  [ts-toml]: https://github.com/tree-sitter-grammars/tree-sitter-toml
237
+ [dotenv]: https://github.com/bkeepers/dotenv
147
238
  [rbs]: https://github.com/ruby/rbs
148
239
  [toml-rb]: https://github.com/emancu/toml-rb
240
+ [toml]: https://github.com/jm/toml
149
241
  [markly]: https://github.com/ioquatix/markly
150
242
  [commonmarker]: https://github.com/gjtorikian/commonmarker
151
-
152
-
153
- The `*-merge` gem family provides intelligent, AST-based merging for various file formats. At the foundation is [tree_haver][tree_haver], which provides a unified cross-Ruby parsing API that works seamlessly across MRI, JRuby, and TruffleRuby.
154
-
155
-
156
- [ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
157
- [dotenv]: https://github.com/bkeepers/dotenv
243
+ [ruby_tree_sitter]: https://github.com/Faveod/ruby-tree-sitter
244
+ [tree_stump]: https://github.com/joker1007/tree_stump
245
+ [jtreesitter]: https://central.sonatype.com/artifact/io.github.tree-sitter/jtreesitter
246
+ [citrus]: https://github.com/mjackson/citrus
247
+ [parslet]: https://github.com/kschiess/parslet
158
248
 
159
249
  ## 💡 Info you can shake a stick at
160
250
 
161
- | Tokens to Remember | [![Gem name](https://img.shields.io/badge/name-json--merge-3C2D2D.svg?style=square&logo=rubygems&logoColor=red)](https://bestgems.org/gems/json-merge) [![Gem namespace](https://img.shields.io/badge/namespace-Json::Merge-3C2D2D.svg?style=square&logo=ruby&logoColor=white)](https://github.com/kettle-rb/json-merge) |
251
+ | Tokens to Remember | [![Gem name][⛳️name-img]][👽dl-rank] [![Gem namespace][⛳️namespace-img]][📜src-gh] |
162
252
  | --- | --- |
163
- | Works with JRuby | [![JRuby 10.0 Compat](https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green)](https://github.com/kettle-rb/json-merge/actions/workflows/current.yml) [![JRuby HEAD Compat](https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue)](https://github.com/kettle-rb/json-merge/actions/workflows/heads.yml) |
164
- | Works with Truffle Ruby | [![Truffle Ruby 23.1 Compat](https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink)](https://github.com/kettle-rb/json-merge/actions/workflows/truffle.yml) [![Truffle Ruby 24.1 Compat](https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green)](https://github.com/kettle-rb/json-merge/actions/workflows/current.yml) |
165
- | Works with MRI Ruby 3 | [![Ruby 3.2 Compat](https://img.shields.io/badge/Ruby-3.2-CC342D?style=for-the-badge&logo=ruby&logoColor=white)](https://github.com/kettle-rb/json-merge/actions/workflows/supported.yml) [![Ruby 3.3 Compat](https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white)](https://github.com/kettle-rb/json-merge/actions/workflows/supported.yml) [![Ruby 3.4 Compat](https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green)](https://github.com/kettle-rb/json-merge/actions/workflows/current.yml) [![Ruby HEAD Compat](https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue)](https://github.com/kettle-rb/json-merge/actions/workflows/heads.yml) |
166
- | Support & Community | [![Join Me on Daily.dev's RubyFriends](https://img.shields.io/badge/daily.dev-%F0%9F%92%8E_Ruby_Friends-0A0A0A?style=for-the-badge&logo=dailydotdev&logoColor=white)](https://app.daily.dev/squads/rubyfriends) [![Live Chat on Discord](https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord)](https://discord.gg/3qme4XHNKN) [![Get help from me on Upwork](https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white)](https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share) [![Get help from me on Codementor](https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white)](https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github) |
167
- | Source | [![Source on GitLab.com](https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange)](https://gitlab.com/kettle-rb/json-merge/) [![Source on CodeBerg.org](https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue)](https://codeberg.org/kettle-rb/json-merge) [![Source on Github.com](https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green)](https://github.com/kettle-rb/json-merge) [![The best SHA: dQw4w9WgXcQ\!](https://img.shields.io/badge/KLOC-4.308-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue)](https://www.youtube.com/watch?v=dQw4w9WgXcQ) |
168
- | Documentation | [![Current release on RubyDoc.info](https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white)](http://rubydoc.info/gems/json-merge) [![YARD on Galtzo.com](https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white)](https://json-merge.galtzo.com) [![Maintainer Blog](https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange)](http://www.railsbling.com/tags/json-merge) [![GitLab Wiki](https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=gitlab&logoColor=white)](https://gitlab.com/kettle-rb/json-merge/-/wikis/home) [![GitHub Wiki](https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/kettle-rb/json-merge/wiki) |
169
- | Compliance | [![License: MIT](https://img.shields.io/badge/License-MIT-259D6C.svg)](https://opensource.org/licenses/MIT) [![Compatible with Apache Software Projects: Verified by SkyWalking Eyes](https://img.shields.io/badge/Apache_Compatible:_Category_A-%E2%9C%93-259D6C.svg?style=flat&logo=Apache)](https://dev.to/galtzo/how-to-check-license-compatibility-41h0) [![📄ilo-declaration-img](https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat)](https://www.ilo.org/declaration/lang--en/index.htm) [![Security Policy](https://img.shields.io/badge/security-policy-259D6C.svg?style=flat)](SECURITY.md) [![Contributor Covenant 2.1](https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg)](CODE_OF_CONDUCT.md) [![SemVer 2.0.0](https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat)](https://semver.org/spec/v2.0.0.html) |
170
- | Style | [![Enforced Code Style Linter](https://img.shields.io/badge/code_style_&_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white)](https://github.com/rubocop-lts/rubocop-lts) [![Keep-A-Changelog 1.0.0](https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat)](https://keepachangelog.com/en/1.0.0/) [![Gitmoji Commits](https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square)](https://gitmoji.dev) [![Compatibility appraised by: appraisal2](https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white)](https://github.com/appraisal-rb/appraisal2) |
171
- | Maintainer 🎖️ | [![Follow Me on LinkedIn](https://img.shields.io/badge/PeterBoling-LinkedIn-0B66C2?style=flat&logo=newjapanprowrestling)](http://www.linkedin.com/in/peterboling) [![Follow Me on Ruby.Social](https://img.shields.io/mastodon/follow/109447111526622197?domain=https://ruby.social&style=flat&logo=mastodon&label=Ruby%20@galtzo)](https://ruby.social/@galtzo) [![Follow Me on Bluesky](https://img.shields.io/badge/@galtzo.com-0285FF?style=flat&logo=bluesky&logoColor=white)](https://bsky.app/profile/galtzo.com) [![Contact Maintainer](https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red)](http://www.railsbling.com/contact) [![My technical writing](https://img.shields.io/badge/dev.to-0A0A0A?style=flat&logo=devdotto&logoColor=white)](https://dev.to/galtzo) |
172
- | `...` 💖 | [![Find Me on WellFound:](https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound)](https://wellfound.com/u/peter-boling) [![Find Me on CrunchBase](https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase)](https://www.crunchbase.com/person/peter-boling) [![My LinkTree](https://img.shields.io/badge/galtzo-purple?style=flat&logo=linktree)](https://linktr.ee/galtzo) [![More About Me](https://img.shields.io/badge/about.me-0A0A0A?style=flat&logo=aboutme&logoColor=white)](https://about.me/peter.boling) [🧊](https://codeberg.org/pboling) [🐙](https://github.org/pboling) [🛖](https://sr.ht/~galtzo/) [🧪](https://gitlab.com/pboling) |
253
+ | Works with JRuby | [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf] |
254
+ | Works with Truffle Ruby | [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] |
255
+ | Works with MRI Ruby 3 | [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] |
256
+ | Support & Community | [![Join Me on Daily.dev's RubyFriends][✉️ruby-friends-img]][✉️ruby-friends] [![Live Chat on Discord][✉️discord-invite-img-ftb]][🖼️galtzo-discord] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] |
257
+ | Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ\!](https://img.shields.io/badge/KLOC-4.308-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue)][🧮kloc] |
258
+ | Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![GitLab Wiki][📜gl-wiki-img]][📜gl-wiki] [![GitHub Wiki][📜gh-wiki-img]][📜gh-wiki] |
259
+ | Compliance | [![License: MIT][📄license-img]][📄license-ref] [![Compatible with Apache Software Projects: Verified by SkyWalking Eyes][📄license-compat-img]][📄license-compat] [![📄ilo-declaration-img][📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] |
260
+ | Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] |
261
+ | Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] |
262
+ | `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] |
173
263
 
174
264
  ### Compatibility
175
265
 
@@ -177,25 +267,25 @@ Compatible with MRI Ruby 3.2.0+, and concordant releases of JRuby, and TruffleRu
177
267
 
178
268
  | 🚚 *Amazing* test matrix was brought to you by | 🔎 appraisal2 🔎 and the color 💚 green 💚 |
179
269
  | --- | --- |
180
- | 👟 Check it out\! | ✨ [github.com/appraisal-rb/appraisal2](https://github.com/appraisal-rb/appraisal2) ✨ |
270
+ | 👟 Check it out\! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ |
181
271
 
182
272
  ### Federated DVCS
183
273
 
184
274
  <details markdown="1">
185
275
  <summary>Find this repo on federated forges (Coming soon!)</summary>
186
276
 
187
- | Federated [DVCS](https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/) Repository | Status | Issues | PRs | Wiki | CI | Discussions |
277
+ | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
188
278
  | --- | --- | --- | --- | --- | --- | --- |
189
- | 🧪 [kettle-rb/json-merge on GitLab](https://gitlab.com/kettle-rb/json-merge/) | The Truth | [💚](https://gitlab.com/kettle-rb/json-merge/-/issues) | [💚](https://gitlab.com/kettle-rb/json-merge/-/merge_requests) | [💚](https://gitlab.com/kettle-rb/json-merge/-/wikis/home) | 🐭 Tiny Matrix | ➖ |
190
- | 🧊 [kettle-rb/json-merge on CodeBerg](https://codeberg.org/kettle-rb/json-merge) | An Ethical Mirror ([Donate](https://donate.codeberg.org/)) | [💚](https://codeberg.org/kettle-rb/json-merge/issues) | [💚](https://codeberg.org/kettle-rb/json-merge/pulls) | ➖ | ⭕️ No Matrix | ➖ |
191
- | 🐙 [kettle-rb/json-merge on GitHub](https://github.com/kettle-rb/json-merge) | Another Mirror | [💚](https://github.com/kettle-rb/json-merge/issues) | [💚](https://github.com/kettle-rb/json-merge/pulls) | [💚](https://github.com/kettle-rb/json-merge/wiki) | 💯 Full Matrix | [💚](https://github.com/kettle-rb/json-merge/discussions) |
192
- | 🎮️ [Discord Server](https://discord.gg/3qme4XHNKN) | [![Live Chat on Discord](https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord)](https://discord.gg/3qme4XHNKN) | [Let's](https://discord.gg/3qme4XHNKN) | [talk](https://discord.gg/3qme4XHNKN) | [about](https://discord.gg/3qme4XHNKN) | [this](https://discord.gg/3qme4XHNKN) | [library\!](https://discord.gg/3qme4XHNKN) |
279
+ | 🧪 [kettle-rb/json-merge on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜gl-wiki] | 🐭 Tiny Matrix | ➖ |
280
+ | 🧊 [kettle-rb/json-merge on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ |
281
+ | 🐙 [kettle-rb/json-merge on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | [💚][📜gh-wiki] | 💯 Full Matrix | [💚][gh-discussions] |
282
+ | 🎮️ [Discord Server][🖼️galtzo-discord] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][🖼️galtzo-discord] | [Let's][🖼️galtzo-discord] | [talk][🖼️galtzo-discord] | [about][🖼️galtzo-discord] | [this][🖼️galtzo-discord] | [library\!][🖼️galtzo-discord] |
193
283
 
194
284
  </details>
195
285
 
196
286
  [gh-discussions]: https://github.com/kettle-rb/json-merge/discussions
197
287
 
198
- ### Enterprise Support [![Tidelift](https://tidelift.com/badges/package/rubygems/json-merge)](https://tidelift.com/subscription/pkg/rubygems-json-merge?utm_source=rubygems-json-merge&utm_medium=referral&utm_campaign=readme)
288
+ ### Enterprise Support [![Tidelift](https://tidelift.com/badges/package/rubygems/json-merge)][🏙️entsup-tidelift]
199
289
 
200
290
  Available as part of the Tidelift Subscription.
201
291
 
@@ -204,33 +294,34 @@ Available as part of the Tidelift Subscription.
204
294
 
205
295
  The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
206
296
 
207
- [![Get help from me on Tidelift](https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white)](https://tidelift.com/subscription/pkg/rubygems-json-merge?utm_source=rubygems-json-merge&utm_medium=referral&utm_campaign=readme)
297
+ [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
208
298
 
209
299
  - 💡Subscribe for support guarantees covering *all* your FLOSS dependencies
210
300
 
211
- - 💡Tidelift is part of [Sonar](https://blog.tidelift.com/tidelift-joins-sonar)
301
+ - 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]
212
302
 
213
- - 💡Tidelift pays maintainers to maintain the software you depend on\!<br/>📊`@`Pointy Haired Boss: An [enterprise support](https://tidelift.com/subscription/pkg/rubygems-json-merge?utm_source=rubygems-json-merge&utm_medium=referral&utm_campaign=readme) subscription is "[never gonna let you down](https://www.youtube.com/watch?v=dQw4w9WgXcQ)", and *supports* open source maintainers
303
+ - 💡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
214
304
  Alternatively:
215
305
 
216
- - [![Live Chat on Discord](https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord)](https://discord.gg/3qme4XHNKN)
306
+ - [![Live Chat on Discord][✉️discord-invite-img-ftb]][🖼️galtzo-discord]
307
+
308
+ - [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork]
217
309
 
218
- - [![Get help from me on Upwork](https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white)](https://www.upwork.com/freelancers/~014942e9b056abdf86?mp_source=share)
310
+ - [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor]
219
311
 
220
- - [![Get help from me on Codementor](https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white)](https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github)
221
312
  </details>
222
313
 
223
314
  ## ✨ Installation
224
315
 
225
316
  Install the gem and add to the application's Gemfile by executing:
226
317
 
227
- ``` console
318
+ ```console
228
319
  bundle add json-merge
229
320
  ```
230
321
 
231
322
  If bundler is not being used to manage dependencies, install the gem by executing:
232
323
 
233
- ``` console
324
+ ```console
234
325
  gem install json-merge
235
326
  ```
236
327
 
@@ -239,19 +330,19 @@ gem install json-merge
239
330
  <details markdown="1">
240
331
  <summary>For Medium or High Security Installations</summary>
241
332
 
242
- This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512](https://gitlab.com/kettle-rb/json-merge/-/tree/main/checksums) checksums by
243
- [stone\_checksums](https://github.com/galtzo-floss/stone_checksums). Be sure the gem you install hasn’t been tampered with
333
+ This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by
334
+ [stone\_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with
244
335
  by following the instructions below.
245
336
 
246
337
  Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate:
247
338
 
248
- ``` console
339
+ ```console
249
340
  gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem)
250
341
  ```
251
342
 
252
343
  You only need to do that once. Then proceed to install with:
253
344
 
254
- ``` console
345
+ ```console
255
346
  gem install json-merge -P HighSecurity
256
347
  ```
257
348
 
@@ -259,7 +350,7 @@ The `HighSecurity` trust profile will verify signed gems, and not allow the inst
259
350
 
260
351
  If you want to up your security game full-time:
261
352
 
262
- ``` console
353
+ ```console
263
354
  bundle config set --global trust-policy MediumSecurity
264
355
  ```
265
356
 
@@ -274,14 +365,15 @@ NOTE: Be prepared to track down certs for signed gems and add them the same way
274
365
  This gem requires the `tree-sitter-json` parser library to be installed on your system.
275
366
  The parser is a native shared library (`.so` on Linux, `.dylib` on macOS) that provides
276
367
  JSON syntax parsing capabilities. For JSONC (JSON with Comments) support, use the
277
- [jsonc-merge](https://github.com/kettle-rb/jsonc-merge) gem instead.
368
+ [jsonc-merge][jsonc-merge] gem instead.
278
369
 
279
370
  #### Option 1: Pre-built Binaries (Recommended)
280
371
 
281
372
  Download pre-built parsers from [Faveod/tree-sitter-parsers](https://github.com/Faveod/tree-sitter-parsers/releases):
282
373
 
283
374
  **Linux (x64):**
284
- ``` console
375
+
376
+ ```console
285
377
  # Download and extract
286
378
  curl -Lo parsers.tar.gz https://github.com/Faveod/tree-sitter-parsers/releases/download/v4.10/tree-sitter-parsers-4.10-linux-x64.tar.gz
287
379
  tar -xzf parsers.tar.gz
@@ -297,13 +389,15 @@ export TREE_SITTER_JSON_PATH="$HOME/.local/lib/tree-sitter/libtree-sitter-json.s
297
389
  ```
298
390
 
299
391
  **Debian/Ubuntu (amd64):**
300
- ``` console
392
+
393
+ ```console
301
394
  curl -Lo parsers.deb https://github.com/Faveod/tree-sitter-parsers/releases/download/v4.10/tree-sitter-parsers-4.10-amd64.deb
302
395
  sudo dpkg -i parsers.deb
303
396
  ```
304
397
 
305
398
  **macOS (Apple Silicon):**
306
- ``` console
399
+
400
+ ```console
307
401
  curl -Lo parsers.tar.gz https://github.com/Faveod/tree-sitter-parsers/releases/download/v4.10/tree-sitter-parsers-4.10-macos-arm64.tar.gz
308
402
  tar -xzf parsers.tar.gz
309
403
 
@@ -315,7 +409,7 @@ export TREE_SITTER_JSON_PATH="$HOME/.local/lib/tree-sitter/libtree-sitter-json.d
315
409
 
316
410
  #### Option 2: Build from Source
317
411
 
318
- ``` console
412
+ ```console
319
413
  git clone https://github.com/tree-sitter/tree-sitter-json.git
320
414
  cd tree-sitter-json
321
415
  make
@@ -329,7 +423,8 @@ sudo cp libtree-sitter-json.dylib /usr/local/lib/ # macOS
329
423
  Some package managers provide tree-sitter parsers:
330
424
 
331
425
  **Fedora Atomic (Silverblue, Kinoite, Bazzite, Aurora, etc.):**
332
- ``` console
426
+
427
+ ```console
333
428
  # Install via rpm-ostree (requires reboot)
334
429
  rpm-ostree install libtree-sitter-json
335
430
 
@@ -339,12 +434,14 @@ export TREE_SITTER_JSON_PATH="/usr/lib64/libtree-sitter-json.so"
339
434
  ```
340
435
 
341
436
  **Fedora (traditional):**
342
- ``` console
437
+
438
+ ```console
343
439
  sudo dnf install libtree-sitter-json
344
440
  ```
345
441
 
346
442
  **Arch Linux:**
347
- ``` console
443
+
444
+ ```console
348
445
  # Check AUR for tree-sitter-json
349
446
  yay -S tree-sitter-json
350
447
  ```
@@ -354,16 +451,18 @@ yay -S tree-sitter-json
354
451
  If the parser is not in a standard location (`/usr/lib/`, `/usr/lib64/`, `/usr/local/lib/`),
355
452
  set the `TREE_SITTER_JSON_PATH` environment variable to point to the parser library:
356
453
 
357
- ``` console
454
+ ```console
358
455
  export TREE_SITTER_JSON_PATH="/path/to/libtree-sitter-json.so"
359
456
  ```
360
457
 
361
458
  **Note:** Some distributions install the library with a version number suffix
362
459
  (e.g., `libtree-sitter-json.so.14` instead of `libtree-sitter-json.so`).
363
460
  If the gem can't find the parser, check for versioned files and either:
461
+
364
462
  - Set `TREE_SITTER_JSON_PATH` to the full versioned path, or
365
463
  - Create a symlink: `sudo ln -s /usr/lib64/libtree-sitter-json.so.14 /usr/lib64/libtree-sitter-json.so`
366
464
  Add this to your shell profile (`.bashrc`, `.zshrc`, etc.) for persistence.
465
+
367
466
  ### 💎 Ruby Interface Gems
368
467
 
369
468
  In addition to the tree-sitter parser library, you need a Ruby gem that provides
@@ -371,9 +470,9 @@ bindings to tree-sitter. Choose **one** of the following based on your Ruby impl
371
470
 
372
471
  | Gem | Ruby Support | Description |
373
472
  | --- | --- | --- |
374
- | [ruby\_tree\_sitter](https://github.com/Faveod/ruby_tree_sitter) | MRI only | C extension bindings (recommended for MRI) |
375
- | [tree\_stump](https://github.com/nickstenning/tree_stump) | MRI (maybe JRuby) | Rust-based bindings via Rutie |
376
- | [ffi](https://github.com/ffi/ffi) | MRI, JRuby, TruffleRuby | Generic FFI bindings (used by tree\_haver's FFI backend) |
473
+ | [ruby\_tree\_sitter][ruby_tree_sitter] | MRI only | C extension bindings (recommended for MRI) |
474
+ | [tree\_stump][tree_stump] | MRI (maybe JRuby) | Rust-based bindings via Rutie |
475
+ | [ffi][ffi] | MRI, JRuby, TruffleRuby | Generic FFI bindings (used by tree\_haver's FFI backend) |
377
476
 
378
477
  [ruby_tree_sitter]: https://github.com/Faveod/ruby_tree_sitter
379
478
  [tree_stump]: https://github.com/nickstenning/tree_stump
@@ -381,25 +480,25 @@ bindings to tree-sitter. Choose **one** of the following based on your Ruby impl
381
480
 
382
481
  #### For MRI Ruby (Recommended)
383
482
 
384
- ``` console
483
+ ```console
385
484
  gem install ruby_tree_sitter
386
485
  ```
387
486
 
388
487
  Or add to your Gemfile:
389
488
 
390
- ``` ruby
489
+ ```ruby
391
490
  gem "ruby_tree_sitter", "~> 2.0"
392
491
  ```
393
492
 
394
493
  #### For JRuby or TruffleRuby
395
494
 
396
- ``` console
495
+ ```console
397
496
  gem install ffi
398
497
  ```
399
498
 
400
499
  Or add to your Gemfile:
401
500
 
402
- ``` ruby
501
+ ```ruby
403
502
  gem "ffi"
404
503
  ```
405
504
 
@@ -415,7 +514,7 @@ you must use the FFI backend.
415
514
 
416
515
  Control which version to use when nodes have matching signatures but different content:
417
516
 
418
- ``` ruby
517
+ ```ruby
419
518
  # Use template version (for config updates)
420
519
  merger = Json::Merge::SmartMerger.new(
421
520
  template,
@@ -435,7 +534,7 @@ merger = Json::Merge::SmartMerger.new(
435
534
 
436
535
  Control whether to add nodes that only exist in the template:
437
536
 
438
- ``` ruby
537
+ ```ruby
439
538
  # Add template-only nodes
440
539
  merger = Json::Merge::SmartMerger.new(
441
540
  template,
@@ -452,8 +551,10 @@ When JSON object properties (key-value pairs) don't match by exact key name, the
452
551
  - Similar key names (e.g., `databaseUrl` vs `database_url`)
453
552
  - Keys with typos or different naming conventions (camelCase vs snake\_case)
454
553
  - Array elements with similar structure or content
554
+
455
555
  <!-- end list -->
456
- ``` ruby
556
+
557
+ ```ruby
457
558
  # Enable object fuzzy matching
458
559
  merger = Json::Merge::SmartMerger.new(
459
560
  template,
@@ -472,7 +573,7 @@ merger = Json::Merge::SmartMerger.new(
472
573
  | `key_weight` | 0.7 | Weight for key name similarity |
473
574
  | `value_weight` | 0.3 | Weight for value similarity |
474
575
 
475
- ``` ruby
576
+ ```ruby
476
577
  # Custom weights for key-centric matching
477
578
  refiner = Json::Merge::ObjectMatchRefiner.new(
478
579
  threshold: 0.6,
@@ -485,7 +586,7 @@ refiner = Json::Merge::ObjectMatchRefiner.new(
485
586
 
486
587
  Enable debug logging to see merge decisions:
487
588
 
488
- ``` bash
589
+ ```bash
489
590
  export JSON_MERGE_DEBUG=1
490
591
  ```
491
592
 
@@ -493,7 +594,7 @@ export JSON_MERGE_DEBUG=1
493
594
 
494
595
  ### Merging Two JSON Files
495
596
 
496
- ``` ruby
597
+ ```ruby
497
598
  require "json/merge"
498
599
 
499
600
  template_content = File.read("template.json")
@@ -507,7 +608,7 @@ File.write("merged.json", result.to_json)
507
608
 
508
609
  ### Analyzing a JSON File
509
610
 
510
- ``` ruby
611
+ ```ruby
511
612
  require "json/merge"
512
613
 
513
614
  source = File.read("config.json")
@@ -525,7 +626,7 @@ end
525
626
  When property names differ between template and destination (e.g., naming convention changes),
526
627
  use the `ObjectMatchRefiner`:
527
628
 
528
- ``` ruby
629
+ ```ruby
529
630
  require "json/merge"
530
631
 
531
632
  template = <<~JSON
@@ -565,7 +666,7 @@ result = merger.merge
565
666
 
566
667
  The `ObjectMatchRefiner` also handles array elements with similar structure:
567
668
 
568
- ``` ruby
669
+ ```ruby
569
670
  template = <<~JSON
570
671
  {
571
672
  "users": [
@@ -601,17 +702,17 @@ Raising a monthly budget of... "dollars" would make the project more sustainable
601
702
 
602
703
  We welcome both individual and corporate sponsors\! We also offer a
603
704
  wide array of funding channels to account for your preferences
604
- (although currently [Open Collective](https://opencollective.com/kettle-rb) is our preferred funding platform).
705
+ (although currently [Open Collective][🖇osc] is our preferred funding platform).
605
706
 
606
707
  **If you're working in a company that's making significant use of kettle-rb tools we'd
607
708
  appreciate it if you suggest to your company to become a kettle-rb sponsor.**
608
709
 
609
710
  You can support the development of kettle-rb tools via
610
- [GitHub Sponsors](https://github.com/sponsors/pboling),
611
- [Liberapay](https://liberapay.com/pboling/donate),
612
- [PayPal](https://www.paypal.com/paypalme/peterboling),
613
- [Open Collective](https://opencollective.com/kettle-rb)
614
- and [Tidelift](https://tidelift.com/subscription/pkg/rubygems-json-merge?utm_source=rubygems-json-merge&utm_medium=referral&utm_campaign=readme).
711
+ [GitHub Sponsors][🖇sponsor],
712
+ [Liberapay][⛳liberapay],
713
+ [PayPal][🖇paypal],
714
+ [Open Collective][🖇osc]
715
+ and [Tidelift][🏙️entsup-tidelift].
615
716
 
616
717
  | 📍 NOTE |
617
718
  | --- |
@@ -619,22 +720,22 @@ and [Tidelift](https://tidelift.com/subscription/pkg/rubygems-json-merge?utm_sou
619
720
 
620
721
  ### Open Collective for Individuals
621
722
 
622
- Support us with a monthly donation and help us continue our activities. \[[Become a backer](https://opencollective.com/kettle-rb#backer)\]
723
+ Support us with a monthly donation and help us continue our activities. \[[Become a backer][🖇osc-backers]\]
623
724
 
624
- NOTE: [kettle-readme-backers](https://github.com/kettle-rb/json-merge/blob/main/exe/kettle-readme-backers) updates this list every day, automatically.
725
+ NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
625
726
 
626
727
  <!-- OPENCOLLECTIVE-INDIVIDUALS:START -->
627
- No backers yet. Be the first\!
728
+ No backers yet. Be the first!
628
729
  <!-- OPENCOLLECTIVE-INDIVIDUALS:END -->
629
730
 
630
731
  ### Open Collective for Organizations
631
732
 
632
- Become a sponsor and get your logo on our README on GitHub with a link to your site. \[[Become a sponsor](https://opencollective.com/kettle-rb#sponsor)\]
733
+ Become a sponsor and get your logo on our README on GitHub with a link to your site. \[[Become a sponsor][🖇osc-sponsors]\]
633
734
 
634
- NOTE: [kettle-readme-backers](https://github.com/kettle-rb/json-merge/blob/main/exe/kettle-readme-backers) updates this list every day, automatically.
735
+ NOTE: [kettle-readme-backers][kettle-readme-backers] updates this list every day, automatically.
635
736
 
636
737
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:START -->
637
- No sponsors yet. Be the first\!
738
+ No sponsors yet. Be the first!
638
739
  <!-- OPENCOLLECTIVE-ORGANIZATIONS:END -->
639
740
 
640
741
  [kettle-readme-backers]: https://github.com/kettle-rb/json-merge/blob/main/exe/kettle-readme-backers
@@ -645,48 +746,48 @@ I’m driven by a passion to foster a thriving open-source community – a space
645
746
 
646
747
  If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`.
647
748
 
648
- I’m developing a new library, [floss\_funding](https://github.com/galtzo-floss/floss_funding), designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.
749
+ I’m developing a new library, [floss\_funding][🖇floss-funding-gem], designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.
649
750
 
650
- **[Floss-Funding.dev](https://floss-funding.dev): 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
751
+ **[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags**
651
752
 
652
- [![OpenCollective Backers](https://opencollective.com/kettle-rb/backers/badge.svg?style=flat)](https://opencollective.com/kettle-rb#backer) [![OpenCollective Sponsors](https://opencollective.com/kettle-rb/sponsors/badge.svg?style=flat)](https://opencollective.com/kettle-rb#sponsor) [![Sponsor Me on Github](https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github)](https://github.com/sponsors/pboling) [![Liberapay Goal Progress](https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat)](https://liberapay.com/pboling/donate) [![Donate on PayPal](https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal)](https://www.paypal.com/paypalme/peterboling) [![Buy me a coffee](https://img.shields.io/badge/buy_me_a_coffee-%E2%9C%93-a51611.svg?style=flat)](https://www.buymeacoffee.com/pboling) [![Donate on Polar](https://img.shields.io/badge/polar-donate-a51611.svg?style=flat)](https://polar.sh/pboling) [![Donate to my FLOSS efforts at ko-fi.com](https://img.shields.io/badge/ko--fi-%E2%9C%93-a51611.svg?style=flat)](https://ko-fi.com/O5O86SNP4) [![Donate to my FLOSS efforts using Patreon](https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat)](https://patreon.com/galtzo)
753
+ [![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS efforts using Patreon][🖇patreon-img]][🖇patreon]
653
754
 
654
755
  ## 🔐 Security
655
756
 
656
- See [SECURITY.md](SECURITY.md).
757
+ See [SECURITY.md][🔐security].
657
758
 
658
759
  ## 🤝 Contributing
659
760
 
660
761
  If you need some ideas of where to help, you could work on adding more code coverage,
661
- or if it is already 💯 (see [below](#code-coverage)) check [reek](REEK), [issues](https://github.com/kettle-rb/json-merge/issues), or [PRs](https://github.com/kettle-rb/json-merge/pulls),
762
+ or if it is already 💯 (see [below](#code-coverage)) check [reek](REEK), [issues][🤝gh-issues], or [PRs][🤝gh-pulls],
662
763
  or use the gem and think about how it could be better.
663
764
 
664
- We [![Keep A Changelog](https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat)](https://keepachangelog.com/en/1.0.0/) so if you make changes, remember to update it.
765
+ We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it.
665
766
 
666
- See [CONTRIBUTING.md](CONTRIBUTING.md) for more detailed instructions.
767
+ See [CONTRIBUTING.md][🤝contributing] for more detailed instructions.
667
768
 
668
769
  ### 🚀 Release Instructions
669
770
 
670
- See [CONTRIBUTING.md](CONTRIBUTING.md).
771
+ See [CONTRIBUTING.md][🤝contributing].
671
772
 
672
773
  ### Code Coverage
673
774
 
674
- [![Coverage Graph](https://codecov.io/gh/kettle-rb/json-merge/graphs/tree.svg)](https://codecov.io/gh/kettle-rb/json-merge)
775
+ [![Coverage Graph][🏀codecov-g]][🏀codecov]
675
776
 
676
- [![Coveralls Test Coverage](https://coveralls.io/repos/github/kettle-rb/json-merge/badge.svg?branch=main)](https://coveralls.io/github/kettle-rb/json-merge?branch=main)
777
+ [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls]
677
778
 
678
- [![QLTY Test Coverage](https://qlty.sh/gh/kettle-rb/projects/json-merge/coverage.svg)](https://qlty.sh/gh/kettle-rb/projects/json-merge/metrics/code?sort=coverageRating)
779
+ [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov]
679
780
 
680
781
  ### 🪇 Code of Conduct
681
782
 
682
783
  Everyone interacting with this project's codebases, issue trackers,
683
- chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1](https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg)](CODE_OF_CONDUCT.md).
784
+ chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct].
684
785
 
685
786
  ## 🌈 Contributors
686
787
 
687
- [![Contributors](https://contrib.rocks/image?repo=kettle-rb/json-merge)](https://github.com/kettle-rb/json-merge/graphs/contributors)
788
+ [![Contributors][🖐contributors-img]][🖐contributors]
688
789
 
689
- Made with [contributors-img](https://contrib.rocks).
790
+ Made with [contributors-img][🖐contrib-rocks].
690
791
 
691
792
  Also see GitLab Contributors: <https://gitlab.com/kettle-rb/json-merge/-/graphs/main>
692
793
 
@@ -705,23 +806,23 @@ Also see GitLab Contributors: <https://gitlab.com/kettle-rb/json-merge/-/graphs/
705
806
 
706
807
  ## 📌 Versioning
707
808
 
708
- This Library adheres to [![Semantic Versioning 2.0.0](https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat)](https://semver.org/spec/v2.0.0.html).
809
+ This Library adheres to [![Semantic Versioning 2.0.0][📌semver-img]][📌semver].
709
810
  Violations of this scheme should be reported as bugs.
710
811
  Specifically, if a minor or patch version is released that breaks backward compatibility,
711
812
  a new version should be immediately released that restores compatibility.
712
813
  Breaking changes to the public API will only be introduced with new major versions.
713
814
 
714
815
  > dropping support for a platform is both obviously and objectively a breaking change <br/>
715
- > —Jordan Harband ([@ljharb](https://github.com/ljharb), maintainer of SemVer) [in SemVer issue 716](https://github.com/semver/semver/issues/716#issuecomment-869336139)
816
+ > —Jordan Harband ([@ljharb](https://github.com/ljharb), maintainer of SemVer) [in SemVer issue 716][📌semver-breaking]
716
817
 
717
818
  I understand that policy doesn't work universally ("exceptions to every rule\!"),
718
819
  but it is the policy here.
719
820
  As such, in many cases it is good to specify a dependency on this library using
720
- the [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/#pessimistic-version-constraint) with two digits of precision.
821
+ the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
721
822
 
722
823
  For example:
723
824
 
724
- ``` ruby
825
+ ```ruby
725
826
  spec.add_dependency("json-merge", "~> 1.0")
726
827
  ```
727
828
 
@@ -734,16 +835,17 @@ is a *breaking change* to an API, and for that reason the bike shedding is endle
734
835
  To get a better understanding of how SemVer is intended to work over a project's lifetime,
735
836
  read this article from the creator of SemVer:
736
837
 
737
- - ["Major Version Numbers are Not Sacred"](https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html)
838
+ - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
839
+
738
840
  </details>
739
841
 
740
- See [CHANGELOG.md](CHANGELOG.md) for a list of releases.
842
+ See [CHANGELOG.md][📌changelog] for a list of releases.
741
843
 
742
844
  ## 📄 License
743
845
 
744
846
  The gem is available as open source under the terms of
745
- the [MIT License](LICENSE.txt) [![License: MIT](https://img.shields.io/badge/License-MIT-259D6C.svg)](https://opensource.org/licenses/MIT).
746
- See [LICENSE.txt](LICENSE.txt) for the official [Copyright Notice](https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year).
847
+ the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref].
848
+ See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer].
747
849
 
748
850
  ### © Copyright
749
851
 
@@ -770,11 +872,11 @@ Please consider sponsoring me or the project.
770
872
 
771
873
  To join the community or get help 👇️ Join the Discord.
772
874
 
773
- [![Live Chat on Discord](https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord)](https://discord.gg/3qme4XHNKN)
875
+ [![Live Chat on Discord][✉️discord-invite-img-ftb]][🖼️galtzo-discord]
774
876
 
775
877
  To say "thanks\!" ☝️ Join the Discord or 👇️ send money.
776
878
 
777
- [![Sponsor kettle-rb/json-merge on Open Source Collective](https://img.shields.io/opencollective/all/kettle-rb?style=for-the-badge)](https://opencollective.com/kettle-rb) 💌 [![Sponsor me on GitHub Sponsors](https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github)](https://github.com/sponsors/pboling) 💌 [![Sponsor me on Liberapay](https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611)](https://liberapay.com/pboling/donate) 💌 [![Donate on PayPal](https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A)](https://www.paypal.com/paypalme/peterboling)
879
+ [![Sponsor kettle-rb/json-merge on Open Source Collective][🖇osc-all-bottom-img]][🖇osc] 💌 [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal]
778
880
 
779
881
  ### Please give the project a star ⭐ ♥.
780
882
 
@@ -815,7 +917,6 @@ Thanks for RTFM. ☺️
815
917
  [✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge&logo=discord
816
918
  [✉️ruby-friends-img]: https://img.shields.io/badge/daily.dev-%F0%9F%92%8E_Ruby_Friends-0A0A0A?style=for-the-badge&logo=dailydotdev&logoColor=white
817
919
  [✉️ruby-friends]: https://app.daily.dev/squads/rubyfriends
818
-
819
920
  [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780
820
921
  [⛳️gem-namespace]: https://github.com/kettle-rb/json-merge
821
922
  [⛳️namespace-img]: https://img.shields.io/badge/namespace-Json::Merge-3C2D2D.svg?style=square&logo=ruby&logoColor=white
@@ -939,7 +1040,7 @@ Thanks for RTFM. ☺️
939
1040
  [📌gitmoji]: https://gitmoji.dev
940
1041
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
941
1042
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
942
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.194-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1043
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.631-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
943
1044
  [🔐security]: SECURITY.md
944
1045
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
945
1046
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -959,8 +1060,3 @@ Thanks for RTFM. ☺️
959
1060
  [💎appraisal2]: https://github.com/appraisal-rb/appraisal2
960
1061
  [💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white
961
1062
  [💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/
962
-
963
- The `*-merge` gem family provides intelligent, AST-based merging for various file formats. At the foundation is [tree\_haver](https://github.com/kettle-rb/tree_haver), which provides a unified cross-Ruby parsing API that works seamlessly across MRI, JRuby, and TruffleRuby.
964
-
965
- [ts-jsonc]: https://gitlab.com/WhyNotHugo/tree-sitter-jsonc
966
- [dotenv]: https://github.com/bkeepers/dotenv