Mead.Node (mead_pdf v0.1.0)

Copy Markdown View Source

An element in the document tree.

Two kinds exist during the spike: :view (a flex container) and :text (a leaf whose content is measured, wrapped, and drawn).

Summary

Types

Barcode symbologies supported by barcode/2.

Normalized barcode spec held in :source for :barcode nodes.

t()

Document props

Functions

Builds a :barcode leaf node — the value is encoded and drawn as crisp vector modules (no rasterization).

Builds an :image leaf node.

Builds a counter span: renders as the total page count (see page_number/1).

Builds a counter span: renders as the current page number.

Builds a :span — a styled run inside a rich text/2 node.

Builds a :table node ("measure globally, split locally").

Builds a body group (semantic only — dissolved into the table's rows).

Builds a table cell (a column-flex container sized by its column track).

Builds a footer group: repeats after each fragment's rows when it fits.

Builds a header group: repeats atop every fragment that shows rows.

Builds a table row (atomic across pages by default: wrap: false).

Builds a :text leaf node.

Builds a :view container node.

Types

barcode_format()

@type barcode_format() ::
  :qr
  | :aztec
  | :data_matrix
  | :pdf417
  | :code128
  | :code39
  | :code93
  | :codabar
  | :ean8
  | :ean13
  | :upc_a
  | :upc_e
  | :itf
  | :telepen

Barcode symbologies supported by barcode/2.

barcode_source()

@type barcode_source() ::
  {String.t(), barcode_format(), String.t() | nil, non_neg_integer() | nil}

Normalized barcode spec held in :source for :barcode nodes.

t()

@type t() :: %Mead.Node{
  asset: non_neg_integer() | nil,
  bookmark: String.t() | nil,
  bookmark_level: pos_integer(),
  break_before: boolean() | :avoid,
  children: [t()],
  columns: [track()] | nil,
  content: String.t() | nil,
  counter: :page | :pages | nil,
  href: String.t() | nil,
  keep_with_next: boolean(),
  kind:
    :view
    | :text
    | :span
    | :image
    | :barcode
    | :table
    | :table_header
    | :table_body
    | :table_footer
    | :table_row
    | :table_cell,
  repeat: boolean(),
  repeat_after: boolean(),
  source: Path.t() | {:binary, binary()} | barcode_source() | nil,
  style: Mead.Style.t(),
  wrap: boolean()
}

track()

@type track() :: number() | {:fr, number()}

Document props:

  • href - external link URI; the node's box becomes a clickable link annotation in the PDF.
  • bookmark / bookmark_level - adds an outline (bookmark) entry pointing at this node; the tree nests by level like HTML headings.

Pagination props:

  • break_before: true - force a page break before this node.
  • break_before: :avoid - avoid a page break directly before this node (CSS break-before: avoid): the break relocates to the latest earlier opportunity — inside the previous sibling, between earlier siblings, or before the whole container. Sugar for keep_with_next: true on the preceding sibling; ignored on a first child (v1: no cross-container chains).
  • keep_with_next: true - keep this node on the same page as (the start of) its next sibling: a break directly after it relocates earlier, as with break_before: :avoid. When no earlier break opportunity exists on the page, the break happens anyway — progress is never sacrificed.
  • wrap: false - atomic: never split across pages; moves whole to the next page when it doesn't fit (unless already at the top of a page).
  • repeat: true - when this node's parent is split across pages, this child is re-emitted at the top of each continuation fragment (table-header semantics).
  • repeat_after: true - re-emitted after the fragment's kept children on every page that shows them, when it fits — rows are never sacrificed for it, and only the presentational clones are omitted: the node itself always renders, flowing onto a continuation page when it can't follow the last child (table-footer semantics).

Table kinds (:table, :table_header, :table_body, :table_footer, :table_row, :table_cell) are desugared to views by Mead.Table before layout; columns holds the table's column track specs.

Functions

barcode(value, attrs \\ [])

@spec barcode(
  String.t(),
  keyword()
) :: t()

Builds a :barcode leaf node — the value is encoded and drawn as crisp vector modules (no rasterization).

Options (all remaining attrs are node/style attrs, as with image/2):

  • :format - the symbology (default :qr); one of barcode_format/0.
  • :ec_level - error-correction level; for QR one of "L", "M", "Q", "H" (atoms accepted).
  • :quiet_zone - quiet-zone width in modules, overriding the symbology's default (QR reserves 4). 0 disables — the drawn modules then touch the node box edge exactly.

Sizing: with no explicit width/height, 2D symbols render at 2pt per module and 1D strips at 1pt per module wide, 40pt tall. With one dimension, 2D symbols keep their square grid (like images keep aspect ratio); 1D width and height are independent. The modules draw in the node's (inherited) text color.

image(source, attrs \\ [])

@spec image(
  Path.t() | {:binary, binary()},
  keyword()
) :: t()

Builds an :image leaf node.

source is a file path or {:binary, data} (PNG/JPEG/GIF/WebP, or an SVG/SVGZ — embedded as vector content, never rasterized; SVG <text> resolves against the document's declared fonts). With no explicit width/height the image renders at its intrinsic size (1px = 0.75pt; for SVG from its width/height or viewBox); with one dimension it scales preserving aspect ratio.

page_count(attrs \\ [])

@spec page_count(keyword()) :: t()

Builds a counter span: renders as the total page count (see page_number/1).

page_number(attrs \\ [])

@spec page_number(keyword()) :: t()

Builds a counter span: renders as the current page number.

Only valid inside text/2 in a page :header/:footer subtree — the value is substituted after pagination. The "0" placeholder content sizes the chrome before substitution.

span(content, attrs \\ [])

@spec span(
  String.t(),
  keyword()
) :: t()

Builds a :span — a styled run inside a rich text/2 node.

Spans inherit unset text properties from their text node and may override font_family/font_weight/italic/font_size/color.

table(children, attrs \\ [])

@spec table(
  [t()],
  keyword()
) :: t()

Builds a :table node ("measure globally, split locally").

Children are table_header/2, table_body/2, table_footer/2 groups and/or bare table_row/2s. :columns freezes the column tracks for every row: a number is a fixed width in points, {:fr, n} a fraction of the remaining width. Rows with more cells than tracks give the extras {:fr, 1}; omitting :columns makes all columns {:fr, 1}.

table_body(rows, attrs \\ [])

@spec table_body(
  [t()],
  keyword()
) :: t()

Builds a body group (semantic only — dissolved into the table's rows).

table_cell(children, attrs \\ [])

@spec table_cell(
  [t()],
  keyword()
) :: t()

Builds a table cell (a column-flex container sized by its column track).

table_footer(rows, attrs \\ [])

@spec table_footer(
  [t()],
  keyword()
) :: t()

Builds a footer group: repeats after each fragment's rows when it fits.

table_header(rows, attrs \\ [])

@spec table_header(
  [t()],
  keyword()
) :: t()

Builds a header group: repeats atop every fragment that shows rows.

table_row(cells, attrs \\ [])

@spec table_row(
  [t()],
  keyword()
) :: t()

Builds a table row (atomic across pages by default: wrap: false).

text(content, attrs \\ [])

@spec text(
  String.t() | [t() | String.t()],
  keyword()
) :: t()

Builds a :text leaf node.

content is a string, or — for rich text — a list of span/2 nodes and plain strings (strings become unstyled spans inheriting the text node's properties).

view(children \\ [], attrs \\ [])

@spec view(
  [t()],
  keyword()
) :: t()

Builds a :view container node.