B2.应用举例
B2.应用举例
米波进行模板翻译,不依赖任何模板,测试和演示时使用pebble,因其benchmark和语法较好。
Pebble,FreeMarker和Velocity此类模板有自己的语法特性,在行业内大量使用。 有些IDE有插件支持,但都是模板语言,而非目标文件的语言的支持,包括语法高亮,纠错等加持。
Thymeleaf(近期停止更新了)类的模板不会破坏目标文件语法,并且应用领域和具体语言特性绑定。
米波的初衷不是模板的动态控制能力,但使用执行引擎
(如js和java)可以做很复杂的功能操作。 尽管从benchmark上看,其性能远高于Freemarker
和Velocity
,是thymeleaf
的3倍, 但并不建议使用米波做工程上的view层渲染,它适合做模板中间层,或叫模板翻译器。
因markdown对空格和空行有自己的理解,估在精确辨识空格和空行时,请参考链接中的源码。
B2.1.忽略指令行空白,可读性优先
底层模板的blog-trim.peb,不能有效的被html和js语法加持,IDE插件能够识别pebble语法。
<body>
{% for article in articles %}
<h3>{{ article.title }}</h3>
<p>{{ article.content }}</p>
{% endfor %}
<script type="text/javascript">
var machineId = {{machineId}}
</script>
</body>
同等输出的blog-trim.htm,保留原本的html和js特性,可以以html编辑。也可以使用pebble插件编辑。 没有使用!
,如果指令行独占一行,且行内全为空白,则不输出此行。第一行故意有个空格。
<!-- HI-MEEPO -->
<body>
<!-- DNA:RAW {% for article in articles %} -->
<h3>{{ article.title }}</h3>
<p>{{ article.content }}</p>
<!-- DNA:RAW {% endfor %} -->
<script type="text/javascript">
// HI-MEEPO
// DNA:SET /"machine-id"/{{machineId}}/
var machineId = "machine-id"
</script>
</body>
B2.2.保留指令行空白,一致性优先
底层模板的blog-pure.peb,注意<body>
上有一空行,var
前共有有4x3=12个空格。
<body>
{% for article in articles %}
<h3>{{ article.title }}</h3>
<p>{{ article.content }}</p>
{% endfor %}
<script type="text/javascript">
var machineId = {{machineId}}
</script>
</body>
同等输出的blog-pure.htm,使用了!
,使得米波只处理注释首尾间的内容,保留之外的换行和空白(var前2行各4个空格)。
<!-- HI-MEEPO! -->
<body>
<!-- DNA:RAW {% for article in articles %} -->
<h3>{{ article.title }}</h3>
<p>{{ article.content }}</p>
<!-- DNA:RAW {% endfor %} -->
<script type="text/javascript">
// HI-MEEPO!
// DNA:SET /"machine-id"/{{machineId}}/
var machineId = "machine-id"
</script>
</body>
B2.3.全部替换,使用匿名全局
输出结果的replace-all-o.htm
<div>
use anonymous all-life to replace div to div
</div>
米波模板的replace-all-i.htm,使用*
为匿名全局替换。
<!-- HI-MEEPO -->
<!-- DNA:SET /body/div/* -->
<body>
use anonymous all-life to replace body to div
</body>
B2.4.间隔替换,使用指定范围
输出结果的replace-1a3-o.htm
<div>
use ranged-life to replace 1st and 3rd body to div
</div>
米波模板的replace-1a3-i.htm,使用1,3
逗号分隔,确认次数。
<!-- HI-MEEPO -->
<!-- DNA:SET /body/div/1,3 -->
<body>
use ranged-life to replace 1st and 3rd body to div
</body>
B2.5.范围替换,使用命名全局
输出结果的replace-end-o.htm
<body>
use named-life to replace scoped div to div
</body>
米波模板的replace-end-i.htm,使用end
和命名生命周期。
<!-- HI-MEEPO -->
<body>
<!-- DNA:SET /body/div/body -->
use named-life to replace scoped body to div
<!-- DNA:END body -->
</body>
B2.6.保留原样,使用魔免黑皇杖
输出结果的black-king-bar-o.htm
<!-- DNA:SET /body/div/* -->
<body>
in bkb, all are plain text, including DNA:SET
</body>
米波模板的black-king-bar-i.htm,使用end
和命名生命周期。
<!-- HI-MEEPO -->
<!-- DNA:BKB bkb -->
<!-- DNA:SET /body/div/* -->
<body>
in bkb, all are plain text, including DNA:SET
</body>
<!-- DNA:END bkb -->
B2.7.删除行块,实际是替换为空
输出结果的delete-1a3-o.htm
delete all, but this line
米波模板的delete-1a3-i.htm,删除(替换为空)第1和3匹配行。
<!-- HI-MEEPO -->
<!-- DNA:SET /^.*\n?//1,3 -->
<body>
delete all, but this line
</body>
米波模板的delete-all-i.htm,删除body及期间所有。
<!-- HI-MEEPO -->
<!-- DNA:SET :<body>[\s\S]*</body>:: -->
<body>
delete all, but this line
</body>
B2.8.单次执行,存入Model
输出结果的put-use-o.htm
<body>
1009+10+7=1026
1009+10+7=1026
</body>
米波模板的put-use-i.htm,用PUT和USE做单次执行,到处使用。
<!-- HI-MEEPO -->
<!-- RNA:PUT js/calc/1009+10+7/ -->
<body>
<!-- RNA:USE /result/calc/* -->
1009+10+7=result
1009+10+7=result
</body>
B2.9.每次执行,js版计数器
输出结果的run-any-o.htm
<body>
i=1009+10+7=1026
i++ == 1027
i++ == 1028
</body>
米波模板的run-any-i.htm,用RUN和js执行引擎。
<!-- HI-MEEPO -->
<!-- RNA:RUN js//i=1009+10+7/ -->
<!-- RNA:RUN js/counter/i++;i.toFixed()/* -->
<body>
i=1009+10+7=1026
i++ == counter
i++ == counter
</body>
B2.A.运行时import静态文本
通过uri引擎,可以读取 file://
,classpath:
和http://
等外部资源
输出结果的import-o.htm
imported text
米波模板的import-i.htm,读入import-f.htm。
<!-- HI-MEEPO -->
<!-- RNA:RUN uri#import-here#classpath:/template/imp/import-f.htm# -->
import-here
B2.B.执行java代码,动态编译
输出结果的compile-java-o.htm
2020-07-09 00:00:00
米波模板的compile-java-i.htm
<!-- HI-MEEPO -->
<!-- RNA:RUN java#java-output#
import java.time.LocalTime, java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
LocalDate date = LocalDate.parse("2020-07-09");
LocalDateTime ldt = LocalDateTime.of(date, LocalTime.of(0, 0, 0));
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return ldt.format(fmt);
# -->
java-output
B2.C.替换默认界定符,不想用斜杆
界定符
是第1个非(空白
,!
,英数
)1-2字节char,常用的如/
,汉字。 所以只要避免和指令中内容重复即可,但是,像👹这种的3,4字节不可以,getChar会分裂。
// RNA:RUN js/counter/i++;i.toFixed()/
// RNA:RUN js:counter:i++;i.toFixed():
// RNA:RUN js|counter|i++;i.toFixed()|
// RNA:RUN js汉counter汉i++;i.toFixed()汉
B2.D.自动缩排多行代码,美观易读
参加测试JavaTest.java,变量
为集合类,其元素自带换行
c.put("method", Arrays.asList("LocalDate date = LocalDate.parse(\"2020-07-09\");\n",
"LocalDateTime ldt = LocalDateTime.of(date, LocalTime.of(0, 0, 0));\n",
"DateTimeFormatter fmt = DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\");\n",
"return ldt.format(fmt);"));
会输出有了缩排的JavaOut.java
public Object eval(@NotNull Map<String, Object> ctx) {
LocalDate date = LocalDate.parse("2020-07-09");
LocalDateTime ldt = LocalDateTime.of(date, LocalTime.of(0, 0, 0));
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return ldt.format(fmt);
}
如果,变量
不是集合类,而是带有\n
的字符串,那么会这样的呲牙效果
public Object eval(@NotNull Map<String, Object> ctx) {
LocalDate date = LocalDate.parse("2020-07-09");
LocalDateTime ldt = LocalDateTime.of(date, LocalTime.of(0, 0, 0));
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return ldt.format(fmt);
}
B2.E.如何自定义函数
/* HI-MEEPO */
/* RNA:PUT fun/fun:abs/return Math.abs(((Number)obj).intValue())/ */
/* RNA:USE /abs/number|fun:abs/*/
abs
以上模板,通过RNA:PUT
和fun
引擎,在context中,put一个名为fun:abs
的函数
, 在合并时,context.put("number",-1),模板输出为1
,详见testFunAbs
。
Map<String, Object> ctx=new HashMap<>();
Function<Number, Integer> abs=number->Math.abs(number.intValue());
ctx.put("fun:abs",abs);
ctx.put("number",-1);
// rna:use /now/number|abs/
以上是运行时,通过java编码做到同等效果,详细参考
- 管道符链接函数,链式处理
- 动态java函数 fun
B2.F.占位符模板
不用作为整块Meepo模板,只处理模板变量替换和函数处理,以下2行分别是输入和输出。 其中 {{moilion-circle|PascalCase}}
为,模板定义的变量及函数替换。
"this is {{moilion-circle|PascalCase}} simple template"
"this is MoilionCircle simple template"
B2.G.组件Widget功能
Widget是View和Model的组合,SON
内PUT
可以实现组件功能。
如网站的TopHead通常根据id加载Model,模板引擎渲染View得到输出输出。 模板引擎支持include功能,但不会加载Model,因为V和M的职责不同,就不应该支持。
实际工作中,我们更希望View层的TopHead被include时,其所需Model也加载了。 而不是,View层include一次,Controller层再include一次Model的加载。
Meepo具备了运行时调整context的能力,也就是自己可加载Model,变为组件。 在本文语境中,import为动态RNA范畴,include为静态DNA范畴。
以相对路径include-i2.htm引入子模板
<!-- HI-MEEPO -->
<!-- DNA:SON ./include-f.txt -->
since 2020-02-02
子模板include-f.txt内容
# HI-MEEPO
# DNA:SET /name/trydofor/
# RNA:USE /domain/gmail/
author = name@domain
输出结果include-o.htm
author = trydofor@gmail.com
since 2020-02-02