浪歌 · 随笔 我的开发笔记

使用scriban模板引擎

[netcore] 2024/11/6 12:00:37

通过nuget安装Scriban

1. 可以解析脚本和混合(脚本+文本),默认是混合模式。单独解析脚本:

var lexerOptions = new LexerOptions() { Mode = ScriptMode.ScriptOnly };

var template = Template.Parse("y = x + 1; y;", lexerOptions: lexerOptions);

var result = template.Evaluate(new {x = 10});

Console.WriteLine(result); // =11
2. 导入自定义函数(方法)

// 自定义函数:
  var scriptObject = new ScriptObject();
        scriptObject.Import("format_price", new Func<decimal, string>(price => 
            price.ToString("C2")));

        var context = new TemplateContext();
        context.PushGlobal(scriptObject);

        var template = Template.Parse(@"
            Price: {{ format_price(product_price) }}
        ");

        var result = template.Render(context.PushGlobal(new { product_price = 99.99m }));


//自定义过滤器
 var scriptObject = new ScriptObject();
        scriptObject.Import("truncate", new Func<string, int, string>((str, length) => 
            str.Length <= length ? str : str.Substring(0, length) + "..."));

        var context = new TemplateContext();
        context.PushGlobal(scriptObject);

        var template = Template.Parse(@"
            {{ long_text | truncate 20 }}
        ");

        var result = template.Render(context.PushGlobal(new { 
            long_text = "This is a very long text that needs to be truncated" 
        }));
3. 按模板布局解析

 // 主布局模板
        var layoutTemplate = @"
            <!DOCTYPE html>
            <html>
            <head>
                <title>{{ page.title }}</title>
            </head>
            <body>
                <header>{{ page.header }}</header>
                {{ page.content }}
                <footer>{{ page.footer }}</footer>
            </body>
            </html>
        ";

        // 页面内容模板
        var pageTemplate = @"
            {{ 
                page = { 
                    title: 'My Page',
                    header: 'Welcome',
                    content: 'This is the main content',
                    footer: 'Copyright 2024'
                }
            }}
            {{ include 'layout' }}
        ";

        var context = new TemplateContext();
        var scriptObject = new ScriptObject();
        scriptObject.Add("layout", Template.Parse(layoutTemplate));
        context.PushGlobal(scriptObject);

        var template = Template.Parse(pageTemplate);
        var result = template.Render(context);
4.内置函数:https://github.com/scriban/scriban/tree/master/src/Scriban/Functions

https://github.com/scriban/scriban/blob/master/doc/builtins.md
1. 字符串函数 (string.*)
--------------------
# 基础操作
string.append         # {{ "hello" | string.append " world" }} => "hello world"
string.capitalize     # {{ "hello" | string.capitalize }} => "Hello"
string.contains       # {{ "hello" | string.contains "lo" }} => true
string.ends_with      # {{ "hello" | string.ends_with "lo" }} => true
string.starts_with    # {{ "hello" | string.starts_with "he" }} => true
string.empty         # {{ "" | string.empty }} => true
string.size          # {{ "hello" | string.size }} => 5
string.upcase        # {{ "hello" | string.upcase }} => "HELLO"
string.downcase      # {{ "HELLO" | string.downcase }} => "hello"

# 高级操作
string.handle        # {{ "Hello World" | string.handle }} => "hello-world"
string.truncate      # {{ "Hello World" | string.truncate 5 }} => "He..."
string.truncate_words # {{ "Hello World" | string.truncate_words 1 }} => "Hello..."
string.pad_left      # {{ "hi" | string.pad_left 5 }} => "   hi"
string.pad_right     # {{ "hi" | string.pad_right 5 }} => "hi   "
string.md5           # {{ "hello" | string.md5 }} => "5d41402abc4b2a76b9719d911017c592"
string.sha1          # {{ "hello" | string.sha1 }}
string.sha256        # {{ "hello" | string.sha256 }}
string.hmac_sha1     # {{ "hello" | string.hmac_sha1 "key" }}
string.hmac_sha256   # {{ "hello" | string.hmac_sha256 "key" }}

# 正则相关
string.replace       # {{ "hello" | string.replace "l" "x" }} => "hexxo"
string.split         # {{ "a b c" | string.split " " }} => ["a", "b", "c"]
string.strip         # {{ " hello " | string.strip }} => "hello"
string.lstrip        # {{ " hello " | string.lstrip }} => "hello "
string.rstrip        # {{ " hello " | string.rstrip }} => " hello"

2. 数组/对象函数 (array.*)
----------------------
# 数组操作
array.add           # {{ [1, 2] | array.add 3 }} => [1, 2, 3]
array.concat        # {{ [1, 2] | array.concat [3, 4] }} => [1, 2, 3, 4]
array.join          # {{ ["a", "b"] | array.join "," }} => "a,b"
array.first         # {{ [1, 2, 3] | array.first }} => 1
array.last          # {{ [1, 2, 3] | array.last }} => 3
array.size          # {{ [1, 2, 3] | array.size }} => 3
array.sort          # {{ [3, 1, 2] | array.sort }} => [1, 2, 3]
array.reverse       # {{ [1, 2, 3] | array.reverse }} => [3, 2, 1]
array.uniq          # {{ [1, 2, 2, 3] | array.uniq }} => [1, 2, 3]

# 过滤和查找
array.filter        # {{ [1, 2, 3] | array.filter @(x) => x > 1 }} => [2, 3]
array.map           # {{ [1, 2, 3] | array.map @(x) => x * 2 }} => [2, 4, 6]
array.remove        # {{ [1, 2, 3] | array.remove 2 }} => [1, 3]
array.remove_at     # {{ [1, 2, 3] | array.remove_at 1 }} => [1, 3]

3. 数学函数 (math.*)
-----------------
math.abs           # {{ -42 | math.abs }} => 42
math.ceil          # {{ 4.2 | math.ceil }} => 5
math.floor         # {{ 4.8 | math.floor }} => 4
math.round         # {{ 4.5 | math.round }} => 5
math.max           # {{ math.max 1 2 3 }} => 3
math.min           # {{ math.min 1 2 3 }} => 1
math.pow           # {{ 2 | math.pow 3 }} => 8
math.sqrt          # {{ 16 | math.sqrt }} => 4
math.random        # {{ math.random }} => [0-1)之间的随机数

4. 日期时间函数 (date.*)
---------------------
date.now           # {{ date.now }}
date.add_days      # {{ date.now | date.add_days 1 }}
date.add_months    # {{ date.now | date.add_months 1 }}
date.add_years     # {{ date.now | date.add_years 1 }}
date.parse         # {{ "2024-01-01" | date.parse }}
date.to_string     # {{ date.now | date.to_string "yyyy-MM-dd" }}

5. 对象函数 (object.*)
-------------------
object.keys        # {{ {a: 1, b: 2} | object.keys }} => ["a", "b"]
object.values      # {{ {a: 1, b: 2} | object.values }} => [1, 2]
object.size        # {{ {a: 1, b: 2} | object.size }} => 2
object.default     # {{ null | object.default "default" }} => "default"

6. 类型转换函数
-------------
to_int            # {{ "42" | to_int }} => 42
to_long           # {{ "42" | to_long }} => 42L
to_double         # {{ "4.2" | to_double }} => 4.2
to_string         # {{ 42 | to_string }} => "42"
to_boolean        # {{ "true" | to_boolean }} => true

7. 控制流函数
-----------
if                # {{ if condition }}...{{ end }}
for               # {{ for item in items }}...{{ end }}
while             # {{ while condition }}...{{ end }}
with              # {{ with object }}...{{ end }}

5.转义:

输入:{%{Hello this is {{ name }}}%}
输出:Hello this is {{ name }}

输入:{%%{This is an escaped block: }%} here}%%} 
输出:This is an escaped block: }%} here
6.空格控制

删除左侧的空格:
输入
This is a <       
{{- name}}> text
输出
This is a <foo> text

删除右侧空格:
输入
This is a <{{ name -}} 
> text 
输出
This is a <foo> text

删除左右空格:
输入
This is a <
{{- name -}} 
> text
输出
This is a <foo> text

保持空格:
输入
<ul>
    {{~ for product in products ~}}
    <li>{{ product.name }}</li>
    {{~ end ~}}
</ul>
输出
<ul>
    <li>Orange</li>
    <li>Banana</li>
    <li>Apple</li>
</ul>
7.注释:

//单行注释#和多行注释##
输入
{{ ## This 
is a multi
line
comment ## }}
输出: