一、发现
在写一个基于模板的代码生成器(我叫她——bud)的时候。因为相对熟悉velocity,而velocity也完全能够胜任,于是就用了他。在生成一个xml文件的时候发现一个有趣的现象——某些情况下velocity会吧模板中的“换行”给吃掉。就是在模板代码里是有换行的。但是处理后就没有了。写了个类似这样的代码:
#foreach($i in [0..10])
$i #if($velocityCount <= 10), #end
#end
看代码写结果。你觉得这段代码会输出什么呢?
0 ,
1 ,
2 ,
3 ,
4 ,
5 ,
6 ,
7 ,
8 ,
9 ,
10
这样? 不对!是这样:
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10
模板上的换行符没了! 这直接影响了生成的代码的美观(质量)。如果是用来生成html,某些情况下会影响界面上的显示。
二、尝试
发现了这个现象以后,我随手做了几个尝试:
1、去掉#if 指令(有效)
#foreach($i in [0..10])
$i
#end
这时候好了,每个数字乖乖的在每一行呆着了。初步怀疑是#if指令引起的 但是也不能去掉#if啊。功能还是要实现的嘛。
2、在#if 指令结束后加上其他代码(有效)
#foreach($i in [0..10])
$i #if($velocityCount <= 10), #end someCode
#end
这也是ok的,换行符还在。 代码总不能随便加吧。
3、在#if 指令结束后加上其他注释(无效) 既然代码不能乱加,注释总是勉强可以加的吧。
#foreach($i in [0..10])
$i #if($velocityCount <= 10), #end ##someComment
#end
很遗憾~,这种方法无效……
4、加入额外的空行(有效,可行) 不能加代码,加注释又不行,那加一个空行总行了吧。
#foreach($i in [0..10])
$i #if($velocityCount <= 10), #end
#end
ok,算是采用指标不治本的方式算是解决了这个问题。
5、……
除了这些,还进行了若干个尝试。
三、结论
经过测试发现,除了#if指令会造成“吃掉行尾回车”以外,其他指令如#set等也会有这个情况。如果需要对生成的代码格式有精确的控制,那对模板代码的美观性和可读性上就要做一定的牺牲了。反之,则可以优先保证模板代码的美观。
四、延伸
又做了一些测试,发现除了某些指令会“吃掉行尾回车”以外,velocity在空白的处理上还有一些不尽如人意的地方: 1、#[[ 和 ]]# 指令后的回车,反而会留着,造成空行。
#[[
#foreach($i in [0..10])
$i
#end
]]#
这样的代码,渲染结果是:
(我是空行)
#foreach($i in [0..10])
$i
#end
(我是空行)
(第一行和第五行都是空行,由于代码高亮插件会自动把空行去掉,我就这么表示了)
2、指令前的空白不会被删除。
#foreach($i in [0..3])
#if(0 == 0)
$i
#end
#end
保证模板代码美观,这里采用了缩进。渲染结果是:
0
1
2
3
(我前面还有一个tab)
可以看到,用于保持模板代码美观的tab(或者空格)被渲染了出来。
3、……
可能(应该)还有其他的,等你来补充。
可能有人说,这算不上什么问题,但对我这种 有洁癖的码农来说。这也算是个不大不小的问题吧,另外在某些情况下,如果你不知道有这么回事,可能真的会影响生成出来的html代码空白结构,进而影响页面显示。