Add the ability to ignore errors in ExprTags

This commit is contained in:
Elara 2024-02-07 18:11:24 -08:00
parent 958a25d559
commit 9df2382a33
6 changed files with 370 additions and 323 deletions

View File

@ -26,6 +26,7 @@ Salix's syntax is similar to Leaf and (in my opinion at least), it's much more f
- [Global Functions](#global-functions) - [Global Functions](#global-functions)
- [Adding Custom Functions](#adding-custom-functions) - [Adding Custom Functions](#adding-custom-functions)
- [Expressions](#expressions) - [Expressions](#expressions)
- [Ignoring errors](#ignoring-errors)
- [Ternary Expressions](#ternary-expressions) - [Ternary Expressions](#ternary-expressions)
- [Coalescing operator](#coalescing-operator) - [Coalescing operator](#coalescing-operator)
- [The `in` operator](#the-in-operator) - [The `in` operator](#the-in-operator)
@ -189,6 +190,19 @@ You can include custom functions as variables using the WithVarMap method on tem
Salix's expressions mostly work like Go's, but there are some extra features worth mentioning. Salix's expressions mostly work like Go's, but there are some extra features worth mentioning.
### Ignoring errors
If you'd like to ignore errors in an expression tag, you can do that by adding a question mark at the end.
```html
<!-- This would return an error if example wasn't defined or if it didn't have an Example() method -->
#(example.Example())
<!-- This would ignore any error and keep executing the rest of the template -->
#(example.Example())?
```
### Ternary Expressions ### Ternary Expressions
Salix supports ternary expressions, which allow you to choose a value based on whether a condition is true. For example: Salix supports ternary expressions, which allow you to choose a value based on whether a condition is true. For example:

View File

@ -32,8 +32,9 @@ func (t Tag) Pos() Position {
} }
type ExprTag struct { type ExprTag struct {
Value Node Value Node
Position Position IgnoreError bool
Position Position
} }
func (et ExprTag) Pos() Position { func (et ExprTag) Pos() Position {

View File

@ -13,4 +13,4 @@
</div> </div>
#!for #!for
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@ -59,12 +59,12 @@ Root = items:(Tag / ExprTag / EndTag / Text)* {
return out, nil return out, nil
} }
Tag = '#' name:Ident params:ParamList? body:':'? { Tag = '#' name:Ident params:ParamList? ignoreErr:'?'? body:':'? {
return ast.Tag{ return ast.Tag{
Name: name.(ast.Ident), Name: name.(ast.Ident),
Params: toNodeSlice(params), Params: toNodeSlice(params),
HasBody: body != nil, HasBody: body != nil,
Position: getPos(c), Position: getPos(c),
}, nil }, nil
} }
@ -75,10 +75,11 @@ EndTag = "#!" name:Ident {
}, nil }, nil
} }
ExprTag = "#(" item:Expr ')' { ExprTag = "#(" item:Expr ')' ignoreErr:'?'? {
return ast.ExprTag{ return ast.ExprTag{
Value: item.(ast.Node), Value: item.(ast.Node),
Position: getPos(c), IgnoreError: ignoreErr != nil,
Position: getPos(c),
}, nil }, nil
} }
@ -248,4 +249,4 @@ ArithmeticOp = ('+' / '-' / '/' / '*' / '%') {
Text = . [^#]* { return ast.Text{Data: c.text, Position: getPos(c)}, nil } Text = . [^#]* { return ast.Text{Data: c.text, Position: getPos(c)}, nil }
_ "whitespace" ← [ \t\r\n]* _ "whitespace" ← [ \t\r\n]*

View File

@ -112,7 +112,11 @@ func (t *Template) execute(w io.Writer, nodes []ast.Node, local map[string]any)
case ast.ExprTag: case ast.ExprTag:
v, err := t.getValue(node.Value, local) v, err := t.getValue(node.Value, local)
if err != nil { if err != nil {
return err if node.IgnoreError {
continue
} else {
return err
}
} }
if _, ok := v.(ast.Assignment); ok { if _, ok := v.(ast.Assignment); ok {
continue continue