Compare commits

...

1 Commits

Author SHA1 Message Date
609f7ff5f2 DOM Operations note 2025-08-13 16:28:31 -04:00
27 changed files with 426 additions and 174 deletions

@ -99,7 +99,7 @@ tables in <https://docs.sheetjs.com/docs/demos/engines/>. The component script
### Formats Graph
The formats graph and legend are written in the DOT language. Rebuilding the
graphs will require Graphviz (`brew install graphviz` on macOS)
graphs will require Graphviz and the "Indie Flower" font.
## Live Demos

@ -36,12 +36,13 @@ This demo was tested in the following configurations:
| Platform | Architecture | Date |
|:------------------------------------------------------------------|:-------------|:-----------|
| NVIDIA RTX 5090 (32 GB VRAM) + Ryzen Z1 Extreme (24 GB RAM) | `win11-x64` | 2025-06-17 |
| NVIDIA RTX 5090 (32 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-06-20 |
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-04-17 |
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-01-28 |
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-06-20 |
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-06-20 |
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-01-29 |
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-06-21 |
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (24 GB RAM) | `win11-x64` | 2025-06-20 |
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-02-08 |
| Intel Arc B580 (12 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-06-21 |
| Apple M4 Max 16-Core CPU + 40-Core GPU (48 GB unified memory) | `darwin-arm` | 2025-03-06 |
| Apple M3 Ultra 28-Core CPU + 60-Core GPU (96 GB unified memory) | `darwin-arm` | 2025-06-24 |
| Apple M2 Max 12-Core CPU + 30-Core GPU (32 GB unified memory) | `darwin-arm` | 2025-03-25 |
@ -55,6 +56,7 @@ SheetJS users have verified this demo in other configurations:
|:---------------------------------------------------------------------|:-------------|:------------|
| NVIDIA L40 (48 GB VRAM) + i9-13900K (32 GB RAM) | `linux-x64` | LangChainJS |
| NVIDIA RTX 4080 SUPER (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | LangChainJS |
| NVIDIA RTX 4080 SUPER (16 GB VRAM) + Ryzen Z2 Go (32 GB RAM) | `linux-x64` | LangChainJS |
| NVIDIA RTX 4070 Ti SUPER (16 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | LangChainJS |
| NVIDIA RTX 4070 Ti (12 GB VRAM) + Ryzen 7 5800x (64 GB RAM) | `win11-x64` | LangChainJS |
| NVIDIA RTX 4060 (8 GB VRAM) + Ryzen 7 5700g (32 GB RAM) | `win11-x64` | LangChainJS |
@ -751,7 +753,7 @@ Intel ARC GPUs require the Intel Extension for PyTorch (IPEX) and a special
version of Ollama that ships with the associated LLM Library (IPEX-LLM).
<details>
<summary><b>ARC Instructions</b> (click to show)</summary>
<summary><b>ARC Instructions on Windows</b> (click to show)</summary>
These instructions are based on the official Intel recommendations.
@ -808,6 +810,26 @@ This window should be kept open throughout the demo.
</details>
<details>
<summary><b>ARC Instructions on Linux</b> (click to show)</summary>
These instructions are based on the official Intel recommendations.
A) Install the dependencies from the [Battlemage quickstart](https://github.com/intel/ipex-llm/blob/main/docs/mddocs/Quickstart/bmg_quickstart.md#11-install-prerequisites)
B) Download and extract the [Ollama Portable Zip](https://github.com/intel/ipex-llm/blob/main/docs/mddocs/Quickstart/ollama_portable_zip_quickstart.md#linux-quickstart).
C) When this demo was last tested, the computer had an AMD processor. To force
Ollama to use the GPU, uncomment the "single GPU" line in `start-ollama.sh`:
```bash title="start-ollama.sh (uncomment line)"
export ONEAPI_DEVICE_SELECTOR=level_zero:0
```
D) Run the `start-ollama.sh` script from the extracted folder.
</details>
:::
After installing dependencies, start a new terminal session.

@ -37,12 +37,20 @@ This demo focuses on VueJS concepts. Other demos cover general deployments:
[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers
installation with Yarn and other package managers.
The library can be imported directly from JS or JSX code with:
In modern sites, the library can be imported directly from JS or JSX code:
```js
import { read, utils, writeFile } from 'xlsx';
```
In projects that use CommonJS, the library can be loaded with `require`:
```js
var XLSX = require("xlsx");
```
["Legacy Deployments"](#legacy-deployments) covers integration strategies for
sites that require standalone scripts.
## Internal State
@ -341,28 +349,29 @@ function exportFile() {
<td>{{ row.Name }}</td>
<td>{{ row.Index }}</td>
</tr>
</tbody><tfoot><td colSpan={2}>
</tbody><tfoot><tr><td colSpan={2}>
<button @click="exportFile">Export XLSX</button>
</td></tfoot></table>
</td></tr></tfoot></table>
</template>
```
<details open>
<summary><b>How to run the example</b> (click to hide)</summary>
<Tabs groupId="starter">
<TabItem name="vite" value="ViteJS">
:::note Tested Deployments
This demo was tested in the following environments:
| VueJS | ViteJS | Date |
|:---------|:---------|:-----------|
| `3.5.13` | `6.1.0` | 2025-02-15 |
| VueJS | Deployment | Date |
|:---------|:----------------|:-----------|
| `3.5.17` | ViteJS `7.0.0` | 2025-06-29 |
| `3.5.17` | NuxtJS `3.17.5` | 2025-06-29 |
:::
<Tabs groupId="starter">
<TabItem name="vite" value="ViteJS">
1) Create a new site:
```bash
@ -378,7 +387,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm run dev`}
</CodeBlock>
3) Open a web browser and access the displayed URL (`http://localhost:5173`)
3) Access the "Local" URL (typically `http://localhost:5173`) in a web browser.
4) Replace `src/App.vue` with the `src/SheetJSVueAoO.vue` example.
@ -406,20 +415,10 @@ and test the page.
</TabItem>
<TabItem name="nuxt" value="NuxtJS">
:::note Tested Deployments
This demo was tested in the following environments:
| VueJS | NuxtJS | Date |
|:---------|:---------|:-----------|
| `3.5.13` | `3.15.0` | 2025-01-02 |
:::
1) Create a new site:
```bash
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit -M ,
```
2) Install the SheetJS dependency and start the dev server:
@ -431,7 +430,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm run dev`}
</CodeBlock>
3) Open a web browser and access the displayed URL (`http://localhost:3000`)
3) Access the "Local" URL (typically `http://localhost:3000`) in a web browser.
4) Replace `app.vue` with the `src/SheetJSVueAoO.vue` example.
@ -511,19 +510,20 @@ function exportFile() {
<details open>
<summary><b>How to run the example</b> (click to hide)</summary>
<Tabs groupId="starter">
<TabItem name="vite" value="ViteJS">
:::note Tested Deployments
This demo was tested in the following environments:
| VueJS | ViteJS | Date |
|:---------|:--------|:-----------|
| `3.5.13` | `6.0.7` | 2025-01-02 |
| VueJS | Deployment | Date |
|:---------|:----------------|:-----------|
| `3.5.17` | ViteJS `7.0.0` | 2025-06-29 |
| `3.5.17` | NuxtJS `3.17.5` | 2025-06-29 |
:::
<Tabs groupId="starter">
<TabItem name="vite" value="ViteJS">
1) Create a new site:
```bash
@ -539,7 +539,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm run dev`}
</CodeBlock>
3) Open a web browser and access the displayed URL (`http://localhost:5173`)
3) Access the "Local" URL (typically `http://localhost:5173`) in a web browser.
4) Replace `src/App.vue` with the `src/SheetJSVueHTML.vue` example.
@ -567,20 +567,10 @@ and test the page.
</TabItem>
<TabItem name="nuxt" value="NuxtJS">
:::note Tested Deployments
This demo was tested in the following environments:
| VueJS | NuxtJS | Date |
|:---------|:---------|:-----------|
| `3.5.13` | `3.15.0` | 2025-01-02 |
:::
1) Create a new site:
```bash
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit
npx nuxi@latest init sheetjs-nuxt --packageManager npm --no-install --no-gitInit -M ,
```
2) Install the SheetJS dependency and start the dev server:
@ -592,7 +582,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm run dev`}
</CodeBlock>
3) Open a web browser and access the displayed URL (`http://localhost:3000`)
3) Access the "Local" URL (typically `http://localhost:3000`) in a web browser.
4) Replace `app.vue` with the `src/SheetJSVueHTML.vue` example.

@ -204,23 +204,24 @@ This demo was tested in the following environments:
| `esbuild` | Date |
|:----------|:-----------|
| `0.24.2` | 2025-01-07 |
| `0.23.1` | 2025-01-07 |
| `0.22.0` | 2025-01-07 |
| `0.21.5` | 2025-01-07 |
| `0.20.2` | 2025-01-07 |
| `0.19.12` | 2025-01-07 |
| `0.18.20` | 2025-01-07 |
| `0.17.19` | 2025-01-07 |
| `0.16.17` | 2025-01-07 |
| `0.15.18` | 2025-01-07 |
| `0.14.54` | 2025-01-07 |
| `0.13.15` | 2025-01-07 |
| `0.12.29` | 2025-01-07 |
| `0.11.23` | 2025-01-07 |
| `0.10.2` | 2025-01-07 |
| `0.9.7` | 2025-01-07 |
| `0.9.1` | 2025-01-07 |
| `0.25.5` | 2025-06-20 |
| `0.24.2` | 2025-06-20 |
| `0.23.1` | 2025-06-20 |
| `0.22.0` | 2025-06-20 |
| `0.21.5` | 2025-06-20 |
| `0.20.2` | 2025-06-20 |
| `0.19.12` | 2025-06-20 |
| `0.18.20` | 2025-06-20 |
| `0.17.19` | 2025-06-20 |
| `0.16.17` | 2025-06-20 |
| `0.15.18` | 2025-06-20 |
| `0.14.54` | 2025-06-20 |
| `0.13.15` | 2025-06-20 |
| `0.12.29` | 2025-06-20 |
| `0.11.23` | 2025-06-20 |
| `0.10.2` | 2025-06-20 |
| `0.9.7` | 2025-06-20 |
| `0.9.1` | 2025-06-20 |
:::

@ -242,7 +242,7 @@ This demo was tested in the following environments:
| Android 34 | Pixel 3a | `0.76.8` | `darwin-arm` | 2025-03-26 |
| iOS 18.3 | iPhone 16 Pro | `0.76.8` | `darwin-arm` | 2025-03-26 |
| Android 35 | Pixel 9 Pro XL | `0.79.2` | `win11-x64` | 2025-06-08 |
| Android 35 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-01-02 |
| Android 36 | Pixel 9 | `0.79.2` | `linux-x64` | 2025-07-06 |
:::
@ -259,12 +259,22 @@ Make sure you can run a basic test app on your phone/simulator before continuing
<details>
<summary><b>Installation Notes</b> (click to show)</summary>
**Java JDK**
On the Steam Deck, JDK17 was installed using `pacman`:
```bash
sudo pacman -Syu jdk17-openjdk
```
Debian and Ubuntu require the `openjdk-17-jdk` package:
```bash
sudo apt install openjdk-17-jdk
```
**Android Studio for Linux**
[The Android Studio tarball](https://developer.android.com/studio) was
downloaded and extracted. After extracting:
@ -276,6 +286,8 @@ cd ./android-studio/bin
In Android Studio, select "SDK Manager" and switch to the "SDK Tools" tab. Check
"Show Package Details" and install "Android SDK Command-line Tools (latest)".
**Environment Variables for Linux**
When this demo was last tested, the following environment variables were used:
```bash
@ -390,8 +402,8 @@ the interactive CLI tool:
npx react-native start
```
Once the dev server is ready, the terminal will display a few options. Press `a`
to run on Android.
Once the dev server is ready, the terminal will display a few options. Press
<kbd>r</kbd> to relaod the app.
:::
@ -1132,7 +1144,7 @@ This demo was tested in the following environments:
| Android 34 | Pixel 3a | `0.76.5` | `darwin-arm` | 2025-01-05 |
| iOS 18.2 | iPhone 16 Pro | `0.76.5` | `darwin-arm` | 2025-01-05 |
| Android 35 | Pixel 9 Pro XL | `0.76.5` | `win11-x64` | 2025-06-08 |
| Android 35 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-01-02 |
| Android 36 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-07-06 |
:::
@ -1217,6 +1229,20 @@ The app should look like the following screenshot:
![React Native Android App](pathname:///reactnative/and1.png)
:::info pass
On Linux, the command may silently stall. It is strongly recommended to launch
the interactive CLI tool:
```bash
npx react-native start
```
Once the dev server is ready, the terminal will display a few options. Press
<kbd>r</kbd> to relaod the app.
:::
:::caution pass
In some test runs on Windows, the build failed with an error:

@ -66,7 +66,7 @@ This demo was tested in the following environments:
| Android 35 | Pixel 9 Pro XL | `8.9.2` | `darwin-x64` | 2025-05-06 |
| iOS 18.4 | iPhone 16 Pro Max | `8.9.2` | `darwin-x64` | 2025-05-06 |
| Android 35 | Pixel 9 | `8.9.2` | `win11-x64` | 2025-06-08 |
| Android 35 | Pixel 9 | `8.8.3` | `linux-x64` | 2025-01-02 |
| Android 36 | Pixel 9 | `8.9.2` | `linux-x64` | 2025-07-06 |
:::
@ -611,7 +611,7 @@ adb root
adb pull /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls SheetJSNS.xls
```
If the emulator cannot be rooted, the following command works in macOS:
If the emulator cannot be rooted, the following workaround should be used:
```bash
adb shell "run-as org.nativescript.SheetJSNS cat /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls" > SheetJSNS.xls
@ -655,7 +655,7 @@ id | name | role
adb push SheetJSNS.xls /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls
```
If the emulator cannot be rooted, the following command works in macOS:
If the emulator cannot be rooted, raw byte operations work in macOS and Linux:
```bash
dd if=SheetJSNS.xls | adb shell "run-as org.nativescript.SheetJSNS dd of=/data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls"

@ -54,7 +54,7 @@ This demo was tested in the following environments:
| Android 34 | Pixel 3a | `7.1.0` / `7.0.0` | `darwin-arm` | 2025-03-30 |
| iOS 18.2 | iPhone 16 Pro Max | `7.1.0` / `7.0.0` | `darwin-arm` | 2025-03-30 |
| Android 35 | Pixel 9 Pro XL | `7.3.0` / `7.1.1` | `win11-x64` | 2025-06-08 |
| Android 35 | Pixel 9 | `6.2.0` / `6.0.2` | `linux-x64` | 2025-01-02 |
| Android 36 | Pixel 9 | `7.4.1` / `7.1.2` | `linux-x64` | 2025-07-06 |
:::
@ -212,12 +212,16 @@ iOS development is only supported on macOS.
:::
<details>
<details open>
<summary><b>Installation Notes</b> (click to show)</summary>
For Android development, CapacitorJS requires a Java version compatible with the
expected Gradle version. When this demo was tested against CapacitorJS `6.2.0`,
Java 20 was required to support Gradle `8.2.1`.
expected Gradle version:
| CapacitorJS | Gradle | Java |
|:------------|:---------|:-----|
| `6.2.0` | `8.2.1` | 20 |
| `7.4.1` | `8.11.1` | 21 |
</details>
@ -249,6 +253,22 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm i --save @capacitor/core @capacitor/cli @capacitor/filesystem`}
</CodeBlock>
:::warning pass
When this demo was last tested, parts of the official project required ViteJS 6
and other parts required ViteJS 7. The install failed.
**This is a bug in the Svelte integration!**
Until the bug is fixed, the `--force` option should be used:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz --force
npm i --save @capacitor/core @capacitor/cli @capacitor/filesystem --force`}
</CodeBlock>
:::
4) Create CapacitorJS structure:
```bash
@ -258,7 +278,7 @@ npm run build
:::note pass
If prompted to create an Ionic account, type `N` and press <kbd>Enter</kbd>.
If prompted to create an Ionic account, Press <kbd>N</kbd> to opt out.
:::
@ -277,6 +297,22 @@ npm i --save @capacitor/android
npx cap add android
```
:::warning pass
When this demo was last tested, parts of the official project required ViteJS 6
and other parts required ViteJS 7. The install failed.
**This is a bug in the Svelte integration!**
Until the bug is fixed, the `--force` option should be used:
```bash
npm i --save @capacitor/android --force
npx cap add android
```
:::
:::caution pass
If the wrong Java version is installed, the last command will fail with a

@ -211,7 +211,7 @@ This demo was tested in the following environments:
| macOS 14.5 | `darwin-arm` | `35.1.2` | 2025-03-30 |
| Windows 11 | `win11-x64` | `33.2.1` | 2025-02-11 |
| Windows 11 | `win11-arm` | `33.2.1` | 2025-02-23 |
| Linux (HoloOS) | `linux-x64` | `33.2.1` | 2025-01-02 |
| Linux (Ubuntu) | `linux-x64` | `35.1.2` | 2025-07-06 |
| Linux (Debian) | `linux-arm` | `33.2.1` | 2025-02-16 |
:::
@ -284,6 +284,28 @@ npx -y electron .
The app will run.
:::info pass
In some Linux deployments, the command will fail with a sandbox error:
```
The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now.
```
The workaround is to temporarily disable the sandbox restriction:
```bash
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
```
After testing, the restriction can be re-enabled with a similar command:
```bash
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=1
```
:::
4) To build a standalone app, run the builder:
```bash

@ -125,7 +125,7 @@ This demo was tested in the following environments:
| macOS 14.5 | `darwin-arm` | `0.94.0` | 2025-03-30 | |
| Windows 11 | `win11-x64` | `0.100.0` | 2025-05-27 | |
| Windows 11 | `win11-arm` | `0.94.0` | 2025-02-23 | |
| Linux (HoloOS) | `linux-x64` | `0.89.0` | 2025-01-10 | |
| Linux (Ubuntu) | `linux-x64` | `0.101.2` | 2025-07-06 | |
| Linux (Debian) | `linux-arm` | `0.60.0` | 2025-02-16 | Unofficial build[^1] |
:::
@ -146,7 +146,7 @@ cd sheetjs-nwjs
"version": "0.0.0",
"main": "index.html",
"dependencies": {
"nw": "0.100.0",
"nw": "0.101.2",
"xlsx": "https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz"
}
}`}
@ -224,7 +224,7 @@ Unfortunately `nw-builder` will not be able to build a standalone program.
5) To build a standalone app, run the builder:
```bash
npx -p nw-builder@4.11.6 nwbuild --mode=build --version=0.100.0 --glob=false --outDir=../out ./
npx -p nw-builder@4.13.14 nwbuild --mode=build --version=0.101.2 --glob=false --outDir=../out ./
```
This will generate the standalone app in the `..\out\` folder.
@ -235,6 +235,10 @@ There is a regression in `nw-builder` versions `4.12.0` and `4.13.14`.
In local `win11-x64` testing, `4.11.6` generates the standalone application.
```bash
npx -p nw-builder@4.11.6 nwbuild --mode=build --version=0.101.2 --glob=false --outDir=../out ./
```
:::
6) Launch the generated application:

@ -64,7 +64,7 @@ This demo was tested in the following environments:
| macOS 14.5 | `darwin-arm` | `v2.10.1` | 2025-03-30 |
| Windows 11 | `win11-x64` | `v2.10.1` | 2025-05-27 |
| Windows 11 | `win11-arm` | `v2.10` | 2025-02-23 |
| Linux (HoloOS) | `linux-x64` | `v2.9.2` | 2025-01-02 |
| Linux (HoloOS) | `linux-x64` | `v2.10.2` | 2025-07-06 |
| Linux (Debian) | `linux-arm` | `v2.10` | 2025-02-16 |
:::

@ -60,7 +60,7 @@ This demo was tested in the following environments:
| macOS 14.5 | `darwin-arm` | `v1.6.0` | 2025-03-30 |
| Windows 11 | `win11-x64` | `v1.6.0` | 2025-05-27 |
| Windows 11 | `win11-arm` | `v1.6.0` | 2025-02-23 |
| Linux (HoloOS) | `linux-x64` | `v1.6.0` | 2025-01-02 |
| Linux (HoloOS) | `linux-x64` | `v1.6.0` | 2025-07-06 |
| Linux (Debian) | `linux-arm` | `v1.6.0` | 2025-05-27 |
:::
@ -376,7 +376,7 @@ At a high level, the following software is required for building Tauri apps:
The platform configuration can be verified by running:
```bash
npx @tauri-apps/cli info
npx @tauri-apps/cli@1 info
```
If required dependencies are installed, the output will show a checkmark next to

@ -55,7 +55,7 @@ This demo was tested in the following environments:
| macOS 14.5 | `darwin-arm` | `6.0.0` | `6.0.0` | 2025-03-30 |
| Windows 11 | `win11-x64` | `6.1.0` | `6.1.0` | 2025-05-27 |
| Windows 11 | `win11-arm` | `5.6.0` | `5.6.0` | 2025-02-23 |
| Linux (HoloOS) | `linux-x64` | `5.5.0` | `5.5.0` | 2025-01-02 |
| Linux (HoloOS) | `linux-x64` | `6.1.0` | `6.1.0` | 2025-07-06 |
| Linux (Debian) | `linux-arm` | `5.6.0` | `5.6.0` | 2025-02-16 |
NeutralinoJS on Windows on ARM generates X64 binaries that run using the X64

@ -466,15 +466,15 @@ This browser demo was tested in the following environments:
| Browser | Date |
|:-------------|:-----------|
| Chromium 131 | 2025-01-07 |
| Chromium 137 | 2025-06-20 |
Some lesser-used browsers do not support File System Access API:
| Browser | Date |
|:-------------|:-----------|
| Safari 17.5 | 2025-01-07 |
| Safari 18.5 | 2025-06-20 |
| Konqueror 22 | 2025-04-23 |
| Firefox 133 | 2025-01-07 |
| Firefox 139 | 2025-06-20 |
:::

@ -53,11 +53,11 @@ This demo was tested in the following deployments:
| Architecture | Version | Date |
|:-------------|:------------------|:-----------|
| `darwin-x64` | `18.5` (StataNow) | 2025-01-08 |
| `darwin-x64` | `18.5` (StataNow) | 2025-06-20 |
| `darwin-arm` | `18.5` (StataNow) | 2025-04-24 |
| `win11-x64` | `18.5` (StataNow) | 2025-04-28 |
| `win11-arm` | `18.5` (StataNow) | 2025-02-23 |
| `linux-x64` | `18.5` (StataNow) | 2025-01-09 |
| `linux-x64` | `19.5` (StataNow) | 2025-07-06 |
:::
@ -203,7 +203,7 @@ import excel "sheetjs.tmp.xlsx", firstrow
1) Open Stata and run the following command:
```stata
```stata title="Find Stata data directory (run in Stata)"
pwd
```
@ -213,7 +213,7 @@ The output will be the default data directory. On macOS this is typically
2) Open a terminal window and create a project folder `sheetjs-stata` within the
Stata data directory:
```bash
```bash title="Create folder in Stata data directory (run in terminal)"
: # `cd` to the Stata data directory
cd ~/Documents/Stata
mkdir sheetjs-stata
@ -252,7 +252,7 @@ bash
3) Download [`stplugin.c`](https://www.stata.com/plugins/stplugin.c) and
[`stplugin.h`](https://www.stata.com/plugins/stplugin.h) from the Stata website:
```bash
```bash title="Download Stata plugin files (run in terminal)"
curl -LO https://www.stata.com/plugins/stplugin.c
curl -LO https://www.stata.com/plugins/stplugin.h
```
@ -276,7 +276,7 @@ curl -LO https://docs.sheetjs.com/plugins/stplugin.h
4) Download Duktape. In Windows, the following commands should be run in WSL. In
macOS, the commands should be run in the same Terminal session.
```bash
```bash title="Download Duktape (run in terminal)"
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
mv duktape-2.7.0/src/*.{c,h} .
@ -287,7 +287,7 @@ mv duktape-2.7.0/src/*.{c,h} .
In Windows, the following commands should be run in WSL. In macOS, the commands
should be run in the same Terminal session.
```bash
```bash title="Download plugin source (run in terminal)"
curl -LO https://docs.sheetjs.com/stata/cleanfile.c
```
@ -298,7 +298,7 @@ curl -LO https://docs.sheetjs.com/stata/cleanfile.c
7) Build the plugin:
```bash
```bash title="Build plugin (run in terminal)"
gcc -shared -fPIC -DSYSTEM=APPLEMAC stplugin.c duktape.c cleanfile.c -lm -std=c99 -Wall -ocleanfile.plugin
```
@ -329,7 +329,7 @@ cl /LD cleanfile.c stplugin.c duktape.c
8) Copy the plugin to the Stata data directory:
```bash
```bash title="Copy compiled plugin to Stata data directory (run in terminal)"
cp cleanfile.plugin ../
```
@ -354,7 +354,7 @@ copy cleanfile.dll c:\data\cleanfile.plugin
9) Move to the Stata data directory:
```bash
```bash title="Move to Stata data directory (run in terminal)"
cd ..
```
@ -383,7 +383,7 @@ bash
In Windows, the following commands should be run in WSL. In macOS, the commands
should be run in the same Terminal session.
<CodeBlock language="bash">{`\
<CodeBlock language="bash" title="Download SheetJS Scripts and files (run in terminal)">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.numbers`}
@ -404,7 +404,7 @@ The screenshot in the introduction shows the result of steps 13 - 19
13) Run the following command in Stata:
```stata
```stata title="List files in data directory (run in Stata)"
dir
```
@ -424,13 +424,13 @@ cd c:\data
14) Load the `cleanfile` plugin:
```stata
```stata title="Load the new plugin (run in Stata)"
program cleanfile, plugin
```
16) Read the `pres.numbers` test file:
```stata
```stata title="Run the plugin (run in Stata)"
plugin call cleanfile, "pres.numbers" verbose
```
@ -453,13 +453,13 @@ for more help, see <span {...b}>import excel</span>
17) Close the plugin:
```stata
```stata title="Close the plugin (run in Stata)"
program drop cleanfile
```
18) Clear the current session:
```stata
```stata title="Clear the current session (run in Stata)"
clear
```
@ -468,7 +468,7 @@ excel "sheetjs.tmp.xlsx", firstrow</span></code></p></li></ol>
Alternatively, manually type the command:
```stata
```stata title="Load the file created by the SheetJS plugin (run in Stata)"
import excel "sheetjs.tmp.xlsx", firstrow
```
@ -481,25 +481,24 @@ The output will show the import result:
20) List the dataset:
```stata
```stata title="List the new variables (run in Stata)"
list Name Index
```
The result should match the following listing:
```
. list Name Index
+----------------------+
| Name Index |
|----------------------|
1. | Bill Clinton 42 |
2. | GeorgeW Bush 43 |
3. | Barack Obama 44 |
4. | Donald Trump 45 |
5. | Joseph Biden 46 |
+----------------------+
```
<pre>
. list Name Index<br/>
{' '}+----------------------+
{' '}| Name Index |
{' '}|----------------------|
{' '}1. | Bill Clinton 42 |
{' '}2. | GeorgeW Bush 43 |
{' '}3. | Barack Obama 44 |
{' '}4. | Donald Trump 45 |
{' '}5. | Joseph Biden 46 |
{' '}+----------------------+
</pre>
In the Stata GUI, the Data Editor should match the following screenshot:

@ -8,6 +8,8 @@ sidebar_custom_props:
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
[Maple](https://www.maplesoft.com/products/Maple/) is a numeric computing
@ -36,8 +38,8 @@ This demo was tested by SheetJS users in the following deployments:
| Architecture | Version | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `2024.0` | 2025-01-10 |
| `win11-x64` | `2024.2` | 2025-05-07 |
| `darwin-x64` | `2025.1` | 2025-06-20 |
| `win11-x64` | `2025.1` | 2025-07-17 |
:::
@ -134,6 +136,20 @@ with(ExcelTools);
Import(SheetToXLSX("pres.numbers"))
```
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
1) Open a new Terminal window and create the `/tmp/sheetjs-maple` folder:
```bash
cd /tmp
mkdir sheetjs-maple
cd sheetjs-maple
```
</TabItem>
<TabItem value="win11-x64" label="Windows">
0) Install "Windows Subsystem for Linux" (WSL)[^5] and Visual Studio[^6].
1) Open a new "x64 Native Tools Command Prompt" window and create a project
@ -145,20 +161,40 @@ mkdir sheetjs-maple
cd sheetjs-maple
```
</TabItem>
</Tabs>
2) Copy the headers and `lib` files from the Maple folder to the project folder.
The headers will be placed in the `extern/include/` folder in the Maple folder.
The `lib` files are placed in a platform-specific `bin` folder.
The following commands apply to x64 versions of Windows:
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
In macOS, the "Maple folder" is located in `/Library/Frameworks`:
```bash
cp /Library/Frameworks/Maple.framework/Versions/2025/extern/include/*.h .
cp /Library/Frameworks/Maple.framework/Versions/2025/bin.APPLE_UNIVERSAL_OSX/*.so .
cp /Library/Frameworks/Maple.framework/Versions/2025/bin.APPLE_UNIVERSAL_OSX/*.dylib .
```
3) Observe that macOS does not need a "Linux Subsystem" and move to Step 4.
</TabItem>
<TabItem value="win11-x64" label="Windows">
```powershell
copy "C:\Program Files\Maple 2024\extern\include\"*.h .
copy "c:\Program Files\Maple 2024\bin.x86_64_WINDOWS"\*.lib .
copy "C:\Program Files\Maple 2025\extern\include\"*.h .
copy "C:\Program Files\Maple 2025\bin.x86_64_WINDOWS"\*.lib .
```
3) Run `bash` to enter WSL
4) Within WSL, install Duktape:
</TabItem>
</Tabs>
4) Install Duktape:
```bash
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
@ -166,7 +202,7 @@ tar -xJf duktape-2.7.0.tar.xz
mv duktape-2.7.0/src/*.{c,h} .
```
5) Still within WSL, download SheetJS scripts and the test file.
5) Download SheetJS scripts and the test file.
<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
@ -174,12 +210,26 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
6) Still within WSL, download the extension C code
6) Download the extension C code
```bash
curl -LO https://docs.sheetjs.com/maple/sheetjs-maple.c
```
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
7) Observe that macOS does not need a "Linux Subsystem" and move to Step 8.
8) Build the extension library:
```powershell
gcc -shared -fPIC duktape.c sheetjs-maple.c -lm -std=c99 -Wall -o libsheetjs-maple.so -L. -lmaplec
```
</TabItem>
<TabItem value="win11-x64" label="Windows">
7) Exit WSL by running `exit`. The window will return to the command prompt.
8) Build the extension DLL:
@ -188,14 +238,30 @@ curl -LO https://docs.sheetjs.com/maple/sheetjs-maple.c
cl -Gz sheetjs-maple.c duktape.c /EHsc -link -dll -out:sheetjs-maple.dll maplec.lib
```
</TabItem>
</Tabs>
9) Close and re-open Maple, then create a new Maple Worksheet or Document
10) Run the following command in Maple to change the working directory:
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
```maple
currentdir("/tmp/sheetjs-maple");
```
</TabItem>
<TabItem value="win11-x64" label="Windows">
```maple
currentdir("c:\\sheetjs-maple");
```
</TabItem>
</Tabs>
11) Load the `SheetToXLSX` method from the extension:
```maple

@ -365,7 +365,7 @@ This demo was tested in the following deployments:
| Architecture | Git Commit | Date |
|:-------------|:-----------|:-----------|
| `darwin-x64` | `8ef11b4` | 2025-03-31 |
| `darwin-arm` | `388376f` | 2025-01-13 |
| `darwin-arm` | `8ef11b4` | 2025-08-07 |
| `linux-x64` | `8ef11b4` | 2025-04-21 |
| `linux-arm` | `388376f` | 2025-02-15 |

@ -210,7 +210,7 @@ In addition to the aforementioned sheet keys, worksheets also add:
merge object is a range object that represents the covered range.
- `ws['!outline']`: configure how outlines should behave. Options default to
the default settings in Excel 2024:
the default settings in Excel:
| key | Excel feature | default |
|:----------|:----------------------------------------------|:--------|

@ -275,12 +275,12 @@ tend to use a continued fraction approach.
The common algorithm produces unexpected results for "Up to one digit":
| Value | Mediant | Excel 2024 |
|:------|--------:|-----------:|
| `0.3` | `2/7` | `2/7` |
| `1.3` | `1 2/7` | `1 1/3` |
| `2.3` | `2 2/7` | `2 2/7` |
| `3.3` | `3 2/7` | `3 2/7` |
| Value | Mediant | Excel |
|:------|--------:|--------:|
| `0.3` | `2/7` | `2/7` |
| `1.3` | `1 2/7` | `1 1/3` |
| `2.3` | `2 2/7` | `2 2/7` |
| `3.3` | `3 2/7` | `3 2/7` |
:::

@ -99,20 +99,26 @@ The read functions accept an options argument:
#### Dense
The ["Cell Storage"](/docs/csf/sheet#cell-storage) section of the SheetJS Data
Model documentation explains the worksheet representation in more detail.
By default, the `read` and `readFile` functions generate "sparse" worksheets.
When the `dense` option is set to `true`, the functions will generate "dense"
worksheets that may be more efficient in modern browsers.
The ["Cell Storage"](/docs/csf/sheet#cell-storage) section explains worksheet
structures in more detail.
:::note pass
[Utility functions that process SheetJS workbook objects](/docs/api/utilities/)
typically process both sparse and dense worksheets.
typically support sparse and dense worksheets.
:::
#### Range
Some file formats, including XLSX and XLS, can self-report worksheet ranges. The
self-reported ranges are used by default.
Some file formats, including XLSX and XLS, can self-report worksheet ranges.
`read` and `readFile` assume the self-reported worksheet ranges are correct. If
files include cells outside this range, the parsers will save cell information
but other utility functions will ignore those cells.
If the `sheetRows` option is set, up to `sheetRows` rows will be parsed from the
worksheets. `sheetRows-1` rows will be generated when looking at the JSON object

@ -120,6 +120,21 @@ or `querySelector`.
:::
:::caution pass
The underlying DOM operations have changed over time. Some deployments using
older SheetJS CE versions may not work using the latest version, throwing an
error such as:
```
Unsupported origin when DIV is not a TABLE
```
[The note](/docs/miscellany/errors#unsupported-origin-when-div-is-not-a-table)
in the "Troubleshooting" section includes a deeper explanation and a workaround.
:::
### Create New Sheet
**Create a worksheet or workbook from a TABLE element**

@ -189,6 +189,43 @@ dev server and copied to the production site in the build process.
:::
#### "Unsupported origin when DIV is not a TABLE"
[`table_to_book` / `table_to_sheet`](/docs/api/utilities/html#html-table-input)
process HTML DOM elements. The underlying behavior has changed over time. The
SheetJS methods use the following techniques:
- Versions up to `0.18.8` (including `0.18.5`) scanned the descendents of the
DOM element to find `TR` table rows. The root element need not be a `TABLE`
- Newer releases expect a `TABLE` element and uses the `rows` property to find
the `TR` elements. This approach automatically handles `TBODY` and other
table section elements.
Some data table libraries may use multiple `DIV` wrappers or multiple `TABLE`
elements. The older implementation of `table_to_book` handles these corner cases
but the newer implementation does not.
The old behavior can be approximated by scanning for `TABLE` elements:
```js
function deep_table_to_sheet(elt, opts) {
let ws;
[...elt.getElementsByTagName("TABLE")].forEach(t => {
if(!ws) ws = XLSX.utils.table_to_sheet(t, opts);
else XLSX.utils.sheet_add_dom(ws, t, {...opts, origin: -1});
});
return ws;
};
function deep_table_to_book(elt, opts) {
return XLSX.utils.book_new(deep_table_to_sheet(elt, opts));
}
```
See [issue #3319](https://git.sheetjs.com/sheetjs/sheetjs/issues/3319) for a
longer discussion.
#### Cloudflare Worker "Error: Script startup exceeded CPU time limit."
This may show up in projects with many dependencies. The official workaround is

@ -41,11 +41,11 @@ These instructions were tested on the following platforms:
| Platform | Architecture | Test Date |
|:------------------------------|:-------------|:-----------|
| Linux (Steam Deck Holo x64) | `linux-x64` | 2025-01-10 |
| Linux (Ubuntu Linux x64) | `linux-x64` | 2025-07-06 |
| Linux (Debian Linux AArch64) | `linux-arm` | 2025-01-14 |
| MacOS 15.3 (x64) | `darwin-x64` | 2025-03-31 |
| MacOS 15.2 (ARM64) | `darwin-arm` | 2025-03-07 |
| Windows 11 (x64) + WSL Ubuntu | `win11-x64` | 2025-01-14 |
| Windows 11 (x64) + WSL Ubuntu | `win11-x64` | 2025-06-20 |
| Windows 11 (ARM) + WSL Ubuntu | `win11-arm` | 2025-02-23 |
With some additional dependencies, the unminified scripts are reproducible and
@ -154,7 +154,7 @@ success with Windows on ARM running on computers with the M2 Max CPU.
B) Install NVM within WSL:
```bash
```bash title="Install NVM (run within WSL)"
sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
```
@ -163,14 +163,14 @@ C) Exit the WSL session and start a new session
D) Install NodeJS 16 using NVM:
```bash
```bash title="Install NodeJS 16 (run within WSL)"
nvm install 16
nvm use 16
```
E) Clone the [`js-crc32` repo](https://git.sheetjs.com/sheetjs/js-crc32)
```bash
```bash title="Clone repo (run within WSL)"
git clone https://git.sheetjs.com/sheetjs/js-crc32
```
@ -211,20 +211,32 @@ F) Set `git` config `core.autocrlf` setting to `false`. The following commands
should be run twice, once within PowerShell (if Git for Windows is installed)
and once within WSL bash:
```bash
```bash title="Configure git (run within WSL AND run within PowerShell)"
git config --global --add core.autocrlf false
git config --global --unset core.autocrlf true
```
G) Run `unzip`. If the program is missing, install manually:
G) Run `unzip` within WSL:
```bash
```bash title="Test if the unzip tool is installed (run within WSL)"
unzip
```
If the program is missing, install manually:
```bash title="Install unzip (run within WSL)"
sudo apt-get install -y unzip
```
H) Run `make`. If the program is missing, install manually:
H) Run `make` within WSL:
```bash
```bash title="Test if the make tool is installed (run within WSL)"
make
```
If the program is missing, install manually:
```bash title="Install make (run within WSL)"
sudo apt-get install -y make
```
@ -326,7 +338,7 @@ On Debian and Ubuntu systems, `build-essential`, `curl` and `git` are required:
```bash title="Debian and Ubuntu"
sudo apt update
sudo apt-get install build-essential curl git
sudo apt install build-essential curl git
```
On Arch Linux, `base-devel`, `curl` and `git` are required:

@ -213,16 +213,27 @@ const config = {
require.resolve("@cmfcmf/docusaurus-search-local"),
[ '@docusaurus/plugin-client-redirects', {
redirects: [
/* installation */
{ from: '/docs/installation', to: '/docs/getting-started/' },
{ from: '/docs/installation/standalone', to: '/docs/getting-started/installation/standalone/' },
{ from: '/docs/installation/frameworks', to: '/docs/getting-started/installation/frameworks/' },
{ from: '/docs/installation/nodejs', to: '/docs/getting-started/installation/nodejs/' },
{ from: '/docs/installation/amd', to: '/docs/getting-started/installation/amd/' },
{ from: '/docs/installation/extendscript', to: '/docs/getting-started/installation/extendscript/' },
{ from: '/docs/installation/deno', to: '/docs/getting-started/installation/deno/' },
{ from: '/docs/installation/bun', to: '/docs/getting-started/installation/bun/' },
/* examples */
{ from: '/docs/example', to: '/docs/getting-started/examples/export/' },
{ from: '/docs/getting-started/example', to: '/docs/getting-started/examples/export/' },
{ from: '/docs/installation', to: '/docs/getting-started/' },
/* api */
{ from: '/docs/interface', to: '/docs/api/' },
{ from: '/docs/read', to: '/docs/api/parse-options/' },
/* demos */
{ from: '/docs/demos/excel', to: '/docs/demos/' },
{ from: '/docs/getting-started/demos/', to: '/docs/demos/' },
{ from: '/docs/getting-started/demos/excel', to: '/docs/demos/' },
{ from: '/docs/demos/content', to: '/docs/demos/static/' },
{ from: '/docs/demos/git', to: '/docs/demos/cloud/github/' },
{ from: '/docs/demo/grid', to: '/docs/demos/grid/' },
/* frontend */
{ from: '/docs/demos/angular', to: '/docs/demos/frontend/angular/' },
{ from: '/docs/demos/react', to: '/docs/demos/frontend/react/' },
@ -241,19 +252,18 @@ const config = {
{ from: '/docs/demos/netsuite', to: '/docs/demos/cloud/netsuite/' },
{ from: '/docs/demos/gsheet', to: '/docs/demos/cloud/gsheet/' },
{ from: '/docs/demos/airtable', to: '/docs/demos/cloud/airtable/' },
{ from: '/docs/demos/git', to: '/docs/demos/cloud/github/' },
{ from: '/docs/demos/cloudata', to: '/docs/demos/cloud/' },
{ from: '/docs/demos/cloudata/gsheet', to: '/docs/demos/cloud/gsheet/' },
{ from: '/docs/demos/cloudata/airtable', to: '/docs/demos/cloud/airtable/' },
{ from: '/docs/getting-started/demos/netsuite', to: '/docs/demos/cloud/netsuite/' },
{ from: '/docs/demos/hosting/dropbox', to: '/docs/demos/cloud/dropbox/' },
{ from: '/docs/demos/hosting/github', to: '/docs/demos/cloud/github/' },
/* extensions */
{ from: '/docs/demos/extendscript', to: '/docs/demos/extensions/extendscript/' },
{ from: '/docs/demos/excelapi', to: '/docs/demos/extensions/excelapi/' },
{ from: '/docs/demos/chromium', to: '/docs/demos/extensions/chromium/' },
{ from: '/docs/getting-started/demos/chromium', to: '/docs/demos/extensions/chromium/' },
/* cloud */
{ from: '/docs/demos/cloudata', to: '/docs/demos/cloud/' },
{ from: '/docs/demos/cloudata/gsheet', to: '/docs/demos/cloud/gsheet/' },
{ from: '/docs/demos/cloudata/airtable', to: '/docs/demos/cloud/airtable/' },
{ from: '/docs/getting-started/demos/netsuite', to: '/docs/demos/cloud/netsuite/' },
/* hosting */
{ from: '/docs/demos/hosting/dropbox', to: '/docs/demos/cloud/dropbox/' },
{ from: '/docs/demos/hosting/github', to: '/docs/demos/cloud/github/' },
/* data */
{ from: '/docs/getting-started/demos/database', to: '/docs/demos/data/' },
{ from: '/docs/demos/database', to: '/docs/demos/data/' },
@ -283,16 +293,11 @@ const config = {
{ from: '/docs/demos/ml', to: '/docs/demos/math/' },
{ from: '/docs/demos/bigdata/ml', to: '/docs/demos/math/' },
{ from: '/docs/demos/engines/pandas', to: '/docs/demos/math/pandas/' },
/* installation */
{ from: '/docs/installation/standalone', to: '/docs/getting-started/installation/standalone/' },
{ from: '/docs/installation/frameworks', to: '/docs/getting-started/installation/frameworks/' },
{ from: '/docs/installation/nodejs', to: '/docs/getting-started/installation/nodejs/' },
{ from: '/docs/installation/amd', to: '/docs/getting-started/installation/amd/' },
{ from: '/docs/installation/extendscript', to: '/docs/getting-started/installation/extendscript/' },
{ from: '/docs/installation/deno', to: '/docs/getting-started/installation/deno/' },
{ from: '/docs/installation/bun', to: '/docs/getting-started/installation/bun/' },
/* misc */
/* grid */
{ from: '/demos/datagrid', to: '/docs/demos/grid/' },
{ from: '/docs/demo/grid', to: '/docs/demos/grid/' },
/* static */
{ from: '/docs/demos/content', to: '/docs/demos/static/' },
]
}]
]

@ -28,7 +28,7 @@ document.getElementById("xport").addEventListener("click", function() {
prez.forEach(function(row) {
row.start = row.terms.find(function(term) {
return term.type === "prez";
}).start
}).start;
});
prez.sort(function(l,r) { return l.start.localeCompare(r.start); });

@ -24,7 +24,11 @@ require(["xlsx"], function(XLSX) {
var prez = raw_data.filter(function(row) { return row.terms.some(function(term) { return term.type === "prez"; }); });
/* sort by first presidential term */
prez.forEach(function(row) { row.start = row.terms.find(function(term) {return term.type === "prez"; }).start; });
prez.forEach(function(row) {
row.start = row.terms.find(function(term) {
return term.type === "prez";
}).start;
});
prez.sort(function(l,r) { return l.start.localeCompare(r.start); });
/* flatten objects */
@ -46,7 +50,7 @@ require(["xlsx"], function(XLSX) {
worksheet["!cols"] = [ { wch: max_width } ];
/* create an XLSX file and try to save to Presidents.xlsx */
//XLSX.writeFileXLSX(workbook, "Presidents.xlsx");
XLSX.writeFileXLSX(workbook, "Presidents.xlsx");
console.log(XLSX.utils.sheet_to_csv(worksheet));
});
});

@ -11,6 +11,12 @@ curl -LO https://docs.sheetjs.com/hermes/sheetjs-hermes.cpp
make init
# CMake 4 workaround
rm -rf build_release
cp hermes/CMakeLists.txt hermes/CMakeLists.bak
awk 'NR != 42' <hermes/CMakeLists.bak >hermes/CMakeLists.txt
make init
make sheetjs-hermes
curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js

@ -63,7 +63,8 @@ app.listen(7262, async() => {
EOF
for n in 0.9.1 0.{9..24}; do
for n in 0.9.1 0.{9..25}; do
npm rm --save esbuild
npm i --save esbuild@$n
npm ls | grep esbuild
rm -f out.js