-
-
-
-
-
-
-
Warning
-
This section may contain outdated information.
-
-Leaf
-Welcome to Leaf. Leaf's goal is to be a simple templating language that can make generating views easier. There are plenty of great templating languages, so use what's best for you -- maybe that's Leaf! The goals of Leaf are:
-
-- Small set of strictly enforced rules
-- Consistency
-- Parser first mentality
-- Extensibility
-
-Syntax
-Structure
-Leaf Tags are made up of 4 Elements:
- - Token: # is the Token
- - Name: A string that identifies the tag
- - Parameter List: () May accept 0 or more arguments
- - Body (optional): {} Must be separated from the Parameter List by a space
-There can be many different usages of these 4 elements depending on the Tag's implementation. Let's look at a few examples of how Leaf's built-in Tags might be used:
-
-#()
-#(variable)
-#import("template")
-#export("link") { <a href="#()"></a> }
-#index(friends, "0")
-#loop(friends, "friend") { <li>#(friend.name)</li> }
-#raw() { <a href="#raw">Anything goes!@#$%^&*</a> }
-
-Using the # token in HTML
-The # token cannot be escaped. Use the #() or #raw() {} Tag to output a # in a Leaf Template. #() => #
-Raw HTML
-All Leaf output is escaped by default. Use the #raw() {} Tag for unescaped output.
-#raw() { <a href="#link">Link</a> } => <a href="#link">Link</a>
-
-IMPORTANT! Make sure you are not using the #raw() {} Tag with user input.
-
-Chaining
-The double token: ## indicates a chain. It can be applied to any standard Tag. If the previous Tag fails, the chained Tag will be given an opportunity to run.
-#if(hasFriends) ##embed("getFriends")
-
-
-
-
-Token: #()
-#() #()hashtags #()FTW => # #hashtags #FTW
-
-
-
-Raw: #raw() {}
-#raw() {
- Do whatever w/ #'s here, this code won't be rendered as leaf document and is not escaped.
- It's a great place for things like Javascript or large HTML sections.
-}
-
-
-
-Equal: #equal(lhs, rhs) {}
-#equal(leaf, leaf) { Leaf == Leaf } => Leaf == Leaf
-#equal(leaf, mustache) { Leaf == Mustache } =>
-
-
-
-Variable: #(variable)
-
-
-
-Loop: #loop(array, "item") {}
-#loop(friends, "friend") {
- #(offset). #(friend.name)
-}
-
-
-
-The body of a #loop can access an index variable corresponding to the index of the array. There is also an offset variable which is the index plus 1.
-Index: #index(array, _ index: String)
-Hello, #index(friends, "0")!
-Hello, #index(friends, "best")!
-
-
-
-Note: array indexes are always strings.
-If - Else: #if(bool) ##else() { this }
-#if(entering) {
- Hello, there!
-} ##if(leaving) {
- Goodbye!
-} ##else() {
- I've been here the whole time.
-}
-
-
-
-Note that #if requires a boolean variable. If you need to do a comparison then #equal is more appropriate. You can chain #equal in the same way as #if:
-#equal(state, "0") {
- <span class="green">Normal</span>
-} ##equal(state, "1") {
- <span class="orange">Warning</span>
-} ##else() {
- <span class="red">Alert</span>
-}
-
-
-
-Import: #import("template")
-Export: #export("template") { Leaf/HTML }
-Extend: #extend("template")
-Embed: #embed("template")
-
-When using these Layout Tags, omit the template file's .leaf extension.
-
-/// base.leaf
-<!DOCTYPE html>
-#import("html")
-
-/// html.leaf
-#extend("base")
-
-#export("html") { <html>#embed("body")</html> }
-
-/// body.leaf
-<body></body>
-
-
-
-Leaf renders html.leaf as:
-<!DOCTYPE html>
-<html><body></body></html>
-
-
-
-
-Look at the existing tags for advanced scenarios, let's look at a basic example by creating Index together. This tag will take two arguments, an array, and an index to access.
-class Index: BasicTag {
- let name = "index"
-
- func run(arguments: [Argument]) throws -> Node? {
- guard
- arguments.count == 2,
- let array = arguments[0].value?.nodeArray,
- let index = arguments[1].value?.int,
- index < array.count
- else { return nil }
- return array[index]
- }
-}
-
-
-
-We can now register this Tag in our main.swift file with:
-if let leaf = drop.view as? LeafRenderer {
- leaf.stem.register(Index())
-}
-
-
-
-And use it just like we did above.
-
-Note: Use of non-alphanumeric characters in Tag Names is strongly discouraged and may be disallowed in future versions of Leaf.
-
-Syntax Highlighting
-Atom
-language-leaf by ButkiewiczP
-Xcode
-It is not currently possible to implement Leaf Syntax Highlighting in Xcode, however, using Xcode's HTML Syntax Coloring can help a bit. Select one or more Leaf files and then choose Editor > Syntax Coloring > HTML. Your selected Leaf files will now use Xcode's HTML Syntax Coloring. Unfortunately the usefulness of this is limited because this association will be removed when vapor xcode is run.
-There appears to be a way to make Xcode file associations persist but that requires a bit more kung-fu.
-VS Code
-html-leaf by FranciscoAmado
-CLion & AppCode
-Some preliminary work has been done to implement a Leaf Plugin for CLion & AppCode but lack of skill and interest in Java has slowed progress! If you have IntelliJ SDK experience and want to help with this, message Tom Holland on Vapor Slack
-
-
-
-
-
-
-
-