diff --git a/cbconvert.go b/cbconvert.go index e51e4ec..d6110ef 100644 --- a/cbconvert.go +++ b/cbconvert.go @@ -7,15 +7,14 @@ import ( "fmt" "image" _ "image/gif" - "image/png" "os" "path/filepath" "strconv" "strings" - pngstructure "github.com/dsoprea/go-png-image-structure" "github.com/dustin/go-humanize" folio "github.com/gen2brain/folio/doc" + "github.com/gen2brain/pngn" ) // Options type. @@ -434,23 +433,6 @@ func (c *Converter) Thumbnail(file File) error { cover = resize(cover, 256, 0, resampleFilter(c.Opts.Filter)) } - var buf bytes.Buffer - err = png.Encode(&buf, cover) - if err != nil { - return fmt.Errorf("%s: %w", fileName, err) - } - - pmp := pngstructure.NewPngMediaParser() - csTmp, err := pmp.ParseBytes(buf.Bytes()) - if err != nil { - return fmt.Errorf("%s: %w", fileName, err) - } - - cs, ok := csTmp.(*pngstructure.ChunkSlice) - if !ok { - return fmt.Errorf("%s: type is not ChunkSlice", fileName) - } - var fName string var fURI string @@ -473,33 +455,13 @@ func (c *Converter) Thumbnail(file File) error { fName = abs } - chunks := cs.Chunks() - textChunks := []*pngstructure.Chunk{ - {Type: `tEXt`, Data: []uint8("Software\x00" + "CBconvert")}, - {Type: `tEXt`, Data: []uint8("Description\x00" + "Thumbnail of " + fileName)}, - {Type: `tEXt`, Data: []uint8("Thumb::URI\x00" + fURI)}, - {Type: `tEXt`, Data: []uint8("Thumb::MTime\x00" + strconv.FormatInt(fileInfo.ModTime().Unix(), 10))}, - {Type: `tEXt`, Data: []uint8("Thumb::Size\x00" + strconv.FormatInt(fileInfo.Size(), 10))}, - } - - for _, textChunk := range textChunks { - textChunk.Length = uint32(len(textChunk.Data)) - textChunk.UpdateCrc32() - } - - chunks = append( - chunks[:1], - append( - textChunks, - chunks[1:]..., - )..., - ) - - cs = pngstructure.NewChunkSlice(chunks) - err = cs.WriteTo(&buf) - if err != nil { - return fmt.Errorf("%s: %w", fileName, err) - } + meta := &pngn.Metadata{Text: []pngn.Text{ + {Keyword: "Software", Value: "CBconvert"}, + {Keyword: "Description", Value: "Thumbnail of " + fileName}, + {Keyword: "Thumb::URI", Value: fURI}, + {Keyword: "Thumb::MTime", Value: strconv.FormatInt(fileInfo.ModTime().Unix(), 10)}, + {Keyword: "Thumb::Size", Value: strconv.FormatInt(fileInfo.Size(), 10)}, + }} f, err := os.Create(fName) if err != nil { @@ -508,8 +470,7 @@ func (c *Converter) Thumbnail(file File) error { defer f.Close() - _, err = buf.WriteTo(f) - if err != nil { + if err = pngn.Encode(f, cover, &pngn.EncodeOptions{Metadata: meta}); err != nil { return fmt.Errorf("%s: %w", fileName, err) } diff --git a/cbconvert_convert.go b/cbconvert_convert.go index 797db48..d620e75 100644 --- a/cbconvert_convert.go +++ b/cbconvert_convert.go @@ -6,7 +6,6 @@ import ( "context" "fmt" "image" - "image/png" "io" "os" "path/filepath" @@ -18,6 +17,7 @@ import ( "github.com/gen2brain/gav1d/avif" "github.com/gen2brain/jpegn" "github.com/gen2brain/jxl" + "github.com/gen2brain/pngn" "github.com/gen2brain/vpx/webp" "github.com/jsummers/gobmp" "github.com/mholt/archives" @@ -401,6 +401,15 @@ func (c *Converter) imageDecode(reader io.Reader) (image.Image, error) { return img, nil } + if magic, err := br.Peek(8); err == nil && string(magic) == "\x89PNG\r\n\x1a\n" { + img, err := pngn.Decode(br) + if err != nil { + return nil, fmt.Errorf("imageDecode: %w", err) + } + + return img, nil + } + img, _, err := image.Decode(br) if err != nil { return img, fmt.Errorf("imageDecode: %w", err) @@ -426,7 +435,7 @@ func (c *Converter) imageEncode(img image.Image, w io.Writer) error { switch c.Opts.Format { case "png": - err = png.Encode(w, img) + err = pngn.Encode(w, img) case "tiff": err = tiff.Encode(w, img, &tiff.Options{Compression: tiff.Uncompressed}) case "jpeg": diff --git a/cmd/cbconvert-gui/go.mod b/cmd/cbconvert-gui/go.mod index b29670a..803bb82 100644 --- a/cmd/cbconvert-gui/go.mod +++ b/cmd/cbconvert-gui/go.mod @@ -6,6 +6,7 @@ require ( github.com/fvbommel/sortorder v1.1.0 github.com/gen2brain/cbconvert v1.2.1-0.20260824143641-01a205a07eb9 github.com/gen2brain/iup-go/iup v0.32.1-0.20260627135200-7df674d35173 + github.com/gen2brain/pngn v0.1.2 ) require ( diff --git a/cmd/cbconvert-gui/go.sum b/cmd/cbconvert-gui/go.sum index 4ebb095..a1f264e 100644 --- a/cmd/cbconvert-gui/go.sum +++ b/cmd/cbconvert-gui/go.sum @@ -48,6 +48,8 @@ github.com/gen2brain/jpegn v0.6.1 h1:S+Em15BvqCl/cTvebB6JU67ndDVdFWPhB0GbxNkWlOE github.com/gen2brain/jpegn v0.6.1/go.mod h1:43hks+w5VNTUDU34uk0tsXYJ97nbYL2idAlZF0D66+A= github.com/gen2brain/jxl v0.2.0 h1:cXSQnfbcC0JGFzaI344VzPMbe7mh6rYc0tjPcBUsE4U= github.com/gen2brain/jxl v0.2.0/go.mod h1:VjJHRai/8I8Es01mULqyiOihRBOjJr1Zo+NoN/MyIwo= +github.com/gen2brain/pngn v0.1.2 h1:j1ikFmwRpJnVxnFcwekIMYzBLOsEXDVrOSHCwqQcnV8= +github.com/gen2brain/pngn v0.1.2/go.mod h1:jmw3LV2MHgoK4PBdsLC3YTiLUBaY5Nlfi3UFvxqJc9E= github.com/gen2brain/vpx v0.2.1 h1:UD6tibcs/zlaIOKNFXeVyZuHBEaW9GYfxKSxvAN9cc8= github.com/gen2brain/vpx v0.2.1/go.mod h1:EVIdqguMSiapbtjDm4AWgFgYYJ4d+k8trXqjxYZ/4XE= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= diff --git a/cmd/cbconvert-gui/main.go b/cmd/cbconvert-gui/main.go index 48e9674..4d79ba5 100644 --- a/cmd/cbconvert-gui/main.go +++ b/cmd/cbconvert-gui/main.go @@ -5,7 +5,6 @@ import ( _ "embed" "flag" "fmt" - "image/png" "os" "path/filepath" "runtime/debug" @@ -14,6 +13,7 @@ import ( "github.com/gen2brain/cbconvert" "github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n" "github.com/gen2brain/iup-go/iup" + "github.com/gen2brain/pngn" ) //go:generate rsrc --ico dist/windows/icon.ico --arch amd64 -o main_windows_amd64.syso @@ -85,7 +85,7 @@ func main() { config = iup.Config() iup.ConfigLoad(config) - img, _ := png.Decode(bytes.NewReader(appLogo)) + img, _ := pngn.Decode(bytes.NewReader(appLogo)) iup.ImageFromImage(img).SetHandle("logo") dlg := iup.Dialog(layout()).SetAttributes(fmt.Sprintf(`TITLE="CBconvert %s", ICON=logo`, appVersion)).SetHandle("dlg") diff --git a/go.mod b/go.mod index e8413a8..f1a4f63 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.26.4 require ( github.com/anthonynsimon/bild v0.15.0 - github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d github.com/dustin/go-humanize v1.0.1 github.com/fvbommel/sortorder v1.1.0 github.com/gen2brain/folio v0.2.4 github.com/gen2brain/gav1d v0.2.4 github.com/gen2brain/jxl v0.2.0 + github.com/gen2brain/pngn v0.1.2 github.com/gen2brain/vpx v0.2.1 github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 github.com/mholt/archives v0.1.5 @@ -24,12 +24,7 @@ require ( github.com/bodgit/sevenzip v1.6.4 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect - github.com/dsoprea/go-exif/v2 v2.0.0-20230826092837-6579e82b732d // indirect - github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect - github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349 // indirect github.com/gen2brain/jpegn v0.6.0 - github.com/go-errors/errors v1.5.1 // indirect - github.com/golang/geo v0.0.0-20260625163123-7c0e84413537 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/klauspost/compress v1.18.6 // indirect github.com/klauspost/pgzip v1.2.6 // indirect @@ -44,5 +39,4 @@ require ( go4.org v0.0.0-20260112195520-a5071408f32f // indirect golang.org/x/net v0.58.0 // indirect golang.org/x/text v0.41.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 57edcc5..d8c8fd7 100644 --- a/go.sum +++ b/go.sum @@ -16,22 +16,6 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E= -github.com/dsoprea/go-exif/v2 v2.0.0-20200604193436-ca8584a0e1c4/go.mod h1:9EXlPeHfblFFnwu5UOqmP2eoZfJyAZ2Ri/Vki33ajO0= -github.com/dsoprea/go-exif/v2 v2.0.0-20230826092837-6579e82b732d h1:yeH8wrJa3+8uKKDAdURHUK1ds2UvKhMqX2MiOdVeKPs= -github.com/dsoprea/go-exif/v2 v2.0.0-20230826092837-6579e82b732d/go.mod h1:oKrjk2kb3rAR5NbtSTLUMvMSbc+k8ZosI3MaVH47noc= -github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8= -github.com/dsoprea/go-exif/v3 v3.0.0-20210512043655-120bcdb2a55e/go.mod h1:cg5SNYKHMmzxsr9X6ZeLh/nfBRHHp5PngtEPcujONtk= -github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA= -github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8= -github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg= -github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8= -github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d h1:8+qI8ant/vZkNSsbwSjIR6XJfWcDVTg/qx/3pRUUZNA= -github.com/dsoprea/go-png-image-structure v0.0.0-20210512210324-29b889a6093d/go.mod h1:yTR3tKgyk20phAFg6IE9ulMA5NjEDD2wyx+okRFLVtw= -github.com/dsoprea/go-utility v0.0.0-20200711062821-fab8125e9bdf/go.mod h1:95+K3z2L0mqsVYd6yveIv1lmtT3tcQQ3dVakPySffW8= -github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349 h1:/py11NlxDaOxkT9OKN+gXgT+QOH5xj1ZRoyusfRIlo4= -github.com/dsoprea/go-utility v0.0.0-20221003172846-a3e1774ef349/go.mod h1:KVK+/Hul09ujXAGq+42UBgCTnXkiJZRnLYdURGjQUwo= -github.com/dsoprea/go-utility/v2 v2.0.0-20200717064901-2fccff4aa15e/go.mod h1:uAzdkPTub5Y9yQwXe8W4m2XuP0tK4a9Q/dantD0+uaU= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= @@ -44,23 +28,13 @@ github.com/gen2brain/jpegn v0.6.0 h1:MYVzF8A4Y5GoDNUotAq4uT4dUDQ0yEVYbcw9xFZgKk8 github.com/gen2brain/jpegn v0.6.0/go.mod h1:43hks+w5VNTUDU34uk0tsXYJ97nbYL2idAlZF0D66+A= github.com/gen2brain/jxl v0.2.0 h1:cXSQnfbcC0JGFzaI344VzPMbe7mh6rYc0tjPcBUsE4U= github.com/gen2brain/jxl v0.2.0/go.mod h1:VjJHRai/8I8Es01mULqyiOihRBOjJr1Zo+NoN/MyIwo= +github.com/gen2brain/pngn v0.1.2 h1:j1ikFmwRpJnVxnFcwekIMYzBLOsEXDVrOSHCwqQcnV8= +github.com/gen2brain/pngn v0.1.2/go.mod h1:jmw3LV2MHgoK4PBdsLC3YTiLUBaY5Nlfi3UFvxqJc9E= github.com/gen2brain/vpx v0.2.1 h1:UD6tibcs/zlaIOKNFXeVyZuHBEaW9GYfxKSxvAN9cc8= github.com/gen2brain/vpx v0.2.1/go.mod h1:EVIdqguMSiapbtjDm4AWgFgYYJ4d+k8trXqjxYZ/4XE= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= -github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= -github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= -github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= -github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= -github.com/golang/geo v0.0.0-20260625163123-7c0e84413537 h1:KeIaDS/+VEy/bhDYjG3Z78dOyLAU4HXcVxmd0WYHJTE= -github.com/golang/geo v0.0.0-20260625163123-7c0e84413537/go.mod h1:Mymr9kRGDc64JPr03TSZmuIBODZ3KyswLzm1xL0HFA8= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -104,30 +78,16 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= go4.org v0.0.0-20260112195520-a5071408f32f h1:ziUVAjmTPwQMBmYR1tbdRFJPtTcQUI12fH9QQjfb0Sw= go4.org v0.0.0-20260112195520-a5071408f32f/go.mod h1:ZRJnO5ZI4zAwMFp+dS1+V6J6MSyAowhRqAE+DPa1Xp0= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/image v0.43.0 h1:FLxcP4ec2350nTfOC8ysKtqYSIFbk/QGjw1ZHNP4tsY= golang.org/x/image v0.43.0/go.mod h1:rrpelvGFt+kLPAjPM4HeWPgrl0FtafueU//e5N0qk/Q= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=