diff --git a/docz/docs/02-getting-started/01-installation/03-nodejs.md b/docz/docs/02-getting-started/01-installation/03-nodejs.md
index 6fd67567..a7a7fec2 100644
--- a/docz/docs/02-getting-started/01-installation/03-nodejs.md
+++ b/docz/docs/02-getting-started/01-installation/03-nodejs.md
@@ -55,19 +55,19 @@ For existing projects, the easiest approach is to uninstall and reinstall:
{`\
npm rm --save xlsx
-npm i --save file:vendor/xlsx-${current}.tgz`}
+npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
diff --git a/docz/docs/03-demos/01-frontend/04-svelte.md b/docz/docs/03-demos/01-frontend/04-svelte.md
index 747294c3..c183871d 100644
--- a/docz/docs/03-demos/01-frontend/04-svelte.md
+++ b/docz/docs/03-demos/01-frontend/04-svelte.md
@@ -114,6 +114,39 @@ function exportFile() {
```
+How to run the example (click to show)
+
+:::note
+
+This demo was last run on 2023 March 08 using `svelte@3.55.1`. When running
+`npm create`, the package `create-vite@4.1.0` was installed.
+
+:::
+
+1) Run `npm create vite@latest sheetjs-svelte -- --template svelte-ts`.
+
+2) Install the SheetJS dependency and start the dev server:
+
+```bash
+cd sheetjs-svelte
+npm install
+npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
+npm run dev
+```
+
+3) Open a web browser and access the displayed URL (`http://localhost:5173`)
+
+4) Replace `src/App.svelte` with the `src/SheetJSSvelteAoO.svelte` example.
+
+The page will refresh and show a table with an Export button. Click the button
+and the page will attempt to download `SheetJSSvelteAoA.xlsx`. There may be a
+delay since Vite will try to optimize the SheetJS library on the fly.
+
+5) Build the site with `npm run build`, then test with `npx http-server dist`.
+Access `http://localhost:8080` with a web browser to test the bundled site.
+
+
+
### HTML
The main disadvantage of the Array of Objects approach is the specific nature
@@ -158,3 +191,36 @@ function exportFile() {
```
+
+How to run the example (click to show)
+
+:::note
+
+This demo was last run on 2023 March 08 using `svelte@3.55.1`. When running
+`npm create`, the package `create-vite@4.1.0` was installed.
+
+:::
+
+1) Run `npm create vite@latest sheetjs-svelte -- --template svelte-ts`.
+
+2) Install the SheetJS dependency and start the dev server:
+
+```bash
+cd sheetjs-svelte
+npm install
+npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
+npm run dev
+```
+
+3) Open a web browser and access the displayed URL (`http://localhost:5173`)
+
+4) Replace `src/App.svelte` with the `src/SheetJSSvelteHTML.svelte` example.
+
+The page will refresh and show a table with an Export button. Click the button
+and the page will attempt to download `SheetJSSvelteHTML.xlsx`. There may be a
+delay since Vite will try to optimize the SheetJS library on the fly.
+
+5) Build the site with `npm run build`, then test with `npx http-server dist`.
+Access `http://localhost:8080` with a web browser to test the bundled site.
+
+
diff --git a/docz/docs/03-demos/02-grid/01-xs.md b/docz/docs/03-demos/02-grid/01-xs.md
index 7faef86b..64e0a31e 100644
--- a/docz/docs/03-demos/02-grid/01-xs.md
+++ b/docz/docs/03-demos/02-grid/01-xs.md
@@ -29,7 +29,7 @@ features like scrolling may not work as expected.
function SheetJSXSpread() {
const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers");
const [done, setDone] = React.useState(false);
- const ref = React.useRef();
+ const ref = React.useRef(); // ref to DIV container
const set_url = React.useCallback((evt) => setUrl(evt.target.value));
return ( <>
@@ -43,7 +43,7 @@ function SheetJSXSpread() {
x_spreadsheet(ref.current).loadData(stox(wb));
setDone(true);
}}>Fetch!
- >)}
+ > )}
> );
}
```
diff --git a/docz/docs/03-demos/02-grid/02-cdg.md b/docz/docs/03-demos/02-grid/02-cdg.md
new file mode 100644
index 00000000..3b56768a
--- /dev/null
+++ b/docz/docs/03-demos/02-grid/02-cdg.md
@@ -0,0 +1,137 @@
+---
+title: Canvas Datagrid
+pagination_prev: demos/frontend/index
+pagination_next: demos/net/index
+---
+
+
+
+
+
+After extensive testing, `canvas-datagrid` stood out as a high-performance grid
+with a straightforward API.
+
+[Click here for a live standalone integration demo.](pathname:///cdg/)
+
+## Live Demo
+
+:::note
+
+Due to CSS conflicts between the data grid and the documentation generator,
+features like scrolling may not work as expected.
+
+[The linked demo uses a simple HTML page.](pathname:///cdg/)
+
+:::
+
+```jsx live
+function SheetJSCDG() {
+ const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers");
+ const [done, setDone] = React.useState(false);
+ const ref = React.useRef(); // ref to DIV container
+ const set_url = React.useCallback((evt) => setUrl(evt.target.value));
+ const [cdg, setCdg] = React.useState(null); // reference to grid object
+
+ return ( <>
+
+ {!done && ( <>
+ URL:
+
+ > )}
+ > );
+}
+```
+
+## Integration Details
+
+#### Obtaining the Library
+
+The `canvas-datagrid` NodeJS packages include a minified script that can be
+directly inserted as a script tag. The unpkg CDN also serves this script:
+
+```html
+
+```
+
+#### Previewing Data
+
+The HTML document needs a container element:
+
+```html
+
+```
+
+Grid initialization is a one-liner:
+
+```js
+var grid = canvasDatagrid({
+ parentNode: document.getElementById('gridctr'),
+ data: []
+});
+```
+
+For large data sets, it's necessary to constrain the size of the grid.
+
+```js
+grid.style.height = '100%';
+grid.style.width = '100%';
+```
+
+Once the workbook is read and the worksheet is selected, assigning the data
+variable automatically updates the view:
+
+```js
+grid.data = XLSX.utils.sheet_to_json(ws, {header:1});
+```
+
+This demo previews the first worksheet.
+
+#### Editing
+
+`canvas-datagrid` handles the entire edit cycle. No intervention is necessary.
+
+#### Saving Data
+
+`grid.data` is immediately readable and can be converted back to a worksheet.
+Some versions return an array-like object without the length, so a little bit of
+preparation may be needed:
+
+```js
+/* converts an array of array-like objects into an array of arrays */
+function prep(arr) {
+ var out = [];
+ for(var i = 0; i < arr.length; ++i) {
+ if(!arr[i]) continue;
+ if(Array.isArray(arr[i])) { out[i] = arr[i]; continue };
+ var o = new Array();
+ Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] });
+ out[i] = o;
+ }
+ return out;
+}
+
+/* build worksheet from the grid data */
+var ws = XLSX.utils.aoa_to_sheet(prep(grid.data));
+
+/* build up workbook */
+var wb = XLSX.utils.book_new();
+XLSX.utils.book_append_sheet(wb, ws, 'SheetJS');
+
+/* generate download */
+XLSX.writeFile(wb, "SheetJS.xlsx");
+```
+
+#### Additional Features
+
+This demo barely scratches the surface. The underlying grid component includes
+many additional features that work with [SheetJS Pro](https://sheetjs.com/pro).
diff --git a/docz/docs/03-demos/02-grid/index.md b/docz/docs/03-demos/02-grid/index.md
index 6e2d6c3c..80e9d65c 100644
--- a/docz/docs/03-demos/02-grid/index.md
+++ b/docz/docs/03-demos/02-grid/index.md
@@ -34,101 +34,16 @@ With a familiar UI, `x-spreadsheet` is an excellent choice for a modern editor.
[Click here for a live integration demo.](pathname:///xspreadsheet/)
-[The exposition has been moved to a separate page.](/docs/demos/grid/xs)
+**[The exposition has been moved to a separate page.](/docs/demos/grid/xs)**
-### Canvas DataGrid
+### Canvas Datagrid
-After extensive testing, [`canvas-datagrid`](https://canvas-datagrid.js.org/demo.html)
-stood out as a very high-performance grid with an incredibly simple API.
+After extensive testing, `canvas-datagrid` stood out as a high-performance grid
+with a straightforward API.
[Click here for a live integration demo.](pathname:///cdg/index.html)
-Full Exposition (click to show)
-
-**Obtaining the Library**
-
-The `canvas-datagrid` NodeJS packages include a minified script that can be
-directly inserted as a script tag. The unpkg CDN also serves this script:
-
-```html
-
-```
-
-**Previewing Data**
-
-The HTML document needs a container element:
-
-```html
-
-```
-
-Grid initialization is a one-liner:
-
-```js
-var grid = canvasDatagrid({
- parentNode: document.getElementById('gridctr'),
- data: []
-});
-```
-
-For large data sets, it's necessary to constrain the size of the grid.
-
-```js
-grid.style.height = '100%';
-grid.style.width = '100%';
-```
-
-Once the workbook is read and the worksheet is selected, assigning the data
-variable automatically updates the view:
-
-```js
-grid.data = XLSX.utils.sheet_to_json(ws, {header:1});
-```
-
-This demo previews the first worksheet.
-
-**Editing**
-
-`canvas-datagrid` handles the entire edit cycle. No intervention is necessary.
-
-**Saving Data**
-
-`grid.data` is immediately readable and can be converted back to a worksheet.
-Some versions return an array-like object without the length, so a little bit of
-preparation may be needed:
-
-```js
-/* converts an array of array-like objects into an array of arrays */
-function prep(arr) {
- var out = [];
- for(var i = 0; i < arr.length; ++i) {
- if(!arr[i]) continue;
- if(Array.isArray(arr[i])) { out[i] = arr[i]; continue };
- var o = new Array();
- Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] });
- out[i] = o;
- }
- return out;
-}
-
-/* build worksheet from the grid data */
-var ws = XLSX.utils.aoa_to_sheet(prep(grid.data));
-
-/* build up workbook */
-var wb = XLSX.utils.book_new();
-XLSX.utils.book_append_sheet(wb, ws, 'SheetJS');
-
-/* generate download */
-XLSX.writeFile(wb, "SheetJS.xlsx");
-```
-
-**Additional Features**
-
-This demo barely scratches the surface. The underlying grid component includes
-many additional features including massive data streaming, sorting and styling.
-
-
-
+**[The exposition has been moved to a separate page.](/docs/demos/grid/cdg)**
### Tabulator
diff --git a/docz/docs/03-demos/07-data/01-websql.md b/docz/docs/03-demos/07-data/01-websql.md
index 9ef9ce55..a616b8d1 100644
--- a/docz/docs/03-demos/07-data/01-websql.md
+++ b/docz/docs/03-demos/07-data/01-websql.md
@@ -13,6 +13,15 @@ work as-is in WebSQL.
The public demo generates a database from workbook.
+:::caution
+
+WebSQL is only supported in Chromium-based browsers including Chrome.
+
+Safari historically supported WebSQL but Safari 13 dropped support. Legacy
+browsers including Internet Explorer and Firefox never added support.
+
+:::
+
## WebSQL Details
Importing data from spreadsheets is straightforward using the `generate_sql`
diff --git a/docz/docs/03-demos/12-engines/08_quickjs.md b/docz/docs/03-demos/12-engines/08_quickjs.md
new file mode 100644
index 00000000..327236d8
--- /dev/null
+++ b/docz/docs/03-demos/12-engines/08_quickjs.md
@@ -0,0 +1,211 @@
+---
+title: C + QuickJS
+pagination_prev: demos/bigdata/index
+pagination_next: solutions/input
+---
+
+QuickJS is an embeddable JS engine written in C. It provides a separate set of
+functions for interacting with the filesystem and the global object. It can run
+the standalone browser scripts.
+
+## Integration Details
+
+_Initialize QuickJS_
+
+QuickJS provides a `global` object through `JS_GetGlobalObject`:
+
+```c
+/* initialize */
+JSRuntime *rt = JS_NewRuntime();
+JSContext *ctx = JS_NewContext(rt);
+
+/* obtain reference to global object */
+JSValue global = JS_GetGlobalObject(ctx);
+
+/* DO WORK HERE */
+
+/* free after use */
+JS_FreeValue(ctx, global);
+
+/* cleanup */
+JS_FreeContext(ctx);
+JS_FreeRuntime(rt);
+```
+
+:::warning
+
+All values must be freed with `JS_FreeValue` before calling `JS_FreeContext`!
+
+`JS_IsException` should be used for validation.
+
+Cleanup and validation code is omitted from the discussion. The integration
+example shows structured validation and controlled memory usage.
+
+:::
+
+_Load SheetJS Scripts_
+
+The main library can be loaded by reading the script from the file system and
+evaluating in the QuickJS context:
+
+```c
+static char *read_file(const char *filename, size_t *sz) {
+ FILE *f = fopen(filename, "rb");
+ if(!f) return NULL;
+ long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fsee (f, 0, SEEK_SET); }
+ char *buf = (char *)malloc(fsize * sizeof(char));
+ *sz = fread((void *) buf, 1, fsize, f);
+ fclose(f);
+ return buf;
+}
+
+// ...
+ /* load library */
+ {
+ size_t len; char *buf = read_file("xlsx.full.min.js", &len);
+ JS_Eval(ctx, buf, len, "", 0);
+ free(buf);
+ }
+```
+
+To confirm the library is loaded, `XLSX.version` can be inspected:
+
+```c
+/* obtain reference to the XLSX object */
+JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX");
+
+/* print version */
+JSValue version = JS_GetPropertyStr(ctx, XLSX, "version");
+size_t vlen; const char *vers = JS_ToCStringLen(ctx, &vlen, version);
+printf("Version: %s\n", vers);
+```
+
+### Reading Files
+
+`JS_NewArrayBuffer` can generate an `ArrayBuffer` from a C byte array. The
+function signature expects `uint8_t *` instead of `char *`:
+
+```c
+/* read file */
+size_t dlen; uint8_t * dbuf = (uint8_t *)read_file("pres.numbers", &dlen);
+
+/* load data into array buffer */
+JSValue ab = JS_NewArrayBuffer(ctx, dbuf, dlen, NULL, NULL, 0);
+
+/* obtain reference to the XLSX object */
+JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX");
+
+/* call XLSX.read(ab) */
+JSValue XLSX_read = JS_GetPropertyStr(ctx, XLSX, "read");
+JSValue args[] = { ab };
+JSValue wb = JS_Call(ctx, XLSX_read, XLSX, 1, args);
+```
+
+## Complete Example
+
+The "Integration Example" covers a traditional integration in a C application,
+while the "CLI Test" demonstrates other concepts using the `quickjs` CLI tool.
+
+### Integration Example
+
+:::note
+
+This demo was last tested on 2023 March 11 against QuickJS commit `2788d71` on
+a Intel Mac. `gcc -v` printed:
+
+```
+Apple clang version 14.0.0 (clang-1400.0.29.202)
+Target: x86_64-apple-darwin21.6.0
+```
+
+:::
+
+0) Build `libquickjs.a`:
+
+```bash
+git clone --depth=1 https://github.com/bellard/quickjs
+cd quickjs
+git checkout 2788d71
+make
+cd ..
+```
+
+1) Copy `libquickjs.a` and `quickjs.h` into the working directory:
+
+```bash
+cp quickjs/libquickjs.a .
+cp quickjs/quickjs.h .
+```
+
+2) Download [`sheetjs.quick.c`](pathname:///quickjs/sheetjs.quick.c):
+
+```bash
+curl -LO https://docs.sheetjs.com/quickjs/sheetjs.quick.c
+```
+
+3) Build the sample application:
+
+```bash
+gcc -o sheetjs.quick -Wall -lm libquickjs.a sheetjs.quick.c
+```
+
+This program tries to parse the file specified by the first argument
+
+4) Download the standalone script and test file:
+
+
+
+```bash
+curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
+curl -LO https://sheetjs.com/pres.numbers
+```
+
+5) Run the test program:
+
+```
+./sheetjs.quick pres.numbers
+```
+
+If successful, the program will print the library version number, file size,
+first worksheet name, and the contents of the first sheet as CSV rows.
+
+
+### CLI Test
+
+:::note
+
+This demo was last tested on 2023 March 11 against QuickJS `2021-03-27`.
+
+:::
+
+0) Ensure `quickjs` command line utility is installed
+
+1) Download the standalone script and the test file:
+
+
+
+```bash
+curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
+curl -LO https://sheetjs.com/pres.numbers
+```
+
+2) Download [`SheetJSQuick.js`](pathname:///quickjs/SheetJSQuick.js)
+
+```bash
+curl -LO https://docs.sheetjs.com/quickjs/SheetJSQuick.js
+```
+
+3) Test the program:
+
+```bash
+quickjs SheetJSQuick.js
+```
+
+If successful, the script will generate `SheetJSQuick.xlsx`.
+
diff --git a/docz/docs/03-demos/12-engines/index.md b/docz/docs/03-demos/12-engines/index.md
index 034ae002..cc57493b 100644
--- a/docz/docs/03-demos/12-engines/index.md
+++ b/docz/docs/03-demos/12-engines/index.md
@@ -246,57 +246,7 @@ QuickJS is an embeddable JS engine written in C. It provides a separate set of
functions for interacting with the filesystem and the global object. It can run
the standalone browser scripts.
-Complete Example (click to show)
-
-0) Ensure `quickjs` command line utility is installed
-
-1) Download the standalone script, the shim and the test file:
-
-