+ override fun plainText() = games
+ .sortedWith(comparing(FreeGame::startDate).thenBy(FreeGame::title))
+ .joinToString("\n") { game ->
+ "${game.title}: ${"%tF %<tT".format(game.startDate.atZone(timezone))} - ${"%tF %<tT".format(game.endDate.atZone(timezone))} (${game.imageUrl})"
+ }
+
+ override fun htmlText() = createHTMLDocument().html {
+ head {
+ style("text/css") {
+ unsafe {
+ raw(
+ """
+ .game { display: inline-grid; width: 200px; height: 350px; grid-template-rows: 0fr 1fr 0fr 0fr; font-family: 'Recursive Sans Linear Static', Roboto, serif; color: white; text-shadow: 2px 2px black; margin: 0 1ex 1ex 0; }
+ .game .game-image { grid-area: 1/1/5/2; }
+ .game .game-image img { object-fit: cover; width: 100%; height: 100%; }
+ .game .game-title { grid-area: 1/1/2/2; padding: 1ex; font-size: 150%; font-weight: bold; }
+ .game .game-start { grid-area: 3/1/4/2; padding: 1ex 1ex 0ex 1ex; }
+ .game .game-end { grid-area: 4/1/5/2; padding: 0ex 1ex 1ex 1ex; }
+ """
+ )
+ }
+ }
+ }
+ body {
+ div("games") {
+ games
+ .sortedWith(comparing(FreeGame::startDate).thenBy(FreeGame::title))
+ .forEach { game ->
+ div("game") {
+ div("game-image") {
+ img(src = game.imageUrl)
+ }
+ div("game-title") {
+ +game.title
+ }
+ div("game-start") {
+ +"%tF %<tT".format(game.startDate.atZone(timezone))
+ }
+ div("game-end") {
+ +"%tF %<tT".format(game.endDate.atZone(timezone))
+ }
+ }
+ }
+ }
+ }
+ }.serialize(prettyPrint = true)