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