#6: Parsing Markdown in Elixir with Earmark

Episode notes

Elixir 1.3.4

Phoenix 1.2.1

Earmark 1.1.1

Episode source code on GitHub

Here we have some movie summaries that have text saved in markdown format. As you can see it’s not being rendered as HTML. Let’s fix that by using the Earmark library by Dave Thomas.

First let’s head to our ‘Mixfile’. And add Earmark to our list of dependencies.

mix.exs

def deps do
…
{:earmark, "~> 1.1"}
…
end

Then let’s fetch our dependencies.

$ mix deps.get

Great, now we can start up our server.

$ mix phoenix.server

Going to our project, we’ll open web/templates/movie/index.html.eex

Let’s go to where we’re rending our markdown, in this case our movie summary.

Now there are two functions for rendering content as html with Earmark.

Earmark.as_html, which will return a tuple indicating if the transformation was successful or not.

And Earmark.as_html! which will return our html and print any error messages to standard error. Let’s use this.

web/templates/movie/index/html.eex

<%= Earmark.as_html!(movie.summary) %>

Now if we go back to the browser, it’ looks like we’re getting HTML, but we’re seeing all of our HTML tags.

One way we can fix this is to use the Phoenix.HTML.raw/1 function.

web/templates/movie/index/html.eex

<%= raw(Earmark.as_html!(movie.summary)) %>

And now if we go back to our browser, we see everything is being rendering correctly. Let’s take this opportunity to refactor our code a bit.

We’ll go to web/views/movie_view.ex. And in it we’ll create a simple function we can use to transform our markdown to HTML.

We’ll call it as_html with ‘txt’ as the parameter.

In this function we’ll take ‘txt’ and pipe it into Earmark.as_html!

And the result of that into raw/1.

web/views/movie_view.ex

def as_html(txt) do
    txt
    |> Earmark.as_html!
    |> raw
end

Back in our template let’s update it to call our new function with ‘movie.summary’ as the argument.

web/templates/movie/index.html.eex

<%= as_html(movie.summary) %>

And if we go back to the browser, it’s still working.

Earmark has a lot of great options to help you customize your output. For a simple example let’s see how we can swap our curly quotes for straight quotes.

Going to the Earmark README, we see there’s an %Earmark.Options{} struct we can use to customize the transformation. And it looks like the ‘smartypants’ option is set to ‘true’ by default, which causes our quotes to be curly. To update this let’s go to web/views/movie_view.ex.

first let’s alias Earmark.Options.

Then we can pass in our ‘Options’ with ‘smartypants’ set to ‘false’.

web/views/movie_view.ex

alias Earmark.Options

def as_html(txt) do
    txt
    |> Earmark.as_html!(%Options{smartypants: false})
    |> raw
end

And if we go back to the browser our curly quotes are gone.

Another cool feature of Earmark is that it can be used from the command line. Let’s see how it works.

First we’ll clone Earmark.

$ git clone git@github.com:pragdave/earmark.git

Then we’ll go into the library and fetch the dependencies and compile it.

$ cd earmark
$ mix deps.get
$ mix compile

Now let’s create a simple markdown file to test.

earmark/markdown.md

This Is A Test
=========

This *will transform* into **markdown**!

Then we can generate an executable with ‘escript’.

Let’s run $ mix escript.build.

Now this will create an executable, in our case it’s named ‘earmark’. We can then run our executable with our markdown file.

$ ./earmark markdown.md
<h1>This Is A Tests</h1>
<p>This <em>will transform</em> info <strong>markdown</strong>!</p>

And great it was transformed into HTML.