[[Obsidian Web Clipper 简介|Web Clipper]] 支持模板逻辑,包括条件判断、循环和变量赋值。该语法受到 [Twig](https://twig.symfony.com/) 和 [Liquid](https://shopify.github.io/liquid/) 模板语言的启发。
> [!warning] 需要最新版本
> 逻辑功能需要 Obsidian Web Clipper 1.0.0,该版本尚未在所有扩展商店通过审核。
## 条件判断
使用 `{% if %}` 根据变量或表达式有条件地包含内容。
```twig
{% if author %}
Author: {{author}}
{% endif %}
```
使用 `{% else %}` 提供备用内容,使用 `{% elseif %}` 串联多个条件:
```twig
{% if status == "published" %}
Live article
{% elseif status == "draft" %}
Draft article
{% else %}
Unknown status
{% endif %}
```
### 比较运算符
支持以下比较运算符:
| 运算符 | 说明 |
|----------|-------------|
| `==` | 等于 |
| `!=` | 不等于 |
| `>` | 大于 |
| `<` | 小于 |
| `>=` | 大于或等于 |
| `<=` | 小于或等于 |
| `contains` | 检查字符串是否包含子字符串,或数组是否包含某个值 |
示例:
- `{% if title == "Home" %}` — 字符串相等比较
- `{% if price >= 100 %}` — 数值比较
- `{% if title contains "Review" %}` — 子字符串检查
- `{% if tags contains "important" %}` — 数组成员检查
### 逻辑运算符
使用逻辑运算符组合条件:
| 运算符 | 替代写法 | 说明 |
| -------- | ----------- | ----------------------------------- |
| `and` | `&&` | 两个条件都必须为真 |
| `or` | \|\| | 至少一个条件为真 |
| `not` | `!` | 对条件取反 |
示例:
- `{% if author and published %}` — 两者必须都存在
- `{% if draft or archived %}` — 任一条件满足
- `{% if not hidden %}` — 取反
- `{% if (premium or featured) and published %}` — 分组条件
### 真值判断
当变量不使用比较运算符时,会对其进行"真值"判断:
- `false`、`null`、`undefined`、空字符串 `""` 和 `0` 被视为**假值**。
- 空数组 `[]` 被视为**假值**。
- 其他所有值被视为**真值**。
```twig
{% if content %}
Has content
{% endif %}
```
## 变量赋值
使用 `{% set %}` 在模板中创建或修改变量:
```twig
{% set slug = title|lower|replace:" ":"-" %}
File: {{slug}}.md
```
变量可以被赋值为:
- 其他变量:`{% set name = author %}`
- 字面量:`{% set count = 5 %}` 或 `{% set label = "Draft" %}`
- 带过滤器的表达式:`{% set excerpt = content|truncate:100 %}`
- 选择器结果:`{% set comments = selector:.comment %}`
使用 `{% set %}` 设置的变量可以在后续的模板逻辑和 `{{variable}}` 输出中使用。
## 回退值
使用 `??` 运算符在变量为空或未定义时提供回退值:
```twig
{{title ?? "Untitled"}}
```
如果 `title` 为空、未定义或为假值,则会使用回退值 `"Untitled"`。
这是等效 `if` 语句的简写形式:
```twig
{% if title %}{{title}}{% else %}Untitled{% endif %}
```
### 链式回退
你可以链式使用多个回退值:
```twig
{{title ?? headline ?? "No title"}}
```
这会优先使用 `title`,如果不可用则使用 `headline`,否则使用字符串 `"No title"`。
### 与过滤器配合使用
过滤器的绑定优先级高于 `??`,因此过滤器会在回退检查之前应用:
```twig
{{title|upper ?? "UNTITLED"}}
```
这会先对 `title` 应用 `upper` 过滤器,如果结果为空则回退到 `"UNTITLED"`。如果要对回退值应用过滤器,请使用括号或单独的表达式:
```twig
{{title ?? "Untitled"|lower}}
```
如果 `title` 可用则使用 `title`,否则对回退值应用 `lower`,结果为 `"untitled"`。
## 循环
使用 `{% for %}` 遍历数组:
```twig
{% for item in schema:author %}
- {{item.name}}
{% endfor %}
```
### 循环数据源
你可以遍历:
- Schema 数组:`{% for item in schema:author %}`
- 选择器结果:`{% for comment in selector:.comment %}`
- 之前设置的变量:`{% set items = selector:.item %}{% for item in items %}`
### 循环变量
在循环内部,你可以访问一个 `loop` 对象,它具有以下属性:
| 变量 | 说明 |
|----------|-------------|
| `loop.index` | 当前迭代次数(从 1 开始) |
| `loop.index0` | 当前迭代次数(从 0 开始) |
| `loop.first` | 如果是第一次迭代则为 `true` |
| `loop.last` | 如果是最后一次迭代则为 `true` |
| `loop.length` | 总项目数 |
```twig
{% for tag in tags %}
{{loop.index}}. {{tag}}
{% if loop.last %} (end of list){% endif %}
{% endfor %}
```
为了向后兼容,你也可以使用 `item_index`(其中 `item` 是你的迭代器变量名)来获取从 0 开始的索引位置:
```twig
{% for tag in tags %}
{{tag_index}}. {{tag}}
{% endfor %}
```
### 通过索引访问数组元素
使用方括号表示法通过索引访问数组元素:
```twig
{{items[0]}}
{{items[loop.index0]}}
```
当你需要并行访问多个数组中的元素时,这非常有用:
```twig
{% set transcripts = selector:.transcript-text %}
{% set timestamps = selector:.timestamp %}
{% for line in transcripts %}
{{timestamps[loop.index0]}} - {{line}}
{% endfor %}
```
方括号表示法同样适用于对象属性:
```twig
{{user["name"]}}
{{data["my-key"]}}
```
### 嵌套循环
循环可以嵌套以处理复杂的数据结构:
```twig
{% for section in sections %}
## {{section.title}}
{% for item in section.items %}
- {{item}}
{% endfor %}
{% endfor %}
```
## 组合逻辑
条件判断和循环可以组合使用:
```twig
{% for item in items %}
{% if item.active %}
- {{item.name}}
{% endif %}
{% endfor %}
```
## 执行顺序
模板逻辑按以下顺序处理:
1. **模板逻辑** — `{% if %}`、`{% for %}`、`{% set %}` 和 `{{variables}}` 最先被执行
2. **提示变量** — [[变量#提示变量|提示变量]](如 `{{"summarize this"|prompt}}`)在模板逻辑完成后发送给解释器
这意味着你可以使用模板逻辑动态构建提示词,但提示词的结果不能用于条件判断或循环中。