Folio (Folio v0.2.3)

Copy Markdown View Source

Print-quality PDF from Markdown + Elixir, powered by Typst.

use Folio

content = ~MD""
# Report

Some **bold** content with $x^2$ math.
""

{:ok, pdf} = Folio.to_pdf(content)

Styles

{:ok, pdf} = Folio.to_pdf("Hello", styles: [
  Folio.Styles.page_size(width: 595, height: 842),
  Folio.Styles.font_family(["Helvetica"]),
])

Document pipeline

doc =
  Folio.Document.new()
  |> Folio.Document.attach_file("logo.png", File.read!("logo.png"))
  |> Folio.Document.add_style(Folio.Styles.page_numbering("1"))
  |> Folio.Document.add_content("# Hello\n\nWorld")

{:ok, pdf} = Folio.to_pdf(doc)

File management

For one-off files, use register_file/2. For session-scoped isolation, use Folio.Document.attach_file/3 — files live only within that document.

Summary

Functions

Parse markdown into content nodes.

Parse markdown into content nodes, raising on error.

Register a file globally for use in documents (images, bibliography, etc).

Compile to PDF bytes.

Compile to PNG images (one per page).

Compile to SVG strings (one per page).

Unregister a previously registered global file, freeing its memory.

Types

compile_result(result)

@type compile_result(result) :: {:ok, result} | {:error, Folio.CompileError.t()}

source()

@type source() :: String.t() | [Folio.Content.t()] | Folio.Document.t()

Functions

__using__(opts)

(macro)

Imports Folio.DSL and Folio.Sigil.

parse_markdown(markdown)

@spec parse_markdown(String.t()) ::
  {:ok, [Folio.Content.t()]} | {:error, Folio.ParseError.t()}

Parse markdown into content nodes.

{:ok, nodes} = Folio.parse_markdown("# Hello\n\nWorld")

Returns {:error, Folio.ParseError.t()} on failure.

parse_markdown!(markdown)

@spec parse_markdown!(String.t()) :: [Folio.Content.t()]

Parse markdown into content nodes, raising on error.

nodes = Folio.parse_markdown!("# Hello\n\nWorld")

Raises Folio.ParseError on failure.

register_file(path, data)

@spec register_file(String.t(), binary()) :: :ok

Register a file globally for use in documents (images, bibliography, etc).

Files registered here are shared across all compile calls for the lifetime of the BEAM VM. For session-scoped isolation, prefer Folio.Document.attach_file/3 instead.

to_pdf(source, opts \\ [])

@spec to_pdf(
  source(),
  keyword()
) :: compile_result(binary())

Compile to PDF bytes.

Accepts markdown strings, content node lists, or Folio.Document structs.

{:ok, pdf} = Folio.to_pdf("# Hello")
{:ok, pdf} = Folio.to_pdf(doc)

to_png(source, opts \\ [])

@spec to_png(
  source(),
  keyword()
) :: compile_result([binary()])

Compile to PNG images (one per page).

Each page is rendered and encoded independently so peak memory is proportional to the largest page, not the total page count.

{:ok, [page1_png, page2_png]} = Folio.to_png("# Hello")
{:ok, pngs} = Folio.to_png("# Hello", dpi: 3.0)

Options:

  • :dpi — render scale factor (default: 2.0). 1.0 = 72 DPI, 2.0 = 144 DPI, 3.0 = 216 DPI.

to_svg(source, opts \\ [])

@spec to_svg(
  source(),
  keyword()
) :: compile_result([String.t()])

Compile to SVG strings (one per page).

{:ok, [page1_svg, page2_svg]} = Folio.to_svg("# Hello")

unregister_file(path)

@spec unregister_file(String.t()) :: :ok

Unregister a previously registered global file, freeing its memory.

Folio.unregister_file("chart.png")