icns

Easily create .icns files (Mac Icons) with this Go library or the included CLI.
Log | Files | Refs | LICENSE

commit d9f37c584c6c615ac1f6f0c0c45de61b275516cd
parent 952d580cc7f3df1b9affea829ddfef91120d1ef5
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Sun, 20 Sep 2026 15:54:27 -0300

wasm: expose validation to the page

The page can already convert without uploading; telling someone their icon
is broken is the same argument, and it is what the conversion is worth
trusting for.

Diffstat:
Mcmd/wasm/main.go | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+), 0 deletions(-)

diff --git a/cmd/wasm/main.go b/cmd/wasm/main.go @@ -23,6 +23,7 @@ func main() { api := js.Global().Get("Object").New() api.Set("convert", js.FuncOf(convert)) api.Set("inspect", js.FuncOf(inspect)) + api.Set("validate", js.FuncOf(validate)) js.Global().Set("icns", api) // The page calls into this, so the program has to stay resident. select {} @@ -96,6 +97,56 @@ func inspect(_ js.Value, args []js.Value) (out any) { return result } +// validate reports what the platform that owns the format will make of an +// icon file, as an array of findings ordered by severity. +func validate(_ js.Value, args []js.Value) (out any) { + defer func() { + if r := recover(); r != nil { + out = failure(fmt.Errorf("validating: %v", r)) + } + }() + if len(args) < 1 { + return failure(errors.New("validate wants an icon file")) + } + type finding struct{ severity, icon, message string } + var ( + src = toGo(args[0]) + findings []finding + ) + switch { + case bytes.HasPrefix(src, []byte("icns")): + problems, err := icns.Validate(bytes.NewReader(src)) + if err != nil { + return failure(err) + } + for _, p := range problems { + findings = append(findings, finding{p.Severity.String(), p.Icon, p.Message}) + } + case bytes.HasPrefix(src, []byte{0x00, 0x00, 0x01, 0x00}): + problems, err := ico.Validate(bytes.NewReader(src)) + if err != nil { + return failure(err) + } + for _, p := range problems { + findings = append(findings, finding{p.Severity.String(), p.Icon, p.Message}) + } + default: + return failure(errors.New("not an icns or ico file")) + } + list := js.Global().Get("Array").New(len(findings)) + for i, f := range findings { + item := js.Global().Get("Object").New() + item.Set("severity", f.severity) + item.Set("icon", f.icon) + item.Set("message", f.message) + list.SetIndex(i, item) + } + result := js.Global().Get("Object").New() + result.Set("ok", true) + result.Set("problems", list) + return result +} + // toGo copies a Uint8Array into Go memory, which the wasm boundary requires. func toGo(v js.Value) []byte { out := make([]byte, v.Get("length").Int())