2023-02-18 02:33:30 +00:00
|
|
|
---
|
2023-08-01 00:28:19 +00:00
|
|
|
title: Let Data Soar with AstroJS
|
|
|
|
sidebar_label: AstroJS
|
2023-02-28 11:40:44 +00:00
|
|
|
pagination_prev: demos/net/index
|
|
|
|
pagination_next: demos/mobile/index
|
2023-02-18 02:33:30 +00:00
|
|
|
---
|
|
|
|
|
2023-04-27 09:12:19 +00:00
|
|
|
import current from '/version.js';
|
2023-05-07 13:58:36 +00:00
|
|
|
import CodeBlock from '@theme/CodeBlock';
|
2023-04-27 09:12:19 +00:00
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
AstroJS[^1] is a site generator. AstroJS projects support ViteJS[^2] plugins for
|
|
|
|
making custom data sources.
|
2023-02-18 02:33:30 +00:00
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
|
|
|
data from spreadsheets.
|
2023-02-18 02:33:30 +00:00
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
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.
|
2023-02-18 02:33:30 +00:00
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
The ["Complete Example"](#complete-example) section includes a complete website
|
|
|
|
powered by Apple Numbers spreadsheets.
|
2023-02-18 02:33:30 +00:00
|
|
|
|
2023-05-25 01:36:15 +00:00
|
|
|
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
|
|
|
|
```
|
|
|
|
|
2023-06-02 02:17:56 +00:00
|
|
|
:::warning Telemetry
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
AstroJS enables telemetry by default. The tool has an option to disable telemetry:
|
2023-06-02 02:17:56 +00:00
|
|
|
|
|
|
|
```bash
|
|
|
|
npx astro telemetry disable
|
|
|
|
```
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
2023-12-05 03:46:54 +00:00
|
|
|
:::note Tested Deployments
|
2023-10-25 06:29:34 +00:00
|
|
|
|
2023-12-05 03:46:54 +00:00
|
|
|
This demo was tested in the following environments:
|
|
|
|
|
|
|
|
| AstroJS | Date |
|
|
|
|
|:---------------|:-----------|
|
|
|
|
| `3.6.4` | 2023-12-04 |
|
|
|
|
| `4.0.0-beta.4` | 2023-12-04 |
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
:::caution pass
|
|
|
|
|
|
|
|
AstroJS has introduced a number of breaking changes in minor releases.
|
|
|
|
|
|
|
|
**The demos worked as expected with the listed versions on the listed dates.**
|
2023-10-25 06:29:34 +00:00
|
|
|
|
|
|
|
:::
|
|
|
|
|
2023-02-18 02:33:30 +00:00
|
|
|
## Integration
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
:::info pass
|
|
|
|
|
|
|
|
This demo uses ["Base64 Loader"](/docs/demos/static/vitejs#base64-loader)
|
|
|
|
from the ViteJS demo.
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
The ViteJS demo used the query `?b64` to identify files. To play nice with
|
2023-08-01 00:28:19 +00:00
|
|
|
AstroJS, this demo matches the file extensions directly.
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
:::
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
Since AstroJS performs per-page processing at build time, it is recommended to
|
2023-02-18 02:33:30 +00:00
|
|
|
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!
|
|
|
|
|
2023-02-22 04:38:10 +00:00
|
|
|
### Loader
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
The loader should be added to `astro.config.mjs` under the `vite` key.
|
|
|
|
|
|
|
|
```js title="astro.config.mjs"
|
|
|
|
import { readFileSync } from 'fs';
|
|
|
|
import { defineConfig } from 'astro/config';
|
|
|
|
export default defineConfig({
|
|
|
|
vite: {
|
|
|
|
// this tells astro which extensions to handle
|
2023-08-01 00:28:19 +00:00
|
|
|
assetsInclude: ['**/*.numbers', '**/*.xlsx', '**/*.xls', '**/*.xlsb'],
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
plugins: [
|
|
|
|
{ // this plugin presents the data as a Base64 string
|
|
|
|
name: "sheet-base64",
|
|
|
|
transform(code, id) {
|
|
|
|
if(!id.match(/\.(numbers|xlsx)$/)) return;
|
|
|
|
var data = readFileSync(id, "base64");
|
|
|
|
return `export default '${data}'`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Types
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
For VSCode and VSCodium integration, types can be specified in `src/env.d.ts`.
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
This data loader returns Base64 strings:
|
|
|
|
|
|
|
|
```ts title="src/env.d.ts"
|
|
|
|
/// <reference types="astro/client" />
|
2023-08-18 20:39:12 +00:00
|
|
|
declare module '*.numbers' { const data: string; export default data; }
|
|
|
|
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; }
|
2023-08-01 00:28:19 +00:00
|
|
|
// ... (more spreadsheet formats) ...
|
2023-02-18 02:33:30 +00:00
|
|
|
```
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
### AstroJS Frontmatter
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
Typically projects store files in `src/pages`. Assuming `pres.numbers` is stored
|
|
|
|
in the `src/data` directory in the project, the relative import
|
|
|
|
|
|
|
|
```js
|
|
|
|
import b64 from "../data/pres.numbers"
|
|
|
|
```
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
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:
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
```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";
|
2023-08-01 00:28:19 +00:00
|
|
|
const wb = read(b64, { type: "base64" });
|
2023-02-18 02:33:30 +00:00
|
|
|
|
|
|
|
/* generate row objects */
|
|
|
|
interface IPresident {
|
|
|
|
Name: string;
|
|
|
|
Index: number;
|
|
|
|
}
|
|
|
|
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
|
|
|
|
---
|
2023-08-01 00:28:19 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
### 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"
|
2023-02-18 02:33:30 +00:00
|
|
|
<html>
|
|
|
|
<body>
|
|
|
|
<h3>Presidents</h3>
|
|
|
|
<table>
|
|
|
|
<thead><tr><th>Name</th><th>Index</th></tr></thead>
|
|
|
|
{/* Display each row object as a TR within the TBODY element */}
|
|
|
|
<tbody>{data.map(row => (
|
|
|
|
<tr><td>{row.Name}</td><td>{row.Index}</td></tr>
|
|
|
|
))}</tbody>
|
|
|
|
</table>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
```
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
When built using `npx astro build`, AstroJS will perform the conversion and emit
|
2023-02-18 02:33:30 +00:00
|
|
|
a simple HTML table without any reference to the existing spreadsheet file!
|
2023-02-22 04:38:10 +00:00
|
|
|
|
|
|
|
## Complete Example
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
:::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:
|
2023-02-22 04:38:10 +00:00
|
|
|
|
|
|
|
```bash
|
|
|
|
npx astro telemetry disable
|
|
|
|
```
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
1) Create a new site using the `starlight` template:
|
2023-02-22 04:38:10 +00:00
|
|
|
|
|
|
|
```bash
|
2023-08-01 00:28:19 +00:00
|
|
|
npm create astro@latest -- --template starlight --yes ./sheetjs-astro
|
2023-02-22 04:38:10 +00:00
|
|
|
cd sheetjs-astro
|
|
|
|
```
|
|
|
|
|
2023-12-05 03:46:54 +00:00
|
|
|
:::note pass
|
|
|
|
|
|
|
|
To test the AstroJS 4 beta release, run the following command:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm install --force @astrojs/starlight@^0.14.0 astro@4.0.0-beta.4
|
|
|
|
```
|
|
|
|
|
|
|
|
The version can be verified by running:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npx astro --version
|
|
|
|
```
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
2023-02-22 04:38:10 +00:00
|
|
|
2) Fetch the example file [`pres.numbers`](https://sheetjs.com/pres.numbers):
|
|
|
|
|
|
|
|
```bash
|
|
|
|
mkdir -p src/data
|
|
|
|
curl -Lo src/data/pres.numbers https://sheetjs.com/pres.numbers
|
|
|
|
```
|
|
|
|
|
|
|
|
3) Install the SheetJS library:
|
|
|
|
|
2023-05-07 13:58:36 +00:00
|
|
|
<CodeBlock language="bash">{`\
|
2023-04-27 09:12:19 +00:00
|
|
|
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
|
2023-05-07 13:58:36 +00:00
|
|
|
</CodeBlock>
|
2023-02-22 04:38:10 +00:00
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
4) Append the following lines to `src/env.d.ts`:
|
2023-02-22 04:38:10 +00:00
|
|
|
|
2023-10-25 06:29:34 +00:00
|
|
|
```ts title="src/env.d.ts (add to end)"
|
2023-02-22 04:38:10 +00:00
|
|
|
/* add to the end of the file */
|
2023-08-18 20:39:12 +00:00
|
|
|
declare module '*.numbers' { const data: string; export default data; }
|
|
|
|
declare module '*.xlsx' { const data: string; export default data; }
|
2023-02-22 04:38:10 +00:00
|
|
|
```
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
5) Add the highlighted lines to `astro.config.mjs`:
|
|
|
|
|
|
|
|
- At the top of the script, import `readFileSync`:
|
2023-02-22 04:38:10 +00:00
|
|
|
|
|
|
|
```js title="astro.config.mjs"
|
2023-02-24 07:46:48 +00:00
|
|
|
// highlight-start
|
|
|
|
/* import `readFileSync` at the top of the script*/
|
|
|
|
import { readFileSync } from 'fs';
|
|
|
|
// highlight-end
|
|
|
|
import { defineConfig } from 'astro/config';
|
2023-08-01 00:28:19 +00:00
|
|
|
```
|
2023-02-24 07:46:48 +00:00
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
- In the object argument to `defineConfig`, add a `vite` section:
|
2023-02-24 07:46:48 +00:00
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
```js title="astro.config.mjs"
|
2023-02-22 04:38:10 +00:00
|
|
|
export default defineConfig({
|
|
|
|
// highlight-start
|
2023-02-24 07:46:48 +00:00
|
|
|
/* this vite section should be added as a property of the object */
|
2023-02-22 04:38:10 +00:00
|
|
|
vite: {
|
|
|
|
// this tells astro which extensions to handle
|
|
|
|
assetsInclude: ['**/*.numbers', '**/*.xlsx'],
|
|
|
|
|
|
|
|
plugins: [
|
|
|
|
{ // this plugin presents the data as a Base64 string
|
|
|
|
name: "sheet-base64",
|
|
|
|
transform(code, id) {
|
|
|
|
if(!id.match(/\.(numbers|xlsx)$/)) return;
|
|
|
|
var data = readFileSync(id, "base64");
|
|
|
|
return `export default '${data}'`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
// highlight-end
|
|
|
|
```
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
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.*
|
|
|
|
```
|
|
|
|
|
2023-12-05 03:46:54 +00:00
|
|
|
:::note pass
|
|
|
|
|
|
|
|
This command may show an error:
|
|
|
|
|
|
|
|
```
|
|
|
|
zsh: no matches found: src/content/index.*
|
|
|
|
```
|
|
|
|
|
|
|
|
This error can be ignored.
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
8) Build the static site:
|
2023-02-22 04:38:10 +00:00
|
|
|
|
|
|
|
```bash
|
|
|
|
npx astro build
|
|
|
|
```
|
|
|
|
|
|
|
|
AstroJS will place the generated site in the `dist` subfolder.
|
|
|
|
|
2023-08-01 00:28:19 +00:00
|
|
|
9) Start a web server to host the static site:
|
2023-02-22 04:38:10 +00:00
|
|
|
|
|
|
|
```bash
|
|
|
|
npx http-server dist
|
|
|
|
```
|
|
|
|
|
2023-05-03 03:40:40 +00:00
|
|
|
Open a web browser and access the displayed URL ( `http://localhost:8080` ).
|
2023-04-19 20:03:23 +00:00
|
|
|
View the page source and confirm that no JS was added to the page. It only
|
2023-04-24 08:50:42 +00:00
|
|
|
contains the content from the file in an HTML table.
|
2023-08-01 00:28:19 +00:00
|
|
|
|
|
|
|
:::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`
|
|
|
|
|
2023-12-05 03:46:54 +00:00
|
|
|
In a later test, AstroJS removed the `docs` template and introduced the
|
|
|
|
`starlight` template. This template included `src/content/index.mdx`, which
|
2023-08-01 00:28:19 +00:00
|
|
|
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)
|