テンプレート#
jimble のテンプレートは jte です。 文字列を実行時に解釈するのではなく、Java にコンパイルします。
get("/", context -> {
context.response().putData("title", "ブログ");
context.response().putData("posts", listPosts());
context.response().view("blog/posts.jte");
});
putData() で入れたものが Data として渡り、view() でテンプレート名を指定します。
テンプレート側#
src/main/jte/blog/posts.jte:
@import db.blog_example.table.post.Post
@import io.jimble.util.data.Data
@import java.util.List
@param Data data
!{List<Data> posts = data.getDataList("posts");}
<h1>${data.getString("title")}</h1>
@for(Data post : posts)
<b>${post.getString(Post.title)}</b>
<p>${post.getString(Post.body)}</p>
@endfor
${ }は HTML エスケープされます。生で出すには$unsafe{ }を使います@paramと@importがあるので、テンプレートの中でも型が効きますPost.titleのようなColumnで引けるので、テンプレートに文字列のキーを撒かずに済みます
枠を共有する#
ページごとに <html> から書くと、ヘッダを直すのに全部を直すことになります。
枠は1枚のレイアウトに閉じ込めて、ページは中身だけを書きます。
src/main/jte/layout/page.jte:
@import gg.jte.Content
@import io.jimble.util.data.Data
@param Data data
@param Content content
<!doctype html>
<html lang="ja">
<head>
<title>${data.getString("title")}</title>
<link rel="stylesheet" href="/assets/app.css">
</head>
<body>
@template.tag.nav(current = data.getString("nav"))
<main>${content}</main>
</body>
</html>
src/main/jte/pages/home.jte:
@import io.jimble.util.data.Data
@param Data data
@template.layout.page(data = data, content = @`
<p>ここが中身です。</p>
`)
Content が「あとで描くもの」です。@ とバッククォートで囲んだかたまりを渡すと、
レイアウトの ${content} の位置に入ります。
呼び出し名はディレクトリ構成そのままです。
src/main/jte/layout/page.jte なら @template.layout.page(...)、
src/main/jte/tag/nav.jte なら @template.tag.nav(...)。
部品#
同じ仕組みで、使い回す部品も作れます。
src/main/jte/tag/card.jte:
@import gg.jte.Content
@param String title
@param Content body
@param String note = ""
<section class="card">
<h2>${title}</h2>
${body}
@if(!note.isEmpty())
<p class="note">${note}</p>
@endif
</section>
@paramには既定値を書けます(= "")。書かなければ呼ぶ側は省略できます- 部品は
Dataではなく、必要なものだけを受け取るほうが使い回せます。Dataを渡すと、呼ぶ側が「どのキーが要るのか」をテンプレートの中身を読まないと分かりません
実際に動いているものは examples/approval-pages にあります。
こつ
エラー画面もレイアウトを共有してください。 共有していないと、404 のときだけ見た目の違うサイトになります。
コメント#
jte のコメントは <%-- と --%> です。
<%-- ここはコメント。出力に出ません --%>
[!WARNING]
@*と*@で囲む書き方はコメントになりません。 そのまま出力され、しかも中に書いた@template.は実行されます。 レイアウトの中に、そのレイアウト自身の呼び出し例をコメントのつもりで書くと、 無限再帰してStackOverflowErrorになります(実際に踏みました)。**コメントは入れ子にできません。**閉じの記号を説明文の中に書くと、そこで終わります。
HTML のコメント(
<!-- -->)も既定では出力から消えます。 ブラウザや外の道具に残したい印は、テンプレートではなく静的ファイル側に置いてください。
ビルド#
io.jimble.jte プラグインを入れると、compileJava の前に
src/main/jte を Java に変換します。
plugins {
application
id("io.jimble.jte")
}
テンプレートの間違いはビルドで落ちます。 実行時に404を見てから気づくことはありません。
設定できることは Gradle プラグイン にあります。
コンパイラ(gg.jte:jte)はビルドのときだけ使い、
アプリの実行時クラスパスには gg.jte:jte-runtime しか入りません。
ホットリロード#
./gradlew jimbleRun で起動していれば、.jte を直した時点で
変換とビルドが走り、次のリクエストで反映されます。