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