View Source CozySVG (cozy_svg v0.2.2)

A tiny and fast library to compile and render SVG files.

CozySVG reads the SVG files at compile-time and provides runtime access through a term stored in the BEAM file, which is very fast to access.

Why use it?

It is recommended to embed the SVG data into web pages instead of asking the browser to make additional requests to servers. This makes web pages load faster.

CozySVG provides the key ability to do this - reading the SVG files as strings in an efficient way. That's the key.

Usage

To use CozySVG, it's better to create a wrapper module instead of calling the low-level API directly.

create wrapper module with pre-built macro

See CozySVG.QuickWrapper for more details.

create wrapper module with low-level API

This method offers the greatest flexibility, allowing you to customize naming , rendering or compiling as required.

An example:

defmodule DemoWeb.SVG do
  # Build the library at compile time
  @library CozySVG.compile("assets/svg")

  # Accesses the library at runtime
  defp library(), do: @library

  # Render an SVG from the library
  def render(key, attrs \ []) do
    CozySVG.render(library(), key, attrs)
  end

  # Render an SVG from the library
  def render!(key, attrs \ []) do
    CozySVG.render!(library(), key, attrs)
  end
end

DemoWeb.SVG.render/1 / DemoWeb.SVG.render/2 / DemoWeb.SVG.render!/1 / DemoWeb.SVG.render!/2 will be ready to use.

@library should be accessed through a function.

The library could be very large, wrapping it with a function ensures that it is only stored as a term in BEAM file once.

The requirements for SVG files

Every SVG file must contain a single valid <svg></svg> tag.

Anything before the <svg> tag or after the </svg> tag is treated as comment and stripped from the content during compilation.

Phoenix Integration

svg/1 component

An example module:

defmodule DemoWebSvgComponents do
  defmodule CompiledSVG do
    use CozySVG.QuickWrapper, root: "assets/svg"
  end

  use Phoenix.Component
  import Phoenix.HTML, only: [raw: 1]

  attr :key, :string, required: true, doc: "The key for SVG file."
  attr :rest, :global, doc: "Additional attributes to add to the <svg> tag."

  def svg(assigns) do
    ~H"""
    <%= raw(CompiledSVG.render!(@key, @rest)) %>
    """
  end
end

Live reloading

Enable live reloading by telling Phoenix to watch the SVG directory:

live_reload: [
  patterns: [
    # ...
    ~r"assets/svg/*/.*(svg)$"
  ]
]

Summary

Functions

Compiles a folder of *.svg files into a library.

Renders an SVG as a string.

Renders an SVG as a string.

The bang variant of render/2.

The bang variant of render/3.

Types

@type attrs() :: keyword() | map()
@type key() :: String.t()
@type library() :: map()
@type path() :: String.t()

Functions

Link to this function

compile(library \\ %{}, root)

View Source
@spec compile(library(), path()) :: library()

Compiles a folder of *.svg files into a library.

The folder and it's subfolders will be traversed and all valid *.svg files will be added to the library with a key that is relative path of the SVG file minus the .svg part.

For example, if you compile the folder "assets/svg" and it finds a file with the path "assets/svg/heroicons/calendar.svg", then the key for that SVG is "heroicons/calendar" in the library.

Examples

# Compiles a folder
CozySVG.compile("assets/svg")

# Compiles multiple folders
CozySVG.compile("assets/svg_a")
|> CozySVG.compile("assets/svg_b")

# Or, compiles multiple folders with a neater pipeline
%{}
|> CozySVG.compile("assets/svg_a")
|> CozySVG.compile("assets/svg_b")
@spec render(library(), key()) ::
  {:ok, String.t()} | {:error, CozySVG.RuntimeError.t()}

Renders an SVG as a string.

The named svg must be in the provided library, which should be built using the compile function.

Examples

iex> CozySVG.render(library(), "heroicons/menu")
{:ok, "<svg xmlns= ... </svg>"}
Link to this function

render(library, key, attrs)

View Source
@spec render(library(), key(), attrs()) ::
  {:ok, String.t()} | {:error, CozySVG.RuntimeError.t()}

Renders an SVG as a string.

The named svg must be in the provided library, which should be built using the compile function.

The attrs will be inserted as attributes of the <svg></svg> tag. But keep one thing in mind, the underscore character "_" in attribute name will be converted to the hyphen character "-".

Examples

iex> CozySVG.render(library(), "heroicons/menu", class: "h-5 w-5")
{:ok, "<svg class="h-5 w-5" xmlns= ... </svg>"}

iex> CozySVG.render(library(), "heroicons/menu", %{phx_click: "action"})
{:ok, "<svg phx-click="action" xmlns= ... </svg>"}
@spec render!(library(), key()) :: String.t()

The bang variant of render/2.

Examples

iex> CozySVG.render!(library(), "heroicons/menu")
"<svg xmlns= ... </svg>"
Link to this function

render!(library, key, attrs)

View Source
@spec render!(library(), key(), attrs()) :: String.t()

The bang variant of render/3.

Examples

iex> CozySVG.render!(library(), "heroicons/menu", class: "h-5 w-5")
"<svg class="h-5 w-5" xmlns= ... </svg>"

iex> CozySVG.render!(library(), "heroicons/menu", %{phx_click: "action"})
"<svg phx-click="action" xmlns= ... </svg>"