lib/phoenix/live_editable/svg.ex

defmodule Phoenix.LiveEditable.Svg do

  @moduledoc """
  Inline SVG utilities.

  FontAwesome-style SVG vector icons, embedded in your code.

  The workflow is: 
  - download the SVG to `assets/static/svg`
  - customize the SVG with default size, color, etc.
  - use the inline SVG macros in your views and string functions

  This approach compiles the SVG into your binary.  Fast, efficient and safe.
  Simpler to use than CDN or NPM approaches.

  To learn more, read the [Elixir Forum Thread][1] on embedded SVGs.

  [1]: https://elixirforum.com/t/svgs-eex-tags-inlining-from-external-file/25942
  """

  @doc """
  Inline SVG for EEX tags.

  Usage Example:

  The file `MyIcon` must be located in `assets/static/svg/MyIcon.svg`.

  You'll have to `require` the SVG module in your view:
  
      defmodule MyappWeb.PageView do
        use MyappWeb, :view
        require Phoenix.LiveEditable.Svg
      end

  Then you can use the function in an EEX tag:

      <%= Phoenix.LiveEditable.Svg.inline_tag("MyIcon") %>
      
  """
  defmacro inline_tag(file) do
    path = static_path(file)
    case File.read(path) do
      {:ok, text} -> quote do: {:safe, unquote(text)}
      {:error, _} -> raise "No SVG for #{path}"
    end
  end

  @doc """
  Inline SVG for elixir functions.

  Returns the SVG text.

  Usage Example:

  The file `MyIcon` must be located in `assets/static/svg/MyIcon.svg`.

  You'll have to `require` the SVG module in your target code:
  
      defmodule MyappWeb.Mycode do
        require Phoenix.LiveEditable.Svg

        def my_svg(file) do
          Phoenix.LiveEditable.Svg.inline(file)
        end
      end

  Then you can use the function in your Elixir code:

      Myapp.Mycode.my_svg("MyIcon")
      
  """
  defmacro inline(file) do
    path = static_path(file)
    case File.read(path) do
      {:ok, text} -> quote do: unquote(text)
      {:error, _} -> raise "No SVG for #{path}"
    end
  end

  defp static_path(file_name) do
    path = "#{__DIR__}/../../../assets/static/svg"
    [path, "#{file_name}.svg"] |> Path.join() |> Path.expand 
  end
end