Skip to content

Commit

Permalink
Misc doc changes
Browse files Browse the repository at this point in the history
Besides other changes, this commit ensures the generated HTML doc for
HexDocs.pm will become the main source doc for this Elixir library which
leverage on ExDoc features.

List of changes:
* Fix typos
* Use common source url
* Use and set ex_doc to latest version
* Add changelog to hex info page
* Set readme as main html page
* Add changelog to html page
* Badges and more badges!
* Update gitignore
* Update formatter config
* Add license section
  • Loading branch information
kianmeng committed Feb 28, 2021
1 parent 3e3bb4e commit 392fe4d
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 50 deletions.
9 changes: 2 additions & 7 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
# Used by "mix format"
[
inputs: [
"lib/**/*.{ex,exs}",
"test/**/*.{ex,exs}",
"mix/**/*.{ex,exs}",
"./mix.exs",
]
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

19 changes: 14 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover
/cover/

# The directory Mix downloads your dependencies sources to.
/deps
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc
# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
deep_merge-*.tar

# Temporary files for e.g. tests.
/tmp/
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 1.0.0 (2019-03-26)

* Added the possibility to `@derive [DeepMerge.Resolver]` if you want your custom structs to also easily be deep_mergeable
Expand Down
44 changes: 31 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# DeepMerge [![Hex Version](https://img.shields.io/hexpm/v/deep_merge.svg)](https://hex.pm/packages/deep_merge) [![docs](https://img.shields.io/badge/docs-hexpm-blue.svg)](https://hexdocs.pm/deep_merge/) [![Build Status](https://travis-ci.org/PragTob/deep_merge.svg?branch=master)](https://travis-ci.org/PragTob/deep_merge) [![Coverage Status](https://coveralls.io/repos/github/PragTob/deep_merge/badge.svg?branch=master)](https://coveralls.io/github/PragTob/deep_merge?branch=master) [![Inline docs](http://inch-ci.org/github/PragTob/deep_merge.svg?branch=master)](http://inch-ci.org/github/PragTob/deep_merge)
# DeepMerge

Provides functionality for "deep merging" maps and keyword lists in elixir, which is if during merging both values at the same key are maps/keyword lists merge them recursively. This is done via a protocol so can be extended for your own structs/data types if needbe.
[![Build Status](https://travis-ci.org/PragTob/deep_merge.svg?branch=master)](https://travis-ci.org/PragTob/deep_merge)
[![Coverage Status](https://coveralls.io/repos/github/PragTob/deep_merge/badge.svg?branch=main)](https://coveralls.io/github/PragTob/deep_merge?branch=main)
[![Inline docs](http://inch-ci.org/github/PragTob/deep_merge.svg?branch=main)](http://inch-ci.org/github/PragTob/deep_merge)
[![Module Version](https://img.shields.io/hexpm/v/deep_merge.svg)](https://hex.pm/packages/deep_merge)
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/deep_merge/)
[![Total Download](https://img.shields.io/hexpm/dt/deep_merge.svg)](https://hex.pm/packages/deep_merge)
[![License](https://img.shields.io/hexpm/l/deep_merge.svg)](https://github.com/PragTob/deep_merge/blob/main/LICENSE)
[![Last Updated](https://img.shields.io/github/last-commit/PragTob/deep_merge.svg)](https://github.com/PragTob/deep_merge/commits/main)

Provides functionality for "deep merging" maps and keyword lists in elixir, which is if during merging both values at the same key are maps/keyword lists merge them recursively. This is done via a protocol so can be extended for your own structs/data types if needed.

```
iex> DeepMerge.deep_merge(%{a: 1, b: [x: 10, y: 9]}, %{b: [y: 20, z: 30], c: 4})
Expand All @@ -24,13 +33,15 @@ I wanted this to be a feature of Elixir itself, however the proposal [was reject

## Installation

Add `deep_merge` to your list of dependencies in `mix.exs`:
Add `:deep_merge` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[{:deep_merge, "~> 1.0"}]
end
```
```elixir
def deps do
[
{:deep_merge, "~> 1.0"}
]
end
```

## General Usage - deep_merge/2

Expand All @@ -50,7 +61,7 @@ It is worth noting that structs are not deeply merged - not with each other and

What is merged and how is defined by implementing the `DeepMerge.Resolver` protocol. This library implements it for `Map`, `List` and falls back to `Any` (where the right hand side value/override is taken).

If you want your own struct to be deeply merged you can simply `@derive` the protocole:
If you want your own struct to be deeply merged you can simply `@derive` the protocol:

```elixir
defmodule Derived do
Expand Down Expand Up @@ -98,7 +109,7 @@ iex> DeepMerge.deep_merge(%{a: %{b: 1}, c: [d: 1]},
%{a: %{b: 1, z: 5}, c: [x: 0]}
```

This function is called for a given merge conflict with the key where it occured and the two conflicting values. Whatever value is returned in this function is inserted at that point in the structure - unless `DeepMerge.continue_deep_merge` is returned in which case the deep merge continues as normal.
This function is called for a given merge conflict with the key where it occurred and the two conflicting values. Whatever value is returned in this function is inserted at that point in the structure - unless `DeepMerge.continue_deep_merge` is returned in which case the deep merge continues as normal.

When would you want to use this versus a protocol? The best use case I can think of is when you want to alter behavior for which a protocol is already implemented or if you care about specific keys.

Expand All @@ -111,7 +122,7 @@ Well not necessarily, no. There are [very simple implementations for maps that u
There are subtle things that can be missed there though (and I missed the first time around):

* the most simple implementation also merges structs which is not always what you want
* For keyword lists on the other hand you gotta be careful that you don't accidentally merge keyword lists with lists as that's [currently possible](https://github.com/elixir-lang/elixir/issues/5395)
* for keyword lists on the other hand you gotta be careful that you don't accidentally merge keyword lists with lists as that's [currently possible](https://github.com/elixir-lang/elixir/issues/5395)
* you might want to further adopt the implementation, in [benchee](https://github.com/bencheeorg/benchee) we have 2 custom implementations of the protocol due to our needs

This library takes care of those problems and will take care of further problems/edge cases should they appear so you can focus on your business logic.
Expand All @@ -120,10 +131,17 @@ At the same time it offers extension mechanisms through protocols and a function

## Performance

You can check out [a benchmark and its results](https://github.com/PragTob/deep_merge/blob/master/benches/bench/deep_merge.exs).
You can check out [a benchmark and its results](https://github.com/PragTob/deep_merge/blob/main/benches/bench/deep_merge.exs).

The TLDR; is this: In the sample it is about 30 times slower than `Map.merge/2` - however, less than twice as slow as calling `Map.merge/3` with simple overriding behaviour (same behaviour as `Map.merge/2`). This is because `Map.merge/2` is highly optimized, but we need to do much more than the `Map.merge/3` sample in the benchmark so I think it's a very passable result. We're still talking about a couple of μs.

## Considered feature-complete

Unless you come with great feature ideas of course ;) So if you come here and there are no recent commits, don't worry - there are no known bugs or whatever. It's a small little library that does its job.
Unless you come with great feature ideas of course ;) So if you come here and there are no recent commits, don't worry - there are no known bugs or whatever. It's a small little library that does its job.

## Copyright and License

Copyright (c) 2016 Tobias Pfeiffer

This library is MIT licensed. See the
[LICENSE](https://github.com/PragTob/deep_merge/blob/main/LICENSE.txt) for details.
46 changes: 26 additions & 20 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
defmodule DeepMerge.Mixfile do
use Mix.Project

@source_url "https://github.com/PragTob/deep_merge"
@version "1.0.0"

def project do
Expand All @@ -12,58 +13,63 @@ defmodule DeepMerge.Mixfile do
start_permanent: Mix.env() == :prod,
elixirc_paths: elixirc_paths(Mix.env()),
deps: deps(),
docs: [source_ref: @version],
docs: docs(),
test_coverage: [tool: ExCoveralls],
preferred_cli_env: [
coveralls: :test,
"coveralls.detail": :test,
"coveralls.post": :test,
"coveralls.html": :test,
"coveralls.travis": :test
],
package: package(),
name: "deep_merge",
source_url: "https://github.com/PragTob/deep_merge",
description: """
Deep (recursive) merging for maps, keyword lists and whatever else
you may want via implementing a simple protocol.
""",
dialyzer: [
flags: [:unmatched_returns, :error_handling, :race_conditions, :underspecs],
ignore_warnings: ".dialyzer_ignore.exs",
list_unused_filters: true
],
description: """
Deep (recursive) merging for maps, keyword lists and whatever else
you may want via implementing a simple protocol.
"""
preferred_cli_env: [
docs: :docs,
coveralls: :test,
"coveralls.detail": :test,
"coveralls.post": :test,
"coveralls.html": :test,
"coveralls.travis": :test
]
]
end

# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]

# Configuration for the OTP application
#
# Type "mix help compile.app" for more information
def application do
[]
end

defp deps do
[
{:credo, "~> 1.0", only: :dev},
{:ex_doc, "~> 0.11", only: :dev},
{:earmark, "~> 1.2", only: :dev},
{:ex_doc, ">= 0.0.0", only: :docs, runtime: false},
{:excoveralls, "~> 0.7", only: :test},
{:inch_ex, "~> 2.0", only: :docs},
{:dialyxir, "~> 1.0.0-rc.4", only: [:dev], runtime: false}
]
end

defp docs do
[
extras: ["CHANGELOG.md", "README.md"],
main: "readme",
source_url: @source_url,
source_ref: @version
]
end

defp package do
[
maintainers: ["Tobias Pfeiffer"],
licenses: ["MIT"],
links: %{
"github" => "https://github.com/PragTob/deep_merge"
"Changelog" => "https://hexdocs.pm/deep_merge/changelog.html",
"GitHub" => @source_url
}
]
end
Expand Down
10 changes: 5 additions & 5 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
"credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"},
"dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
"earmark": {:hex, :earmark, "1.4.10", "bddce5e8ea37712a5bfb01541be8ba57d3b171d3fa4f80a0be9bcf1db417bcaf", [:mix], [{:earmark_parser, ">= 1.4.10", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "12dbfa80810478e521d3ffb941ad9fbfcbbd7debe94e1341b4c4a1b2411c1c27"},
"earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"},
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"},
"ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
"excoveralls": {:hex, :excoveralls, "0.13.1", "b9f1697f7c9e0cfe15d1a1d737fb169c398803ffcbc57e672aa007e9fd42864c", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b4bb550e045def1b4d531a37fb766cbbe1307f7628bf8f0414168b3f52021cce"},
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]},
"hackney": {:hex, :hackney, "1.16.0", "5096ac8e823e3a441477b2d187e30dd3fff1a82991a806b2003845ce72ce2d84", [:rebar3], [{:certifi, "2.5.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.0", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "3bf0bebbd5d3092a3543b783bf065165fa5d3ad4b899b836810e513064134e18"},
"idna": {:hex, :idna, "6.0.1", "1d038fb2e7668ce41fbf681d2c45902e52b3cb9e9c77b55334353b222c2ee50c", [:rebar3], [{:unicode_util_compat, "0.5.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a02c8a1c4fd601215bb0b0324c8a6986749f807ce35f25449ec9e69758708122"},
"inch_ex": {:hex, :inch_ex, "2.0.0", "24268a9284a1751f2ceda569cd978e1fa394c977c45c331bb52a405de544f4de", [:mix], [{:bunt, "~> 0.2", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "96d0ec5ecac8cf63142d02f16b7ab7152cf0f0f1a185a80161b758383c9399a8"},
"jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"},
"jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []},
"makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
Expand Down

0 comments on commit 392fe4d

Please sign in to comment.