Renduva

Renduva documentation

Templates and tags

A template is an ordinary Word document (.docx) with tags where the data goes. This page covers everything Renduva understands: fields, repeating table rows, images, line breaks, and what happens when data is missing. Conditional sections and number formatting come in later versions.

Data

A template is rendered against one JSON object:

{
  "customer": "City of Example",
  "invoice": "INV-2026-0042",
  "items": [
    { "description": "Water service", "quantity": 1, "price": "42.50" }
  ]
}

The data may also be a list of such objects. Each object is one record: the template is filled once per record and the results are joined, in order, into one output file. Joining needs an output that can merge (PDF in v0.1); asking for DOCX output with more than one record is an error. Each record is rendered on its own, so headers, footers, and page numbers restart for every record.

Fields

{{name}} is replaced by the value of name.

  • Names start with a letter or _, followed by letters, digits, or _. They are case-sensitive: {{Customer}} and {{customer}} are different fields.
  • Spaces inside the braces are allowed: {{ customer }} is the same as {{customer}}.
  • Anything else between {{ and }} that is not a valid tag ({{customer name}}, {{price-total}}) is an error, so a mistyped tag never prints silently.
  • No dotted paths ({{customer.name}}) in v0.1. Flatten nested data in the query.

Everything around the tags (fonts, tables, headers, footers, page numbers, a logo pasted into the template) prints exactly as you designed it in Word.

How values print:

JSON value Printed as
string the string, unchanged
number exactly as written in the JSON (42.50 stays 42.50, 1e3 stays 1e3)
true / false true / false
null nothing
object or array error

Renduva does no number or date formatting in v0.1. Format values in SQL (TO_CHAR) before sending them.

Loops

{{#items}} ... {{/items}} repeats its content once for each element of the list items.

  • In v0.1 a loop repeats table rows. Put {{#items}} in the first row to repeat and {{/items}} in the last one (often the same row: open tag in the first cell, close tag in the last). Every row from the opening row to the closing row is repeated together.
  • Loops in ordinary paragraphs (outside a table) are not supported in v0.1 and return an error.
  • Each element must be an object. Inside the loop, {{description}} reads from the current element first, then from the outer data, so {{customer}} still works inside a row.
  • Loops can nest (a row block inside a row block), with the same lookup order working outward.
  • An empty list, a missing list, or null removes the rows. A value that is not a list is an error.

Images

To place an image (a logo, a signature, a product photo), insert any picture in Word as a stand-in, size and position it, then right-click it, choose View Alt Text (or Edit Alt Text), and type the tag as the whole alt text: {{logo}}.

{ "logo": "iVBORw0KGgoAAAANSUhEUgAA..." }
  • The value is the image file in base64: PNG, JPEG or GIF. A data:image/png;base64, prefix and line breaks in the base64 are allowed. From PL/SQL, renduva.image(blob) does the encoding (see the PL/SQL package).
  • The image keeps the stand-in's position, wrapping and border, and is fitted inside its frame without distortion: a wide logo in a square frame keeps the width and gets shorter. Images are never stretched and never larger than the frame you drew.
  • A missing, null or empty value keeps the stand-in picture, so it can serve as a default (a generic logo, or a blank signature line).
  • Pictures work in the body, tables, headers and footers. In a repeating row, each row reads its own value, e.g. a product photo per line.
  • The same image used many times is stored once in the document.

Missing fields

A field with no key in the data prints as nothing, the same as null. Oracle commonly omits null columns from generated JSON (ABSENT ON NULL), so treating a missing key as an error would break ordinary queries.

Escaping

Values are always inserted as plain text, never as document markup. &, <, and > in the data appear as those characters in the output and cannot alter the document's structure.

A line break inside a value (\n or \r\n) becomes a line break in the document, so multi-line addresses print as written.

There is no way to write a literal {{ ... }} in the text of a template in v0.1; it is read as a tag (and is an error if it is not a valid one).

Writing tags in Word

  • Type each tag in one go. Word often splits typed text into several pieces internally (spell check, autocorrect, editing history). Renduva handles that, but a tag must sit inside a single paragraph.
  • A tag takes the formatting of its first character. Format the whole tag the way the value should look.
  • Tags work in the document body, tables, headers, and footers. Footnotes, comments, and text boxes are not covered in v0.1.

Errors

Rendering stops with an error, and no document, when:

  • text in {{ }} is not a valid tag, or a tag is split across paragraphs;
  • {{#name}} has no matching {{/name}}, or {{/name}} has no opening tag;
  • a loop's tags are not inside table rows;
  • a loop's value is not a list, or an element of it is not an object;
  • a field's value is an object or an array;
  • a picture's alt text holds anything besides one {{name}} tag, or its value is not base64 of a PNG, JPEG or GIF.

Errors name the offending tag. They never include data values.

The data may start with a UTF-8 byte-order mark; it is ignored.