README.md

# Phoenix Inline SVG

[![Build Status](https://travis-ci.org/nikkomiu/phoenix_inline_svg.svg?branch=master)](https://travis-ci.org/nikkomiu/phoenix_inline_svg)
[![Coverage Status](https://coveralls.io/repos/github/nikkomiu/phoenix_inline_svg/badge.svg?branch=master)](https://coveralls.io/github/nikkomiu/phoenix_inline_svg?branch=master)
[![Inline docs](http://inch-ci.org/github/nikkomiu/phoenix_inline_svg.svg)](http://inch-ci.org/github/nikkomiu/phoenix_inline_svg)
[![Hex.pm](https://img.shields.io/hexpm/dt/phoenix_inline_svg.svg)](https://hex.pm/packages/phoenix_inline_svg)
[![Hex.pm](https://img.shields.io/hexpm/v/phoenix_inline_svg.svg)](https://hex.pm/packages/phoenix_inline_svg)
[![Hex.pm](https://img.shields.io/hexpm/l/phoenix_inline_svg.svg)](https://hex.pm/packages/phoenix_inline_svg)

Adds support for inline SVG files in Phoenix Framework. This package
allows you to quickly and easily add SVG files into your HTML templates in Phoenix Framework.

## Installation

Add `phoenix_inline_svg` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [{:phoenix_inline_svg, "~> 1.3"}]
end
```

## Usage

```elixir
def view do
  quote do
    ...
    use PhoenixInlineSvg.Helpers, otp_app: :my_app_name
    ...
  end
end
```

### Generic Collection

```elixir
<%= svg_image("home") %>
```

Where `home` is the name of the SVG file you want to load.

This will output the HTML:

```html
<svg>...</svg>
```

By default this will load the SVG file from:

```
/priv/static/svg/generic/home.svg
```

### Collections

There is an optional argument in the function to allow for breaking up SVG files into collections (or folders on the filesystem):

```
<%= svg_image("user", "fontawesome") %>
```

Will result in the output:

```html
<svg>...</svg>
```

This will load the SVG file from:

```
/priv/static/svg/fontawesome/user.svg
```

### HTML attributes

You can also pass optional HTML attributes into the function to set
those properties on the SVG.

```
<%= svg_image("home", class: "logo", id: "bounce-animation") %>
```

Will result in the output:

```html
<svg class="logo" id="bounce-animation">...</svg>
```


## Configuration Options

There are several _optional_ configuration settings for adjusting this package to your needs:

### Directory

The directory in the project to load image assets from. If you are using Exrm make sure you use a directory that is outputted to the projects `lib` directory after the release has been created.

```elixir
config :phoenix_inline_svg, dir: "/priv/somewhere/"
```

The default value is `/priv/static/svg/` and is a directory relative to the project's root directory.

### Default Collection

The name of the collection to use by default. This is usually overridden to be the primary collection of images.

```elixir
config :phoenix_inline_svg, default_collection: "fontawesome"
```

The default value is `generic`

### Not Found

What should be dispayed in the `<i>` element when there is no SVG file found.

```elixir
config :phoenix_inline_svg, not_found: "<p>Oh No!</p>"
```

The default value is:

```
<svg viewbox='0 0 60 60'>
  <text x='0' y='40' font-size='30' font-weight='bold'
    font-family='monospace'>Err</text>
</svg>
```

## Old Style

To use this package in the old style, add the following line to the view function in your `my_app_web.ex` file.

```elixir
def view do
  quote do
    ...
    import PhoenixInlineSvg.Helpers
    ...
  end
end
```

### Caching SVGs

Since the old style will read the images from disk on every request, you can enable caching through a GenServer.

**For Use with Import Only**: If you use the new style, `use PhoenixInlineSvg.Helpers, otp_app: :my_app_name`, your images are already cached since they are loaded into functions at compile time.


Add the following code to the file `lib/__MY_APP_NAME__/inline_svg_cache.ex`.

**Note**: Be sure to change **\_\_MY_APP_NAME\_\_** to the name of your app.

```elixir
defmodule __MY_APP_NAME__.InlineSvgCache do
  use GenServer

  alias PhoenixInlineSvg.Helpers

  #
  # Client API
  #

  def start_link() do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  def svg_image(conn, svg, collection \\ nil) do
    svg_name = "#{collection}/#{svg}"
    case lookup(svg_name) do
      {:ok, data} ->
        data
      {:error} ->
        data =
          if collection != nil do
            Helpers.svg_image(conn, svg, collection)
          else
            Helpers.svg_image(conn, svg)
          end
        insert(svg_name, data)
        data
    end
  end

  def lookup(name) do
    GenServer.call(__MODULE__, {:lookup, name})
  end

  def insert(name, data) do
    GenServer.cast(__MODULE__, {:insert, name, data})
  end

  #
  # Server API
  #

  def init(_) do
    :ets.new(:svg_image, [:named_table, read_concurrency: true])
    {:ok, %{}}
  end

  def handle_call({:lookup, name}, _from, state) do
    data =
      case :ets.lookup(:svg_image, name) do
        [{^name, data}] -> {:ok, data}
        [] -> {:error}
      end
    {:reply, data, state}
  end

  def handle_cast({:insert, name, data}, state) do
    :ets.insert(:svg_image, {name, data})
    {:noreply, state}
  end
end
```