diff --git a/docz/docs/03-demos/06-desktop/09-cli.md b/docz/docs/03-demos/06-desktop/09-cli.md index 7707ffd..dc33631 100644 --- a/docz/docs/03-demos/06-desktop/09-cli.md +++ b/docz/docs/03-demos/06-desktop/09-cli.md @@ -17,6 +17,68 @@ it is feasible to build command-line tools for various workflows. This demo covers a number of strategies for building standalone processors. The goal is to generate CSV output from an arbitrary spreadsheet file. +## V8 + +The [V8](/docs/demos/engines/v8) demo covers standalone programs that embed the +V8 engine. This demo uses the Rust integration to generate a command line tool. + +
Tested Deployments (click to show) + +This demo was last tested in the following deployments: + +| Architecture | V8 Version | Date | +|:-------------|:-------------|:-----------| +| `darwin-x64` | `11.4.183.2` | 2023-05-22 | + +
+ +0) Make a new folder for the project: + +```bash +mkdir sheetjs2csv +cd sheetjs2csv +``` + +1) Download the following scripts: + +- [`Cargo.toml`](pathname:///cli/Cargo.toml) +- [`snapshot.rs`](pathname:///cli/snapshot.rs) +- [`sheet2csv.rs`](pathname:///cli/sheet2csv.rs) + +```bash +curl -LO https://docs.sheetjs.com/cli/Cargo.toml +curl -LO https://docs.sheetjs.com/cli/snapshot.rs +curl -LO https://docs.sheetjs.com/cli/sheet2csv.rs +``` + +2) Download the [standalone build](/docs/getting-started/installation/standalone): + +{`\ +curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`} + + +3) Build the V8 snapshot: + +```bash +cargo build --bin snapshot +cargo run --bin snapshot +``` + +4) Build `sheet2csv`: + +```bash +cargo build --release --bin sheet2csv +mv target/release/sheet2csv . +``` + +5) Download the test file : + +```bash +curl -LO https://sheetjs.com/pres.numbers +``` + +Test by running `./sheet2csv pres.numbers` + ## NodeJS There are a few popular tools for compiling NodeJS scripts to CLI programs. @@ -185,8 +247,8 @@ deno compile -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts The following demos for JS engines produce standalone programs: -- [ChakraCore](/docs/demos/engines/chakra) - [Duktape](/docs/demos/engines/duktape) +- [ChakraCore](/docs/demos/engines/chakra) +- [QuickJS](/docs/demos/engines/quickjs) - [Goja](/docs/demos/engines/goja) - [JavaScriptCore](/docs/demos/engines/jsc) -- [QuickJS](/docs/demos/engines/quickjs) diff --git a/docz/docs/03-demos/11-bigdata/02-worker.md b/docz/docs/03-demos/11-bigdata/02-worker.md index e17ac61..311f544 100644 --- a/docz/docs/03-demos/11-bigdata/02-worker.md +++ b/docz/docs/03-demos/11-bigdata/02-worker.md @@ -183,6 +183,20 @@ const worker = new Worker( ## Live Demos +:::note + +Each browser demo was tested in the following environments: + +| Browser | Date | Comments | +|:------------|:-----------|:----------------------------------------| +| Chrome 113 | 2023-05-22 | | +| Edge 113 | 2023-05-22 | | +| Safari 16.4 | 2023-05-22 | File System Access API is not supported | +| Brave 1.51 | 2023-05-22 | File System Access API is not supported | +| Firefox 113 | 2023-05-22 | File System Access API is not supported | + +::: + ### Downloading a Remote File :::note fetch in Web Workers diff --git a/docz/static/cli/Cargo.toml b/docz/static/cli/Cargo.toml new file mode 100644 index 0000000..957c392 --- /dev/null +++ b/docz/static/cli/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "sheetjs2csv" +version = "0.1.0" +edition = "2021" + +[dependencies] +v8 = "0.71.2" + +[[bin]] +name = "sheet2csv" +path = "sheet2csv.rs" + +[[bin]] +name = "snapshot" +path = "snapshot.rs" diff --git a/docz/static/cli/sheet2csv.rs b/docz/static/cli/sheet2csv.rs new file mode 100644 index 0000000..8ec5731 --- /dev/null +++ b/docz/static/cli/sheet2csv.rs @@ -0,0 +1,42 @@ +/* run code, get result as a Rust String */ +fn eval_code(scope: &mut v8::HandleScope, code: &str) -> std::string::String { + let source = v8::String::new(scope, &code).unwrap(); + let script = v8::Script::compile(scope, source, None).unwrap(); + let result = script.run(scope).unwrap(); + return result.to_string(scope).unwrap().to_rust_string_lossy(scope); +} + +fn main() { + /* parse arguments */ + let mut iter = std::env::args(); + let path: String = iter.nth(1).expect("must specify a file name"); + let sheetname: String = match iter.nth(0) { + Some(v) => format!("'{}'", v), + None => "wb.SheetNames[0]".to_string() + }; + + /* initialize */ + let platform = v8::new_default_platform(0, false).make_shared(); + v8::V8::initialize_platform(platform); + v8::V8::initialize(); + + /* read snapshot */ + let startup_data: Vec = include_bytes!("./snapshot.bin").to_vec(); + let params = v8::Isolate::create_params().snapshot_blob(startup_data); + let isolate = &mut v8::Isolate::new(params); + let handle_scope = &mut v8::HandleScope::new(isolate); + let context = v8::Context::new(handle_scope); + let context_scope = &mut v8::ContextScope::new(handle_scope, context); + + /* read file */ + let data: Vec = std::fs::read(path.clone()).unwrap(); + let back: v8::UniqueRef = v8::ArrayBuffer::new_backing_store_from_vec(data); + let shared = back.make_shared(); + let ab: v8::Local = v8::ArrayBuffer::with_backing_store(context_scope, &shared); + let key = v8::String::new(context_scope, "buf").unwrap(); + context.global(context_scope).set(context_scope, key.into(), ab.into()); + + /* print CSV of specified sheet */ + let result = eval_code(context_scope, &mut format!("var wb = XLSX.read(buf, {{dense: true}}); XLSX.utils.sheet_to_csv(wb.Sheets[{}])", sheetname)); + println!("{}", result); +} diff --git a/docz/static/cli/snapshot.rs b/docz/static/cli/snapshot.rs new file mode 100644 index 0000000..8644c08 --- /dev/null +++ b/docz/static/cli/snapshot.rs @@ -0,0 +1,38 @@ +/* run code, get result as a Rust String */ +fn eval_code(scope: &mut v8::HandleScope, code: &str) -> std::string::String { + let source = v8::String::new(scope, &code).unwrap(); + let script = v8::Script::compile(scope, source, None).unwrap(); + let result = script.run(scope).unwrap(); + return result.to_string(scope).unwrap().to_rust_string_lossy(scope); +} + + +fn main() { + create_snapshot(); +} + +fn create_snapshot() { + /* initialize */ + let platform = v8::new_default_platform(0, false).make_shared(); + v8::V8::initialize_platform(platform); + v8::V8::initialize(); + + let startup_data = { + let mut isolate = v8::Isolate::snapshot_creator(None); + { + let handle_scope = &mut v8::HandleScope::new(&mut isolate); + let context = v8::Context::new(handle_scope); + let context_scope = &mut v8::ContextScope::new(handle_scope, context); + + /* load library */ + { + let script = std::fs::read_to_string("./xlsx.full.min.js").expect("Error reading xlsx.full.min.js"); + let _result = eval_code(context_scope, &script); + } + context_scope.set_default_context(context); + } + isolate.create_blob(v8::FunctionCodeHandling::Clear).unwrap() + }; + let blob: Vec = startup_data.to_vec(); + std::fs::write("snapshot.bin", blob).unwrap(); +}