From 392fe4ddeb190a63b53f6f1ec9b2fb078a11fa29 Mon Sep 17 00:00:00 2001 From: Kian-Meng Ang Date: Sun, 28 Feb 2021 21:48:08 +0800 Subject: [PATCH] Misc doc changes 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 --- .formatter.exs | 9 ++------- .gitignore | 19 ++++++++++++++----- CHANGELOG.md | 7 +++++++ README.md | 44 +++++++++++++++++++++++++++++++------------- mix.exs | 46 ++++++++++++++++++++++++++-------------------- mix.lock | 10 +++++----- 6 files changed, 85 insertions(+), 50 deletions(-) diff --git a/.formatter.exs b/.formatter.exs index 1f9a976..d2cda26 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -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}"] ] - diff --git a/.gitignore b/.gitignore index 6e1db0f..6923f88 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 5202dcb..60f8791 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index 32b8eab..f2ad5c4 100644 --- a/README.md +++ b/README.md @@ -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}) @@ -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 @@ -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 @@ -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. @@ -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. @@ -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. \ No newline at end of file +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. diff --git a/mix.exs b/mix.exs index e9cbaa8..e10f29e 100644 --- a/mix.exs +++ b/mix.exs @@ -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 @@ -12,37 +13,33 @@ 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 @@ -50,20 +47,29 @@ defmodule DeepMerge.Mixfile do 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 diff --git a/mix.lock b/mix.lock index 83f0338..adaa6e2 100644 --- a/mix.lock +++ b/mix.lock @@ -4,9 +4,9 @@ "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"}, @@ -14,11 +14,11 @@ "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"},