Render options
Everything after template: and data: in a Soli::PDF.render call is an option. Each one maps to a render_pdf command-line flag. Any other key raises ArgumentError.
Soli::PDF.render(
template: template,
data: data,
title: 'Statement ST-2025-0947',
author: 'Northwind Trading Co.',
password: 'demo',
attachments: ['exports/statement.csv'],
images: false
)
#Reference
| Option | Type | Flag | Effect |
|---|---|---|---|
title: | String | --title | Document title in the PDF metadata, shown by viewers in the window title. Also used in the Factur-X metadata. |
author: | String | --author | Document author in the PDF metadata. |
subject: | String | --subject | Document subject in the PDF metadata. |
password: | String | --password | Encrypts the PDF with AES-128. This password is required to open it. |
owner_password: | String | --owner-password | The owner password, which lifts restrictions. It defaults to password. |
stationery: | String (path) | --stationery | A letterhead PDF drawn beneath every page. |
attachments: | Array of paths | --attach (repeated) | Files embedded in the PDF's attachments panel. |
fonts: | Array of directories | --font-dir (repeated) | Extra font directories, loaded along with the bundled fonts. |
images: | false | --no-images | Never fetches http(s) images. See Images. |
profile: | String | --profile | The Factur-X profile, used with xml: or invoice:. See Factur-X. |
Values are converted with to_s, so a Pathname works wherever a path is expected. An option set to nil is left out.
Note Relative paths (
stationery:,attachments:,fonts:) are resolved against the current working directory of your Ruby process. That is the app root under Rails, but not always in a job runner or cron. Pass absolute paths, for exampleRails.root.join(...), to be safe.
#Metadata
title:, author: and subject: fill the PDF's document information. Viewers show the title in the tab or window bar instead of the file name, and search tools index it. Always set title:: it costs nothing.
#Password protection
pdf = Soli::PDF.render(template: template, data: data,
password: customer.birth_date.strftime('%d%m%Y'))
The PDF is encrypted with AES-128, and opening it requires the password. owner_password: sets a second password that grants full rights. When you leave it out, it is the same as password:.
The account statement example is rendered with password: 'demo'. Download it to try.
Warning Encryption is incompatible with Factur-X. PDF/A, which Factur-X builds on, forbids encryption, so combining
password:withxml:orinvoice:makes the render fail with aRenderError.
#Letterhead stationery
Soli::PDF.render(template: template, data: data,
stationery: Rails.root.join('app/pdf/letterhead.pdf'))
Your template's content is drawn on top of an existing PDF. Page 1 of the output uses the letterhead's first page. Later pages use its second page when it has one, and the first page otherwise. That lets you have a full letterhead on page 1 and a lighter continuation sheet after it. The letterhead is scaled to the output page size.
This is the easiest way to reuse a letterhead a designer made in another tool. Leave room for it with the template's margins and header_height options. A missing file makes the render fail.
#Attachments
Soli::PDF.render(template: template, data: data,
attachments: ['tmp/timesheet.csv', 'tmp/terms.pdf'])
The files are embedded in the PDF and appear in the viewer's attachments panel. Each attachment is named after its file's base name, and its MIME type is guessed from the extension. Attachments work together with Factur-X: your files sit next to the embedded factur-x.xml.
#Fonts
The renderer ships with Titillium Web (regular, bold, italic, bold italic) and JetBrains Mono (regular, bold, italic). The gem passes the bundled font directory automatically. Use fonts: to add more:
Soli::PDF.render(template: template, data: data,
fonts: [Rails.root.join('app/pdf/fonts')])
A directory holds TrueType or OpenType files. The template's fonts key names the main text family, for example "fonts": ["titillium"]. Every other font loaded from the directories becomes a fallback for the characters the main one lacks. Adding a directory with a CJK font such as Noto Sans JP is enough to print Japanese names. A character that no loaded font covers is dropped and reported in Soli::PDF.last_warnings. See Text & paragraphs.
#Images
Warning With
render_pdf2.9.0, the binary the gem downloads today, onlydata:URIs load:http(s)URLs andfile://paths are skipped withno image-source policy installed. The next release loads local files under your process's working directory andhttp(s)images from public addresses, and still refuses the rest. See Layout & drawing for the policy. The render never fails because of an image.
images: false passes --no-images, which tells the renderer never to fetch http(s) images: renders stay offline and reproducible. Local files and data: URIs still load.
A data: URI works for SVG and for raster images (PNG, JPEG, WebP, GIF). Build it in Ruby and put it in the template, because an image's value is not interpolated: ${company.logo} would be read literally.
require 'base64'
LOGO = "data:image/svg+xml;base64,#{Base64.strict_encode64(File.read('app/pdf/logo.svg'))}"
template = JSON.parse(File.read('app/pdf/invoice.template.json'))
template['content'].unshift({ 'type' => 'image', 'value' => LOGO, 'width' => 120, 'alt' => 'Logo' })
Soli::PDF.render(template: template, data: data)
#Options that live in the template
Some settings belong to the document, not to the call, so they go in the template's options object: page size, orientation, margins, header height, background, watermark, and accessible (tagged) output. See Template structure.