From e3ca16d9973d19e6646e1f1af19db77634a132e9 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Mon, 18 Mar 2024 04:24:41 -0400 Subject: [PATCH] node-sea --- .../02-frontend/19-bundler/05-webpack.md | 17 +- .../03-demos/03-net/03-server/04-drash.md | 2 +- docz/docs/03-demos/12-static/01-lume.md | 18 +- docz/docs/03-demos/19-desktop/01-electron.md | 2 +- docz/docs/03-demos/19-desktop/02-nwjs.md | 2 +- docz/docs/03-demos/19-desktop/03-wails.md | 2 +- docz/docs/03-demos/19-desktop/04-tauri.md | 2 +- .../docs/03-demos/19-desktop/05-neutralino.md | 2 +- .../03-demos/19-desktop/06-reactnative.md | 2 +- docz/docs/03-demos/19-desktop/_category_.json | 2 +- docz/docs/03-demos/19-desktop/index.md | 18 +- docz/docs/03-demos/20-cli/09-nodesea.md | 346 ++++++++++++++++++ docz/docs/03-demos/20-cli/23-deno.md | 151 ++++++++ docz/docs/03-demos/20-cli/_category_.json | 4 + .../{19-desktop/09-cli.md => 20-cli/index.md} | 104 +++--- docz/docs/03-demos/23-data/10-sql.md | 2 +- docz/docs/03-demos/23-data/11-sqlite.md | 2 +- docz/docs/03-demos/23-data/14-knex.md | 2 +- docz/docs/03-demos/23-data/16-postgresql.md | 2 +- docz/docs/03-demos/23-data/17-mariadb.md | 2 +- docz/docs/03-demos/23-data/19-alasql.md | 2 +- docz/docs/03-demos/23-data/25-mongodb.md | 2 +- docz/docs/03-demos/23-data/26-redis.md | 2 +- docz/docs/03-demos/23-data/29-pouchdb.md | 2 +- docz/docs/03-demos/23-data/index.md | 2 +- docz/docs/03-demos/27-local/01-file.md | 3 +- docz/docs/03-demos/30-cloud/19-deno.md | 2 +- .../03-demos/32-extensions/09-mathematica.md | 4 +- docz/docs/03-demos/32-extensions/11-matlab.md | 4 +- docz/docs/03-demos/index.md | 2 +- docz/docs/07-csf/07-features/01-dates.md | 143 +++++++- docz/docusaurus.config.js | 5 +- 32 files changed, 745 insertions(+), 112 deletions(-) create mode 100644 docz/docs/03-demos/20-cli/09-nodesea.md create mode 100644 docz/docs/03-demos/20-cli/23-deno.md create mode 100644 docz/docs/03-demos/20-cli/_category_.json rename docz/docs/03-demos/{19-desktop/09-cli.md => 20-cli/index.md} (84%) diff --git a/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md b/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md index da8cc60..109f17f 100644 --- a/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md +++ b/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md @@ -41,10 +41,10 @@ This demo was tested in the following environments: | Version | Date | Required Workarounds | |:---------|:-----------|:------------------------------------| -| `2.7.0` | 2023-10-17 | Import `xlsx/dist/xlsx.full.min.js` | -| `3.12.0` | 2023-10-17 | Import `xlsx/dist/xlsx.full.min.js` | -| `4.47.0` | 2023-10-17 | Downgrade NodeJS (tested v16.20.2) | -| `5.89.0` | 2023-12-04 | | +| `2.7.0` | 2024-03-16 | Import `xlsx/dist/xlsx.full.min.js` | +| `3.12.0` | 2024-03-16 | Import `xlsx/dist/xlsx.full.min.js` | +| `4.47.0` | 2024-03-16 | Downgrade NodeJS (tested v16.20.2) | +| `5.90.3` | 2024-03-16 | | ::: @@ -271,8 +271,13 @@ version above 4.0 can be pinned by locally installing webpack and the CLI tool. :::info pass -Webpack 4 is incompatible with Node 18+. When this demo was last tested, NodeJS -was locally downgraded to 16.20.2 +Webpack 4 is incompatible with Node 18+. It will elicit the following error: + +``` +Error: error:0308010C:digital envelope routines::unsupported +``` + +When this demo was last tested, NodeJS was locally downgraded to 16.20.2 ::: diff --git a/docz/docs/03-demos/03-net/03-server/04-drash.md b/docz/docs/03-demos/03-net/03-server/04-drash.md index 3b3fc40..be1c051 100644 --- a/docz/docs/03-demos/03-net/03-server/04-drash.md +++ b/docz/docs/03-demos/03-net/03-server/04-drash.md @@ -28,7 +28,7 @@ This demo was last tested on 2024 March 11 against Drash 2.8.1 and Deno 1.41.2. ## Integration Details -The [SheetJS Deno module](/docs/getting-started/installation/nodejs) can be +The [SheetJS Deno module](/docs/getting-started/installation/deno) can be imported from Drash server scripts. ### Reading Data diff --git a/docz/docs/03-demos/12-static/01-lume.md b/docz/docs/03-demos/12-static/01-lume.md index 2bf6b58..4f0ab81 100644 --- a/docz/docs/03-demos/12-static/01-lume.md +++ b/docz/docs/03-demos/12-static/01-lume.md @@ -129,7 +129,12 @@ site.use(sheets({ :::note Tested Deployments -This demo was last tested against Lume `v1.19.4` on 2023 December 04. +This demo was tested in the following environments: + +| Lume | Date | +|:---------|:-----------| +| `1.19.4` | 2024-03-16 | +| `2.1.2` | 2024-03-16 | This example uses the Nunjucks template format. Lume plugins support additional template formats, including Markdown and JSX. @@ -145,17 +150,24 @@ template formats, including Markdown and JSX. ```bash mkdir -p sheetjs-lume cd sheetjs-lume -deno run -Ar https://deno.land/x/lume/init.ts +deno run -Ar https://deno.land/x/lume@v2.1.2/init.ts ``` When prompted, enter the following options: - `Choose the configuration file format`: select `_config.ts` - `Do you want to install some plugins now?`: select `Yes` -- `Select the plugins to install`: scroll down, select `sheets`, and submit +- `Select the plugins to install`: select `sheets` and `nunjucks` +- `Do you want to setup a CMS?`: select `Maybe later` The project will be configured and modules will be installed. +:::note pass + +The `nunjucks` plugin was included by default in Lume version 1. + +::: + 2) Download and place in a `_data` subfolder: ```bash diff --git a/docz/docs/03-demos/19-desktop/01-electron.md b/docz/docs/03-demos/19-desktop/01-electron.md index 5e96dd4..a011c76 100644 --- a/docz/docs/03-demos/19-desktop/01-electron.md +++ b/docz/docs/03-demos/19-desktop/01-electron.md @@ -1,7 +1,7 @@ --- title: Electron pagination_prev: demos/mobile/index -pagination_next: demos/data/index +pagination_next: demos/cli/index sidebar_position: 1 sidebar_custom_props: summary: Embedded NodeJS + Chromium diff --git a/docz/docs/03-demos/19-desktop/02-nwjs.md b/docz/docs/03-demos/19-desktop/02-nwjs.md index 7eabd1f..ee37f3e 100644 --- a/docz/docs/03-demos/19-desktop/02-nwjs.md +++ b/docz/docs/03-demos/19-desktop/02-nwjs.md @@ -1,7 +1,7 @@ --- title: NW.js pagination_prev: demos/mobile/index -pagination_next: demos/data/index +pagination_next: demos/cli/index sidebar_position: 2 sidebar_custom_props: summary: Embedded Chromium + NodeJS diff --git a/docz/docs/03-demos/19-desktop/03-wails.md b/docz/docs/03-demos/19-desktop/03-wails.md index 5f7a8ff..0927de3 100644 --- a/docz/docs/03-demos/19-desktop/03-wails.md +++ b/docz/docs/03-demos/19-desktop/03-wails.md @@ -3,7 +3,7 @@ title: Spreadsheet-Powered Wails Apps sidebar_label: Wails description: Build data-intensive desktop apps using Wails. Seamlessly integrate spreadsheets into your app using SheetJS. Modernize Excel-powered business processes with confidence. pagination_prev: demos/mobile/index -pagination_next: demos/data/index +pagination_next: demos/cli/index sidebar_position: 3 sidebar_custom_props: summary: Webview + Go Backend diff --git a/docz/docs/03-demos/19-desktop/04-tauri.md b/docz/docs/03-demos/19-desktop/04-tauri.md index 4fbe5de..6a568f9 100644 --- a/docz/docs/03-demos/19-desktop/04-tauri.md +++ b/docz/docs/03-demos/19-desktop/04-tauri.md @@ -3,7 +3,7 @@ title: Data Wrangling in Tauri Apps sidebar_label: Tauri description: Build data-intensive desktop apps using Tauri. Seamlessly integrate spreadsheets into your app using SheetJS. Modernize Excel-powered business processes with confidence. pagination_prev: demos/mobile/index -pagination_next: demos/data/index +pagination_next: demos/cli/index sidebar_position: 4 sidebar_custom_props: summary: Webview + Rust Backend diff --git a/docz/docs/03-demos/19-desktop/05-neutralino.md b/docz/docs/03-demos/19-desktop/05-neutralino.md index b6a09d9..0c494a2 100644 --- a/docz/docs/03-demos/19-desktop/05-neutralino.md +++ b/docz/docs/03-demos/19-desktop/05-neutralino.md @@ -3,7 +3,7 @@ title: Data Munging in NeutralinoJS sidebar_label: NeutralinoJS description: Build data-intensive desktop apps using NeutralinoJS. Seamlessly integrate spreadsheets into your app using SheetJS. Quickly modernize Excel-powered business processes. pagination_prev: demos/mobile/index -pagination_next: demos/data/index +pagination_next: demos/cli/index sidebar_position: 5 sidebar_custom_props: summary: Webview + Lightweight Extensions diff --git a/docz/docs/03-demos/19-desktop/06-reactnative.md b/docz/docs/03-demos/19-desktop/06-reactnative.md index 296d55f..047eb9b 100644 --- a/docz/docs/03-demos/19-desktop/06-reactnative.md +++ b/docz/docs/03-demos/19-desktop/06-reactnative.md @@ -3,7 +3,7 @@ title: Sheets on the Desktop with React Native sidebar_label: React Native description: Build data-intensive desktop apps with React Native. Seamlessly integrate spreadsheets into your app using SheetJS. Securely process and generate Excel files at the desk. pagination_prev: demos/mobile/index -pagination_next: demos/data/index +pagination_next: demos/cli/index sidebar_position: 6 sidebar_custom_props: summary: Native Components with React diff --git a/docz/docs/03-demos/19-desktop/_category_.json b/docz/docs/03-demos/19-desktop/_category_.json index a78039b..b85604e 100644 --- a/docz/docs/03-demos/19-desktop/_category_.json +++ b/docz/docs/03-demos/19-desktop/_category_.json @@ -1,4 +1,4 @@ { - "label": "Desktop and CLI Tools", + "label": "Desktop Apps", "position": 19 } diff --git a/docz/docs/03-demos/19-desktop/index.md b/docz/docs/03-demos/19-desktop/index.md index 801382c..f61da32 100644 --- a/docz/docs/03-demos/19-desktop/index.md +++ b/docz/docs/03-demos/19-desktop/index.md @@ -1,7 +1,7 @@ --- -title: Desktop and CLI Tools +title: Desktop Applications pagination_prev: demos/mobile/index -pagination_next: demos/data/index +pagination_next: demos/cli/index --- import DocCardList from '@theme/DocCardList'; @@ -40,16 +40,4 @@ Frameworks like React Native generate applications that use native UI elements. ## Command-Line Tools -Command-line tools bundle a JavaScript engine and a system runtime. The runtime -provides low-level access to computer resources. - -Demos for common command-line tools are included in separate pages: - - +**[The exposition has been moved to a separate page.](/docs/demos/cli)** diff --git a/docz/docs/03-demos/20-cli/09-nodesea.md b/docz/docs/03-demos/20-cli/09-nodesea.md new file mode 100644 index 0000000..9421471 --- /dev/null +++ b/docz/docs/03-demos/20-cli/09-nodesea.md @@ -0,0 +1,346 @@ +--- +title: NodeJS SEA +pagination_prev: demos/desktop/index +pagination_next: demos/data/index +sidebar_custom_props: + summary: Single Executable Applications +--- + +import current from '/version.js'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import CodeBlock from '@theme/CodeBlock'; + +NodeJS "Single Executable Applications"[^1] are standalone CLI tools that embed +bundled scripts in a special standalone copy of the NodeJS binary. + +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. + +This demo uses NodeJS SEA and SheetJS to create a standalone CLI tool for +parsing spreadsheets and generating CSV rows. + +:::info pass + +It is strongly recommended to install NodeJS on systems using SheetJS libraries +in command-line tools. This workaround should only be considered if a standalone +binary is considered desirable. + +::: + +:::caution NodeJS SEA support is considered experimental. + +Great open source software grows with user tests and reports. Any issues should +be reported to the NodeJS single-executable project for further diagnosis. + +::: + +## Integration Details + +The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be +required from NodeJS SEA base scripts. + +:::info pass + +**NodeJS SEA does not support ECMAScript Modules!** + +A CommonJS script is conveniently included in the SheetJS NodeJS module package. + +::: + +At a high level, single-executable applications are constructed in four steps: + +1) Pre-process an existing NodeJS script, creating a SEA bundle. + +2) Copy the NodeJS binary and remove any signatures. + +3) Inject the SEA bundle into the unsigned NodeJS binary. + +4) Re-sign the binary. + +:::note pass + +macOS and Windows enforce digital signatures. Both operating systems will warn +users if a signed program is modified. + +Existing signatures should be removed *before* injecting the SEA bundle. After +injecting the SEA bundle, the binary should be resigned. + +::: + +### Script Requirements + +Scripts that exclusively use SheetJS libraries and NodeJS built-in modules can +be bundled using NodeJS SEA. Due to limitations in the SEA bundler, a special +`require` function must be created manually: + +```js +const { createRequire } = require('node:module'); +require = createRequire(__filename); +const { readFile, utils } = require("xlsx"); +``` + +For example, the following script accepts one command line argument, parses the +specified file using the SheetJS `readFile` method[^2], generates CSV text from +the first worksheet using `sheet_to_csv`[^3], and prints to terminal: + +```js title="sheet2csv.js" +// For NodeJS SEA, the CommonJS `require` must be used +const { createRequire } = require('node:module'); +require = createRequire(__filename); +const { readFile, utils } = require("xlsx"); + +// argv[2] is the first argument to the script +const filename = process.argv[2]; + +// read file +const wb = readFile(filename); + +// generate CSV of first sheet +const ws = wb.Sheets[wb.SheetNames[0]]; +const csv = utils.sheet_to_csv(ws); + +// print to terminal +console.log(csv); +``` + +### SEA Bundles + +SEA Bundles are blobs that represent the script and supporting libraries. + +#### Configuration + +SEA configuration is specified using a special JSON file. Assuming no special +assets are bundled with the script, there are two relevant fields: + +- `main` is a relative path to the entry script. +- `output` is a relative path to the output file (typically ending in `.blob`) + +For example, the following configuration specifies `sheet2csv.js` as the entry +script and `sheet2csv.blob` as the output blob: + +```js title="sheet2csv.json" +{ + "main": "sheet2csv.js", + "output": "sheet2csv.blob" +} +``` + +#### Construction + +The main `node` program, with the command-line flag `--experimental-sea-config`, +will generate a SEA bundle: + +```bash +node --experimental-sea-config sheet2csv.json +``` + +The bundle will be written to the file specified in the `output` field of the +SEA configuration file. + +#### Injection + +A special `postject` utility is used to add the SEA bundle to the NodeJS binary. +The specific command depends on the operating system. + +On macOS, assuming the copy of the NodeJS binary is named `sheet2csv` and the +SEA bundle is named `sheet2csv.blob`, the following command injects the bundle: + +```bash +npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 --macho-segment-name NODE_SEA sheet2csv NODE_SEA_BLOB sheet2csv.blob +``` + +## Complete Example + +:::note Tested Deployments + +This demo was tested in the following deployments: + +| Architecture | NodeJS | Date | +|:-------------|:----------|:-----------| +| `darwin-x64` | `20.11.1` | 2024-03-17 | +| `linux-x64` | `20.11.1` | 2024-03-18 | + +::: + +0) Ensure NodeJS version 20 or later is installed. + +:::note pass + +To display the current version, run the following command: + +```bash +node --version +``` + +The major version number starts after the `v` and ends before the first `.` + +If the version number is 19 or earlier, upgrade NodeJS before proceeding. + +::: + +### Project Setup + +1) Create a new project folder: + +```bash +mkdir sheetjs-sea +cd sheetjs-sea +npm init -y +``` + +2) Save the [contents of the `sheet2csv.js` code block](#script-requirements) +to `sheet2csv.js` in the project folder. + +3) Install the SheetJS dependency: + + + +{`\ +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} + + + +{`\ +pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} + + + +{`\ +yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} + + + + +### Script Test + +:::caution pass + +Before building the standalone app, the base script should be tested using the +local NodeJS platform. + +::: + +4) Download the test file : + +```bash +curl -LO https://sheetjs.com/pres.numbers +``` + +5) Run the script and pass `pres.numbers` as the first argument: + +```bash +node sheet2csv.js pres.numbers +``` + +The script should display CSV contents from the first sheet: + +``` +Name,Index +Bill Clinton,42 +GeorgeW Bush,43 +Barack Obama,44 +Donald Trump,45 +Joseph Biden,46 +``` + +### SEA Bundle + +6) Save the [contents of the `sheet2csv.json` code block](#configuration) to +`sheet2csv.json` in the project folder. + +7) Generate the SEA bundle: + +```bash +node --experimental-sea-config sheet2csv.json +``` + +### SEA Injection + +8) Create a local copy of the NodeJS binary. On macOS and Linux: + +```bash +cp `which node` sheet2csv +``` + + + + +9) Remove the code signature. + +```bash +codesign --remove-signature ./sheet2csv +``` + + + + +9) Observe that many Linux distributions do not enforce code signatures. + + + + +10) Inject the SEA bundle. + + + + +```bash +npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 --macho-segment-name NODE_SEA sheet2csv NODE_SEA_BLOB sheet2csv.blob +``` + +11) Resign the binary. The following command performs macOS ad-hoc signing: + +```bash +codesign -s - ./sheet2csv +``` + + + + +```bash +npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 sheet2csv NODE_SEA_BLOB sheet2csv.blob +``` + +11) Observe that many Linux distributions do not enforce code signatures. + + + + + +### Standalone Test + +12) Run the command and pass `pres.numbers` as the first argument: + +```bash +./sheet2csv pres.numbers +``` + +The program should display the same CSV contents as the script (from step 5) + + + + +13) Validate the binary signature. On macOS: + +```bash +codesign -dv ./sheet2csv +``` + +Inspecting the output, the following line confirms ad-hoc signing was used: + +``` +Signature=adhoc +``` + + + + +13) Observe that many Linux distributions do not enforce code signatures. + + + + +[^1]: See ["Single Executable Applications"](https://nodejs.org/api/single-executable-applications.html) in the NodeJS documentation. +[^2]: See [`readFile` in "Reading Files"](/docs/api/parse-options) +[^3]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output) diff --git a/docz/docs/03-demos/20-cli/23-deno.md b/docz/docs/03-demos/20-cli/23-deno.md new file mode 100644 index 0000000..179edca --- /dev/null +++ b/docz/docs/03-demos/20-cli/23-deno.md @@ -0,0 +1,151 @@ +--- +title: Deno Compiler +pagination_prev: demos/desktop/index +pagination_next: demos/data/index +sidebar_custom_props: + summary: Deno Standalone Binaries +--- + +import current from '/version.js'; +import CodeBlock from '@theme/CodeBlock'; + +[Deno](https://docs.deno.com/runtime/manual/tools/compiler) is a JavaScript +runtime with support for compiling scripts into self-contained executables. + +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. + +This demo uses the Deno compiler and SheetJS to create a standalone CLI tool for +parsing spreadsheets and generating CSV rows. + +:::info pass + +It is strongly recommended to install Deno on systems using SheetJS libraries in +command-line tools. This workaround should only be considered if a standalone +binary is considered desirable. + +::: + +:::caution Deno support is considered experimental. + +Great open source software grows with user tests and reports. Any issues should +be reported to the Deno project for further diagnosis. + +::: + +## Integration Details + +The [SheetJS Deno module](/docs/getting-started/installation/deno) can be +imported from Deno scripts. + +`deno compile` generates a standalone executable that includes the entire JS +runtime as well as user JS code. + +### Script Requirements + +Scripts that exclusively use SheetJS libraries and Deno built-in modules can be +bundled using `deno compile`. The ESM script should be imported directly: + +{`\ +// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" +import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';`} + + +For example, the following script accepts one command line argument, parses the +specified file using the SheetJS `readFile` method[^1], generates CSV text from +the first worksheet using `sheet_to_csv`[^2], and prints to terminal: + +{`\ +// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts" +import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs'; +import * as cptable from 'https://cdn.sheetjs.com/xlsx-${current}/package/dist/cpexcel.full.mjs'; +XLSX.set_cptable(cptable); +\n\ +/* Deno.args[0] is the first argument to the script */ +const filename = Deno.args[0]; +\n\ +/* read file */ +const wb = XLSX.readFile(filename); +\n\ +/* generate CSV of first sheet */ +const ws = wb.Sheets[wb.SheetNames[0]]; +const csv = utils.sheet_to_csv(ws); +\n\ +/* print to terminal */ +console.log(csv);`} + + +### Deno Permissions + +The same permissions that apply to normal Deno scripts apply to the compiler: + +- The `--allow-read` option must be specified to allow the program to read files + from the filesystem with the SheetJS `readFile` [^3] method. + +- The `--allow-write` option must be specified to allow the program to write + files to the filesystem with the SheetJS `writeFile` [^4] method. + +- The `--allow-net` option must be specified to allow the program to download + and upload spreadsheets. + +More flags can be found in the official permissions list[^5] + + +## Complete Example + +:::note Tested Deployments + +This demo was last tested in the following deployments: + +| Architecture | Deno | Date | +|:-------------|:---------|:-----------| +| `darwin-x64` | `1.41.3` | 2024-03-15 | +| `darwin-arm` | `1.37.2` | 2023-10-18 | +| `win10-x64` | `1.37.1` | 2023-10-09 | +| `win11-x64` | `1.37.2` | 2023-10-14 | +| `win11-arm` | `1.38.4` | 2023-12-01 | +| `linux-x64` | `1.41.3` | 2024-03-18 | +| `linux-arm` | `1.38.4` | 2023-12-01 | + +::: + +0) Install Deno.[^6] + +1) Download the test file : + +```bash +curl -LO https://sheetjs.com/pres.numbers +``` + +2) Test the script with `deno run`: + +```bash +deno run -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts pres.numbers +``` + +The script should display CSV contents from the first sheet: + +``` +Name,Index +Bill Clinton,42 +GeorgeW Bush,43 +Barack Obama,44 +Donald Trump,45 +Joseph Biden,46 +``` + +3) Compile and run `sheet2csv`: + +```bash +deno compile -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts +./sheet2csv pres.numbers +``` + +The program should display the same CSV contents as the script (from step 2) + +[^1]: See [`readFile` in "Reading Files"](/docs/api/parse-options) +[^2]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output) +[^3]: See [`readFile` in "Reading Files"](/docs/api/parse-options) +[^4]: See [`writeFile` in "Writing Files"](/docs/api/write-options) +[^5]: See ["Permissions list"](https://docs.deno.com/runtime/manual/basics/permissions#permissions-list) in the official Deno documentation +[^6]: [The official instructions](https://docs.deno.com/runtime/manual/getting_started/installation) cover most platforms. Deno does not provide official Linux ARM64 builds, but [there are unofficial community builds](https://github.com/LukeChannings/deno-arm64). \ No newline at end of file diff --git a/docz/docs/03-demos/20-cli/_category_.json b/docz/docs/03-demos/20-cli/_category_.json new file mode 100644 index 0000000..e90f116 --- /dev/null +++ b/docz/docs/03-demos/20-cli/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Command-Line Tools", + "position": 20 +} diff --git a/docz/docs/03-demos/19-desktop/09-cli.md b/docz/docs/03-demos/20-cli/index.md similarity index 84% rename from docz/docs/03-demos/19-desktop/09-cli.md rename to docz/docs/03-demos/20-cli/index.md index 9dee21c..86ec1a2 100644 --- a/docz/docs/03-demos/19-desktop/09-cli.md +++ b/docz/docs/03-demos/20-cli/index.md @@ -1,21 +1,47 @@ --- title: Command-Line Tools -pagination_prev: demos/mobile/index +pagination_prev: demos/desktop/index pagination_next: demos/data/index -sidebar_custom_props: - cli: true --- import current from '/version.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; With the availability of JS engines and the success of server-side platforms, -it is feasible to build command-line tools for various workflows. +it is possible to build standalone command-line tools from JavaScript code. -This demo covers a number of strategies for building standalone processors. The -goal is to generate CSV output from an arbitrary spreadsheet file. +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. + +This demo covers a number of strategies for building standalone spreadsheet +processors. The ultimate goal is to use SheetJS libraries to generate CSV output +from arbitrary spreadsheet files. The generated command-line tool will accept an +argument, parse the specified workbook, and print CSV rows to the terminal. + +>**Sample terminal session** +```bash +$ xlsx-cli.exe pres.numbers +Name,Index +Bill Clinton,42 +GeorgeW Bush,43 +Barack Obama,44 +Donald Trump,45 +Joseph Biden,46 +``` + +Demos for common standalone CLI tools are included in separate pages: + +
    {useCurrentSidebarCategory().items.map((item, index) => { + const listyle = (item.customProps?.icon) ? { + listStyleImage: `url("${item.customProps.icon}")` + } : {}; + return (
  • + {item.label}{item.customProps?.summary && (" - " + item.customProps.summary)} +
  • ); +})}
:::tip pass @@ -25,6 +51,18 @@ translating files between supported spreadsheet file formats. ::: +:::caution pass + +For most common deployment scenarios, it is possible to install a server-side +platform such as [NodeJS](/docs/getting-started/installation/nodejs). + +**It is strongly recommended to use a dedicated platform when possible.** + +The standalone programs generated in this demo are useful when a dedicated +server-side scripting platform cannot be installed on the target computer. + +::: + ## NodeJS There are a few popular tools for compiling NodeJS scripts to CLI programs. @@ -309,7 +347,7 @@ This demo was last tested in the following deployments: | `darwin-arm` | `11.8.172.13` | `0.79.2` | 2023-10-18 | | `win10-x64` | `11.8.172.13` | `0.79.2` | 2023-10-09 | | `win11-x64` | `11.8.172.13` | `0.79.2` | 2023-10-14 | -| `linux-x64` | `12.0.267.8` | `0.83.1` | 2024-01-26 | +| `linux-x64` | `12.3.219.9` | `0.88.0` | 2024-03-18 | | `linux-arm` | `12.0.267.8` | `0.82.0` | 2023-12-01 | ::: @@ -400,54 +438,9 @@ mv target/release/sheet2csv.exe . -## Deno +#### Deno -`deno compile` generates a standalone executable that includes the entire JS -runtime as well as user JS code. - -When compiling, the `--allow-read` option must be specified to allow the script -to read files from the filesystem with `Deno.readFileSync`. - - can be compiled and run from Deno. - -:::note Tested Deployments - -This demo was last tested in the following deployments: - -| Architecture | Version | Date | -|:-------------|:---------|:-----------| -| `darwin-x64` | `1.41.3` | 2024-03-15 | -| `darwin-arm` | `1.37.2` | 2023-10-18 | -| `win10-x64` | `1.37.1` | 2023-10-09 | -| `win11-x64` | `1.37.2` | 2023-10-14 | -| `win11-arm` | `1.38.4` | 2023-12-01 | -| `linux-x64` | `1.39.4` | 2024-01-22 | -| `linux-arm` | `1.38.4` | 2023-12-01 | - -::: - -0) Install Deno.[^2] - -1) Download the test file : - -```bash -curl -LO https://sheetjs.com/pres.numbers -``` - -2) Test the script with `deno run`: - -```bash -deno run -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts pres.numbers -``` - -If this worked, the program will print a CSV of the first worksheet. - -3) Compile and run `sheet2csv`: - -```bash -deno compile -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts -./sheet2csv pres.numbers -``` +**[The exposition has been moved to a separate page.](/docs/demos/cli/deno)** ## Dedicated Engines @@ -459,5 +452,4 @@ The following demos for JS engines produce standalone programs: - [Goja](/docs/demos/engines/goja) - [JavaScriptCore](/docs/demos/engines/jsc) -[^1]: Downloads can be found [at the main NASM project website](https://www.nasm.us/) -[^2]: [The official instructions](https://docs.deno.com/runtime/manual/getting_started/installation) cover most platforms. Deno does not provide official Linux ARM64 builds, but [there are unofficial community builds](https://github.com/LukeChannings/deno-arm64). \ No newline at end of file +[^1]: Downloads can be found [at the main NASM project website](https://www.nasm.us/) \ No newline at end of file diff --git a/docz/docs/03-demos/23-data/10-sql.md b/docz/docs/03-demos/23-data/10-sql.md index 958d2ff..00de992 100644 --- a/docz/docs/03-demos/23-data/10-sql.md +++ b/docz/docs/03-demos/23-data/10-sql.md @@ -1,6 +1,6 @@ --- title: SQL Connectors -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: sql: true diff --git a/docz/docs/03-demos/23-data/11-sqlite.md b/docz/docs/03-demos/23-data/11-sqlite.md index 2761943..d6d4207 100644 --- a/docz/docs/03-demos/23-data/11-sqlite.md +++ b/docz/docs/03-demos/23-data/11-sqlite.md @@ -1,7 +1,7 @@ --- title: Sheets with SQLite sidebar_label: SQLite -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: sql: true diff --git a/docz/docs/03-demos/23-data/14-knex.md b/docz/docs/03-demos/23-data/14-knex.md index 9c4b9f9..cb11f28 100644 --- a/docz/docs/03-demos/23-data/14-knex.md +++ b/docz/docs/03-demos/23-data/14-knex.md @@ -1,6 +1,6 @@ --- title: Knex SQL Builder -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: sql: true diff --git a/docz/docs/03-demos/23-data/16-postgresql.md b/docz/docs/03-demos/23-data/16-postgresql.md index fbae1a6..d15a6e4 100644 --- a/docz/docs/03-demos/23-data/16-postgresql.md +++ b/docz/docs/03-demos/23-data/16-postgresql.md @@ -1,7 +1,7 @@ --- title: Sheets with PostgreSQL sidebar_label: PostgreSQL -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: sql: true diff --git a/docz/docs/03-demos/23-data/17-mariadb.md b/docz/docs/03-demos/23-data/17-mariadb.md index 6bf631d..a59e60c 100644 --- a/docz/docs/03-demos/23-data/17-mariadb.md +++ b/docz/docs/03-demos/23-data/17-mariadb.md @@ -1,7 +1,7 @@ --- title: Sheets with MariaDB and MySQL sidebar_label: MariaDB / MySQL -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: sql: true diff --git a/docz/docs/03-demos/23-data/19-alasql.md b/docz/docs/03-demos/23-data/19-alasql.md index 56dda08..3d8d66e 100644 --- a/docz/docs/03-demos/23-data/19-alasql.md +++ b/docz/docs/03-demos/23-data/19-alasql.md @@ -1,7 +1,7 @@ --- title: Sheets with AlaSQL sidebar_label: AlaSQL -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: sql: true diff --git a/docz/docs/03-demos/23-data/25-mongodb.md b/docz/docs/03-demos/23-data/25-mongodb.md index 6a62928..b43bc1f 100644 --- a/docz/docs/03-demos/23-data/25-mongodb.md +++ b/docz/docs/03-demos/23-data/25-mongodb.md @@ -1,7 +1,7 @@ --- title: Sheets with MongoDB sidebar_label: MongoDB -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: type: document diff --git a/docz/docs/03-demos/23-data/26-redis.md b/docz/docs/03-demos/23-data/26-redis.md index 5ba4edb..bf71c57 100644 --- a/docz/docs/03-demos/23-data/26-redis.md +++ b/docz/docs/03-demos/23-data/26-redis.md @@ -2,7 +2,7 @@ title: Redis Databases Wrapped in Sheets sidebar_label: Redis description: Store complex datasets in Redis. Seamlessly save data to spreadsheets and read data from sheets using SheetJS. Enable Excel spreadsheet experts to update content. -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: type: nosql diff --git a/docz/docs/03-demos/23-data/29-pouchdb.md b/docz/docs/03-demos/23-data/29-pouchdb.md index 472906f..7884c46 100644 --- a/docz/docs/03-demos/23-data/29-pouchdb.md +++ b/docz/docs/03-demos/23-data/29-pouchdb.md @@ -1,7 +1,7 @@ --- title: Sheets in PouchDB sidebar_label: PouchDB -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: type: nosql diff --git a/docz/docs/03-demos/23-data/index.md b/docz/docs/03-demos/23-data/index.md index d55842f..011f0de 100644 --- a/docz/docs/03-demos/23-data/index.md +++ b/docz/docs/03-demos/23-data/index.md @@ -1,6 +1,6 @@ --- title: Databases and Stores -pagination_prev: demos/desktop/index +pagination_prev: demos/cli/index pagination_next: demos/local/index --- diff --git a/docz/docs/03-demos/27-local/01-file.md b/docz/docs/03-demos/27-local/01-file.md index 6d04a9f..1e090e6 100644 --- a/docz/docs/03-demos/27-local/01-file.md +++ b/docz/docs/03-demos/27-local/01-file.md @@ -28,7 +28,8 @@ Some snippets are also available in the "Common Use Cases" section: Other demos cover APIs for local file access on special platforms: - ["iOS and Android Apps"](/docs/demos/mobile/) covers mobile app frameworks -- ["Desktop and CLI Tools"](/docs/demos/desktop/) covers desktop apps and CLIs +- ["Desktop Apps"](/docs/demos/desktop/) covers desktop apps +- ["Command-Line Tools"](/docs/demos/cli) covers standalone command-line tools ::: diff --git a/docz/docs/03-demos/30-cloud/19-deno.md b/docz/docs/03-demos/30-cloud/19-deno.md index cab3826..3984d65 100644 --- a/docz/docs/03-demos/30-cloud/19-deno.md +++ b/docz/docs/03-demos/30-cloud/19-deno.md @@ -33,7 +33,7 @@ This demo was last tested by SheetJS users on 2023 October 18. ## Integration Details -The [SheetJS Deno module](/docs/getting-started/installation/nodejs) can be +The [SheetJS Deno module](/docs/getting-started/installation/deno) can be imported from Deno Deploy server scripts. ### Supported Frameworks diff --git a/docz/docs/03-demos/32-extensions/09-mathematica.md b/docz/docs/03-demos/32-extensions/09-mathematica.md index 8043d16..7e517b7 100644 --- a/docz/docs/03-demos/32-extensions/09-mathematica.md +++ b/docz/docs/03-demos/32-extensions/09-mathematica.md @@ -197,7 +197,7 @@ SheetJSImportFileEE["pres.numbers"] ### Command-Line Tools -The ["Command-Line Tools" demo](/docs/demos/desktop/cli) creates `xlsx-cli`, a +The ["Command-Line Tools" demo](/docs/demos/cli) creates `xlsx-cli`, a command-line tool that reads a spreadsheet file and generates CSV rows from the first worksheet. @@ -354,5 +354,5 @@ data = SheetJSImportURL["https://sheetjs.com/pres.numbers"] [^11]: See [`ImportString`](https://reference.wolfram.com/language/ref/ImportString.html) in the Mathematica documentation. [^12]: A [`Dataset`](https://reference.wolfram.com/language/ref/Dataset.html) will be created when using the [`"Dataset"` element in `ImportString`](https://reference.wolfram.com/language/ref/format/CSV.html) [^13]: See [`HeaderLines`](https://reference.wolfram.com/language/ref/HeaderLines.html) in the Mathematica documentation. -[^14]: See ["Command-line Tools"](/docs/demos/desktop/cli) for more details. +[^14]: See ["Command-line Tools"](/docs/demos/cli) for more details. [^15]: Mathematica 11 introduced new methods including [`URLRead`](https://reference.wolfram.com/language/ref/URLRead.html). \ No newline at end of file diff --git a/docz/docs/03-demos/32-extensions/11-matlab.md b/docz/docs/03-demos/32-extensions/11-matlab.md index f036331..6b1d951 100644 --- a/docz/docs/03-demos/32-extensions/11-matlab.md +++ b/docz/docs/03-demos/32-extensions/11-matlab.md @@ -55,7 +55,7 @@ loaded in NodeJS scripts and bundled in standalone command-line tools. ### Command-Line Tools -The ["Command-Line Tools" demo](/docs/demos/desktop/cli) creates `xlsx-cli`, a +The ["Command-Line Tools" demo](/docs/demos/cli) creates `xlsx-cli`, a command-line tool that reads a spreadsheet file and generates output. The examples in the "NodeJS" section are able to generate XLSX spreadsheets using the `--xlsx` command line flag: @@ -265,5 +265,5 @@ matlab -batch SheetJSMATLAB [^4]: See [`writeFile` in "Writing Files"](/docs/api/write-options) [^5]: See [`system`](https://www.mathworks.com/help/matlab/ref/system.html) in the MATLAB documentation. [^6]: See ["MATLAB Operators and Special Characters](https://www.mathworks.com/help/matlab/matlab_prog/matlab-operators-and-special-characters.html) in the MATLAB documentation. -[^7]: See ["Command-line Tools"](/docs/demos/desktop/cli) for more details. +[^7]: See ["Command-line Tools"](/docs/demos/cli) for more details. diff --git a/docz/docs/03-demos/index.md b/docz/docs/03-demos/index.md index 52ad9df..d795b10 100644 --- a/docz/docs/03-demos/index.md +++ b/docz/docs/03-demos/index.md @@ -106,7 +106,7 @@ in the [issue tracker](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues) ### Platforms and Integrations -- [`Command-Line Tools`](/docs/demos/desktop/cli) +- [`Command-Line Tools`](/docs/demos/cli) - [`NodeJS Server-Side Processing`](/docs/demos/net/server#nodejs) - [`Deno Server-Side Processing`](/docs/demos/net/server#deno) - [`Headless Automation`](/docs/demos/net/headless) diff --git a/docz/docs/07-csf/07-features/01-dates.md b/docz/docs/07-csf/07-features/01-dates.md index 72bc2eb..760419c 100644 --- a/docz/docs/07-csf/07-features/01-dates.md +++ b/docz/docs/07-csf/07-features/01-dates.md @@ -1,8 +1,10 @@ --- +title: Dates and Times sidebar_position: 1 --- -# Dates and Times +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem';
File Format Support (click to show) @@ -70,7 +72,10 @@ recommended to [upgrade](/docs/getting-started/installation/). ::: The following example exports the current time to XLSX spreadsheet. The time -shown on this page will be the time displayed in Excel +shown on this page will be the time displayed in Excel. + + + ```jsx live function SheetJSNow() { @@ -87,8 +92,7 @@ function SheetJSNow() { ws["!cols"] = [{wch: 20}]; /* generate workbook and export */ - const wb = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); + const wb = XLSX.utils.book_new(ws, "Sheet1"); XLSX.writeFile(wb, "SheetJSNow.xlsx"); }, []); return ( <> @@ -97,10 +101,71 @@ function SheetJSNow() {

- ) + ); } ``` +
+ + +:::note pass + +1) Create a new Date object and set milliseconds to 0 (to avoid date rounding): + +```js +/* starting date */ +const date = new Date(); +/* to avoid confusion, set milliseconds to 0 */ +date.setMilliseconds(0); +``` + +2) Construct an array of arrays to store the date. It will be placed in cell A1: + +```js +/* generate array of arrays */ +const aoa = [[date]]; +``` + +3) [Create a worksheet](/docs/api/utilities/array#array-of-arrays-input): + +```js +/* generate workbook */ +const ws = XLSX.utils.aoa_to_sheet(aoa, {dense: true}); +``` + +4) Adjust the date format using a [custom number format](/docs/csf/features/nf): + +```js +/* set cell A1 number format */ +ws["!data"][0][0].z = "yyyy-mm-dd hh:mm:ss" +``` + +5) Adjust the [column width](/docs/csf/features/colprops) + +```js +/* adjust column width */ +ws["!cols"] = [{wch: 20}]; +``` + +6) [Create a workbook](/docs/api/utilities/wb): + +```js +/* create workbook object */ +const wb = XLSX.utils.book_new(ws, "Sheet1"); +``` + +7) [Write XLSX file](/docs/api/write-options): + +```js +/* generate XLSX workbook and attempt to download */ +XLSX.writeFile(wb, "SheetJSNow.xlsx"); +``` + +::: + + +
+ ## How Spreadsheets Understand Time Excel stores dates as numbers. When displaying dates, the format code should @@ -500,3 +565,71 @@ function SSFIsDate() { ```
+ +## How JSON and APIs Understand Time + +JSON does not have a native representation for JavaScript Date objects. + +Starting from a Date object, the `JSON.stringify` method will encode the object +as a ISO 8601 date string. Applying `JSON.parse` to the result will return the +string rather than a proper Date object. + +```mermaid +flowchart LR + ws(("new Date#40;#41;"\nObject)) + jstr[["'#quot;2001-01-01T00:00:00.000Z#quot;'"\nEncoded String]] + js[["#quot;2001-01-01T00:00:00.000Z#quot;"\nJavaScript String]] + ws --> |JSON\nstringify| jstr + jstr --> |JSON.parse\n\n| js + js --> |\nJSON.stringify| jstr +``` + +SheetJS utility functions will not try to interpret those strings as dates. +Instead, the strings will be translated to text. + +In the following example, the "ISO Text" data will be converted to a string cell +while the "Date Obj" data will be converted to a spreadsheet date. + +```jsx live +function SheetJSONDates() { return ( ); } +``` + +:::caution pass + +Many API wrapper libraries return dates as strings instead of Date objects. + +If the SheetJS operations generate string cells, review the documentation for +the wrapper library to ensure the other library is properly handling dates. + +::: + +### Fixing Arrays of Objects + +Many APIs will return data as JSON objects. When particular fields are known to +contain date strings, they can be manually fixed. + +For example, the [Export Tutorial](/docs/getting-started/examples/export) makes +a final array of objects with birthdays stored as strings: + +```js +const rows = [ + { name: "George Washington", birthday: "1732-02-22" }, + { name: "John Adams", birthday: "1735-10-19" }, + // ... one row per President +]; +``` + +If this dataset is exported, the `birthday` column will contain raw text values. +A single `Array#map` operation can create a fixed dataset: + +```js +const new_rows = rows.map(({birthday, ...rest}) => ({birthday: new Date(birthday), ...rest})) +``` \ No newline at end of file diff --git a/docz/docusaurus.config.js b/docz/docusaurus.config.js index bb2596a..1e56632 100644 --- a/docz/docusaurus.config.js +++ b/docz/docusaurus.config.js @@ -269,9 +269,10 @@ const config = { { from: '/docs/demos/data/storageapi', to: '/docs/demos/local/storageapi/' }, { from: '/docs/demos/data/websql', to: '/docs/demos/local/websql/' }, /* desktop */ - { from: '/docs/demos/cli', to: '/docs/demos/desktop/cli/' }, - { from: '/docs/getting-started/demos/cli', to: '/docs/demos/desktop/cli/' }, { from: '/docs/getting-started/demos/desktop', to: '/docs/demos/desktop/' }, + /* cli */ + { from: '/docs/getting-started/demos/cli', to: '/docs/demos/cli/' }, + { from: '/docs/demos/desktop/cli', to: '/docs/demos/cli/' }, /* bigdata */ { from: '/docs/demos/worker', to: '/docs/demos/bigdata/worker/' }, { from: '/docs/demos/stream', to: '/docs/demos/bigdata/stream/' },