A fast CSS demo challenge
The very first step is so as to add Leaf as a dependency to your challenge. You must notice that Leaf 4 just isn’t completed but and these model new options are solely accessible from the tau pre-release.
import PackageDescription
let package deal = Bundle(
identify: "myProject",
platforms: [
.macOS(.v10_15)
],
dependencies: [
.package(url: "https://github.com/vapor/vapor", from: "4.32.0"),
.package(url: "https://github.com/vapor/leaf", .exact("4.0.0-tau.1")),
.package(url: "https://github.com/vapor/leaf-kit", .exact("1.0.0-tau.1.1")),
],
targets: [
.target(name: "App", dependencies: [
.product(name: "Leaf", package: "leaf"),
.product(name: "Vapor", package: "vapor"),
]),
.goal(identify: "Run", dependencies: ["App"]),
.testTarget(identify: "AppTests", dependencies: [
.target(name: "App"),
.product(name: "XCTVapor", package: "vapor"),
])
]
)
We’re able to import Leaf
in your Swift recordsdata, since there’s a new LeafFileMiddleware
accessible as a part of Leaf we will create some publicly accessible template recordsdata and use this middleware to render them. Create a brand new Public
listing inside the basis folder of the challenge and place an new index.html
file there. You can too use a .leaf
extension, however for the sake of simplicity (and Xcode syntax highlighting causes) we will use the .html
extension this time.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta identify="viewport" content material="width=device-width, initial-scale=1">
<title>#(title)</title>
<hyperlink rel="stylesheet" href="/css/type.css">
</head>
<physique>
<header>
<h1>#(title)</h1>
</header>
</physique>
</html>
Fairly primary HTML5 boilerplate code, besides that we’ll print the title utilizing a Leaf tag. We’ll set a price for this context variable by way of some Swift code in a second. Within the head part we additionally import our css/type.css
stylesheet file. Now you must create a css
folder contained in the Public listing and place a type.css
file within it.
* {
margin: 0;
padding: 0;
}
physique {
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Helvetica", "Segoe UI", Roboto, Ubuntu;
font-size: 16px;
line-height: 1.4em;
background: #(background);
}
h1 {
padding: #(padding);
}
@media (max-width: 599px) {}
@media (min-width: 600px) {}
@media (min-width: 900px) {}
@media (min-width: 1200px) {}
@media (min-width: 1800px) {}
Since this file is “secretly” a leaf template file we will use the #(variable)
syntax to print out values. We’re going to go a background
coloration key and a padding
key with some customized values as context variables.
Now let me present you how one can configure this new LeafFileMiddleware, so we will render each our html and css templates.
import Vapor
import Leaf
public func configure(_ app: Software) throws {
if !app.setting.isRelease {
LeafRenderer.Possibility.caching = .bypass
}
LeafFileMiddleware.defaultMediaType = .html
LeafFileMiddleware.processableExtensions = ["leaf", "html", "css", "js"]
LeafFileMiddleware.contexts = [
.css: [
"background": "#eee",
"padding": "16px",
],
.html: [
"title": "Hello world!"
],
]
if let lfm = LeafFileMiddleware(publicDirectory: app.listing.publicDirectory) {
app.middleware.use(lfm)
}
app.views.use(.leaf)
}
First we disable the cache, however that is a fairly apparent chunk of code, subsequent we set the default media kind to html. This shall be used to set the Content material-Kind
header if the file extension within the request is an unknown kind. The processableExtensions
property will inform the LeafFileMiddleware to course of and render solely these recordsdata, every part else with a special extension shall be streamed identical to whenever you use a daily FileMiddleware
.
As you possibly can see we will set totally different context values for particular media sorts, in our case all of the css recordsdata can use the background and padding properties and each html file can benefit from the title context variable. It is usually doable to set them by way of a subscript syntax:
LeafFileMiddleware[.css] = [
"background": "green",
"padding": "16px",
]
LeafFileMiddleware[.html] = [
"title": "Hello world!"
]
The final step is to create the precise middleware with a publicDirectory
argument. This listing is the situation the place the system will search for publicly accessible recordsdata and if wanted they are often processed as common Leaf templates. You can too setup listing indexing by way of the LeafFileMiddleware, however that is a special matter.
For those who navigate to the http://localhost:8080/index.html
deal with you must see your rendered index.html file with the proper stylesheet utilized to it. In fact you possibly can register a customized route and render your templates utilizing the same old Assets / Views location if wanted, however I simply wished to point out you this cool trick, because it permits us to serve public recordsdata utilizing a extra dynamic strategy.