Leaf は Swift の影響を受けたテンプレートエンジニアで、動的な HTML を生成することができます。
Leaf is a powerful templating language with Swift-inspired syntax. You can use it to generate dynamic HTML pages for a front-end website or generate rich emails to send from an API.
Webモードでプロジェクトを作成するとすぐに Leaf を使うことができます。
Vapor の環境構築やプロジェクト作成はこちら↓
Swift製Webフレームワーク Vaporの紹介2019
プロジェクトが作成されたら、まずは routes.swift
を確認してみましょう。
// "It works" page
router.get { req in
return try req.view().render("welcome")
}
// Says hello
router.get("hello", String.parameter) { req -> Future<View> in
return try req.view().render("hello", [
"name": req.parameters.next(String.self)
])
}
2つのルーティングが設定されています。
1つは トップページです。/
にアクセスすると it works! の文言とロゴが表示されます。
もう1つは /hello/{String}
です。 /hello
の後ろに文字列のパラメーターを入力すると、このルーティングにマッチします。
具体的には http://localhost:8080/hello/Kabigon
というアドレスにアクセスすると、 Hello, Kabigon!
と表示されます。
次に base.leaf
を見ていきます。
welcome.leaf
で base.leaf
を読み込み、title と body を埋め込んでいます。
base.leaf
hello.leaf
でも使われるベースとなるファイルで、ほぼ HTML です。
とっても簡単ですね。
<!DOCTYPE html>
<html>
<head>
<title>#get(title)</title>
<link rel="stylesheet" href="/styles/app.css">
</head>
<body>
#get(body)
</body>
</html>
#set("title") { It works }
#set("body") {
<div class="welcome">
<img src="/images/it-works.png">
</div>
}
#embed("base")
今回は Vapor を使って 2chまとめのまとめ の技術ブログ版のようなサイトを作ります。
まずは技術ブログのタイトルを表示してみようと思います。クックパッドさんとクラスメソッドさんの技術ブログが特に大好きなので、まずはその2つのサイトのブログ名を表示してみます。
2chmm.leaf
というファイルを作成します。blogs という文字列が入った配列を受け取り、blogs の要素数だけリストを表示します。
#set("title") { 技術ブログまとめ }
#set("body") {
<ul>
#for(blog in blogs) {
<li>#(blog)</li>
}
</ul>
}
#embed("base")
routes.swift
で 2chmm.leaf
に 文字列の入った blogs 配列を渡します。
これでブログ名を並べて表示することができました。
import Vapor
public func routes(_ router: Router) throws {
// 2chmm page
router.get { req -> Future<View> in
return try req.view().render("2chmm", [
"blogs": ["クックパッド開発者ブログ", "クラスメソッド発「やってみた」系技術メディア | Developers.IO"]
])
}
}
ただ、文字列だけでは使いづらいので、自分で定義した Struct を leaf 側に渡してみようと思います。
まずは Blog
という Struct を作成します。leaf に渡す Struct は Encodable プロトコルに準拠する必要があります。
struct Blog: Encodable {
let name: String
let url: String
}
import Vapor
public func routes(_ router: Router) throws {
// 2chmm page
router.get { req -> Future<View> in
return try req.view().render("2chmm", [
"blogs": [
Blog(name: "クックパッド開発者ブログ", url: "https://techlife.cookpad.com/"),
Blog(name: "クラスメソッド発「やってみた」系技術メディア | Developers.IO", url: "https://dev.classmethod.jp/")
]
])
}
}
#set("title") { 技術ブログまとめ }
#set("body") {
<ul>
#for(blog in blogs) {
<li>
<a href="#(blog.url)">#(blog.name)</a>
</li>
}
</ul>
}
#embed("base")
これで以下のような HTML が出力されます。
<!DOCTYPE html>
<html>
<head>
<title> 技術ブログまとめ </title>
<link rel="stylesheet" href="/styles/app.css">
</head>
<body>
<ul>
<li>
<a href="https://techlife.cookpad.com/">クックパッド開発者ブログ</a>
</li>
<li>
<a href="https://dev.classmethod.jp/">クラスメソッド発「やってみた」系技術メディア | Developers.IO</a>
</li>
</ul>
</body>
</html>