ViteJS Static Demo refresh

This commit is contained in:
SheetJS 2024-06-02 20:59:49 -04:00
parent 1a80a55e76
commit 14bd6a4ed0
11 changed files with 503 additions and 73 deletions

@ -86,16 +86,16 @@
<Row>
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/cli/nodesea#complete-example"><Data ss:Type="String">NodeJS SEA</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
</Row>
<Row>
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/cli/bunsea#complete-example"><Data ss:Type="String">Bun SEA</Data></Cell>
<Cell ss:StyleID="s20" ss:HRef="/docs/demos/cli/bunsea#complete-example"><Data ss:Type="String">BunJS SEA</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>

@ -12,15 +12,15 @@ sidebar_custom_props:
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
[ViteJS](https://vitejs.dev/) is a modern build tool for generating static sites.
It has a robust JavaScript-powered plugin system[^1]
[ViteJS](https://vitejs.dev/) is a build tool for generating static websites. It
has a robust JavaScript-powered plugin system[^1].
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo uses ViteJS and SheetJS to pull data from a spreadsheet and display
the content in an HTML table. We'll explore how to load SheetJS in a ViteJS
plugin and compare a few different data loading strategies.
plugin and evaluate data loading strategies.
The ["Complete Demo"](#complete-demo) section creates a complete website powered
by a XLSX spreadsheet.
@ -32,16 +32,97 @@ suitable for end of week or end of month (EOM) reports published in HTML tables.
For processing user-submitted files in the browser, the
[ViteJS "Bundlers" demo](/docs/demos/frontend/bundler/vitejs) shows client-side
bundling of the SheetJS library. The ["ReactJS" demo](/docs/demos/frontend/react)
bundling of SheetJS libraries. The ["ReactJS" demo](/docs/demos/frontend/react)
shows example sites using ViteJS with the ReactJS starter.
:::
## Plugins
ViteJS supports static asset imports[^2], but the default raw loader interprets data
as UTF-8 strings. This corrupts binary formats like XLSX and XLS, but a custom
loader can override the default behavior.
ViteJS supports static asset imports[^2], but the default raw loader interprets
data as UTF-8 strings. This corrupts binary formats including XLSX and XLS. A
custom loader can bypass the raw loader and directly read files.
Since a custom loader must be used, some data processing work can be performed
by the loader. Three approaches are explored in this demo.
The following diagrams show the ViteJS data flow. The pink "Main Script import"
boxes represent the division between the loader and the main script. The green
"SheetJS Operations" boxes represent the steps performed by SheetJS libraries.
<table>
<tr>
<th>[HTML](#html-plugin)</th>
<th>[Data](#pure-data-plugin)</th>
<th>[Base64](#base64-plugin)</th>
</tr>
<tr>
<td style={{verticalAlign: "top"}}>
```mermaid
flowchart TB
file[(workbook\nfile)]
buffer(NodeJS\nBuffer)
sheetjs[[SheetJS Operations]]
tabeller{{HTML\nString}}
handoff[[Main Script import]]
html{{HTML\nTABLE}}
style handoff fill:#FFC7CE
style sheetjs fill:#C6EFCE
file --> buffer
buffer --> sheetjs
sheetjs --> tabeller
tabeller --> handoff
handoff --------> html
```
</td>
<td style={{verticalAlign: "top"}}>
```mermaid
flowchart TB
file[(workbook\nfile)]
buffer(NodeJS\nBuffer)
sheetjs[[SheetJS Operations]]
aoo(array of\nobjects)
handoff[[Main Script import]]
import(array of\nobjects)
html{{HTML\nTABLE}}
style handoff fill:#FFC7CE
style sheetjs fill:#C6EFCE
file --> buffer
buffer --> sheetjs
sheetjs --> aoo
aoo --> handoff
handoff ------> import
import --> html
```
</td>
<td style={{verticalAlign: "top"}}>
```mermaid
flowchart TB
file[(workbook\nfile)]
base64(Base64\nString)
handoff[[Main Script import]]
import(Base64\nString)
sheetjs[[SheetJS Operations]]
aoo(array of\nobjects)
html{{HTML\nTABLE}}
style handoff fill:#FFC7CE
style sheetjs fill:#C6EFCE
file --> base64
base64 ------> handoff
handoff --> import
import --> sheetjs
sheetjs --> aoo
aoo --> html
```
</td>
</tr>
</table>
For simple tables of data, ["Pure Data Plugin"](#pure-data-plugin) is strongly
recommended. The file processing is performed at build time and the generated
@ -51,6 +132,9 @@ For more complex parsing or display logic, ["Base64 Plugin"](#base64-plugin) is
preferable. Since the raw parsing logic is performed in the page, the library
will be included in the final bundle.
The ["HTML Plugin"](#html-plugin) generates HTML in the loader script. The
SheetJS HTML writer renders merged cells and other features.
### Pure Data Plugin
For a pure static site, a plugin can load data into an array of row objects. The
@ -72,7 +156,7 @@ flowchart LR
```
This ViteJS plugin will read spreadsheets using the SheetJS `read` method[^3]
and generate arrays of row objects with `sheet_to_json`[^4]:
and generate arrays of row objects with the SheetJS `sheet_to_json`[^4] method:
```js title="vite.config.js"
import { readFileSync } from 'fs';
@ -89,13 +173,23 @@ export default defineConfig({
if(!id.match(/\?sheetjs$/)) return;
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return `export default JSON.parse('${JSON.stringify(data)}')`;
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
}
}
]
});
```
:::info pass
ViteJS plugins are expected to return strings representing ECMAScript modules.
The plugin uses `JSON.stringify` to encode the array of objects. The generated
string is injected into the new module code. When ViteJS processes the module,
`JSON.parse` recovers the array of objects.
:::
In frontend code, the loader will look for all modules with a `?sheetjs`
query string. The default export is an array of row objects.
@ -115,9 +209,75 @@ document.querySelector('#app').innerHTML = `<table>
</table>`;
```
### HTML Plugin
A plugin can generate raw HTML strings that can be added to a page. The SheetJS
libraries are used in the plugin but will not be added to the site.
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
buffer(NodeJS\nBuffer)
tavolo{{HTML\nString}}
end
html{{HTML\nTABLE}}
file --> |vite.config.js\ncustom plugin| buffer
buffer --> |vite.config.js\ncustom plugin| tavolo
tavolo --> |main.js\nfrontend code| html
```
This ViteJS plugin will read spreadsheets using the SheetJS `read` method[^5]
and generate HTML using the SheetJS `sheet_to_html`[^6] method:
```js title="vite.config.js"
import { readFileSync } from 'fs';
import { read, utils } from 'xlsx';
import { defineConfig } from 'vite';
export default defineConfig({
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
plugins: [
{ // this plugin handles ?html tags
name: "vite-sheet-html",
transform(code, id) {
if(!id.match(/\?html/)) return;
var wb = read(readFileSync(id.replace(/\?html/, "")));
var html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
return (`export default JSON.parse('${JSON.stringify(html).replace(/\\/g, "\\\\")}')`);
}
}
]
});
```
:::info pass
ViteJS plugins are expected to return strings representing ECMAScript modules.
The plugin uses `JSON.stringify` to encode the HTML string. The generated string
is injected into the new module code. When ViteJS processes the module,
`JSON.parse` recovers the original HTML string.
:::
In frontend code, the loader will look for all modules with a `?html` query
string. The default export is a string that can be directly added to the page.
The following example script sets the `innerHTML` property of the container:
```js title="main.js"
import html from './data/pres.xlsx?html';
document.querySelector('#app').innerHTML = html;
```
### Base64 Plugin
This plugin pulls in data as a Base64 string that can be read with `read`[^5].
This plugin pulls in data as a Base64 string that can be read with `read`[^7].
While this approach works, it is not recommended since it loads the library in
the front-end site.
@ -161,7 +321,7 @@ export default defineConfig({
```
When importing using the `b64` query, the raw Base64 string will be exposed.
`read` will process the Base64 string using the `base64` input type[^6]:
`read` will process the Base64 string using the `base64` input type[^8]:
```js title="main.js"
import { read, utils } from "xlsx";
@ -187,22 +347,22 @@ document.querySelector('#app').innerHTML = `<table>
## Complete Demo
The demo walks through the process of creating a new ViteJS website from scratch.
A Git repository with the completed site can be cloned[^9].
:::note Tested Deployments
This demo was tested in the following environments:
| ViteJS | Date |
|:---------|:-----------|
| `5.0.5` | 2023-12-04 |
| `4.5.0` | 2023-12-04 |
| `3.2.7` | 2023-12-04 |
| `2.9.16` | 2023-12-04 |
| `5.2.12` | 2024-06-02 |
| `4.5.3` | 2024-06-02 |
| `3.2.10` | 2024-06-02 |
| `2.9.18` | 2024-06-02 |
:::
The demo walks through the process of creating a new ViteJS website from scratch.
A Git repository with the completed site can be cloned[^7].
### Initial Setup
1) Create a new site with the `vue-ts` template and install the SheetJS package:
@ -275,9 +435,30 @@ npx http-server dist/
The terminal will display a URL, typically `http://127.0.0.1:8080` . Access
that page with a web browser.
:::caution pass
When this demo was tested against ViteJS `2.9.18`, the build failed:
```
src/App.vue:8:3 - error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
8 <img alt="Vue logo" src="./assets/logo.png" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
**As it affects the project template, this is a bug in ViteJS.**
The simplest workaround is to force upgrade the `vue-tsc` dependency:
```bash
npm i vue-tsc@latest
```
:::
7) To confirm that only the raw data is present in the page, view the page
source. The code will reference some script like `/assets/index-HASH.js`.
Open that script.
source. The code will reference a script `/assets/index-HASH.js` where `HASH` is
a string of characters. Open that script.
Searching for `Bill Clinton` reveals the following:
@ -291,11 +472,11 @@ included in the final site!
:::info pass
ViteJS also supports "Server-Side Rendering". In SSR, only the HTML table
would be added to the final page. Details are covered in the ViteJS docs[^8].
would be added to the final page. Details are covered in the ViteJS docs[^10].
:::
### Base64 Test
### HTML Test
8) Run the dev server:
@ -303,10 +484,88 @@ would be added to the final page. Details are covered in the ViteJS docs[^8].
npm run dev
```
Open a browser window to the displayed URL.
Open a browser window to the displayed URL (typically `http://localhost:5173` )
9) Replace the component `src/components/HelloWorld.vue` with:
```html title="src/components/HelloWorld.vue"
<script setup lang="ts">
// @ts-ignore
import html from '../../data/pres.xlsx?html';
</script>
<template>
<div v-html="html"></div>
</template>
```
Save and refresh the page. A data table should be displayed
10) Stop the dev server and build the site
```bash
npm run build
npx http-server dist/
```
The terminal will display a URL, typically `http://127.0.0.1:8080` . Access
that page with a web browser.
:::caution pass
When this demo was tested against ViteJS `2.9.18`, the build failed:
```
src/App.vue:8:3 - error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
8 <img alt="Vue logo" src="./assets/logo.png" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
**As it affects the project template, this is a bug in ViteJS.**
The simplest workaround is to force upgrade the `vue-tsc` dependency:
```bash
npm i vue-tsc@latest
```
:::
11) To confirm that only the raw HTML is present in the page, view the page
source. The code will reference a script `/assets/index-HASH.js` where `HASH` is
a string of characters. Open that script.
Searching for `Bill Clinton` reveals the following encoded HTML element:
```
<td data-t=\\"s\\" data-v=\\"Bill Clinton\\" id=\\"sjs-A2\\">Bill Clinton</td>
```
Searching for `BESSELJ` should reveal no results. The SheetJS scripts are not
included in the final site!
:::info pass
The HTML code is still stored in a script and is injected dynamically.
ViteJS "Server-Side Rendering" offers the option to render the site at build
time, ensuring that the HTML table is directly added to the page.
:::
### Base64 Test
12) Run the dev server:
```bash
npm run dev
```
Open a browser window to the displayed URL (typically `http://localhost:5173` )
13) Replace the component `src/components/HelloWorld.vue` with:
```html title="src/components/HelloWorld.vue"
<script setup lang="ts">
// @ts-ignore
@ -330,7 +589,7 @@ const data = utils.sheet_to_json<IPresident>(ws);
</template>
```
10) Stop the dev server and build the site
14) Stop the dev server and build the site
```bash
npm run build
@ -340,9 +599,30 @@ npx http-server dist/
The terminal will display a URL ( `http://127.0.0.1:8080` ). Access that page
with a web browser.
11) To confirm that the object data is not present in the page, view the page
source. The code will reference some script like `/assets/index-HASH.js` with
a different hash from the previous test. Open that script.
:::caution pass
When this demo was tested against ViteJS `2.9.18`, the build failed:
```
src/App.vue:8:3 - error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
8 <img alt="Vue logo" src="./assets/logo.png" />
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
**As it affects the project template, this is a bug in ViteJS.**
The simplest workaround is to force upgrade the `vue-tsc` dependency:
```bash
npm i vue-tsc@latest
```
:::
15) To confirm that the object data is not present in the page, view the page
source. The code will reference a script `/assets/index-HASH.js` where `HASH` is
a string of characters. Open that script.
Searching for `BESSELJ` should match the code:
@ -356,8 +636,10 @@ embedded in the final site and the data is parsed when the page is loaded.
[^1]: See ["Using Plugins"](https://vitejs.dev/guide/using-plugins.html) in the ViteJS documentation.
[^2]: See ["Static Asset Handling"](https://vitejs.dev/guide/assets.html) in the ViteJS documentation.
[^3]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^4]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
[^4]: See [`sheet_to_html` in "Utilities"](/docs/api/utilities/html#html-table-output)
[^5]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^6]: See [the "base64" type in "Reading Files"](/docs/api/parse-options#input-type)
[^7]: See [`SheetJS/sheetjs-vite`](https://git.sheetjs.com/sheetjs/sheetjs-vite/) on the SheetJS git server.
[^8]: See ["Server-Side Rendering"](https://vitejs.dev/guide/ssr.html) in the ViteJS documentation.
[^6]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
[^7]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^8]: See [the "base64" type in "Reading Files"](/docs/api/parse-options#input-type)
[^9]: See [`examples/sheetjs-vite`](https://git.sheetjs.com/examples/sheetjs-vite/) on the SheetJS git server.
[^10]: See ["Server-Side Rendering"](https://vitejs.dev/guide/ssr.html) in the ViteJS documentation.

@ -159,6 +159,7 @@ This demo was tested in the following deployments:
| Architecture | NodeJS | Date |
|:-------------|:----------|:-----------|
| `darwin-x64` | `22.2.0` | 2024-05-28 |
| `darwin-arm` | `22.2.0` | 2024-05-29 |
| `win10-x64` | `20.12.0` | 2024-03-26 |
| `win11-x64` | `20.13.1` | 2024-05-22 |
| `linux-x64` | `20.11.1` | 2024-03-18 |

@ -80,6 +80,7 @@ This demo was last tested in the following deployments:
| Architecture | BunJS | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `1.1.10` | 2024-05-28 |
| `darwin-arm` | `1.1.10` | 2024-05-29 |
:::

@ -14,7 +14,16 @@ export default defineConfig({
if(!id.match(/\?sheetjs$/)) return;
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return `export default JSON.parse('${JSON.stringify(data)}')`;
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
}
},
{ // this plugin handles ?html tags
name: "vite-sheet-html",
transform(code, id) {
if(!id.match(/\?html/)) return;
var wb = read(readFileSync(id.replace(/\?html/, "")));
var html = utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
return (`export default JSON.parse('${JSON.stringify(html).replace(/\\/g, "\\\\")}')`);
}
},
{ // this plugin handles ?b64 tags

@ -81,16 +81,16 @@ const express = require('express');
const app = express();
app.use(express.static('./'));
app.listen(7262, async() => {
await new Promise((res,rej) => setTimeout(res, 1000));
await new Promise((res,rej) => setTimeout(res, 1000));
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on("console", msg => console.log("PAGE LOG:", msg.text()));
await page.setViewport({width: 1920, height: 1080});
await page.goto('http://localhost:7262/');
await page.click("#xport");
await new Promise((res,rej) => setTimeout(res, 1000));
await new Promise((res,rej) => setTimeout(res, 1000));
await browser.close();
process.exit();
process.exit();
});
EOF

@ -68,7 +68,7 @@ const express = require('express');
const app = express();
app.use(express.static('./'));
app.listen(7262, async() => {
await new Promise((res,rej) => setTimeout(res, 1000));
await new Promise((res,rej) => setTimeout(res, 1000));
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on("console", msg => console.log("PAGE LOG:", msg.text()));
@ -77,12 +77,12 @@ app.listen(7262, async() => {
/* wait for requirejs to request xlsx.full.min.js */
await page.waitForRequest(request => request.url().indexOf('xlsx.full.min.js') !== -1);
await new Promise((res,rej) => setTimeout(res, 1000));
await new Promise((res,rej) => setTimeout(res, 1000));
await page.click("#xport");
await new Promise((res,rej) => setTimeout(res, 1000));
await new Promise((res,rej) => setTimeout(res, 1000));
await browser.close();
process.exit();
process.exit();
});
EOF
@ -92,16 +92,16 @@ const express = require('express');
const app = express();
app.use(express.static('./'));
app.listen(7262, async() => {
await new Promise((res,rej) => setTimeout(res, 1000));
await new Promise((res,rej) => setTimeout(res, 1000));
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on("console", msg => console.log("PAGE LOG:", msg.text()));
await page.setViewport({width: 1920, height: 1080});
await page.goto('http://localhost:7262/optimized.html');
await page.click("#xport");
await new Promise((res,rej) => setTimeout(res, 1000));
await new Promise((res,rej) => setTimeout(res, 1000));
await browser.close();
process.exit();
process.exit();
});
EOF

@ -21,10 +21,10 @@ curl -LO https://sheetjs.com/pres.xlsx
curl -LO https://docs.sheetjs.com/nashorn/SheetJSNashorn.java
for n in {17..22}; do
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
rm -fr SheetJSNashorn.class SheetJSNashorn.jar sheethorn
javac SheetJSNashorn.java
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
rm -fr SheetJSNashorn.class SheetJSNashorn.jar sheethorn
javac SheetJSNashorn.java
java -cp ".:js-scriptengine-24.0.1.jar:js-language-24.0.1.jar:polyglot-24.0.1.jar:collections-24.0.1.jar:truffle-api-24.0.1.jar:nativeimage-24.0.1.jar:icu4j-24.0.1.jar:regex-24.0.1.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx

@ -19,31 +19,31 @@ curl -L -o asm-util-9.5.jar "https://search.maven.org/remotecontent?filepath=org
# Standalone Nashorn
for n in {15..22}; do
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
rm -fr SheetJSNashorn.class SheetJSNashorn.jar sheethorn
javac SheetJSNashorn.java
java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar SheetJSNashorn pres.xlsx
jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js
mkdir -p sheethorn
cp *.jar pres.xlsx sheethorn
cd sheethorn
java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar:SheetJSNashorn.jar SheetJSNashorn pres.xlsx
cd -
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
rm -fr SheetJSNashorn.class SheetJSNashorn.jar sheethorn
javac SheetJSNashorn.java
java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar SheetJSNashorn pres.xlsx
jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js
mkdir -p sheethorn
cp *.jar pres.xlsx sheethorn
cd sheethorn
java -cp .:asm-9.5.jar:asm-tree-9.5.jar:asm-commons-9.5.jar:asm-analysis-9.5.jar:asm-util-9.5.jar:nashorn-core-15.4.jar:SheetJSNashorn.jar SheetJSNashorn pres.xlsx
cd -
done
# Built-in Nashorn
for n in 1.8 {9..14}; do
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
rm -fr SheetJSNashorn.class SheetJSNashorn.jar sheethorn
javac SheetJSNashorn.java
java SheetJSNashorn pres.xlsx
jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js
mkdir -p sheethorn
cp *.jar pres.xlsx sheethorn
cd sheethorn
java -cp .:SheetJSNashorn.jar SheetJSNashorn pres.xlsx
cd -
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
rm -fr SheetJSNashorn.class SheetJSNashorn.jar sheethorn
javac SheetJSNashorn.java
java SheetJSNashorn pres.xlsx
jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js
mkdir -p sheethorn
cp *.jar pres.xlsx sheethorn
cd sheethorn
java -cp .:SheetJSNashorn.jar SheetJSNashorn pres.xlsx
cd -
done

@ -43,8 +43,8 @@ public class SheetJSRhino {
EOF
for n in 1.8 {9..22}; do
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
find . -name \*.class | while read x; do rm $x; done
javac -cp ".:rhino.jar" SheetJSRhino.java

137
tests/static-vite.sh Executable file

@ -0,0 +1,137 @@
#!/bin/bash
# https://docs.sheetjs.com/docs/demos/static/vitejs
# This script builds the Pure Data test and Base64 test. It does not test HMR!
cd /tmp
rm -rf sheetjs-vite-static
mkdir sheetjs-vite-static
cd sheetjs-vite-static
for n in {2..5}; do
npm create -y vite@$n sheetjs-vite-$n -- --template vue-ts
cd sheetjs-vite-$n
npm i
npm i --save https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz
npm i --save puppeteer express@4
if [[ "$n" == "2" ]]; then
# The default vitejs2 + vuejs project does not build
#
# src/App.vue:8:3 - error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
#
# 8 <img alt="Vue logo" src="./assets/logo.png" />
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Before the TS errors, there is a message:
# Please update to v0.35.0 or higher for TypeScript version: 4.9.5
#
# Forcefully upgrading `vue-tsc` appears to be innocuous.
npm i --save vue-tsc@latest
fi
curl -O https://docs.sheetjs.com/vitejs/vite.config.ts
mkdir -p data
curl -L -o data/pres.xlsx https://docs.sheetjs.com/pres.xlsx
cat >test.cjs <<EOF
const puppeteer = require('puppeteer');
const express = require('express');
const app = express();
app.use(express.static('./dist/'));
app.listen(7262, async() => {
await new Promise((res,rej) => setTimeout(res, 1000));
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on("console", msg => console.log("PAGE LOG:", msg.text()));
await page.setViewport({width: 1920, height: 1080});
await page.goto('http://localhost:7262/');
await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-0.20.2/package/dist/xlsx.full.min.js' });
await new Promise((res,rej) => setTimeout(res, 1000));
const csv = await page.evaluate(() => {
const tbl = document.querySelector('table');
const ws = XLSX.utils.table_to_sheet(tbl);
return XLSX.utils.sheet_to_csv(ws);
});
console.log(csv);
await browser.close();
process.exit();
});
EOF
## Pure Data Test
cat >src/components/HelloWorld.vue <<EOF
<script setup lang="ts">
// @ts-ignore
import data from '../../data/pres.xlsx?sheetjs';
</script>
<template>
<table>
<tr><th>Name</th><th>Index</th></tr>
<tr v-for="(row,R) in data" v-bind:key="R">
<td>{{row.Name}}</td>
<td>{{row.Index}}</td>
</tr>
</table>
</template>
EOF
npm run build
npm ls | grep "vite@"
node test.cjs
# Expected output: CSV contents of first sheet
echo "Clinton" $(grep Clinton dist/assets/*.js | wc -l) "BESSELJ" $(grep BESSELJ dist/assets/*.js | wc -l)
# Expected output: Clinton 1 BESSELJ 0
## HTML Test
cat >src/components/HelloWorld.vue <<EOF
<script setup lang="ts">
// @ts-ignore
import html from '../../data/pres.xlsx?html';
</script>
<template>
<div v-html="html"></div>
</template>
EOF
npm run build
npm ls | grep "vite@"
node test.cjs
# Expected output: CSV contents of first sheet
echo "Clinton" $(grep Clinton dist/assets/*.js | wc -l) "BESSELJ" $(grep BESSELJ dist/assets/*.js | wc -l)
# Expected output: Clinton 1 BESSELJ 0
## Base64 Test
cat >src/components/HelloWorld.vue <<EOF
<script setup lang="ts">
// @ts-ignore
import b64 from '../../data/pres.xlsx?b64';
import { read, utils } from "xlsx";
/* parse workbook and convert first sheet to row array */
const wb = read(b64);
const ws = wb.Sheets[wb.SheetNames[0]];
interface IPresident { Name: string; Index: number; };
const data = utils.sheet_to_json<IPresident>(ws);
</script>
<template>
<table>
<tr><th>Name</th><th>Index</th></tr>
<tr v-for="(row,R) in data" v-bind:key="R">
<td>{{row.Name}}</td>
<td>{{row.Index}}</td>
</tr>
</table>
</template>
EOF
npm run build
npm ls | grep "vite@"
node test.cjs
# Expected output: CSV contents of first sheet
echo "Clinton" $(grep Clinton dist/assets/*.js | wc -l) "BESSELJ" $(grep BESSELJ dist/assets/*.js | wc -l)
# Expected output: Clinton 0 BESSELJ 1
cd -
done