Skip to content

Commit deccf87

Browse files
committed
Added esbuild
0 parents  commit deccf87

5 files changed

Lines changed: 309 additions & 0 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
tmp
2+
bin
3+
pkg
4+
obj

esbuild/esbuild.go

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
package esbuild
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"os"
9+
"path"
10+
"path/filepath"
11+
"strings"
12+
13+
"github.com/evanw/esbuild/pkg/api"
14+
)
15+
16+
func BuildApp() {
17+
var dir = "app"
18+
if _, err := os.Stat(dir); os.IsNotExist(err) {
19+
fmt.Println("Skipping esbuild")
20+
return
21+
}
22+
fmt.Println("Bundling with esbuild...")
23+
result := api.Build(api.BuildOptions{
24+
EntryPoints: []string{dir + "/main.tsx"},
25+
Outdir: "dist/",
26+
GlobalName: "Emerald",
27+
28+
AllowOverwrite: true,
29+
Bundle: true,
30+
MinifyWhitespace: true,
31+
MinifyIdentifiers: true,
32+
MinifySyntax: true,
33+
// Engines: []api.Engine{
34+
// {api.EngineChrome, "58"},
35+
// {api.EngineFirefox, "57"},
36+
// {api.EngineSafari, "11"},
37+
// {api.EngineEdge, "16"},
38+
// },
39+
// Alias: GetImportsFromImportMap(),
40+
// Plugins: []api.Plugin{envPlugin(), importmapPlugin(), esmUrlResolverPlugin()},
41+
Plugins: []api.Plugin{envPlugin(), esmUrlResolverPlugin()},
42+
External: []string{"Alpine"},
43+
// JSXFactory: "m",
44+
// JSXFragment: "m.Fragment",
45+
Write: true,
46+
})
47+
48+
if len(result.Errors) > 0 {
49+
fmt.Println("esbuild Errors: %v", result.Errors)
50+
// os.Exit(1)
51+
}
52+
53+
fmt.Println("esbuild Done")
54+
}
55+
56+
func envPlugin() api.Plugin {
57+
return api.Plugin{
58+
Name: "env",
59+
Setup: func(build api.PluginBuild) {
60+
// Intercept import paths called "env" so esbuild doesn't attempt
61+
// to map them to a file system location. Tag them with the "env-ns"
62+
// namespace to reserve them for this plugin.
63+
build.OnResolve(api.OnResolveOptions{Filter: `^env$`},
64+
func(args api.OnResolveArgs) (api.OnResolveResult, error) {
65+
return api.OnResolveResult{
66+
Path: args.Path,
67+
Namespace: "env-ns",
68+
}, nil
69+
})
70+
71+
// Load paths tagged with the "env-ns" namespace and behave as if
72+
// they point to a JSON file containing the environment variables.
73+
build.OnLoad(api.OnLoadOptions{Filter: `.*`, Namespace: "env-ns"},
74+
func(args api.OnLoadArgs) (api.OnLoadResult, error) {
75+
mappings := make(map[string]string)
76+
for _, item := range os.Environ() {
77+
if equals := strings.IndexByte(item, '='); equals != -1 {
78+
mappings[item[:equals]] = item[equals+1:]
79+
}
80+
}
81+
bytes, err := json.Marshal(mappings)
82+
if err != nil {
83+
return api.OnLoadResult{}, err
84+
}
85+
contents := string(bytes)
86+
return api.OnLoadResult{
87+
Contents: &contents,
88+
Loader: api.LoaderJSON,
89+
}, nil
90+
})
91+
},
92+
}
93+
}
94+
95+
func esmUrlResolverPlugin() api.Plugin {
96+
var importmap, err = os.ReadFile("importmap.json")
97+
if err != nil {
98+
fmt.Println("Error in reading importmap.json: ", err.Error())
99+
return api.Plugin{}
100+
}
101+
importMap := &ImportMap{}
102+
json.Unmarshal(importmap, &importMap)
103+
104+
var esmPlugin = api.Plugin{
105+
Name: "esm",
106+
Setup: func(build api.PluginBuild) {
107+
// Intercept import paths called "env" so esbuild doesn't attempt
108+
// to map them to a file system location. Tag them with the "env-ns"
109+
// namespace to reserve them for this plugin.
110+
// filter := `^https\:\/\/esm.sh\/.+$`
111+
// filter := `.+`
112+
/*
113+
build.OnResolve(api.OnResolveOptions{Filter: `.*`, Namespace: "esm-ns"},
114+
func(args api.OnResolveArgs) (api.OnResolveResult, error) {
115+
// return nil, nil
116+
fmt.Println("esm Url Resolver Plugin / args.Path:", args.Path, ", ns:", args.Namespace, ",importer:", args.Importer, ", kind:", args.Kind)
117+
118+
joinedPath := path.Join(path.Dir(args.Importer), args.Path)
119+
// fmt.Println(joinedPath)
120+
absPath, err := filepath.Abs(joinedPath)
121+
if err != nil {
122+
fmt.Println("Error in resolving absolute path from:", args.Path)
123+
}
124+
return api.OnResolveResult{
125+
Path: absPath,
126+
Namespace: args.Namespace,
127+
// Importer: args.Importer,
128+
// Kind: args.Kind,
129+
// Namespace: "esm-ns",
130+
}, nil
131+
})
132+
build.OnResolve(api.OnResolveOptions{Filter: `https\:\/\/`, Namespace: "esm-ns"},
133+
func(args api.OnResolveArgs) (api.OnResolveResult, error) {
134+
// return nil, nil
135+
fmt.Println("esm Url Resolver Plugin https:// args.Path:", args.Path, ", ns:", args.Namespace, ",importer:", args.Importer, ", kind:", args.Kind)
136+
return api.OnResolveResult{
137+
// Path: args.Path,
138+
// Namespace: args.Namespace,
139+
// Namespace: "esm-ns",
140+
}, nil
141+
})
142+
*/
143+
144+
build.OnResolve(api.OnResolveOptions{Filter: `.*`},
145+
func(args api.OnResolveArgs) (api.OnResolveResult, error) {
146+
// fmt.Println("esm Plugin: args.Path:", args.Path, ", ns:", args.Namespace, ",importer:", args.Importer, ", kind:", args.Kind)
147+
148+
if url, ok := importMap.Imports[args.Path]; ok {
149+
return api.OnResolveResult{
150+
Path: url,
151+
Namespace: "esm-ns",
152+
}, nil
153+
} else if args.Namespace == "esm-ns" {
154+
// fmt.Println("esm Plugin: args.Path:", args.Path, ", ns:", args.Namespace, ",importer:", args.Importer, ", kind:", args.Kind)
155+
if strings.HasPrefix(args.Path, ".") {
156+
joinedPath := path.Join(path.Dir(args.Importer), args.Path)
157+
absPath, err := filepath.Abs(joinedPath)
158+
if err != nil {
159+
fmt.Println("Error.1 in resolving absolute path from:", args.Path)
160+
}
161+
fmt.Println("Resolved ", args.Path, " to: ", absPath)
162+
return api.OnResolveResult{
163+
Path: absPath,
164+
Namespace: args.Namespace,
165+
}, nil
166+
}
167+
return api.OnResolveResult{
168+
Path: args.Path,
169+
Namespace: args.Namespace,
170+
}, nil
171+
} else if args.Namespace == "file" {
172+
// fmt.Println("args.Path", args.Path, ", importer:", args.Importer)
173+
joinedPath := path.Join(path.Dir(args.Importer), args.Path)
174+
// fmt.Println(joinedPath)
175+
absPath, err := filepath.Abs(joinedPath)
176+
if err != nil {
177+
fmt.Println("Error.2 in resolving absolute path from:", args.Path)
178+
}
179+
return api.OnResolveResult{
180+
Path: absPath,
181+
Namespace: "file",
182+
// Namespace: "importmap-ns",
183+
}, nil
184+
} else {
185+
return api.OnResolveResult{
186+
Path: args.Path,
187+
Namespace: args.Namespace,
188+
// Importer: args.Importer,
189+
// Kind: args.Kind,
190+
}, nil
191+
}
192+
})
193+
194+
build.OnLoad(api.OnLoadOptions{Filter: `.*`, Namespace: "esm-ns"},
195+
func(args api.OnLoadArgs) (api.OnLoadResult, error) {
196+
// fmt.Println("esm-ns:", args.Path, args.Namespace, args.With, args.Suffix)
197+
url := args.Path
198+
if !strings.HasPrefix(url, "https://") {
199+
url = "https:/" + path.Join("/esm.sh", url)
200+
}
201+
// fmt.Println("GET", url, args.Namespace)
202+
res, err := http.Get(url)
203+
if err != nil {
204+
return api.OnLoadResult{}, err
205+
}
206+
defer res.Body.Close()
207+
bytes, err := io.ReadAll(res.Body)
208+
if err != nil {
209+
return api.OnLoadResult{}, err
210+
}
211+
contents := string(bytes)
212+
// return api.OnLoadResult{Contents: &contents, Loader: api.LoaderTSX}, nil
213+
return api.OnLoadResult{Contents: &contents}, nil
214+
})
215+
},
216+
}
217+
218+
return esmPlugin
219+
}
220+
221+
type ImportMap struct {
222+
Imports map[string]string `json:"imports"`
223+
}
224+
225+
func GetImportsFromImportMap() map[string]string {
226+
var importmap, err = os.ReadFile("importmap.json")
227+
if err != nil {
228+
fmt.Println("Error in reading importmap.json: ", err.Error())
229+
return map[string]string{}
230+
}
231+
importMap := &ImportMap{}
232+
json.Unmarshal(importmap, &importMap)
233+
return importMap.Imports
234+
}
235+
236+
/*
237+
func importmapPlugin() api.Plugin {
238+
var importmap, err = os.ReadFile("importmap.json")
239+
if err != nil {
240+
fmt.Println("Error in reading importmap.json: ", err.Error())
241+
return api.Plugin{}
242+
}
243+
importMap := &ImportMap{}
244+
json.Unmarshal(importmap, &importMap)
245+
246+
var importmapPlugin = api.Plugin{
247+
Name: "importmap",
248+
Setup: func(build api.PluginBuild) {
249+
// Intercept import paths called "env" so esbuild doesn't attempt
250+
// to map them to a file system location. Tag them with the "env-ns"
251+
// namespace to reserve them for this plugin.
252+
build.OnResolve(api.OnResolveOptions{Filter: `.*`},
253+
func(args api.OnResolveArgs) (api.OnResolveResult, error) {
254+
if url, ok := importMap.Imports[args.Path]; ok {
255+
return api.OnResolveResult{
256+
Path: url,
257+
Namespace: "esm-ns",
258+
}, nil
259+
} else if args.Namespace == "file" {
260+
// fmt.Println("args.Path", args.Path, ", importer:", args.Importer)
261+
joinedPath := path.Join(path.Dir(args.Importer), args.Path)
262+
// fmt.Println(joinedPath)
263+
absPath, err := filepath.Abs(joinedPath)
264+
if err != nil {
265+
fmt.Println("Error in resolving absolute path from:", args.Path)
266+
}
267+
return api.OnResolveResult{
268+
Path: absPath,
269+
Namespace: "file",
270+
// Namespace: "importmap-ns",
271+
}, nil
272+
} else {
273+
return api.OnResolveResult{
274+
Path: args.Path,
275+
Namespace: args.Namespace,
276+
// Importer: args.Importer,
277+
// Kind: args.Kind,
278+
}, nil
279+
}
280+
})
281+
282+
},
283+
}
284+
285+
return importmapPlugin
286+
}
287+
*/

go.mod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module github.com/scriptmaster/emerald-esbuild
2+
3+
go 1.22.5
4+
5+
require github.com/evanw/esbuild v0.23.1
6+
7+
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/evanw/esbuild v0.23.1 h1:ociewhY6arjTarKLdrXfDTgy25oxhTZmzP8pfuBTfTA=
2+
github.com/evanw/esbuild v0.23.1/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
3+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
4+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package main
2+
3+
import "github.com/scriptmaster/emerald-esbuild/esbuild"
4+
5+
func main() {
6+
esbuild.BuildApp()
7+
}

0 commit comments

Comments
 (0)