Prawn-style declarative PDF generation for Elixir.
Pure Elixir, no Chrome or HTML. Build a document spec and emit PDF 1.4 binary.
Image / asset path
When using this library as a dependency, set in your application config:
config :prawn_ex, image_dir: "priv/images"Relative paths passed to image/3 (e.g. "photo.jpg", "logo.png") are then resolved from that directory.
Absolute paths and raw JPEG or PNG binaries are used as-is.
Example
PrawnEx.build("out.pdf", fn doc ->
doc
|> PrawnEx.set_font("Helvetica", 12)
|> PrawnEx.text("Hello, PDF!")
|> PrawnEx.rectangle(100, 400, 200, 50)
|> PrawnEx.stroke()
end)See module docs for PrawnEx.Document, PrawnEx.Units, PrawnEx.Layout (flow, stacks, region, markup), and PrawnEx.Layout.Markup.
Summary
Functions
Adds a new page. The new page becomes current.
Draws a bar chart. data is a list of {label, value} or [label, value].
Options: :at, :width, :height, :bar_color (gray 0–1), :axis, :labels, :label_font_size, :padding.
Builds a PDF by running the function on a new document, then writes to the given path.
Closes the current path back to its starting point.
Fills the current path.
Fills and strokes the current path in one operation — a shape with both a background and a border.
Embeds an image at the given position. path_or_binary is a file path or image binary.
Draws a line from {x1, y1} to {x2, y2}. Call stroke/1 to draw it.
Draws a line chart. data is a list of y-values (x = index) or [{x, y}, ...].
Options: :at, :width, :height, :stroke_color, :axis, :padding.
Draws a line from the current path point to {x, y}. Call stroke/1 after the path is complete.
Adds an external link annotation on the current page. Clicking the rectangle opens the URL.
x, y are bottom-left in pt; width and height define the clickable area.
Draws several lines in one chart box on a shared scale. See
PrawnEx.Chart.multi_line_chart/3 for series shape and options.
Appends a closed polygon path through a list of {x, y} points, to be
painted with fill/1, stroke/1, or fill_stroke/1.
Registers a TrueType font for embedding, under name.
Appends a rounded-rectangle path (Bézier corners). Like
rectangle/5 it only builds the path — follow with fill/1,
stroke/1, or fill_stroke/1.
Sets the current font (e.g. "Helvetica") and size in points.
Sets the stroke (line) width in points for subsequent stroked paths.
Sets the non-stroking (fill and text) color to gray. g in 0..1 (0=black, 1=white).
Sets the non-stroking (fill and text) color to RGB. r, g, b in 0..1.
Sets fill and stroke opacity (0.0 transparent .. 1.0 opaque) for
subsequent drawing. Set it back to 1.0 when done — like colors,
it stays in effect.
Sets the stroking (lines, borders) color to gray. g in 0..1.
Sets the stroking (lines, borders) color to RGB. r, g, b in 0..1.
Strokes the current path (e.g. after rectangle/5 or line/3).
Draws a table at the given position. rows is a list of rows (list of cell values).
First row can be styled as header with header: true (default).
Appends text at the current position (single line).
Draws text at the given position {x, y} (PDF coordinates: origin bottom-left).
Draws text wrapped to fit within a width. First line baseline at {x, y}; subsequent lines below (smaller y).
Converts the document to PDF binary.
Writes the document to a file at path.
Functions
@spec add_page(PrawnEx.Document.t()) :: PrawnEx.Document.t()
Adds a new page. The new page becomes current.
@spec bar_chart(PrawnEx.Document.t(), [{String.t(), number()} | [term()]], keyword()) :: PrawnEx.Document.t()
Draws a bar chart. data is a list of {label, value} or [label, value].
Options: :at, :width, :height, :bar_color (gray 0–1), :axis, :labels, :label_font_size, :padding.
@spec build(String.t(), (PrawnEx.Document.t() -> PrawnEx.Document.t())) :: :ok | {:error, term()}
@spec build(String.t(), keyword(), (PrawnEx.Document.t() -> PrawnEx.Document.t())) :: :ok | {:error, term()}
Builds a PDF by running the function on a new document, then writes to the given path.
Options (when passing a keyword list as second argument):
:header-fn(doc, page_number) -> doc— add ops at top of each page (e.g. title, line):footer-fn(doc, page_number) -> doc— add ops at bottom of each page (e.g. "Page N")
Returns :ok or {:error, reason}.
Closes the current path back to its starting point.
Appends a cubic Bézier curve from the current point to {x, y} with
control points c1 and c2. Draw with stroke/1 or fill/1.
@spec fill(PrawnEx.Document.t()) :: PrawnEx.Document.t()
Fills the current path.
Fills and strokes the current path in one operation — a shape with both a background and a border.
@spec image(PrawnEx.Document.t(), String.t() | binary(), keyword()) :: PrawnEx.Document.t() | {:error, term()}
Embeds an image at the given position. path_or_binary is a file path or image binary.
Supported formats: JPEG (embedded as DCT) and PNG (8-bit RGB or RGBA, non-interlaced;
RGBA is composited on white). Other formats return {:error, :unsupported_image_format}.
If path_or_binary is a relative path, it is resolved against the configured image directory
(see "Image / asset path" in the module docs). Set config :prawn_ex, image_dir: "priv/images"
in your app to define where to look for image files.
Options: :at (required) {x, y} bottom-left of image, :width and :height in pt (default: intrinsic size).
@spec line(PrawnEx.Document.t(), {number(), number()}, {number(), number()}) :: PrawnEx.Document.t()
Draws a line from {x1, y1} to {x2, y2}. Call stroke/1 to draw it.
@spec line_chart(PrawnEx.Document.t(), [number()] | [{number(), number()}], keyword()) :: PrawnEx.Document.t()
Draws a line chart. data is a list of y-values (x = index) or [{x, y}, ...].
Options: :at, :width, :height, :stroke_color, :axis, :padding.
@spec line_to( PrawnEx.Document.t(), {number(), number()} ) :: PrawnEx.Document.t()
Draws a line from the current path point to {x, y}. Call stroke/1 after the path is complete.
@spec link(PrawnEx.Document.t(), number(), number(), number(), number(), String.t()) :: PrawnEx.Document.t()
Adds an external link annotation on the current page. Clicking the rectangle opens the URL.
x, y are bottom-left in pt; width and height define the clickable area.
@spec move_to( PrawnEx.Document.t(), {number(), number()} ) :: PrawnEx.Document.t()
Moves the path to {x, y} without drawing. Use with line_to/2 and then stroke/1 for polylines.
@spec multi_line_chart(PrawnEx.Document.t(), [map() | keyword()], keyword()) :: PrawnEx.Document.t()
Draws several lines in one chart box on a shared scale. See
PrawnEx.Chart.multi_line_chart/3 for series shape and options.
Appends a closed polygon path through a list of {x, y} points, to be
painted with fill/1, stroke/1, or fill_stroke/1.
# a small upward triangle
PrawnEx.polygon(doc, [{10, 10}, {16, 20}, {4, 20}]) |> PrawnEx.fill()
@spec rectangle(PrawnEx.Document.t(), number(), number(), number(), number()) :: PrawnEx.Document.t()
Adds a rectangle at (x, y) with width and height. Call stroke/1 or fill/1 to draw it.
Registers a TrueType font for embedding, under name.
source is a path to a .ttf file or the font binary itself. After
registering, pass name to set_font/3 like any built-in font — the
writer embeds the font program (flate-compressed) and real glyph
widths, so text renders in the actual typeface instead of a base-14
stand-in. Text keeps flowing through the same WinAnsi transliteration.
Raises ArgumentError when the data is not a usable TrueType font
(CFF-flavoured OpenType included — that needs /FontFile3).
doc
|> PrawnEx.register_font("HankenGrotesk", "priv/fonts/HankenGrotesk-Regular.ttf")
|> PrawnEx.set_font("HankenGrotesk", 12)
Appends a rounded-rectangle path (Bézier corners). Like
rectangle/5 it only builds the path — follow with fill/1,
stroke/1, or fill_stroke/1.
@spec set_font(PrawnEx.Document.t(), String.t(), number()) :: PrawnEx.Document.t()
Sets the current font (e.g. "Helvetica") and size in points.
@spec set_line_width(PrawnEx.Document.t(), number()) :: PrawnEx.Document.t()
Sets the stroke (line) width in points for subsequent stroked paths.
@spec set_non_stroking_gray(PrawnEx.Document.t(), number()) :: PrawnEx.Document.t()
Sets the non-stroking (fill and text) color to gray. g in 0..1 (0=black, 1=white).
@spec set_non_stroking_rgb(PrawnEx.Document.t(), number(), number(), number()) :: PrawnEx.Document.t()
Sets the non-stroking (fill and text) color to RGB. r, g, b in 0..1.
Sets fill and stroke opacity (0.0 transparent .. 1.0 opaque) for
subsequent drawing. Set it back to 1.0 when done — like colors,
it stays in effect.
@spec set_stroking_gray(PrawnEx.Document.t(), number()) :: PrawnEx.Document.t()
Sets the stroking (lines, borders) color to gray. g in 0..1.
@spec set_stroking_rgb(PrawnEx.Document.t(), number(), number(), number()) :: PrawnEx.Document.t()
Sets the stroking (lines, borders) color to RGB. r, g, b in 0..1.
@spec stroke(PrawnEx.Document.t()) :: PrawnEx.Document.t()
Strokes the current path (e.g. after rectangle/5 or line/3).
@spec table(PrawnEx.Document.t(), [list()], keyword()) :: PrawnEx.Document.t()
Draws a table at the given position. rows is a list of rows (list of cell values).
First row can be styled as header with header: true (default).
Options
:at-{x, y}top-left of table (default{50, 750}):column_widths- list of pt widths or:auto:row_height,:cell_padding,:header,:border,:font_size,:header_font_size
Example
PrawnEx.table(doc, [["Name", "Score"], ["Alice", "95"], ["Bob", "87"]],
at: {50, 650}, column_widths: [200, 80])
@spec text(PrawnEx.Document.t(), String.t()) :: PrawnEx.Document.t()
Appends text at the current position (single line).
@spec text_at(PrawnEx.Document.t(), {number(), number()}, String.t()) :: PrawnEx.Document.t()
Draws text at the given position {x, y} (PDF coordinates: origin bottom-left).
@spec text_box(PrawnEx.Document.t(), String.t(), keyword()) :: PrawnEx.Document.t()
Draws text wrapped to fit within a width. First line baseline at {x, y}; subsequent lines below (smaller y).
Options:
:at-{x, y}(required) — position of first line baseline:width- max width in pt (required):font_name- default"Helvetica":font_size- default12:line_height- default1.2 * font_size
@spec to_binary(PrawnEx.Document.t()) :: binary()
Converts the document to PDF binary.
@spec write_to_file(PrawnEx.Document.t(), String.t()) :: :ok | {:error, term()}
Writes the document to a file at path.