diff --git a/.spelling b/.spelling
index 3d415ba..14d7ffe 100644
--- a/.spelling
+++ b/.spelling
@@ -185,6 +185,7 @@ Nashorn
NativeScript
NestJS
NetSuite
+NeutralinoJS
NextJS
NoSQL
NodeJS
diff --git a/docz/docs/03-demos/03-desktop.md b/docz/docs/03-demos/03-desktop.md
index 32519ea..551813b 100644
--- a/docz/docs/03-demos/03-desktop.md
+++ b/docz/docs/03-demos/03-desktop.md
@@ -534,7 +534,7 @@ const filters = [
// ... other desired formats ...
];
-async function saveFile() {
+async function saveFile(wb) {
/* show save file dialog */
const selected = await save({
title: "Save to Spreadsheet",
@@ -761,3 +761,239 @@ async function exportFile(wb) {
// The demo shows a success message at this point
}
```
+
+## NeutralinoJS
+
+The [Standalone build](../getting-started/installation/standalone) can be added
+to the entry `index.html`
+
+This demo was tested against "binaries" `4.7.0` and "client" `3.6.0`
+
+:::note
+
+NeutralinoJS currently does not provide the equivalent of NodeJS `fs` module.
+The raw `Neutralino.filesystem` and `Neutralino.os` methods are used.
+
+:::
+
+The `os` and `filesystem` modules must be enabled in `neutralino.conf.json`.
+The starter already enables `os` so typically one line must be added:
+
+```json title="neutralino.config.json"
+ "nativeAllowList": [
+ "app.*",
+ "os.*",
+// highlight-next-line
+ "filesystem.*",
+ "debug.log"
+ ],
+```
+
+The "Complete Example" creates an app that looks like the screenshot:
+
+![SheetJS NeutralinoJS MacOS screenshot](pathname:///neu/macos.png)
+
+:::caution
+
+At the time of writing, `filters` did not work as expected on MacOS. They have
+been omitted in the example and commented in the code snippets
+
+:::
+
+Complete Example (click to show)
+
+The app core state will be the HTML table. Reading files will add the table to
+the window. Writing files will parse the table into a spreadsheet.
+
+1) Create a new NeutralinoJS app:
+
+```bash
+npx @neutralinojs/neu create sheetjs-neu
+cd sheetjs-neu
+```
+
+2) Download the standalone script and place in `resources/js/main.js`:
+
+```bash
+curl -L -o resources/js/xlsx.full.min.js https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
+```
+
+3) Add the highlighted lines to `neutralino.conf.json` in `nativeAllowList`:
+
+```json title="neutralino.config.json"
+ "nativeAllowList": [
+ "app.*",
+// highlight-start
+ "os.*",
+ "filesystem.*",
+// highlight-end
+ "debug.log"
+ ],
+```
+
+4) Set up skeleton app and print version info:
+
+- Edit `resources/index.html` and replace the `` with the code below:
+
+```html title="resources/index.html"
+
+
+
SheetJS × NeutralinoJS
+
+
+
+
+
+
+
+
+
+```
+
+- Append the following code to `resources/styles.css` to center the table:
+
+```css title="resources/styles.css"
+#info {
+ width:100%;
+ text-align: unset;
+}
+table {
+ margin: 0 auto;
+}
+```
+
+- Print the version number in the `showInfo` method of `resources/js/main.js`:
+
+```js title="resources/js/main.js"
+ ${NL_APPID} is running on port ${NL_PORT} inside ${NL_OS}
+
+ SheetJS version ${XLSX.version}
+// highlight-end
+ `;
+```
+
+5) Run the app:
+
+```bash
+npx @neutralinojs/neu run
+```
+
+You should see `SheetJS Version ` followed by the library version number.
+
+6) Add the following code to the bottom of `resources/js/main.js`:
+
+```js
+(async() => {
+ const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer();
+ const wb = XLSX.read(ab);
+ const ws = wb.Sheets[wb.SheetNames[0]];
+ document.getElementById('info').innerHTML = XLSX.utils.sheet_to_html(ws);
+})();
+```
+
+Save the source file, close the app and re-run the command from step 5.
+
+When the app loads, a table should show in the main screen.
+
+7) Add `importFile` and `exportFile` to the bottom of `resources/js/main.js`:
+
+```js
+async function importData() {
+ /* show open dialog */
+ const [filename] = await Neutralino.os.showOpenDialog('Open a spreadsheet');
+
+ /* read data */
+ const ab = await Neutralino.filesystem.readBinaryFile(filename);
+ const wb = XLSX.read(ab);
+
+ /* make table */
+ const ws = wb.Sheets[wb.SheetNames[0]];
+ document.getElementById('info').innerHTML = XLSX.utils.sheet_to_html(ws);
+}
+
+async function exportData() {
+ /* show save dialog */
+ const filename = await Neutralino.os.showSaveDialog('Save to file');
+
+ /* make workbook */
+ const tbl = document.getElementById('info').querySelector("table");
+ const wb = XLSX.utils.table_to_book(tbl);
+
+ /* make file */
+ const bookType = filename.slice(filename.lastIndexOf(".") + 1);
+ const data = XLSX.write(wb, { bookType, type: "buffer" });
+ await Neutralino.filesystem.writeBinaryFile(filename, data);
+}
+```
+
+Save the source file, close the app and re-run the command from step 5.
+
+When the app loads, click the "Import File" button and select a spreadsheet to
+see the contents. Click "Export File" and enter `SheetJSNeu.xlsx` to write.
+
+8) Build production apps:
+
+```bash
+npx @neutralinojs/neu run
+```
+
+Platform-specific programs will be created in the `dist` folder.
+
+
+
+### Reading Files
+
+There are two steps to reading files: obtaining a path and reading binary data:
+
+```js
+const filters = [
+ {name: "Excel Binary Workbook", extensions: ["xlsb"]},
+ {name: "Excel Workbook", extensions: ["xlsx"]},
+]
+
+async function openFile() {
+ /* show open file dialog */
+ const [filename] = await Neutralino.os.showOpenDialog(
+ 'Open a spreadsheet',
+ { /* filters, */ multiSelections: false }
+ );
+
+ /* read data into an ArrayBuffer */
+ const ab = await Neutralino.filesystem.readBinaryFile(filename);
+
+ /* parse with SheetJS */
+ const wb = XLSX.read(ab);
+ return wb;
+}
+```
+
+This method can be called from a button click or other event.
+
+### Writing Files
+
+There are two steps to writing files: obtaining a path and writing binary data:
+
+```js
+const filters = [
+ {name: "Excel Binary Workbook", extensions: ["xlsb"]},
+ {name: "Excel Workbook", extensions: ["xlsx"]},
+]
+
+async function saveFile(wb) {
+ /* show save file dialog */
+ const filename = await Neutralino.os.showSaveDialog(
+ 'Save to file',
+ { /* filters */ }
+ );
+
+ /* Generate workbook */
+ const bookType = filename.slice(filename.lastIndexOf(".") + 1);
+ const data = XLSX.write(wb, { bookType, type: "buffer" });
+
+ /* save data to file */
+ await Neutralino.filesystem.writeBinaryFile(filename, data);
+}
+```
diff --git a/docz/docs/03-demos/33-localfile.md b/docz/docs/03-demos/33-localfile.md
index f6cc3a1..93cfd4a 100644
--- a/docz/docs/03-demos/33-localfile.md
+++ b/docz/docs/03-demos/33-localfile.md
@@ -339,6 +339,14 @@ const wb = XLSX.readFile("sheetjs.numbers");
XLSX.writeFile(wb, "sheetjs.xlsx");
```
+:::note
+
+Any script using `XLSX.readFile` requires the `--allow-read` permission.
+
+Any script using `XLSX.writeFile` requires the `--allow-write` permission.
+
+:::
+
### Bun
Bun requires the `fs` module:
diff --git a/docz/docs/03-demos/45-git.md b/docz/docs/03-demos/45-git.md
index 77a4922..39ed00c 100644
--- a/docz/docs/03-demos/45-git.md
+++ b/docz/docs/03-demos/45-git.md
@@ -162,7 +162,7 @@ the source data or artifacts from the `postprocess` script changed.
### Post-Processing Data
-:::caution
+:::warning
The `flat-postprocessing` library includes a number of utilities for different
data formats. The `readXLSX` helper uses SheetJS under the hood.
@@ -175,17 +175,17 @@ releases, the examples import from the SheetJS CDN:
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
```
+The official registry endpoint is out of date.
+[This is a known registry bug](https://github.com/denoland/dotland/issues/2072)
+
:::
#### Post-Process Script
The first argument to the post-processing script is the filename. The file can
-be read with `XLSX.readFile` directly. On the export side, `writeCSV` from the
-`flat` library can write data generated from `XLSX.utils.sheet_to_csv`:
+be read with `XLSX.readFile` directly. `XLSX.utils.sheet_to_csv` generates CSV:
```ts title="postprocess.ts"
-import { writeCSV } from "https://deno.land/x/flat/mod.ts";
-// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs';
/* load the codepage support library for extended support with older formats */
import * as cptable from 'https://cdn.sheetjs.com/xlsx-latest/package/dist/cpexcel.full.mjs';
@@ -206,7 +206,7 @@ const csv = XLSX.utils.sheet_to_csv(first_sheet);
/* write CSV */
// highlight-next-line
-await writeCSV(out_file, csv);
+Deno.writeFileSync(out_file, new TextEncoder().encode(csv));
```
diff --git a/docz/static/neu/macos.png b/docz/static/neu/macos.png
new file mode 100644
index 0000000..40252f8
Binary files /dev/null and b/docz/static/neu/macos.png differ