package module import ( "bytes" "embed" "errors" "fmt" "image" "image/jpeg" "image/png" "path" "strings" "github.com/dop251/goja" "github.com/dop251/goja_nodejs/require" "tangled.org/cdbrdr.com/scrn/internal/transform" ) var ( ErrImgSrcUnknown = errors.New("img src unknown") ) //go:generate esbuild scrn/*.jsx --jsx=automatic --jsx-factory=h --jsx-fragment=b --jsx-import-source=react --format=cjs --minify --outdir=scrn //go:generate esbuild jsx/jsx-runtime.js --outfile=jsx/jsx-runtime.min.js --format=cjs --minify //go:embed scrn/* jsx/* var f embed.FS func LoadImgSrc(p string) (image.Image, error) { content, err := f.ReadFile(p) if err != nil { return nil, err } if strings.HasSuffix(p, ".png") { img, err := png.Decode(bytes.NewBuffer(content)) if err != nil { return nil, err } return img, nil } else if strings.HasSuffix(p, ".jpg") { img, err := jpeg.Decode(bytes.NewBuffer(content)) if err != nil { return nil, err } return img, nil } return nil, ErrImgSrcUnknown } func LoadModule(p string) ([]byte, error) { ext := path.Ext(p) tryPaths := []string{} if ext == "" { tryPaths = append(tryPaths, fmt.Sprintf("%s.js", p)) tryPaths = append(tryPaths, fmt.Sprintf("%s.jsx", p)) } if len(tryPaths) == 0 { tryPaths = append(tryPaths, p) } for _, pth := range tryPaths { content, err := f.ReadFile(pth) if err != nil { continue } if strings.HasSuffix(pth, ".jsx") { code, errs := transform.Transform(path.Base(pth), string(content), transform.FormatCommonJS) if len(errs) > 0 { continue } return code, nil } else { return content, nil } } return nil, require.ModuleFileDoesNotExistError } func LoadJSXRuntime() ([]byte, error) { // First try pre-transformed if code, err := f.ReadFile("jsx/jsx-runtime.min.js"); err == nil { return code, nil } // Then load original source and transform it content, err := f.ReadFile("jsx/jsx-runtime.js") if err != nil { return nil, require.ModuleFileDoesNotExistError } code, errs := transform.Transform("jsx-runtime.js", string(content), transform.FormatCommonJS) if len(errs) > 0 { return nil, require.ModuleFileDoesNotExistError } return code, nil } func Enable(runtime *goja.Runtime) *require.RequireModule { registry := require.NewRegistryWithLoader(func(p string) ([]byte, error) { if strings.HasSuffix(p, "node_modules/react/jsx-runtime") { return LoadJSXRuntime() } if strings.HasPrefix(p, "node_modules/scrn/") { return LoadModule(strings.TrimPrefix(p, "node_modules/")) } return nil, require.ModuleFileDoesNotExistError }) return registry.Enable(runtime) }