@@ -5,11 +5,13 @@ import (
55 "math"
66 "os"
77 "path/filepath"
8+ "strings"
89 "time"
910
1011 "github.com/lucasepe/checkit/internal/parser"
1112 "github.com/lucasepe/checkit/internal/render"
1213 "github.com/lucasepe/x/text/slugify"
14+ "github.com/mattn/go-runewidth"
1315 "github.com/signintech/gopdf"
1416 "golang.org/x/image/font/gofont/gomono"
1517)
@@ -35,7 +37,7 @@ func New(opts ...RenderOption) (render.Renderer, error) {
3537 H : g .opts .pageHeight ,
3638 },
3739 })
38- err := g .doc .AddTTFFontData (fontName , gomono .TTF )
40+ err := g .doc .AddTTFFontData (defaultFontName , gomono .TTF )
3941 if err != nil {
4042 return g , err
4143 }
@@ -47,12 +49,10 @@ func New(opts ...RenderOption) (render.Renderer, error) {
4749}
4850
4951const (
50- fontName = "GoMono"
51- symbol = "\u25CB " // ○
52- itemIndent = " " // Indent for wrapped lines
53- itemNoteIndent = " " // Indent for wrapped lines
54-
55- defaultCreator = "Check IT (github.com/lucasepe/checkit)"
52+ defaultFontName = "GoMono"
53+ defaultSymbol = " \u25CB " // ○
54+ defaultLineSpacingRatio = 0.5
55+ defaultCreator = "Check IT (github.com/lucasepe/checkit)"
5656)
5757
5858var _ render.Renderer = (* pdfRenderImpl )(nil )
@@ -83,6 +83,13 @@ func (g *pdfRenderImpl) Render(lst *parser.CheckList) (err error) {
8383 return err
8484 }
8585
86+ for _ , el := range grp .Notes {
87+ y , err = g .handleGroupNote (y , el )
88+ if err != nil {
89+ return err
90+ }
91+ }
92+
8693 for _ , it := range grp .Items {
8794 y , err = g .handleItem (y , it .Title )
8895 if err != nil {
@@ -105,12 +112,9 @@ func (g *pdfRenderImpl) setup() error {
105112 fontSize := 0.02 * math .Min (g .opts .pageWidth , g .opts .pageHeight )
106113
107114 g .opts .itemFontSize = fontSize
108- g .opts .lineSpacing = 0.5 * fontSize
109- g .opts .itemMargin = 0.8 * fontSize
110115 g .opts .itemNoteFontSize = 0.75 * fontSize
111- g .opts .itemNoteMargin = 1.15 * (0.75 * fontSize )
112116 g .opts .groupTitleFontSize = fontSize + 4
113- g .opts .groupTitleMargin = 1.1 * ( fontSize + 4 )
117+ g .opts .groupNoteFontSize = fontSize + 2
114118 g .opts .documentTitleFontSize = (fontSize + 4 ) + 4
115119
116120 return os .MkdirAll (g .outputDir , 0755 )
@@ -135,130 +139,78 @@ func (g *pdfRenderImpl) setMeta(title string) {
135139 })
136140}
137141
138- func (g * pdfRenderImpl ) handleGroup (y float64 , title string ) (float64 , error ) {
139- if y + g .opts .groupTitleFontSize + g .opts .lineSpacing > g .opts .pageHeight - g .opts .marginBottom {
140- g .doc .AddPage ()
141- g .pageCount ++
142-
143- y = g .opts .marginTop
144- } else {
145- y += g .opts .groupTitleMargin
146- }
147-
148- g .doc .SetTextColor (53 , 57 , 53 )
149-
150- g .doc .SetFont (fontName , "" , g .opts .groupTitleFontSize )
151- g .doc .SetX (g .opts .marginLeft )
152- g .doc .SetY (y )
153- g .doc .Text (title )
154-
155- y += g .opts .groupTitleFontSize //+ 0.5*g.opts.groupTitleMargin
156-
157- return y , nil
158- }
159-
160142func (g * pdfRenderImpl ) handleDocumentTitle (y float64 , title string ) (float64 , error ) {
161143 g .filename = fmt .Sprintf ("%s.pdf" , slugify .Sprint (title ))
162144
163- err := g .doc .SetFont (fontName , "" , g .opts .documentTitleFontSize )
164- if err != nil {
165- return y , err
166- }
167-
168- // Calcola larghezza testo
169- tw , err := g .doc .MeasureTextWidth (title )
170- if err != nil {
171- return y , err
172- }
173-
174- th , err := g .doc .MeasureCellHeightByText (title )
175- if err != nil {
176- return y , err
177- }
178-
179- y += th
145+ prefix := ""
146+ y += defaultLineSpacingRatio * g .opts .documentTitleFontSize
147+ return g .renderText (y , title , prefix , g .opts .documentTitleFontSize , true , 53 , 57 , 53 )
148+ }
180149
181- // Centra il testo orizzontalmente
182- titleX := (g .opts .pageWidth - tw ) / 2
150+ func (g * pdfRenderImpl ) handleGroup (y float64 , title string ) (float64 , error ) {
151+ prefix := ""
152+ y += defaultLineSpacingRatio * g .opts .groupTitleFontSize
153+ return g .renderText (y , title , prefix , g .opts .groupTitleFontSize , false , 53 , 57 , 53 )
154+ }
183155
184- g .doc .SetTextColor (112 , 128 , 144 )
156+ func (g * pdfRenderImpl ) handleGroupNote (y float64 , line string ) (float64 , error ) {
157+ prefix := " "
158+ return g .renderText (y , line , prefix , g .opts .groupNoteFontSize , false , 178 , 190 , 181 )
159+ }
185160
186- // Posiziona in alto
187- g .doc .SetX (titleX )
188- g .doc .SetY (y )
189- g .doc .Text (title )
161+ func (g * pdfRenderImpl ) handleItem (y float64 , line string ) (float64 , error ) {
162+ prefix := defaultSymbol
190163
191- // Sposta `y` sotto il titolo
192- y += g . opts . documentTitleFontSize + g . opts . groupTitleMargin
164+ return g . renderText ( y , line , prefix , g . opts . itemFontSize , false , 54 , 69 , 79 )
165+ }
193166
194- return y , nil
167+ func (g * pdfRenderImpl ) handleItemNote (y float64 , line string ) (float64 , error ) {
168+ prefix := strings .Repeat (" " , 5 )
169+ return g .renderText (y , line , prefix , g .opts .itemNoteFontSize , false , 132 , 136 , 139 )
195170}
196171
197- func (g * pdfRenderImpl ) handleItem (y float64 , line string ) (float64 , error ) {
198- err := g .doc .SetFont (fontName , "" , g . opts . itemFontSize ) // reset to item font
172+ func (rdr * pdfRenderImpl ) renderText (y float64 , line string , firstPrefix string , fontSize float64 , center bool , r , g , b uint8 ) (float64 , error ) {
173+ err := rdr .doc .SetFont (defaultFontName , "" , fontSize )
199174 if err != nil {
200175 return y , err
201176 }
202177
203- g .doc .SetTextColor (54 , 69 , 79 )
178+ rdr .doc .SetTextColor (r , g , b )
204179
205- prefix := fmt . Sprintf (" %s " , symbol )
206- maxTextWidth := g .opts .pageWidth - 2 * g .opts .marginLeft
207- wrappedLines := wrapTextWithPrefix (g .doc , line , prefix , itemIndent , maxTextWidth )
180+ indent := strings . Repeat (" " , runewidth . StringWidth ( firstPrefix ) )
181+ maxTextWidth := rdr .opts .pageWidth - 2 * rdr .opts .marginLeft
182+ wrappedLines := wrapTextWithPrefix (rdr .doc , line , firstPrefix , indent , maxTextWidth )
208183
209- y += g . opts . itemMargin
184+ deltaY := defaultLineSpacingRatio * fontSize
210185
211186 for _ , l := range wrappedLines {
212- if y + g .opts .itemFontSize + g .opts .lineSpacing > g .opts .pageHeight - g .opts .marginBottom {
213- g .doc .AddPage ()
214- g .pageCount ++
215187
216- th , err := g .doc .MeasureCellHeightByText (l )
188+ if y + fontSize + 2 * deltaY > rdr .opts .pageHeight - rdr .opts .marginBottom {
189+ rdr .doc .AddPage ()
190+ rdr .pageCount ++
191+ y = rdr .opts .marginTop
192+ }
193+
194+ x := rdr .opts .marginLeft
195+ if center {
196+ tw , err := rdr .doc .MeasureTextWidth (l )
217197 if err != nil {
218198 return y , err
219199 }
220200
221- y = g .opts .marginTop + th
222- }
223-
224- g .doc .SetX (g .opts .marginLeft )
225- g .doc .SetY (y )
226- g .doc .Text (l )
227- y += g .opts .itemFontSize + g .opts .itemMargin
228- }
229-
230- return y , nil
231- }
232-
233- func (g * pdfRenderImpl ) handleItemNote (y float64 , line string ) (float64 , error ) {
234- err := g .doc .SetFont (fontName , "" , g .opts .itemNoteFontSize ) // reset to item font
235- if err != nil {
236- return y , err
237- }
238-
239- g .doc .SetTextColor (132 , 136 , 139 )
240-
241- maxTextWidth := g .opts .pageWidth - 2 * g .opts .marginLeft
242- wrappedLines := wrapTextWithPrefix (g .doc , line , itemNoteIndent , itemNoteIndent , maxTextWidth )
243-
244- for _ , l := range wrappedLines {
245- if y + g .opts .itemNoteFontSize + g .opts .lineSpacing > g .opts .pageHeight - g .opts .marginBottom {
246- g .doc .AddPage ()
247- g .pageCount ++
248- y = g .opts .marginTop
201+ x = ((rdr .opts .pageWidth - rdr .opts .marginLeft ) - tw ) / 2
249202 }
250-
251- g .doc .SetX (g .opts .marginLeft )
252- g .doc .SetY (y )
253- g .doc .Text (l )
254- y += g .opts .itemNoteFontSize + g .opts .itemNoteMargin
203+ rdr .doc .SetX (x )
204+ rdr .doc .SetY (y + deltaY )
205+ rdr .doc .Text (l )
206+ y += (fontSize + 2 * deltaY )
255207 }
256208
257209 return y , nil
258210}
259211
260212func (g * pdfRenderImpl ) savePDF () error {
261- err := g .doc .SetFont (fontName , "" , 8.0 )
213+ err := g .doc .SetFont (defaultFontName , "" , 8.0 )
262214 if err != nil {
263215 return err
264216 }
0 commit comments