Scriban 语法速查
引言
Scriban是一个功能强大、语法简洁的模板引擎,被TMaker采用作为页面渲染的核心。它采用类似Liquid的语法,支持变量输出、条件判断、循环渲染、函数调用等丰富特性,同时具备优秀的性能和安全性。掌握Scriban的基本语法是高效使用TMaker的前提。
本文是Scriban语法的快速参考指南,涵盖了模板开发中最常用的语法结构、内置函数、过滤器使用、以及实战技巧。无论你是刚接触Scriban的新手,还是需要查阅语法细节的熟练开发者,这份参考都能帮你快速找到所需信息。建议配合VS Code的Scriban语法高亮扩展使用,必要时也可以借助Claude Code、OpenAI Codex或GLM等AI工具进行语法校对和代码生成。
变量与输出
在TMaker中,所有页面数据都存储在post对象中。通过post.xxx访问字段数据,使用双花括号{{ }}输出变量值。
基础输出
{{ post.title }}
{{ post.summary }}
{{ post.author.name }}
{{ post.publishDate }}
安全访问(避免null错误)
<!-- 使用默认值 -->
{{ post.description | default: "暂无描述" }}
<!-- 条件输出 -->
{{ if post.subtitle }}
<p class="subtitle">{{ post.subtitle }}</p>
{{ end }}
<!-- 安全导航操作符(可选链) -->
{{ post.author?.name | default: "匿名" }}
变量赋值
{{ $pageTitle = post.title + " | TMaker文档" }}
{{ $currentYear = date.now | date.year }}
<title>{{ $pageTitle }}</title>
<footer>© {{ $currentYear }} TMaker</footer>
对象和数组访问
<!-- 对象字段访问 -->
{{ post.author.name }}
{{ post["author"]["name"] }} <!-- 方括号访问 -->
<!-- 数组索引访问 -->
{{ post.tags[0] }}
{{ post.relatedPosts[1].title }}
条件判断
Scriban提供丰富的条件判断语法,支持if、else if、else以及多种比较运算符。
基本条件
{{ if post.isFeatured }}
<div class="badge">精选文章</div>
{{ end }}
<!-- if-else -->
{{ if post.coverImage }}
<img src="{{ post.coverImage }}" alt="{{ post.title }}" />
{{ else }}
<img src="/images/default-cover.jpg" alt="默认封面" />
{{ end }}
多分支条件
{{ if post.status == "draft" }}
<span class="badge badge-gray">草稿</span>
{{ else if post.status == "published" }}
<span class="badge badge-green">已发布</span>
{{ else if post.status == "archived" }}
<span class="badge badge-red">已归档</span>
{{ else }}
<span class="badge">未知状态</span>
{{ end }}
比较运算符
<!-- 等于/不等于 -->
{{ if post.category == "tech" }}
{{ if post.category != "draft" }}
<!-- 大小比较 -->
{{ if post.readTime > 10 }}
{{ if post.viewCount >= 1000 }}
{{ if post.rating < 3.5 }}
{{ if post.priority <= 5 }}
<!-- 逻辑运算 -->
{{ if post.isPublished && post.isFeatured }}
{{ if post.isDraft || post.isPending }}
{{ if !post.isHidden }}
<!-- 存在性检查 -->
{{ if post.tags }} <!-- 检查是否存在且非空 -->
{{ if post.description == null }} <!-- 检查是否为null -->
三元运算符
{{ $statusClass = post.isPublished ? "published" : "draft" }}
<div class="status-{{ $statusClass }}">{{ post.title }}</div>
循环渲染
使用for循环遍历数组和对象,Scriban提供了丰富的循环辅助变量。
基础循环
{{ for item in post.toc }}
<a href="#{{ item.id }}">{{ item.title }}</a>
{{ end }}
<!-- 遍历标签 -->
{{ for tag in post.tags }}
<span class="tag">{{ tag }}</span>
{{ end }}
循环辅助变量
{{ for article in post.relatedPosts }}
<div class="article
{{ if for.first }} first{{ end }}
{{ if for.last }} last{{ end }}
{{ if for.even }} even{{ else }} odd{{ end }}
">
<h3>{{ for.index }}. {{ article.title }}</h3>
<p>共 {{ for.length }} 篇相关文章,当前第 {{ for.index }} 篇</p>
</div>
{{ end }}
<!-- 循环辅助变量说明:
for.index - 当前索引(从1开始)
for.rindex - 反向索引(从长度到1)
for.first - 是否第一项
for.last - 是否最后一项
for.even - 是否偶数项
for.odd - 是否奇数项
for.length - 总长度
-->
带条件的循环
<!-- 过滤条件 -->
{{ for post in posts }}
{{ if post.isPublished }}
<article>{{ post.title }}</article>
{{ end }}
{{ end }}
<!-- 或使用数组过滤器 -->
{{ for post in posts | array.filter "isPublished" }}
<article>{{ post.title }}</article>
{{ end }}
循环范围
<!-- 数字范围循环 -->
{{ for i in 1..5 }}
<div class="item-{{ i }}">Item {{ i }}</div>
{{ end }}
<!-- 限制循环次数 -->
{{ for post in posts | array.limit 3 }}
<div>{{ post.title }}</div>
{{ end }}
循环中断
{{ for item in items }}
{{ if item.id == targetId }}
<div>找到了:{{ item.name }}</div>
{{ break }} <!-- 跳出循环 -->
{{ end }}
{{ end }}
{{ for item in items }}
{{ if item.isHidden }}
{{ continue }} <!-- 跳过当前项 -->
{{ end }}
<div>{{ item.name }}</div>
{{ end }}
组件引入
使用include引入自定义组件,实现代码复用和模块化。
基础引入
<!-- 引入组件(文件名不含.sbn扩展名) -->
{{ include 'docsSidebar' }}
{{ include 'ui/button' }}
{{ include 'content/article-card' }}
传递参数
<!-- 传递参数对象 -->
{{ include 'ui/button' with {
text: '查看更多',
type: 'primary',
link: '/blog/',
size: 'large'
} }}
<!-- 组件内部通过$0访问参数 -->
<!-- components/ui/button.sbn -->
<a href="{{ $0.link }}" class="btn btn-{{ $0.type }} btn-{{ $0.size }}">
{{ $0.text }}
</a>
传递当前数据
<!-- 传递整个post对象 -->
{{ include 'content/article-card' with post }}
<!-- 传递子对象 -->
{{ include 'ui/user-avatar' with post.author }}
<!-- 传递数组项 -->
{{ for article in post.relatedPosts }}
{{ include 'content/article-card' with article }}
{{ end }}
内置过滤器
Scriban提供丰富的内置过滤器(管道函数),用于数据转换和格式化。
字符串处理
<!-- 大小写转换 -->
{{ post.title | upcase }} <!-- 全大写 -->
{{ post.title | downcase }} <!-- 全小写 -->
{{ post.title | capitalize }} <!-- 首字母大写 -->
<!-- 字符串操作 -->
{{ post.summary | truncate: 100 }} <!-- 截断到100字符 -->
{{ post.content | strip_html }} <!-- 移除HTML标签 -->
{{ post.slug | replace: "-", "_" }} <!-- 替换字符 -->
{{ post.title | append: " - TMaker" }} <!-- 追加字符串 -->
{{ "Hello" | prepend: "Say: " }} <!-- 前置字符串 -->
<!-- 修剪空白 -->
{{ post.content | strip }} <!-- 去除首尾空白 -->
{{ post.content | lstrip }} <!-- 去除左侧空白 -->
{{ post.content | rstrip }} <!-- 去除右侧空白 -->
数字处理
<!-- 数学运算 -->
{{ post.price | times: 0.8 }} <!-- 乘法 -->
{{ post.count | plus: 10 }} <!-- 加法 -->
{{ post.total | minus: 5 }} <!-- 减法 -->
{{ post.amount | divided_by: 2 }} <!-- 除法 -->
{{ post.value | modulo: 3 }} <!-- 取模 -->
<!-- 数字格式化 -->
{{ post.price | math.round }} <!-- 四舍五入 -->
{{ post.price | math.ceil }} <!-- 向上取整 -->
{{ post.price | math.floor }} <!-- 向下取整 -->
{{ post.rating | math.format "0.00" }} <!-- 格式化为两位小数 -->
数组处理
<!-- 数组操作 -->
{{ post.tags | array.size }} <!-- 获取长度 -->
{{ post.tags | array.first }} <!-- 第一个元素 -->
{{ post.tags | array.last }} <!-- 最后一个元素 -->
{{ post.tags | array.join: ", " }} <!-- 连接为字符串 -->
{{ post.tags | array.sort }} <!-- 排序 -->
{{ post.tags | array.uniq }} <!-- 去重 -->
{{ post.tags | array.reverse }} <!-- 反转 -->
{{ posts | array.limit: 5 }} <!-- 限制数量 -->
{{ posts | array.offset: 3 }} <!-- 跳过前3个 -->
<!-- 过滤 -->
{{ posts | array.filter "isPublished" }} <!-- 过滤 -->
{{ posts | array.where "category", "tech" }} <!-- 条件过滤 -->
日期处理
<!-- 日期格式化 -->
{{ post.publishDate | date.format "%Y-%m-%d" }} <!-- 2026-02-11 -->
{{ post.publishDate | date.format "%Y年%m月%d日" }} <!-- 2026年02月11日 -->
{{ post.publishDate | date.format "%B %d, %Y" }} <!-- February 11, 2026 -->
<!-- 相对时间 -->
{{ post.publishDate | date.to_string }} <!-- 格式化为字符串 -->
{{ date.now }} <!-- 当前时间 -->
{{ date.now | date.year }} <!-- 当前年份 -->
URL和HTML处理
<!-- URL编码 -->
{{ post.title | url_encode }} <!-- URL编码 -->
{{ post.content | escape }} <!-- HTML转义 -->
{{ post.safeHtml | raw }} <!-- 原始输出(不转义) -->
内置函数
除了过滤器,Scriban还提供了一些内置函数用于更复杂的操作。
字符串函数
<!-- 字符串包含检查 -->
{{ if string.contains post.title "TMaker" }}
<span>这是关于TMaker的文章</span>
{{ end }}
<!-- 字符串开始/结束检查 -->
{{ if string.starts_with post.url "/blog/" }}
{{ if string.ends_with post.filename ".md" }}
<!-- 字符串分割 -->
{{ $parts = string.split post.tags_string "," }}
{{ for part in $parts }}
<span>{{ part | strip }}</span>
{{ end }}
数组函数
<!-- 数组包含检查 -->
{{ if array.contains post.tags "TMaker" }}
<span>标签包含TMaker</span>
{{ end }}
<!-- 数组映射 -->
{{ $names = array.map posts "title" }} <!-- 提取所有title字段 -->
高级特性
自定义函数
<!-- 定义函数 -->
{{ func format_author(author)
ret author.name + " <" + author.email + ">"
end }}
<!-- 使用函数 -->
{{ format_author post.author }}
捕获输出
<!-- 捕获内容到变量 -->
{{ capture $authorInfo }}
<div class="author">
<h3>{{ post.author.name }}</h3>
<p>{{ post.author.bio }}</p>
</div>
{{ end }}
<!-- 稍后使用捕获的内容 -->
{{ $authorInfo }}
注释
<!-- Scriban注释(不会输出到HTML) -->
{{## 这是单行注释 ##}}
{{##
这是多行注释
可以写很多行
##}}
常见陷阱与最佳实践
1. 不要在.sbn中包含完整HTML结构
<!-- ✗ 错误:包含html/head/body标签 -->
<html>
<head><title>{{ post.title }}</title></head>
<body>
<h1>{{ post.title }}</h1>
</body>
</html>
<!-- ✓ 正确:只写内容部分 -->
<h1>{{ post.title }}</h1>
<p>{{ post.summary }}</p>
2. Clean URL规范
<!-- ✓ 正确:以/结尾 -->
<a href="/docs/config/">配置说明</a>
<a href="/blog/{{ post.slug }}/">{{ post.title }}</a>
<!-- ✗ 错误:不带/或带.html -->
<a href="/docs/config">配置说明</a>
<a href="/blog/{{ post.slug }}.html">{{ post.title }}</a>
3. 数据字段命名
// ✓ 正确:使用小驼峰命名
{
"publishDate": "2026-02-11",
"authorName": "张三",
"isPublished": true
}
// ✗ 错误:不规范的命名
{
"publish_date": "2026-02-11",
"AuthorName": "张三",
"published": true
}
4. 避免过度嵌套
<!-- ✗ 不推荐:深层嵌套 -->
{{ if post.author }}
{{ if post.author.profile }}
{{ if post.author.profile.avatar }}
<img src="{{ post.author.profile.avatar }}" />
{{ end }}
{{ end }}
{{ end }}
<!-- ✓ 推荐:使用默认值或安全导航 -->
{{ $avatar = post.author?.profile?.avatar | default: "/images/default-avatar.jpg" }}
<img src="{{ $avatar }}" />
5. 组件参数传递
<!-- ✓ 正确:明确传递需要的数据 -->
{{ include 'ui/card' with {
title: post.title,
summary: post.summary,
image: post.coverImage
} }}
<!-- ✗ 不推荐:传递整个post可能包含不必要的数据 -->
{{ include 'ui/card' with post }}
6. 使用AI辅助
在VS Code中编写Scriban模板时,建议安装Scriban Language扩展获得语法高亮。遇到复杂的模板逻辑时,可以借助AI工具:
- Claude Code:擅长理解复杂的数据结构和模板逻辑,适合重构和优化
- OpenAI Codex:擅长生成Scriban代码片段和过滤器链
- GLM(智谱清言):擅长中文注释和文档生成
调试技巧
输出调试信息
<!-- 输出完整对象结构(JSON格式) -->
<pre>{{ post | json }}</pre>
<!-- 输出对象类型 -->
{{ post.tags | object.typeof }}
<!-- 条件断点 -->
{{ if post.id == "debug-target" }}
<pre>Debug: {{ post | json }}</pre>
{{ end }}
常见错误排查
- 语法错误:检查
{{和}}是否配对,end关键字是否遗漏 - 变量未定义:确认
.data.json中字段存在且拼写正确 - 循环不执行:检查数组是否为空或null
- 组件找不到:确认组件文件存在且路径正确
学习资源
- 官方文档:Scriban GitHub
- 在线测试:Scriban Playground(在线尝试语法)
- VS Code扩展:Scriban Language(语法高亮和智能提示)
- TMaker示例:查看
templates/tmaker/下的示例模板
总结
Scriban是一个功能强大且易于学习的模板引擎。掌握变量输出、条件判断、循环渲染、组件引入这四大核心特性,就能完成大部分模板开发工作。配合丰富的内置过滤器和函数,可以实现复杂的数据处理和格式化。遵循Clean URL规范、合理命名数据字段、避免过度嵌套,能够编写出清晰、可维护的模板代码。
在实际开发中,善用VS Code的语法高亮扩展,遇到复杂逻辑时借助AI工具辅助,能够显著提升开发效率。记住,模板引擎只是工具,关键在于理解数据流和组件化思想。通过持续实践和参考优秀示例,你会越来越熟练地使用Scriban构建高质量的模板。
找不到你需要的内容?
联系我们