package render import ( "bytes" "embed" "html/template" "time" "github.com/russross/blackfriday/v2" "beelloo/internal/invoice" ) //go:embed template.html style.css var assets embed.FS type renderItem struct { Designation template.HTML UnitPrice string Quantity string Amount string } type renderData struct { Seller invoice.Party Buyer invoice.Party Invoice invoice.InvoiceInfo InvoiceDate string InvoiceDescription template.HTML Items []renderItem TotalExclTax string Payment invoice.PaymentInfo CSS template.CSS CSSHref string } func RenderHTML(doc invoice.Document) (string, error) { cssBytes, err := assets.ReadFile("style.css") if err != nil { return "", err } return RenderHTMLWithCSS(doc, string(cssBytes)) } func RenderHTMLWithCSS(doc invoice.Document, css string) (string, error) { return renderHTML(doc, css, "") } func RenderHTMLWithCSSLink(doc invoice.Document, href string) (string, error) { return renderHTML(doc, "", href) } func renderHTML(doc invoice.Document, css string, href string) (string, error) { invoice.ComputeTotals(&doc) tmplBytes, err := assets.ReadFile("template.html") if err != nil { return "", err } tmpl, err := template.New("invoice").Parse(string(tmplBytes)) if err != nil { return "", err } data := renderData{ Seller: doc.Seller, Buyer: doc.Buyer, Invoice: doc.Invoice, InvoiceDate: formatDate(doc.Invoice.Date), InvoiceDescription: markdownHTML(doc.Invoice.Description), TotalExclTax: invoice.FormatMoney(doc.Totals.TotalExclTax), Payment: doc.Payment, CSS: template.CSS(css), CSSHref: href, } for _, item := range doc.Items { data.Items = append(data.Items, renderItem{ Designation: markdownHTML(item.Designation), UnitPrice: invoice.FormatMoney(item.UnitPrice), Quantity: invoice.FormatQuantity(item.Quantity), Amount: invoice.FormatMoney(invoice.LineAmount(item)), }) } var buf bytes.Buffer if err := tmpl.Execute(&buf, data); err != nil { return "", err } return buf.String(), nil } func DefaultCSS() ([]byte, error) { return assets.ReadFile("style.css") } func markdownHTML(input string) template.HTML { output := blackfriday.Run([]byte(input)) return template.HTML(output) } func formatDate(date time.Time) string { if date.IsZero() { return "" } return date.Format("02/01/2006") }