Appearance
Repeating Content
The <repeat> directive lets you generate elements from data arrays, iterate over flow groups, or repeat pages until a flow is consumed. It's how Press turns a single template into a multi-page, data-driven document.
Repeating Over Data
The most common use: iterate over an array and render elements for each item.
xml
<repeat data="data.team" item="person">
<frame direction="row" space-after-desired="8pt">
<frame width="fill">
<frame font-style="bold">{{ person.name }}</frame>
<frame font-size="9pt" font-color="#6b7280">{{ person.role }}</frame>
</frame>
<frame>{{ person.email }}</frame>
</frame>
</repeat>Attributes
| Attribute | Required | Description |
|---|---|---|
data | Yes | Path to the array to iterate over |
item | No | Variable name for each element (defaults to item) |
If you omit item, the current element is accessible as item:
xml
<repeat data="data.tags">
<span>{{ item }}</span>
</repeat>Generating Table Rows
A common pattern -- generate table rows from data:
xml
<table>
<tr>
<th>Product</th>
<th text-align="center">Quantity</th>
<th text-align="right">Price</th>
</tr>
<repeat data="data.products" item="product">
<tr>
<td>{{ product.name }}</td>
<td text-align="center">{{ product.qty }}</td>
<td text-align="right">£{{ product.price }}</td>
</tr>
</repeat>
</table>Nested Repeats
Use different item names to nest repeats:
xml
<repeat data="data.departments" item="dept">
<h2>{{ dept.name }}</h2>
<repeat data="dept.members" item="person">
<p>{{ person.name }} - {{ person.title }}</p>
</repeat>
</repeat>Combining Repeat with show-if
Use show-if inside a repeat to conditionally render items:
xml
<repeat data="data.contacts" item="contact">
<frame direction="row" space-after-desired="4pt">
<frame width="fill" font-style="bold">{{ contact.name }}</frame>
<frame show-if="contact.phone">{{ contact.phone }}</frame>
</frame>
</repeat>Repeating Over Flow Groups
When flows are organized into groups, use <repeat group="..."> to iterate over them:
xml
<flows>
<group name="chapters">
<introduction type="markdown">
<data type="json">{ "title": "Introduction" }</data>
Our research focused on three key areas...
</introduction>
<analysis type="markdown">
<data type="json">{ "title": "Analysis" }</data>
The data reveals clear patterns...
</analysis>
</group>
</flows>xml
<document format="A4" page-margin="2cm">
<repeat group="chapters" item="chapter">
<page>
<h1>{{ chapter.data.title }}</h1>
<flow name="chapter" />
</page>
</repeat>
</document>Each group member's <data> is accessible through the item variable's .data property.
Repeating Pages for a Flow
Use <repeat flow="..."> to generate as many pages as needed to consume a flow. This is only usable in the <document> tag:
xml
<document format="A4" page-margin="2cm">
<repeat flow="body">
<page>
<flow name="body" />
</page>
</repeat>
</document>Press generates pages until all content in the body flow has been rendered.
Alternating Page Types
Put multiple pages inside a flow repeat for alternating layouts:
xml
<repeat flow="body">
<odd-page />
<even-page />
</repeat>Generating Pages from Data
Combine <repeat data="..."> at the document level to create one page per data item:
xml
<document format="A4" page-margin="1.5cm">
<repeat data="data.employees" item="employee">
<page>
<h1>{{ employee.name }}</h1>
<frame direction="row">
<frame width="50%">
<p>Department: {{ employee.department }}</p>
<p>Start date: {{ employee.start_date }}</p>
</frame>
<frame width="50%">
<img show-if="employee.photo" src="{{ employee.photo }}" max-height="150pt" />
</frame>
</frame>
</page>
</repeat>
</document>This generates one page per employee -- useful for directories, ID cards, certificates, or property listings.
Repeating with Outline Tracking
When building a table of contents, use <repeat outline="..."> to iterate over collected outline entries:
xml
<repeat outline="sections" item="entry">
<tr>
<td>{{ entry.page-number }}</td>
<td>{{ entry.text-content }}</td>
</tr>
</repeat>Repeating over the outline requires being in a deferred page or a deferred flow. See the Table of Contents guide for full details.