diff --git a/.formatter.exs b/.formatter.exs index ef8840c..bd84584 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,6 +1,6 @@ [ import_deps: [:ecto, :ecto_sql, :phoenix], subdirectories: ["priv/*/migrations"], - plugins: [Phoenix.LiveView.HTMLFormatter], + plugins: [Phoenix.LiveView.HTMLFormatter, TailwindFormatter], inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"] ] diff --git a/assets/css/app.css b/assets/css/app.css index b5c61c9..d93b2db 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -1,3 +1,18 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@layer utilities { + .text-shadow { + text-shadow: 0px 1px 2px rgb(0 0 0 / 50%); + } + .text-shadow-md { + text-shadow: 0px 3px 6px rgb(0 0 0 / 30%); + } + .text-shadow-lg { + text-shadow: 0px 3px 6px rgb(0 0 0 / 30%), 0px 14px 28px rgb(0 0 0 / 25%); + } + .text-shadow-none { + text-shadow: none; + } +} diff --git a/lib/swornforged/dataforged.ex b/lib/swornforged/dataforged.ex index 94d8a7e..a6adfbe 100644 --- a/lib/swornforged/dataforged.ex +++ b/lib/swornforged/dataforged.ex @@ -6,10 +6,13 @@ defmodule Swornforged.Dataforged do Req.get!("https://registry.npmjs.org/dataforged/") |> Map.get(:body) - dataforged_raw = - manifest["versions"][version]["dist"]["tarball"] + dataforged = + get_in(manifest, ["versions", version, "dist", "tarball"]) |> Req.get!() |> Map.get(:body) + + dataforged_json = + dataforged |> Enum.find(fn curr -> case curr do {'package/dist/starforged/dataforged.json', _str} -> true @@ -17,11 +20,8 @@ defmodule Swornforged.Dataforged do end end) |> then(fn {_, json_str} -> json_str end) + |> Jason.decode!() - dataforged = Jason.decode!(dataforged_raw) - - Cachex.put!(:swornforged, "dataforged", dataforged) - - :ok + Cachex.put_many!(:swornforged, dataforged_raw: dataforged, dataforged_json: dataforged_json) end end diff --git a/lib/swornforged/kernel_helpers.ex b/lib/swornforged/kernel_helpers.ex new file mode 100644 index 0000000..09a0748 --- /dev/null +++ b/lib/swornforged/kernel_helpers.ex @@ -0,0 +1,8 @@ +defmodule Swornforged.KernelHelpers do + def get_in(data, keys, default) do + case get_in(data, keys) do + nil -> default + result -> result + end + end +end diff --git a/lib/swornforged/markdown.ex b/lib/swornforged/markdown.ex new file mode 100644 index 0000000..0e1c0cf --- /dev/null +++ b/lib/swornforged/markdown.ex @@ -0,0 +1,13 @@ +defmodule Swornforged.Markdown do + @cache_prefix "HTML_CACHE::" + + def get_cache_html!(markdown, key, options \\ []) do + case Cachex.get(:swornforged, @cache_prefix <> key) do + {:ok, nil} -> + html = Earmark.as_html!(markdown, options) + Cachex.put!(:swornforged, @cache_prefix <> key, html) + html + {:ok, html} -> html + end + end +end diff --git a/lib/swornforged_web.ex b/lib/swornforged_web.ex index 2f788d8..25816a4 100644 --- a/lib/swornforged_web.ex +++ b/lib/swornforged_web.ex @@ -46,6 +46,9 @@ defmodule SwornforgedWeb do import SwornforgedWeb.Gettext unquote(verified_routes()) + + # Include general helpers for kernel functions + unquote(kernel_helpers()) end end @@ -55,6 +58,9 @@ defmodule SwornforgedWeb do layout: {SwornforgedWeb.Layouts, :app} unquote(html_helpers()) + + # Include general helpers for kernel functions + unquote(kernel_helpers()) end end @@ -63,6 +69,9 @@ defmodule SwornforgedWeb do use Phoenix.LiveComponent unquote(html_helpers()) + + # Include general helpers for kernel functions + unquote(kernel_helpers()) end end @@ -76,6 +85,15 @@ defmodule SwornforgedWeb do # Include general helpers for rendering HTML unquote(html_helpers()) + + # Include general helpers for kernel functions + unquote(kernel_helpers()) + end + end + + defp kernel_helpers do + quote do + import Swornforged.KernelHelpers end end @@ -87,6 +105,9 @@ defmodule SwornforgedWeb do import SwornforgedWeb.CoreComponents import SwornforgedWeb.Gettext + # Markdown helpers + alias Swornforged.Markdown + # Shortcut for generating JS commands alias Phoenix.LiveView.JS diff --git a/lib/swornforged_web/components/layouts/app.html.heex b/lib/swornforged_web/components/layouts/app.html.heex index fa10840..0c726c5 100644 --- a/lib/swornforged_web/components/layouts/app.html.heex +++ b/lib/swornforged_web/components/layouts/app.html.heex @@ -1,36 +1,26 @@ -
-
+ +
+ @@ -52,4 +42,4 @@ <%= @inner_content %>
- + \ No newline at end of file diff --git a/lib/swornforged_web/components/layouts/root.html.heex b/lib/swornforged_web/components/layouts/root.html.heex index c6b2283..ec40341 100644 --- a/lib/swornforged_web/components/layouts/root.html.heex +++ b/lib/swornforged_web/components/layouts/root.html.heex @@ -11,7 +11,7 @@ - + <%= @inner_content %> diff --git a/lib/swornforged_web/controllers/page_controller.ex b/lib/swornforged_web/controllers/page_controller.ex index 617645f..7526671 100644 --- a/lib/swornforged_web/controllers/page_controller.ex +++ b/lib/swornforged_web/controllers/page_controller.ex @@ -2,8 +2,6 @@ defmodule SwornforgedWeb.PageController do use SwornforgedWeb, :controller def home(conn, _params) do - # The home page is often custom made, - # so skip the default app layout. - render(conn, :home, layout: false, dataforged: Cachex.get!(:swornforged, "dataforged")) + render(conn, :home, dataforged: Cachex.get!(:swornforged, :dataforged_json)) end end diff --git a/lib/swornforged_web/controllers/page_html.ex b/lib/swornforged_web/controllers/page_html.ex index b56592c..668ffea 100644 --- a/lib/swornforged_web/controllers/page_html.ex +++ b/lib/swornforged_web/controllers/page_html.ex @@ -3,29 +3,31 @@ defmodule SwornforgedWeb.PageHTML do embed_templates "page_html/*" - def get_in(data, keys, default) do - case get_in(data, keys) do - nil -> default - result -> result - end + def srd_header(assigns) do + ~H""" +
+

<%= @title %>

+
+ """ end def srd_category_card(assigns) do assigns = assign(assigns, card_colors: %{ - :asset_types => "bg-blue-500", - :encounters => "bg-rose-500", - :move_categories => "bg-violet-500", - :oracle_categories => "bg-amber-500" + :asset_types => "bg-sky-500 hover:bg-sky-400 dark:bg-sky-900 border-sky-500/50 dark:focus:border-sky-500/100 dark:focus:bg-sky-800 dark:hover:border-sky-500/100 dark:hover:bg-sky-800 light:shadow-sky-700/25 light:hover:shadow-sky-700/50", + :encounters => "bg-red-500 hover:bg-red-400 dark:bg-red-900 border-red-500/50 dark:focus:border-red-500/100 dark:focus:bg-red-800 dark:hover:border-red-500/100 dark:hover:bg-red-800 light:shadow-red-700/25 light:hover:shadow-red-700/50", + :move_categories => "bg-emerald-500 hover:bg-emerald-400 dark:bg-emerald-900 border-emerald-500/50 dark:focus:border-emerald-500/100 dark:focus:bg-emerald-800 dark:hover:border-emerald-500/100 dark:hover:bg-emerald-800 light:shadow-emerald-700/25 light:hover:shadow-emerald-700/50", + :oracle_categories => "bg-purple-500 hover:bg-purple-400 dark:bg-purple-900 border-purple-500/50 dark:focus:border-purple-500/100 dark:focus:bg-purple-800 dark:hover:border-purple-500/100 dark:hover:bg-purple-800 light:shadow-purple-700/25 light:hover:shadow-purple-700/50" } ) ~H""" @@ -33,75 +35,4 @@ defmodule SwornforgedWeb.PageHTML do """ end - - def srd_header(assigns) do - ~H""" -
-

<%= @title %>

-
- """ - end - - def srd_type_title(assigns) do - ~H""" -

<%= render_slot(@inner_block) %>

- """ - end - - def srd_subtype_title(assigns) do - ~H""" -

<%= render_slot(@inner_block) %>

- """ - end - - def srd_type_container(assigns) do - ~H""" -
- <%= render_slot(@inner_block) %> -
- """ - end - - def srd_item_inner_title(assigns) do - ~H""" -

<%= render_slot(@inner_block) %>

- """ - end - - def srd_item(assigns) do - ~H""" -
-

- @item["$id"]}><%= render_slot(@title) %> -

-
-
- <%= render_slot(@inner_block) %> -

- Source -
- <%= get_in(@item, ["Source", "Title"]) %> - - p.<%= get_in(@item, ["Source", "Page"]) %> - -

-
-
-
- Raw JSON -
-
<%= Jason.encode!(@item, pretty: true, escape: :html_safe) %>
-
-
-
-
-
- """ - end end diff --git a/lib/swornforged_web/controllers/page_html/assets.html.heex b/lib/swornforged_web/controllers/page_html/assets.html.heex deleted file mode 100644 index e69de29..0000000 diff --git a/lib/swornforged_web/controllers/page_html/home.html.heex b/lib/swornforged_web/controllers/page_html/home.html.heex index cf0689f..73df895 100644 --- a/lib/swornforged_web/controllers/page_html/home.html.heex +++ b/lib/swornforged_web/controllers/page_html/home.html.heex @@ -1,129 +1,14 @@ -<.srd_header title="Swornforged" /> -
-
- <.srd_category_card category={:asset_types} title="Asset Types" /> - <.srd_category_card category={:oracle_categories} title="Oracle Categories" /> - <.srd_category_card category={:move_categories} title="Move Categories" /> - <.srd_category_card category={:encounters} title="Encounters" /> +
+
+

Swornforged

+

An unofficial online systems reference document for Ironsworn: Starforged

-
-
- <.srd_type_container> - <.srd_type_title>Assets -
- <.srd_subtype_title> - asset_type["$id"]}><%= get_in(asset_type, ["Display", "Title"]) %> - -
    -
  • - <.srd_item item={asset}> - <:title><%= get_in(asset, ["Display", "Title"]) %> -
      -
    1. -
      - -
      - <%= raw(Earmark.as_html!(ability["Text"], compact_output: true)) %> -
      -
      -
    2. -
    - -
  • -
-
- - <.srd_type_container> - <.srd_type_title>Oracles -
- <.srd_subtype_title> - oracle_category["$id"]}> - <%= get_in(oracle_category, ["Display", "Title"]) %> - - -
    -
  • - <.srd_item item={oracle}> - <:title><%= get_in(oracle, ["Display", "Title"]) %> -
    -
    - <%= raw(Earmark.as_html!(str, compact_output: true)) %> -
    - - - - - - - - - - - - - -
    RollResult
    <%= row["Floor"] %>-<%= row["Ceiling"] %> - <%= raw(Earmark.as_html!(row["Result"], compact_output: true)) %> -
    -
    -
    -
    - <.srd_item_inner_title> - <%= get_in(inner_oracle, ["Display", "Title"]) %> - -
    -
    - <%= raw(Earmark.as_html!(str, compact_output: true)) %> -
    - - - - - - - - - - - - - -
    RollResult
    <%= row["Floor"] %>-<%= row["Ceiling"] %> - <%= raw(Earmark.as_html!(row["Result"], compact_output: true)) %> -
    -
    -
    - -
  • -
-
- - <.srd_type_container> - <.srd_type_title>Moves -
- <.srd_subtype_title> - move_category["$id"]}> - <%= get_in(move_category, ["Display", "Title"]) %> - - -
    -
  • - <.srd_item item={move}> - <:title><%= get_in(move, ["Display", "Title"]) %> -
    - <%= raw( - Earmark.as_html!(move["Text"], gfm: true, gfm_tables: true, compact_output: true) - ) %> -
    - -
  • -
-
- -
+ +
+
+ <.srd_category_card category={:move_categories} title="Moves" to={~p"/srd/moves"} /> + <.srd_category_card category={:oracle_categories} title="Oracles" to={~p"/srd/oracles"} /> + <.srd_category_card category={:asset_types} title="Assets" to={~p"/srd/assets/"} /> + <.srd_category_card category={:encounters} title="Encounters" to={~p"/srd/encounters"} /> +
+
diff --git a/lib/swornforged_web/controllers/page_html/moves.html.heex b/lib/swornforged_web/controllers/page_html/moves.html.heex deleted file mode 100644 index e69de29..0000000 diff --git a/lib/swornforged_web/controllers/page_html/oracles.html.heex b/lib/swornforged_web/controllers/page_html/oracles.html.heex deleted file mode 100644 index e69de29..0000000 diff --git a/lib/swornforged_web/controllers/srd_controller.ex b/lib/swornforged_web/controllers/srd_controller.ex new file mode 100644 index 0000000..9695d8d --- /dev/null +++ b/lib/swornforged_web/controllers/srd_controller.ex @@ -0,0 +1,19 @@ +defmodule SwornforgedWeb.SrdController do + use SwornforgedWeb, :controller + + def assets(conn, _params) do + render(conn, :assets, assets: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Asset Types"])) + end + + def moves(conn, _params) do + render(conn, :moves, moves: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Move Categories"])) + end + + def oracles(conn, _params) do + render(conn, :oracles, oracles: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Oracle Categories"])) + end + + def encounters(conn, _params) do + render(conn, :encounters, encounters: get_in(Cachex.get!(:swornforged, :dataforged_json), ["Encounters"])) + end +end diff --git a/lib/swornforged_web/controllers/srd_html.ex b/lib/swornforged_web/controllers/srd_html.ex new file mode 100644 index 0000000..6db68bc --- /dev/null +++ b/lib/swornforged_web/controllers/srd_html.ex @@ -0,0 +1,68 @@ +defmodule SwornforgedWeb.SrdHTML do + use SwornforgedWeb, :html + + embed_templates "srd_html/*" + + def srd_type_title(assigns) do + ~H""" +

<%= render_slot(@inner_block) %>

+ """ + end + + def srd_subtype_title(assigns) do + ~H""" +

<%= render_slot(@inner_block) %>

+ """ + end + + def srd_type_container(assigns) do + ~H""" +
+ <%= render_slot(@inner_block) %> +
+ """ + end + + def srd_item_inner_title(assigns) do + ~H""" +

<%= render_slot(@inner_block) %>

+ """ + end + + def srd_item(assigns) do + ~H""" +
+

+ <%= render_slot(@title) %> +

+
+
+ <%= render_slot(@inner_block) %> +

+ Source +
+ <%= get_in(@item, ["Source", "Title"]) %> + + p.<%= get_in(@item, ["Source", "Page"]) %> + +

+
+
+
+ Raw JSON +
+
<%= Jason.encode!(@item, pretty: true, escape: :html_safe) %>
+
+
+
+
+
+ """ + end +end diff --git a/lib/swornforged_web/controllers/srd_html/assets.html.heex b/lib/swornforged_web/controllers/srd_html/assets.html.heex new file mode 100644 index 0000000..6814850 --- /dev/null +++ b/lib/swornforged_web/controllers/srd_html/assets.html.heex @@ -0,0 +1,25 @@ +<.srd_type_container> + <.srd_type_title>Assets +
+ <.srd_subtype_title> + <%= get_in(asset_type, ["Display", "Title"]) %> + +
    +
  • + <.srd_item item={asset}> + <:title><%= get_in(asset, ["Display", "Title"]) %> +
      +
    1. +
      + +
      + <%= raw(Markdown.get_cache_html!(ability["Text"], ability["$id"], compact_output: true)) %> +
      +
      +
    2. +
    + +
  • +
+
+ \ No newline at end of file diff --git a/lib/swornforged_web/controllers/srd_html/encounters.html.heex b/lib/swornforged_web/controllers/srd_html/encounters.html.heex new file mode 100644 index 0000000..7db9657 --- /dev/null +++ b/lib/swornforged_web/controllers/srd_html/encounters.html.heex @@ -0,0 +1,28 @@ +<.srd_type_container> + <.srd_type_title>Encounters +
+ <.srd_item item={item}> + <:title> + <%= get_in(item, ["Display", "Title"]) %> + +
+
+ <%= raw Markdown.get_cache_html!(item["Description"], item["$id"]) %> +
+
+ <.srd_item item={variant}> + <:title><%= get_in(variant, ["Display", "Title"]) %> +
+ <%= raw Markdown.get_cache_html!(variant["Description"], item["$id"]) %> +
+ +
+
+
+ Quest Starter: <%= item["Quest Starter"] %> +
+
+
+ +
+ \ No newline at end of file diff --git a/lib/swornforged_web/controllers/srd_html/moves.html.heex b/lib/swornforged_web/controllers/srd_html/moves.html.heex new file mode 100644 index 0000000..e7a4ce9 --- /dev/null +++ b/lib/swornforged_web/controllers/srd_html/moves.html.heex @@ -0,0 +1,20 @@ +<.srd_type_container> + <.srd_type_title>Moves +
+ <.srd_subtype_title> + <%= get_in(move_category, ["Display", "Title"]) %> + +
    +
  • + <.srd_item item={move}> + <:title><%= get_in(move, ["Display", "Title"]) %> +
    + <%= raw( + Markdown.get_cache_html!(move["Text"], move["$id"], gfm: true, gfm_tables: true, compact_output: true) + ) %> +
    + +
  • +
+
+ \ No newline at end of file diff --git a/lib/swornforged_web/controllers/srd_html/oracles.html.heex b/lib/swornforged_web/controllers/srd_html/oracles.html.heex new file mode 100644 index 0000000..d80d48c --- /dev/null +++ b/lib/swornforged_web/controllers/srd_html/oracles.html.heex @@ -0,0 +1,63 @@ +<.srd_type_container> + <.srd_type_title>Oracles +
+ <.srd_subtype_title> + <%= get_in(oracle_category, ["Display", "Title"]) %> + +
    +
  • + <.srd_item item={oracle}> + <:title><%= get_in(oracle, ["Display", "Title"]) %> +
    +
    + <%= raw(Markdown.get_cache_html!(str, oracle["$id"], compact_output: true)) %> +
    + + + + + + + + + + + + + +
    RollResult
    <%= row["Floor"] %>-<%= row["Ceiling"] %> + <%= raw(Markdown.get_cache_html!(row["Result"], row["$id"], compact_output: true)) %> +
    +
    +
    +
    + <.srd_item item={inner_oracle}> + <:title><%= get_in(inner_oracle, ["Display", "Title"]) %> +
    + + + + + + + + + + + + + +
    RollResult
    <%= row["Floor"] %>-<%= row["Ceiling"] %> + <%= raw(Markdown.get_cache_html!(row["Result"], row["$id"] || row["Result"], compact_output: true)) %> +
    +
    + +
    +
    + +
  • +
+
+ \ No newline at end of file diff --git a/lib/swornforged_web/router.ex b/lib/swornforged_web/router.ex index 91d2d38..6dc62f0 100644 --- a/lib/swornforged_web/router.ex +++ b/lib/swornforged_web/router.ex @@ -20,6 +20,15 @@ defmodule SwornforgedWeb.Router do get "/", PageController, :home end + scope "/srd/", SwornforgedWeb do + pipe_through :browser + + get "/assets/", SrdController, :assets + get "/moves/", SrdController, :moves + get "/oracles/", SrdController, :oracles + get "/encounters/", SrdController, :encounters + end + # Other scopes may use custom stacks. # scope "/api", SwornforgedWeb do # pipe_through :api diff --git a/mix.exs b/mix.exs index 0c4e8f8..d9e0031 100644 --- a/mix.exs +++ b/mix.exs @@ -32,7 +32,7 @@ defmodule Swornforged.MixProject do # Type `mix help deps` for examples and options. defp deps do [ - {:phoenix, "~> 1.7.0-rc.1", override: true}, + {:phoenix, "~> 1.7.0-rc.2", override: true}, {:phoenix_ecto, "~> 4.4"}, {:ecto_sql, "~> 3.6"}, {:ecto_sqlite3, ">= 0.0.0"}, @@ -53,7 +53,8 @@ defmodule Swornforged.MixProject do {:plug_cowboy, "~> 2.5"}, {:req, "~> 0.3"}, {:cachex, "~> 3.5"}, - {:earmark, "~> 1.4"} + {:earmark, "~> 1.4"}, + {:tailwind_formatter, "~> 0.3.2", only: :dev, runtime: false} ] end diff --git a/mix.lock b/mix.lock index 2815852..92b2015 100644 --- a/mix.lock +++ b/mix.lock @@ -29,7 +29,7 @@ "mint": {:hex, :mint, "1.4.2", "50330223429a6e1260b2ca5415f69b0ab086141bc76dc2fbf34d7c389a6675b2", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "ce75a5bbcc59b4d7d8d70f8b2fc284b1751ffb35c7b6a6302b5192f8ab4ddd80"}, "nimble_options": {:hex, :nimble_options, "0.5.2", "42703307b924880f8c08d97719da7472673391905f528259915782bb346e0a1b", [:mix], [], "hexpm", "4da7f904b915fd71db549bcdc25f8d56f378ef7ae07dc1d372cbe72ba950dce0"}, "nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"}, - "phoenix": {:hex, :phoenix, "1.7.0-rc.1", "28d6591441347ba68da9750771cec6fe18ce040c91095a46d5d332804d5037d5", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.4", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "96d98dcf161b2784fd08a52fd480729a9eeae33773440b4e7a89d1e7e804af52"}, + "phoenix": {:hex, :phoenix, "1.7.0-rc.2", "8faaff6f699aad2fe6a003c627da65d0864c868a4c10973ff90abfd7286c1f27", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.4", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "71abde2f67330c55b625dcc0e42bf76662dbadc7553c4f545c2f3759f40f7487"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"}, @@ -45,7 +45,8 @@ "sleeplocks": {:hex, :sleeplocks, "1.1.2", "d45aa1c5513da48c888715e3381211c859af34bee9b8290490e10c90bb6ff0ca", [:rebar3], [], "hexpm", "9fe5d048c5b781d6305c1a3a0f40bb3dfc06f49bf40571f3d2d0c57eaa7f59a5"}, "swoosh": {:hex, :swoosh, "1.9.1", "0a5d7bf9954eb41d7e55525bc0940379982b090abbaef67cd8e1fd2ed7f8ca1a", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "76dffff3ffcab80f249d5937a592eaef7cc49ac6f4cdd27e622868326ed6371e"}, "tailwind": {:hex, :tailwind, "0.1.9", "25ba09d42f7bfabe170eb67683a76d6ec2061952dc9bd263a52a99ba3d24bd4d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "9213f87709c458aaec313bb5f2df2b4d2cedc2b630e4ae821bf3c54c47a56d0b"}, - "telemetry": {:hex, :telemetry, "1.2.0", "a8ce551485a9a3dac8d523542de130eafd12e40bbf76cf0ecd2528f24e812a44", [:rebar3], [], "hexpm", "1427e73667b9a2002cf1f26694c422d5c905df889023903c4518921d53e3e883"}, + "tailwind_formatter": {:hex, :tailwind_formatter, "0.3.2", "82e38496c049e2da2df6e4f81edf68f3470ee83f4859ba637b57681dfabfb9ba", [:mix], [{:phoenix_live_view, ">= 0.17.6", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "e370e5af152cc7b4350bb6616999433929e01be9e82e895f12beebdbff33a2a2"}, + "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"},