Template functions for semantic version comparisons

Would the Hugo project consider a PR to add several semver template functions?

Examples
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.

1 Like

I believe this would be much better than the partial I posted for checking Hugo min/max version once itā€™s had time to be out ā€˜in the wildā€™ for long enough.

Thank you for proposing this.

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

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

You would do:

{{ 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

{{ 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.

1 Like

I see at least one test example in the code:

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

Which should illustrate the potential.

1 Like

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).