forked from sheetjs/docs.sheetjs.com
		
	quick
This commit is contained in:
		
							parent
							
								
									efc57df123
								
							
						
					
					
						commit
						edaa2e6b5e
					
				@ -33,3 +33,6 @@ Specific pages can load scripts using the `head` component:
 | 
			
		||||
</head>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Other Notes
 | 
			
		||||
 | 
			
		||||
`src/theme/Admonition` was swizzled from 2.4.1 to address Docusaurus issue 8568
 | 
			
		||||
@ -22,10 +22,25 @@ Most scenarios involving spreadsheets and data can be divided into 5 parts:
 | 
			
		||||
   locally.  Data can be presented to users in an HTML TABLE or data grid.
 | 
			
		||||
 | 
			
		||||
A common problem involves generating a valid spreadsheet export from data stored
 | 
			
		||||
in an HTML table.  In this example, an HTML TABLE on the page will be scraped,
 | 
			
		||||
a row will be added to the bottom with the date of the report, and a new file
 | 
			
		||||
will be generated and downloaded locally. `XLSX.writeFile` takes care of
 | 
			
		||||
packaging the data and attempting a local download:
 | 
			
		||||
in an HTML table.
 | 
			
		||||
 | 
			
		||||
```mermaid
 | 
			
		||||
flowchart LR
 | 
			
		||||
  server[(Backend\nServer)]
 | 
			
		||||
  html{{HTML\nTABLE}}
 | 
			
		||||
  wb(((SheetJS\nWorkbook)))
 | 
			
		||||
  wb2(((Modified\nWorkbook)))
 | 
			
		||||
  file[(workbook\nfile)]
 | 
			
		||||
  server --> |"Get Table (1)\n."| html
 | 
			
		||||
  html --> |"Parse Table (2)\n`table_to_book`"| wb
 | 
			
		||||
  wb --> |"Add data (3)\n`sheet_add_aoa`"| wb2
 | 
			
		||||
  wb2 --> |"Export file (4,5)\n`writeFile`"| file
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In this example, an HTML TABLE on the page will be scraped, a row will be added
 | 
			
		||||
to the bottom with the date of the report, and a new file will be generated and
 | 
			
		||||
downloaded locally. `XLSX.writeFile` takes care of packaging the data and
 | 
			
		||||
attempting a local download:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
// Acquire Data (reference to the HTML table)
 | 
			
		||||
@ -54,6 +69,9 @@ Utility functions help with step 3.
 | 
			
		||||
 | 
			
		||||
## Highlights
 | 
			
		||||
 | 
			
		||||
["Demos"](/docs/demos) describes special deployments using SheetJS in tandem with
 | 
			
		||||
other tools and libraries.
 | 
			
		||||
 | 
			
		||||
["Data Import"](/docs/solutions/input) describes solutions for common data import
 | 
			
		||||
scenarios.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -94,14 +94,22 @@ export default defineConfig({
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In frontend code, the loader will look for all modules with a `?sheetjs`
 | 
			
		||||
query string. The default export is an array of row objects:
 | 
			
		||||
query string. The default export is an array of row objects.
 | 
			
		||||
 | 
			
		||||
The following example script displays the data in a table:
 | 
			
		||||
 | 
			
		||||
```js title="main.js"
 | 
			
		||||
import data from './data.xlsx?sheetjs';
 | 
			
		||||
import data from './data/pres.xlsx?sheetjs';
 | 
			
		||||
 | 
			
		||||
document.querySelector('#app').innerHTML = `<div><pre>
 | 
			
		||||
  ${data.map(row => JSON.stringify(row)).join("\n")}
 | 
			
		||||
</pre></div>`;
 | 
			
		||||
document.querySelector('#app').innerHTML = `<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>`).join("\n")}
 | 
			
		||||
  </tbody>
 | 
			
		||||
</table>`;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Base64 Plugin
 | 
			
		||||
@ -155,17 +163,23 @@ When importing using the `b64` query, the raw Base64 string will be exposed.
 | 
			
		||||
```js title="main.js"
 | 
			
		||||
import { read, utils } from "xlsx";
 | 
			
		||||
 | 
			
		||||
/* reference workbook */
 | 
			
		||||
/* import workbook data */
 | 
			
		||||
import b64 from './data.xlsx?b64';
 | 
			
		||||
/* parse workbook and export first sheet to CSV */
 | 
			
		||||
 | 
			
		||||
/* parse workbook and pull data from the first worksheet */
 | 
			
		||||
const wb = read(b64, { type: "base64" });
 | 
			
		||||
const wsname = wb.SheetNames[0];
 | 
			
		||||
const csv = utils.sheet_to_csv(wb.Sheets[wsname]);
 | 
			
		||||
const data = utils.sheet_to_json(wb.Sheets[wsname]);
 | 
			
		||||
 | 
			
		||||
document.querySelector('#app').innerHTML = `<div><pre>
 | 
			
		||||
<b>${wsname}</b>
 | 
			
		||||
${csv}
 | 
			
		||||
</pre></div>`;
 | 
			
		||||
document.querySelector('#app').innerHTML = `<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>`).join("\n")}
 | 
			
		||||
  </tbody>
 | 
			
		||||
</table>`;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Complete Demo
 | 
			
		||||
@ -278,7 +292,7 @@ source.  The code will reference some script like `/assets/index-HASH.js`.
 | 
			
		||||
Open that script.  Searching for `Bill Clinton` reveals the following:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
JSON.parse('[{"Name":"Bill Clinton","Index":42}
 | 
			
		||||
{"Name":"Bill Clinton","Index":42}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Searching for `BESSELJ` should reveal no results.  The SheetJS scripts are not
 | 
			
		||||
@ -350,9 +364,9 @@ The SheetJS library is embedded in the final site.
 | 
			
		||||
 | 
			
		||||
[^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 [`sheet_to_json` in "Utilities"](/docs/api/utilities/#array-output)
 | 
			
		||||
[^4]: See [`read` in "Parsing Options"](/docs/api/parse-options)
 | 
			
		||||
[^5]: See [`read` in "Parsing Options"](/docs/api/parse-options)
 | 
			
		||||
[^6]: See [the "base64" type in "Parsing Options"](/docs/api/parse-options#input-type)
 | 
			
		||||
[^3]: See [`read` in "Reading Files"](/docs/api/parse-options)
 | 
			
		||||
[^4]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-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.
 | 
			
		||||
@ -1,5 +1,7 @@
 | 
			
		||||
---
 | 
			
		||||
title: Wails
 | 
			
		||||
sidebar_label: Wails
 | 
			
		||||
description: Build data-intensive desktop apps using Wails. Seamlessly integrate spreadsheets into your app using SheetJS. Modernize Excel-powered business processes with confidence.
 | 
			
		||||
pagination_prev: demos/mobile/index
 | 
			
		||||
pagination_next: demos/data/index
 | 
			
		||||
sidebar_position: 3
 | 
			
		||||
@ -7,18 +9,28 @@ sidebar_custom_props:
 | 
			
		||||
  summary: Webview + Go Backend
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Spreadsheet-Powered Wails Apps
 | 
			
		||||
 | 
			
		||||
import current from '/version.js';
 | 
			
		||||
import Tabs from '@theme/Tabs';
 | 
			
		||||
import TabItem from '@theme/TabItem';
 | 
			
		||||
import CodeBlock from '@theme/CodeBlock';
 | 
			
		||||
 | 
			
		||||
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
 | 
			
		||||
from JavaScript code.
 | 
			
		||||
[Wails](https://wails.io/) is a modern toolkit for building desktop apps. Wails
 | 
			
		||||
apps pair a Go-powered backend with a JavaScript-powered frontend[^1].
 | 
			
		||||
 | 
			
		||||
The "Complete Example" creates an app that looks like the screenshot:
 | 
			
		||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
 | 
			
		||||
data from spreadsheets.
 | 
			
		||||
 | 
			
		||||
This demo uses Wails and SheetJS to pull data from a spreadsheet and display the
 | 
			
		||||
data in the app. We'll explore how to load SheetJS in a Wails app and exchange
 | 
			
		||||
file data between the JavaScript frontend and Go backend.
 | 
			
		||||
 | 
			
		||||
The ["Complete Example"](#complete-example) section covers a complete desktop
 | 
			
		||||
app to read and write workbooks. The app will look like the screenshots below:
 | 
			
		||||
 | 
			
		||||
<table><thead><tr>
 | 
			
		||||
  <th><a href="#complete-example">Win10</a></th>
 | 
			
		||||
  <th><a href="#complete-example">Windows</a></th>
 | 
			
		||||
  <th><a href="#complete-example">macOS</a></th>
 | 
			
		||||
  <th><a href="#complete-example">Linux</a></th>
 | 
			
		||||
</tr></thead><tbody><tr><td>
 | 
			
		||||
@ -35,49 +47,71 @@ The "Complete Example" creates an app that looks like the screenshot:
 | 
			
		||||
 | 
			
		||||
</td></tr></tbody></table>
 | 
			
		||||
 | 
			
		||||
## Integration Details
 | 
			
		||||
:::info
 | 
			
		||||
 | 
			
		||||
All operations must be run from Go code.  This example passes Base64 strings.
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
Wails currently does not provide the equivalent of NodeJS `fs` module.  All raw
 | 
			
		||||
file operations must be performed in Go code.
 | 
			
		||||
 | 
			
		||||
The HTML File Input Element does not show a file picker.  This is a known bug.
 | 
			
		||||
The demo works around the issue by showing pickers in Go code.
 | 
			
		||||
This demo assumes some familiarity with JavaScript and with Go. If you would
 | 
			
		||||
prefer a pure JavaScript solution, the [Electron](/docs/demos/desktop/electron)
 | 
			
		||||
platform provides many native features out of the box.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## Integration Details
 | 
			
		||||
 | 
			
		||||
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
 | 
			
		||||
installed in the `frontend` folder and imported in frontend scripts.
 | 
			
		||||
 | 
			
		||||
:::caution
 | 
			
		||||
 | 
			
		||||
Wails currently does not provide the equivalent of NodeJS `fs` module.
 | 
			
		||||
 | 
			
		||||
Reading and writing raw file data must be implemented in native Go code.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
This demo includes native Go code for showing dialogs and reading and writing
 | 
			
		||||
files. When sending data between Go and JavaScript code, the raw files are
 | 
			
		||||
encoded as Base64 strings.
 | 
			
		||||
 | 
			
		||||
### Reading Files
 | 
			
		||||
 | 
			
		||||
The file picker and reading operations can be combined in one Go function.
 | 
			
		||||
When the user clicks the "Import File" button, the frontend tells the Go backend
 | 
			
		||||
to read data. The user will be presented with a file picker to select a file to
 | 
			
		||||
read. The Go backend will read the data, encode as a Base64 string, and send the
 | 
			
		||||
result to the frontend.
 | 
			
		||||
 | 
			
		||||
The frontend will parse the data using the SheetJS `read` method[^2], generate
 | 
			
		||||
HTML tables with `sheet_to_html`[^3], and display the tables on the frontend.
 | 
			
		||||
 | 
			
		||||
The following diagram summarizes the steps:
 | 
			
		||||
 | 
			
		||||
```mermaid
 | 
			
		||||
sequenceDiagram
 | 
			
		||||
  autonumber
 | 
			
		||||
  actor User
 | 
			
		||||
  participant JS
 | 
			
		||||
  participant Go
 | 
			
		||||
  participant JS as Frontend (JS)
 | 
			
		||||
  participant Go as Backend (Go)
 | 
			
		||||
  User->>JS: click button
 | 
			
		||||
  JS->>Go: ask for data
 | 
			
		||||
  Note over Go: Show Open Dialog
 | 
			
		||||
  Note over Go: Read File Bytes
 | 
			
		||||
  Note over Go: Generate Base64
 | 
			
		||||
  Go->>JS: return data
 | 
			
		||||
  Note over JS: Parse data
 | 
			
		||||
  Note over JS: Display Table
 | 
			
		||||
  Note over JS: Parse Data<br/>`read`
 | 
			
		||||
  Note over JS: Display Table<br/>`sheet_to_html`
 | 
			
		||||
  JS->>User: app shows data
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Go
 | 
			
		||||
 | 
			
		||||
The Wails runtime provides the cross-platform `OpenFileDialog` function[^4] to
 | 
			
		||||
show a file picker. The Go standard library provides methods for reading data
 | 
			
		||||
from the selected file[^5] and encoding in a Base64 string[^6]
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
  "context"
 | 
			
		||||
// highlight-start
 | 
			
		||||
  "encoding/base64"
 | 
			
		||||
  "io/ioutil"
 | 
			
		||||
  "os"
 | 
			
		||||
  "github.com/wailsapp/wails/v2/pkg/runtime"
 | 
			
		||||
// highlight-end
 | 
			
		||||
)
 | 
			
		||||
@ -98,7 +132,7 @@ func (a *App) ReadFile() string {
 | 
			
		||||
  })
 | 
			
		||||
  if err != nil { return "" } // The demo app shows an error message
 | 
			
		||||
  // highlight-next-line
 | 
			
		||||
  data, err := ioutil.ReadFile(selection)
 | 
			
		||||
  data, err := os.ReadFile(selection)
 | 
			
		||||
  if err != nil { return "" } // The demo app shows an error message
 | 
			
		||||
  // highlight-next-line
 | 
			
		||||
  return base64.StdEncoding.EncodeToString(data)
 | 
			
		||||
@ -107,7 +141,8 @@ func (a *App) ReadFile() string {
 | 
			
		||||
 | 
			
		||||
#### JS
 | 
			
		||||
 | 
			
		||||
Wails will automatically create bindings for use in JS:
 | 
			
		||||
Wails will automatically create bindings for use in JS. The `App` binding module
 | 
			
		||||
will export the function `ReadFile`.
 | 
			
		||||
 | 
			
		||||
```js title="frontend/src/App.svelte"
 | 
			
		||||
import { read, utils } from 'xlsx';
 | 
			
		||||
@ -115,38 +150,53 @@ import { ReadFile } from '../wailsjs/go/main/App';
 | 
			
		||||
 | 
			
		||||
async function importFile(evt) {
 | 
			
		||||
// highlight-start
 | 
			
		||||
  /* call the native Go function and receive a base64 string */
 | 
			
		||||
  const b64 = await ReadFile();
 | 
			
		||||
  /* parse the base64 string with SheetJS */
 | 
			
		||||
  const wb = read(b64, { type: "base64" });
 | 
			
		||||
// highlight-end
 | 
			
		||||
 | 
			
		||||
  const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
 | 
			
		||||
  html = utils.sheet_to_html(ws); // generate HTML and update state
 | 
			
		||||
  return utils.sheet_to_html(ws); // generate HTML table
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Writing Files
 | 
			
		||||
 | 
			
		||||
There is a multi-part dance since the library needs the file extension.
 | 
			
		||||
:::info
 | 
			
		||||
 | 
			
		||||
1) Show the save file picker in Go, pass back to JS
 | 
			
		||||
The SheetJS `write` method[^7] can write spreadsheets in a number of formats[^8]
 | 
			
		||||
including XLSX, XLSB, XLS, and NUMBERS. It expects a `bookType` option. This
 | 
			
		||||
means the frontend needs to know the output file name before creating the file.
 | 
			
		||||
 | 
			
		||||
2) Generate the file data in JS, pass the data back to Go
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
3) Write to file in Go
 | 
			
		||||
When the user clicks the "Export File" button, the frontend asks the Go backend
 | 
			
		||||
for the output filename and path. The user will be presented with a file picker
 | 
			
		||||
to select the output folder and workbook type. The backend will send the name
 | 
			
		||||
to the frontend.
 | 
			
		||||
 | 
			
		||||
The frontend will generate a workbook object from the table using the SheetJS
 | 
			
		||||
`table_to_book` method[^9]. The SheetJS `write` method[^10] will generate a
 | 
			
		||||
Base64 string from the data.
 | 
			
		||||
 | 
			
		||||
The frontend will send the Base64 string to the backend. The backend will write
 | 
			
		||||
the data to a file in the selected folder.
 | 
			
		||||
 | 
			
		||||
```mermaid
 | 
			
		||||
sequenceDiagram
 | 
			
		||||
  autonumber
 | 
			
		||||
  actor User
 | 
			
		||||
  participant JS
 | 
			
		||||
  participant Go
 | 
			
		||||
  participant JS as Frontend (JS)
 | 
			
		||||
  participant Go as Backend (Go)
 | 
			
		||||
  User->>JS: click button
 | 
			
		||||
  JS->>Go: ask for path
 | 
			
		||||
  Note over Go: Show Save Dialog
 | 
			
		||||
  Go->>JS: path to save file
 | 
			
		||||
  Note over JS: write workbook
 | 
			
		||||
  Note over JS: Read from Table<br/>`table_to_book`
 | 
			
		||||
  Note over JS: Write Workbook<br/>`write`
 | 
			
		||||
  JS->>Go: base64-encoded bytes
 | 
			
		||||
  Note over Go: decode data
 | 
			
		||||
  Note over Go: write to file
 | 
			
		||||
  Note over Go: Decode Data
 | 
			
		||||
  Note over Go: Write to File
 | 
			
		||||
  Go->>JS: write finished
 | 
			
		||||
  JS->>User: alert
 | 
			
		||||
```
 | 
			
		||||
@ -155,7 +205,8 @@ sequenceDiagram
 | 
			
		||||
 | 
			
		||||
Two Go functions will be exposed.
 | 
			
		||||
 | 
			
		||||
- `SaveFile` will show the file picker and return the path:
 | 
			
		||||
- `SaveFile` will show the file picker and return the path. It will use the
 | 
			
		||||
  cross-platform `SaveFileDialog` function[^11].
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
@ -183,14 +234,16 @@ func (a *App) SaveFile() string {
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- `WriteFile` performs the file write given a Base64 string and file path:
 | 
			
		||||
- `WriteFile` performs the file write given a Base64 string and file path. The
 | 
			
		||||
  Go standard library provides methods for decoding Base64 strings[^12] and
 | 
			
		||||
  writing data to the filesystem[^13]
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
  "context"
 | 
			
		||||
// highlight-start
 | 
			
		||||
  "encoding/base64"
 | 
			
		||||
  "io/ioutil"
 | 
			
		||||
  "os"
 | 
			
		||||
// highlight-end
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -201,29 +254,32 @@ type App struct {
 | 
			
		||||
func (a *App) WriteFile(b64 string, path string) {
 | 
			
		||||
  // highlight-start
 | 
			
		||||
  buf, _ := base64.StdEncoding.DecodeString(b64);
 | 
			
		||||
  _ = ioutil.WriteFile(path, buf, 0644);
 | 
			
		||||
  _ = os.WriteFile(path, buf, 0644);
 | 
			
		||||
  // highlight-end
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### JS
 | 
			
		||||
 | 
			
		||||
Wails will automatically create bindings for use in JS:
 | 
			
		||||
Wails will automatically create bindings for use in JS. The `App` binding module
 | 
			
		||||
will export the functions `SaveFile` and `WriteFile`:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
```js title="frontend/src/App.svelte"
 | 
			
		||||
import { utils, write } from 'xlsx';
 | 
			
		||||
import { SaveFile, WriteFile } from '../wailsjs/go/main/App';
 | 
			
		||||
 | 
			
		||||
async function exportFile(wb) {
 | 
			
		||||
async function exportFile(table_element) {
 | 
			
		||||
  /* generate workbook */
 | 
			
		||||
  const elt = tbl.getElementsByTagName("TABLE")[0];
 | 
			
		||||
  const wb = utils.table_to_book(elt);
 | 
			
		||||
  const wb = utils.table_to_book(table_element);
 | 
			
		||||
 | 
			
		||||
  /* show save picker and get path */
 | 
			
		||||
  const path = await SaveFile();
 | 
			
		||||
 | 
			
		||||
  /* generate base64 string based on the path */
 | 
			
		||||
  const b64 = write(wb, { bookType: path.slice(path.lastIndexOf(".")+1), type: "base64" });
 | 
			
		||||
  /* get the file extension -> bookType */
 | 
			
		||||
  const bookType = path.slice(path.lastIndexOf(".")+1);
 | 
			
		||||
 | 
			
		||||
  /* generate base64 string */
 | 
			
		||||
  const b64 = write(wb, { bookType: bookType, type: "base64" });
 | 
			
		||||
 | 
			
		||||
  /* write to file */
 | 
			
		||||
  await WriteFile(b64, path);
 | 
			
		||||
@ -239,7 +295,44 @@ the Svelte TypeScript starter.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
0) [Read Wails "Getting Started" guide and install dependencies.](https://wails.io/docs/gettingstarted/installation)
 | 
			
		||||
0) Read the Wails "Getting Started" guide[^14] and install dependencies.
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Installation Notes</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
Wails will require:
 | 
			
		||||
 | 
			
		||||
- A recent version of [Go](https://go.dev/doc/install).
 | 
			
		||||
- The "LTS" version of [NodeJS](https://nodejs.org/en/download).
 | 
			
		||||
 | 
			
		||||
After installing both, run the following command to install Wails:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
go install github.com/wailsapp/wails/v2/cmd/wails@latest
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Once that finishes, run the following command in a new terminal window:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
wails doctor
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The output will include a `# Diagnosis` section. It should display:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
# Diagnosis
 | 
			
		||||
 | 
			
		||||
Your system is ready for Wails development!
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If a required dependency is missing, it will be displayed.
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
None of the optional packages are required for building and running this demo.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
1) Create a new Wails app:
 | 
			
		||||
 | 
			
		||||
@ -280,3 +373,18 @@ wails build
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
At the end, it will print the path to the generated program. Run the program!
 | 
			
		||||
 | 
			
		||||
[^1]: See ["How does it Work?"](https://wails.io/docs/howdoesitwork) in the Wails documentation.
 | 
			
		||||
[^2]: See [`read` in "Parsing Options"](/docs/api/parse-options)
 | 
			
		||||
[^3]: See [`sheet_to_html` in "Utilities"](/docs/api/utilities/html#html-table-output)
 | 
			
		||||
[^4]: See [`OpenFileDialog`](https://wails.io/docs/reference/runtime/dialog#openfiledialog) in the Wails documentation.
 | 
			
		||||
[^5]: See [`ReadFile`](https://pkg.go.dev/os#ReadFile) in the Go documentation
 | 
			
		||||
[^6]: See [`EncodeToString`](https://pkg.go.dev/encoding/base64#Encoding.EncodeToString) in the Go documentation
 | 
			
		||||
[^7]: See [`write` in "Writing Files"](/docs/api/write-options)
 | 
			
		||||
[^8]: See ["Supported Output Formats" type in "Writing Files"](/docs/api/write-options#supported-output-formats)
 | 
			
		||||
[^9]: See ["HTML Table Input" in "Utilities"](/docs/api/utilities/html#create-new-sheet)
 | 
			
		||||
[^10]: See [`write` in "Writing Files"](/docs/api/write-options)
 | 
			
		||||
[^11]: See [`SaveFileDialog`](https://wails.io/docs/reference/runtime/dialog#savefiledialog) in the Wails documentation.
 | 
			
		||||
[^12]: See [`DecodeString`](https://pkg.go.dev/encoding/base64#Encoding.DecodeString) in the Go documentation
 | 
			
		||||
[^13]: See [`WriteFile`](https://pkg.go.dev/os#WriteFile) in the Go documentation
 | 
			
		||||
[^14]: See ["Installation"](https://wails.io/docs/gettingstarted/installation) in the Wails documentation.
 | 
			
		||||
@ -1,36 +1,66 @@
 | 
			
		||||
---
 | 
			
		||||
title: C + QuickJS
 | 
			
		||||
sidebar_label: C + QuickJS
 | 
			
		||||
description: Process structured data in C programs. Seamlessly integrate spreadsheets into your program by pairing QuickJS and SheetJS. Supercharge programs with modern data tools.
 | 
			
		||||
pagination_prev: demos/bigdata/index
 | 
			
		||||
pagination_next: solutions/input
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Data Processing with QuickJS
 | 
			
		||||
 | 
			
		||||
import current from '/version.js';
 | 
			
		||||
import CodeBlock from '@theme/CodeBlock';
 | 
			
		||||
 | 
			
		||||
QuickJS is an embeddable JS engine written in C.  It provides a separate set of
 | 
			
		||||
functions for interacting with the filesystem and the global object.  It can run
 | 
			
		||||
the standalone browser scripts.
 | 
			
		||||
[QuickJS](https://bellard.org/quickjs/) is an embeddable JS engine written in C.
 | 
			
		||||
It has built-in support for reading and writing file data stored in memory.
 | 
			
		||||
 | 
			
		||||
The [Standalone scripts](/docs/getting-started/installation/standalone) can be
 | 
			
		||||
parsed and evaluated in a QuickJS context.
 | 
			
		||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
 | 
			
		||||
data from spreadsheets.
 | 
			
		||||
 | 
			
		||||
This demo uses QuickJS and SheetJS to pull data from a spreadsheet and print CSV
 | 
			
		||||
rows. We'll explore how to load SheetJS in a QuickJS context and process
 | 
			
		||||
spreadsheets from C programs.
 | 
			
		||||
 | 
			
		||||
The ["Integration Example"](#integration-example) section includes a complete
 | 
			
		||||
command-line tool for reading data from files.
 | 
			
		||||
 | 
			
		||||
## Integration Details
 | 
			
		||||
 | 
			
		||||
_Initialize QuickJS_
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
Many QuickJS functions are not documented. The explanation was verified against
 | 
			
		||||
the latest release (version `2021-03-27`, commit `2788d71`).
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
### Initialize QuickJS
 | 
			
		||||
 | 
			
		||||
Most QuickJS API functions interact with a `JSContext` object[^1], which is
 | 
			
		||||
normally created with `JS_NewRuntime` and `JS_NewContext`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
#include "quickjs.h"
 | 
			
		||||
 | 
			
		||||
/* initialize context */
 | 
			
		||||
JSRuntime *rt = JS_NewRuntime();
 | 
			
		||||
JSContext *ctx = JS_NewContext(rt);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
QuickJS provides a `global` object through `JS_GetGlobalObject`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* initialize */
 | 
			
		||||
JSRuntime *rt = JS_NewRuntime();
 | 
			
		||||
JSContext *ctx = JS_NewContext(rt);
 | 
			
		||||
 | 
			
		||||
/* obtain reference to global object */
 | 
			
		||||
JSValue global = JS_GetGlobalObject(ctx);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
/* DO WORK HERE */
 | 
			
		||||
<details><summary><b>Cleanup</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
/* free after use */
 | 
			
		||||
Once finished, programs are expected to cleanup by using `JS_FreeValue` to free
 | 
			
		||||
values, `JS_FreeContext` to free the context pointer, and `JS_FreeRuntime` to
 | 
			
		||||
free the runtime:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* global is a JSValue */
 | 
			
		||||
JS_FreeValue(ctx, global);
 | 
			
		||||
 | 
			
		||||
/* cleanup */
 | 
			
		||||
@ -38,27 +68,23 @@ JS_FreeContext(ctx);
 | 
			
		||||
JS_FreeRuntime(rt);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
The [Integration Example](#integration-example) frees JS values after use.
 | 
			
		||||
 | 
			
		||||
All values must be freed with `JS_FreeValue` before calling `JS_FreeContext`!
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
`JS_IsException` should be used for validation.
 | 
			
		||||
### Load SheetJS Scripts
 | 
			
		||||
 | 
			
		||||
Cleanup and validation code is omitted from the discussion.  The integration
 | 
			
		||||
example shows structured validation and controlled memory usage.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
_Load SheetJS Scripts_
 | 
			
		||||
[SheetJS Standalone scripts](/docs/getting-started/installation/standalone) can
 | 
			
		||||
be loaded and executed in QuickJS.
 | 
			
		||||
 | 
			
		||||
The main library can be loaded by reading the script from the file system and
 | 
			
		||||
evaluating in the QuickJS context:
 | 
			
		||||
evaluating in the QuickJS context using `JS_Eval`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
static char *read_file(const char *filename, size_t *sz) {
 | 
			
		||||
  FILE *f = fopen(filename, "rb");
 | 
			
		||||
  if(!f) return NULL;
 | 
			
		||||
  long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fsee  (f, 0, SEEK_SET); }
 | 
			
		||||
  long fsize; { fseek(f, 0, SEEK_END); fsize = ftell(f); fseek(f, 0, SEEK_SET); }
 | 
			
		||||
  char *buf = (char *)malloc(fsize * sizeof(char));
 | 
			
		||||
  *sz = fread((void *) buf, 1, fsize, f);
 | 
			
		||||
  fclose(f);
 | 
			
		||||
@ -66,22 +92,37 @@ static char *read_file(const char *filename, size_t *sz) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ...
 | 
			
		||||
  /* load library */
 | 
			
		||||
  {
 | 
			
		||||
    /* Read `xlsx.full.min.js` from the filesystem */
 | 
			
		||||
    size_t len; char *buf = read_file("xlsx.full.min.js", &len);
 | 
			
		||||
    /* evaluate from the QuickJS context */
 | 
			
		||||
    JS_Eval(ctx, buf, len, "<input>", 0);
 | 
			
		||||
    /* Free the file buffer */
 | 
			
		||||
    free(buf);
 | 
			
		||||
  }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To confirm the library is loaded, `XLSX.version` can be inspected:
 | 
			
		||||
If the library is loaded, `XLSX.version` will be a string. This string can be
 | 
			
		||||
pulled into the main C program.
 | 
			
		||||
 | 
			
		||||
1) Get the `XLSX` property of the global object using `JS_GetPropertyStr`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* obtain reference to the XLSX object */
 | 
			
		||||
JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
/* print version */
 | 
			
		||||
2) Get the `version` property of the `XLSX` object using `JS_GetPropertyStr`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* obtain reference to `XLSX.version` */
 | 
			
		||||
JSValue version = JS_GetPropertyStr(ctx, XLSX, "version");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Pull the string into C code with `JS_ToCStringLen`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* pull the version string into C */
 | 
			
		||||
size_t vlen; const char *vers = JS_ToCStringLen(ctx, &vlen, version);
 | 
			
		||||
printf("Version: %s\n", vers);
 | 
			
		||||
```
 | 
			
		||||
@ -97,16 +138,119 @@ size_t dlen; uint8_t * dbuf = (uint8_t *)read_file("pres.numbers", &dlen);
 | 
			
		||||
 | 
			
		||||
/* load data into array buffer */
 | 
			
		||||
JSValue ab = JS_NewArrayBuffer(ctx, dbuf, dlen, NULL, NULL, 0);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
/* obtain reference to the XLSX object */
 | 
			
		||||
The `ArrayBuffer` will be parsed with the SheetJS `read` method[^2]. The CSV row
 | 
			
		||||
data will be generated with `sheet_to_csv`[^3].
 | 
			
		||||
 | 
			
		||||
#### Parse the ArrayBuffer
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
The goal is to run the equivalent of the following JavaScript code:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* `ab` is the `ArrayBuffer` from the previous step */
 | 
			
		||||
var wb = XLSX.read(ab);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
1) Get the `XLSX` property of the global object and the `read` property of `XLSX`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* obtain reference to XLSX.read */
 | 
			
		||||
JSValue XLSX = JS_GetPropertyStr(ctx, global, "XLSX");
 | 
			
		||||
 | 
			
		||||
/* call XLSX.read(ab) */
 | 
			
		||||
JSValue XLSX_read = JS_GetPropertyStr(ctx, XLSX, "read");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Create an array of arguments to pass to the function. In this case, the
 | 
			
		||||
`read` function will be called with one argument (`ArrayBuffer` data):
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* prepare arguments */
 | 
			
		||||
JSValue args[] = { ab };
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
3) Use `JS_Call` to call the function with the arguments:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* call XLSX.read(ab) */
 | 
			
		||||
JSValue wb = JS_Call(ctx, XLSX_read, XLSX, 1, args);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Get First Worksheet
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
The goal is to get the first worksheet. In JavaScript, the `SheetNames` property
 | 
			
		||||
of the workbook is an array of strings and the `Sheets` property holds worksheet
 | 
			
		||||
objects[^4]. The desired action looks like:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* `wb` is the workbook from the previous step */
 | 
			
		||||
var wsname = wb.SheetNames[0];
 | 
			
		||||
var ws = wb.Sheets[wsname];
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
4) Pull `wb.SheetNames[0]` into a C string using `JS_GetPropertyStr`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* get `wb.SheetNames[0]` */
 | 
			
		||||
JSValue SheetNames = JS_GetPropertyStr(ctx, wb, "SheetNames");
 | 
			
		||||
JSValue Sheet1 = JS_GetPropertyStr(ctx, SheetNames, "0");
 | 
			
		||||
 | 
			
		||||
/* pull first sheet name into C code */
 | 
			
		||||
size_t wslen; const char *wsname = JS_ToCStringLen(ctx, &wslen, Sheet1);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
5) Get the worksheet object:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* get wb.Sheets[wsname] */
 | 
			
		||||
JSValue Sheets = JS_GetPropertyStr(ctx, wb, "Sheets");
 | 
			
		||||
JSValue ws = JS_GetPropertyStr(ctx, Sheets, wsname);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### Convert to CSV
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
The goal is to call `sheet_to_csv`[^5] and pull the result into C code:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* `ws` is the worksheet from the previous step */
 | 
			
		||||
var csv = XLSX.utils.sheet_to_csv(ws);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
6) Create a references to `XLSX.utils` and `XLSX.utils.sheet_to_csv`:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* obtain reference to XLSX.utils.sheet_to_csv */
 | 
			
		||||
JSValue utils = JS_GetPropertyStr(ctx, XLSX, "utils");
 | 
			
		||||
JSValue sheet_to_csv = JS_GetPropertyStr(ctx, utils, "sheet_to_csv");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
7) Create arguments array:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
/* prepare arguments */
 | 
			
		||||
JSValue args[] = { ws };
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
8) Use `JS_Call` to call the function and use `JS_ToCStringLen` to pull the CSV:
 | 
			
		||||
 | 
			
		||||
```c
 | 
			
		||||
JSValue csv = JS_Call(ctx, sheet_to_csv, utils, 1, args);
 | 
			
		||||
size_t csvlen; const char *csvstr = JS_ToCStringLen(ctx, &csvlen, csv);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
At this point, `csvstr` is a C string that can be printed to standard output.
 | 
			
		||||
 | 
			
		||||
## Complete Example
 | 
			
		||||
 | 
			
		||||
The "Integration Example" covers a traditional integration in a C application,
 | 
			
		||||
@ -124,6 +268,8 @@ This demo was tested in the following deployments:
 | 
			
		||||
| `darwin-arm` | `2788d71`  | 2023-06-05 |
 | 
			
		||||
| `linux-x64`  | `2788d71`  | 2023-06-02 |
 | 
			
		||||
 | 
			
		||||
Git commit `2788d71` corresponds to the latest release (`2021-03-27`)
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
0) Build `libquickjs.a`:
 | 
			
		||||
@ -171,7 +317,7 @@ curl -LO https://sheetjs.com/pres.numbers`}
 | 
			
		||||
 | 
			
		||||
5) Run the test program:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
./sheetjs.quick pres.numbers
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -215,3 +361,9 @@ quickjs SheetJSQuick.js
 | 
			
		||||
 | 
			
		||||
If successful, the script will generate `SheetJSQuick.xlsx`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[^1]: See ["Runtime and Contexts"](https://bellard.org/quickjs/quickjs.html#Runtime-and-contexts) in the QuickJS documentation
 | 
			
		||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
 | 
			
		||||
[^3]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)
 | 
			
		||||
[^4]: See ["Workbook Object" in "SheetJS Data Model"](/docs/csf/book)
 | 
			
		||||
[^5]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,22 @@ std::unique_ptr<facebook::jsi::Runtime> rt(facebook::hermes::makeHermesRuntime()
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Hermes does not expose a `console` or `global` variable, but those can be
 | 
			
		||||
synthesized from JS code in the runtime:
 | 
			
		||||
synthesized from JS code in the runtime.
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
The JavaScript code is shown below:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
/* create global object */
 | 
			
		||||
var global = (function(){ return this; }).call(null);
 | 
			
		||||
/* create a fake `console` from the hermes `print` builtin */
 | 
			
		||||
var console = { log: function(x) { print(x); } };
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
The code can be stored in a C string and evaluated after creating a runtime:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
auto src = std::make_shared<facebook::jsi::StringBuffer>(
 | 
			
		||||
@ -96,7 +111,7 @@ Hermes supports `ArrayBuffer` but has no simple helper to read raw memory.
 | 
			
		||||
Libraries are expected to implement `MutableBuffer`:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
/* ArrayBuffer constructor expects MutableBuffer*/
 | 
			
		||||
/* ArrayBuffer constructor expects MutableBuffer */
 | 
			
		||||
class CMutableBuffer : public facebook::jsi::MutableBuffer {
 | 
			
		||||
  public:
 | 
			
		||||
    CMutableBuffer(uint8_t *data, size_t size) : buf(data), sz(size) {}
 | 
			
		||||
@ -117,8 +132,10 @@ class CMutableBuffer : public facebook::jsi::MutableBuffer {
 | 
			
		||||
It is strongly recommended to create a stub function to perform the entire
 | 
			
		||||
workflow in JS code and pass the final result back to C++.
 | 
			
		||||
 | 
			
		||||
> _JS Stub function_
 | 
			
		||||
>
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
The stub function will be passed an `ArrayBuffer` object:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
function(buf) {
 | 
			
		||||
  /* `buf` will be an ArrayBuffer */
 | 
			
		||||
@ -127,6 +144,8 @@ function(buf) {
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
_C++ integration code_
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
 | 
			
		||||
@ -3,19 +3,102 @@ sidebar_position: 1
 | 
			
		||||
title: Addresses and Ranges
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
export const g = {style: {backgroundColor:"green"}};
 | 
			
		||||
 | 
			
		||||
Each cell in a worksheet has a unique address which specifies the row and the
 | 
			
		||||
column that include the cell.
 | 
			
		||||
 | 
			
		||||
## Basic Concepts
 | 
			
		||||
 | 
			
		||||
### Rows
 | 
			
		||||
 | 
			
		||||
Spreadsheet applications typically display ordinal row numbers, where `1` is the
 | 
			
		||||
first row, `2` is the second row, etc. The numbering starts at `1`.
 | 
			
		||||
 | 
			
		||||
SheetJS follows JavaScript counting conventions, where `0` is the first row, `1`
 | 
			
		||||
is the second row, etc. The numbering starts at `0`.
 | 
			
		||||
 | 
			
		||||
The following table lists some example row labels:
 | 
			
		||||
 | 
			
		||||
| Ordinal   | Row Label |   SheetJS |
 | 
			
		||||
|:----------|----------:|----------:|
 | 
			
		||||
| First     |       `1` |       `0` |
 | 
			
		||||
| Second    |       `2` |       `1` |
 | 
			
		||||
| 26th      |      `26` |      `25` |
 | 
			
		||||
| 420th     |     `420` |     `419` |
 | 
			
		||||
| 7262nd    |    `7262` |    `7261` |
 | 
			
		||||
| 1048576th | `1048576` | `1048575` |
 | 
			
		||||
 | 
			
		||||
### Columns
 | 
			
		||||
 | 
			
		||||
Spreadsheet applications typically use letters to represent columns.
 | 
			
		||||
 | 
			
		||||
The first column is `A`, the second column is `B`, and the 26th column is `Z`.
 | 
			
		||||
After `Z`, the next column is `AA` and counting continues through `AZ`.  After
 | 
			
		||||
`AZ`, the count continues with `BA`. After `ZZ`, the count continues with `AAA`.
 | 
			
		||||
 | 
			
		||||
Some sample values, along with SheetJS column indices, are listed below:
 | 
			
		||||
 | 
			
		||||
| Ordinal | Column Label | SheetJS |
 | 
			
		||||
|:--------|:-------------|--------:|
 | 
			
		||||
| First   | `A`          |     `0` |
 | 
			
		||||
| Second  | `B`          |     `1` |
 | 
			
		||||
| 26th    | `Z`          |    `25` |
 | 
			
		||||
| 27th    | `AA`         |    `26` |
 | 
			
		||||
| 420th   | `PD`         |   `419` |
 | 
			
		||||
| 702nd   | `ZZ`         |   `701` |
 | 
			
		||||
| 703rd   | `AAA`        |   `702` |
 | 
			
		||||
| 7262nd  | `JSH`        |  `7261` |
 | 
			
		||||
| 16384th | `XFD`        | `16383` |
 | 
			
		||||
 | 
			
		||||
## Cell Addresses
 | 
			
		||||
 | 
			
		||||
### A1-Style
 | 
			
		||||
 | 
			
		||||
A1-Style is the default address style in Lotus 1-2-3 and Excel.
 | 
			
		||||
 | 
			
		||||
A cell address is the concatenation of column label and row label.
 | 
			
		||||
 | 
			
		||||
For example, the cell in the third column and fourth row is `C4`, concatenating
 | 
			
		||||
the third column label (`C`) and the fourth row label (`4`)
 | 
			
		||||
 | 
			
		||||
### SheetJS Cell Address
 | 
			
		||||
 | 
			
		||||
Cell address objects are stored as `{c:C, r:R}` where `C` and `R` are 0-indexed
 | 
			
		||||
column and row numbers, respectively.  For example, the cell address `B5` is
 | 
			
		||||
represented by the object `{c:1, r:4}`.
 | 
			
		||||
 | 
			
		||||
## Cell Ranges
 | 
			
		||||
 | 
			
		||||
### A1-Style
 | 
			
		||||
 | 
			
		||||
A cell range is represented as the top-left cell of the range, followed by `:`,
 | 
			
		||||
followed by the bottom-right cell of the range. For example, the range `"C2:D4"`
 | 
			
		||||
includes the 6 green cells in the following table:
 | 
			
		||||
 | 
			
		||||
<table><tbody>
 | 
			
		||||
  <tr><th> </th><th>A</th><th>B</th><th>C</th><th>D</th><th>E</th></tr>
 | 
			
		||||
  <tr><th>1</th><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
 | 
			
		||||
  <tr><th>2</th><td> </td><td> </td><td {...g}></td><td {...g}></td><td> </td></tr>
 | 
			
		||||
  <tr><th>3</th><td> </td><td> </td><td {...g}></td><td {...g}></td><td> </td></tr>
 | 
			
		||||
  <tr><th>4</th><td> </td><td> </td><td {...g}></td><td {...g}></td><td> </td></tr>
 | 
			
		||||
  <tr><th>5</th><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
 | 
			
		||||
</tbody></table>
 | 
			
		||||
 | 
			
		||||
A column range is represented by the left-most column, followed by `:`, followed
 | 
			
		||||
by the right-most column.  For example, the range `C:D` represents the third and
 | 
			
		||||
fourth columns.
 | 
			
		||||
 | 
			
		||||
A row range is represented by the top-most row, followed by `:`, followed by the
 | 
			
		||||
bottom-most column.  For example, `2:4` represents the second/third/fourth rows.
 | 
			
		||||
 | 
			
		||||
### SheetJS Range
 | 
			
		||||
 | 
			
		||||
Cell range objects are stored as `{s:S, e:E}` where `S` is the first cell and
 | 
			
		||||
`E` is the last cell in the range.  The ranges are inclusive.  For example, the
 | 
			
		||||
range `A3:B7` is represented by the object `{s:{c:0, r:2}, e:{c:1, r:6}}`.
 | 
			
		||||
 | 
			
		||||
### Column and Row Ranges
 | 
			
		||||
#### Column and Row Ranges
 | 
			
		||||
 | 
			
		||||
A column range (spanning every row) is represented with the starting row `0` and
 | 
			
		||||
the ending row `1048575`:
 | 
			
		||||
@ -33,54 +116,9 @@ the ending col `16383`:
 | 
			
		||||
{ s: { c: 0, r: 1 }, e: { c: 16383, r: 2 } } // 2:3
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# Common Spreadsheet Address Styles
 | 
			
		||||
## Utilities
 | 
			
		||||
 | 
			
		||||
## A1-Style
 | 
			
		||||
 | 
			
		||||
A1-Style is the default address style in Lotus 1-2-3 and Excel.
 | 
			
		||||
 | 
			
		||||
Columns are specified with letters, counting from `A` to `Z`, then `AA` to `ZZ`,
 | 
			
		||||
then `AAA`.  Some sample values, along with SheetJS column indices, are listed:
 | 
			
		||||
 | 
			
		||||
| Ordinal | `A1`    | SheetJS |
 | 
			
		||||
|:--------|:--------|--------:|
 | 
			
		||||
| First   | `A`     |     `0` |
 | 
			
		||||
| Second  | `B`     |     `1` |
 | 
			
		||||
| 26th    | `Z`     |    `25` |
 | 
			
		||||
| 27th    | `AA`    |    `26` |
 | 
			
		||||
| 702nd   | `ZZ`    |   `701` |
 | 
			
		||||
| 703rd   | `AAA`   |   `702` |
 | 
			
		||||
| 16384th | `XFD`   | `16383` |
 | 
			
		||||
 | 
			
		||||
Rows are specified with numbers, starting from `1` for the first row.  SheetJS
 | 
			
		||||
APIs that take row indices start from `0` (ECMAScript convention).
 | 
			
		||||
 | 
			
		||||
A cell address is the concatenation of column text and row number.  For example,
 | 
			
		||||
the cell in the third column and fourth row is "C4".
 | 
			
		||||
 | 
			
		||||
A cell range is represented as the top-left cell of the range, followed by `:`,
 | 
			
		||||
followed by the bottom-right cell of the range. For example, the range `"C2:D4"`
 | 
			
		||||
includes 6 cells marked with ▒ in the table below:
 | 
			
		||||
 | 
			
		||||
<table><tbody>
 | 
			
		||||
  <tr><th> </th><th>A</th><th>B</th><th>C</th><th>D</th><th>E</th></tr>
 | 
			
		||||
  <tr><th>1</th><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
 | 
			
		||||
  <tr><th>2</th><td> </td><td> </td><td>▒</td><td>▒</td><td> </td></tr>
 | 
			
		||||
  <tr><th>3</th><td> </td><td> </td><td>▒</td><td>▒</td><td> </td></tr>
 | 
			
		||||
  <tr><th>4</th><td> </td><td> </td><td>▒</td><td>▒</td><td> </td></tr>
 | 
			
		||||
  <tr><th>5</th><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
 | 
			
		||||
</tbody></table>
 | 
			
		||||
 | 
			
		||||
A column range is represented by the left-most column, followed by `:`, followed
 | 
			
		||||
by the right-most column.  For example, the range `C:D` represents the third and
 | 
			
		||||
fourth columns.
 | 
			
		||||
 | 
			
		||||
A row range is represented by the top-most row, followed by `:`, followed by the
 | 
			
		||||
bottom-most column.  For example, `2:4` represents the second/third/fourth rows.
 | 
			
		||||
 | 
			
		||||
### Utilities
 | 
			
		||||
 | 
			
		||||
#### Column Names
 | 
			
		||||
### Column Names
 | 
			
		||||
 | 
			
		||||
_Get the SheetJS index from an A1-Style column_
 | 
			
		||||
 | 
			
		||||
@ -98,7 +136,7 @@ var col_name = XLSX.utils.encode_col(3);
 | 
			
		||||
 | 
			
		||||
The argument is expected to be a SheetJS column (non-negative integer).
 | 
			
		||||
 | 
			
		||||
#### Row Names
 | 
			
		||||
### Row Names
 | 
			
		||||
 | 
			
		||||
_Get the SheetJS index from an A1-Style row_
 | 
			
		||||
 | 
			
		||||
@ -116,7 +154,7 @@ var row_name = XLSX.utils.encode_row(3);
 | 
			
		||||
 | 
			
		||||
The argument is expected to be a SheetJS column (non-negative integer).
 | 
			
		||||
 | 
			
		||||
#### Cell Addresses
 | 
			
		||||
### Cell Addresses
 | 
			
		||||
 | 
			
		||||
_Generate a SheetJS cell address from an A1-Style address string_
 | 
			
		||||
 | 
			
		||||
@ -134,7 +172,7 @@ var a1_addr = XLSX.utils.encode_cell({r:1, c:0});
 | 
			
		||||
 | 
			
		||||
The argument is expected to be a SheetJS cell address
 | 
			
		||||
 | 
			
		||||
#### Cell Ranges
 | 
			
		||||
### Cell Ranges
 | 
			
		||||
 | 
			
		||||
_Generate a SheetJS cell range from an A1-Style range string_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -104,6 +104,7 @@ Read functions attempt to populate all three properties.  Write functions will
 | 
			
		||||
try to cycle specified values to the desired type.  In order to avoid potential
 | 
			
		||||
conflicts, manipulation should delete the other properties first.  For example,
 | 
			
		||||
when changing the pixel width, delete the `wch` and `width` properties.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
@ -222,10 +223,6 @@ function Visibility(props) {
 | 
			
		||||
 | 
			
		||||
    </tr>))}</tbody></table>);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,9 +7,12 @@ title: Common Spreadsheet Format
 | 
			
		||||
import DocCardList from '@theme/DocCardList';
 | 
			
		||||
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
 | 
			
		||||
 | 
			
		||||
The "Common Spreadsheet Format" is the object model used by SheetJS. This
 | 
			
		||||
section covers the JS representation of workbooks, worksheets, cells, ranges,
 | 
			
		||||
addresses and other features.
 | 
			
		||||
The "Common Spreadsheet Format" is the object model used by SheetJS. The library
 | 
			
		||||
[includes a number of API functions](/docs/api) for common operations, but some
 | 
			
		||||
features are only accessible by inspecting and modifying the objects directly.
 | 
			
		||||
 | 
			
		||||
This section covers the JS representation of workbooks, worksheets, cells,
 | 
			
		||||
ranges, addresses and other features.
 | 
			
		||||
 | 
			
		||||
### Contents
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,15 +4,26 @@ sidebar_position: 5
 | 
			
		||||
title: API Reference
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## Interface Summary
 | 
			
		||||
import current from '/version.js';
 | 
			
		||||
 | 
			
		||||
`XLSX` is the exposed variable in the browser and the exported node variable
 | 
			
		||||
This section lists the functions defined in the library.
 | 
			
		||||
 | 
			
		||||
`XLSX.version` is the version of the library (added by the build script).
 | 
			
		||||
Using the ["Standalone" scripts](/docs/getting-started/installation/standalone),
 | 
			
		||||
`XLSX` is added to the `window` or other `global` object.
 | 
			
		||||
 | 
			
		||||
`XLSX.SSF` is an embedded version of the [format library](https://git.sheetjs.com/sheetjs/sheetjs/src/branch/master/packages/ssf).
 | 
			
		||||
Using the ["NodeJS" module](/docs/getting-started/installation/nodejs), the
 | 
			
		||||
`XLSX` variable refers to the CommonJS export:
 | 
			
		||||
 | 
			
		||||
`XLSX.CFB` is an embedded version of the [container library](https://git.sheetjs.com/sheetjs/js-cfb).
 | 
			
		||||
```js
 | 
			
		||||
var XLSX = require("xlsx");
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Using [a framework](/docs/getting-started/installation/frameworks), the `XLSX`
 | 
			
		||||
variable refers to the glob import:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
import * as XLSX from "xlsx";
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Parsing functions
 | 
			
		||||
 | 
			
		||||
@ -127,4 +138,20 @@ for different languages in XLS or text parsing.
 | 
			
		||||
provides NodeJS ESM support for `XLSX.readFile` and `XLSX.writeFile`.
 | 
			
		||||
 | 
			
		||||
`XLSX.utils.set_readable` supplies a NodeJS `stream.Readable` constructor.  This
 | 
			
		||||
provides NodeJS ESM support for the streaming operations.
 | 
			
		||||
provides NodeJS ESM support for the streaming operations.
 | 
			
		||||
 | 
			
		||||
ESM helper functions are described in the ["NodeJS" Installation section](/docs/getting-started/installation/nodejs)
 | 
			
		||||
 | 
			
		||||
## Miscellaneous
 | 
			
		||||
 | 
			
		||||
`XLSX.version` is the version of the library.
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
<p>The current version is <code>{current}</code></p>
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
`XLSX.SSF` is an embedded version of the [format library](https://git.sheetjs.com/sheetjs/sheetjs/src/branch/master/packages/ssf).
 | 
			
		||||
 | 
			
		||||
`XLSX.CFB` is an embedded version of the [container library](https://git.sheetjs.com/sheetjs/js-cfb).
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@ const config = {
 | 
			
		||||
      ({
 | 
			
		||||
        docs: {
 | 
			
		||||
          sidebarPath: require.resolve('./sidebars.js'),
 | 
			
		||||
          showLastUpdateTime: true,
 | 
			
		||||
          editUrl: 'https://git.sheetjs.com/sheetjs/docs.sheetjs.com/src/branch/master/docz',
 | 
			
		||||
        },
 | 
			
		||||
        //blog: {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										180
									
								
								docz/src/theme/Admonition/index.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										180
									
								
								docz/src/theme/Admonition/index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,180 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import clsx from 'clsx';
 | 
			
		||||
import {ThemeClassNames} from '@docusaurus/theme-common';
 | 
			
		||||
import Translate from '@docusaurus/Translate';
 | 
			
		||||
import styles from './styles.module.css';
 | 
			
		||||
function NoteIcon() {
 | 
			
		||||
  return (
 | 
			
		||||
    <svg viewBox="0 0 14 16">
 | 
			
		||||
      <path
 | 
			
		||||
        fillRule="evenodd"
 | 
			
		||||
        d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
 | 
			
		||||
      />
 | 
			
		||||
    </svg>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
function TipIcon() {
 | 
			
		||||
  return (
 | 
			
		||||
    <svg viewBox="0 0 12 16">
 | 
			
		||||
      <path
 | 
			
		||||
        fillRule="evenodd"
 | 
			
		||||
        d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"
 | 
			
		||||
      />
 | 
			
		||||
    </svg>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
function DangerIcon() {
 | 
			
		||||
  return (
 | 
			
		||||
    <svg viewBox="0 0 12 16">
 | 
			
		||||
      <path
 | 
			
		||||
        fillRule="evenodd"
 | 
			
		||||
        d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"
 | 
			
		||||
      />
 | 
			
		||||
    </svg>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
function InfoIcon() {
 | 
			
		||||
  return (
 | 
			
		||||
    <svg viewBox="0 0 14 16">
 | 
			
		||||
      <path
 | 
			
		||||
        fillRule="evenodd"
 | 
			
		||||
        d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"
 | 
			
		||||
      />
 | 
			
		||||
    </svg>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
function CautionIcon() {
 | 
			
		||||
  return (
 | 
			
		||||
    <svg viewBox="0 0 16 16">
 | 
			
		||||
      <path
 | 
			
		||||
        fillRule="evenodd"
 | 
			
		||||
        d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"
 | 
			
		||||
      />
 | 
			
		||||
    </svg>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
 | 
			
		||||
const AdmonitionConfigs = {
 | 
			
		||||
  note: {
 | 
			
		||||
    infimaClassName: 'secondary',
 | 
			
		||||
    iconComponent: NoteIcon,
 | 
			
		||||
    label: (
 | 
			
		||||
      <Translate
 | 
			
		||||
        id="theme.admonition.note"
 | 
			
		||||
        description="The default label used for the Note admonition (:::note)">
 | 
			
		||||
        note
 | 
			
		||||
      </Translate>
 | 
			
		||||
    ),
 | 
			
		||||
  },
 | 
			
		||||
  tip: {
 | 
			
		||||
    infimaClassName: 'success',
 | 
			
		||||
    iconComponent: TipIcon,
 | 
			
		||||
    label: (
 | 
			
		||||
      <Translate
 | 
			
		||||
        id="theme.admonition.tip"
 | 
			
		||||
        description="The default label used for the Tip admonition (:::tip)">
 | 
			
		||||
        tip
 | 
			
		||||
      </Translate>
 | 
			
		||||
    ),
 | 
			
		||||
  },
 | 
			
		||||
  danger: {
 | 
			
		||||
    infimaClassName: 'danger',
 | 
			
		||||
    iconComponent: DangerIcon,
 | 
			
		||||
    label: (
 | 
			
		||||
      <Translate
 | 
			
		||||
        id="theme.admonition.danger"
 | 
			
		||||
        description="The default label used for the Danger admonition (:::danger)">
 | 
			
		||||
        danger
 | 
			
		||||
      </Translate>
 | 
			
		||||
    ),
 | 
			
		||||
  },
 | 
			
		||||
  info: {
 | 
			
		||||
    infimaClassName: 'info',
 | 
			
		||||
    iconComponent: InfoIcon,
 | 
			
		||||
    label: (
 | 
			
		||||
      <Translate
 | 
			
		||||
        id="theme.admonition.info"
 | 
			
		||||
        description="The default label used for the Info admonition (:::info)">
 | 
			
		||||
        info
 | 
			
		||||
      </Translate>
 | 
			
		||||
    ),
 | 
			
		||||
  },
 | 
			
		||||
  caution: {
 | 
			
		||||
    infimaClassName: 'warning',
 | 
			
		||||
    iconComponent: CautionIcon,
 | 
			
		||||
    label: (
 | 
			
		||||
      <Translate
 | 
			
		||||
        id="theme.admonition.caution"
 | 
			
		||||
        description="The default label used for the Caution admonition (:::caution)">
 | 
			
		||||
        caution
 | 
			
		||||
      </Translate>
 | 
			
		||||
    ),
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
// Legacy aliases, undocumented but kept for retro-compatibility
 | 
			
		||||
const aliases = {
 | 
			
		||||
  secondary: 'note',
 | 
			
		||||
  important: 'info',
 | 
			
		||||
  success: 'tip',
 | 
			
		||||
  warning: 'danger',
 | 
			
		||||
};
 | 
			
		||||
function getAdmonitionConfig(unsafeType) {
 | 
			
		||||
  const type = aliases[unsafeType] ?? unsafeType;
 | 
			
		||||
  const config = AdmonitionConfigs[type];
 | 
			
		||||
  if (config) {
 | 
			
		||||
    return config;
 | 
			
		||||
  }
 | 
			
		||||
  console.warn(
 | 
			
		||||
    `No admonition config found for admonition type "${type}". Using Info as fallback.`,
 | 
			
		||||
  );
 | 
			
		||||
  return AdmonitionConfigs.info;
 | 
			
		||||
}
 | 
			
		||||
// Workaround because it's difficult in MDX v1 to provide a MDX title as props
 | 
			
		||||
// See https://github.com/facebook/docusaurus/pull/7152#issuecomment-1145779682
 | 
			
		||||
function extractMDXAdmonitionTitle(children) {
 | 
			
		||||
  const items = React.Children.toArray(children);
 | 
			
		||||
  const mdxAdmonitionTitle = items.find(
 | 
			
		||||
    (item) =>
 | 
			
		||||
      React.isValidElement(item) &&
 | 
			
		||||
      item.props?.mdxType === 'mdxAdmonitionTitle',
 | 
			
		||||
  );
 | 
			
		||||
  const rest = <>{items.filter((item) => item !== mdxAdmonitionTitle)}</>;
 | 
			
		||||
  return {
 | 
			
		||||
    mdxAdmonitionTitle,
 | 
			
		||||
    rest,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
function processAdmonitionProps(props) {
 | 
			
		||||
  const {mdxAdmonitionTitle, rest} = extractMDXAdmonitionTitle(props.children);
 | 
			
		||||
  return {
 | 
			
		||||
    ...props,
 | 
			
		||||
    title: props.title ?? mdxAdmonitionTitle,
 | 
			
		||||
    children: rest,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
export default function Admonition(props) {
 | 
			
		||||
  const {children, type, title, icon: iconProp} = processAdmonitionProps(props);
 | 
			
		||||
  const typeConfig = getAdmonitionConfig(type);
 | 
			
		||||
  const titleLabel = title ?? typeConfig.label;
 | 
			
		||||
  const {iconComponent: IconComponent} = typeConfig;
 | 
			
		||||
  const icon = iconProp ?? <IconComponent />;
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={clsx(
 | 
			
		||||
        ThemeClassNames.common.admonition,
 | 
			
		||||
        ThemeClassNames.common.admonitionType(props.type),
 | 
			
		||||
        'alert',
 | 
			
		||||
        `alert--${typeConfig.infimaClassName}`,
 | 
			
		||||
        styles.admonition,
 | 
			
		||||
      )}>
 | 
			
		||||
      {titleLabel == "pass" ? void 0 : (
 | 
			
		||||
        <div className={styles.admonitionHeading}>
 | 
			
		||||
        <span className={styles.admonitionIcon}>{icon}</span>
 | 
			
		||||
        {titleLabel}
 | 
			
		||||
      </div>
 | 
			
		||||
      )}
 | 
			
		||||
      <div className={styles.admonitionContent}>{children}</div>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
/* See docusaurus issue 8568 -- this was swizzled against 2.4.1 */
 | 
			
		||||
							
								
								
									
										31
									
								
								docz/src/theme/Admonition/styles.module.css
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										31
									
								
								docz/src/theme/Admonition/styles.module.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
.admonition {
 | 
			
		||||
  margin-bottom: 1em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.admonitionHeading {
 | 
			
		||||
  font: var(--ifm-heading-font-weight) var(--ifm-h5-font-size) /
 | 
			
		||||
    var(--ifm-heading-line-height) var(--ifm-heading-font-family);
 | 
			
		||||
  text-transform: uppercase;
 | 
			
		||||
  margin-bottom: 0.3rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.admonitionHeading code {
 | 
			
		||||
  text-transform: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.admonitionIcon {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  vertical-align: middle;
 | 
			
		||||
  margin-right: 0.4em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.admonitionIcon svg {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  height: 1.6em;
 | 
			
		||||
  width: 1.6em;
 | 
			
		||||
  fill: var(--ifm-alert-foreground-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.admonitionContent > :last-child {
 | 
			
		||||
  margin-bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								docz/static/vitejs/table.png
									
									
									
									
									
										Normal file
									
								
							
							
								
									
								
								
								
								
								
									
									
								
							
						
						
									
										
											BIN
										
									
								
								docz/static/vitejs/table.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 26 KiB  | 
		Loading…
	
		Reference in New Issue
	
	Block a user