Cache icon bodies and components
This commit is contained in:
@ -18,12 +18,23 @@ defmodule Heroicons do
|
||||
"""
|
||||
|
||||
# https://github.com/tailwindlabs/heroicons/releases
|
||||
|
||||
@latest_version "2.0.10"
|
||||
|
||||
@tmp_dir_name "heroicons-elixir"
|
||||
|
||||
use Application
|
||||
require Logger
|
||||
|
||||
@doc false
|
||||
def start(_type, _args) do
|
||||
children = [
|
||||
{Heroicons.IconCache, []}
|
||||
]
|
||||
|
||||
opts = [strategy: :one_for_one, name: Heroicons.Supervisor]
|
||||
Supervisor.start_link(children, opts)
|
||||
end
|
||||
|
||||
@doc false
|
||||
# Latest known version at the time of publishing.
|
||||
def latest_version, do: @latest_version
|
||||
|
@ -66,14 +66,13 @@ defmodule Heroicons.Generator do
|
||||
attrs = @assigns_to_attrs_mod.assigns_to_attributes(assigns)
|
||||
assigns = @assign_mod.assign(assigns, :attrs, attrs)
|
||||
|
||||
EEx.compile_string("<svg {@attrs}" <> Heroicons.IconCache.icon_body(path),
|
||||
engine: Phoenix.LiveView.HTMLEngine,
|
||||
file: __ENV__.file,
|
||||
line: __ENV__.line + 1,
|
||||
module: __ENV__.module,
|
||||
indentation: 0,
|
||||
assigns: assigns
|
||||
)
|
||||
{component, _binding} =
|
||||
Code.eval_quoted(
|
||||
Heroicons.IconCache.fetch_component(path),
|
||||
assigns: assigns
|
||||
)
|
||||
|
||||
component
|
||||
end
|
||||
|
||||
@doc false
|
||||
@ -93,7 +92,7 @@ defmodule Heroicons.Generator do
|
||||
"<svg",
|
||||
Phoenix.HTML.Safe.to_iodata(attrs),
|
||||
" ",
|
||||
Heroicons.IconCache.icon_body(path)
|
||||
Heroicons.IconCache.fetch_body(path)
|
||||
]}
|
||||
end
|
||||
end
|
||||
|
@ -1,8 +1,64 @@
|
||||
defmodule Heroicons.IconCache do
|
||||
|
||||
@doc "Get's an icon's body from the filesystem"
|
||||
# TODO implement ETS-based caching & benchmark
|
||||
def icon_body(path) do
|
||||
use GenServer
|
||||
|
||||
@name __MODULE__
|
||||
|
||||
def start_link(_), do: GenServer.start_link(__MODULE__, [], name: @name)
|
||||
|
||||
def fetch_component(path) do
|
||||
case :ets.lookup(@name.Components, path) do
|
||||
[{^path, component}] ->
|
||||
component
|
||||
|
||||
[] ->
|
||||
GenServer.call(@name, {:cache_component, path})
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_body(path) do
|
||||
case :ets.lookup(@name, path) do
|
||||
[{^path, body}] ->
|
||||
body
|
||||
|
||||
[] ->
|
||||
GenServer.call(@name, {:cache_body, path})
|
||||
end
|
||||
end
|
||||
|
||||
def init(_) do
|
||||
:ets.new(@name, [:set, :protected, :named_table])
|
||||
:ets.new(@name.Components, [:set, :protected, :named_table])
|
||||
|
||||
{:ok, []}
|
||||
end
|
||||
|
||||
def handle_call({:cache_body, path}, _ref, state) do
|
||||
body = read_body(path)
|
||||
|
||||
:ets.insert_new(@name, {path, body})
|
||||
|
||||
{:reply, body, state}
|
||||
end
|
||||
|
||||
def handle_call({:cache_component, path}, _ref, state) do
|
||||
body = read_body(path)
|
||||
|
||||
component =
|
||||
EEx.compile_string("<svg {@attrs}" <> body,
|
||||
engine: Phoenix.LiveView.HTMLEngine,
|
||||
file: __ENV__.file,
|
||||
line: __ENV__.line + 1,
|
||||
module: __ENV__.module,
|
||||
indentation: 0
|
||||
)
|
||||
|
||||
:ets.insert_new(@name.Components, {path, component})
|
||||
|
||||
{:reply, component, state}
|
||||
end
|
||||
|
||||
defp read_body(path) do
|
||||
icon = File.read!(path)
|
||||
|
||||
<<"<svg ", body::binary>> = icon
|
||||
|
Reference in New Issue
Block a user