18

Korzystanie z Play Framework 2 Zauważyłem, że renderowane szablony Scala HTML nie lubią wciętych @if lub @for.Czy można upiększyć szablony scala za pomocą gry framework 2?

Tak więc, na przykład coś takiego:

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

Will narzucają niepotrzebne spacje. Aby to naprawić, muszę zrobić coś takiego:

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

Który będzie bałagan z dodatkowymi @defining lub innych sprawozdań.

Czy istnieje sposób na upiększenie/upiększenie renderowania szablonów Scala, aby pozbyć się dodatkowych białych znaków?

UPDATE:

Reading this thread Zauważyłem dodatkowe spacje i znaki końca linii są dodawane jak również ze względu na parametry na szczycie szablonów. Tak więc:

@(myParam: String) 


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

doda 3 dodatkowe znaki podziału wiersza nad wynikowym HTML. Co jest zdecydowanie denerwujące.

Wątek wydaje się mówić, że obecnie nie ma opcji, aby to poprawić.

Odpowiedz

16

więc więcej szczegółów Użyłem @biesor odpowiedź i przeszedł kroki:

Dodaj HtmlCompressor jako plugin

W 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; 
    } 
} 

Następnie każdy kontroler powinien przedłużyć PrettyController.

+0

Podoba mi się to, unikając DRY violation, może mógłbyś stworzyć przykładową aplikację dla innych na Githubie? – biesior

+3

Zastanawiam się, czy można to zrobić w czasie kompilacji, więc ładną wersją jest ta osadzona w wynikowej klasie, zamiast konieczności upiększania jej przy każdym żądaniu. – monzonj

4

Oczywiście zawsze istnieje kilka opcji :), przyciąć ciało i ponownie ustawić nagłówek SO (przyczyna po operacjach na ciąg zostanie on zwrócony jako text/plain):

// instead of 
return ok(index.render("some")); 

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

dla „urody” pętle lub jeśli to trzeba napisać bardziej zwarty kod

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

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

I wreszcie można użyć jakiś kompresor (tj. com.googlecode.htmlcompressor) do ... cały minify strony (w tym próbki do tylko w trybie produkcyjnym)

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

ciekawe, jak zrobiłbyś to przy każdym połączeniu? zmieniając każde żądanie dla każdego kontrolera? –

+0

W wersji 2.1 znajduje się mechanizm Filter (https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/mvc/Filters.scala), który będzie idealnym rozwiązaniem, aby to zrobić. Ale to bardzo skomplikowane, musisz pracować z Iteratee API zamiast String ... Próbowałem kilka dni temu, ale zbyt skomplikowane dla mnie! –

+0

@RomainPiel Tak, ale czy to jest problem? w istniejącym projekcie wkleja się ze schowka. Ile akcji zwraca kod HTML? 20? 30, 5 minut pracy. – biesior

8

Wydałem wtyczkę Google HTML Compressor dla Play 2.1. Można go znaleźć na GitHub.

+0

To zadziałało dobrze, dzięki. Przekazałem aktualizację do Play 2.2.1. –

+0

Bardzo duża wtyczka. Łatwa konfiguracja i działa dobrze z filtrem GZIP. – Gavin

1

Spodziewałem się odpowiedzi, które naprawdę "upiększają" dane wyjściowe HTML, w sensie prawidłowego wcięcia wyjścia oraz usuwania pustych linii. Jednak HtmlCompressor kompresuje tylko dane wyjściowe i nie ma ładnej logiki drukowania.

Wpadłem na rozwiązanie, które wykorzystuje zarówno HtmlCompressor dla kompresji w produkcji, jak i Jsoup dla ładnego drukowania podczas tworzenia. Nie dbam o wywołanie konwersji prettify wyraźnie, więc moje rozwiązanie wygląda tak:

// 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)) 
    } 

} 

W trybie dev ten wytwarza pewną ładnie sformatowany HTML.

Wymagane zmiany build.sbt są:

libraryDependencies += "org.jsoup" % "jsoup" % "1.10.2" 
libraryDependencies += "com.googlecode.htmlcompressor" % "htmlcompressor" % "1.5.2" 
0

Powtarzając na odpowiedź bluenote10 za stworzyłem następujące, nie wymaga libraryDependecies osób trzecich. Byłoby miło zintegrować go z filtrem, niestety nie jestem pewien, jak to zrobić dzisiaj poprawnie.

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())) 
}