基于仓颉实现的mustache模板引擎
分支说明: master版本使用序列化来实现模板渲染的变量查找, 现在可以正常使用, 不支持模板的方法调用(mustache lambda), 无参调用可以在实现序列化接口时多添加字段并存放方法调用结果来实现。
reflect版本因为反射无法调用Collection相关接口,而无法使用,仓颉可能会改反射,先留着。
[dependencies]
mustache = {git = "https://github.com/ystyle/mustache-cj", branch = "master"}
没有实现
mustache(5)
的所有功能, 已实现的主要功能如下
- Variables
- Dotted Names:
{{user.name}}
- Implicit Iterator:
{{.}}
- Lambdas: 不支持, 但可以在实现
MustacheComponent
接口时, 使用方法调用的方式代替
- Dotted Names:
- Sections
- List:
{{#list}}{{name}}{{/list}}
- if:
{{#isTrue}}{{.}}{{/isTrue}}
- Non-Empty Lists:
{{#repo}}<b>{{name}}</b>{{/repo}}
- Inverted Sections:
{{^repo}}No content{{/repo}}
- Lambdas: 不支持, 但可以在实现
MustacheComponent
接口时, 使用方法调用的方式代替 - Non-False Values
- List:
- Comments:
{{! this is Comments}}
- Partials:
{{> header}}
- Dynamic Names
- Blocks
- Parents
- Set Delimiter:
{{=<% %>=}} print: <% name %>
orTemplate(name: String, delimiters("<%", "%>"))
如果是自定义类型的话需要实现MustacheComponent
接口, 自带的类型已经用扩展功能实现过了。
MustacheComponent
接口
public interface MustacheComponent {
func mustache(): DataModel
}
自定义类型示例:
import mustache.*
class MyData <: MustacheComponent {
MyData(let string: String) {}
public func mustache(): DataModel {
return DataModelStruct().add(field<String>("string", string))
}
}
渲染模板
import mustache.*
main(): Int64 {
let t = Template("tpl_name")
t.parse("some text {{foo}} here")
let data = HashMap<String, String>(
("foo", "bar")
)
let out = t.render(data)
println(out)
// some text bar here
return 0
}
使用类渲染模板:
import mustache.*
import std.collection.HashMap
import serialization.serialization.*
class TestData <: MustacheComponent {
TestData(let integer: Int64, let string: String, let boolean: Bool, let map: HashMap<String, String>, let list:Array<Int64>) {}
public func serialize(): DataModel {
return DataModelStruct()
.add(field<Int64>("integer", integer))
.add(field<String>("string", string))
.add(field<Bool>("boolean", boolean))
.add(field<HashMap<String, String>>("map", map))
.add(field<Array<Int64>>("list", list))
}
}
main() {
let t = Template("tpl_name")
t.parse("integer:\t{{integer}}\nstring:\t{{string}}\nboolean:\t{{boolean}}\nmap.in:\t{{map.in}}\nlist:\t{{^list}}{{.}}{{/list}}")
let data = TestData(123, "abc", true, HashMap<String, String>(("in", "I'm nested!")), 1,2,3)
let out = t.render(data)
println(out)
// integer: 123
// string: abc
// boolean: true
// map.in: I'm nested!
// list: 123
}
引用模板
main() {
println("Partials:")
let t1 = Template("text")
t1.parse("from partial")
let t2 = Template("index", partial(t1))
t2.parse("{{>text}}")
let out = t2.render(1)
println(out) // from partial
}
Template()
: 实例化一个模板Template(name: String, options: Array<OptionFn>)
: 自定义名称和变量标记public func parse(input: InputStream): Unit
: 从流加载模板public func parse(content: String): Unit
: 从字符串加载模板public func parse(bs: Array<Byte>): Unit
: 从字节数组加载模板public func render<T>(w: OutputStream, context: Array<T>): Unit where T <: MustacheComponent
: 渲染模板到输出流public func render<T>(context: Array<T>): String where T <: MustacheComponent
: 渲染模板为字符串public func renderBytes<T>(context: Array<T>): Array<Byte> where T <: MustacheComponent
: 渲染模板到字节数组
OptionFn(t:Template):Unit
: 设置引擎参数, 有以下lambdadelimiters("{{", "}}")
: 设置变量标记partial(t:Template)
: 设置模板, 以便引用模板enableErrors()
: 启用错误, 找不到变量时会抛出异常silentMiss()
: 禁用错误, 找不到变量时不处理disableEscape()
: 禁用转义, 比如在生成xml标签时用Template(name: String, delimiters("{{", "}}"), partial(t:Template), partial(t:Template))
: 可以多个一起设置