# Template functions for semantic version comparisons

**URL:** <https://discourse.gohugo.io/t/template-functions-for-semantic-version-comparisons/40501>\
**Category:** dev\
**Created:** [September 13, 2022, 5:16am UTC](https://discourse.gohugo.io/t/template-functions-for-semantic-version-comparisons/40501 "2022-09-13T05:16:57Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [September 13, 2022, 5:16am UTC](https://discourse.gohugo.io/t/template-functions-for-semantic-version-comparisons/40501/1 "2022-09-13T05:16:57Z")

</div>

Would the Hugo project consider a PR to add several [semver](https://pkg.go.dev/golang.org/x/mod/semver) template functions?

> **Examples**
>
> ```nohighlight
> semver.Eq
> 
> {{ semver.Eq "v0.100.0" "v0.101.3" }} ---> false
> {{ semver.Eq "v0.101.3" "v0.101.3" }} ---> true
> 
> semver.Ne
> 
> {{ semver.Ne "v0.100.0" "v0.101.3" }} ---> true
> {{ semver.Ne "v0.101.3" "v0.101.3" }} ---> false
> 
> semver.Ge
> 
> {{ semver.Ge "v0.100.0" "v0.101.3" }} ---> false
> {{ semver.Ge "v0.101.3" "v0.101.3" }} ---> true
> {{ semver.Ge "v0.101.3" "v0.100.0" }} ---> true
> 
> semver.Gt
> 
> {{ semver.Gt "v0.100.0" "v0.101.3" }} ---> false
> {{ semver.Gt "v0.101.3" "v0.101.3" }} ---> false
> {{ semver.Gt "v0.101.3" "v0.100.0" }} ---> true
> 
> semver.Le
> 
> {{ semver.Le "v0.100.0" "v0.101.3" }} ---> true
> {{ semver.Le "v0.101.3" "v0.101.3" }} ---> true
> {{ semver.Le "v0.101.3" "v0.100.0" }} ---> false
> 
> semver.Lt
> 
> {{ semver.Lt "v0.100.0" "v0.101.3" }} ---> true
> {{ semver.Lt "v0.101.3" "v0.101.3" }} ---> false
> {{ semver.Lt "v0.101.3" "v0.100.0" }} ---> false
> 
> semver.Canonical
> 
> {{ semver.Canonical "v0.101.3" }} ---> v0.101.3
> {{ semver.Canonical "v0.101" }} ---> v0.101.0
> {{ semver.Canonical "v0" }} ---> v0.0.0
> 
> semver.IsValid
> 
> {{ semver.IsValid "v0.101.3" }} ---> true
> {{ semver.IsValid "v0.101" }} ---> true
> {{ semver.IsValid "v0" }} ---> true
> {{ semver.IsValid "aaa" }} ---> false
> 
> semver.Major
> 
> {{ semver.Major "v0.101.3" }} ---> v0
> {{ semver.Major "v0.101" }} ---> v0
> {{ semver.Major "v0" }} ---> v0
> 
> semver.MajorMinor
> 
> {{ semver.MajorMinor "v0.101.3" }} ---> v0.101
> {{ semver.MajorMinor "v0.101" }} ---> v0.101
> {{ semver.MajorMinor "v0" }} ---> v0.0
> 
> ```

For all functions, the leading lowercase “v” of the argument(s) would be optional.

It would take several release/upgrade cycles for this to be useful (similar to adding the `.IsExtended` method in v0.83.0), so if we want to do it, sooner is better.

---

<div class="post-metadata">

**Author:** ![cshoredaniel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/cshoredaniel/32/19684_2.png) [@cshoredaniel](https://discourse.gohugo.io/u/cshoredaniel)\
**Post date:** [September 13, 2022, 9:30pm UTC](https://discourse.gohugo.io/t/template-functions-for-semantic-version-comparisons/40501/2 "2022-09-13T21:30:21Z")

</div>

I believe this would be much better than [the partial I posted for checking Hugo min/max version](https://discourse.gohugo.io/t/partial-for-checking-min-max-hugo-version/40474/2) once it’s had time to be out ‘in the wild’ for long enough.

Thank you for proposing this.

---

<div class="post-metadata">

**Author:** ![bep](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bep/32/3332_2.png) [@bep](https://discourse.gohugo.io/u/bep)\
**Post date:** [September 13, 2022, 9:49pm UTC](https://discourse.gohugo.io/t/template-functions-for-semantic-version-comparisons/40501/3 "2022-09-13T21:49:25Z")

</div>

We already have a `VersionString` type that supports all of the above ops. I’m not sure if it’s fully semver compatible, but it’s what Hugo uses, so it’s … Hugo compatible. I think it’s exposed in a template somehow, but the main take is that we don’t want to re-implement all of the ne/ge/gt … in yet another API.

So instead of

```auto
{{ semver.Gt "v0.100.0" "v0.101.3" }} ---> false

```

You would do:

```auto
{{ gt (ver "v0.100.0") ver("v0.101.3") }} ---> false

```

We certainly do some magic in other situations as well, so we could also maybe do

```auto
{{ gt "v0.100.0" "v0.101.3" }} ---> false

```

But that said, I’m not sure where this came from. We at least should have enough tools to determine if the current Hugo version is before/after a given string.

---

<div class="post-metadata">

**Author:** ![bep](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/bep/32/3332_2.png) [@bep](https://discourse.gohugo.io/u/bep)\
**Post date:** [September 13, 2022, 9:53pm UTC](https://discourse.gohugo.io/t/template-functions-for-semantic-version-comparisons/40501/4 "2022-09-13T21:53:08Z")

</div>

I see at least one test example in the code:

```auto
{{ if ge hugo.Version "0.80" }}Reasonable new Hugo version!{{ end }}

```

Which should illustrate the potential.

---

<div class="post-metadata">

**Author:** ![cshoredaniel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/cshoredaniel/32/19684_2.png) [@cshoredaniel](https://discourse.gohugo.io/u/cshoredaniel)\
**Post date:** [September 13, 2022, 10:42pm UTC](https://discourse.gohugo.io/t/template-functions-for-semantic-version-comparisons/40501/5 "2022-09-13T22:42:37Z")

</div>

> [@bep](#):
>
> But that said, I’m not sure where this came from.

It’s probably because I did the min/max partial thing because I didn’t find anything in the docs for doing checks on hugo.Version vs. some string. If that exists (I’ll do some testing shortly) then I’ll add some docs on how to do it with the existing checks since it was totally not obvious to me that there was a way to do it without something like my partial.

EDIT: Well that makes things a **lot** easier. I’ll run it through my tests since I have them anyway, but I’m thinking Hugo’s automagic typing caught me surprise and still blows my mind!

It simply never occurred to me that Hugo already could automatically convert a string to a sufficiently ‘proper’ version string for what I wanted without external functions.

EDIT Again: Wow! This is one of those things that ‘Just Works™!’ that I would never have expected, and either missed in the docs, or will be adding a hopefully prominent enough not that others don’t make the same mistake (I spent far too much time on this, for something that didn’t need doing).
