From c2a3326377f5dc020ce55309d38280eff9fc7c1c Mon Sep 17 00:00:00 2001 From: SheetJS Date: Tue, 14 Feb 2023 01:54:02 -0500 Subject: [PATCH] goja --- docz/docs/03-demos/31-engines/05_goja.md | 136 ++++++++++++++++++++++ docz/docs/03-demos/31-engines/index.md | 140 +---------------------- docz/static/goja/SheetGoja.go | 61 ++++++++++ 3 files changed, 199 insertions(+), 138 deletions(-) create mode 100644 docz/docs/03-demos/31-engines/05_goja.md create mode 100644 docz/static/goja/SheetGoja.go diff --git a/docz/docs/03-demos/31-engines/05_goja.md b/docz/docs/03-demos/31-engines/05_goja.md new file mode 100644 index 0000000..a4544e3 --- /dev/null +++ b/docz/docs/03-demos/31-engines/05_goja.md @@ -0,0 +1,136 @@ +--- +title: Go + Goja +pagination_prev: demos/cli +pagination_next: demos/clipboard +--- + +Goja is a pure Go implementation of ECMAScript 5. + +The [Standalone scripts](/docs/getting-started/installation/standalone) can be +parsed and evaluated in a Goja context. + +## Integration Details + +_Initialize Goja_ + +Goja does not provide a `global` variable. It can be created in one line: + +```go +/* initialize */ +vm := goja.New() + +/* goja does not expose a standard "global" by default */ +// highlight-next-line +v, err := vm.RunString("var global = (function(){ return this; }).call(null);") +``` + +_Load SheetJS Scripts_ + +The shim and main libraries can be loaded by reading the scripts from the file +system and evaluating in the Goja context: + +```go +func safe_run_file(vm *goja.Runtime, file string) { + data, err := ioutil.ReadFile(file) + if err != nil { panic(err) } + src := string(data) + _, err = vm.RunString(src) + if err != nil { panic(err) } +} + +// ... + safe_run_file(vm, "shim.min.js") + safe_run_file(vm, "xlsx.full.min.js") +``` + +To confirm the library is loaded, `XLSX.version` can be inspected: + +```go + /* get version string */ + v, err := vm.RunString("XLSX.version") + fmt.Printf("SheetJS library version %s\n", v) +``` + +### Reading Files + +Files can be read into `[]byte`: + +```go +/* read file */ +data, _ := ioutil.ReadFile("sheetjs.xlsx") +``` + +`[]byte` should be converted to an `ArrayBuffer` from Go: + +```go +/* load into engine */ +vm.Set("buf", vm.ToValue(vm.NewArrayBuffer(data))) + +/* parse */ +wb, _ = vm.RunString("wb = XLSX.read(buf, {type:'buffer'});") +``` + +### Writing Files + +`"base64"` strings can be passed from the JS context to Go code: + +```go +/* write to Base64 string */ +b64str, _ := vm.RunString("XLSX.write(wb, {type:'base64', bookType:'xlsx'})") + +/* pull data back into Go and write to file */ +buf, _ := base64.StdEncoding.DecodeString(b64str.String()) +_ = ioutil.WriteFile("sheetjs.xlsx", buf, 0644) +``` + +## Complete Example + +:::note + +This demo was tested on 2023 February 14. + +::: + +0) Create a module and install dependencies: + +```bash +mkdir SheetGoja +cd SheetGoja +go mod init SheetGoja +go get github.com/dop251/goja +``` + +1) Download the standalone script, shim and test file: + + + +```bash +curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js +curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js +curl -LO https://sheetjs.com/pres.numbers +``` + +2) Download [`SheetGoja.go`](pathname:///goja/SheetGoja.go): + +```bash +curl -LO https://docs.sheetjs.com/goja/SheetGoja.go +``` + +3) Build standalone `SheetGoja` binary: + +```bash +go build SheetGoja.go +``` + +4) Run the demo: + +```bash +./SheetGoja pres.numbers +``` + +If the program succeeded, the CSV contents will be printed to console and the +file `sheetjsw.xlsb` will be created. That file can be opened with Excel. diff --git a/docz/docs/03-demos/31-engines/index.md b/docz/docs/03-demos/31-engines/index.md index a0a1268..73d93c2 100644 --- a/docz/docs/03-demos/31-engines/index.md +++ b/docz/docs/03-demos/31-engines/index.md @@ -67,145 +67,9 @@ The demo includes examples in C and Perl. ### Goja -Goja is a pure Go implementation of ECMAScript 5. It supports the standalone -scripts out of the box. - -**Reading data** - -Files can be read into `[]byte`: - -```go -/* read file */ -data, _ := ioutil.ReadFile("sheetjs.xlsx") -``` - -`[]byte` should be converted to an `ArrayBuffer` from Go: - -```go -/* load into engine */ -vm.Set("buf", vm.ToValue(vm.NewArrayBuffer(data))) - -/* parse */ -wb, _ = vm.RunString("wb = XLSX.read(buf, {type:'buffer'});") -``` - -**Writing data** - -`"base64"` strings can be decoded in Go: - -```go -/* write to Base64 string */ -b64str, _ := vm.RunString("XLSX.write(wb, {type:'base64', bookType:'xlsx'})") - -/* pull data back into Go and write to file */ -buf, _ := base64.StdEncoding.DecodeString(b64str.String()) -_ = ioutil.WriteFile("sheetjs.xlsx", buf, 0644) -``` - -
Complete Example (click to show) - -0) Install Go - -1) Create a `go.mod` file and install dependencies: - -```bash -go mod init SheetGoja -go get github.com/dop251/goja -``` - -2) Download the standalone script and the shim: - - - -3) Save the following code to `SheetGoja.go`: - -```go title="SheetGoja.go" -package main - -import ( - b64 "encoding/base64" - "fmt" - "os" - "io/ioutil" - "github.com/dop251/goja" -) - -func safe_run_file(vm *goja.Runtime, file string) { - data, err := ioutil.ReadFile(file) - if err != nil { panic(err) } - src := string(data) - _, err = vm.RunString(src) - if err != nil { panic(err) } -} - -func eval_string(vm *goja.Runtime, cmd string) goja.Value { - v, err := vm.RunString(cmd) - if err != nil { panic(err) } - return v -} - -func write_type(vm *goja.Runtime, t string) { - b64str := eval_string(vm, "XLSX.write(wb, {type:'base64', bookType:'" + t + "'})") - buf, err := b64.StdEncoding.DecodeString(b64str.String()); - if err != nil { panic(err) } - err = ioutil.WriteFile("sheetjsg." + t, buf, 0644) - if err != nil { panic(err) } -} - -func main() { - vm := goja.New() - - /* initialize */ - eval_string(vm, "if(typeof global == 'undefined') global = (function(){ return this; }).call(null);") - - /* load library */ - safe_run_file(vm, "shim.min.js") - safe_run_file(vm, "xlsx.full.min.js") - - /* get version string */ - v := eval_string(vm, "XLSX.version") - fmt.Printf("SheetJS library version %s\n", v) - - /* read file */ - data, err := ioutil.ReadFile(os.Args[1]) - if err != nil { panic(err) } - vm.Set("buf", vm.ToValue(vm.NewArrayBuffer(data))) - fmt.Printf("Loaded file %s\n", os.Args[1]) - - /* parse workbook */ - eval_string(vm, "wb = XLSX.read(buf, {type:'buffer'});") - fmt.Printf("Parsed %s\n", os.Args[1]) - eval_string(vm, "ws = wb.Sheets[wb.SheetNames[0]]") - fmt.Printf("Grabbed %s\n", os.Args[1]) - - /* print CSV */ - csv := eval_string(vm, "XLSX.utils.sheet_to_csv(ws)") - fmt.Printf("%s\n", csv) - - /* write file */ - write_type(vm, "csv") -} -``` - -4) Build `SheetGoja`: - -```bash -go build SheetGoja.go -``` - -For testing, download and run - -```bash -./SheetGoja pres.numbers -``` - -This will print the contents as a CSV to screen AND write to `sheetjsg.csv` - -
+Goja is a pure Go implementation of ECMAScript 5. +This demo has been moved [to a dedicated page](/docs/demos/engines/goja). ### Hermes diff --git a/docz/static/goja/SheetGoja.go b/docz/static/goja/SheetGoja.go new file mode 100644 index 0000000..42caa0e --- /dev/null +++ b/docz/static/goja/SheetGoja.go @@ -0,0 +1,61 @@ +/* SheetGoja (C) SheetJS LLC -- https://sheetjs.com */ +package main + +import ( + b64 "encoding/base64" + "fmt" + "os" + "io/ioutil" + "github.com/dop251/goja" +) + +func safe_run_file(vm *goja.Runtime, file string) { + data, err := ioutil.ReadFile(file) + if err != nil { panic(err) } + _, err = vm.RunString(string(data)) + if err != nil { panic(err) } +} + +func eval_string(vm *goja.Runtime, cmd string) goja.Value { + v, err := vm.RunString(cmd) + if err != nil { panic(err) } + return v +} + +func write_type(vm *goja.Runtime, t string) { + b64str := eval_string(vm, "XLSX.write(wb, {type:'base64', bookType:'" + t + "'})") + buf, err := b64.StdEncoding.DecodeString(b64str.String()); + if err != nil { panic(err) } + err = ioutil.WriteFile("sheetjsw." + t, buf, 0644) + if err != nil { panic(err) } +} + +func main() { + /* initialize */ + vm := goja.New() + eval_string(vm, "var global = (function(){ return this; }).call(null);") + + /* load library */ + safe_run_file(vm, "shim.min.js") + safe_run_file(vm, "xlsx.full.min.js") + + /* get version string */ + v := eval_string(vm, "XLSX.version") + fmt.Printf("SheetJS library version %s\n", v) + + /* read file */ + data, err := ioutil.ReadFile(os.Args[1]) + if err != nil { panic(err) } + vm.Set("buf", vm.ToValue(vm.NewArrayBuffer(data))) + + /* parse workbook */ + eval_string(vm, "wb = XLSX.read(buf, {type:'buffer'});") + eval_string(vm, "ws = wb.Sheets[wb.SheetNames[0]]") + + /* print CSV */ + csv := eval_string(vm, "XLSX.utils.sheet_to_csv(ws)") + fmt.Printf("%s\n", csv) + + /* write file */ + write_type(vm, "xlsb") +} \ No newline at end of file