// BuildJSDir builds the js file and returns the content. // goPkgPath must be a package path eg. github.com/influx6/haiku-examples/app func BuildJSDir(jsession *JSSession, dir, importpath, name string, js, jsmap *bytes.Buffer) error { session, options := jsession.Session, jsession.Option buildpkg, err := build.NewBuildContext(session.InstallSuffix(), options.BuildTags).ImportDir(dir, 0) if err != nil { return err } pkg := &build.PackageData{Package: buildpkg} pkg.ImportPath = importpath //build the package using the sessios if err = session.BuildPackage(pkg); err != nil { return err } //build up the source map also smfilter := &compiler.SourceMapFilter{Writer: js} smsrc := &sourcemap.Map{File: name + ".js"} smfilter.MappingCallback = build.NewMappingCallback(smsrc, options.GOROOT, options.GOPATH) deps, err := compiler.ImportDependencies(pkg.Archive, session.ImportContext.Import) if err != nil { return err } err = compiler.WriteProgramCode(deps, smfilter) smsrc.WriteTo(jsmap) js.WriteString("//# sourceMappingURL=" + name + ".map.js\n") return nil }
func Compile(ctx context.Context, source []byte, mapping bool) ([]byte, error) { vos := vosctx.FromContext(ctx) options := &build.Options{ GOROOT: vos.Getenv("GOROOT"), GOPATH: vos.Getenv("GOPATH"), CreateMapFile: mapping, } s := build.NewSession(options) packages := make(map[string]*compiler.Archive) importContext := &compiler.ImportContext{ Packages: s.Types, Import: s.BuildImportPath, } fileSet := token.NewFileSet() file, err := parser.ParseFile(fileSet, "prog.go", source, parser.ParseComments) if err != nil { return nil, kerr.Wrap("NCYFEKGCWX", err) } mainPkg, err := compiler.Compile("main", []*ast.File{file}, fileSet, importContext, false) if err != nil { return nil, kerr.Wrap("KPHUKOLTBX", err) } packages["main"] = mainPkg bufCode := bytes.NewBuffer(nil) filter := &compiler.SourceMapFilter{Writer: bufCode} allPkgs, err := compiler.ImportDependencies(mainPkg, importContext.Import) if err != nil { return nil, kerr.Wrap("TIMQHFQTWL", err) } if mapping { bufMap := bytes.NewBuffer(nil) smap := &sourcemap.Map{File: "script.js"} filter.MappingCallback = build.NewMappingCallback(smap, options.GOROOT, options.GOPATH, false) if err := compiler.WriteProgramCode(allPkgs, filter); err != nil { return nil, kerr.Wrap("YKQEKRKBPL", err) } if err := smap.WriteTo(bufMap); err != nil { return nil, kerr.Wrap("VYQGYAAADG", err) } return bufMap.Bytes(), nil } if err := compiler.WriteProgramCode(allPkgs, filter); err != nil { return nil, kerr.Wrap("DPPVHCOTBQ", err) } if _, err := bufCode.WriteString("//# sourceMappingURL=script.js.map\n"); err != nil { return nil, kerr.Wrap("CXXKWQVGUI", err) } return bufCode.Bytes(), nil }
// BuildJS builds the js file and returns the content. // goPkgPath must be a package path eg. github.com/influx6/haiku-examples/app func BuildJS(jsession *JSSession, goPkgPath, name string, js, jsmap *bytes.Buffer) error { session, options := jsession.Session, jsession.Option //get the build path buildpkg, err := build.Import(goPkgPath, 0, session.InstallSuffix(), options.BuildTags) if err != nil { return err } if buildpkg.Name != "main" { return ErrNotMain } //build the package data for building // pkg := &build.PackageData{Package: buildpkg} //build the package using the sessios if err = session.BuildPackage(buildpkg); err != nil { return err } //build up the source map also smfilter := &compiler.SourceMapFilter{Writer: js} smsrc := &sourcemap.Map{File: name + ".js"} smfilter.MappingCallback = build.NewMappingCallback(smsrc, options.GOROOT, options.GOPATH) deps, err := compiler.ImportDependencies(buildpkg.Archive, session.ImportContext.Import) if err != nil { return err } err = compiler.WriteProgramCode(deps, smfilter) smsrc.WriteTo(jsmap) js.WriteString("//# sourceMappingURL=" + name + ".map.js\n") return nil }
func (fs serveCommandFileSystem) Open(requestName string) (http.File, error) { name := path.Join(fs.serveRoot, requestName[1:]) // requestName[0] == '/' dir, file := path.Split(name) base := path.Base(dir) // base is parent folder name, which becomes the output file name. isPkg := file == base+".js" isMap := file == base+".js.map" isIndex := file == "index.html" if isPkg || isMap || isIndex { // If we're going to be serving our special files, make sure there's a Go command in this folder. s := gbuild.NewSession(fs.options) pkg, err := gbuild.Import(path.Dir(name), 0, s.InstallSuffix(), fs.options.BuildTags) if err != nil || pkg.Name != "main" { isPkg = false isMap = false isIndex = false } switch { case isPkg: buf := bytes.NewBuffer(nil) browserErrors := bytes.NewBuffer(nil) exitCode := handleError(func() error { archive, err := s.BuildPackage(pkg) if err != nil { return err } sourceMapFilter := &compiler.SourceMapFilter{Writer: buf} m := &sourcemap.Map{File: base + ".js"} sourceMapFilter.MappingCallback = gbuild.NewMappingCallback(m, fs.options.GOROOT, fs.options.GOPATH) deps, err := compiler.ImportDependencies(archive, s.BuildImportPath) if err != nil { return err } if err := compiler.WriteProgramCode(deps, sourceMapFilter); err != nil { return err } mapBuf := bytes.NewBuffer(nil) m.WriteTo(mapBuf) buf.WriteString("//# sourceMappingURL=" + base + ".js.map\n") fs.sourceMaps[name+".map"] = mapBuf.Bytes() return nil }, fs.options, browserErrors) if exitCode != 0 { buf = browserErrors } return newFakeFile(base+".js", buf.Bytes()), nil case isMap: if content, ok := fs.sourceMaps[name]; ok { return newFakeFile(base+".js.map", content), nil } } } for _, d := range fs.dirs { dir := http.Dir(filepath.Join(d, "src")) f, err := dir.Open(name) if err == nil { return f, nil } // source maps are served outside of serveRoot f, err = dir.Open(requestName) if err == nil { return f, nil } } if isIndex { // If there was no index.html file in any dirs, supply our own. return newFakeFile("index.html", []byte(`<html><head><meta charset="utf-8"><script src="`+base+`.js"></script></head></html>`)), nil } return nil, os.ErrNotExist }
func (fs serveCommandFileSystem) Open(name string) (http.File, error) { for _, d := range fs.dirs { file, err := http.Dir(filepath.Join(d, "src")).Open(name) if err == nil { return file, nil } } if strings.HasSuffix(name, "/main.js.map") { if content, ok := fs.sourceMaps[name]; ok { return newFakeFile("main.js.map", content), nil } } isIndex := strings.HasSuffix(name, "/index.html") isMain := strings.HasSuffix(name, "/main.js") if isIndex || isMain { s := gbuild.NewSession(fs.options) buildPkg, err := gbuild.Import(path.Dir(name[1:]), 0, s.InstallSuffix(), fs.options.BuildTags) if err != nil || buildPkg.Name != "main" { return nil, os.ErrNotExist } if isIndex { return newFakeFile("index.html", []byte(`<html><head><meta charset="utf-8"><script src="main.js"></script></head></html>`)), nil } if isMain { buf := bytes.NewBuffer(nil) browserErrors := bytes.NewBuffer(nil) exitCode := handleError(func() error { pkg := &gbuild.PackageData{Package: buildPkg} if err := s.BuildPackage(pkg); err != nil { return err } sourceMapFilter := &compiler.SourceMapFilter{Writer: buf} m := &sourcemap.Map{File: "main.js"} sourceMapFilter.MappingCallback = gbuild.NewMappingCallback(m, fs.options.GOROOT, fs.options.GOPATH) deps, err := compiler.ImportDependencies(pkg.Archive, s.ImportContext.Import) if err != nil { return err } if err := compiler.WriteProgramCode(deps, sourceMapFilter); err != nil { return err } mapBuf := bytes.NewBuffer(nil) m.WriteTo(mapBuf) buf.WriteString("//# sourceMappingURL=main.js.map\n") fs.sourceMaps[name+".map"] = mapBuf.Bytes() return nil }, fs.options, browserErrors) if exitCode != 0 { buf = browserErrors } return newFakeFile("main.js", buf.Bytes()), nil } } return nil, os.ErrNotExist }