u/yo_waka

▲ 91 r/rails

Still on wicked_pdf? I wrote a :pdf renderer that needs neither wkhtmltopdf nor headless Chrome

I'm the author. If you have a Rails app still on wicked_pdf, you've probably had the same conversation I did after wkhtmltopdf was archived in 2023: keep shipping an unmaintained binary, or move to Grover and take on a Chrome process.

I wrote a third option. sghtmltopdf is a rendering engine in Rust with no browser inside it — the HTML and CSS parsers come from Servo's crates, and the layout and pagination are written for this project. The gem registers a :pdf renderer in the spirit of wicked_pdf, so an existing controller often needs no changes:

render pdf: "invoice",
  template: "invoices/show",
  layout: "pdf",
  page_size: "A4",
  margin_top: "20mm"

show_as_html: true works too, so you can still open the thing in a browser and poke at it with devtools. The converter keys are flat CLI flag names, so wicked_pdf's nested margin: {top: 10} becomes margin_top: "10mm" — the docs map every key one by one.

A few things that matter inside a Rails process specifically. It runs in-process via a native extension, so no subprocess and no temp files, and it releases the GVL while rendering so other Puma threads keep working. /assets/... URLs resolve as local files, with helpers that inline assets in development. And with ActionController::Live you can stream pages as their layout finalizes, which also makes Rack::Timeout effective at chunk boundaries.

If you'd rather not spend app CPU on rendering, or the gem can't run where your app runs, set server_url and the same calls get delegated to a separate server process.

JavaScript execution isn't in yet and CSS coverage isn't complete — both are things I want to grow, and JS is likely to come via an embedded engine rather than a browser. Pixel parity with Chrome isn't a goal, though. Right now it handles invoices, receipts and reports well; for arbitrary pages it isn't the tool.

Early 0.1 release, MIT, precompiled gem.

Migration notes from wicked_pdf: https://waka.github.io/sghtmltopdf/migration/wicked-pdf.html
Repo: https://github.com/waka/sghtmltopdf

Sample output:

https://preview.redd.it/nnc1nb326sih1.png?width=589&format=png&auto=webp&s=8f5e4a56fea161e7b1e069ef77c9f1261007aa62

reddit.com
u/yo_waka — 9 days ago
▲ 30 r/ruby

I missed wkhtmltopdf and wicked_pdf, so I wrote a new HTML-to-PDF engine with a Ruby gem

I'm the author. wkhtmltopdf was archived in 2023, and since then the practical options have been an unmaintained binary or spawning headless Chrome. Neither felt right for the kind of documents I actually generate — invoices and reports that flow top to bottom — so I wrote a new engine.

sghtmltopdf is written in Rust and does not embed Chromium, WebKit or Gecko. CSS Fragmentation (break-before, break-inside, orphans, widows) and atpage are implemented directly, so page breaks are a first-class concern rather than something you approximate with print stylesheets and hope for.

On the Ruby side it's a native extension, so there's no subprocess and no temp files. It releases the GVL while rendering, so other Puma threads keep serving, and pages are streamed out as soon as their layout is final rather than being buffered until the end.

gem "sghtmltopdf"

pdf = Sghtmltopdf.render("<h1>Invoice</h1>", page_size: "A4")

There's also a CLI and an HTTP server sharing the same engine, and a Docker image with Japanese fonts bundled so output doesn't depend on host fonts.

What it deliberately doesn't do: execute JavaScript, or match a browser pixel for pixel. Full CSS coverage isn't a goal either. If you're rendering arbitrary web pages, headless Chrome is still the right tool.

This is an early 0.1 release and I'd like to hear where it breaks on real documents.

https://github.com/waka/sghtmltopdf

Docs: https://waka.github.io/sghtmltopdf/en/

u/yo_waka — 9 days ago