From 0c8e54f0c453311af20c9626edb4f6450c291b45 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Mon, 13 May 2024 13:27:34 +0200 Subject: [PATCH] limit usage of Sprint --- internal/pkg/converter/converter.go | 6 +- internal/pkg/converter/options.go | 29 +++++---- internal/pkg/converter/profiles.go | 10 +++- internal/pkg/epub/epub.go | 30 +++++----- internal/pkg/epubimage/epub_image.go | 35 ++++++----- internal/pkg/epubimageprocessor/loader.go | 2 +- internal/pkg/epubimageprocessor/processor.go | 3 +- internal/pkg/epuboptions/epub_options.go | 4 +- internal/pkg/epuboptions/image.go | 4 ++ internal/pkg/epuboptions/view.go | 12 ++++ internal/pkg/epubprogress/epub_progress.go | 10 +++- internal/pkg/epubtemplates/content.go | 17 +++--- internal/pkg/utils/utils.go | 32 ++++++++++ internal/pkg/utils/utils_test.go | 62 ++++++++++++++++++++ 14 files changed, 190 insertions(+), 66 deletions(-) create mode 100644 internal/pkg/utils/utils_test.go diff --git a/internal/pkg/converter/converter.go b/internal/pkg/converter/converter.go index 1722a05..0f1a66e 100644 --- a/internal/pkg/converter/converter.go +++ b/internal/pkg/converter/converter.go @@ -104,7 +104,7 @@ func (c *Converter) InitParse() { c.AddStringParam(&c.Options.Title, "title", "", "Title of the EPUB") c.AddSection("Config") - c.AddStringParam(&c.Options.Profile, "profile", c.Options.Profile, fmt.Sprintf("Profile to use: \n%s", c.Options.AvailableProfiles())) + c.AddStringParam(&c.Options.Profile, "profile", c.Options.Profile, "Profile to use: \n"+c.Options.AvailableProfiles()) c.AddIntParam(&c.Options.Quality, "quality", c.Options.Quality, "Quality of the image") c.AddBoolParam(&c.Options.Grayscale, "grayscale", c.Options.Grayscale, "Grayscale image. Ideal for eInk devices.") c.AddIntParam(&c.Options.GrayscaleMode, "grayscale-mode", c.Options.GrayscaleMode, "Grayscale Mode\n0 = normal\n1 = average\n2 = luminance") @@ -298,10 +298,10 @@ func (c *Converter) Validate() error { var defaultOutput string inputBase := filepath.Clean(c.Options.Input) if fi.IsDir() { - defaultOutput = fmt.Sprintf("%s.epub", inputBase) + defaultOutput = inputBase + ".epub" } else { ext := filepath.Ext(inputBase) - defaultOutput = fmt.Sprintf("%s.epub", inputBase[0:len(inputBase)-len(ext)]) + defaultOutput = inputBase[0:len(inputBase)-len(ext)] + ".epub" } if c.Options.Output == "" { diff --git a/internal/pkg/converter/options.go b/internal/pkg/converter/options.go index 4e06c9e..4381bde 100644 --- a/internal/pkg/converter/options.go +++ b/internal/pkg/converter/options.go @@ -9,6 +9,8 @@ import ( "strings" "gopkg.in/yaml.v3" + + "github.com/celogeek/go-comic-converter/v2/internal/pkg/utils" ) type Options struct { @@ -217,13 +219,7 @@ func (o *Options) ShowConfig() string { var profileDesc string profile := o.GetProfile() if profile != nil { - profileDesc = fmt.Sprintf( - "%s - %s - %dx%d", - o.Profile, - profile.Description, - profile.Width, - profile.Height, - ) + profileDesc = profile.String() } sortpathmode := "" @@ -238,10 +234,10 @@ func (o *Options) ShowConfig() string { aspectRatio := "auto" if o.AspectRatio > 0 { - aspectRatio = fmt.Sprintf("1:%.02f", o.AspectRatio) + aspectRatio = "1:" + utils.FloatToString(o.AspectRatio, 2) } else if o.AspectRatio < 0 { if profile != nil { - aspectRatio = fmt.Sprintf("1:%0.2f (device)", float64(profile.Height)/float64(profile.Width)) + aspectRatio = "1:" + utils.FloatToString(float64(profile.Height)/float64(profile.Width), 2) + " (device)" } else { aspectRatio = "1:?? (device)" } @@ -277,7 +273,14 @@ func (o *Options) ShowConfig() string { {"Grayscale", o.Grayscale, true}, {"Grayscale mode", grayscaleMode, o.Grayscale}, {"Crop", o.Crop, true}, - {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - Limit %d%% - Skip %v", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit, o.CropSkipIfLimitReached), o.Crop}, + {"Crop ratio", + utils.IntToString(o.CropRatioLeft) + " Left - " + + utils.IntToString(o.CropRatioUp) + " Up - " + + utils.IntToString(o.CropRatioRight) + " Right - " + + utils.IntToString(o.CropRatioBottom) + " Bottom - " + + "Limit " + utils.IntToString(o.CropLimit) + "% - " + + "Skip " + utils.BoolToString(o.CropSkipIfLimitReached), + o.Crop}, {"Brightness", o.Brightness, o.Brightness != 0}, {"Contrast", o.Contrast, o.Contrast != 0}, {"Auto contrast", o.AutoContrast, true}, @@ -288,11 +291,11 @@ func (o *Options) ShowConfig() string { {"No blank image", o.NoBlankImage, true}, {"Manga", o.Manga, true}, {"Has cover", o.HasCover, true}, - {"Limit", fmt.Sprintf("%d Mb", o.LimitMb), o.LimitMb != 0}, + {"Limit", utils.IntToString(o.LimitMb) + " Mb", o.LimitMb != 0}, {"Strip first directory from toc", o.StripFirstDirectoryFromToc, true}, {"Sort path mode", sortpathmode, true}, - {"Foreground color", fmt.Sprintf("#%s", o.ForegroundColor), true}, - {"Background color", fmt.Sprintf("#%s", o.BackgroundColor), true}, + {"Foreground color", "#" + o.ForegroundColor, true}, + {"Background color", "#" + o.BackgroundColor, true}, {"Resize", !o.NoResize, true}, {"Aspect ratio", aspectRatio, true}, {"Portrait only", o.PortraitOnly, true}, diff --git a/internal/pkg/converter/profiles.go b/internal/pkg/converter/profiles.go index c01a09b..4029840 100644 --- a/internal/pkg/converter/profiles.go +++ b/internal/pkg/converter/profiles.go @@ -4,6 +4,8 @@ package converter import ( "fmt" "strings" + + "github.com/celogeek/go-comic-converter/v2/internal/pkg/utils" ) type Profile struct { @@ -13,6 +15,10 @@ type Profile struct { Height int `json:"height"` } +func (p Profile) String() string { + return p.Code + " - " + p.Description + " - " + utils.IntToString(p.Width) + "x" + utils.IntToString(p.Height) +} + type Profiles map[string]Profile // NewProfiles Initialize list of all supported profiles. @@ -61,9 +67,9 @@ func (p Profiles) String() string { s := make([]string, 0) for _, v := range p { s = append(s, fmt.Sprintf( - " - %-7s ( %9s ) - %s", + " - %-7s - %4d x %-4d - %s", v.Code, - fmt.Sprintf("%dx%d", v.Width, v.Height), + v.Width, v.Height, v.Description, )) } diff --git a/internal/pkg/epub/epub.go b/internal/pkg/epub/epub.go index b72be7a..a7503b5 100644 --- a/internal/pkg/epub/epub.go +++ b/internal/pkg/epub/epub.go @@ -73,8 +73,8 @@ func (e EPUB) writeImage(wz epubzip.EPUBZip, img epubimage.EPUBImage, zipImg *zi err := wz.WriteContent( img.EPUBPagePath(), []byte(e.render(epubtemplates.Text, map[string]any{ - "Title": fmt.Sprintf("Image %d Part %d", img.Id, img.Part), - "ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height), + "Title": "Image " + utils.IntToString(img.Id) + " Part " + utils.IntToString(img.Part), + "ViewPort": e.Image.View.Port(), "ImagePath": img.ImgPath(), "ImageStyle": img.ImgStyle(e.Image.View.Width, e.Image.View.Height, ""), })), @@ -91,8 +91,8 @@ func (e EPUB) writeBlank(wz epubzip.EPUBZip, img epubimage.EPUBImage) error { return wz.WriteContent( img.EPUBSpacePath(), []byte(e.render(epubtemplates.Blank, map[string]any{ - "Title": fmt.Sprintf("Blank Page %d", img.Id), - "ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height), + "Title": "Blank Page " + utils.IntToString(img.Id), + "ViewPort": e.Image.View.Port(), })), ) } @@ -102,16 +102,16 @@ func (e EPUB) writeCoverImage(wz epubzip.EPUBZip, img epubimage.EPUBImage, part, title := "Cover" text := "" if totalParts > 1 { - text = fmt.Sprintf("%d / %d", part, totalParts) - title = fmt.Sprintf("%s %s", title, text) + text = utils.IntToString(part) + " / " + utils.IntToString(totalParts) + title = title + " " + text } if err := wz.WriteContent( "OEBPS/Text/cover.xhtml", []byte(e.render(epubtemplates.Text, map[string]any{ "Title": title, - "ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height), - "ImagePath": fmt.Sprintf("Images/cover.%s", e.Image.Format), + "ViewPort": e.Image.View.Port(), + "ImagePath": "Images/cover." + e.Image.Format, "ImageStyle": img.ImgStyle(e.Image.View.Width, e.Image.View.Height, ""), })), ); err != nil { @@ -156,7 +156,7 @@ func (e EPUB) writeTitleImage(wz epubzip.EPUBZip, img epubimage.EPUBImage, title "OEBPS/Text/space_title.xhtml", []byte(e.render(epubtemplates.Blank, map[string]any{ "Title": "Blank Page Title", - "ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height), + "ViewPort": e.Image.View.Port(), })), ); err != nil { return err @@ -167,8 +167,8 @@ func (e EPUB) writeTitleImage(wz epubzip.EPUBZip, img epubimage.EPUBImage, title "OEBPS/Text/title.xhtml", []byte(e.render(epubtemplates.Text, map[string]any{ "Title": title, - "ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height), - "ImagePath": fmt.Sprintf("Images/title.%s", e.Image.Format), + "ViewPort": e.Image.View.Port(), + "ImagePath": "Images/title." + e.Image.Format, "ImageStyle": img.ImgStyle(e.Image.View.Width, e.Image.View.Height, titleAlign), })), ); err != nil { @@ -344,7 +344,7 @@ func (e EPUB) writePart(path string, currentPart, totalParts int, part epubPart, title := e.Title if totalParts > 1 { - title = fmt.Sprintf("%s [%d/%d]", title, currentPart, totalParts) + title = title + " [" + utils.IntToString(currentPart) + "/" + utils.IntToString(totalParts) + "]" } type zipContent struct { @@ -450,12 +450,12 @@ func (e EPUB) Write() error { ext := filepath.Ext(e.Output) suffix := "" if totalParts > 1 { - fmtLen := len(fmt.Sprint(totalParts)) - fmtPart := fmt.Sprintf(" Part %%0%dd of %%0%dd", fmtLen, fmtLen) + fmtLen := utils.FormatNumberOfDigits(totalParts) + fmtPart := "Part " + fmtLen + " of " + fmtLen suffix = fmt.Sprintf(fmtPart, i+1, totalParts) } - path := fmt.Sprintf("%s%s%s", e.Output[0:len(e.Output)-len(ext)], suffix, ext) + path := e.Output[0:len(e.Output)-len(ext)] + suffix + ext if err := e.writePart( path, diff --git a/internal/pkg/epubimage/epub_image.go b/internal/pkg/epubimage/epub_image.go index fe33cf2..6e8742c 100644 --- a/internal/pkg/epubimage/epub_image.go +++ b/internal/pkg/epubimage/epub_image.go @@ -2,9 +2,10 @@ package epubimage import ( - "fmt" "image" "strings" + + "github.com/celogeek/go-comic-converter/v2/internal/pkg/utils" ) type EPUBImage struct { @@ -25,47 +26,51 @@ type EPUBImage struct { // SpaceKey key name of the blank page after the image func (i EPUBImage) SpaceKey() string { - return fmt.Sprintf("space_%d", i.Id) + return "space_" + utils.IntToString(i.Id) } // SpacePath path of the blank page func (i EPUBImage) SpacePath() string { - return fmt.Sprintf("Text/%s.xhtml", i.SpaceKey()) + return "Text/" + i.SpaceKey() + ".xhtml" } // EPUBSpacePath path of the blank page into the EPUB func (i EPUBImage) EPUBSpacePath() string { - return fmt.Sprintf("OEBPS/%s", i.SpacePath()) + return "OEBPS/" + i.SpacePath() +} + +func (i EPUBImage) PartKey() string { + return utils.IntToString(i.Id) + "_p" + utils.IntToString(i.Part) } // PageKey key for page func (i EPUBImage) PageKey() string { - return fmt.Sprintf("page_%d_p%d", i.Id, i.Part) + return "page_" + i.PartKey() } // PagePath page path linked to the image func (i EPUBImage) PagePath() string { - return fmt.Sprintf("Text/%s.xhtml", i.PageKey()) + return "Text/" + i.PageKey() + ".xhtml" } // EPUBPagePath page path into the EPUB func (i EPUBImage) EPUBPagePath() string { - return fmt.Sprintf("OEBPS/%s", i.PagePath()) + return "OEBPS/" + i.PagePath() } // ImgKey key for image func (i EPUBImage) ImgKey() string { - return fmt.Sprintf("img_%d_p%d", i.Id, i.Part) + return "img_" + i.PartKey() } // ImgPath image path func (i EPUBImage) ImgPath() string { - return fmt.Sprintf("Images/%s.%s", i.ImgKey(), i.Format) + return "Images/" + i.ImgKey() + "." + i.Format } // EPUBImgPath image path into the EPUB func (i EPUBImage) EPUBImgPath() string { - return fmt.Sprintf("OEBPS/%s", i.ImgPath()) + return "OEBPS/" + i.ImgPath() } // ImgStyle style to apply to the image. @@ -76,11 +81,11 @@ func (i EPUBImage) ImgStyle(viewWidth, viewHeight int, align string) string { relWidth, relHeight := i.RelSize(viewWidth, viewHeight) marginW, marginH := float64(viewWidth-relWidth)/2, float64(viewHeight-relHeight)/2 - var style []string + style := make([]string, 0, 4) - style = append(style, fmt.Sprintf("width:%dpx", relWidth)) - style = append(style, fmt.Sprintf("height:%dpx", relHeight)) - style = append(style, fmt.Sprintf("top:%.2f%%", marginH*100/float64(viewHeight))) + style = append(style, "width:"+utils.IntToString(relWidth)+"px") + style = append(style, "height:"+utils.IntToString(relHeight)+"px") + style = append(style, "top:"+utils.FloatToString(marginH*100/float64(viewHeight), 2)+"%") if align == "" { switch i.Position { case "rendition:page-spread-left": @@ -88,7 +93,7 @@ func (i EPUBImage) ImgStyle(viewWidth, viewHeight int, align string) string { case "rendition:page-spread-right": style = append(style, "left:0") default: - style = append(style, fmt.Sprintf("left:%.2f%%", marginW*100/float64(viewWidth))) + style = append(style, "left:"+utils.FloatToString(marginW*100/float64(viewWidth), 2)+"%") } } else { style = append(style, align) diff --git a/internal/pkg/epubimageprocessor/loader.go b/internal/pkg/epubimageprocessor/loader.go index cfdf7e1..a317725 100644 --- a/internal/pkg/epubimageprocessor/loader.go +++ b/internal/pkg/epubimageprocessor/loader.go @@ -404,7 +404,7 @@ func (e EPUBImageProcessor) loadPdf() (totalImages int, output chan task, err er } totalImages = len(pdf.Pages()) - pageFmt := fmt.Sprintf("page %%0%dd", len(fmt.Sprintf("%d", totalImages))) + pageFmt := "page " + utils.FormatNumberOfDigits(totalImages) output = make(chan task) go func() { defer close(output) diff --git a/internal/pkg/epubimageprocessor/processor.go b/internal/pkg/epubimageprocessor/processor.go index daf92b7..104d80c 100644 --- a/internal/pkg/epubimageprocessor/processor.go +++ b/internal/pkg/epubimageprocessor/processor.go @@ -2,7 +2,6 @@ package epubimageprocessor import ( - "fmt" "image" "image/color" "image/draw" @@ -324,7 +323,7 @@ func (e EPUBImageProcessor) CoverTitleData(o CoverTitleDataOptions) (epubzip.Ima g.Draw(dst, o.Src) return epubzip.CompressImage( - fmt.Sprintf("OEBPS/Images/%s.%s", o.Name, e.Image.Format), + "OEBPS/Images/"+o.Name+"."+e.Image.Format, e.Image.Format, dst, e.Image.Quality, diff --git a/internal/pkg/epuboptions/epub_options.go b/internal/pkg/epuboptions/epub_options.go index 8018566..28e3ee1 100644 --- a/internal/pkg/epuboptions/epub_options.go +++ b/internal/pkg/epuboptions/epub_options.go @@ -1,8 +1,6 @@ // Package epuboptions EPUBOptions for EPUB creation. package epuboptions -import "fmt" - type EPUBOptions struct { Input string Output string @@ -29,5 +27,5 @@ func (o EPUBOptions) WorkersRatio(pct int) (nbWorkers int) { } func (o EPUBOptions) ImgStorage() string { - return fmt.Sprintf("%s.tmp", o.Output) + return o.Output + ".tmp" } diff --git a/internal/pkg/epuboptions/image.go b/internal/pkg/epuboptions/image.go index 807d583..ff16a30 100644 --- a/internal/pkg/epuboptions/image.go +++ b/internal/pkg/epuboptions/image.go @@ -20,3 +20,7 @@ type Image struct { Format string AppleBookCompatibility bool } + +func (i Image) MediaType() string { + return "image/" + i.Format +} diff --git a/internal/pkg/epuboptions/view.go b/internal/pkg/epuboptions/view.go index d2fbdd5..1fbc841 100644 --- a/internal/pkg/epuboptions/view.go +++ b/internal/pkg/epuboptions/view.go @@ -1,8 +1,20 @@ package epuboptions +import ( + "github.com/celogeek/go-comic-converter/v2/internal/pkg/utils" +) + type View struct { Width, Height int AspectRatio float64 PortraitOnly bool Color Color } + +func (v View) Dimension() string { + return utils.IntToString(v.Width) + "x" + utils.IntToString(v.Height) +} + +func (v View) Port() string { + return "width=" + utils.IntToString(v.Width) + ",height=" + utils.IntToString(v.Height) +} diff --git a/internal/pkg/epubprogress/epub_progress.go b/internal/pkg/epubprogress/epub_progress.go index 0cefb67..272fc45 100644 --- a/internal/pkg/epubprogress/epub_progress.go +++ b/internal/pkg/epubprogress/epub_progress.go @@ -38,15 +38,19 @@ func New(o Options) EPUBProgress { } } - fmtJob := fmt.Sprintf("%%0%dd", len(fmt.Sprint(o.TotalJob))) - fmtDesc := fmt.Sprintf("[%s/%s] %%-15s", fmtJob, fmtJob) + fmtJob := utils.FormatNumberOfDigits(o.TotalJob) return progressbar.NewOptions(o.Max, progressbar.OptionSetWriter(os.Stderr), progressbar.OptionThrottle(65*time.Millisecond), progressbar.OptionOnCompletion(func() { utils.Println() }), - progressbar.OptionSetDescription(fmt.Sprintf(fmtDesc, o.CurrentJob, o.TotalJob, o.Description)), + progressbar.OptionSetDescription(fmt.Sprintf( + "["+fmtJob+"/"+fmtJob+"] %-15s", + o.CurrentJob, + o.TotalJob, + o.Description, + )), progressbar.OptionSetWidth(60), progressbar.OptionShowCount(), progressbar.OptionSetRenderBlankState(true), diff --git a/internal/pkg/epubtemplates/content.go b/internal/pkg/epubtemplates/content.go index c263f09..0075812 100644 --- a/internal/pkg/epubtemplates/content.go +++ b/internal/pkg/epubtemplates/content.go @@ -1,12 +1,11 @@ package epubtemplates import ( - "fmt" - "github.com/beevik/etree" "github.com/celogeek/go-comic-converter/v2/internal/pkg/epubimage" "github.com/celogeek/go-comic-converter/v2/internal/pkg/epuboptions" + "github.com/celogeek/go-comic-converter/v2/internal/pkg/utils" ) type Content struct { @@ -98,9 +97,9 @@ func (o Content) getMeta() []tag { {"meta", tagAttrs{"property": "schema:accessibilityHazard"}, "noSoundHazard"}, {"meta", tagAttrs{"name": "book-type", "content": "comic"}, ""}, {"opf:meta", tagAttrs{"name": "fixed-layout", "content": "true"}, ""}, - {"opf:meta", tagAttrs{"name": "original-resolution", "content": fmt.Sprintf("%dx%d", o.ImageOptions.View.Width, o.ImageOptions.View.Height)}, ""}, + {"opf:meta", tagAttrs{"name": "original-resolution", "content": o.ImageOptions.View.Dimension()}, ""}, {"dc:title", tagAttrs{}, o.Title}, - {"dc:identifier", tagAttrs{"id": "ean"}, fmt.Sprintf("urn:uuid:%s", o.UID)}, + {"dc:identifier", tagAttrs{"id": "ean"}, "urn:uuid:" + o.UID}, {"dc:language", tagAttrs{}, "en"}, {"dc:creator", tagAttrs{}, o.Author}, {"dc:publisher", tagAttrs{}, o.Publisher}, @@ -134,7 +133,7 @@ func (o Content) getMeta() []tag { metas = append( metas, tag{"meta", tagAttrs{"name": "calibre:series", "content": o.Title}, ""}, - tag{"meta", tagAttrs{"name": "calibre:series_index", "content": fmt.Sprint(o.Current)}, ""}, + tag{"meta", tagAttrs{"name": "calibre:series_index", "content": utils.IntToString(o.Current)}, ""}, ) } @@ -145,7 +144,7 @@ func (o Content) getManifest() []tag { var imageTags, pageTags, spaceTags []tag addTag := func(img epubimage.EPUBImage, withSpace bool) { imageTags = append(imageTags, - tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": fmt.Sprintf("image/%s", o.ImageOptions.Format)}, ""}, + tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": o.ImageOptions.MediaType()}, ""}, ) pageTags = append(pageTags, tag{"item", tagAttrs{"id": img.PageKey(), "href": img.PagePath(), "media-type": "application/xhtml+xml"}, ""}, @@ -161,13 +160,13 @@ func (o Content) getManifest() []tag { {"item", tagAttrs{"id": "toc", "href": "toc.xhtml", "properties": "nav", "media-type": "application/xhtml+xml"}, ""}, {"item", tagAttrs{"id": "css", "href": "Text/style.css", "media-type": "text/css"}, ""}, {"item", tagAttrs{"id": "page_cover", "href": "Text/cover.xhtml", "media-type": "application/xhtml+xml"}, ""}, - {"item", tagAttrs{"id": "img_cover", "href": fmt.Sprintf("Images/cover.%s", o.ImageOptions.Format), "media-type": fmt.Sprintf("image/%s", o.ImageOptions.Format)}, ""}, + {"item", tagAttrs{"id": "img_cover", "href": "Images/cover." + o.ImageOptions.Format, "media-type": o.ImageOptions.MediaType()}, ""}, } if o.HasTitlePage { items = append(items, tag{"item", tagAttrs{"id": "page_title", "href": "Text/title.xhtml", "media-type": "application/xhtml+xml"}, ""}, - tag{"item", tagAttrs{"id": "img_title", "href": fmt.Sprintf("Images/title.%s", o.ImageOptions.Format), "media-type": fmt.Sprintf("image/%s", o.ImageOptions.Format)}, ""}, + tag{"item", tagAttrs{"id": "img_title", "href": "Images/title." + o.ImageOptions.Format, "media-type": o.ImageOptions.MediaType()}, ""}, ) if !o.ImageOptions.View.PortraitOnly { @@ -212,7 +211,7 @@ func (o Content) getSpineAuto() []tag { } } getSpreadBlank := func() string { - return fmt.Sprintf("%s layout-blank", getSpread(false)) + return getSpread(false) + " layout-blank" } var spine []tag diff --git a/internal/pkg/utils/utils.go b/internal/pkg/utils/utils.go index 5a55a37..da2d2b3 100644 --- a/internal/pkg/utils/utils.go +++ b/internal/pkg/utils/utils.go @@ -3,6 +3,7 @@ package utils import ( "fmt" "os" + "strconv" ) func Printf(format string, a ...interface{}) { @@ -12,3 +13,34 @@ func Printf(format string, a ...interface{}) { func Println(a ...interface{}) { _, _ = fmt.Fprintln(os.Stderr, a...) } + +func IntToString(i int) string { + return strconv.FormatInt(int64(i), 10) +} + +func FloatToString(f float64, precision int) string { + return strconv.FormatFloat(f, 'f', precision, 64) +} + +func BoolToString(b bool) string { + if b { + return "true" + } + return "false" +} + +func NumberOfDigits(i int) int { + x, count := 10, 1 + if i < 0 { + i = -i + count++ + } + for ; x <= i; count++ { + x *= 10 + } + return count +} + +func FormatNumberOfDigits(i int) string { + return "%0" + IntToString(NumberOfDigits(i)) + "d" +} diff --git a/internal/pkg/utils/utils_test.go b/internal/pkg/utils/utils_test.go new file mode 100644 index 0000000..09d825b --- /dev/null +++ b/internal/pkg/utils/utils_test.go @@ -0,0 +1,62 @@ +package utils + +import "fmt" + +func ExampleFloatToString() { + fmt.Println("test=" + FloatToString(3.14151617, 0) + "=") + fmt.Println("test=" + FloatToString(3.14151617, 1) + "=") + fmt.Println("test=" + FloatToString(3.14151617, 2) + "=") + fmt.Println("test=" + FloatToString(3.14151617, 4) + "=") + // Output: test=3= + // test=3.1= + // test=3.14= + // test=3.1415= +} + +func ExampleIntToString() { + fmt.Println("test=" + IntToString(159) + "=") + // Output: test=159= +} + +func ExampleNumberOfDigits() { + fmt.Println(NumberOfDigits(0)) + fmt.Println(NumberOfDigits(4)) + fmt.Println(NumberOfDigits(10)) + fmt.Println(NumberOfDigits(14)) + fmt.Println(NumberOfDigits(256)) + fmt.Println(NumberOfDigits(2004)) + fmt.Println(NumberOfDigits(-5)) + fmt.Println(NumberOfDigits(-10)) + fmt.Println(NumberOfDigits(-12)) + + // Output: 1 + // 1 + // 2 + // 2 + // 3 + // 4 + // 2 + // 3 + // 3 +} + +func ExampleFormatNumberOfDigits() { + fmt.Println(FormatNumberOfDigits(0)) + fmt.Println(FormatNumberOfDigits(4)) + fmt.Println(FormatNumberOfDigits(10)) + fmt.Println(FormatNumberOfDigits(14)) + fmt.Println(FormatNumberOfDigits(256)) + fmt.Println(FormatNumberOfDigits(2004)) + fmt.Println(FormatNumberOfDigits(-5)) + fmt.Println(FormatNumberOfDigits(-10)) + fmt.Println(FormatNumberOfDigits(-12)) + // Output: %01d + // %01d + // %02d + // %02d + // %03d + // %04d + // %02d + // %03d + // %03d +}