Rendro.Document (Rendro v0.3.0)

Copy Markdown View Source

Top-level document: pages, content (flow), metadata, and rendering options.

Pipeline Builder API

Documents can be composed dynamically using a pipeable builder API, mirroring the ergonomics of Plug.Conn or Ecto.Changeset:

Rendro.Document.new()
|> Rendro.Document.put_metadata(%Rendro.Metadata{title: "Invoice"})
|> Rendro.Document.add_template(page_template)
|> Rendro.Document.set_template(:invoice)
|> Rendro.Document.add_section(section)
|> Rendro.Document.put_options(%{deterministic: true})

This supports dynamic, conditional assembly during a request cycle while keeping each transformation a pure function over the %Rendro.Document{} struct.

Diagnostics

diagnostics is the developer-facing layout-debug surface for non-fatal pagination and measurement events. Entries stay map-based: stable common keys such as :level and :type are always present, event-specific optional keys such as :message, :page_index, :reason, and :keep_rule may appear, and future additive keys are allowed.

Typography & Honest I18n

Documents own the logical font registry used by authored content. The default registry keeps a narrow Helvetica-compatible path available out of the box while letting callers register additional logical names as pure data.

Rendro embraces an "honest I18n" model: text crossing into unsupported scripts (e.g., RTL, complex shaping) or unmapped glyphs will not silently degrade into squares or overlapping text. Instead, the rendering pipeline will explicitly trap the boundary and return an actionable Rendro.Error. Callers can configure fallback font chains when registering fonts to automatically substitute missing glyphs.

Summary

Types

Developer-facing layout-debug structured maps emitted during render.

t()

Functions

Appends a section to the document's sections list.

Appends a page template to the document's page_templates list.

Creates a new empty %Rendro.Document{} struct.

Creates a new %Rendro.Document{} struct with the given keyword options.

Sets the document default logical font.

Updates the document metadata.

Merges the given options map into the document's existing options.

Registers a document-level embedded file on the document's owned registry.

Registers a logical name against an explicit embedded font source.

Registers a four-variant embedded font family on the document.

Registers a logical font name on the document's owned font registry.

Registers an image asset on the document's owned asset registry.

Sets the active page template by name.

Types

diagnostic()

@type diagnostic() :: %{
  :level => atom(),
  :type => atom(),
  optional(:message) => String.t(),
  optional(:page_index) => non_neg_integer(),
  optional(:reason) => term(),
  optional(:keep_rule) => atom(),
  optional(atom()) => term()
}

Developer-facing layout-debug structured maps emitted during render.

Stable common keys such as :level and :type are present on every entry. Event-specific optional keys such as :message, :page_index, :reason, and :keep_rule may appear depending on the pagination event. Future additive keys are allowed so callers should match only on the fields they need.

t()

@type t() :: %Rendro.Document{
  asset_registry: Rendro.AssetRegistry.t(),
  content: [Rendro.Block.t()],
  default_font: Rendro.FontRegistry.logical_name(),
  diagnostics: [map()],
  embedded_file_registry: Rendro.EmbeddedFileRegistry.t(),
  font_registry: Rendro.FontRegistry.t(),
  footer: [Rendro.Block.t()],
  header: [Rendro.Block.t()],
  metadata: Rendro.Metadata.t(),
  options: %{optional(atom()) => term()},
  page_template: atom() | String.t() | nil,
  page_templates: [Rendro.PageTemplate.t()],
  pages: [Rendro.Page.t()],
  sections: [Rendro.Section.t()]
}

Functions

add_section(doc, section)

@spec add_section(t(), Rendro.Section.t()) :: t()

Appends a section to the document's sections list.

Examples

iex> section = %Rendro.Section{name: :body, region: :body}
iex> Rendro.Document.new() |> Rendro.Document.add_section(section)
%Rendro.Document{sections: [%Rendro.Section{name: :body, region: :body}]}

add_template(doc, template)

@spec add_template(t(), Rendro.PageTemplate.t()) :: t()

Appends a page template to the document's page_templates list.

Examples

iex> template = %Rendro.PageTemplate{name: :invoice}
iex> Rendro.Document.new() |> Rendro.Document.add_template(template)
%Rendro.Document{page_templates: [%Rendro.PageTemplate{name: :invoice}]}

new()

@spec new() :: t()

Creates a new empty %Rendro.Document{} struct.

Examples

iex> Rendro.Document.new()
%Rendro.Document{}

new(opts)

@spec new(keyword()) :: t()

Creates a new %Rendro.Document{} struct with the given keyword options.

Examples

iex> Rendro.Document.new(metadata: %Rendro.Metadata{title: "Invoice"})
%Rendro.Document{metadata: %Rendro.Metadata{title: "Invoice"}}

put_default_font(doc, logical_name)

@spec put_default_font(t(), Rendro.FontRegistry.logical_name()) :: t()

Sets the document default logical font.

The logical name must already be registered on the document.

put_metadata(doc, metadata)

@spec put_metadata(t(), Rendro.Metadata.t()) :: t()

Updates the document metadata.

Examples

iex> doc = Rendro.Document.new()
iex> Rendro.Document.put_metadata(doc, %Rendro.Metadata{title: "Invoice"})
%Rendro.Document{metadata: %Rendro.Metadata{title: "Invoice"}}

put_options(doc, options)

@spec put_options(t(), %{optional(atom()) => term()}) :: t()

Merges the given options map into the document's existing options.

Examples

iex> Rendro.Document.new()
iex> |> Rendro.Document.put_options(%{deterministic: true})
iex> |> Rendro.Document.put_options(%{compress: false})
%Rendro.Document{options: %{deterministic: true, compress: false}}

register_embedded_file(doc, logical_name, source, metadata)

@spec register_embedded_file(
  t(),
  atom(),
  {:path, Path.t()} | {:binary, binary()},
  keyword()
) :: t()

Registers a document-level embedded file on the document's owned registry.

register_embedded_font(doc, logical_name, source)

@spec register_embedded_font(
  t(),
  Rendro.FontRegistry.logical_name(),
  {:path, Path.t()} | {:binary, binary()}
) :: t()

Registers a logical name against an explicit embedded font source.

register_embedded_font_family(doc, family_name, variants)

@spec register_embedded_font_family(
  t(),
  Rendro.FontRegistry.logical_name(),
  %{
    required(Rendro.FontRegistry.embedded_variant()) =>
      {:path, Path.t()} | {:binary, binary()}
  }
) :: t()

Registers a four-variant embedded font family on the document.

register_font(doc, logical_name, opts)

@spec register_font(t(), Rendro.FontRegistry.logical_name(), keyword()) :: t()

Registers a logical font name on the document's owned font registry.

Examples

iex> Rendro.Document.new()
...> |> Rendro.Document.register_font(:body, built_in: :helvetica)
%Rendro.Document{
  font_registry: %Rendro.FontRegistry{
    fonts: %{default: %{source: :built_in, family: :helvetica}, body: %{source: :built_in, family: :helvetica}}
  }
}

register_image(doc, logical_name, source)

@spec register_image(
  t(),
  atom(),
  {:path, Path.t()} | {:binary, binary()}
) :: t()

Registers an image asset on the document's owned asset registry.

set_template(doc, name)

@spec set_template(t(), atom() | String.t()) :: t()

Sets the active page template by name.

Examples

iex> Rendro.Document.new() |> Rendro.Document.set_template(:invoice)
%Rendro.Document{page_template: :invoice}