> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pictify.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Expressions

> Dynamic logic with the template expression engine

# Expressions

Pictify templates come in two engines, and each has its own syntax for dynamic logic:

| Engine | Syntax style | Example |
| - | - | - |
| `html` (Handlebars) | Handlebars blocks + positional helpers | `{{#if isPremium}}...{{/if}}`, `{{currency price 'USD'}}` |
| `fabric` (canvas) | Expression engine — function calls, operators, ternaries | `{{currency(price, 'USD')}}`, `{{isPremium ? 'Gold' : 'Silver'}}` |

Both engines share the **same function library** (the tables below) — only the call style differs. Using expression-style `currency(price, 'USD')` in a Handlebars HTML template (or vice versa) will fail validation.

## Handlebars syntax (HTML templates)

HTML templates (`engine: "html"`) use standard [Handlebars](https://handlebarsjs.com): `{{variable}}` interpolation, block helpers, and positional helper calls. Templates are compile-validated on save — unclosed blocks or unknown helpers fail with HTTP 422.

### Variables and escaping

```handlebars theme={null}
{{title}}
{{user.name}}
```

`{{variable}}` HTML-escapes its output. Raw HTML output with `{{{variable}}}` additionally requires `allowRawHtml: true` on that variable's definition — an XSS guard for user-supplied data.

### Conditionals

```handlebars theme={null}
{{#if isPremium}}
  <span class="badge">Premium</span>
{{else if isTrial}}
  <span class="badge">Trial</span>
{{else}}
  <span class="badge">Free</span>
{{/if}}

{{#unless emailVerified}}<p>Please verify your email.</p>{{/unless}}
```

There is no `==` operator and no custom helper registration (helpers are safelisted). For comparisons, pass a precomputed boolean in your render variables — or use the boolean helpers in a subexpression:

```handlebars theme={null}
{{#if (contains roles 'admin')}}Admin panel{{/if}}
{{#if (isEmpty items)}}Nothing here yet.{{/if}}
```

`contains`, `isEmpty`, `isNotEmpty`, `isDefined`, `startsWith`, `endsWith`, and the other boolean functions all compose this way.

### Loops

```handlebars theme={null}
{{#each items}}
  <li>{{@index}}. {{this.name}} — {{currency this.price 'USD'}}</li>
{{else}}
  <li>No items.</li>
{{/each}}
```

`@index`, `@first`, `@last`, and `@key` (for objects) are available inside the block; `../` reaches the parent context. Each render carries a 5,000-iteration cap across all `#each` blocks — runaway loops fail loudly instead of hanging.

### Calling functions from Handlebars

Every function in the library below is available as a Handlebars helper using **positional arguments** (no parentheses or commas):

```handlebars theme={null}
{{titleCase title}}
{{currency price 'USD'}}
{{date publishedAt 'MMM D, YYYY'}}
{{truncate description 100 '...'}}
```

Partials (`{{> name}}`) are not supported — reuse happens at the template level.

## Expression syntax (canvas templates)

Canvas templates (`engine: "fabric"`) use the expression engine: function calls, arithmetic and comparison operators, and ternaries inside `{{expression}}`. The examples in the rest of this page use this style.

### Simple Variables

```
{{title}}
{{user.name}}
{{items[0].price}}
```

### Property Access

Access nested properties with dot notation:

```
{{user.profile.avatar}}
{{order.items[0].name}}
```

### Arithmetic

```
{{price * quantity}}
{{subtotal + tax}}
{{total / 100}}
{{count % 2}}
```

### Comparisons

```
{{price > 100}}
{{status == 'active'}}
{{count >= 10}}
{{name != 'Guest'}}
```

### Logical Operators

```
{{isAdmin && isPremium}}
{{hasDiscount || isFirstOrder}}
{{!isExpired}}
```

### Ternary Operator

```
{{isPremium ? 'Premium Member' : 'Free User'}}
{{count > 0 ? count : 'None'}}
```

## Built-in Functions

The function library is shared by both engines. Examples below use expression style (canvas engine); in Handlebars HTML templates call the same functions positionally — `{{currency price 'USD'}}` instead of `{{currency(price, 'USD')}}`.

### String Functions

| Function | Description | Example |
| - | - | - |
| `uppercase(str)` | Convert to uppercase | `{{uppercase(name)}}` |
| `lowercase(str)` | Convert to lowercase | `{{lowercase(email)}}` |
| `capitalize(str)` | Capitalize first letter | `{{capitalize(title)}}` |
| `titleCase(str)` | Capitalize each word | `{{titleCase(name)}}` |
| `trim(str)` | Remove whitespace | `{{trim(input)}}` |
| `truncate(str, len, suffix)` | Truncate with suffix | `{{truncate(desc, 100, '...')}}` |
| `replace(str, search, replace)` | Replace all occurrences | `{{replace(text, '-', ' ')}}` |
| `split(str, delimiter)` | Split into array | `{{split(tags, ',')}}` |
| `padStart(str, len, char)` | Pad from start | `{{padStart(id, 5, '0')}}` |
| `padEnd(str, len, char)` | Pad from end | `{{padEnd(code, 10, '-')}}` |

### Number Functions

| Function | Description | Example |
| - | - | - |
| `round(num, decimals)` | Round to decimals | `{{round(price, 2)}}` |
| `floor(num)` | Round down | `{{floor(rating)}}` |
| `ceil(num)` | Round up | `{{ceil(shipping)}}` |
| `abs(num)` | Absolute value | `{{abs(difference)}}` |
| `min(a, b, ...)` | Minimum value | `{{min(price, maxPrice)}}` |
| `max(a, b, ...)` | Maximum value | `{{max(0, quantity)}}` |
| `sum(array)` | Sum array values | `{{sum(prices)}}` |
| `average(array)` | Average of array | `{{average(ratings)}}` |

### Formatting Functions

| Function | Description | Example |
| - | - | - |
| `currency(num, currency, locale)` | Format as currency | `{{currency(price, 'USD')}}` |
| `number(num, locale)` | Format number | `{{number(count, 'en-US')}}` |
| `percent(num, decimals)` | Format as percent | `{{percent(rate, 1)}}` |
| `date(str, format)` | Format date | `{{date(createdAt, 'MMM D, YYYY')}}` |
| `time(str)` | Format time | `{{time(timestamp)}}` |

### Array Functions

| Function | Description | Example |
| - | - | - |
| `length(arr)` | Array length | `{{length(items)}}` |
| `first(arr)` | First element | `{{first(images)}}` |
| `last(arr)` | Last element | `{{last(comments)}}` |
| `join(arr, separator)` | Join elements | `{{join(tags, ', ')}}` |
| `slice(arr, start, end)` | Slice array | `{{slice(items, 0, 3)}}` |
| `contains(arr, value)` | Check if contains | `{{contains(roles, 'admin')}}` |
| `indexOf(arr, value)` | Find index | `{{indexOf(items, 'apple')}}` |

### Type Checks

| Function | Description | Example |
| - | - | - |
| `isEmpty(val)` | Check if empty | `{{isEmpty(items)}}` |
| `isNotEmpty(val)` | Check if not empty | `{{isNotEmpty(name)}}` |
| `isDefined(val)` | Check if defined | `{{isDefined(user)}}` |
| `isArray(val)` | Check if array | `{{isArray(items)}}` |
| `isString(val)` | Check if string | `{{isString(name)}}` |
| `isNumber(val)` | Check if number | `{{isNumber(count)}}` |

### Utilities

| Function | Description | Example |
| - | - | - |
| `default(val, fallback)` | Default if empty | `{{default(name, 'Guest')}}` |
| `coalesce(a, b, ...)` | First non-null | `{{coalesce(nickname, name, 'User')}}` |
| `json(val)` | To JSON string | `{{json(data)}}` |
| `parseJson(str)` | Parse JSON | `{{parseJson(jsonString)}}` |

## Conditional Rendering

### If/Else in Text

```
{{isPremium ? 'Premium Member' : 'Free User'}}
```

### Conditional Objects

In template objects, use the `_if` property:

```json theme={null}
{
  "type": "textbox",
  "text": "Premium Badge",
  "_if": "isPremium"
}
```

The object is only rendered if the condition evaluates to true.

### Complex Conditions

```json theme={null}
{
  "type": "image",
  "src": "{{badge}}",
  "_if": "isPremium && !isExpired"
}
```

## Text Interpolation

Combine static text with expressions:

```
Hello, {{name}}! You have {{count}} {{count == 1 ? 'message' : 'messages'}}.
```

Multiple expressions in one string:

```
{{currency(price, 'USD')}} ({{percent(discount)}} off)
```

## Testing Expressions

Test expressions before using them in templates:

### Validate Syntax

```bash theme={null}
curl -X POST https://api.pictify.io/templates/expression/validate \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expression": "price * quantity"}'
```

Response:

```json theme={null}
{
  "valid": true,
  "expression": "price * quantity"
}
```

### Test with Data

```bash theme={null}
curl -X POST https://api.pictify.io/templates/expression/test \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "expression": "currency(price * quantity, 'USD')",
    "variables": {
      "price": 29.99,
      "quantity": 3
    }
  }'
```

Response:

```json theme={null}
{
  "success": true,
  "result": "$89.97",
  "resultType": "string"
}
```

### List Available Functions

```bash theme={null}
curl https://api.pictify.io/templates/expression/functions \
  -H "Authorization: Bearer $API_KEY"
```

## Examples

### Personalized Greeting

```
{{capitalize(greeting)}}, {{titleCase(name)}}!
```

### Price Display

```
{{currency(price, 'USD')}}{{hasDiscount ? ' (' + percent(discount) + ' off)' : ''}}
```

### Date Formatting

```
Published {{date(publishedAt, 'MMMM D, YYYY')}}
```

### Conditional Badge

```json theme={null}
{
  "type": "rect",
  "fill": "{{isPremium ? '#FFD700' : '#C0C0C0'}}",
  "_if": "showBadge"
}
```

### Array Display

```
{{join(slice(tags, 0, 3), ' • ')}}{{length(tags) > 3 ? ' +' + (length(tags) - 3) + ' more' : ''}}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.