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
nullremoves 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,
nullor 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.