22

我有一个名为 render_something 的方法,它可以创建很多空格,例如:

<a href="#">#render_something('xxx')</a>

结果可以是:

<a href="#">     

           something that generate from redner_something


              </a> 

实际上我希望它是这样的:

<a href="#">something that generate from redner_something</a>

速度有这样的东西吗?

#trim(#render_something('xxx'))
4

8 回答 8

16

我刚刚阅读了有关Velocity Whitespace Gobbling的这篇文章,其中提出了一些解决方法,包括Velocity Whitespace 被 Line Comment 截断

这基本上建议通过在每行末尾添加注释来注释掉换行符。它还建议不要在宏中缩进代码以防止出现多余的(我最喜欢的词之一)空格。

TBH 这不是一个很好的解决方案,但可能适合您的需求。只需放在##宏中每一行的末尾,这会让事情变得更好......有点

于 2011-12-23T11:49:39.613 回答
8

似乎只是 java native trim() 有效。

$someValue.trim()为我工作

于 2013-02-27T12:10:06.300 回答
2

解决方案

在创建 VelocityEngine 的类中,添加如下方法

public String trim(String str) {
    return str.trim()/*.replace("\n", "").replace("\r", "")*/;
}

然后将以下内容添加到您创建的 VelocityContext 中:

    context.put("trimmer", this);

最后在速度模板中执行以下操作

<a href="#">$trimmer.trim("#render_something('xxx')")</a>

为什么它有效?

尽管 Velocity 的行为已明确定义,但有时要了解它的工作原理可能有点棘手。单独的 trim() 方法对于将 char-sequence 从模板获取到 Java 方法中是必要的,您可以在其中调用 String 上的实际 trim()。据我所知,Velocity 内部没有修剪,但你总是可以用像这样的技巧回调 Java。

双引号是必要的,因为 #render_something 只是一个宏,而不是函数调用,这意味着宏中语句的结果被逐字放入宏被“执行”的位置。

于 2011-12-23T00:34:04.607 回答
2

我挣扎了一段时间才找到一个简单的解决空格吞噬的方法,所以我终于想出了一个。它的灵感来自 Vadzim 的回答和这个页面http://wiki.apache.org/velocity/StructuredGlobbingResourceLoader

我们可以在网站上找到的 StructuredGlobbingResourceLoader 具有复杂的行为,并且没有消除任何类型的空格,因此我对其进行了修改以获得简单的行为:“删除行首的任何空格,并在每行的结尾”(防止换行评估)。过滤器在加载时应用于输入流。

这种速度模板

#if($value)
    the value is $value
#end

被转化为

#if($value)##
the value is $value##
#end##

然后,如果你想有换行符或行首空格,你必须像 Vadzim 解释的那样在你的上下文中 put($br,"\n") 和 put($sp," ") 并在你的模板中明确使用它们. 这种做法将允许您保留缩进的模板,并最大限度地控制。

从此页面获取类http://wiki.apache.org/velocity/StructuredGlobbingResourceLoader 将扩展类更改为您需要的加载器类型(这个使用 webapp 加载器)用我提供的代码替换 read() 方法使用该类作为您的属性中的资源加载器。webapp 加载器示例:webapp.resource.loader.class=...StructuredGlobbingResourceLoader

public int read() throws IOException {        
    int ch;
    switch(state){
        case bol: //beginning of line, read until non-indentation character
            while(true){
                ch = in.read();
                if (ch!=(int)' ' && ch!=(int)'\t'){
                    state = State.content;
                    return processChar(ch);
                }
            }

        case content:
            ch = in.read();
            return processChar(ch);

        //eol states replace all "\n" by "##\n"
        case eol1: 
            state = State.eol2;
            return (int)'#';

        case eol2:
            state = State.bol;
            return (int)'\n';

        case eof: 
            return -1;
    }
    return -1;
}

//Return the normal character if not end of file or \n
private int processChar(int ch){
    switch(ch){
    case -1:
        state = State.eof;
        return -1;
    case (int)'\n':
        state = State.eol1;
    return (int)'#';
    default:
        return ch;
    }
}

欢迎对我的实施提供任何反馈

于 2015-05-14T02:47:13.187 回答
2

受到Velocity Whitespace 被行注释截断的启发,可以使用块注释而不是行注释来获得更好看的结果:

#foreach( $record in $records )#**
    *##if( $record.id == 0 )#**
    *##end
#end

用一个体面的语法突出注释并不是很突兀。

于 2018-08-09T08:14:43.730 回答
1

这是我对速度空白吞噬的替代解决方案,它允许制表模板结构。

每个模板文本在首次加载时都会在 custom 中进行预处理ResourceLoader

private String enhanceTemplate(String body) {
    if (!body.startsWith("##preserveWhitespace")) {
        body = body.replaceAll("(##.*)?[ \\t\\r]*\\n+[ \\t\\r]*", Matcher.quoteReplacement("##\n"));
        body = body.trim();
    }
    return body;
}

这仅用一个注释换行符替换所有新行和调整空格。

可以使用默认上下文中的 $br 和 $sp 变量显式插入换行符和尾随空格:

private static final VelocityContext DEFAULT_CONTEXT = new VelocityContext(new HashMap<String, String>() {{
    put("sp", " ");
    put("br", "\n");
}});
于 2012-09-18T16:33:01.733 回答
1

在某些情况下,我不得不像 js 或 css 一样将我的脚本最小化。它运作良好,尽管人类阅读起来并不容易。消除多余空间的另一种选择:

<ul class="tabs">#foreach($par in $bodypars)#set( $parLen = ${_MathTool.toInteger($bodypars.size())} )#set( $parLn = $parLen - 1 )#set( $thClass = 'tb'+${parLn} )#set( $thaClass = '' )#if( $foreach.index == 1 )#set( $thClass = ${thClass}+' selected' )#set( $thaClass = ' selected' )#end#if($foreach.index != 0 && $parLen <= $maxTabs)#set ( $btitle = $_XPathTool.selectSingleNode($par,'item-subtitle') )<li class="${thClass}">#if($!btitle && $btitle != '')<a href="#" class="#cleanString($btitle.value.toLowerCase())${thaClass}">$_SerializerTool.serialize($btitle, true)</a>#end</li>#end#end</ul>
于 2015-05-27T13:48:24.547 回答
0

您可以使用标准的 java trim,注意您的变量是否是对象而不是字符串。

$string.trim()  //work fine
$object.trim()  //exception

祝你有美好的一天!

于 2020-09-02T13:51:14.053 回答