WIP: Add SVG Templating #10

Draft
tueem wants to merge 14 commits from feat/template into dev
3 changed files with 143 additions and 34 deletions
Showing only changes of commit 741b196497 - Show all commits

View File

@@ -5,9 +5,13 @@ import (
"tomatentum.net/svg-templater/internal/command" "tomatentum.net/svg-templater/internal/command"
"tomatentum.net/svg-templater/internal/database" "tomatentum.net/svg-templater/internal/database"
"tomatentum.net/svg-templater/pkg/format"
) )
func main() { func main() {
if !format.CheckInkscape() {
panic("Inkscape not found")
}
if err := database.OpenSQLite(); err != nil { if err := database.OpenSQLite(); err != nil {
log.Fatal("Failed opening DB:\n", err) log.Fatal("Failed opening DB:\n", err)
return return

View File

@@ -0,0 +1,97 @@
package format
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"tomatentum.net/svg-templater/pkg/svg"
)
type ConversionParameters struct {
Format string
Width, Height int
}
func ConvertByte(svgblob []byte, param ConversionParameters) ([]byte, error) {
reader, err := ConvertReader(svgblob, param)
if err != nil {
return nil, err
}
defer reader.Close()
result, err := io.ReadAll(reader)
if err != nil {
return nil, err
}
return result, nil
}
func ConvertReader(svgblob []byte, param ConversionParameters) (io.ReadCloser, error) {
if param.Format == "svg" {
return io.NopCloser(bytes.NewReader(svgblob)), nil
}
file, err := svg.CreateTemp(bytes.NewReader(svgblob), "svg")
if err != nil {
return nil, err
}
defer os.Remove(file)
return runCommand(file, param)
}
func runCommand(input string, param ConversionParameters) (io.ReadCloser, error) {
var args []string
var outExt string
switch param.Format {
case "png":
args = append(args, "--export-type=png")
outExt = ".png"
case "jpg":
args = append(args, "--export-type=png") // inkscape doesn't export jpg directly
outExt = ".png"
case "pdf":
args = append(args, "--export-type=pdf")
outExt = ".pdf"
default:
return nil, fmt.Errorf("format not supported: %s", param.Format)
}
if param.Width > 0 {
args = append(args, "-w", strconv.Itoa(param.Width))
}
if param.Height > 0 {
args = append(args, "-h", strconv.Itoa(param.Height))
}
outFile := strings.TrimSuffix(input, filepath.Ext(input)) + outExt
args = append(args, "-o", outFile)
args = append(args, input)
cmd := exec.Command("/opt/homebrew/bin/inkscape", args...)
cmd.Dir = svg.TempDir
out, err := cmd.CombinedOutput()
if err != nil {
return nil, fmt.Errorf("inkscape failed: %w: %s", err, string(out))
}
file, err := os.Open(outFile)
if err != nil {
return nil, err
}
return file, nil
}
func CheckInkscape() bool {
_, err := exec.LookPath("inkscape")
return err == nil
}

View File

@@ -9,47 +9,18 @@ import (
type SvgStorage interface { type SvgStorage interface {
Create(id string, svg io.Reader) (string, error) Create(id string, svg io.Reader) (string, error)
Get(id string) (io.Reader, error) Get(id string) (io.ReadCloser, error)
CreateTemp(data io.Reader, filetype string) (string, error)
CreatePublic(data io.Reader, filetype string) (string, error) CreatePublic(data io.Reader, filetype string) (string, error)
GetPublic(path string) (io.ReadCloser, error)
} }
var _ SvgStorage = FileSvgStorage{} var _ SvgStorage = FileSvgStorage{}
var TempDir string = ""
type FileSvgStorage struct { type FileSvgStorage struct {
basepath string basepath string
} }
func (f FileSvgStorage) CreatePublic(data io.Reader, filetype string) (string, error) {
path := filepath.Join(f.basepath, "public")
if err := os.Mkdir(path, 0755); err != nil {
return "", err
}
file, err := os.CreateTemp(path, "*."+filetype)
if err != nil {
return "", err
}
defer file.Close()
return file.Name(), nil
}
func (f FileSvgStorage) CreateTemp(data io.Reader, filetype string) (string, error) {
path := filepath.Join(f.basepath, "temp")
if err := os.Mkdir(path, 0755); err != nil {
return "", err
}
file, err := os.CreateTemp(path, "*."+filetype)
if err != nil {
return "", err
}
defer file.Close()
return file.Name(), nil
}
func NewFileStorage(path string) *FileSvgStorage { func NewFileStorage(path string) *FileSvgStorage {
err := os.MkdirAll(path, 0755) err := os.MkdirAll(path, 0755)
if err != nil { if err != nil {
@@ -76,10 +47,47 @@ func (f FileSvgStorage) Create(id string, svg io.Reader) (string, error) {
return file.Name(), nil return file.Name(), nil
} }
func (f FileSvgStorage) Get(id string) (io.Reader, error) { func (f FileSvgStorage) Get(id string) (io.ReadCloser, error) {
file, err := os.Open(filepath.Join(f.basepath, "svg", id+".svg")) file, err := os.Open(filepath.Join(f.basepath, id+".svg"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return file, nil return file, nil
} }
func (f FileSvgStorage) CreatePublic(data io.Reader, filetype string) (string, error) {
path := filepath.Join(f.basepath, "public")
if err := os.Mkdir(path, 0755); err != nil {
return "", err
}
file, err := os.CreateTemp(path, "*."+filetype)
if err != nil {
return "", err
}
defer file.Close()
return file.Name(), nil
}
func (f FileSvgStorage) GetPublic(path string) (io.ReadCloser, error) {
file, err := os.Open(filepath.Join(f.basepath, "public", path))
if err != nil {
return nil, err
}
return file, nil
}
func CreateTemp(data io.Reader, filetype string) (string, error) {
file, err := os.CreateTemp(TempDir, "*."+filetype)
if err != nil {
return "", err
}
defer file.Close()
_, err = io.Copy(file, data)
if err != nil {
return "", err
}
return file.Name(), nil
}