mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
tpl: adds truth
and bool
template functions
The behavior of `truth` and `bool` is described in the corresponding test cases and examples. The decision-making around the behavior is a based on combination of the existing behavior of strconv.ParseBool in go and the MDN definition of "truthy" as JavaScript has the most interop with the Hugo ecosystem. Addresses #9160 and (indirectly) #5792
This commit is contained in:
parent
f650e4d751
commit
5a72de2600
5 changed files with 230 additions and 0 deletions
48
docs/content/en/functions/bool.md
Normal file
48
docs/content/en/functions/bool.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: bool
|
||||
linktitle: bool
|
||||
description: Creates a `bool` from the argument passed into the function.
|
||||
date: 2023-01-28
|
||||
publishdate: 2023-01-28
|
||||
lastmod: 2023-01-28
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: "functions"
|
||||
keywords: [strings,boolean,bool]
|
||||
signature: ["bool INPUT"]
|
||||
workson: []
|
||||
hugoversion:
|
||||
relatedfuncs: [truth]
|
||||
deprecated: false
|
||||
aliases: []
|
||||
---
|
||||
|
||||
Useful for turning ints, strings, and nil into booleans.
|
||||
|
||||
```
|
||||
{{ bool "true" }} → true
|
||||
{{ bool "false" }} → false
|
||||
|
||||
{{ bool "TRUE" }} → true
|
||||
{{ bool "FALSE" }} → false
|
||||
|
||||
{{ truth "t" }} → true
|
||||
{{ truth "f" }} → false
|
||||
|
||||
{{ truth "T" }} → true
|
||||
{{ truth "F" }} → false
|
||||
|
||||
{{ bool "1" }} → true
|
||||
{{ bool "0" }} → false
|
||||
|
||||
{{ bool 1 }} → true
|
||||
{{ bool 0 }} → false
|
||||
|
||||
{{ bool true }} → true
|
||||
{{ bool false }} → false
|
||||
|
||||
{{ bool nil }} → false
|
||||
```
|
||||
|
||||
This function will throw a type-casting error for most other types or strings. For less strict behavior, see [`truth`](/functions/truth).
|
53
docs/content/en/functions/truth.md
Normal file
53
docs/content/en/functions/truth.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
title: truth
|
||||
linktitle: truth
|
||||
description: Creates a `bool` from the truthyness of the argument passed into the function
|
||||
date: 2023-01-28
|
||||
publishdate: 2023-01-28
|
||||
lastmod: 2023-01-28
|
||||
categories: [functions]
|
||||
menu:
|
||||
docs:
|
||||
parent: "functions"
|
||||
keywords: [strings,boolean,bool,truthy,falsey]
|
||||
signature: ["truth INPUT"]
|
||||
workson: []
|
||||
hugoversion:
|
||||
relatedfuncs: [bool]
|
||||
deprecated: false
|
||||
aliases: []
|
||||
---
|
||||
|
||||
Useful for turning different types into booleans based on their [truthy-ness](https://developer.mozilla.org/en-US/docs/Glossary/Truthy).
|
||||
|
||||
It follows the same rules as [`bool`](/functions/bool), but with increased flexibility.
|
||||
|
||||
```
|
||||
{{ truth "true" }} → true
|
||||
{{ truth "false" }} → false
|
||||
|
||||
{{ truth "TRUE" }} → true
|
||||
{{ truth "FALSE" }} → false
|
||||
|
||||
{{ truth "t" }} → true
|
||||
{{ truth "f" }} → false
|
||||
|
||||
{{ truth "T" }} → true
|
||||
{{ truth "F" }} → false
|
||||
|
||||
{{ truth "1" }} → true
|
||||
{{ truth "0" }} → false
|
||||
|
||||
{{ truth 1 }} → true
|
||||
{{ truth 0 }} → false
|
||||
|
||||
{{ truth true }} → true
|
||||
{{ truth false }} → false
|
||||
|
||||
{{ truth nil }} → false
|
||||
|
||||
{{ truth "cheese" }} → true
|
||||
{{ truth 1.67 }} → true
|
||||
```
|
||||
|
||||
This function will not throw an error. For more strict behavior, see [`bool`](/functions/bool).
|
|
@ -46,6 +46,28 @@ func (ns *Namespace) ToFloat(v any) (float64, error) {
|
|||
return _cast.ToFloat64E(v)
|
||||
}
|
||||
|
||||
// ToBool converts v to a boolean.
|
||||
func (ns *Namespace) ToBool(v any) (bool, error) {
|
||||
v = convertTemplateToString(v)
|
||||
return _cast.ToBoolE(v)
|
||||
}
|
||||
|
||||
// ToTruth yields the same behavior as ToBool when possible.
|
||||
// If the cast is unsuccessful, ToTruth converts v to a boolean using the JavaScript [definition of truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy).
|
||||
// Accordingly, it never yields an error, but maintains the signature of other cast methods for consistency.
|
||||
func (ns *Namespace) ToTruth(v any) (bool, error) {
|
||||
result, err := ns.ToBool(v)
|
||||
if err != nil {
|
||||
switch v {
|
||||
case "", "nil", "null", "undefined", "NaN":
|
||||
return false, nil
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func convertTemplateToString(v any) any {
|
||||
switch vv := v.(type) {
|
||||
case template.HTML:
|
||||
|
|
|
@ -117,3 +117,92 @@ func TestToFloat(t *testing.T) {
|
|||
c.Assert(result, qt.Equals, test.expect, errMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToBool(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
ns := New()
|
||||
|
||||
for i, test := range []struct {
|
||||
v any
|
||||
expect any
|
||||
error any
|
||||
}{
|
||||
{"true", true, nil},
|
||||
{"false", false, nil},
|
||||
{"TRUE", true, nil},
|
||||
{"FALSE", false, nil},
|
||||
{"t", true, nil},
|
||||
{"f", false, nil},
|
||||
{"T", true, nil},
|
||||
{"F", false, nil},
|
||||
{"1", true, nil},
|
||||
{"0", false, nil},
|
||||
{1, true, nil},
|
||||
{0, false, nil},
|
||||
{true, true, nil},
|
||||
{false, false, nil},
|
||||
{nil, false, nil},
|
||||
|
||||
// error cases
|
||||
{"cheese", nil, false},
|
||||
{"", nil, false},
|
||||
{1.67, nil, false},
|
||||
} {
|
||||
errMsg := qt.Commentf("[%d] %v", i, test.v)
|
||||
|
||||
result, err := ns.ToBool(test.v)
|
||||
|
||||
if b, ok := test.error.(bool); ok && !b {
|
||||
c.Assert(err, qt.Not(qt.IsNil), errMsg)
|
||||
continue
|
||||
}
|
||||
|
||||
c.Assert(err, qt.IsNil, errMsg)
|
||||
c.Assert(result, qt.Equals, test.expect, errMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToTruth(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
ns := New()
|
||||
|
||||
for i, test := range []struct {
|
||||
v any
|
||||
expect any
|
||||
}{
|
||||
{"true", true},
|
||||
{"false", false},
|
||||
{"TRUE", true},
|
||||
{"FALSE", false},
|
||||
{"t", true},
|
||||
{"f", false},
|
||||
{"T", true},
|
||||
{"F", false},
|
||||
{"1", true},
|
||||
{"0", false},
|
||||
{1, true},
|
||||
{0, false},
|
||||
{"cheese", true},
|
||||
{"", false},
|
||||
{1.67, true},
|
||||
{template.HTML("2"), true},
|
||||
{template.CSS("3"), true},
|
||||
{template.HTMLAttr("4"), true},
|
||||
{template.JS("-5.67"), true},
|
||||
{template.JSStr("6"), true},
|
||||
{t, true},
|
||||
{nil, false},
|
||||
{"null", false},
|
||||
{"undefined", false},
|
||||
{"NaN", false},
|
||||
} {
|
||||
errMsg := qt.Commentf("[%d] %v", i, test.v)
|
||||
|
||||
result, err := ns.ToTruth(test.v)
|
||||
|
||||
c.Assert(err, qt.IsNil, errMsg)
|
||||
c.Assert(result, qt.Equals, test.expect, errMsg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,24 @@ func init() {
|
|||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.ToBool,
|
||||
[]string{"bool"},
|
||||
[][2]string{
|
||||
{`{{ "0" | bool | printf "%T" }}`, `bool`},
|
||||
{`{{ "true" | bool }}`, `true`},
|
||||
{`{{ "false" | bool }}`, `false`},
|
||||
},
|
||||
)
|
||||
|
||||
ns.AddMethodMapping(ctx.ToTruth,
|
||||
[]string{"truth"},
|
||||
[][2]string{
|
||||
{`{{ "1234" | truth | printf "%T" }}`, `bool`},
|
||||
{`{{ "1234" | truth }}`, `true`},
|
||||
{`{{ "" | truth }}`, `false`},
|
||||
},
|
||||
)
|
||||
|
||||
return ns
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue