static-webpack

This commit is contained in:
SheetJS 2023-05-24 21:36:15 -04:00
parent 75697ac27e
commit 0acbc990f0
12 changed files with 535 additions and 75 deletions

@ -1496,6 +1496,13 @@ Click on "Click here to export" to generate a file.
</details>
:::note
The [Webpack section of the Content demo](/docs/demos/static/webpack) covers asset
loaders. They are ideal for static sites pulling data from sheets at build time.
:::
## WMR
WMR works with no caveats.

@ -12,7 +12,7 @@ import CodeBlock from '@theme/CodeBlock';
:::note
This demo covers static asset imports. For processing files in the browser, the
["Bundlers" demo](/docs/demos/bundler#vite) includes an example.
["Bundlers" demo](/docs/demos/frontend/bundler#vite) includes an example.
:::
@ -39,6 +39,22 @@ will be included in the final bundle.
For a pure static site, a plugin can load data into an array of row objects. The
SheetJS work is performed in the plugin. The library is not loaded in the page!
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
buffer(NodeJS\nBuffer)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |vite.config.js\ncustom plugin| buffer
buffer --> |vite.config.js\ncustom plugin| aoo
aoo --> |main.js\nfrontend code| html
```
```js title="vite.config.js"
import { readFileSync } from 'fs';
import { read, utils } from 'xlsx';
@ -77,6 +93,21 @@ This loader pulls in data as a Base64 string that can be read with `XLSX.read`.
While this approach works, it is not recommended since it loads the library in
the front-end site.
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
base64(base64\nstring)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |vite.config.js\ncustom plugin| base64
base64 --> |main.js\nfrontend code| aoo
aoo --> |main.js\nfrontend code| html
```
```js title="vite.config.js"
import { readFileSync } from 'fs';
import { defineConfig } from 'vite';
@ -121,7 +152,7 @@ ${csv}
:::note
This demo was tested on 2023 April 30 against `vite v4.3.3`.
This demo was tested on 2023 May 24 against `vite v4.3.8`.
:::

@ -0,0 +1,304 @@
---
title: Webpack
pagination_prev: demos/net/index
pagination_next: demos/mobile/index
sidebar_custom_props:
type: bundler
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
:::note
This demo covers static asset imports. For processing files in the browser, the
["Bundlers" demo](/docs/demos/frontend/bundler#webpack) includes an example.
:::
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
from Webpack loader scripts.
## Webpack 5 Asset Module
Webpack 5 supports asset modules. With a special option, the loader will receive
NodeJS Buffers that can be parsed. The dev server will even watch the files and
reload the page in development mode!
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
buffer(NodeJS\nBuffer)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |webpack.config.js\ncustom rule| buffer
buffer --> |sheetjs-loader.js\ncustom plugin| aoo
aoo --> |src/index.js\nfrontend code| html
```
### Webpack Config
A special rule should be added to `module.rules`:
```js title="webpack.config.js"
// ...
module.exports = {
// ...
module: {
rules: [
// highlight-start
{
/* `test` matches file extensions */
test: /\.(numbers|xls|xlsx|xlsb)/,
/* use the loader script */
use: [ { loader: './sheetjs-loader' } ]
}
// highlight-end
]
}
};
```
Hot Module Replacement enables reloading when files are updated:
```js title="webpack.config.js"
// ...
module.exports = {
// ...
// highlight-start
devServer: {
static: './dist',
hot: true,
}
// highlight-end
};
```
It is strongly recommended to add an alias to simplify imports:
```js title="webpack.config.js"
// ...
module.exports = {
// ...
// highlight-start
resolve: {
alias: {
/* `~` root of the project */
"~": __dirname
}
},
// highlight-end
};
```
### SheetJS Loader
The SheetJS loader script must export a `raw` property that is set to `true`.
The base export is expected to be the loader function. That function receives
the file contents as a Buffer, which can be parsed with `XLSX.read`. Typically
this script is CommonJS so the `require` form should be used.
The loader in this demo will parse the first worksheet:
```js title="sheetjs-loader.js"
const XLSX = require("xlsx");
function loader(content) {
/* since `loader.raw` is true, `content` is a Buffer */
const wb = XLSX.read(content);
/* pull data from first worksheet */
var data = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return `export default JSON.parse('${JSON.stringify(data)}')`;
}
/* ensure the function receives a Buffer */
loader.raw = true;
module.exports = loader;
```
### Asset Imports
Spreadsheets can be imported using the plugin. Assuming `pres.xlsx` is stored
in the `data` subfolder, `~/data/pres.xlsx` can be imported from any script:
```js title="src/index.js"
import data from '~/data/pres.xlsx';
/* `data` is an array of objects from data/pres.xlsx */
const elt = document.createElement('div');
elt.innerHTML = "<table><tr><th>Name</th><th>Index</th></tr>" +
data.map((row) => `<tr>
<td>${row.Name}</td>
<td>${row.Index}</td>
</tr>`).join("") +
"</table>";
document.body.appendChild(elt);
```
## Webpack 5 Demo
:::note
This demo was last tested on 2023 May 24 against Webpack 5.84.0
:::
### Initial Setup
0) Create a new skeleton project:
```bash
mkdir sheetjs-wp5
cd sheetjs-wp5
npm init -y
npm install webpack@5.84.0 webpack-cli@5.1.1 webpack-dev-server@4.15.0 --save
mkdir -p dist
mkdir -p src
mkdir -p data
```
1) Install the SheetJS NodeJS module:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
2) Save the following to `dist/index.html`:
```html title="dist/index.html"
<!DOCTYPE html>
<html>
<head>
<title>SheetJS + Webpack 5</title>
</head>
<body>
<script src="main.js"></script>
</body>
</html>
```
3) Save the following to `src/index.js`:
```js title="src/index.js"
import data from '~/data/pres.xlsx';
const elt = document.createElement('div');
elt.innerHTML = "<table><tr><th>Name</th><th>Index</th></tr>" +
data.map((row) => `<tr>
<td>${row.Name}</td>
<td>${row.Index}</td>
</tr>`).join("") +
"</table>";
document.body.appendChild(elt);
```
4) Save the following to `webpack.config.js`:
```js title="webpack.config.js"
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
static: './dist',
hot: true,
},
resolve: {
alias: {
"~": __dirname
}
},
module: {
rules: [
{
test: /\.(numbers|xls|xlsx|xlsb)/,
use: [ { loader: './sheetjs-loader' } ]
}
]
}
};
```
5) Save the following to `sheetjs-loader.js`:
```js title="sheetjs-loader.js"
const XLSX = require("xlsx");
function loader(content) {
/* since `loader.raw` is true, `content` is a Buffer */
const wb = XLSX.read(content);
/* pull data from first worksheet */
var data = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return `export default JSON.parse('${JSON.stringify(data)}')`;
}
/* ensure the function receives a Buffer */
loader.raw = true;
module.exports = loader;
```
6) Download <https://sheetjs.com/pres.xlsx> and save to the `data` folder:
```bash
curl -L -o data/pres.xlsx https://sheetjs.com/pres.xlsx
```
### Live Reload Test
7) Open the test file `data/pres.xlsx` in a spreadsheet editor like Excel.
8) Start the development server:
```bash
npx webpack serve --mode=development
```
The terminal will print URLs for the development server:
```
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
```
9) Open the `Loopback` address (`http://localhost:8080`) in a web browser.
It should display a table of Presidents with "Name" and "Index" columns
10) Add a new row to the spreadsheet and save the file.
Upon saving, the page should refresh with the new data.
### Static Site Test
11) Stop Webpack and build the site:
```bash
npx webpack --mode=production
```
The final site will be placed in the `dist` folder.
12) Start a local web server to host the `dist` folder:
```bash
npx http-server dist
```
The command will print a list of URLs.
13) Open one of the URLs printed in the previous step (`http://localhost:8080`)
and confirm that the same data is displayed.
To verify that the page is independent of the spreadsheet, make some changes to
the file and save. The page will not automatically update.
To verify that the data was added to the page, append `main.js` to the URL
(`http://localhost:8080/main.js`) and view the source. The source will include
president names. It will not include SheetJS library references!

@ -12,6 +12,21 @@ Eleventy is a static site generator.
The [NodeJS module](/docs/getting-started/installation/nodejs) can be loaded in
`.eleventy.js` and used in custom data file format parsers.
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
buffer(NodeJS\nBuffer)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |.eleventy.js\ncustom parser| buffer
buffer --> |.eleventy.js\ncustom parser| aoo
aoo --> |index.njk\ntemplate| html
```
## Integration Details
### Data File Parser

@ -25,6 +25,21 @@ The following deployments were tested:
Nuxt Content v1 is designed to work with Nuxt v2.
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
buffer(NodeJS\nBuffer)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |nuxt.config.js\ncustom parser| buffer
buffer --> |nuxt.config.js\ncustom parser| aoo
aoo --> |index.vue\ntemplate| html
```
### Configuration
Through an override in `nuxt.config.js`, Nuxt Content will use custom parsers.
@ -246,6 +261,21 @@ will not change.
Nuxt Content v2 is designed to work with Nuxt v3.
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
buffer(NodeJS\nBuffer)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |custom module\ntransformer| buffer
buffer --> |custom module\ntransformer| aoo
aoo --> |index.vue\nContentRenderer| html
```
### Overview
Nuxt Content `v2` supports custom transformers for controlling data. Although

@ -27,12 +27,12 @@ flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
base64(base64\nstring)
aoa(array of\nobjects)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |vite.config.js\ndata loader| base64
base64 --> |+page.server.js\nload function| aoa
aoa --> |+page.svelte\ncomponent| html
base64 --> |+page.server.js\nload function| aoo
aoo --> |+page.svelte\ncomponent| html
```
## Integration

@ -18,6 +18,21 @@ Astro is a site generator. Astro projects use ViteJS under the hood. They expose
project configuration through the `vite` property in `astro.config.mjs`. The
[ViteJS demo](/docs/demos/static/vitejs) examples work as expected!
The following diagram depicts the workbook waltz:
```mermaid
flowchart LR
file[(workbook\nfile)]
subgraph SheetJS operations
base64(base64\nstring)
aoo(array of\nobjects)
end
html{{HTML\nTABLE}}
file --> |astro.config.mjs\nvite data loader| base64
base64 --> |index.astro\nfrontmatter| aoo
aoo --> |index.astro\ntemplate body| html
```
## Integration
:::note

@ -60,6 +60,7 @@ npx @capacitor/cli telemetry
:::caution
The latest version of Ionic uses CapacitorJS. These notes are for Cordova apps.
The [CapacitorJS demo](/docs/demos/mobile/capacitor) covers CapacitorJS apps.
:::

@ -17,68 +17,6 @@ it is feasible to build command-line tools for various workflows.
This demo covers a number of strategies for building standalone processors. The
goal is to generate CSV output from an arbitrary spreadsheet file.
## V8
The [V8](/docs/demos/engines/v8) demo covers standalone programs that embed the
V8 engine. This demo uses the Rust integration to generate a command line tool.
<details><summary><b>Tested Deployments</b> (click to show)</summary>
This demo was last tested in the following deployments:
| Architecture | V8 Version | Date |
|:-------------|:-------------|:-----------|
| `darwin-x64` | `11.4.183.2` | 2023-05-22 |
</details>
0) Make a new folder for the project:
```bash
mkdir sheetjs2csv
cd sheetjs2csv
```
1) Download the following scripts:
- [`Cargo.toml`](pathname:///cli/Cargo.toml)
- [`snapshot.rs`](pathname:///cli/snapshot.rs)
- [`sheet2csv.rs`](pathname:///cli/sheet2csv.rs)
```bash
curl -LO https://docs.sheetjs.com/cli/Cargo.toml
curl -LO https://docs.sheetjs.com/cli/snapshot.rs
curl -LO https://docs.sheetjs.com/cli/sheet2csv.rs
```
2) Download the [standalone build](/docs/getting-started/installation/standalone):
<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
</CodeBlock>
3) Build the V8 snapshot:
```bash
cargo build --bin snapshot
cargo run --bin snapshot
```
4) Build `sheet2csv`:
```bash
cargo build --release --bin sheet2csv
mv target/release/sheet2csv .
```
5) Download the test file <https://sheetjs.com/pres.numbers>:
```bash
curl -LO https://sheetjs.com/pres.numbers
```
Test by running `./sheet2csv pres.numbers`
## NodeJS
There are a few popular tools for compiling NodeJS scripts to CLI programs.
@ -200,6 +138,88 @@ example, on an Intel Mac, `nexe` generates `xlsx-cli` so the command is:
./xlsx-cli pres.numbers
```
## V8
The [V8](/docs/demos/engines/v8) demo covers standalone programs that embed the
V8 engine. This demo uses the Rust integration to generate a command line tool.
<details><summary><b>Tested Deployments</b> (click to show)</summary>
This demo was last tested in the following deployments:
| Architecture | V8 Version | Date |
|:-------------|:-------------|:-----------|
| `darwin-x64` | `11.4.183.2` | 2023-05-22 |
| `linux-x64` | `11.4.183.2` | 2023-05-23 |
| `win32-x64` | `11.4.183.2` | 2023-05-23 |
</details>
0) Make a new folder for the project:
```bash
mkdir sheetjs2csv
cd sheetjs2csv
```
1) Download the following scripts:
- [`Cargo.toml`](pathname:///cli/Cargo.toml)
- [`snapshot.rs`](pathname:///cli/snapshot.rs)
- [`sheet2csv.rs`](pathname:///cli/sheet2csv.rs)
```bash
curl -LO https://docs.sheetjs.com/cli/Cargo.toml
curl -LO https://docs.sheetjs.com/cli/snapshot.rs
curl -LO https://docs.sheetjs.com/cli/sheet2csv.rs
```
2) Download the [standalone build](/docs/getting-started/installation/standalone):
<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
</CodeBlock>
3) Build the V8 snapshot:
```bash
cargo build --bin snapshot
cargo run --bin snapshot
```
4) Build `sheet2csv` (`sheet2csv.exe` in Windows):
```bash
cargo build --release --bin sheet2csv
```
5) Download the test file <https://sheetjs.com/pres.numbers>:
```bash
curl -LO https://sheetjs.com/pres.numbers
```
6) Test the application:
<Tabs groupId="os">
<TabItem value="unix" label="Linux/MacOS">
```bash
mv target/release/sheet2csv .
./sheet2csv pres.numbers
```
</TabItem>
<TabItem value="win" label="Windows">
```bash
mv target/release/sheet2csv.exe .
./sheet2csv pres.numbers
```
</TabItem>
</Tabs>
## Deno
`deno compile` generates a standalone executable that includes the entire JS

@ -289,6 +289,14 @@ fn eval_code_ab(scope: &mut v8::HandleScope, code: &str) -> Vec<u8> {
:::note
This demo was last tested in the following deployments:
| Architecture | V8 Crate | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `0.71.2` | 2023-05-22 |
| `linux-x64` | `0.71.2` | 2023-05-23 |
| `win32-x64` | `0.71.2` | 2023-05-23 |
This demo was last tested on 2023 May 22 against `v8` crate version `0.71.2`
:::

@ -17,8 +17,8 @@ parsed and evaluated in a JSC context.
:::warning Platform Limitations
JavaScriptCore is primarily deployed in MacOS and iOS applications. There is
some experimental support through the Bun runtime, but production applications
intending to support Windows / Linux / Android should try to embed V8.
some experimental support through the Bun runtime, but apps intending to support
Windows / Linux / Android should try to embed [V8](/docs/demos/engines/v8).
:::
@ -77,6 +77,32 @@ context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectPro
context.evaluateScript("var wb = XLSX.read(payload, {type:'binary'});");
```
<details><summary><b>Direct Read</b> (click to show)</summary>
`Uint8Array` data can be passed directly, skipping string encoding and decoding:
```swift
let url = URL(fileURLWithPath: file)
var data: Data! = try Data(contentsOf: url);
let count = data.count;
/* Note: the operations must be performed in the closure! */
let wb: JSValue! = data.withUnsafeMutableBytes { (dataPtr: UnsafeMutableRawBufferPointer) in
// highlight-next-line
let ab: JSValue! = JSValue(jsValueRef: JSObjectMakeTypedArrayWithBytesNoCopy(context.jsGlobalContextRef, kJSTypedArrayTypeUint8Array, dataPtr.baseAddress, count, nil, nil, nil), in: context)
/* prepare options argument */
context.evaluateScript(String(format: "var readopts = {type:'array', dense:true}"));
let readopts: JSValue = context.objectForKeyedSubscript("readopts");
/* call XLSX.read */
let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX");
let readfunc: JSValue = XLSX.objectForKeyedSubscript("read");
return readfunc.call(withArguments: [ab, readopts]);
}
```
For broad compatibility with Swift versions, the demo uses the String method.
</details>
### Writing Files
When writing to binary string in JavaScriptCore, the result should be stored in

@ -34,17 +34,13 @@ const config = {
({
docs: {
sidebarPath: require.resolve('./sidebars.js'),
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
// editUrl:
// 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
// editUrl: 'https://git.sheetjs.com/sheetjs/docs.sheetjs.com/src/branch/master/docz',
},
//blog: {
// showReadingTime: true,
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
// editUrl:
// 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/',
// editUrl: 'https://git.sheetjs.com/sheetjs/docs.sheetjs.com/src/branch/master/docz/',
//},
theme: {
customCss: require.resolve('./src/css/custom.css'),
@ -60,6 +56,13 @@ const config = {
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
mermaid: {
options: {
themeVariables: {
edgeLabelBackground: ""
}
}
},
navbar: {
title: 'SheetJS CE Docs',
logo: {