feat(template): add multiple page support to templates
build / Go-Build (push) Successful in 1m30s

This commit is contained in:
2026-05-27 22:02:11 +02:00
parent 2aab1bcdd2
commit ba2332ecb6
5 changed files with 76 additions and 36 deletions
+13 -6
View File
@@ -17,7 +17,7 @@ type downloadRequest struct {
} }
type downloadResponse struct { type downloadResponse struct {
Url string Urls []string
} }
func DownloadSVG(w http.ResponseWriter, r *http.Request) { func DownloadSVG(w http.ResponseWriter, r *http.Request) {
@@ -73,16 +73,23 @@ func DownloadSVG(w http.ResponseWriter, r *http.Request) {
Keys: request.TemplateKeys, Keys: request.TemplateKeys,
} }
filename, err := actions.ProvideFile(&templateParam, &convParam) filenames, err := actions.ProvideFile(&templateParam, &convParam)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
urlparsed := getPublicUrl(r, filename)
log.Printf("Made %s available as %s\n", id, urlparsed) urlsparsed := make([]string, len(filenames))
response := downloadResponse{ for i, filename := range filenames {
Url: urlparsed, urlsparsed[i] = getPublicUrl(r, filename)
log.Printf("Made %s page %d available as %s\n", id, i, urlsparsed[i])
} }
response := downloadResponse{
Urls: urlsparsed,
}
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
json, err := json.Marshal(response) json, err := json.Marshal(response)
if err != nil { if err != nil {
+19 -7
View File
@@ -3,20 +3,32 @@ package actions
import ( import (
"bytes" "bytes"
"log" "log"
"strconv"
"tomatentum.net/svg-templater/pkg/format" "tomatentum.net/svg-templater/pkg/format"
"tomatentum.net/svg-templater/pkg/svg" "tomatentum.net/svg-templater/pkg/svg"
) )
func ProvideFile(r *TemplateParameters, conversion *format.ConversionParameters) (string, error) { func ProvideFile(r *TemplateParameters, conversion *format.ConversionParameters) ([]string, error) {
templatedSvgblob, err := Template(r) templatedPages, err := Template(r)
if err != nil { if err != nil {
return "", err return nil, err
} }
log.Printf("Converting %s to format %s (w=%d,h=%d)", r.Id, conversion.Format, conversion.Width, conversion.Height) log.Printf("Converting %s to format %s (w=%d,h=%d)", r.Id, conversion.Format, conversion.Width, conversion.Height)
result, err := format.ConvertByte(templatedSvgblob, *conversion) filenames := make([]string, len(templatedPages))
if err != nil { for i, pagedata := range templatedPages {
return "", err result, err := format.ConvertByte(pagedata, *conversion)
if err != nil {
return nil, err
}
filenames[i], err = svg.Storage.CreatePublic(bytes.NewReader(result), strconv.Itoa(i+1), conversion.Format)
if err != nil {
return nil, err
}
log.Printf("Converted %s page %d to format %s (w=%d,h=%d)", r.Id, i, conversion.Format, conversion.Width, conversion.Height)
} }
return svg.Storage.CreatePublic(bytes.NewReader(result), conversion.Format)
return filenames, nil
} }
+13
View File
@@ -3,6 +3,7 @@ package actions
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"log" "log"
"regexp" "regexp"
"strconv" "strconv"
@@ -34,6 +35,18 @@ func AddPage(id string, svgbuf []byte) (svg.TemplatePage, error) {
return data, nil return data, nil
} }
func GetPage(id string, page int) ([]byte, error) {
file, err := svg.Storage.Get(fmt.Sprintf(FILEFORMAT, id, page))
if err != nil {
return nil, err
}
defer file.Close()
return io.ReadAll(file)
}
func DeletePage(id string, page int) (bool, error) { func DeletePage(id string, page int) (bool, error) {
if success, err := database.DeleteSVGPage(id, page); err != nil || !success { if success, err := database.DeleteSVGPage(id, page); err != nil || !success {
return success, err return success, err
+27 -20
View File
@@ -2,7 +2,6 @@ package actions
import ( import (
"errors" "errors"
"io"
"log" "log"
"maps" "maps"
"regexp" "regexp"
@@ -18,29 +17,42 @@ type TemplateParameters struct {
Keys map[string]string Keys map[string]string
} }
func Template(r *TemplateParameters) ([]byte, error) { func Template(r *TemplateParameters) ([][]byte, error) {
mapkeys := slices.Collect(maps.Keys(r.Keys))
ok, err := verifyTemplate(r.Id, mapkeys) data, err := database.GetSpecificSVG(r.Id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
mapkeys := slices.Collect(maps.Keys(r.Keys))
ok, err := verifyTemplate(data, mapkeys)
if err != nil {
return nil, err
}
if !ok { if !ok {
return nil, errors.New("Template does not exist.") return nil, errors.New("Template does not exist.")
} }
log.Printf("Replacing keys of %s template\n", r.Id) log.Printf("Replacing keys of %s template\n", r.Id)
reader, err := svg.Storage.Get(r.Id) pagesdata := make([][]byte, len(data.Pages))
if err != nil {
return nil, err for _, page := range data.Pages {
pagedata, err := GetPage(page.TemplateId, page.Page)
if err != nil {
return nil, err
}
replaceAll(&pagedata, r.Keys)
pagesdata[page.Page-1] = pagedata
log.Printf("Finished replacing keys of %s page %d\n", r.Id, page.Page)
} }
defer reader.Close()
svgblob, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
replaceAll(&svgblob, r.Keys)
log.Printf("Finished replacing keys of %s template\n", r.Id) log.Printf("Finished replacing keys of %s template\n", r.Id)
return svgblob, nil return pagesdata, nil
} }
func replaceAll(svgblob *[]byte, keys map[string]string) { func replaceAll(svgblob *[]byte, keys map[string]string) {
@@ -51,12 +63,7 @@ func replaceAll(svgblob *[]byte, keys map[string]string) {
})) }))
} }
func verifyTemplate(id string, keys []string) (bool, error) { func verifyTemplate(data svg.TemplateData, keys []string) (bool, error) {
data, err := database.GetSpecificSVG(id)
if err != nil {
return false, err
}
for _, key := range data.AllKeys() { for _, key := range data.AllKeys() {
if !slices.Contains(keys, key) { if !slices.Contains(keys, key) {
return false, nil return false, nil
+4 -3
View File
@@ -2,6 +2,7 @@ package svg
import ( import (
"errors" "errors"
"fmt"
"io" "io"
"log" "log"
"net/http" "net/http"
@@ -20,7 +21,7 @@ type SvgStorage interface {
AddFont(reader io.Reader, format string) error AddFont(reader io.Reader, format string) error
GetFonts() ([]string, error) GetFonts() ([]string, error)
GetFontsDir() string GetFontsDir() string
CreatePublic(data io.Reader, filetype string) (string, error) CreatePublic(data io.Reader, suffix string, filetype string) (string, error)
GetPublic(path string) (io.ReadCloser, error) GetPublic(path string) (io.ReadCloser, error)
GetPublicDir() http.Dir GetPublicDir() http.Dir
} }
@@ -86,13 +87,13 @@ func (f FileSvgStorage) List() ([]os.DirEntry, error) {
return os.ReadDir(f.basepath) return os.ReadDir(f.basepath)
} }
func (f FileSvgStorage) CreatePublic(data io.Reader, filetype string) (string, error) { func (f FileSvgStorage) CreatePublic(data io.Reader, suffix string, filetype string) (string, error) {
path := filepath.Join(f.basepath, f.publicSubPath) path := filepath.Join(f.basepath, f.publicSubPath)
if err := os.MkdirAll(path, 0755); err != nil { if err := os.MkdirAll(path, 0755); err != nil {
return "", err return "", err
} }
file, err := os.CreateTemp(path, "*."+filetype) file, err := os.CreateTemp(path, fmt.Sprintf("*-%s."+filetype, suffix))
if err != nil { if err != nil {
return "", err return "", err
} }