visit
By the end of this article, you should have a working mix project that can generate a PDF from an
HTML
template and json
payload.This tutorial assumes you have basic experience with the Elixir language.We’ll generate our project using
mix
. Running mix new pdfer --sup
(or w/e you call your project) will produce something resembling the following output:Once the project is created, change into the project directory (
cd pdfer
) and open it in your editor — code .
if you’re using (and have that ).Once open, you should see the following files:: This will handle the actual generation of the PDF
: This will be used to parse our template “mapping” data.
NOTE: I’d love some insight from the Elixir community on the differences between and , and if there is a growing preference.
: This handles merging our
json
mapping with our template file. It’s all done using , so it’s super clean and simple.Initially, I tried using from mustache’s own website, however, I wasn’t able to get it working non-empty lists and inverted-selections (something I needed).
After adding the above dependencies to your
mix.exs
, it should look something like this: defp deps do
[
{:bbmustache, github: "soranoba/bbmustache"},
{:jason, "~> 1.1"},
{:pdf_generator, ">=0.5.5"}
]
end
Install all our dependencies with
mix deps.get
and get ready to write some code…template
and mapping
files from disk. This step is actually optional. If you wanted to, you could simply create the variables template
and mapping
and set their values inline to be html
and json
respectively. I’m reading from disk for now simply because it’s more useful out-of-the-box if you wanted to start generating PDFs right away.bbmustache
will take the template
and mapping
and “mustache” them together for us. This is actually really awesome because, otherwise, we’d have to do some messy string interpolation stuff. And frankly, it would be impossible if you were trying to use multiple templates and mappings to generate different PDFs.elixir-pdf-generator
gives us that flexibility.defmodule Pdfer do
@moduledoc """
Documentation for Pdfer.
"""
#
def generate(pdf_path, template_path, mapping_path) do
mapping = Jason.decode!(read_file(mapping_path))
template = read_file(template_path)
template
|> :bbmustache.render(mapping, key_type: :binary)
|> PdfGenerator.generate_binary!()
|> (&File.write("#{pdf_path}.pdf", &1)).()
end
#
defp read_file(filepath) do
__DIR__
|> Path.join(filepath)
|> File.read!()
end
end
Depending on if you decided to read these from disk, or just drop them into the code inline, the final pieces to this may or may not be adding the
template.html
and mapping.json
files.For now, we’ll just dump both of them in the file alongside our module. Create a
template.html
and mapping.json
at pdfer/lib/
with the following contents:<html>
<body>
<h1>Hello {{ location }}</h1>
</body>
</html>
{"location": "World"}
That’s it! We’re ready to generate a PDF. Run our code with
iex -S mix
to drop into iex
. From there we’ll run our module, giving it three arguments. A PDF name, the template file name, and the mapping file name:iex(1)> Pdfer.generate("test", "template.html", "mapping.json"
Almost instantly, you should see a
test.pdf
in the root of your project directory.