feat(formatconverter): add formatconverter method using inkscape

This commit is contained in:
2026-02-08 19:42:28 +01:00
parent 7c6d8f4206
commit 741b196497
3 changed files with 143 additions and 34 deletions

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
}