WIP trmnl BYOS
1package module
2
3import (
4 "bytes"
5 "embed"
6 "errors"
7 "fmt"
8 "image"
9 "image/jpeg"
10 "image/png"
11 "path"
12 "strings"
13
14 "github.com/dop251/goja"
15 "github.com/dop251/goja_nodejs/require"
16 "tangled.org/cdbrdr.com/scrn/internal/transform"
17)
18
19var (
20 ErrImgSrcUnknown = errors.New("img src unknown")
21)
22
23//go:generate esbuild scrn/*.jsx --jsx=automatic --jsx-factory=h --jsx-fragment=b --jsx-import-source=react --format=cjs --minify --outdir=scrn
24//go:generate esbuild jsx/jsx-runtime.js --outfile=jsx/jsx-runtime.min.js --format=cjs --minify
25
26//go:embed scrn/* jsx/*
27var f embed.FS
28
29func LoadImgSrc(p string) (image.Image, error) {
30 content, err := f.ReadFile(p)
31 if err != nil {
32 return nil, err
33 }
34
35 if strings.HasSuffix(p, ".png") {
36 img, err := png.Decode(bytes.NewBuffer(content))
37 if err != nil {
38 return nil, err
39 }
40
41 return img, nil
42 } else if strings.HasSuffix(p, ".jpg") {
43 img, err := jpeg.Decode(bytes.NewBuffer(content))
44 if err != nil {
45 return nil, err
46 }
47
48 return img, nil
49 }
50
51 return nil, ErrImgSrcUnknown
52}
53
54func LoadModule(p string) ([]byte, error) {
55 ext := path.Ext(p)
56
57 tryPaths := []string{}
58 if ext == "" {
59 tryPaths = append(tryPaths, fmt.Sprintf("%s.js", p))
60 tryPaths = append(tryPaths, fmt.Sprintf("%s.jsx", p))
61 }
62
63 if len(tryPaths) == 0 {
64 tryPaths = append(tryPaths, p)
65 }
66
67 for _, pth := range tryPaths {
68 content, err := f.ReadFile(pth)
69 if err != nil {
70 continue
71 }
72
73 if strings.HasSuffix(pth, ".jsx") {
74 code, errs := transform.Transform(path.Base(pth), string(content), transform.FormatCommonJS)
75 if len(errs) > 0 {
76 continue
77 }
78
79 return code, nil
80 } else {
81 return content, nil
82 }
83 }
84
85 return nil, require.ModuleFileDoesNotExistError
86}
87
88func LoadJSXRuntime() ([]byte, error) {
89 // First try pre-transformed
90 if code, err := f.ReadFile("jsx/jsx-runtime.min.js"); err == nil {
91 return code, nil
92 }
93
94 // Then load original source and transform it
95 content, err := f.ReadFile("jsx/jsx-runtime.js")
96 if err != nil {
97 return nil, require.ModuleFileDoesNotExistError
98 }
99
100 code, errs := transform.Transform("jsx-runtime.js", string(content), transform.FormatCommonJS)
101 if len(errs) > 0 {
102 return nil, require.ModuleFileDoesNotExistError
103 }
104
105 return code, nil
106}
107
108func Enable(runtime *goja.Runtime) *require.RequireModule {
109 registry := require.NewRegistryWithLoader(func(p string) ([]byte, error) {
110 if strings.HasSuffix(p, "node_modules/react/jsx-runtime") {
111 return LoadJSXRuntime()
112 }
113 if strings.HasPrefix(p, "node_modules/scrn/") {
114 return LoadModule(strings.TrimPrefix(p, "node_modules/"))
115 }
116
117 return nil, require.ModuleFileDoesNotExistError
118 })
119
120 return registry.Enable(runtime)
121}