soli-pdf

A Ruby gem · MIT

JSON in.
PDF out.

soli-pdf turns a JSON layout template and your data into a finished PDF — invoices, quotes, statements, reports, Factur-X e-invoices. No headless browser, no HTML-to-PDF guesswork, no drawing DSL to learn: one method call.

Gemfile ruby
gem 'soli-pdf', git: 'https://github.com/solisoft/soli_lang',
               glob: 'gem/soli-pdf/*.gemspec'

How you use it

A template, your data, one call.

The template describes the layout once. The data changes on every render. Both are plain JSON, so templates live in your repository, diff cleanly and can be generated or edited by any tool.

1 Describe the layout

invoice.template.json json
{
  "fonts": ["titillium"],
  "content": [
    { "type": "paragraph",
      "value": "Invoice ${invoice.number}",
      "options": { "fontSize": 24,
                   "fontWeight": "bold" } },
    { "type": "table", "data": "items",
      "rows": [[
        { "text": "${name}" },
        { "text": "${amount}",
          "alignment": "right" }
      ]] }
  ]
}

2 Bring the data

app/models/invoice.rb ruby
def to_pdf_data
  {
    'invoice' => { 'number' => number },
    'items' => lines.map do |line|
      { 'name'   => line.label,
        'amount' => format('%.2f €', line.total) }
    end
  }
end

3 Render

app/controllers/invoices_controller.rb ruby
require 'soli/pdf'

pdf = Soli::PDF.render(
  template: TEMPLATE,
  data: invoice.to_pdf_data,
  title: "Invoice #{invoice.number}"
)

send_data pdf, type: 'application/pdf',
               filename: 'invoice.pdf'

Rendered live

Real documents, with their source.

Every example comes with its template, its data and the Ruby call. Open one, read how it is built, download the PDF.

All examples

Under the hood

A thin gem over a fast native renderer.

The gem is under 300 lines of Ruby with no runtime dependencies. It serialises your template and data, pipes them to render_pdf — a self-contained binary written in Rust — and reads the PDF back from its standard output.

  • On first use the gem downloads the binary for your platform from the GitHub release, verifies its SHA-256 and caches it under ~/.cache/soli-pdf/.
  • Linux and macOS on x86-64 and ARM64, Windows on x86-64. Point SOLI_PDF_BIN at your own build to skip the download.
  • No browser to boot and no server to run: each render starts the binary, writes the PDF and exits. Fonts ship with it.
How the binary is found and verified →

Ruby

Hash → JSON

→

render_pdf

stdin · stdout

→

%PDF

binary String

irb ruby
pdf = Soli::PDF.render(template: tpl, data: data)
pdf.encoding            # => #<Encoding:BINARY>
pdf[0, 8]               # => "%PDF-1.3"
Soli::PDF.last_warnings # => []

Try a template before you install anything.

The playground renders any template and data you paste, shows every page, and gives you the Ruby call to reproduce it.