jonnycharles

jonnycharles

I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions about this topic in the past, I’m interested in any recent developments or current libraries that the community recommends. Key features I’m looking for include support for complex layouts, text styling, and custom tables. Any insights or suggestions would be greatly appreciated!

Showing Posts 1 to 10

Hermanverschooten

Hermanverschooten

There (sadly) is no real equivalence to Prawn for Elixir.

There are 2 libraries, pdf and mudbrick. The first is more mature, uses GenServers to store the state of the pdf being build, where the second one is very new and still lacking a lot of features, but it uses a struct to store the state.
Mudbrick is easy to extend with your own features, where pdf is practically impossible to extend.
Mudbrick supports OpenType (otf) fonts, pdf, adobe type mananger (atm).

If you do not want to shell out to something like htmltopdf, these are currently the most feasible options.

The font-handling in pdf was recently rewritten, making it compile several times faster.

I have been using pdf for several years, tried mudbrick, I like it, but is not yet there.

10
Post #1
kokolegorille

kokolegorille

If You really miss prawn, You can run it in Elixir with erlport…

_io2

_io2

We have had great success with https://wkhtmltopdf.org/

Within our phoenix application, a simple GenServer calls out to the wkhtmltopdf binary, passing along generated html and returning the resulting pdf file.

The html itself is generated from a bunch of $template.html.heex files and for each new PDF document type we simply add a new *.html.heex file.

We produce a lot of different types of pdf reports, and regularly add new ones so this approach (converting html → pdf) makes it easy to assign that task to anyone who can write html, and allows us to produce some very rich, and complex page / document designs.

dimitarvp

dimitarvp

I wanted to bring it up but assumed they were not okay with the Chromium dependence.

lccezinha

lccezinha

Here we are using GitHub - gutschilla/elixir-pdf-generator: Create PDFs with wkhtmltopdf or puppeteer/chromium from Elixir. · GitHub for simple PDF and it has been working fine for the last years

outlog

outlog

+1 for wkhtmltopdf

egze

egze

Nice. Didn’t know about mudbrick. A modern native Elixir PDF writer would be so cool for the ecosystem.

mindok

mindok

It depends what you’re looking for, but we use typst (https://typst.app/). We use it to generate high quality output for work instructions (images, pixel perfect layout, table of contents etc etc). Having used it for that, I’d also use it for things like database reports, invoice generation etc. It’s also deterministic - it doesn’t rely on browser engines etc to interpret CSS, so once you have placed elements on a page, they stay put.

There’s a command-line version that compiles to a single binary (it’s written in Rust, so easy enough to add to your docker builder image for most platforms [I think that’s the lingo - I’m no docker whiz]. Build time is a couple of minutes, but the guys at Alembic designed the docker build to minimise the likelihood that it needs to be recompiled for each deploy). We’re currently just calling it with System.cmd. The main downer is you have to assemble all the inputs (e.g. images, JSON data extracts) into the directory where the main .typ file is, so no referencing images on the web. There are Elixir bindings, but for our use-case isn’t wasn’t worth the extra dependency.

The output quality is awesome (it is designed as a Latex successor). Coding up the layout is very similar to composing views with Phoenix function components. Some of the syntax takes a bit of getting used to, but it’s still the least fighting I’ve been through to get nice quality output from a database to a PDF or printer, by a long way, in >30 years of doing this kind of stuff.

Edit: PS - tables allow fine control on layout, styling, row/col-spans etc.

17
Post #9
outlog

outlog

Took a look at what I used last time around, and it was https://weasyprint.org, probably due to the nice templates out of the box.. you render the html, path to the css file, and call it using Rambo (you might need {:rambo, github: "/myobie/rambo", branch: "aarch64-apple"},)..

defmodule RamboPdf do
  def create_pdf(item) do
    css = Path.join([PDFfile.path(), "templates/invoice", "invoice.css"])

    # grab data, and EEx.eval_file with the template file
    html =
      PDF.gen_data(item)
      |> PDF.populate_html("templates/invoice", "invoice.html")

    output_file = Path.join([PDFfile.path(), "output", "#{item.room}.pdf"])
    # https://doc.courtbouillon.org/weasyprint/stable/api_reference.html#command-line-api

    task =
      Task.async(fn ->
        Rambo.run("weasyprint", ["--encoding", "utf8", "-q", "-s", css, "-", "-"],
          in: html,
          log: false,
          timeout: 20_000
        )

        # System.cmd("weasyprint", ["--encoding", "utf8", "-q", "-s", css, "-", "-", html])
      end)

    task_output = Task.await(task, :infinity)

    case task_output do
      {:ok, %Rambo{err: _err, out: output, status: 0}} ->
        File.write(output_file, output, [:binary])
        output

      error ->
        IO.inspect("error")
        IO.inspect(error)
    end
  end
end

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews