# platelet
`platelet` is an HTML-first templating language.
This repo contains a Rust library for rendering `platelet` templates.
## Why platelet?
Unlike `moustache`, `handlebars`, `Jinja`, `Liquid` and other templating languages, `platelet`'s syntax is part of HTML (similar to Vue.js).
This has a few upsides:
- **Higher level** but [less powerful](https://www.w3.org/DesignIssues/Principles.html#:~:text=Principle%20of%20Least%20Power) than direct string manipulation
- The language is **natural to read and write** when working with HTML, and control flow follows HTML structure
- You can use your own HTML formatters and **tooling**
- HTML **sanitization** is more natural and straightforward
## Example
You can explore live examples in the [platelet playground](https://angusjf.com/platelet/playground)
###### Template
```html
```
###### Context (input)
```json
{
"title": "Angus' Blog",
"blogposts": [
{
"img_url": "...",
"link": "...",
"summary": "...",
"title": "...",
"date": "01/11/2025"
},
{
"img_url": "...",
"link": "...",
"summary": "...",
"title": "...",
"date": "01/11/2020"
}
]
}
```
## Reference
| Syntax | Example | Details |
| ----------------- | --------------------- | -------------------- |
| `pl-` directives | `pl-if`, `pl-for` ... | [→](#pl--directives) |
| `^` attributes | `^class`, `^name` ... | [→](#-attributes) |
| `{{ ... }}` nodes | `{{ user.email }}` | [→](#text-nodes) |
| Expressions | `1 + users[i].score` | [→](#expressions) |
## `pl-` Directives
HTML Attributes starting with a `pl-` are special. They are inspired by Vue's directives.
| attribute |
| ------------ |
| `pl-if` |
| `pl-else-if` |
| `pl-else` |
| `pl-for` |
| `pl-html` |
| `pl-src` |
| `pl-slot` |
| `pl-is` |
### Conditionals: `pl-if`, `pl-else-if`, `pl-else`
`pl-if` will only render this element if the expression is truthy
`pl-else-if`, used following a `pl-if`, will only render this element if the expression is truthy
`pl-else`, used following a `pl-if` or `pl-else-if`, will render this element otherwise
```html
```
If applied to a ``, the template will be and the children rendered.
### `pl-for`
Render element multiple times.
Allows 4 types of expression:
```html
{{item.text}}
...
...
...
```
If applied to a ``, the template will be removed and the children rendered.
### `pl-html`
Set the innerHTML (without sanitization) to the given expression.
To set the outerHTML, apply this to a ``.
```html
```
```json
{ "markdown": "
Content from a CMS
..." }
```
### `pl-src`
Given a path as a string, renders the template at the path and replaces the element.
```html
Some text...
```
The attributes set on the element (regular attributes or rendered `^` attributes) are used as the context for rendering the template.
### `pl-slot`
On a ``, `pl-slot` (with an optional name) marks the element as a slot, to be replaced.
On a ``, `pl-slot` marks the template content as "what fills that slot".
###### `index.html`
```html
...
```
### `pl-is`
Replace the rendered element's tag with this element, given an expression that returns a string
```html
{item}
```
## `^` Attributes
In an HTML attribute, prefixing the attribute with `^` allows you to set the value to a `platelet` expression.
```html
```
If the expression is `false` or `null`, the attribute will not render.
```html
```
This will render:
```html
```
## Text Nodes
In an HTML text node, `{{variable}}` inserts a (sanitized) string.
```html
Welcome back {{user.name}}!
```
If the variable is not defined then an error is returned.
| Data type | Rendered as |
| --------- | ------------- |
| Number | A number |
| String | A string |
| Boolean | true or false |
| Null | blank |
| Array | error |
| Object | error |
## Expressions
All valid JSON values are valid `platelet` expressions. On top of this, single-quoted strings `'like this'` are allowed for convenience when working with HTML.
### Operators
On anything: `==`, `!=`, `&&`, `||`, `!`, `x ? y : z`
On numbers: `+` (addition)
On strings and arrays: `+` (concatenation)
On objects: `+` (shallow merge, right hand side overriding)
On numbers: `-`, `*`, `/`, `%` (mod)
On numbers: `>`, `<`, `>=`, `<=`
On objects arrays and strings, indexing operator `a[b]`
On objects, dot access: `{"name": "angus"}.name`
On arrays, objects and strings: `len(z)`
Expressions can be bracketed `(9 + 3) / 2 == 6`
### Truthiness
`false`, `[]`, `""`, `{}`, `null` are **falsy**.
All other values are **truthy**.