使用Play Framework 2,是否可能美化Scala模板?

19

我注意到在使用Play Framework 2时,渲染的Scala HTML模板不喜欢缩进的@if@for

因此,例如以下代码:

<ul>
   @for(test <- tests) {
      <li>@test.name</li>
   }
</ul>

会有额外的不必要的空格。为了修复它,我需要做类似这样的事情:

<ul>
@for(test <- tests) {
   <li>@test.name</li>
}
</ul>

如果有额外的@defining或其他语句,代码会变得混乱。

那么,有没有一种方法可以使Scala模板呈现更漂亮/美观,以摆脱多余的空格呢?

更新:

阅读这个帖子,我注意到由于模板顶部的参数,也会添加额外的空格和换行符。所以这个:

@(myParam: String)


<!DOCTYPE html>
<html>
   <head></head>
   <body></body>
</html>

在生成的HTML顶部会添加3个额外的换行符,这绝对很烦人。

该帖子似乎表示目前没有纠正此问题的选项。

5个回答

17

关于更多细节,我使用了@biesor的答案,并按照以下步骤进行:

将HtmlCompressor添加为插件

在Build.scala中:

val appDependencies = Seq(
    "com.googlecode.htmlcompressor" % "htmlcompressor" % "1.5.2"
)

PrettyController

public class PrettyController extends Controller {

    public static Results.Status ok(Content content) {
        return Results.ok(prettify(content)).as("text/html; charset=utf-8");        
    }

    public static Results.Status badRequest(Content content) {
        return Results.badRequest(prettify(content)).as("text/html; charset=utf-8");        
    }

    public static Results.Status notFound(Content content) {
        return Results.notFound(prettify(content)).as("text/html; charset=utf-8");      
    }

    public static Results.Status forbidden(Content content) {
        return Results.forbidden(prettify(content)).as("text/html; charset=utf-8");     
    }

    public static Results.Status internalServerError(Content content) {
        return Results.internalServerError(prettify(content)).as("text/html; charset=utf-8");       
    }

    public static Results.Status unauthorized(Content content) {
        return Results.unauthorized(prettify(content)).as("text/html; charset=utf-8");      
    }

    private static String prettify(Content content) {
        HtmlCompressor compressor = new HtmlCompressor();
        String output = content.body().trim();

        if (Play.isDev()) {
            compressor.setPreserveLineBreaks(true);
        }

        output = compressor.compress(output);

        return output;
    }
}

那么每个控制器都应该扩展PrettyController


我喜欢这个,避免了DRY违规,也许你可以在Github上为其他人创建一个示例应用程序? - biesior
4
我在想是否可以在编译时完成这个操作,这样漂亮版本的代码就会嵌入到生成的类中,而不是每次请求时都需要进行美化处理。 - monzonj

8

我已经发布了一个适用于Play 2.1的Google HTML压缩插件。你可以在GitHub上找到它。


这对我很有效,谢谢。我为Play 2.2.1贡献了一个升级。 - Fernando Correia
非常棒的插件。配置简单,与GZIP过滤器兼容性良好。 - Gavin

4
当然总有一些选择:裁剪正文并重新设置标题,这样操作字符串后它将以text/plain格式返回。
// instead of
return ok(index.render("some"));

// use
return ok(index.render("some").body().trim()).as("text/html; charset=utf-8");

对于“优雅”的循环或条件语句,您需要编写更紧凑的代码。

// instead of
@for(test <- tests) {
  <li>@test.name</li>
}

// use
@for(test <- tests) {<li>@test.name</li>}

最后,您可以使用一些压缩器(例如com.googlecode.htmlcompressor)来压缩整个页面(在此示例中仅适用于生产模式)。

String output = index.render("some").body().trim();
if (Play.isProd()) output = compressor.compress(output);
return ok(output).as("text/html; charset=utf-8");

有趣,你会如何为每个调用执行此操作?更改每个控制器的每个请求? - Romain Piel
在Play 2.1中,有一个过滤器(https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/mvc/Filters.scala)机制,这将是解决此问题的完美方案。但它非常复杂,您必须使用Iteratee API而不是String...我几天前尝试过,但对我来说太复杂了! - Julien Lafont
@RomainPiel 是的,但这是问题吗?在现有项目中,它是从剪贴板粘贴的。你有多少返回HTML的操作?20?30?只需要5分钟的工作。 - biesior
1
@RomainPiel 你可以使用辅助方法,或者重写 Ok - lambdas

1
我原本期望得到真正“美化”HTML输出的答案,即除了删除空行之外,还能正确缩进输出。然而,HtmlCompressor只是压缩输出,并没有美化输出的逻辑。
我想出了一个解决方案,在生产中使用HtmlCompressor进行压缩,在开发过程中使用Jsoup进行美化输出。我不关心显式调用prettify转换,所以我的解决方案如下:
// required extra imports
import play.twirl.api.Html
import com.googlecode.htmlcompressor.compressor.HtmlCompressor
import org.jsoup.Jsoup
import org.jsoup.parser.Parser

@Singleton
class MyController @Inject() (environment: Environment) extends Controller {

  /** Helper to format Html */
  def prettify(content: Html): Html = {
    val rawString = content.body.trim()
    val html = environment.mode match {
      case Mode.Dev =>
        val doc = Jsoup.parse(rawString, "", Parser.xmlParser())
        doc.outputSettings().indentAmount(2)
        Html(doc.toString())
      case _ =>
        val compressor = new HtmlCompressor()
        compressor.setPreserveLineBreaks(true)
        Html(compressor.compress(rawString))
    }
    html
  }

  /** example usage */
  def index = Action {
    Ok(prettify(views.html.index))
  }

}  

在开发模式下,这将生成一些格式良好的HTML。
所需更改的build.sbt如下:
libraryDependencies += "org.jsoup" % "jsoup" % "1.10.2"
libraryDependencies += "com.googlecode.htmlcompressor" % "htmlcompressor" % "1.5.2"

0
回应bluenote10的答案,我创建了以下内容,它不需要第三方库依赖。将其集成到过滤器中会很好,但今天我不确定如何正确地做到这一点。
import play.twirl.api.Html

/** Helper to format Html */
def prettify(content: Html): Html = {
  Html(content.body.trim().replaceAll("\\n\\s*\\n", "\n"))
}

def index = Action { implicit request =>
  Ok(prettify(views.html.index()))
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接