annot.at is a service for syncing static websites, such as blogs, to atproto and standard.site annot.at
elixir atproto standardsite
3

Configure Feed

Select the types of activity you want to include in your feed.

Add credo

Johanna Larsson (Jun 8, 2026, 9:51 PM +0100) e8217e1c c645fb18

+246 -11
+219
.credo.exs
··· 1 + # This file contains the configuration for Credo and you are probably reading 2 + # this after creating it with `mix credo.gen.config`. 3 + # 4 + # If you find anything wrong or unclear in this file, please report an 5 + # issue on GitHub: https://github.com/rrrene/credo/issues 6 + # 7 + %{ 8 + # 9 + # You can have as many configs as you like in the `configs:` field. 10 + configs: [ 11 + %{ 12 + # 13 + # Run any config using `mix credo -C <name>`. If no config name is given 14 + # "default" is used. 15 + # 16 + name: "default", 17 + # 18 + # These are the files included in the analysis: 19 + files: %{ 20 + # 21 + # You can give explicit globs or simply directories. 22 + # In the latter case `**/*.{ex,exs}` will be used. 23 + # 24 + included: [ 25 + "lib/", 26 + "src/", 27 + "test/", 28 + "web/", 29 + "scripts/*.exs", 30 + "apps/*/lib/", 31 + "apps/*/src/", 32 + "apps/*/test/", 33 + "apps/*/web/" 34 + ], 35 + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] 36 + }, 37 + # 38 + # Load and configure plugins here: 39 + # 40 + plugins: [], 41 + # 42 + # If you create your own checks, you must specify the source files for 43 + # them here, so they can be loaded by Credo before running the analysis. 44 + # 45 + requires: [], 46 + # 47 + # If you want to enforce a style guide and need a more traditional linting 48 + # experience, you can change `strict` to `true` below: 49 + # 50 + strict: true, 51 + # 52 + # To modify the timeout for parsing files, change this value: 53 + # 54 + parse_timeout: 5000, 55 + # 56 + # If you want to use uncolored output by default, you can change `color` 57 + # to `false` below: 58 + # 59 + color: true, 60 + # 61 + # You can customize the parameters of any check by adding a second element 62 + # to the tuple. 63 + # 64 + # To disable a check put `false` as second element: 65 + # 66 + # {Credo.Check.Design.DuplicatedCode, false} 67 + # 68 + checks: %{ 69 + enabled: [ 70 + # 71 + ## Consistency Checks 72 + # 73 + {Credo.Check.Consistency.ExceptionNames, []}, 74 + {Credo.Check.Consistency.LineEndings, []}, 75 + {Credo.Check.Consistency.ParameterPatternMatching, []}, 76 + {Credo.Check.Consistency.SpaceAroundOperators, []}, 77 + {Credo.Check.Consistency.SpaceInParentheses, []}, 78 + {Credo.Check.Consistency.TabsOrSpaces, []}, 79 + 80 + # 81 + ## Design Checks 82 + # 83 + # You can customize the priority of any check 84 + # Priority values are: `low, normal, high, higher` 85 + # 86 + {Credo.Check.Design.AliasUsage, 87 + [priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]}, 88 + {Credo.Check.Design.TagFIXME, []}, 89 + # You can also customize the exit_status of each check. 90 + # If you don't want TODO comments to cause `mix credo` to fail, just 91 + # set this value to 0 (zero). 92 + # 93 + # TODOs are allowed as intentional markers for future work. 94 + {Credo.Check.Design.TagTODO, [exit_status: 0]}, 95 + 96 + # 97 + ## Readability Checks 98 + # 99 + {Credo.Check.Readability.AliasOrder, []}, 100 + {Credo.Check.Readability.BlockPipe, []}, 101 + {Credo.Check.Readability.FunctionNames, []}, 102 + {Credo.Check.Readability.ImplTrue, []}, 103 + {Credo.Check.Readability.LargeNumbers, []}, 104 + {Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]}, 105 + {Credo.Check.Readability.ModuleAttributeNames, []}, 106 + {Credo.Check.Readability.ModuleDoc, []}, 107 + {Credo.Check.Readability.ModuleNames, []}, 108 + {Credo.Check.Readability.MultiAlias, []}, 109 + {Credo.Check.Readability.OneArityFunctionInPipe, []}, 110 + {Credo.Check.Readability.OnePipePerLine, []}, 111 + {Credo.Check.Readability.ParenthesesInCondition, []}, 112 + {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, 113 + {Credo.Check.Readability.PipeIntoAnonymousFunctions, []}, 114 + {Credo.Check.Readability.PredicateFunctionNames, []}, 115 + {Credo.Check.Readability.PreferImplicitTry, []}, 116 + {Credo.Check.Readability.RedundantBlankLines, []}, 117 + {Credo.Check.Readability.Semicolons, []}, 118 + {Credo.Check.Readability.SeparateAliasRequire, []}, 119 + {Credo.Check.Readability.SingleFunctionToBlockPipe, []}, 120 + {Credo.Check.Readability.SinglePipe, []}, 121 + {Credo.Check.Readability.SpaceAfterCommas, []}, 122 + {Credo.Check.Readability.StrictModuleLayout, []}, 123 + {Credo.Check.Readability.StringSigils, []}, 124 + {Credo.Check.Readability.TrailingBlankLine, []}, 125 + {Credo.Check.Readability.TrailingWhiteSpace, []}, 126 + {Credo.Check.Readability.UnnecessaryAliasExpansion, []}, 127 + {Credo.Check.Readability.VariableNames, []}, 128 + {Credo.Check.Readability.WithCustomTaggedTuple, []}, 129 + {Credo.Check.Readability.WithSingleClause, []}, 130 + 131 + # 132 + ## Refactoring Opportunities 133 + # 134 + {Credo.Check.Refactor.Apply, []}, 135 + {Credo.Check.Refactor.CondStatements, []}, 136 + {Credo.Check.Refactor.CyclomaticComplexity, []}, 137 + {Credo.Check.Refactor.DoubleBooleanNegation, []}, 138 + {Credo.Check.Refactor.FilterCount, []}, 139 + {Credo.Check.Refactor.FilterFilter, []}, 140 + {Credo.Check.Refactor.FunctionArity, []}, 141 + {Credo.Check.Refactor.LongQuoteBlocks, []}, 142 + {Credo.Check.Refactor.MapJoin, []}, 143 + {Credo.Check.Refactor.MatchInCondition, []}, 144 + {Credo.Check.Refactor.NegatedConditionsInUnless, []}, 145 + {Credo.Check.Refactor.NegatedConditionsWithElse, []}, 146 + {Credo.Check.Refactor.Nesting, [max_nesting: 3]}, 147 + {Credo.Check.Refactor.PassAsyncInTestCases, []}, 148 + {Credo.Check.Refactor.PipeChainStart, []}, 149 + {Credo.Check.Refactor.RedundantWithClauseResult, []}, 150 + {Credo.Check.Refactor.RejectReject, []}, 151 + {Credo.Check.Refactor.UnlessWithElse, []}, 152 + {Credo.Check.Refactor.WithClauses, []}, 153 + 154 + # 155 + ## Warnings 156 + # 157 + {Credo.Check.Warning.ApplicationConfigInModuleAttribute, []}, 158 + {Credo.Check.Warning.BoolOperationOnSameValues, []}, 159 + {Credo.Check.Warning.Dbg, []}, 160 + {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, 161 + {Credo.Check.Warning.IExPry, []}, 162 + {Credo.Check.Warning.IoInspect, []}, 163 + {Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []}, 164 + {Credo.Check.Warning.MixEnv, []}, 165 + {Credo.Check.Warning.OperationOnSameValues, []}, 166 + {Credo.Check.Warning.OperationWithConstantResult, []}, 167 + {Credo.Check.Warning.RaiseInsideRescue, []}, 168 + {Credo.Check.Warning.SpecWithStruct, []}, 169 + {Credo.Check.Warning.UnsafeExec, []}, 170 + {Credo.Check.Warning.UnusedEnumOperation, []}, 171 + {Credo.Check.Warning.UnusedFileOperation, []}, 172 + {Credo.Check.Warning.UnusedKeywordOperation, []}, 173 + {Credo.Check.Warning.UnusedListOperation, []}, 174 + {Credo.Check.Warning.UnusedPathOperation, []}, 175 + {Credo.Check.Warning.UnusedRegexOperation, []}, 176 + {Credo.Check.Warning.UnusedStringOperation, []}, 177 + {Credo.Check.Warning.UnusedTupleOperation, []}, 178 + {Credo.Check.Warning.WrongTestFileExtension, []} 179 + ], 180 + disabled: [ 181 + # 182 + # Checks scheduled for next check update (opt-in for now) 183 + {Credo.Check.Refactor.UtcNowTruncate, []}, 184 + 185 + # 186 + # Controversial and experimental checks (opt-in, just move the check to `:enabled` 187 + # and be sure to use `mix credo --strict` to see low priority checks) 188 + # 189 + {Credo.Check.Consistency.MultiAliasImportRequireUse, []}, 190 + {Credo.Check.Consistency.UnusedVariableNames, []}, 191 + {Credo.Check.Design.DuplicatedCode, []}, 192 + {Credo.Check.Design.SkipTestWithoutComment, []}, 193 + {Credo.Check.Readability.AliasAs, []}, 194 + {Credo.Check.Readability.NestedFunctionCalls, []}, 195 + {Credo.Check.Readability.Specs, []}, 196 + {Credo.Check.Refactor.ABCSize, []}, 197 + {Credo.Check.Refactor.AppendSingleItem, []}, 198 + {Credo.Check.Refactor.FilterReject, []}, 199 + {Credo.Check.Refactor.IoPuts, []}, 200 + {Credo.Check.Refactor.MapMap, []}, 201 + {Credo.Check.Refactor.ModuleDependencies, []}, 202 + {Credo.Check.Refactor.NegatedIsNil, []}, 203 + {Credo.Check.Refactor.RejectFilter, []}, 204 + {Credo.Check.Refactor.VariableRebinding, []}, 205 + {Credo.Check.Warning.LazyLogging, []}, 206 + {Credo.Check.Warning.LeakyEnvironment, []}, 207 + {Credo.Check.Warning.MapGetUnsafePass, []}, 208 + {Credo.Check.Warning.UnsafeToAtom, []} 209 + 210 + # {Credo.Check.Refactor.MapInto, []}, 211 + 212 + # 213 + # Custom checks can be created using `mix credo.gen.check`. 214 + # 215 + ] 216 + } 217 + } 218 + ] 219 + }
+2 -2
lib/annot_at/application.ex
··· 5 5 6 6 use Application 7 7 8 - @impl true 8 + @impl Application 9 9 def start(_type, _args) do 10 10 children = [ 11 11 AnnotAtWeb.Telemetry, ··· 26 26 27 27 # Tell Phoenix to update the endpoint configuration 28 28 # whenever the application is updated. 29 - @impl true 29 + @impl Application 30 30 def config_change(changed, _new, removed) do 31 31 AnnotAtWeb.Endpoint.config_change(changed, removed) 32 32 :ok
+1 -1
lib/annot_at_web.ex
··· 88 88 import AnnotAtWeb.CoreComponents 89 89 90 90 # Common modules used in templates 91 - alias Phoenix.LiveView.JS 92 91 alias AnnotAtWeb.Layouts 92 + alias Phoenix.LiveView.JS 93 93 94 94 # Routes generation with the ~p sigil 95 95 unquote(verified_routes())
+2 -1
lib/annot_at_web/components/core_components.ex
··· 29 29 use Phoenix.Component 30 30 use Gettext, backend: AnnotAtWeb.Gettext 31 31 32 + alias Phoenix.HTML.Form 32 33 alias Phoenix.LiveView.JS 33 34 34 35 @doc """ ··· 208 209 def input(%{type: "checkbox"} = assigns) do 209 210 assigns = 210 211 assign_new(assigns, :checked, fn -> 211 - Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value]) 212 + Form.normalize_value("checkbox", assigns[:value]) 212 213 end) 213 214 214 215 ~H"""
+1 -1
lib/annot_at_web/telemetry.ex
··· 6 6 Supervisor.start_link(__MODULE__, arg, name: __MODULE__) 7 7 end 8 8 9 - @impl true 9 + @impl Supervisor 10 10 def init(_arg) do 11 11 children = [ 12 12 # Telemetry poller will execute the given period measurements
+10 -2
mix.exs
··· 65 65 {:gettext, "~> 1.0"}, 66 66 {:jason, "~> 1.2"}, 67 67 {:dns_cluster, "~> 0.2.0"}, 68 - {:bandit, "~> 1.5"} 68 + {:bandit, "~> 1.5"}, 69 + {:jose, "~> 1.11"}, 70 + {:credo, "~> 1.7", only: [:dev, :test]} 69 71 ] 70 72 end 71 73 ··· 88 90 "esbuild annot_at --minify", 89 91 "phx.digest" 90 92 ], 91 - precommit: ["compile --warnings-as-errors", "deps.unlock --unused", "format", "test"] 93 + precommit: [ 94 + "compile --warnings-as-errors", 95 + "deps.unlock --unused", 96 + "format", 97 + "test", 98 + "credo --strict" 99 + ] 92 100 ] 93 101 end 94 102 end
+3
mix.lock
··· 1 1 %{ 2 2 "bandit": {:hex, :bandit, "1.12.0", "6c5214daa2469644ac4ab0113b98abc24f75e348378e6a974c6343b3e5da22ef", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.5", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "45dac82dc86f45cf4a196dee9cc5a8b791d9c9469d996055f055e6ee36c66e20"}, 3 + "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, 3 4 "cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"}, 5 + "credo": {:hex, :credo, "1.7.19", "cc52129665fc7c15143d47838fda0f9cd6dac9ceced7bf4da6f85fcbfe64b12a", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "2d8bc95d5a7bb99dd2613621d4f08c6a3575c3fd4b62e6a2b48a100352a557b8"}, 4 6 "db_connection": {:hex, :db_connection, "2.10.1", "d5465f6bcc125c1b8981c1dbf23c193ca16f446ec0b25832dc174f74f18be510", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "18ed94c6e627b4bf452dbd4df61b69a35a1e768525140bc1917b7a685026a6a3"}, 5 7 "decimal": {:hex, :decimal, "3.1.1", "430d87b04011ce6cbd4fd205be758311a81f87d552d40904abd00f015935b1d0", [:mix], [], "hexpm", "c5f25f2ced74a0587d03e6023f595db8e924c9d3922c8c8ffd9edfc4498cf1f6"}, 6 8 "dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"}, ··· 17 19 "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, 18 20 "idna": {:hex, :idna, "7.1.0", "1067a13043538129602d2f2ce6899d8713125c7d19734aa557ce2e3ea55bd4f1", [:rebar3], [], "hexpm", "6ae959a025bf36df61a8cab8508d9654891b5426a84c44d82deaffd6ddf8c71f"}, 19 21 "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, 22 + "jose": {:hex, :jose, "1.11.12", "06e62b467b61d3726cbc19e9b5489f7549c37993de846dfb3ee8259f9ed208b3", [:mix, :rebar3], [], "hexpm", "31e92b653e9210b696765cdd885437457de1add2a9011d92f8cf63e4641bab7b"}, 20 23 "lazy_html": {:hex, :lazy_html, "0.1.11", "136c8e9cd616b4f4e9c1562daa683880891120b759606dc4c3b6b18058ba5d79", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "3b1be592929c31eca1a21673d25696e5c14cddfe922d9d1a3e3b48be4163883b"}, 21 24 "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"}, 22 25 "mint": {:hex, :mint, "1.9.0", "d6f534c2a3e98b2a8cc749b4796eb77e9e3af79a76f96e4c74035a827de0d318", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "007154c7d8c43916aed3c93afd1f11aebbaa9c5ff4b7ba55ebe0d17ee0296042"},
+1 -1
test/annot_at_web/controllers/page_controller_test.exs
··· 1 1 defmodule AnnotAtWeb.PageControllerTest do 2 - use AnnotAtWeb.ConnCase 2 + use AnnotAtWeb.ConnCase, async: true 3 3 4 4 test "GET /", %{conn: conn} do 5 5 conn = get(conn, ~p"/")
+7 -3
test/support/data_case.ex
··· 16 16 17 17 use ExUnit.CaseTemplate 18 18 19 + alias Ecto.Adapters.SQL.Sandbox 20 + 19 21 using do 20 22 quote do 21 23 alias AnnotAt.Repo ··· 36 38 Sets up the sandbox based on the test tags. 37 39 """ 38 40 def setup_sandbox(tags) do 39 - pid = Ecto.Adapters.SQL.Sandbox.start_owner!(AnnotAt.Repo, shared: not tags[:async]) 40 - on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) 41 + pid = Sandbox.start_owner!(AnnotAt.Repo, shared: not tags[:async]) 42 + on_exit(fn -> Sandbox.stop_owner(pid) end) 41 43 end 42 44 43 45 @doc """ ··· 51 53 def errors_on(changeset) do 52 54 Ecto.Changeset.traverse_errors(changeset, fn {message, opts} -> 53 55 Regex.replace(~r"%{(\w+)}", message, fn _, key -> 54 - opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string() 56 + opts 57 + |> Keyword.get(String.to_existing_atom(key), key) 58 + |> to_string() 55 59 end) 56 60 end) 57 61 end