Skip to content

过滤器与助手

过滤器对插值值做变换,| 分隔、可链式,namename:arg 形式(arg 支持 "带引号字面量",内部可含中文与 |)。

html
{{ name | upper }}
{{ bio | default:"暂无" }}
{{ title | lower | capitalize }}

内置值过滤器

过滤器作用
upperASCII 大写(多字节字符原样)
lowerASCII 小写
capitalize首字母(ASCII)大写
default:"x"值为空值/空串/空列表时取 x,否则原值
length列表→元素数;字符串→Unicode 字符数
json把值序列化为 JSON 字符串(终结,见下)

upper/lower/capitalize 只做 ASCII 大小写折叠,以规避 Unicode 大小写映射的复杂度与歧义;多字节字符保持原样。

终结转义过滤器

以下过滤器决定最终输出转义,出现在链末位时会跳过默认 HTML 转义

过滤器作用典型上下文
raw不转义(等价 {{& x }}已可信的 HTML 片段
htmlHTML 实体转义元素内容/属性(默认即此)
jsJS 字符串字面量转义(含 </script> 中和)<script> 内嵌
urlRFC 3986 组件百分号编码URL 查询参数
attrHTML 属性值转义(含反引号)属性上下文
html
<a href="/s?q={{ query | url }}">搜索</a>
<script>var name = "{{ name | js }}";</script>
<div title="{{ tip | attr }}">…</div>

求值与转义顺序

  1. 解析 path 取值;
  2. 依次应用链中的值过滤器upper/default/…);
  3. 转标量字符串;
  4. 若链末位是终结转义过滤器(raw/html/js/url/attr/json)→ 按它输出,不再自动 HTML 转义;否则若是默认 {{ }} → HTML 转义,{{& }}/{{{ }}} → 原样。

因此 {{ x | upper }} 先大写再 HTML 转义;{{ x | raw }}{{& x }}{{ x | js }} 输出 JS 转义且不被二次 HTML 转义。未注册的过滤器名被静默跳过(不改变值,链继续)。

自定义助手(registerFilter)

engine.registerFilter(name, fn) 注册助手,签名 (TemplateValue, ?String) -> TemplateValue

cangjie
// 应用启动期(如组件 onReady / @PostConstruct)注册自定义助手
// 加感叹号:{{ word | exclaim }}
engine.registerFilter("exclaim", {v: TemplateValue, _: ?String =>
    TStr(scalarString(v) + "!")
})

// 带参数:{{ label | prefix:"[TODO] " }}
engine.registerFilter("prefix", {v: TemplateValue, arg: ?String =>
    let p = arg ?? ""
    TStr(p + scalarString(v))
})
html
{{ word | exclaim }}
{{ label | prefix:"[TODO] " }}

同名可覆盖内置过滤器。

安全说明

  • 默认插值 {{ x }} 始终 HTML 转义(含反引号 `),覆盖元素内容与带引号/无引号属性上下文。
  • 上下文匹配:进入 JS 用 | js、URL 参数用 | url、属性用 | attrjson 过滤器已中和 < > & /,可安全内联进 <script>(防 </script> 断标签)。
  • raw / {{& }} / {{{ }}} 绕过转义,仅用于可信内容,切勿直接输出用户输入。

基于 Apache-2.0 许可证发布