Expand the numeric conversions to template funcs/methods

So the example mentioned in #14079 also works for TOML and JSON front matter.

See #14079
This commit is contained in:
Bjørn Erik Pedersen
2025-10-22 19:12:11 +02:00
parent df4f80d54f
commit e08278d165
3 changed files with 88 additions and 3 deletions
+16
View File
@@ -315,6 +315,7 @@ func IsContextType(tp reflect.Type) bool {
// This is currently only implemented for int kinds, // This is currently only implemented for int kinds,
// added to handle the move to a new YAML library which produces uint64 for unsigned integers. // added to handle the move to a new YAML library which produces uint64 for unsigned integers.
// We can expand on this later if needed. // We can expand on this later if needed.
// This conversion is lossless.
// See Issue 14079. // See Issue 14079.
func ConvertIfPossible(val reflect.Value, typ reflect.Type) (reflect.Value, bool) { func ConvertIfPossible(val reflect.Value, typ reflect.Type) (reflect.Value, bool) {
if IsInt(typ.Kind()) { if IsInt(typ.Kind()) {
@@ -333,6 +334,21 @@ func ConvertIfPossible(val reflect.Value, typ reflect.Type) (reflect.Value, bool
} }
return val.Convert(typ), true return val.Convert(typ), true
} }
if IsFloat(val.Kind()) {
f := val.Float()
if f < float64(math.MinInt64) || f > float64(math.MaxInt64) {
return reflect.Value{}, false
}
i := int64(f)
if typ.OverflowInt(i) {
return reflect.Value{}, false
}
// Check for lossless conversion.
if float64(i) != f {
return reflect.Value{}, false
}
return val.Convert(typ), true
}
} }
return reflect.Value{}, false return reflect.Value{}, false
} }
+27
View File
@@ -231,6 +231,33 @@ func TestCastIfPossible(t *testing.T) {
ok: true, ok: true,
expected: int(math.MaxInt16), expected: int(math.MaxInt16),
}, },
// From float to int.
{
name: "float64(1.5) to int",
value: float64(1.5),
typ: int(0),
ok: false, // loss of precision
},
{
name: "float64(1.0) to int",
value: float64(1.0),
typ: int(0),
ok: true,
expected: int(1),
},
{
name: "float64(math.MaxFloat64) to int16",
value: float64(math.MaxFloat64),
typ: int16(0),
ok: false, // overflow
},
{
name: "float64(32767) to int16",
value: float64(32767),
typ: int16(0),
ok: true,
expected: int16(32767),
},
} { } {
v, ok := ConvertIfPossible(reflect.ValueOf(test.value), reflect.TypeOf(test.typ)) v, ok := ConvertIfPossible(reflect.ValueOf(test.value), reflect.TypeOf(test.typ))
+45 -3
View File
@@ -327,11 +327,53 @@ myinteger: 2
-- layouts/all.html -- -- layouts/all.html --
{{ $date := "2023-10-15T13:18:50-07:00" | time }} {{ $date := "2023-10-15T13:18:50-07:00" | time }}
{{ $mydata := resources.Get "mydata.yaml" | transform.Unmarshal }} {{ $mydata := resources.Get "mydata.yaml" | transform.Unmarshal }}
date: {{ $date | time.Format "2006-01-06" }}| date: {{ $date | time.Format "2006-01-02" }}|
date+2y: {{ $date.AddDate $mydata.myinteger 0 0 | time.Format "2006-01-06" }}| date+2y: {{ $date.AddDate $mydata.myinteger 0 0 | time.Format "2006-01-02" }}|
` `
b := hugolib.Test(t, files) b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html", "date: 2023-10-23|", "date+2y: 2025-10-25|") b.AssertFileContent("public/index.html", "date: 2023-10-15", "date+2y: 2025-10-15")
}
func TestTOMLAddDateIssue14079(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ["page", "section", "taxonomy", "term", "sitemap", "RSS"]
-- assets/mydata.toml --
myinteger = 2
-- layouts/all.html --
{{ $date := "2023-10-15T13:18:50-07:00" | time }}
{{ $mydata := resources.Get "mydata.toml" | transform.Unmarshal }}
date: {{ $date | time.Format "2006-01-02" }}|
date+2y: {{ $date.AddDate $mydata.myinteger 0 0 | time.Format "2006-01-02" }}|
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html", "date: 2023-10-15", "date+2y: 2025-10-15")
}
func TestJSONAddDateIssue14079(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ["page", "section", "taxonomy", "term", "sitemap", "RSS"]
-- assets/mydata.json --
{
"myinteger": 2
}
-- layouts/all.html --
{{ $date := "2023-10-15T13:18:50-07:00" | time }}
{{ $mydata := resources.Get "mydata.json" | transform.Unmarshal }}
date: {{ $date | time.Format "2006-01-02" }}|
date+2y: {{ $date.AddDate $mydata.myinteger 0 0 | time.Format "2006-01-02" }}|
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html", "date: 2023-10-15", "date+2y: 2025-10-15")
} }