Compare commits

12 Commits

Author SHA1 Message Date
b59c939e3e Add acl
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-20 21:22:52 +01:00
3a30c7a6f4 Actually fix path
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-20 21:18:57 +01:00
bdab11b100 try fix path
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-20 21:16:30 +01:00
d3f6f0e946 update ci
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-20 21:13:40 +01:00
f05c4bbcc7 Update wasm
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-20 20:32:57 +01:00
d2ac081d5e Update pipeline 2022-01-20 20:32:40 +01:00
39af776d00 ci test 2
Some checks failed
continuous-integration/drone Build is failing
2022-01-20 17:10:11 +01:00
15130938ce ci test 1
Some checks reported errors
continuous-integration/drone/push Build was killed
2022-01-20 16:58:49 +01:00
05ac24254c Generate that beautiful double page 2021-12-17 22:07:00 +01:00
72a245610a Remove sha256 debug output 2021-12-17 21:47:20 +01:00
7040909625 Add split-output to cli 2021-12-17 21:46:13 +01:00
ec9426b59c Remove compiled wasm 2021-12-17 21:37:29 +01:00
8 changed files with 247 additions and 37 deletions

55
.drone.yml Normal file
View File

@@ -0,0 +1,55 @@
---
kind: pipeline
type: kubernetes
name: build-clis
steps:
- name: build
image: golang:1.17
commands:
- make build-cross-clis
- name: upload
image: plugins/s3
settings:
bucket: covergen
source: dist/*
target: /dist/
strip_prefix: dist/
acl: readonly
path_style: true
endpoint: https://s3.blacknova.io
access_key:
from_secret: minio_access_key_id
secret_key:
from_secret: minio_secret_access_key
---
kind: pipeline
type: kubernetes
name: build-wasm
steps:
- name: build
image: golang:1.17
environment:
GOOS: js
GOARCH: wasm
commands:
- make wasm
- name: upload
image: plugins/s3
settings:
bucket: covergen
source: assets/**/*
target: /
strip_prefix: assets/
acl: readonly
path_style: true
endpoint: https://s3.blacknova.io
access_key:
from_secret: minio_access_key_id
secret_key:
from_secret: minio_secret_access_key

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
covergen
!covergen/
*.pdf
assets/*.wasm
dist/

View File

@@ -1,3 +1,9 @@
.PHONY: build-cross-clis
build-cross-clis:
rm -rf ./dist && mkdir ./dist
GOOS=linux GOARCH=amd64 go build -o dist/covergen.linux-amd64 ./cmd/covergen
GOOS=darwin GOARCH=amd64 go build -o dist/covergen.darwin-amd64 ./cmd/covergen
.PHONY: wasm
wasm:
GOOS=js GOARCH=wasm go build -o assets/covergen.wasm ./cmd/wasm/main.go
.PHONY: wasm

Binary file not shown.

View File

@@ -9,7 +9,7 @@
});
function makeCover(args) {
const result = window.covergen(args);
const result = window.generateCover(args);
if (result.error) {
throw result.error;
}
@@ -17,19 +17,44 @@
return new File([result], 'cover.pdf', {type: 'application/pdf'});
}
function makeSplitCover(args) {
const result = window.generateSplitCover(args);
if (result.error) {
throw result.error;
}
return Object.fromEntries(['front', 'back'].map((side) => [side, new File([result[side]], `${side}.pdf`, {type: 'application/pdf'})]));
}
function letsfuckinggo() {
document.getElementById('cover').src = window.URL.createObjectURL(makeCover({
const covers = makeSplitCover({
customer: document.getElementById('customer').value,
number: document.getElementById('number').value,
}));
numberPrefix: document.getElementById('prefix').value,
hlColor: document.getElementById('color').value,
})
document.getElementById('front').src = window.URL.createObjectURL(covers.front);
document.getElementById('back').src = window.URL.createObjectURL(covers.back);
}
</script>
<style>
html, body, #cover {
html, body {
height: 100%;
width: 100%;
}
.covers {
height: 100%;
width: 90%;
display: flex;
flex-direction: row;
}
.covers iframe {
flex-grow: 1;
}
</style>
</head>
<body>
@@ -39,15 +64,30 @@
<textarea id="customer"></textarea>
</label>
</div>
<div>
<label>
Prefix:
<input id="prefix" type="text" value="offerte">
</label>
</div>
<div>
<label>
Number:
<input id="number" type="text">
</label>
</div>
<div>
<label>
Color:
<input id="color" type="color" value="#FF69B4">
</label>
</div>
<div>
<button onclick="letsfuckinggo()">Fuck it!</button>
</div>
<iframe id="cover"></iframe>
<div class="covers">
<iframe id="front"></iframe>
<iframe id="back"></iframe>
</div>
</body>
</html>

View File

@@ -26,6 +26,7 @@ var customer = pflag.StringP("customer", "c", "", "Customer name for cover")
var numberPrefix = pflag.String("number-prefix", "offerte", "Prefix to use for number")
var color = pflag.String("color", "random", "Selects a color to use for the grid highlight. Valid choices: ['random', 'red', 'blue', 'yellow', 'green']")
var output = pflag.StringP("output", "o", "cover.pdf", "File to output to")
var output2 = pflag.StringP("output-back", "b", "", "Output front and back separately")
func init() {
log.Logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger()
@@ -69,13 +70,15 @@ func main() {
}
*customer = strings.ReplaceAll(*customer, "\\n", "\n")
pdf, err := covergen.GenerateInvoice(covergen.CoverSettings{
settings := covergen.CoverSettings{
Number: *number,
NumberPrefix: *numberPrefix,
CustomerName: *customer,
HLColor: chosenColor,
})
}
if *output2 == "" {
pdf, err := covergen.GenerateInvoice(settings)
if err != nil {
log.Fatal().Err(err).Msg("Failed to render invoice")
@@ -84,4 +87,22 @@ func main() {
if err := pdf.OutputFileAndClose(*output); err != nil {
log.Fatal().Err(err).Msg("Failed to write invoice to disk")
}
} else {
front, err := covergen.GenerateFrontCover(settings)
if err != nil {
log.Fatal().Err(err).Msg("Failed to render front")
}
if err := front.OutputFileAndClose(*output); err != nil {
log.Fatal().Err(err).Msg("Failed to write front to disk")
}
back, err := covergen.GenerateBackCover(settings)
if err != nil {
log.Fatal().Err(err).Msg("Failed to render back")
}
if err := back.OutputFileAndClose(*output2); err != nil {
log.Fatal().Err(err).Msg("Failed to write back to disk")
}
}
}

View File

@@ -2,12 +2,11 @@ package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"syscall/js"
"github.com/go-pdf/fpdf"
"github.com/thegrumpylion/jsref"
"covergen/pkg/covergen"
@@ -72,6 +71,18 @@ func settingsFromValue(arg js.Value) (*covergen.CoverSettings, error) {
}, nil
}
func pdfToJs(pdf *fpdf.Fpdf) (js.Value, error) {
var buf bytes.Buffer
if err := pdf.Output(&buf); err != nil {
return js.Null(), fmt.Errorf("failed to write pdf: %w", err)
}
s := buf.Bytes()
ta := js.Global().Get("Uint8Array").New(len(s))
js.CopyBytesToJS(ta, s)
return ta, nil
}
func generateCover(this js.Value, args []js.Value) interface{} {
defer func() {
if r := recover(); r != nil {
@@ -98,21 +109,61 @@ func generateCover(this js.Value, args []js.Value) interface{} {
return jsmap{"error": err.Error()}
}
var buf bytes.Buffer
if err = pdf.Output(&buf); err != nil {
jsBytes, err := pdfToJs(pdf)
if err != nil {
return jsmap{"error": err.Error()}
}
return jsBytes
}
func generateSplitCover(this js.Value, args []js.Value) interface{} {
defer func() {
if r := recover(); r != nil {
fmt.Println("recovered", r)
}
}()
if len(args) != 1 {
return jsmap{"error": "missing argument"}
}
arg := args[0]
if arg.Type() != js.TypeObject {
return jsmap{"error": "expected object"}
}
settings, err := settingsFromValue(arg)
if err != nil {
return jsmap{"error": err.Error()}
}
s := buf.Bytes()
sum := sha256.Sum256(s)
fmt.Println("shasum", hex.EncodeToString(sum[:]))
front, err := covergen.GenerateFrontCover(*settings)
if err != nil {
return jsmap{"error": fmt.Sprintf("failed to render front: %s", err.Error())}
}
ta := js.Global().Get("Uint8Array").New(len(s))
js.CopyBytesToJS(ta, s)
return ta
back, err := covergen.GenerateBackCover(*settings)
if err != nil {
return jsmap{"error": fmt.Sprintf("failed to render back: %s", err.Error())}
}
frontJSBytes, err := pdfToJs(front)
if err != nil {
return jsmap{"error": fmt.Sprintf("failed to render front: %s", err.Error())}
}
backJSBytes, err := pdfToJs(back)
if err != nil {
return jsmap{"error": fmt.Sprintf("failed to render back: %s", err.Error())}
}
return jsmap{
"front": frontJSBytes,
"back": backJSBytes,
}
}
func main() {
js.Global().Set("covergen", js.FuncOf(generateCover))
js.Global().Set("generateCover", js.FuncOf(generateCover))
js.Global().Set("generateSplitCover", js.FuncOf(generateSplitCover))
<-make(chan bool)
}

View File

@@ -6,7 +6,6 @@ import (
"strings"
"github.com/go-pdf/fpdf"
"github.com/rs/zerolog/log"
)
const margin = 20
@@ -44,17 +43,58 @@ type CoverSettings struct {
}
func GenerateInvoice(settings CoverSettings) (*fpdf.Fpdf, error) {
pdf, err := GenerateFrontCover(settings)
if err != nil {
return nil, err
}
pdf.AddPage()
drawCustomerName(pdf, settings)
if pdf.Err() {
return nil, pdf.Error()
}
return pdf, nil
}
func GenerateFrontCover(settings CoverSettings) (*fpdf.Fpdf, error) {
pdf, err := generateBaseInvoice(settings)
if err != nil {
return nil, err
}
drawInvoiceNumber(pdf, settings)
drawMiwebbLink(pdf)
if pdf.Err() {
return nil, pdf.Error()
}
return pdf, nil
}
func GenerateBackCover(settings CoverSettings) (*fpdf.Fpdf, error) {
pdf, err := generateBaseInvoice(settings)
if err != nil {
return nil, err
}
return pdf, err
}
func generateBaseInvoice(settings CoverSettings) (*fpdf.Fpdf, error) {
pdf := fpdf.New("P", scaleUnit, "A4", "")
if err := addEmbeddedFont(pdf, "Mark Medium", "", "Mark-Medium"); err != nil {
log.Fatal().Err(err).Msg("Error adding font")
return nil, fmt.Errorf("error adding font: %w", err)
}
if err := addEmbeddedFont(pdf, "Mark Light", "", "Mark-Light"); err != nil {
log.Fatal().Err(err).Msg("Error adding font")
return nil, fmt.Errorf("error adding font: %w", err)
}
miwebbLogo, err := addEmbeddedLogo(pdf, miwebbLogoName, miwebbLogoPath)
miwebbLogo, err := addEmbeddedLogo(pdf, miwebbLogoName, "miwebb.white.png")
if err != nil {
log.Fatal().Err(err).Msg("Error adding logo")
return nil, fmt.Errorf("error adding logo: %w", err)
}
pdf.SetMargins(margin, margin, margin)
@@ -67,21 +107,16 @@ func GenerateInvoice(settings CoverSettings) (*fpdf.Fpdf, error) {
pdf.Image(miwebbLogoName, margin-5, margin, miwebbLogo.Width()*logoScale, miwebbLogo.Height()*logoScale, false, "", 0, "")
})
pdf.AddPage()
drawCustomerName(pdf, settings)
drawInvoiceNumber(pdf, settings)
drawMiwebbLink(pdf)
pdf.AddPage()
drawCustomerName(pdf, settings)
if pdf.Err() {
return nil, pdf.Error()
return nil, fmt.Errorf("error generating invoice: %w", pdf.Error())
}
return pdf, nil
}
func drawInvoiceNumber(pdf *fpdf.Fpdf, settings CoverSettings) {
_, pageHeight := pdf.GetPageSize()