diff --git a/docz/data/cli.xls b/docz/data/cli.xls
index 9081dcd..99fc077 100644
--- a/docz/data/cli.xls
+++ b/docz/data/cli.xls
@@ -88,18 +88,18 @@
✔ |
✔ |
✔ |
- |
+ ✱ |
+ ✔ |
✔ |
- |
BunJS SEA |
✔ |
✔ |
- |
- |
✔ |
|
+ ✔ |
+ ✔ |
Deno SEA |
diff --git a/docz/docs/03-demos/20-cli/11-nodesea.md b/docz/docs/03-demos/20-cli/11-nodesea.md
index cc8dfef..a012e67 100644
--- a/docz/docs/03-demos/20-cli/11-nodesea.md
+++ b/docz/docs/03-demos/20-cli/11-nodesea.md
@@ -162,7 +162,16 @@ This demo was tested in the following deployments:
| `darwin-arm` | `22.2.0` | 2024-05-29 |
| `win10-x64` | `20.12.0` | 2024-03-26 |
| `win11-x64` | `20.13.1` | 2024-05-22 |
+| `win11-arm` | `20.14.0` | 2024-06-11 |
| `linux-x64` | `20.11.1` | 2024-03-18 |
+| `linux-arm` | `20.14.0` | 2024-06-10 |
+
+:::
+
+:::caution pass
+
+NodeJS on Windows on ARM uses the X64 compatibility layer. It does not generate
+a native ARM64 binary!
:::
diff --git a/docz/docs/03-demos/20-cli/12-bunsea.md b/docz/docs/03-demos/20-cli/12-bunsea.md
index 85f6fa9..7bb0d5e 100644
--- a/docz/docs/03-demos/20-cli/12-bunsea.md
+++ b/docz/docs/03-demos/20-cli/12-bunsea.md
@@ -81,7 +81,9 @@ This demo was last tested in the following deployments:
|:-------------|:---------|:-----------|
| `darwin-x64` | `1.1.10` | 2024-05-28 |
| `darwin-arm` | `1.1.10` | 2024-05-29 |
+| `win10-x64` | `1.1.12` | 2024-06-10 |
| `linux-x64` | `1.1.12` | 2024-06-09 |
+| `linux-arm` | `1.1.12` | 2024-06-10 |
:::
@@ -102,6 +104,24 @@ to `sheet2csv.ts` in the project folder.
bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+:::caution pass
+
+On Windows, the command failed with a `ENOTEMPTY` error:
+
+```
+error: InstallFailed extracting tarball for https://cdn.sheetjs.com/xlsx-0.20.1/xlsx-0.20.1.tgz
+error: moving "https://cdn.sheetjs.com/xlsx-0.20.1/xlsx-0.20.1.tgz" to cache dir failed
+ENOTEMPTY: Directory not empty (NtSetInformationFile())
+```
+
+The workaround is to prepend `xlsx@` to the URL:
+
+{`\
+bun install xlsx@https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+
+
+:::
+
4) Test the script with `bun run`:
```bash
diff --git a/docz/docs/03-demos/30-cloud/12-azure.md b/docz/docs/03-demos/30-cloud/12-azure.md
index 9e053e2..66a7869 100644
--- a/docz/docs/03-demos/30-cloud/12-azure.md
+++ b/docz/docs/03-demos/30-cloud/12-azure.md
@@ -495,7 +495,7 @@ requests and 2000 write requests per month.
:::
-0) If you do not have an account, create a new Azure free tier account[^8].
+0) If you do not have an account, create a new Azure free tier account[^15].
#### Storage Account Setup
@@ -646,3 +646,4 @@ is valid, open the file in Excel or another spreadsheet editor.
[^12]: See [`write` in "Writing Files"](/docs/api/write-options)
[^13]: See [`aoa_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-arrays-input)
[^14]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
+[^15]: Registering for a free account [on the Azure Free Tier](https://azure.microsoft.com/en-us/free) requires a valid phone number and a valid credit card.
diff --git a/docz/docs/03-demos/30-cloud/21-gsheet.md b/docz/docs/03-demos/30-cloud/21-gsheet.md
index 08c16e3..2810b8a 100644
--- a/docz/docs/03-demos/30-cloud/21-gsheet.md
+++ b/docz/docs/03-demos/30-cloud/21-gsheet.md
@@ -394,8 +394,20 @@ const file = await drive.files.export({
});
```
+:::note pass
+
+The `mimeType` property is expected to be one of the supported formats[^8]. When
+the demo was last tested, the following workbook conversions were supported:
+
+| Format | MIME Type |
+|:-------|:--------------------------------------------------------------------|
+| XLSX | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |
+| ODS | `application/x-vnd.oasis.opendocument.spreadsheet` |
+
+:::
+
The response object has a `data` field whose value will be a `Blob` object. Data
-can be pulled into an `ArrayBuffer` and passed to the SheetJS `read`[^8] method:
+can be pulled into an `ArrayBuffer` and passed to the SheetJS `read`[^9] method:
```js
/* Obtain ArrayBuffer */
@@ -405,7 +417,78 @@ const ab = await file.data.arrayBuffer();
const wb = XLSX.read(buf);
```
-At this point `wb` is a SheetJS workbook object[^9].
+:::note pass
+
+The code snippet works for XLSX and ODS. Google Sheets supports other formats
+with different integration logic.
+
+**Plaintext**
+
+The following formats are considered "plaintext":
+
+| Format | MIME Type |
+|:------------------|:----------------------------|
+| CSV (first sheet) | `text/csv` |
+| TSV (first sheet) | `text/tab-separated-values` |
+
+For these formats, `file.data` is a JS string that can be parsed directly:
+
+```js
+/* Request CSV export */
+const file = await drive.files.export({ mimeType: "text/csv", fileId: id });
+
+/* Parse CSV string*/
+const wb = XLSX.read(file.data, {type: "string"});
+```
+
+**HTML**
+
+Google Sheets has one relevant HTML type:
+
+| Format | MIME Type |
+|:------------------|:------------------|
+| HTML (all sheets) | `application/zip` |
+
+The HTML export of a Google Sheets worksheet includes a row for the column
+labels (`A`, `B`, ...) and a column for the row labels (`1`, `2`, ...).
+
+The complete package is a ZIP file that includes a series of `.html` files.
+The files are written in tab order. The name of each file matches the name in
+Google Sheets.
+
+This ZIP can be extracted using the embedded CFB library:
+
+```js
+import { read, utils, CFB } from 'xlsx';
+// -------------------^^^-- `CFB` named import
+
+// ...
+
+/* Parse Google Sheets ZIP file */
+const cfb = CFB.read(new Uint8Array(ab), {type: "array"});
+
+/* Create new SheetJS workbook */
+const wb = utils.book_new();
+
+/* Scan through each entry in the ZIP */
+cfb.FullPaths.forEach((n, i) => {
+ /* only process HTML files */
+ if(n.slice(-5) != ".html") return;
+
+ /* Extract worksheet name */
+ const name = n.slice(n.lastIndexOf("/")+1).slice(0,-5);
+
+ /* parse HTML */
+ const htmlwb = read(cfb.FileIndex[i].content);
+
+ /* add worksheet to workbook */
+ utils.book_append_sheet(wb, htmlwb.Sheets.Sheet1, name);
+});
+```
+
+:::
+
+At this point `wb` is a SheetJS workbook object[^10].
## Complete Example
@@ -840,5 +923,6 @@ Joseph Biden,46
[^5]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
[^6]: See ["Workbook Object"](/docs/csf/book) for more details.
[^7]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
-[^8]: See [`read` in "Reading Files"](/docs/api/parse-options)
-[^9]: See ["Workbook Object"](/docs/csf/book) for a description of the workbook object or ["API Reference"](/docs/api) for various methods to work with workbook and sheet objects.
+[^8]: See ["Export MIME types for Google Workspace documents"](https://developers.google.com/drive/api/guides/ref-export-formats) in the Google Developer documentation for the complete list of supported file types.
+[^9]: See [`read` in "Reading Files"](/docs/api/parse-options)
+[^10]: See ["Workbook Object"](/docs/csf/book) for a description of the workbook object or ["API Reference"](/docs/api) for various methods to work with workbook and sheet objects.