Add ternary expressions
This commit is contained in:
parent
9d44c8d02c
commit
c1a2e56f4f
@ -10,10 +10,10 @@
|
||||
</div>
|
||||
<div class="navbar-menu" id="navbarMenu">
|
||||
<div class="navbar-end">
|
||||
<a class='navbar-item #if(title == "Home"):is-active#!if' href="/">
|
||||
<a class='navbar-item #(title == "Home" ? "is-active" : "")' href="/">
|
||||
Home
|
||||
</a>
|
||||
<a class='navbar-item #if(title == "About"):is-active#!if' href="/about">
|
||||
<a class='navbar-item #(title == "About" ? "is-active" : "")' href="/about">
|
||||
About
|
||||
</a>
|
||||
</div>
|
||||
|
@ -199,3 +199,14 @@ func (l Logical) Pos() Position {
|
||||
func (l Logical) Op() string {
|
||||
return l.Value
|
||||
}
|
||||
|
||||
type Ternary struct {
|
||||
Condition Node
|
||||
IfTrue Node
|
||||
Else Node
|
||||
Position Position
|
||||
}
|
||||
|
||||
func (t Ternary) Pos() Position {
|
||||
return t.Position
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -55,13 +55,15 @@ EndTag = "#!" name:Ident {
|
||||
}, nil
|
||||
}
|
||||
|
||||
ExprTag = "#(" expr:Expr ')' {
|
||||
ExprTag = "#(" item:Item ')' {
|
||||
return ast.ExprTag{
|
||||
Value: expr.(ast.Node),
|
||||
Value: item.(ast.Node),
|
||||
Position: getPos(c),
|
||||
}, nil
|
||||
}
|
||||
|
||||
Item = Ternary / Expr
|
||||
|
||||
Expr = first:ExprSegment rest:(_ Logical _ ExprSegment)* {
|
||||
restSlice := toAnySlice(rest)
|
||||
if len(restSlice) == 0 {
|
||||
@ -100,7 +102,7 @@ ExprSegment = first:Value rest:(_ Operator _ Value)* {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
ParamList = '(' params:(Expr ( ',' _ Expr )* )? ')' {
|
||||
ParamList = '(' params:(Item ( ',' _ Item )* )? ')' {
|
||||
paramSlice := toAnySlice(params)
|
||||
if len(paramSlice) == 0 {
|
||||
return []ast.Node{}, nil
|
||||
@ -121,6 +123,14 @@ Value = not:"!"? node:(MethodCall / FieldAccess / Index / String / RawString / F
|
||||
}, nil
|
||||
}
|
||||
|
||||
Ternary = cond:Expr _ '?' _ ifTrue:Value _ ':' _ elseVal:Value {
|
||||
return ast.Ternary{
|
||||
Condition: cond.(ast.Node),
|
||||
IfTrue: ifTrue.(ast.Node),
|
||||
Else: elseVal.(ast.Node),
|
||||
}, nil
|
||||
}
|
||||
|
||||
MethodCall = value:Value '.' name:Ident params:ParamList {
|
||||
return ast.MethodCall{
|
||||
Value: value.(ast.Node),
|
||||
|
21
salix.go
21
salix.go
@ -27,6 +27,7 @@ var (
|
||||
ErrFuncTooManyReturns = errors.New("template functions can only have two return values")
|
||||
ErrFuncNoReturns = errors.New("template functions must return at least one value")
|
||||
ErrFuncSecondReturnType = errors.New("the second return value of a template function must be an error")
|
||||
ErrTernaryCondBool = errors.New("ternary condition must be a boolean")
|
||||
)
|
||||
|
||||
// HTML represents unescaped HTML strings
|
||||
@ -215,6 +216,8 @@ func (t *Template) getValue(node ast.Node, local map[string]any) (any, error) {
|
||||
return t.getField(node, local)
|
||||
case ast.MethodCall:
|
||||
return t.execMethodCall(node, local)
|
||||
case ast.Ternary:
|
||||
return t.evalTernary(node, local)
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
@ -427,6 +430,24 @@ func (t *Template) execFunc(fn reflect.Value, node ast.Node, args []ast.Node, lo
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Template) evalTernary(tr ast.Ternary, local map[string]any) (any, error) {
|
||||
condVal, err := t.getValue(tr.Condition, local)
|
||||
if err != nil {
|
||||
return nil, t.posError(tr.Condition, "%w", ErrTernaryCondBool)
|
||||
}
|
||||
|
||||
cond, ok := condVal.(bool)
|
||||
if !ok {
|
||||
return nil, errors.New("ternary condition must be a boolean")
|
||||
}
|
||||
|
||||
if cond {
|
||||
return t.getValue(tr.IfTrue, local)
|
||||
} else {
|
||||
return t.getValue(tr.Else, local)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Template) posError(n ast.Node, format string, v ...any) error {
|
||||
return ast.PosError(n, t.name, format, v...)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user