add template functions
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,3 +29,4 @@ build
|
||||
assets
|
||||
libgofunc
|
||||
libgo
|
||||
cmd/out.png
|
||||
|
||||
12
build_lib.sh
12
build_lib.sh
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
APP_NAME="libgofunc"
|
||||
VERSION="${1:-v0.1.3}"
|
||||
OUTPUT_DIR="assets"
|
||||
BUILD_DIR="build"
|
||||
VERSION="${1:-v0.1.5}"
|
||||
OUTPUT_DIR="../assets"
|
||||
BUILD_DIR="../build"
|
||||
|
||||
# need Android NDK
|
||||
NDK_HOME="$HOME/Android/Sdk/ndk/28.2.13676358" # <--- CHECK YOUR VERSION
|
||||
@@ -11,7 +11,7 @@ API=21
|
||||
|
||||
TOOLCHAIN="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
|
||||
OS="$(uname -s)"
|
||||
|
||||
cd cmd
|
||||
if [ "$OS" = "Darwin" ]; then
|
||||
export IOS_SDK=$(xcrun --sdk iphoneos --show-sdk-path)
|
||||
export IOS_SIM_SDK=$(xcrun --sdk iphonesimulator --show-sdk-path)
|
||||
@@ -27,7 +27,7 @@ if [ "$OS" = "Darwin" ]; then
|
||||
CC="$(xcrun --sdk iphonesimulator --find clang)" \
|
||||
CGO_CFLAGS="-isysroot $IOS_SIM_SDK -arch x86_64" \
|
||||
CGO_LDFLAGS="-isysroot $IOS_SIM_SDK -arch x86_64" \
|
||||
go build -buildmode=c-archive -o build/ios/sim/libgofunc_arm64_sim.a .
|
||||
go build ./cmd -buildmode=c-archive -o build/ios/sim/libgofunc_arm64_sim.a .
|
||||
|
||||
# xcodebuild -create-xcframework \
|
||||
# -library build/ios/device/libgofunc_arm64.a -headers build/ios/device/ \
|
||||
@@ -74,7 +74,7 @@ elif [ "$OS" = "Linux" ]; then
|
||||
tar -czf "${OUTPUT_DIR}/${VERSION}/${ARCHIVE_NAME}" -C "${BUILD_DIR}" ./${VERSION}/${ARCH}
|
||||
|
||||
export HTTPS_PROXY="socks5://localhost:8080"
|
||||
rclone copy ./assets/${VERSION} s3:mokkon/libs/libgofunc/${VERSION}
|
||||
rclone copy ../assets/${VERSION} s3:mokkon/libs/libgofunc/${VERSION}
|
||||
else
|
||||
echo "Unsupported OS: $OS"
|
||||
exit 1
|
||||
|
||||
2
go.sum
2
go.sum
@@ -4,8 +4,6 @@ github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/google/gousb v1.1.3 h1:xt6M5TDsGSZ+rlomz5Si5Hmd/Fvbmo2YCJHN+yGaK4o=
|
||||
github.com/google/gousb v1.1.3/go.mod h1:GGWUkK0gAXDzxhwrzetW592aOmkkqSGcj5KLEgmCVUg=
|
||||
github.com/kenshaw/escpos v0.0.0-20221114190919-df06b682a8fc h1:4JwmN2Scz1vR+hfSxkdy2IE/DzxX2Cftm2lhWHyN0k0=
|
||||
github.com/kenshaw/escpos v0.0.0-20221114190919-df06b682a8fc/go.mod h1:M+GIBmg2MqaSWIJrXCZS+/wRFbr9fOguRz3SHn8DRPE=
|
||||
golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE=
|
||||
|
||||
78
img.go
78
img.go
@@ -24,7 +24,13 @@ import (
|
||||
|
||||
"github.com/kenshaw/escpos"
|
||||
)
|
||||
import "log"
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
)
|
||||
|
||||
const (
|
||||
defalutFontSize = 18.0
|
||||
@@ -102,8 +108,13 @@ func GenImg(width int, outputPath, payload, tmpl string) string {
|
||||
return r
|
||||
}
|
||||
|
||||
var funcMap = template.FuncMap{
|
||||
"formatNumber": FormatNumber,
|
||||
"div": Div,
|
||||
}
|
||||
|
||||
func renderTemplate(tmp string, data map[string]interface{}) (string, error) {
|
||||
tmpl, err := template.New("mytemplate").Parse(tmp)
|
||||
tmpl, err := template.New("mytemplate").Funcs(funcMap).Parse(tmp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -431,3 +442,66 @@ func nodeHeight(n *html.Node, dc *gg.Context, canvasWidth int, xPadding, yPaddin
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
type RealNumber interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
|
||||
~float32 | ~float64
|
||||
}
|
||||
|
||||
func FormatNumber(precision int, b any) string {
|
||||
return GenericFormatNumber(precision, convertToFloat64(b))
|
||||
}
|
||||
|
||||
func GenericFormatNumber[T RealNumber](precision int, v T) string {
|
||||
pEnglish := message.NewPrinter(language.English)
|
||||
|
||||
n := float64(v)
|
||||
s := fmt.Sprintf("%.*f", precision, n)
|
||||
|
||||
parts := strings.Split(s, ".")
|
||||
intPart := parts[0]
|
||||
i, err := strconv.Atoi(intPart)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
out := pEnglish.Sprintf("%d", i)
|
||||
|
||||
if len(parts) > 1 {
|
||||
return out + "." + parts[1]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func Div(a, b any) float64 {
|
||||
return GenericDiv(convertToFloat64(a), convertToFloat64(b))
|
||||
}
|
||||
|
||||
func GenericDiv[T RealNumber](a, b T) float64 {
|
||||
floatB := float64(b)
|
||||
if floatB == 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(a) / floatB
|
||||
}
|
||||
|
||||
func convertToFloat64(v any) float64 {
|
||||
switch t := v.(type) {
|
||||
case float64:
|
||||
return t
|
||||
case float32:
|
||||
return float64(t)
|
||||
case int:
|
||||
return float64(t)
|
||||
case int64:
|
||||
return float64(t)
|
||||
case int32:
|
||||
return float64(t)
|
||||
case uint:
|
||||
return float64(t)
|
||||
case uint64:
|
||||
return float64(t)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
60
img_test.go
Normal file
60
img_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package libgofunc
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDiv(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
a any
|
||||
b any
|
||||
want float64
|
||||
}{
|
||||
{"Float division", 10.5, 2.0, 5.25},
|
||||
{"Float division", 4975, 1000, 4.975},
|
||||
{"Integer division", 10, 4, 2.5},
|
||||
{"Mixed types", int64(100), float64(4.0), 25.0},
|
||||
{"Division by zero (float)", 10.0, 0.0, 0.0},
|
||||
{"Division by zero (int)", 5, 0, 0.0},
|
||||
{"Unsupported type defaults to zero", "string", 2, 0.0},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := Div(tt.a, tt.b)
|
||||
if got != tt.want {
|
||||
t.Errorf("TemplateDiv() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatNumber(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
precision int
|
||||
val any
|
||||
want string
|
||||
}{
|
||||
{"Standard float with commas", 2, 1234567.891, "1,234,567.89"},
|
||||
{"Standard float with commas", 3, 4.975, "4.975"},
|
||||
{"Integer input with commas", 0, 5000000, "5,000,000"},
|
||||
{"Integer input forced decimals", 2, 5000, "5,000.00"},
|
||||
{"Negative float commas", 2, -9876543.21, "-9,876,543.21"},
|
||||
{"Small float rounding up", 2, 0.128, "0.13"},
|
||||
{"Small float rounding down", 2, 0.123, "0.12"},
|
||||
{"Handling NaN", 2, math.NaN(), ""},
|
||||
{"Handling Inf", 2, math.Inf(1), ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := FormatNumber(tt.precision, tt.val)
|
||||
if got != tt.want {
|
||||
t.Errorf("TemplateFloat() = %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/kenshaw/escpos"
|
||||
)
|
||||
import "errors"
|
||||
|
||||
//export PrintImg
|
||||
func PrintImg(printer *C.char, imagePath *C.char) *C.char {
|
||||
@@ -77,6 +78,8 @@ func PrintImg(printer *C.char, imagePath *C.char) *C.char {
|
||||
// reader := bufio.NewReader(rw)
|
||||
// writer := bufio.NewWriter(rw)
|
||||
// w = bufio.NewReadWriter(reader, writer)
|
||||
} else {
|
||||
return NewErr(errors.New("invalid printer"))
|
||||
}
|
||||
prt := escpos.New(w)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user