Add more information about the syntax to the README
This commit is contained in:
parent
9b15d2a7dd
commit
a942ceae20
149
README.md
149
README.md
@ -7,6 +7,26 @@ Salix (pronounced *say-lix*) is a Go templating engine inspired by [Leaf](https:
|
|||||||
|
|
||||||
Salix's syntax is similar to Leaf and (in my opinion at least), it's much more fun to write than the Go template syntax. If you like this project, please star the repo. I hope you enjoy! :)
|
Salix's syntax is similar to Leaf and (in my opinion at least), it's much more fun to write than the Go template syntax. If you like this project, please star the repo. I hope you enjoy! :)
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Template](#template)
|
||||||
|
- [API Usage](#api-usage)
|
||||||
|
- [Tags](#tags)
|
||||||
|
- [Creating custom tags](#creating-custom-tags)
|
||||||
|
- [`for` tag](#for-tag)
|
||||||
|
- [`if` tag](#if-tag)
|
||||||
|
- [`include` tag](#include-tag)
|
||||||
|
- [`macro` tag](#macro-tag)
|
||||||
|
- [Functions](#functions)
|
||||||
|
- [Global Functions](#global-functions)
|
||||||
|
- [Adding Custom Functions](#adding-custom-functions)
|
||||||
|
- [Expressions](#expressions)
|
||||||
|
- [Ternary Expressions](#ternary-expressions)
|
||||||
|
- [Coalescing operator](#coalescing-operator)
|
||||||
|
- [The `in` operator](#the-in-operator)
|
||||||
|
- [Acknowledgements](#acknowledgements)
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Template
|
### Template
|
||||||
@ -49,11 +69,100 @@ if err != nil {
|
|||||||
|
|
||||||
See the [examples](examples) directory for more examples.
|
See the [examples](examples) directory for more examples.
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
|
||||||
|
In Salix, tags have full control over the Abstract Syntax Tree (AST), which allows them to do things the language wouldn't ordinarily allow. Salix's if statements, for loops, macros, includes, etc. are implemented as tags.
|
||||||
|
|
||||||
|
### Creating custom tags
|
||||||
|
|
||||||
|
You can extend the capabilities of Salix by creating custom tags. To create a custom tag, you need to implement the `salix.Tag` interface and add it to the tag map of your template or namespace using the `WithTagMap` method.
|
||||||
|
|
||||||
|
Salix tags follow a distinctive syntax pattern. They start with a pound sign (`#`), followed by a name and optional arguments. Tags can also enclose a block of content, and if they do, the block is terminated by an end tag with the same name. Here's an example of a template with both a `macro` tag and an `include` tag:
|
||||||
|
|
||||||
|
```
|
||||||
|
#macro("example"):
|
||||||
|
Content
|
||||||
|
#!macro
|
||||||
|
|
||||||
|
#include("template.html")
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example:
|
||||||
|
|
||||||
|
- The `macro` tag has a block, indicated by the content enclosed between `#macro("example"):` and `#!macro`.
|
||||||
|
- The `include` tag doesn't have a block; it simply includes the content of `template.html`.
|
||||||
|
|
||||||
|
### `for` tag
|
||||||
|
|
||||||
|
Salix's `for` tag is used for iterating over slices, arrays, and maps. It can assign one or two variables depending on your needs. When using a single variable, it sets that variable to the current element in the case of slices or arrays, or the current value for maps. With two variables, it assigns the first to the index (in the case of slices or arrays) or the key (for maps), and the second to the element or value, respectively. Here's an example of the for tag in action:
|
||||||
|
|
||||||
|
```
|
||||||
|
#for(id, name in users):
|
||||||
|
Name: #(name)
|
||||||
|
ID: #(id)
|
||||||
|
#!for
|
||||||
|
```
|
||||||
|
|
||||||
|
### `if` tag
|
||||||
|
|
||||||
|
The `if` tag in Salix allows you to create conditional statements within your templates. It evaluates specified conditions and includes the enclosed content only if the condition is true. Here's an example:
|
||||||
|
```
|
||||||
|
#if(weather.Temp > 30):
|
||||||
|
<p>It's a hot day!</p>
|
||||||
|
#elif(weather.Temp < 0):
|
||||||
|
<p>It's freezing!</p>
|
||||||
|
#else:
|
||||||
|
<p>The temperature is between 0 and 30</p<
|
||||||
|
#!if
|
||||||
|
```
|
||||||
|
|
||||||
|
### `include` tag
|
||||||
|
|
||||||
|
The include tag allows you to import content from other templates in the namespace, into your current template, making it easier to manage complex templates. Here's an example of the `include` tag:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include("header.html")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using the `include` tag with extra arguments
|
||||||
|
|
||||||
|
The `include` tag can accept extra local variables as arguments. Here's an example with a `title` variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include("header.html", title = "Home")
|
||||||
|
```
|
||||||
|
|
||||||
|
These local variables will then be defined in the included template.
|
||||||
|
|
||||||
|
### `macro` tag
|
||||||
|
|
||||||
|
The macro tag is a powerful feature that allows you to define reusable template sections. These sections can be included later in the current template or in other templates that were included by the `include` tag. Here's an example of the macro tag:
|
||||||
|
|
||||||
|
```
|
||||||
|
#macro("content"): <!-- This defines a macro called "content" -->
|
||||||
|
Content
|
||||||
|
#!macro
|
||||||
|
|
||||||
|
#macro("content") <!-- This inserts the content macro -->
|
||||||
|
```
|
||||||
|
|
||||||
|
When a macro tag has a block, it sets the macro's content. When it doesn't, it inserts the contents of the macro. In the above example, a macro is defined and then inserted.
|
||||||
|
|
||||||
|
#### Using the `macro` tag with extra arguments
|
||||||
|
|
||||||
|
Similar to the `include` tag, the `macro` tag can accept extra local variables as arguments. You can define these variables when including the macro. Here's an example:
|
||||||
|
|
||||||
|
```
|
||||||
|
#macro("content", x = 1, y = x + 2)
|
||||||
|
```
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
Functions that are used in a template can have any amount of arguments, but cannot have more than two return values. If a function has two return values, the second one must be an error value.
|
Functions used in a template can accept any number of arguments but are limited to returning a maximum of two values. When a function returns two values, the second one must be an error value.
|
||||||
|
|
||||||
Salix includes the following default functions in all templates:
|
### Global Functions
|
||||||
|
|
||||||
|
Salix includes several useful global functions in all templates:
|
||||||
|
|
||||||
- `len(v any) int`: Returns the length of the value passed in. If the length cannot be found, it returns `-1`.
|
- `len(v any) int`: Returns the length of the value passed in. If the length cannot be found, it returns `-1`.
|
||||||
- `toUpper(s string) string`: Returns `s`, but with all characters mapped to their uppercase equivalents.
|
- `toUpper(s string) string`: Returns `s`, but with all characters mapped to their uppercase equivalents.
|
||||||
@ -68,9 +177,41 @@ Salix includes the following default functions in all templates:
|
|||||||
- `split(s, sep string) []string`: Returns a slice containing all substrings separated by `sep`.
|
- `split(s, sep string) []string`: Returns a slice containing all substrings separated by `sep`.
|
||||||
- `join(ss []string, sep string) string`: Returns a string with all substrings in `ss` joined by `sep`.
|
- `join(ss []string, sep string) string`: Returns a string with all substrings in `ss` joined by `sep`.
|
||||||
|
|
||||||
## What does the name mean?
|
### Adding Custom Functions
|
||||||
|
|
||||||
Salix is the latin name for willow trees. I wanted to use a name related to plants since the syntax was highly inspired by Leaf, and I really liked the name Salix.
|
You can include custom functions as variables using the WithVarMap method on templates or namespaces. Methods that fit the above conditions can also be used as template functions.
|
||||||
|
|
||||||
|
## Expressions
|
||||||
|
|
||||||
|
Salix's expressions mostly work like Go's, but there are some extra features worth mentioning.
|
||||||
|
|
||||||
|
### Ternary Expressions
|
||||||
|
|
||||||
|
Salix supports ternary expressions, which allow you to choose a value based on whether a condition is true. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
#(len(matches) > 1 ? "several matches" : "one match")
|
||||||
|
```
|
||||||
|
|
||||||
|
This example returns `"several matches"` if the length of matches is greater than one. Otherwise, it returns `"one match"`.
|
||||||
|
|
||||||
|
### Coalescing operator
|
||||||
|
|
||||||
|
The coalescing operator allows you to return a default value if a variable isn't defined. Here's an example:
|
||||||
|
|
||||||
|
```
|
||||||
|
<title>#(title | "Home")</title>
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, the expression will return the content of the `title` variable if it's defined. If not, it will return `"Home"` as the default value.
|
||||||
|
|
||||||
|
### The `in` operator
|
||||||
|
|
||||||
|
Salix's `in` operator allows you to check if a slice or array contains a specific element, or if a string contains a substring. Here's one example:
|
||||||
|
|
||||||
|
```
|
||||||
|
#("H" in "Hello") <!-- Returns true -->
|
||||||
|
```
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user