Skip to content

Getting Started with Template Kit

Template Kit (vapor/template-kit) is a framework for implementing templating languages in Swift. It is currently used to power Leaf (vapor/leaf) and hopefully more languages in the future.

Template Kit is designed to make implementing a templating language easy by defining a common template structure and handling the entire serialization step.

Warning

These docs are for developers interested in implementing a templating language using Template Kit. See Leaf → Getting Started for information about using Leaf.

Vapor

This package is included with Vapor and exported by default. You will have access to all TemplateKit APIs when you import Vapor.

import Vapor

Standalone

The Template Kit package is lightweight, pure-Swift, and has very few dependencies. This means it can be used as a templating framework for any Swift project—even one not using Vapor.

To include it in your package, add the following to your Package.swift file.

// swift-tools-version:4.0
import PackageDescription

let package = Package(
    name: "Project",
    dependencies: [
        ...
        .package(url: "https://github.com/vapor/template-kit.git", from: "1.0.0"),
    ],
    targets: [
      .target(name: "Project", dependencies: ["TemplateKit", ... ])
    ]
)

Use import TemplateKit to access the APIs.

Overview

Let's take a look at how Leaf uses Template Kit to render views.

Assume we have a template greeting.leaf with the following contents:

Hello, #capitalize(name)!

This first step in rendering this view is to parse the syntax into an abstract syntax tree (AST). This is the part of view rendering that Leaf is responsible for, since Leaf has a unique syntax.

Leaf does this by creating a LeafParser that conforms to TemplateParser.

greeting.leaf -> LeafParser -> AST

In code, this looks like:

func parse(scanner: TemplateByteScanner) throws -> [TemplateSyntax]

The AST for our example greeting.leaf file would look something like this:

[
    .raw(data: "Hello. "), 
    .tag(
        name: "capitalize", 
        parameters: [.identifier("name")]
    ),
    .raw(data: "!"), 
]

Now that Leaf has created an AST, it's job is done! Template Kit will handle converting this AST into a rendered view. All it needs is a TemplateData to use for filling in any variables.

let data = TemplateData.dictionary(["name": "vapor"])

The above data will be combined with the AST and used by the TemplateSerializer to create a rendered view.

AST + Data -> TemplateSerializer -> View

Our rendered view will look something like:

Hello, Vapor!

All of these steps are handled by LeafRenderer which conforms to TemplateRenderer. A template renderer is simply an object that contains both a parser and a serializer. When you implement one, you will get several helpful extensions from Template Kit for free that help load files and cache parsed ASTs. It's what the end user will use to render views.

The entire pipeline looks like this:

                            LeafRenderer
                                 |
|----------------------------------------------------------------|
 greeting.leaf -> LeafParser -> AST -> TemplateSerializer -> View
                                 ^
                                /
                   TemplateData

In code, the method looks like this:

public func render(_ path: String, _ context: TemplateData) -> Future<View>

Check out Template Kit's API docs for detailed information about all of the protocols, structs, and classes Template Kit offers.