diff --git a/internal/warpc/avif_integration_test.go b/internal/warpc/avif_integration_test.go index 7c0b3e0fa..9b3b68cb3 100644 --- a/internal/warpc/avif_integration_test.go +++ b/internal/warpc/avif_integration_test.go @@ -82,9 +82,11 @@ text:{{ ($img.Process "avif text").RelPermalink }}| b := hugolib.Test(t, files) b.AssertFileContent("public/index.html", - "default:/logo_hu_add3d7dfc55b7f80.avif|", - "photo:/logo_hu_add3d7dfc55b7f80.avif|", - "text:/logo_hu_b7080fe2a2e2a664.avif|") + ` +default:/logo_hu_72e150ce03376cfd.avif| +photo:/logo_hu_72e150ce03376cfd.avif| +text:/logo_hu_9de8f282912bc925.avif| +`) } // See issue 14985. diff --git a/resources/images/config.go b/resources/images/config.go index ccc5e360d..93454c222 100644 --- a/resources/images/config.go +++ b/resources/images/config.go @@ -84,6 +84,13 @@ var ( // Increment to mark all processed images as stale. Only use when absolutely needed. // See the finer grained smartCropVersionNumber. mainImageVersionNumber = 1 + + // Increment a format's version number to mark all processed images targeting + // that format as stale, e.g. after a change to its encoder. This is finer + // grained than mainImageVersionNumber, which invalidates every format. + formatVersionNumbers = map[Format]int{ + AVIF: 1, + } ) var anchorPositions = map[string]gift.Anchor{ @@ -391,6 +398,10 @@ func DecodeImageConfig(options []string, defaults *config.ConfigNamespace[Imagin options = append(options, strconv.Itoa(mainImageVersionNumber)) } + if v := formatVersionNumbers[c.TargetFormat]; v > 0 { + options = append(options, "tfv"+strconv.Itoa(v)) + } + usesSmartCrop := c.Anchor == SmartCropAnchor && (c.Action == ActionCrop || c.Action == ActionFill) if smartCropVersionNumber > 0 && usesSmartCrop { options = append(options, strconv.Itoa(smartCropVersionNumber)) diff --git a/resources/images/config_test.go b/resources/images/config_test.go index 9206c041d..ad6cfbd00 100644 --- a/resources/images/config_test.go +++ b/resources/images/config_test.go @@ -229,6 +229,30 @@ func TestImageConfigAvifDefaultQuality(t *testing.T) { c.Assert(quality(cfg, "avif", "q33"), qt.Equals, 33) } +// See issue 14990. +func TestImageConfigFormatVersionNumber(t *testing.T) { + c := qt.New(t) + + cfg, err := DecodeConfig(map[string]any{}) + c.Assert(err, qt.IsNil) + + key := func(f string) string { + conf, err := DecodeImageConfig([]string{"resize", "100x", f}, cfg, JPEG) + c.Assert(err, qt.IsNil) + return conf.Key + } + + avifBefore, jpgBefore := key("avif"), key("jpg") + + orig := formatVersionNumbers[AVIF] + defer func() { formatVersionNumbers[AVIF] = orig }() + formatVersionNumbers[AVIF] = orig + 1 + + // Bumping the AVIF version invalidates AVIF images only. + c.Assert(key("avif"), qt.Not(qt.Equals), avifBefore) + c.Assert(key("jpg"), qt.Equals, jpgBefore) +} + func TestDecodeImageConfig(t *testing.T) { for i, this := range []struct { action string