diff --git a/lib/sloane_sh/asset.ex b/lib/sloane_sh/asset.ex index c66749f..63fca9f 100644 --- a/lib/sloane_sh/asset.ex +++ b/lib/sloane_sh/asset.ex @@ -13,7 +13,7 @@ defmodule SloaneSH.Asset do @callback extensions(cfg :: Config.t()) :: [String.t()] @callback attrs(cfg :: Config.t(), path :: String.t(), data :: binary()) :: - {:ok, map(), without_attrs :: binary()} | {:ok, map()} | :error | {:error, term()} + {:ok, map(), without_attrs :: term()} | {:ok, map()} | :error | {:error, term()} @callback render( cfg :: Config.t(), diff --git a/lib/sloane_sh/assets/image.ex b/lib/sloane_sh/assets/image.ex index 5dae625..1547660 100644 --- a/lib/sloane_sh/assets/image.ex +++ b/lib/sloane_sh/assets/image.ex @@ -8,12 +8,35 @@ defmodule SloaneSH.Assets.Image do def extensions(_cfg), do: ~w[.jpg .jpeg .png .webp .gif] @impl Asset - def attrs(_cfg, _path, _data) do - {:ok, %{}} + def attrs(_cfg, _path, data) do + {:ok, image} = Image.from_binary(data) + + aspect = Image.aspect(image) + {width, height, _} = Image.shape(image) + + {:ok, %{aspect: aspect, width: width, height: height}, image} end @impl Asset def render(cfg, _ctx, path, data, _attrs) do - {:ok, [{OutputDirs.image(cfg, path), data}]} + formats = ~w[.webp .png .jpg] + + outputs = + for format <- formats do + format_path = OutputDirs.replace_ext(path, format) + output_path = OutputDirs.image(cfg, format_path) + + {:ok, converted} = + Image.write(data, :memory, + suffix: format, + strip_metadata: true, + minimize_file_size: true, + quality: 80 + ) + + {output_path, converted} + end + + {:ok, outputs} end end diff --git a/lib/sloane_sh/layouts/helpers.ex b/lib/sloane_sh/layouts/helpers.ex index 8109509..603177b 100644 --- a/lib/sloane_sh/layouts/helpers.ex +++ b/lib/sloane_sh/layouts/helpers.ex @@ -1,5 +1,7 @@ defmodule SloaneSH.Layouts.Helpers do + require Logger alias SloaneSH.Context + alias SloaneSH.OutputDirs def cx(classes) do classes @@ -20,4 +22,35 @@ defmodule SloaneSH.Layouts.Helpers do def fmt_date(date) do Timex.format!(date, "{Mfull} {D}, {YYYY}") end + + def picture(ctx, src, alt \\ "", class \\ "") do + image = Enum.find(ctx.images, fn i -> + output = OutputDirs.image(ctx.config, i.src) + src == OutputDirs.to_permalink(ctx.config, output) + end) + + if is_nil(image) do + Logger.warning("Could not find #{inspect(src)} to make picture element") + ~s|#{alt}| + else + [{_, src} | srcsets] = [ + {"image/jpg", ".jpg"}, + {"image/webp", ".webp"}, + {"image/png", ".png"}, + ] + |> Enum.map(fn {type, ext} -> + {type, OutputDirs.replace_ext(src, ext)} + end) + + + EEx.eval_string(~S""" + + <%= for {type, srcset} <- srcsets do %> + + <% end %> + <%= alt %> + + """, src: src, srcsets: srcsets, alt: alt, class: class) + end + end end diff --git a/lib/sloane_sh/layouts/partials.ex b/lib/sloane_sh/layouts/partials.ex index 6e62216..80113ae 100644 --- a/lib/sloane_sh/layouts/partials.ex +++ b/lib/sloane_sh/layouts/partials.ex @@ -16,7 +16,10 @@ defmodule SloaneSH.Layouts.Partials do <% end %>
- sloane.sh +
+ sloane.sh + <%= picture(ctx, "/assets/images/heart.png", "a purple heart emoji", "w-4 h-4") %> +