# `Premailex`
[🔗](https://github.com/danschultzer/premailex/blob/v1.0.0/lib/premailex.ex#L1)

Preflight for your HTML emails. Inlines CSS styles and converts HTML to plain text.

## Features

* Inline CSS from `<style>` tags
* Inline CSS from external `<link>` stylesheets
* Convert HTML to plain text

## Usage

Convert an HTML string to plain text:

```elixir
Premailex.to_text(html)
```

Inline an HTML string with CSS styles defined in `<head>`:

```elixir
Premailex.to_inline_css(html)
```

## Example with Swoosh

```elixir
def welcome(user) do
  new()
  |> to({user.name, user.email})
  |> from({"Dr B Banner", "hulk.smash@example.com"})
  |> subject("Hello, Avengers!")
  |> render_body("welcome.html", %{username: user.username})
  |> premail()
end

defp premail(email) do
  html = Premailex.to_inline_css(email.html_body)
  text = Premailex.to_text(email.html_body)

  email
  |> html_body(html)
  |> text_body(text)
end
```

## Example with Bamboo

```elixir
def welcome_email do
  new_email
  |> subject("Email subject")
  |> to("test@example.com")
  |> from("test@example.com")
  |> put_text_layout(false)
  |> render("email.html")
  |> premail()
end

defp premail(email) do
  html = Premailex.to_inline_css(email.html_body)
  text = Premailex.to_text(email.html_body)

  email
  |> html_body(html)
  |> text_body(text)
end
```

## HTML parser

Premailex supports `LazyHTML`, `Floki`, `Meeseeks`, and `m::xmerl`.

It automatically selects the first available parser based on your `mix.exs` dependencies:

```elixir
defp deps do
  [
    {:premailex, "~> 1.0"},
    # {:lazy_html, "~> 0.1.11"},
    # {:floki, "~> 0.24"},
    # {:meeseeks, "~> 0.11"}
  ]
end
```

To explicitly configure which parser to use, add to your `config.exs`:

```elixir
config :premailex, html_parser: Premailex.HTMLParser.Meeseeks
# or
config :premailex, html_parser: Premailex.HTMLParser.LazyHTML
```

# `html`

```elixir
@type html() :: String.t()
```

# `html_element`

```elixir
@type html_element() :: {String.t(), [{String.t(), String.t()}], [html_node()]}
```

# `html_node`

```elixir
@type html_node() :: html_element() | {:comment, String.t()} | String.t()
```

# `html_tree`

```elixir
@type html_tree() :: [html_node()]
```

# `parse`

```elixir
@spec parse(html(), Keyword.t()) :: html_tree()
```

Parses an HTML string into a `t:html_tree/0`.

## Options

  * `:html_parser` - HTML parser to use (see `Premailex.HTMLParser`);

## Examples

    iex> Premailex.parse(~s(<p class="lead">Hello</p>))
    [{"p", [{"class", "lead"}], ["Hello"]}]

# `to_html`

```elixir
@spec to_html(html_tree(), Keyword.t()) :: html()
```

Converts a `t:html_tree/0` into an HTML string.

## Options

  * `:html_parser` - HTML parser to use (see `Premailex.HTMLParser`);

## Examples

    iex> Premailex.to_html([{"p", [{"class", "lead"}], ["Hello"]}])
    ~s(<p class="lead">Hello</p>)

# `to_inline_css`

```elixir
@spec to_inline_css(html() | html_tree(), Keyword.t()) :: html()
```

Adds inline styles to an HTML string or `t:html_tree/0`.

## Options

  * `:html_parser` - HTML parser to use (see `Premailex.HTMLParser`);

  * `:http_adapter` - HTTP adapter to use for fetching external stylesheets
    (see `Premailex.HTTPAdapter`);

  * `:remove_style_tags` - whether to remove the `<style>` and `<link>` tags
    after inlining. Defaults to false;

## Examples

    iex> Premailex.to_inline_css(
    ...> ~s(<html><head>
    ...>   <style>p{background-color: #fff;}</style>
    ...> </head><body>
    ...>   <p style="color: #000;">Text</p>
    ...> </body></html>))
    ~s(<html><head>
       <style>p{background-color: #fff;}</style>
     </head><body>
       <p style="background-color: #fff; color: #000;">Text</p>
     </body></html>)

# `to_text`

```elixir
@spec to_text(html() | html_tree(), Keyword.t()) :: String.t()
```

Converts an HTML string or `t:html_tree/0` to plain text.

## Options

  * `:html_parser` - HTML parser to use (see `Premailex.HTMLParser`);

## Examples

    iex> Premailex.to_text(
    ...> ~s(<html><head>
    ...>   <style>p{background-color:#fff;}</style>
    ...> </head><body>
    ...>   <p style="color:#000;">Text</p>
    ...> </body></html>))
    "Text"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
