diff --git a/debian/control b/debian/control index 60b7b91..b1ceaeb 100644 --- a/debian/control +++ b/debian/control @@ -10,8 +10,9 @@ Build-Depends: golang-github-jackc-pgx-v4-dev, golang-github-julienschmidt-httprouter-dev, golang-github-leonelquinteros-gotext-dev, - golang-golang-x-text-dev, + golang-github-rainycape-unidecode-dev, golang-github-tealeg-xlsx-dev, + golang-golang-x-text-dev, postgresql-all (>= 217~), sqitch, pgtap, diff --git a/go.mod b/go.mod index 075fdc0..2e06b1b 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/jackc/pgx/v4 v4.15.0 github.com/julienschmidt/httprouter v1.3.0 github.com/leonelquinteros/gotext v1.5.0 + github.com/rainycape/unidecode v0.0.0-20150906181237-c9cf8cdbbfe8 github.com/tealeg/xlsx v0.0.0-20181024002044-dbf71b6a931e golang.org/x/text v0.7.0 ) diff --git a/go.sum b/go.sum index 592b363..38e30d5 100644 --- a/go.sum +++ b/go.sum @@ -92,6 +92,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rainycape/unidecode v0.0.0-20150906181237-c9cf8cdbbfe8 h1:iZTHFqK/oFrjyFDkiw5U/RjQxkMlkpq6tHQIO407i+s= +github.com/rainycape/unidecode v0.0.0-20150906181237-c9cf8cdbbfe8/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= diff --git a/pkg/invoices.go b/pkg/invoices.go index d11ba96..ffc7243 100644 --- a/pkg/invoices.go +++ b/pkg/invoices.go @@ -658,7 +658,7 @@ func mustWriteInvoicesPdf(r *http.Request, slugs []string) []byte { if inv == nil { continue } - f, err := w.Create(inv.Number + ".pdf") + f, err := w.Create(fmt.Sprintf("%s-%s.pdf", inv.Number, slugify(inv.Invoicee.Name))) if err != nil { panic(err) } diff --git a/pkg/slug.go b/pkg/slug.go new file mode 100644 index 0000000..ae87296 --- /dev/null +++ b/pkg/slug.go @@ -0,0 +1,22 @@ +package pkg + +import ( + "github.com/rainycape/unidecode" + "regexp" + "strings" +) + +var ( + nonValidChars = regexp.MustCompile("[^a-z0-9-_]") + multipleDashes = regexp.MustCompile("-+") +) + +func slugify(s string) (slug string) { + slug = strings.TrimSpace(s) + slug = unidecode.Unidecode(slug) + slug = strings.ToLower(slug) + slug = nonValidChars.ReplaceAllString(slug, "-") + slug = multipleDashes.ReplaceAllString(slug, "-") + slug = strings.Trim(slug, "-_") + return slug +} diff --git a/pkg/template.go b/pkg/template.go index 71249ad..af592bf 100644 --- a/pkg/template.go +++ b/pkg/template.go @@ -86,6 +86,9 @@ func mustRenderTemplate(wr io.Writer, r *http.Request, layout string, filename s sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"} return humanizeBytes(bytes, 1024, sizes) }, + "slugify": func(s string) string { + return slugify(s) + }, }) if _, err := t.ParseFiles(templateFile(filename), templateFile(layout), templateFile("form.gohtml")); err != nil { panic(err) diff --git a/web/template/invoices/index.gohtml b/web/template/invoices/index.gohtml index 15283fb..58136bf 100644 --- a/web/template/invoices/index.gohtml +++ b/web/template/invoices/index.gohtml @@ -104,7 +104,7 @@ {{ .Total|formatPrice }} {{- $title = .Number | printf (pgettext "Download invoice %s" "action") -}} diff --git a/web/template/invoices/view.gohtml b/web/template/invoices/view.gohtml index 5db7399..f054595 100644 --- a/web/template/invoices/view.gohtml +++ b/web/template/invoices/view.gohtml @@ -19,7 +19,7 @@ href="{{ companyURI "/invoices/"}}{{ .Slug }}/edit">{{( pgettext "Edit" "action" )}} {{( pgettext "Download invoice" "action" )}} + download="{{ .Number}}-{{ .Invoicee.Name | slugify }}.pdf">{{( pgettext "Download invoice" "action" )}}

{{- end }}