astrojs-breaking-changes

This commit is contained in:
SheetJS 2023-07-31 20:28:19 -04:00
parent 611704e001
commit ba3ffafe47
8 changed files with 216 additions and 111 deletions

@ -1,5 +1,5 @@
---
title: ViteJS
title: ViteJS Spreadsheet Plugins
sidebar_class_name: red
sidebar_label: ViteJS
description: Make static websites from spreadsheets using ViteJS. Seamlessly integrate data into your website using SheetJS. Empower non-technical people to write content from Excel.
@ -9,8 +9,6 @@ sidebar_custom_props:
type: bundler
---
# ViteJS Spreadsheet Plugins
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
@ -27,10 +25,13 @@ plugin and compare a few different data loading strategies.
The ["Complete Demo"](#complete-demo) section includes a complete website powered
by an XLSX spreadsheet.
:::note pass
:::tip pass
This demo covers static asset imports. For processing files in the browser, the
["Bundlers" demo](/docs/demos/frontend/bundler#vite) includes an example.
This demo covers use cases where data is available at build time. The flow is
suitable for end of week or end of month (EOM) reports published in HTML tables
For processing user-submitted files in the browser, the
["Bundlers" demo](/docs/demos/frontend/bundler#vite) is more appropriate.
:::
@ -204,39 +205,10 @@ npm i
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
2) Replace `vite.config.ts` with the following:
2) Download and replace [`vite.config.ts`](pathname:///vitejs/vite.config.ts)
```js title="vite.config.ts"
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { readFileSync } from 'fs';
import { read, utils } from 'xlsx';
export default defineConfig({
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
plugins: [
vue(),
{ // this plugin handles ?sheetjs tags
name: "vite-sheet",
transform(code, id) {
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)}')`;
}
},
{ // this plugin handles ?b64 tags
name: "vite-b64-plugin",
transform(code, id) {
if(!id.match(/\?b64$/)) return;
var path = id.replace(/\?b64/, "");
var data = readFileSync(path, "base64");
return `export default '${data}'`;
}
}
]
});
```bash
curl -O https://docs.sheetjs.com/vitejs/vite.config.ts
```
3) Make a `data` folder and download <https://sheetjs.com/pres.xlsx> :
@ -289,7 +261,9 @@ that page with a web browser.
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. Searching for `Bill Clinton` reveals the following:
Open that script.
Searching for `Bill Clinton` reveals the following:
```
{"Name":"Bill Clinton","Index":42}
@ -351,16 +325,17 @@ 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`.
Open that script. Searching for `Bill Clinton` should yield no results.
source. The code will reference some script like `/assets/index-HASH.js` with
a different hash from the previous test. Open that script.
Searching for `BESSELJ` should match the code:
```
425:"BESSELJ"
```
The SheetJS library is embedded in the final site.
Searching for `Bill Clinton` should yield no results. The SheetJS library is
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.

@ -1,5 +1,6 @@
---
title: AstroJS
title: Let Data Soar with AstroJS
sidebar_label: AstroJS
pagination_prev: demos/net/index
pagination_next: demos/mobile/index
---
@ -7,16 +8,18 @@ pagination_next: demos/mobile/index
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
:::note
AstroJS[^1] is a site generator. AstroJS projects support ViteJS[^2] plugins for
making custom data sources.
This demo uses ["Base64 Loader"](/docs/demos/static/vitejs#base64-loader)
from the ViteJS demo.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
:::
This demo uses AstroJS and SheetJS to pull data from a spreadsheet and display
the content in an HTML table. We'll explore how to load SheetJS libraries during
the AstroJS build process and create static HTML pages.
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 ["Complete Example"](#complete-example) section includes a complete website
powered by Apple Numbers spreadsheets.
The following diagram depicts the workbook waltz:
@ -35,7 +38,7 @@ flowchart LR
:::warning Telemetry
Astro enables telemetry by default. The tool has an option to disable telemetry:
AstroJS enables telemetry by default. The tool has an option to disable telemetry:
```bash
npx astro telemetry disable
@ -45,14 +48,17 @@ npx astro telemetry disable
## Integration
:::note
:::info pass
This demo uses ["Base64 Loader"](/docs/demos/static/vitejs#base64-loader)
from the ViteJS demo.
The ViteJS demo used the query `?b64` to identify files. To play nice with
Astro, this demo matches the file extensions directly.
AstroJS, this demo matches the file extensions directly.
:::
Since Astro performs per-page heavy lifting at build time, it is recommended to
Since AstroJS performs per-page processing at build time, it is recommended to
use the Base64 string loader to get file data and parse with the SheetJS library
in the relevant pages. If the SheetJS operations are performed in frontmatter,
only the results will be added to the generated pages!
@ -67,7 +73,7 @@ import { defineConfig } from 'astro/config';
export default defineConfig({
vite: {
// this tells astro which extensions to handle
assetsInclude: ['**/*.numbers', '**/*.xlsx'],
assetsInclude: ['**/*.numbers', '**/*.xlsx', '**/*.xls', '**/*.xlsb'],
plugins: [
{ // this plugin presents the data as a Base64 string
@ -85,7 +91,7 @@ export default defineConfig({
#### Types
For VSCodium integration, types can be specified in `src/env.d.ts`.
For VSCode and VSCodium integration, types can be specified in `src/env.d.ts`.
This data loader returns Base64 strings:
@ -99,9 +105,18 @@ declare module '*.xlsx' {
const data: string;
export default data;
}
declare module '*.xls' {
const data: string;
export default data;
}
declare module '*.xlsb' {
const data: string;
export default data;
}
// ... (more spreadsheet formats) ...
```
### Astro Frontmatter
### AstroJS Frontmatter
Typically projects store files in `src/pages`. Assuming `pres.numbers` is stored
in the `src/data` directory in the project, the relative import
@ -110,9 +125,20 @@ in the `src/data` directory in the project, the relative import
import b64 from "../data/pres.numbers"
```
will return a Base64 string which can be parsed in the frontmatter. The workbook
object can be post-processed using utility functions. The following example
uses `sheet_to_json` to generate row objects that are rendered as table rows:
will return a Base64 string.
The Base64 string can be parsed in the frontmatter using the SheetJS `read`[^3]
method with the `base64` type. The method returns a SheetJS workbook object[^4].
```js
import { read } from "xlsx";
const wb = read(b64, { type: "base64" });
```
The workbook object can be post-processed using utility functions. The following
example uses the `sheet_to_json`[^5] method to generate row objects from the
first worksheet in the workbook:
```jsx title="src/pages/index.astro"
---
@ -121,7 +147,7 @@ import { read, utils } from "xlsx";
/* parse workbook */
import b64 from "../data/pres.numbers";
const wb = read(b64, {type: "base64"});
const wb = read(b64, { type: "base64" });
/* generate row objects */
interface IPresident {
@ -130,6 +156,14 @@ interface IPresident {
}
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
---
```
### Page Body
The frontmatter used `sheet_to_json` to create an "array of objects"[^6]. Using
standard JSX techniques, the data can be rendered as table rows:
```jsx title="src/pages/index.astro"
<html>
<body>
<h3>Presidents</h3>
@ -144,27 +178,34 @@ const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
</html>
```
When built using `npx astro build`, Astro will perform the conversion and emit
When built using `npx astro build`, AstroJS will perform the conversion and emit
a simple HTML table without any reference to the existing spreadsheet file!
## Complete Example
:::note
This demo was tested on 2023 February 21 using AstroJS `v2.0.14`
This demo was tested on 2023 July 30 using AstroJS `v2.9.6`
:::
0) Disable Astro telemetry:
:::caution pass
AstroJS has introduced a number of breaking changes. If the demo fails, please
[leave a note](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues)
:::
0) Disable AstroJS telemetry:
```bash
npx astro telemetry disable
```
1) Create a new site using the `docs` template:
1) Create a new site using the `starlight` template:
```bash
npm create astro@latest -- --template docs --yes ./sheetjs-astro
npm create astro@latest -- --template starlight --yes ./sheetjs-astro
cd sheetjs-astro
```
@ -181,40 +222,7 @@ curl -Lo src/data/pres.numbers https://sheetjs.com/pres.numbers
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
4) Replace `src/pages/index.astro` with the following:
```jsx title="src/pages/index.astro"
---
/* -- the code in the frontmatter is only run at build time -- */
import { read, utils } from "xlsx";
/* parse workbook */
import b64 from "../data/pres.numbers";
const wb = read(b64, {type: "base64"});
/* generate row objects */
interface IPresident {
Name: string;
Index: number;
}
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
---
<html>
<body>
<h3>Presidents</h3>
<table>
<thead><tr><th>Name</th><th>Index</th></tr></thead>
<tbody>
{data.map(row => (<tr>
<td>{row.Name}</td><td>{row.Index}</td>
</tr>))}
</tbody>
</table>
</body>
</html>
```
5) Append the following lines to `src/env.d.ts`:
4) Append the following lines to `src/env.d.ts`:
```ts title="src/env.d.ts"
/* add to the end of the file */
@ -228,7 +236,9 @@ declare module '*.xlsx' {
}
```
6) Add the highlighted lines to `astro.config.mjs`:
5) Add the highlighted lines to `astro.config.mjs`:
- At the top of the script, import `readFileSync`:
```js title="astro.config.mjs"
// highlight-start
@ -236,8 +246,11 @@ declare module '*.xlsx' {
import { readFileSync } from 'fs';
// highlight-end
import { defineConfig } from 'astro/config';
```
- In the object argument to `defineConfig`, add a `vite` section:
```js title="astro.config.mjs"
export default defineConfig({
// highlight-start
/* this vite section should be added as a property of the object */
@ -257,10 +270,23 @@ export default defineConfig({
]
},
// highlight-end
integrations: [
```
7) Build the static site:
6) Download [`index.astro`](pathname:///astrojs/index.js) and save to
`src/pages/index.astro` (creating a new folder if it does not exist):
```bash
mkdir -p src/pages
curl -o src/pages/index.astro https://docs.sheetjs.com/astrojs/index.astro
```
7) Remove any `index` files in the `src/content` directory:
```bash
rm src/content/index.*
```
8) Build the static site:
```bash
npx astro build
@ -268,7 +294,7 @@ npx astro build
AstroJS will place the generated site in the `dist` subfolder.
8) Start a web server to host the static site:
9) Start a web server to host the static site:
```bash
npx http-server dist
@ -277,3 +303,25 @@ npx http-server dist
Open a web browser and access the displayed URL ( `http://localhost:8080` ).
View the page source and confirm that no JS was added to the page. It only
contains the content from the file in an HTML table.
:::caution pass
**If the site shows a Welcome page, inspect the project!**
When this demo was first written, the `docs` template used `src/pages/index.astro`
During the most recent test, AstroJS removed the `docs` template and introduced
the `starlight` template. This template included `src/content/index.mdx`, which
takes priority over `src/pages/index.astro`.
To resolve this issue, as noted in step 7, remove any `index.*` files in the
`src/content` folder.
:::
[^1]: The [official website](https://astro.build/) uses the name "Astro" but most of the tooling uses the name `@astrojs`.
[^2]: See ["ViteJS" demo](/docs/demos/static/vitejs) for more details and advanced use cases.
[^3]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^4]: See ["SheetJS Data Model"](/docs/csf)
[^5]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
[^6]: See ["Arrays of Objects" in "Utilities"](/docs/api/utilities/array#arrays-of-objects)

@ -1,5 +1,5 @@
---
title: Tauri
title: Data Wrangling in Tauri Apps
sidebar_label: Tauri
description: Build data-intensive desktop apps using Tauri. Seamlessly integrate spreadsheets into your app using SheetJS. Modernize Excel-powered business processes with confidence.
pagination_prev: demos/mobile/index
@ -9,7 +9,7 @@ sidebar_custom_props:
summary: Webview + Rust Backend
---
# Data Wranging in Tauri Apps
# Data Wrangling in Tauri Apps
import current from '/version.js';
import Tabs from '@theme/Tabs';
@ -259,8 +259,8 @@ This demo was tested in the following environments:
|:---------------|:-----|:---------|:-----------|
| macOS 13.4.1 | ARM | `v1.4.0` | 2023-06-29 |
| macOS 13.4.0 | x64 | `v1.4.0` | 2023-06-25 |
| Windows 10 | x64 | `v1.2.3` | 2023-03-18 |
| Linux (HoloOS) | x64 | `v1.2.3` | |
| Windows 10 | x64 | `v1.4.1` | 2023-07-30 |
| Linux (HoloOS) | x64 | `v1.4.1` | 2023-07-30 |
:::
@ -363,7 +363,7 @@ In the same file, look for the `"identifier"` key and replace the value with `co
with the downloaded script.
```bash
curl -L -o src/App.vue https://docs.sheetjs.com/tauri/App.vue
curl -o src/App.vue https://docs.sheetjs.com/tauri/App.vue
```
5) Build the app with
@ -372,7 +372,24 @@ curl -L -o src/App.vue https://docs.sheetjs.com/tauri/App.vue
npm run tauri build
```
At the end, it will print the path to the generated program.
At the end, it will print the path to the generated program. If the program path
is not listed, it is typically found in the `src-tauri/target/release` folder.
:::info pass
During the last Linux test, the build had failed with an error:
```
'openssl/opensslv.h' file not found
```
This error was resolved installing OpenSSL. On Arch Linux and HoloOS:
```bash
sudo pacman -S openssl
```
:::
6) Run the program. The following features should be manually verified:

@ -10,6 +10,13 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
:::tip pass
The ["Import Tutorial"](/docs/getting-started/examples/import) is a gentle
introduction to data import and analysis.
:::
## Parsing Workbooks
### API

@ -0,0 +1,28 @@
---
/* -- the code in the frontmatter is only run at build time -- */
import { read, utils } from "xlsx";
/* parse workbook */
import b64 from "../data/pres.numbers";
const wb = read(b64, {type: "base64"});
/* generate row objects */
interface IPresident {
Name: string;
Index: number;
}
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
---
<html>
<body>
<h3>Presidents</h3>
<table>
<thead><tr><th>Name</th><th>Index</th></tr></thead>
<tbody>
{data.map(row => (<tr>
<td>{row.Name}</td><td>{row.Index}</td>
</tr>))}
</tbody>
</table>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 119 KiB

@ -0,0 +1,30 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { readFileSync } from 'fs';
import { read, utils } from 'xlsx';
export default defineConfig({
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
plugins: [
vue(),
{ // this plugin handles ?sheetjs tags
name: "vite-sheet",
transform(code, id) {
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)}')`;
}
},
{ // this plugin handles ?b64 tags
name: "vite-b64-plugin",
transform(code, id) {
if(!id.match(/\?b64$/)) return;
var path = id.replace(/\?b64/, "");
var data = readFileSync(path, "base64");
return `export default '${data}'`;
}
}
]
});