diff --git a/exampleSite/data/tests/casting.yml b/exampleSite/data/tests/casting.yml index c80137e..1ff6fc2 100644 --- a/exampleSite/data/tests/casting.yml +++ b/exampleSite/data/tests/casting.yml @@ -51,3 +51,12 @@ cases: structure: test-cast args: items-list: [1, "two", true] + # Whole-number floats cast losslessly to int (JSON round-trips — e.g. frontmatter + # injected by CloudCannon's visual editor — deliver every number as float64). + - name: whole-float-to-int + structure: test-cast + args: {count: 42.0} + # Fractional floats still fail the int type check. + - name: fractional-float-to-int + structure: test-cast + args: {count: 42.5} diff --git a/layouts/_partials/utilities/Args.html b/layouts/_partials/utilities/Args.html index 0220b24..2d65a8b 100644 --- a/layouts/_partials/utilities/Args.html +++ b/layouts/_partials/utilities/Args.html @@ -133,6 +133,14 @@ {{ $value = float $value }} {{ $kind = "float" }} {{ end }} + {{ else if and (eq $kind "float") (in $node.accepts "int") (not (in $node.accepts "float")) (eq (float (int $value)) (float $value)) }} + {{/* whole-number floats cast losslessly to int. Data that round-trips through + JSON — notably page frontmatter injected by CloudCannon's visual editor + (Bookshop live rendering) — arrives with every number as float64, so an + int argument would otherwise reject values the YAML source declares as + plain integers. Fractional values still fail the type check below. */}} + {{ $value = int $value }} + {{ $kind = "int" }} {{ else if and (in $node.accepts "string") (in (slice "bool" "int" "float") $kind) (not (in $node.accepts $kind)) }} {{ $value = string $value }} {{ $kind = "string" }} diff --git a/tests/golden/casting.json b/tests/golden/casting.json index 7a7497d..599ed8e 100644 --- a/tests/golden/casting.json +++ b/tests/golden/casting.json @@ -62,6 +62,27 @@ ] } }, + "fractional-float-to-int": { + "args": { + "args": { + "count": 42.5 + }, + "defaulted": [], + "err": true, + "errmsg": [ + "[test-cast] argument 'count': expected type 'int', got 'float64' with value '42.5'" + ], + "warnmsg": [] + }, + "initargs": { + "default": [], + "err": true, + "errmsg": [ + "[test-cast] argument 'count': expected type 'int', got 'float64' with value '42.5'" + ], + "warnmsg": [] + } + }, "generic-dict-as-map": { "args": { "args": { @@ -233,6 +254,24 @@ "warnmsg": [] } }, + "whole-float-to-int": { + "args": { + "args": { + "count": 42 + }, + "defaulted": [], + "err": false, + "errmsg": [], + "warnmsg": [] + }, + "initargs": { + "count": 42, + "default": [], + "err": false, + "errmsg": [], + "warnmsg": [] + } + }, "wrong-type-errors": { "args": { "args": {