## 6.1 handlebars模板语言 >本节主要介绍handlebars模板语言的使用,利用handlebars语音定制机器人回答,使机器人更加灵活多样。 > [ruyi.ai](http://ruyi.ai) 为开发者提供了丰富的定制模块。在匹配用户的自然语言表达方 面,提供了词典,暗号,必须词条以及优先级的配置,以达到对用户意图的精 准匹配。而在回答用户说法的角度上,开发了基于模版语言handlebars的自 定义版本,为ruyi.ai的用户提供持续定制改进空间。 >handlebars语言在微信硬件端皆可以编写。 ![](https://box.kancloud.cn/babbd12514f438c434c55e8733331239_1110x274.png) ### 6.1.1 简介 **Handlebars = JSON + 模版 + 函数** >Handlebars 是一个语义化的 web模板系统,最初由 Yehuda Katz 于 2010 年编写。[1]它是 Mustache (模板系统)的一个超集,除渲染 Handlebars 模板之外,也可以渲染 Mustache 模板。不像 Mustache, Handlebars 包括一 些逻辑,如 #if, #unless, #with 和 #list。 Handlebars.js是一个由Javascript构建的编译器,它接收任意HTML与 Handlebars.js表达式并将它们编译为Javascript函数。这个派生出来的 Javascript函数接着接收一个参数,一个对象 - 即你的数据 - 然后它返回一个 包含HTML以及被插值在HTML中的对象属性值的字符串。因此,你最终可以 得到一个对象属性值位于相应地方的字符串(HTML),你可以将这个字符串 插入到页面中。 ### 6.1.2 基本概念实战 在线测试(基于javascript): http://tryhandlebarsjs.com/ (注意,RUYI- API 使用的是JAVA版实现,可能与Javascript有细微差异) Handlebars模板看起来就像是正常的文本,并使用了嵌入的 handlebars表达式。更多handlebars表达式参见以下链接。http://handlebarsjs.com/ (中文首页翻译http://handlebarsjs.cn/) handlebars表达式,是以`{{`开始,跟一些内容,然后以`}}`结束。 姓名: {{name}} 城市:{{address.city}} 姓名:张三,城市:上海 ``` name:姓名—张三 age:城市—上海 ``` JSON数据结构, JSON(JavaScript Object Notation) 是一种轻量级的数据交换格 式。 易于人阅读和编写。同时也易于机器解析和生成。 ``` http://www.json.org/json-zh.html { "name": "张三", "age": 24, "address": { "street": "盛夏路", "city": "上海" }, "friends": ["李四", "Joe"] } ``` 对象(Object)是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开 始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’对”之间使 用“,”(逗号)分隔。 数组(Array)是值(value)的有序集合。一个数组以“[”(左中括号)开 始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。 编译/应用模板 `JAVA(https://github.com/jknack/handlebars.java) javascript(https://github.com/wycats/handlebars.js/) ` 采用不同技术实现 ### 6.1.3 技术要点 基于模版的JSON数据渲染 支持自定义函数回调丰富渲染能力--基本上支持编程 ### 6.1.4 网上教程 中文资料1:Handlebars.js初级教程:学习Javascript模板Handlebars.js http://www.html-js.com/article/1595 中文资料2:js模版引擎handlebars.js实用教程 -杨元 http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471227.html ### 6.1.5 实例分析 基于ruyi开发者后台 注:所有handlebars的表达式均填写在助理答的 handlebars编辑框中,助理识别结果结构 `in=parameters (如意NLP识别结果)` `out=result (如意ACTION处理结果)` ### 6.1.6 变量引用 简单路径 ` sys.template.mustache={{in.details}` 标准变量引用路径 `sys.template.mustache={{#in}}{{details}}{{/in}}` 引用自己 `{{ .}}` (如果没有该变量,则不显示) 定制变量格式化 ` sys.template.mustache={{#in}} {{#time_start}}从【{{timeFormat . format="yyyy年M月d日h点m分"}}】{{/ time_start}} {{/in}} ` timeFormat为ruyi-api定制函数,可以讲数字型时间表示转化为中文表示。具体时间格式化参数(format) 参考https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx ### 6.1.7 实例(日程提醒) + 例一 `用户说:今天晚上6点在张江深山老屋和朋友吃饭,提前1小时提醒 ` `期望答复: 日程: (内容)吃饭 (开始的时间)【2016年4月1日18点0分】在(地点 )【张江深山老屋】和【朋友】(提醒时间)【提前一小时】提醒` + 变量分解 details:内容-吃饭 time_start:开始时间-晚上六点,调用timeFormat为ruyi-api定制函数,将数字型时间表示转化为中文表示,“yyyy年M月d日h点m分”,并且用方括号“【】”括起来,这里显示的就是“【2016年4月1日18点0分】”具体时间格式化参数(format)参考https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx time_end:结束时间-没有该变量不显示 timedelta_alert:提醒时间-时间差,提前一小时识别为“-1小时”。 participant:参与者-朋友 location:地点-张江深山老屋 助理答填写(按照句子期望回答的结构顺序) sys.template.mustache= {{#in}} 日程:{{details}}\n {{#time_start}}【{{timeFormat . format="yyyy年M月d日h点m分"}}】{ {/time_start}} {{#location}}在【{{.}}】{{/location}} {{#participant}}和【{{.}}】{{/participant}} {{#timedelta_alert}}\n【{{timedeltaFormat .}}】提醒{{/timedelta _alert}} {{/in}} JSON输出结果 "result": { "text": "日程: 和朋友吃饭\\n【2016年4月1日18点0分】 在【张江深山老屋 】 \\n【提前1小时】提醒 ", "type": "dialog" }, ### 6.1.8 条件分支逻辑 IF THEN ELSE `if—>{{#}}...{{/}}` `else——>{{^}}...{{/}}` 举例: sys.template.mustache= {{#age}}有年龄:{{.}}{{/age}}——>有年龄则引用输入的年龄 {{^age}}无年龄{{/age}}——>若没有年 龄则什么都不引用 数据1 -- 期望输出年龄 { "name": "张三", "age": 24 }(有年龄”24“的显示) 数据2-- 期望没有年龄的输出 { "name": "张三" }(没有年龄的显示) ### 6.1.9 自建处理函数 为了提高智能助理回答答案的多样化和定制性,我们持续自定义和扩充 handlebars helper函数,帮助用户可以以快捷,简便的方式对数据结果进行自定 义的输出。 ### 6.1.10 split函数 Handlebars新增了split函数,可以将参数值按照一定的分隔符分隔,并按照下标 获取其中的某个值。如果分隔不成功,或者下标值超出范围,则返回原参数值。 使用方法: `{{split 参数名 分隔符 下标值}}` 举例: input值为 a#b#c {{split input "#" 0}} 返回 a {{split input "#" 1}} 返回 b {{split input "#" 2}} 返回 c ### 6.1.11 概述: strComp Handlebars之前不能对字符串之间进行比较,现在新增了strComp (String Compare)函数,可以进行如下的逻辑判断: 1. 等于 equals 2. 包含 contains 3. 前缀比较 startswith 4. 后缀比较 endswith 使用方法: # 号跟strComp,后面跟三个参数,第一个是变量名,第二个是判断符号,(如equals,需要使用双引号“”括起来,否则无法识别),第三个是需要 比较的字符串 局限性: 目前只能支持一个参数与字符串之间进行比较,无法进行两个参数的比较。 ### 6.1.12 概述:ifCond Handlebars内置的 if 只能判断一个参数值有没有,是不是null或者0,不能对其 具体的值进行逻辑判断,所以新增了ifCond,可以进行如下的逻辑判断: 1.等于 == 2.不等于 != 3.大于 > 4.小于 < 5.大于等于 >= 6.小于等于 <= 使用方法: # 号跟ifCond,后面跟三个参数,第一个是变量名,第二个是判断符 号,(如==,需要使用双引号 “ ” 或者单引号 ‘ ’ 括起来,否则无法识别),第三 个是数值(除了整数之外,小数、布尔值、字符串等都需要用双引号 “ ” 或者单引 号 ‘ ’ 括起来,否则无法识别) 举例: ``` {{#ifCond num "==" 3}} number equals to 3 {{else}} number not equal to 3 {{/ifCond}} ================================= {{#ifCond num "==" "3.2"}} number equals to 3.2 {{else}} number not equal to 3.2 {{/ifCond}} ================================= {{#ifCond bool "==" "true"}} bool is true {{else}} bool is false {{/ifCond}} ================================= {{#ifCond str "==" "good"}} str is good {{else}} str is not good {{/ifCond}} ``` 局限性: 目前只能支持一个参数与数值之间进行比较,无法进行两个参数的比较。