Skip to content

Commit 6dfa835

Browse files
committed
Add image generation & routing
1 parent fbc0162 commit 6dfa835

File tree

7 files changed

+157
-9
lines changed

7 files changed

+157
-9
lines changed

lib/vyasa/corpus/gita.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ defmodule Vyasa.Corpus.Gita do
5757
end
5858

5959
def verse(chapter_no, verse_no) when is_binary(verse_no) and is_binary(chapter_no) do
60-
IO.puts("testing... #{chapter_no}, #{verse_no} \n\n")
60+
IO.puts("checking verse resolution... #{chapter_no}, #{verse_no} \n\n")
6161

6262
verse = @verses[String.to_atom(chapter_no)]
6363
|> Enum.find(fn %{:verse_number => verse_num} -> Integer.to_string(verse_num) === verse_no end)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule VyasaWeb.OgImageController do
2+
use VyasaWeb, :controller
3+
4+
def show(conn, %{"filename" => filename}) do
5+
target_url = System.tmp_dir() |> Path.join(filename)
6+
case File.exists?(target_url) do
7+
true ->
8+
conn
9+
|> put_resp_content_type("image/png")
10+
|> send_file(200, target_url)
11+
_ ->
12+
conn
13+
|> send_resp(404, "Not found")
14+
end
15+
end
16+
end
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
defmodule VyasaWeb.GitaLive.ImageGenerator do
2+
@moduledoc """
3+
Contains logic for creating images, initially for opengraph purposes mainly.
4+
"""
5+
@fallback_text "Gita -- The Song Celestial"
6+
@col_width 20
7+
alias VyasaWeb.GitaLive.ImageGenerator
8+
alias Vix.Vips.Operation
9+
10+
@doc """
11+
Returns a url string that can be used for the open-graph image meta-tag.
12+
Currently stores images locally in a temp directory.
13+
"""
14+
def generate_opengraph_image(filename, title \\ @fallback_text) do
15+
url =
16+
title
17+
|> generate_svg()
18+
|> write_opengraph_image(filename)
19+
20+
url
21+
end
22+
23+
defp write_opengraph_image(svg, filename) do
24+
target_url = System.tmp_dir() |> Path.join(filename)
25+
IO.puts(">> [write_opengraph_image] target url: #{target_url}")
26+
{image, _} = Operation.svgload_buffer!(svg)
27+
28+
Image.write!(image, target_url)
29+
target_url
30+
end
31+
32+
defp generate_svg(title) do
33+
svg_text_nodes =
34+
title
35+
|> ImageGenerator.wrap_text(@col_width)
36+
|> Enum.with_index()
37+
|> Enum.map(fn
38+
{line, idx} -> get_svg_for_text(line, idx)
39+
end)
40+
|> Enum.join("")
41+
42+
svg_precursor = """
43+
<svg viewbox="0 0 1200 600" width="1200px" height="600px" xmlns="http://www.w3.org/2000/svg">
44+
<defs>
45+
<linearGradient y2="1" x2="1" y1="0.14844" x1="0.53125" id="gradient">
46+
<stop offset="0" stop-opacity="0.99609" stop-color="#5b21b6"/>
47+
<stop offset="0.99219" stop-opacity="0.97656" stop-color="#ff8300"/>
48+
</linearGradient>
49+
</defs>
50+
<g>
51+
<rect stroke="#000" height="800px" width="1800px" y="0" x="0" stroke-width="0" fill="url(#gradient)"/>
52+
"""
53+
54+
svg_end = """
55+
</g>
56+
</svg>
57+
"""
58+
svg = svg_precursor <> svg_text_nodes <> svg_end
59+
svg
60+
end
61+
62+
defp get_svg_for_text(text, offset) do
63+
initial_y = 250
64+
vert_line_space = 90
65+
y_resolved = Integer.to_string(initial_y + vert_line_space * offset)
66+
67+
"""
68+
<text textLength="500px" lengthAdjust="spacingAndGlyphs" font-style="normal" font-weight="normal" xml:space="preserve" text-anchor="start" font-family="'Alumni Sans'" font-size="70" y="#{y_resolved}" x="100" stroke-width="0" stroke="#000" fill="#f8fafc">#{text}</text>
69+
"""
70+
end
71+
72+
@doc """
73+
Manually wraps a text to width of size @col_width.
74+
"""
75+
def wrap_text(text, col_length \\ @col_width) do
76+
77+
78+
words = String.split(text, " ")
79+
80+
Enum.reduce(words, [], fn word, acc_lines ->
81+
IO.puts("[word:] #{word}")
82+
curr_line = List.last(acc_lines, "")
83+
new_combined_line = curr_line <> " " <> word
84+
has_space_in_curr_line = String.length(new_combined_line) <= col_length
85+
86+
if has_space_in_curr_line do
87+
if acc_lines == [] do
88+
[word]
89+
else
90+
List.replace_at(acc_lines, length(acc_lines) - 1, new_combined_line)
91+
end
92+
else
93+
acc_lines ++ [word]
94+
end
95+
end)
96+
end
97+
end

lib/vyasa_web/live/gita_live/show_verse.ex

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
defmodule VyasaWeb.GitaLive.ShowVerse do
22
use VyasaWeb, :live_view
33
alias Vyasa.Corpus.Gita
4+
alias VyasaWeb.GitaLive.ImageGenerator
45

56
@impl true
67
def mount(_params, _session, socket) do
@@ -14,12 +15,9 @@ defmodule VyasaWeb.GitaLive.ShowVerse do
1415
|> assign(:chapter, Gita.chapters(chapter_no))
1516
|> stream(:verses, Gita.verses(chapter_no))
1617
|> assign(:verse, Gita.verse(chapter_no, verse_no))
17-
|> assign_meta()
18-
19-
}
18+
|> assign_meta()}
2019
end
2120

22-
2321
defp assign_meta(socket) do
2422
IO.inspect(socket.assigns.verse)
2523
%{:chapter_id => chapter, :verse_number => verse, :text => text} = socket.assigns.verse
@@ -28,8 +26,24 @@ defmodule VyasaWeb.GitaLive.ShowVerse do
2826
title: "Chapter #{chapter} | Verse #{verse}",
2927
description: text,
3028
type: "website",
31-
url: url(socket, ~p"/gita/#{chapter}/#{verse}"),
29+
image: url(~p"/images/#{get_image_url(socket, chapter, verse)}"),
30+
url: url(socket, ~p"/gita/#{chapter}/#{verse}")
3231
})
3332
end
3433

34+
@opengraph_filename_prefix "opengraph_file"
35+
@image_file_ext ".png"
36+
defp get_image_url(socket, chapter_num, verse_num) do
37+
filename =
38+
@opengraph_filename_prefix <>
39+
"-" <> Integer.to_string(chapter_num) <> "-" <> Integer.to_string(verse_num) <> @image_file_ext
40+
target_url = System.tmp_dir() |> Path.join(filename)
41+
42+
if File.exists?(target_url) do
43+
target_url
44+
else
45+
text = socket.assigns.verse.text
46+
ImageGenerator.generate_opengraph_image(filename, text)
47+
end
48+
end
3549
end

lib/vyasa_web/router.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ defmodule VyasaWeb.Router do
1414
plug :accepts, ["json"]
1515
end
1616

17+
18+
1719
scope "/", VyasaWeb do
1820
pipe_through :browser
1921

22+
23+
get "/images/:filename", OgImageController, :show
24+
2025
get "/", PageController, :home
2126
live "/gita/", GitaLive.Index, :index
2227
live "/gita/:chapter_id", GitaLive.Show, :show
@@ -47,6 +52,7 @@ defmodule VyasaWeb.Router do
4752
scope "/dev" do
4853
pipe_through :browser
4954

55+
5056
live_dashboard "/dashboard", metrics: VyasaWeb.Telemetry
5157
forward "/mailbox", Plug.Swoosh.MailboxPreview
5258
end

mix.exs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defmodule Vyasa.MixProject do
77
version: "0.1.0-alpha.1",
88
elixir: "~> 1.14",
99
elixirc_paths: elixirc_paths(Mix.env()),
10-
elixirc_options: [
10+
elixirc_options: [
1111
warnings_as_errors: true
1212
],
1313
start_permanent: Mix.env() == :prod,
@@ -53,7 +53,10 @@ defmodule Vyasa.MixProject do
5353
{:gettext, "~> 0.20"},
5454
{:jason, "~> 1.2"},
5555
{:dns_cluster, "~> 0.1.1"},
56-
{:plug_cowboy, "~> 2.5"}
56+
{:plug_cowboy, "~> 2.5"},
57+
{:image, "~> 0.37"},
58+
{:vix, "~> 0.5"},
59+
{:kino, "~> 0.12.0"}
5760
]
5861
end
5962

@@ -71,7 +74,11 @@ defmodule Vyasa.MixProject do
7174
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
7275
"assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
7376
"assets.build": ["tailwind default", "esbuild default"],
74-
"assets.deploy": ["tailwind default --minify", "esbuild default --minify --loader:.ttf=file", "phx.digest"]
77+
"assets.deploy": [
78+
"tailwind default --minify",
79+
"esbuild default --minify --loader:.ttf=file",
80+
"phx.digest"
81+
]
7582
]
7683
end
7784
end

mix.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
%{
22
"castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"},
3+
"cc_precompiler": {:hex, :cc_precompiler, "0.1.9", "e8d3364f310da6ce6463c3dd20cf90ae7bbecbf6c5203b98bf9b48035592649b", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "9dcab3d0f3038621f1601f13539e7a9ee99843862e66ad62827b0c42b2f58a54"},
34
"cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"},
45
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
56
"cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"},
@@ -8,14 +9,18 @@
89
"dns_cluster": {:hex, :dns_cluster, "0.1.1", "73b4b2c3ec692f8a64276c43f8c929733a9ab9ac48c34e4c0b3d9d1b5cd69155", [:mix], [], "hexpm", "03a3f6ff16dcbb53e219b99c7af6aab29eb6b88acf80164b4bd76ac18dc890b3"},
910
"ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"},
1011
"ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"},
12+
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"},
1113
"esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"},
1214
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
1315
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
1416
"finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"},
1517
"floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"},
18+
"fss": {:hex, :fss, "0.1.1", "9db2344dbbb5d555ce442ac7c2f82dd975b605b50d169314a20f08ed21e08642", [:mix], [], "hexpm", "78ad5955c7919c3764065b21144913df7515d52e228c09427a004afe9c1a16b0"},
1619
"gettext": {:hex, :gettext, "0.23.1", "821e619a240e6000db2fc16a574ef68b3bd7fe0167ccc264a81563cc93e67a31", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "19d744a36b809d810d610b57c27b934425859d158ebd56561bc41f7eeb8795db"},
1720
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
21+
"image": {:hex, :image, "0.39.0", "c003ce095ee32c40f194ca1a48ffa6d3e67192e567183e70dfd8b77bb7144119", [:mix], [{:bumblebee, "~> 0.3", [hex: :bumblebee, repo: "hexpm", optional: true]}, {:evision, "~> 0.1.33", [hex: :evision, repo: "hexpm", optional: true]}, {:exla, "~> 0.5", [hex: :exla, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}, {:nx, "~> 0.5", [hex: :nx, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.14 or ~> 3.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: true]}, {:rustler, "> 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: false]}, {:vix, "~> 0.23", [hex: :vix, repo: "hexpm", optional: false]}], "hexpm", "d83de26e009a59cb8c53d2efecaacd7c9b990897dc3c7095a5b8847e73c8f968"},
1822
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
23+
"kino": {:hex, :kino, "0.12.0", "dfebe415f31cf2f54d98600178c08fd017931d9dada6fb59b7716b5431bee4a1", [:mix], [{:fss, "~> 0.1.0", [hex: :fss, repo: "hexpm", optional: false]}, {:nx, "~> 0.1", [hex: :nx, repo: "hexpm", optional: true]}, {:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "6796a64ae978fc2e50e52cae022ae6a3d28b8e50589af158b8f3904e7f748377"},
1924
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
2025
"mint": {:hex, :mint, "1.5.1", "8db5239e56738552d85af398798c80648db0e90f343c8469f6c6d8898944fb6f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4a63e1e76a7c3956abd2c72f370a0d0aecddc3976dea5c27eccbecfa5e7d5b1e"},
2126
"nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"},
@@ -33,11 +38,14 @@
3338
"plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"},
3439
"postgrex": {:hex, :postgrex, "0.17.3", "c92cda8de2033a7585dae8c61b1d420a1a1322421df84da9a82a6764580c503d", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "946cf46935a4fdca7a81448be76ba3503cff082df42c6ec1ff16a4bdfbfb098d"},
3540
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
41+
"sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"},
3642
"swoosh": {:hex, :swoosh, "1.14.0", "710e363e114dedb4080b737e0307f5410887ffc9a239f818231e5618b6b84e1b", [: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, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {: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", "dccfc986ac99c18345ab3e1a8b934b2d817fd6d59a2494f0af78502184c71025"},
43+
"table": {:hex, :table, "0.1.2", "87ad1125f5b70c5dea0307aa633194083eb5182ec537efc94e96af08937e14a8", [:mix], [], "hexpm", "7e99bc7efef806315c7e65640724bf165c3061cdc5d854060f74468367065029"},
3744
"tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"},
3845
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
3946
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
4047
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
48+
"vix": {:hex, :vix, "0.26.0", "027f10b6969b759318be84bd0bd8c88af877445e4e41cf96a0460392cea5399c", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "71b0a79ae7f199cacfc8e679b0e4ba25ee47dc02e182c5b9097efb29fbe14efd"},
4149
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
4250
"websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"},
4351
}

0 commit comments

Comments
 (0)