Custom Tags
You can extend Leaf to provide your own tags that add custom functionality. To demonstrate this, let’s look at a basic example by recreating #uppercase
together. This tag will take one argument, which is the string to uppercase.
When working with custom tags, there are four important things to know:
- You should call
requireParameterCount()
with the number of parameters you expect to receive. This will throw an error if your tag is used incorrectly. - If you do or do not require a body, you should use either
requireBody()
orrequireNoBody()
. Again, this will throw an error if your tag is used incorrectly. - You can read individual parameters using the
parameters
array. Each parameter will be of typeLeafData
, which you can convert to concrete data types using properties such as.string
,.dictionary
, and so on. - You must return a
Future<LeafData?>
containing what should be rendered. In the example below we wrap the resulting uppercase string in aLeafData
string, then send that back wrapped in a future.
Here’s example code for a CustomUppercase
Leaf tag:
import Async
import Leaf
public final class CustomUppercase: Leaf.LeafTag {
public init() {}
public func render(parsed: ParsedTag, context: LeafContext, renderer: LeafRenderer) throws -> Future<LeafData?> {
// ensure we receive precisely one parameter
try parsed.requireParameterCount(1)
// pull out our lone parameter as a string then uppercase it, or use an empty string
let string = parsed.parameters[0].string?.uppercased() ?? ""
// send it back wrapped in a LeafData
return Future(.string(string))
}
}
We can now register this Tag in our configure.swift
file with:
services.register { container -> LeafConfig in
// take a copy of Leaf's default tags
var tags = defaultTags
// add our custom tag
tags["customuppercase"] = CustomUppercase()
// find the location of our Resources/Views directory
let directoryConfig = try container.make(DirectoryConfig.self, for: LeafRenderer.self)
let viewsDirectory = directoryConfig.workDir + "Resources/Views"
// put all that into a new Leaf configuration and return it
return LeafConfig(tags: tags, viewsDir: viewsDirectory)
}
Once that is complete, you can use #customuppercase(some_variable)
to run your custom code.
Note: Use of non-alphanumeric characters in tag names is strongly discouraged and may be disallowed in future versions of Leaf.