saurus-excel 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +278 -106
- package/dist/astro.js +3 -3
- package/dist/astro.js.map +1 -1
- package/dist/index.d.ts +43 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +83 -45
- package/dist/react.js +1 -2
- package/dist/react.js.map +1 -1
- package/dist/worker.js +3 -3
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/pkg/excelsaurus.d.ts +13 -0
- package/pkg/excelsaurus.js +31 -0
- package/pkg/excelsaurus_bg.wasm +0 -0
- package/pkg/excelsaurus_bg.wasm.d.ts +1 -0
package/README.md
CHANGED
|
@@ -1,82 +1,121 @@
|
|
|
1
|
-
# 🦖
|
|
1
|
+
# 🦖 Saurus-Excel
|
|
2
2
|
|
|
3
|
-
> Blazingly fast Excel parser for the web - powered by Rust & WebAssembly
|
|
3
|
+
> Blazingly fast Excel & CSV parser for the web - powered by Rust & WebAssembly
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/saurus-excel)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Saurus-Excel is a high-performance spreadsheet parser designed for handling **large datasets** in the browser. Built with Rust and compiled to WebAssembly, it processes millions of rows without crashing your browser.
|
|
9
9
|
|
|
10
10
|
## ✨ Features
|
|
11
11
|
|
|
12
12
|
- 🚀 **Blazingly Fast** - 10x faster than SheetJS for large files
|
|
13
|
-
- 💾 **Memory Efficient** -
|
|
14
|
-
- 📊 **Multiple Formats** - XLSX, XLS, XLSM, XLSB, ODS
|
|
15
|
-
-
|
|
16
|
-
- ⚛️ **Framework Support** - React hooks & Astro components included
|
|
13
|
+
- 💾 **Memory Efficient** - Minimal RAM usage
|
|
14
|
+
- 📊 **Multiple Formats** - XLSX, XLS, XLSM, XLSB, ODS, **CSV**
|
|
15
|
+
- ⚛️ **Framework Support** - React hooks included
|
|
17
16
|
- 🔧 **TypeScript First** - Full type definitions
|
|
17
|
+
- 📄 **CSV Support** - Parse CSV with custom delimiters
|
|
18
18
|
|
|
19
19
|
## 📦 Installation
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
npm install
|
|
22
|
+
npm install saurus-excel
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
### Basic Usage
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
import { parseExcel } from "excelsaurus";
|
|
31
|
-
|
|
32
|
-
// Parse from file input
|
|
33
|
-
const file = event.target.files[0];
|
|
34
|
-
const result = await parseExcel(file);
|
|
25
|
+
---
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
## 🚀 Usage
|
|
28
|
+
|
|
29
|
+
### Vanilla JavaScript (Browser)
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<!DOCTYPE html>
|
|
33
|
+
<html>
|
|
34
|
+
<head>
|
|
35
|
+
<title>Excel Parser</title>
|
|
36
|
+
</head>
|
|
37
|
+
<body>
|
|
38
|
+
<input type="file" id="fileInput" accept=".xlsx,.xls" />
|
|
39
|
+
<pre id="output"></pre>
|
|
40
|
+
|
|
41
|
+
<script type="module">
|
|
42
|
+
// Import from pkg folder for direct Wasm access
|
|
43
|
+
import init, { parseExcel } from "saurus-excel/pkg/excelsaurus.js";
|
|
44
|
+
|
|
45
|
+
// Initialize Wasm module (required once)
|
|
46
|
+
await init();
|
|
47
|
+
|
|
48
|
+
document
|
|
49
|
+
.getElementById("fileInput")
|
|
50
|
+
.addEventListener("change", async (e) => {
|
|
51
|
+
const file = e.target.files[0];
|
|
52
|
+
if (!file) return;
|
|
53
|
+
|
|
54
|
+
// Read file as bytes
|
|
55
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
56
|
+
const bytes = new Uint8Array(arrayBuffer);
|
|
57
|
+
|
|
58
|
+
// Parse Excel
|
|
59
|
+
const result = parseExcel(bytes, { hasHeaders: true });
|
|
60
|
+
|
|
61
|
+
console.log(result.headers); // ["Name", "Email", "Age"]
|
|
62
|
+
console.log(result.rows); // [["John", "john@example.com", 30], ...]
|
|
63
|
+
|
|
64
|
+
document.getElementById("output").textContent = JSON.stringify(
|
|
65
|
+
result,
|
|
66
|
+
null,
|
|
67
|
+
2,
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
</script>
|
|
71
|
+
</body>
|
|
72
|
+
</html>
|
|
39
73
|
```
|
|
40
74
|
|
|
41
|
-
### With
|
|
75
|
+
### With Bundler (Vite, Webpack, etc.)
|
|
42
76
|
|
|
43
77
|
```typescript
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
### Streaming Large Files
|
|
78
|
+
// Note: Wasm needs special bundler config (see below)
|
|
79
|
+
import init, {
|
|
80
|
+
parseExcel,
|
|
81
|
+
getSheetNames,
|
|
82
|
+
} from "saurus-excel/pkg/excelsaurus.js";
|
|
83
|
+
|
|
84
|
+
// Initialize once at app startup
|
|
85
|
+
let initialized = false;
|
|
86
|
+
async function ensureInit() {
|
|
87
|
+
if (!initialized) {
|
|
88
|
+
await init();
|
|
89
|
+
initialized = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
59
92
|
|
|
60
|
-
|
|
61
|
-
|
|
93
|
+
export async function parseExcelFile(file: File) {
|
|
94
|
+
await ensureInit();
|
|
62
95
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
onProgress: (p) => console.log(`${p.percent}%`),
|
|
66
|
-
});
|
|
96
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
97
|
+
const bytes = new Uint8Array(arrayBuffer);
|
|
67
98
|
|
|
68
|
-
|
|
69
|
-
|
|
99
|
+
return parseExcel(bytes, {
|
|
100
|
+
hasHeaders: true,
|
|
101
|
+
limit: 1000, // Optional: limit rows
|
|
102
|
+
});
|
|
70
103
|
}
|
|
71
104
|
```
|
|
72
105
|
|
|
73
|
-
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## ⚛️ React 19 / Next.js (Plug & Play)
|
|
109
|
+
|
|
110
|
+
### Quick Start
|
|
74
111
|
|
|
75
112
|
```tsx
|
|
76
|
-
import { useExcelParser } from "
|
|
113
|
+
import { useExcelParser } from "saurus-excel/react";
|
|
114
|
+
|
|
115
|
+
function ImportPage() {
|
|
116
|
+
const { parse, data, loading, error, ready } = useExcelParser();
|
|
77
117
|
|
|
78
|
-
|
|
79
|
-
const { parse, data, isLoading, progress, error } = useExcelParser();
|
|
118
|
+
if (!ready) return <p>Loading parser...</p>;
|
|
80
119
|
|
|
81
120
|
return (
|
|
82
121
|
<div>
|
|
@@ -85,98 +124,231 @@ function ImportComponent() {
|
|
|
85
124
|
accept=".xlsx,.xls"
|
|
86
125
|
onChange={(e) => e.target.files?.[0] && parse(e.target.files[0])}
|
|
87
126
|
/>
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
{error && <
|
|
127
|
+
|
|
128
|
+
{loading && <p>Parsing...</p>}
|
|
129
|
+
{error && <p style={{ color: "red" }}>{error.message}</p>}
|
|
130
|
+
|
|
131
|
+
{data && (
|
|
132
|
+
<table>
|
|
133
|
+
<thead>
|
|
134
|
+
<tr>
|
|
135
|
+
{data.headers.map((h, i) => (
|
|
136
|
+
<th key={i}>{h}</th>
|
|
137
|
+
))}
|
|
138
|
+
</tr>
|
|
139
|
+
</thead>
|
|
140
|
+
<tbody>
|
|
141
|
+
{data.rows.map((row, i) => (
|
|
142
|
+
<tr key={i}>
|
|
143
|
+
{row.map((cell, j) => (
|
|
144
|
+
<td key={j}>{cell}</td>
|
|
145
|
+
))}
|
|
146
|
+
</tr>
|
|
147
|
+
))}
|
|
148
|
+
</tbody>
|
|
149
|
+
</table>
|
|
150
|
+
)}
|
|
91
151
|
</div>
|
|
92
152
|
);
|
|
93
153
|
}
|
|
94
154
|
```
|
|
95
155
|
|
|
96
|
-
###
|
|
156
|
+
### With Provider (Recommended for Next.js App Router)
|
|
97
157
|
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<excel-importer on-complete="handleData"></excel-importer>
|
|
158
|
+
```tsx
|
|
159
|
+
// app/providers.tsx
|
|
160
|
+
"use client";
|
|
161
|
+
import { ExcelProvider } from "saurus-excel/react";
|
|
103
162
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
163
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
164
|
+
return <ExcelProvider>{children}</ExcelProvider>;
|
|
165
|
+
}
|
|
107
166
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
167
|
+
// app/layout.tsx
|
|
168
|
+
import { Providers } from "./providers";
|
|
169
|
+
|
|
170
|
+
export default function RootLayout({ children }) {
|
|
171
|
+
return (
|
|
172
|
+
<html>
|
|
173
|
+
<body>
|
|
174
|
+
<Providers>{children}</Providers>
|
|
175
|
+
</body>
|
|
176
|
+
</html>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
112
179
|
```
|
|
113
180
|
|
|
114
|
-
###
|
|
181
|
+
### Drop-in Component
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
import { ExcelDropzone } from "saurus-excel/react";
|
|
185
|
+
|
|
186
|
+
function UploadPage() {
|
|
187
|
+
return (
|
|
188
|
+
<ExcelDropzone
|
|
189
|
+
onData={(result) => {
|
|
190
|
+
console.log("Headers:", result.headers);
|
|
191
|
+
console.log("Rows:", result.rows);
|
|
192
|
+
}}
|
|
193
|
+
onError={(err) => console.error(err)}
|
|
194
|
+
options={{ hasHeaders: true, limit: 1000 }}
|
|
195
|
+
/>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Available Hooks
|
|
201
|
+
|
|
202
|
+
| Hook | Description |
|
|
203
|
+
| ------------------ | --------------------------- |
|
|
204
|
+
| `useExcelParser()` | Main hook for parsing files |
|
|
205
|
+
| `useExcelSheets()` | Get sheet names from file |
|
|
206
|
+
|
|
207
|
+
### Hook Return Values
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
const {
|
|
211
|
+
parse, // (file: File, options?) => Promise<ParseResult>
|
|
212
|
+
data, // ParseResult | null
|
|
213
|
+
loading, // boolean
|
|
214
|
+
error, // Error | null
|
|
215
|
+
progress, // number (0-100)
|
|
216
|
+
ready, // boolean - Wasm loaded
|
|
217
|
+
reset, // () => void
|
|
218
|
+
} = useExcelParser();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## ⚙️ Bundler Configuration
|
|
224
|
+
|
|
225
|
+
### Vite
|
|
115
226
|
|
|
116
227
|
```typescript
|
|
117
|
-
|
|
228
|
+
// vite.config.ts
|
|
229
|
+
import { defineConfig } from "vite";
|
|
230
|
+
|
|
231
|
+
export default defineConfig({
|
|
232
|
+
optimizeDeps: {
|
|
233
|
+
exclude: ["saurus-excel"],
|
|
234
|
+
},
|
|
235
|
+
build: {
|
|
236
|
+
target: "esnext",
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
```
|
|
118
240
|
|
|
119
|
-
|
|
241
|
+
### Next.js
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
// next.config.js
|
|
245
|
+
module.exports = {
|
|
246
|
+
webpack: (config) => {
|
|
247
|
+
config.experiments = {
|
|
248
|
+
...config.experiments,
|
|
249
|
+
asyncWebAssembly: true,
|
|
250
|
+
};
|
|
251
|
+
return config;
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
```
|
|
120
255
|
|
|
121
|
-
|
|
122
|
-
worker.onComplete((result) => displayData(result));
|
|
123
|
-
worker.onError((err) => showError(err));
|
|
256
|
+
### Webpack 5
|
|
124
257
|
|
|
125
|
-
|
|
258
|
+
```javascript
|
|
259
|
+
// webpack.config.js
|
|
260
|
+
module.exports = {
|
|
261
|
+
experiments: {
|
|
262
|
+
asyncWebAssembly: true,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
126
265
|
```
|
|
127
266
|
|
|
267
|
+
---
|
|
268
|
+
|
|
128
269
|
## 📖 API Reference
|
|
129
270
|
|
|
130
|
-
### parseExcel(
|
|
271
|
+
### parseExcel(bytes, options?)
|
|
131
272
|
|
|
132
|
-
Parse an Excel file
|
|
273
|
+
Parse an Excel file from Uint8Array.
|
|
133
274
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
275
|
+
```typescript
|
|
276
|
+
const result = parseExcel(bytes, {
|
|
277
|
+
sheet: 0, // Sheet index or name (default: 0)
|
|
278
|
+
limit: 1000, // Max rows to parse (default: all)
|
|
279
|
+
skipRows: 0, // Rows to skip from start
|
|
280
|
+
hasHeaders: true, // Treat first row as headers
|
|
281
|
+
});
|
|
282
|
+
```
|
|
140
283
|
|
|
141
|
-
|
|
284
|
+
**Returns:**
|
|
142
285
|
|
|
143
|
-
|
|
286
|
+
```typescript
|
|
287
|
+
{
|
|
288
|
+
headers: string[]; // Column headers
|
|
289
|
+
rows: CellValue[][]; // Row data
|
|
290
|
+
rowCount: number; // Total rows parsed
|
|
291
|
+
sheetName: string; // Sheet name
|
|
292
|
+
}
|
|
293
|
+
```
|
|
144
294
|
|
|
145
|
-
|
|
146
|
-
| ------------ | ------------------ | ------------------------------------------------------- |
|
|
147
|
-
| `name` | `string` | Output field name |
|
|
148
|
-
| `column` | `number \| string` | Column index (0-based) or letter (A, B, C...) |
|
|
149
|
-
| `type` | `string` | `string`, `number`, `integer`, `boolean`, `date`, `any` |
|
|
150
|
-
| `required` | `boolean` | Is field required? |
|
|
151
|
-
| `validate` | `string` | Built-in validator: `email`, `phone`, `url`, `nonempty` |
|
|
152
|
-
| `default` | `any` | Default value if empty |
|
|
295
|
+
### getSheetNames(bytes)
|
|
153
296
|
|
|
154
|
-
|
|
297
|
+
Get list of sheet names in workbook.
|
|
155
298
|
|
|
156
|
-
|
|
299
|
+
```typescript
|
|
300
|
+
const sheets = getSheetNames(bytes);
|
|
301
|
+
// ["Sheet1", "Sheet2", "Data"]
|
|
302
|
+
```
|
|
157
303
|
|
|
158
|
-
|
|
159
|
-
| ------------ | ---------- | ------- | ----------------- |
|
|
160
|
-
| `chunkSize` | `number` | `1000` | Rows per chunk |
|
|
161
|
-
| `onProgress` | `function` | - | Progress callback |
|
|
304
|
+
### parseCsv(bytes, options?)
|
|
162
305
|
|
|
163
|
-
|
|
306
|
+
Parse a CSV file.
|
|
164
307
|
|
|
165
|
-
|
|
308
|
+
```typescript
|
|
309
|
+
import { parseCsv } from "saurus-excel";
|
|
310
|
+
|
|
311
|
+
const result = await parseCsv(file, {
|
|
312
|
+
delimiter: ",", // Delimiter character (default: ',')
|
|
313
|
+
hasHeaders: true, // First row is headers
|
|
314
|
+
limit: 1000, // Max rows to parse
|
|
315
|
+
skipRows: 0, // Rows to skip
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
console.log(result.headers); // ["name", "email", "age"]
|
|
319
|
+
console.log(result.rows); // [["John", "john@example.com", 30], ...]
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Supported delimiters:** `,` (comma), `;` (semicolon), `\t` (tab), `|` (pipe)
|
|
323
|
+
|
|
324
|
+
### parseSpreadsheet(file, options?)
|
|
325
|
+
|
|
326
|
+
Auto-detect file type and parse (Excel or CSV).
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
import { parseSpreadsheet } from "saurus-excel";
|
|
330
|
+
|
|
331
|
+
// Automatically handles .xlsx, .xls, .csv files
|
|
332
|
+
const result = await parseSpreadsheet(file, { hasHeaders: true });
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
166
336
|
|
|
167
337
|
## 🏎 Performance
|
|
168
338
|
|
|
169
|
-
|
|
339
|
+
Tested with 100,000 rows:
|
|
170
340
|
|
|
171
|
-
| Metric | SheetJS |
|
|
172
|
-
| ------------ | ------- |
|
|
173
|
-
| Parse Time | ~15s | ~2s
|
|
174
|
-
| Memory Usage | ~800MB | ~100MB
|
|
175
|
-
| Bundle Size | ~300KB | ~150KB
|
|
341
|
+
| Metric | SheetJS | Saurus-Excel | Improvement |
|
|
342
|
+
| ------------ | ------- | ------------ | --------------- |
|
|
343
|
+
| Parse Time | ~15s | ~2s | **7.5x faster** |
|
|
344
|
+
| Memory Usage | ~800MB | ~100MB | **8x less** |
|
|
345
|
+
| Bundle Size | ~300KB | ~150KB | **2x smaller** |
|
|
346
|
+
|
|
347
|
+
---
|
|
176
348
|
|
|
177
349
|
## 📝 License
|
|
178
350
|
|
|
179
|
-
MIT ©
|
|
351
|
+
MIT © trietcn
|
|
180
352
|
|
|
181
353
|
---
|
|
182
354
|
|
package/dist/astro.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var
|
|
2
|
-
${t.stack}`:r}function z(t){t<132||(
|
|
1
|
+
var U=Object.defineProperty;var M=(t,e)=>()=>(t&&(e=t(t=0)),e);var W=(t,e)=>{for(var n in e)U(t,n,{get:e[n],enumerable:true});};var O={};W(O,{default:()=>Y,getSheetNames:()=>B,init:()=>N,initSync:()=>J,parseCsv:()=>$,parseExcel:()=>V});function B(t){try{let s=o.__wbindgen_add_to_stack_pointer(-16),i=R(t,o.__wbindgen_export),c=_;o.getSheetNames(s,i,c);var e=u().getInt32(s+0,!0),n=u().getInt32(s+4,!0),r=u().getInt32(s+8,!0);if(r)throw d(n);return d(e)}finally{o.__wbindgen_add_to_stack_pointer(16);}}function N(){o.init();}function $(t,e){try{let i=o.__wbindgen_add_to_stack_pointer(-16),c=R(t,o.__wbindgen_export),l=_;o.parseCsv(i,c,l,f(e));var n=u().getInt32(i+0,!0),r=u().getInt32(i+4,!0),s=u().getInt32(i+8,!0);if(s)throw d(r);return d(n)}finally{o.__wbindgen_add_to_stack_pointer(16);}}function V(t,e){try{let i=o.__wbindgen_add_to_stack_pointer(-16),c=R(t,o.__wbindgen_export),l=_;o.parseExcel(i,c,l,f(e));var n=u().getInt32(i+0,!0),r=u().getInt32(i+4,!0),s=u().getInt32(i+8,!0);if(s)throw d(r);return d(n)}finally{o.__wbindgen_add_to_stack_pointer(16);}}function L(){return {__proto__:null,"./excelsaurus_bg.js":{__proto__:null,__wbg_Error_8c4e43fe74559d73:function(e,n){let r=Error(x(e,n));return f(r)},__wbg_Number_04624de7d0e8332d:function(e){return Number(a(e))},__wbg_String_8f0eb39a4a4c2f66:function(e,n){let r=String(a(n)),s=A(r,o.__wbindgen_export,o.__wbindgen_export2),i=_;u().setInt32(e+4,i,true),u().setInt32(e+0,s,true);},__wbg___wbindgen_bigint_get_as_i64_8fcf4ce7f1ca72a2:function(e,n){let r=a(n),s=typeof r=="bigint"?r:void 0;u().setBigInt64(e+8,g(s)?BigInt(0):s,true),u().setInt32(e+0,!g(s),true);},__wbg___wbindgen_boolean_get_bbbb1c18aa2f5e25:function(e){let n=a(e),r=typeof n=="boolean"?n:void 0;return g(r)?16777215:r?1:0},__wbg___wbindgen_debug_string_0bc8482c6e3508ae:function(e,n){let r=I(a(n)),s=A(r,o.__wbindgen_export,o.__wbindgen_export2),i=_;u().setInt32(e+4,i,true),u().setInt32(e+0,s,true);},__wbg___wbindgen_in_47fa6863be6f2f25:function(e,n){return a(e)in a(n)},__wbg___wbindgen_is_bigint_31b12575b56f32fc:function(e){return typeof a(e)=="bigint"},__wbg___wbindgen_is_null_ac34f5003991759a:function(e){return a(e)===null},__wbg___wbindgen_is_object_5ae8e5880f2c1fbd:function(e){let n=a(e);return typeof n=="object"&&n!==null},__wbg___wbindgen_is_undefined_9e4d92534c42d778:function(e){return a(e)===void 0},__wbg___wbindgen_jsval_eq_11888390b0186270:function(e,n){return a(e)===a(n)},__wbg___wbindgen_jsval_loose_eq_9dd77d8cd6671811:function(e,n){return a(e)==a(n)},__wbg___wbindgen_number_get_8ff4255516ccad3e:function(e,n){let r=a(n),s=typeof r=="number"?r:void 0;u().setFloat64(e+8,g(s)?0:s,true),u().setInt32(e+0,!g(s),true);},__wbg___wbindgen_string_get_72fb696202c56729:function(e,n){let r=a(n),s=typeof r=="string"?r:void 0;var i=g(s)?0:A(s,o.__wbindgen_export,o.__wbindgen_export2),c=_;u().setInt32(e+4,c,true),u().setInt32(e+0,i,true);},__wbg___wbindgen_throw_be289d5034ed271b:function(e,n){throw new Error(x(e,n))},__wbg_error_7534b8e9a36f1ab4:function(e,n){let r,s;try{r=e,s=n,console.error(x(e,n));}finally{o.__wbindgen_export3(r,s,1);}},__wbg_get_with_ref_key_1dc361bd10053bfe:function(e,n){let r=a(e)[a(n)];return f(r)},__wbg_instanceof_ArrayBuffer_c367199e2fa2aa04:function(e){let n;try{n=a(e)instanceof ArrayBuffer;}catch{n=false;}return n},__wbg_instanceof_Uint8Array_9b9075935c74707c:function(e){let n;try{n=a(e)instanceof Uint8Array;}catch{n=false;}return n},__wbg_isSafeInteger_bfbc7332a9768d2a:function(e){return Number.isSafeInteger(a(e))},__wbg_length_32ed9a279acd054c:function(e){return a(e).length},__wbg_new_361308b2356cecd0:function(){let e=new Object;return f(e)},__wbg_new_3eb36ae241fe6f44:function(){let e=new Array;return f(e)},__wbg_new_8a6f238a6ece86ea:function(){let e=new Error;return f(e)},__wbg_new_dd2b680c8bf6ae29:function(e){let n=new Uint8Array(a(e));return f(n)},__wbg_prototypesetcall_bdcdcc5842e4d77d:function(e,n,r){Uint8Array.prototype.set.call(D(e,n),a(r));},__wbg_set_3f1d0b984ed272ed:function(e,n,r){a(e)[d(n)]=d(r);},__wbg_set_f43e577aea94465b:function(e,n,r){a(e)[n>>>0]=d(r);},__wbg_stack_0ed75d68575b0f3c:function(e,n){let r=a(n).stack,s=A(r,o.__wbindgen_export,o.__wbindgen_export2),i=_;u().setInt32(e+4,i,true),u().setInt32(e+0,s,true);},__wbindgen_cast_0000000000000001:function(e){return f(e)},__wbindgen_cast_0000000000000002:function(e,n){let r=x(e,n);return f(r)},__wbindgen_cast_0000000000000003:function(e){let n=BigInt.asUintN(64,e);return f(n)},__wbindgen_object_clone_ref:function(e){let n=a(e);return f(n)},__wbindgen_object_drop_ref:function(e){d(e);}}}}function f(t){m===p.length&&p.push(p.length+1);let e=m;return m=p[e],p[e]=t,e}function I(t){let e=typeof t;if(e=="number"||e=="boolean"||t==null)return `${t}`;if(e=="string")return `"${t}"`;if(e=="symbol"){let s=t.description;return s==null?"Symbol":`Symbol(${s})`}if(e=="function"){let s=t.name;return typeof s=="string"&&s.length>0?`Function(${s})`:"Function"}if(Array.isArray(t)){let s=t.length,i="[";s>0&&(i+=I(t[0]));for(let c=1;c<s;c++)i+=", "+I(t[c]);return i+="]",i}let n=/\[object ([^\]]+)\]/.exec(toString.call(t)),r;if(n&&n.length>1)r=n[1];else return toString.call(t);if(r=="Object")try{return "Object("+JSON.stringify(t)+")"}catch{return "Object"}return t instanceof Error?`${t.name}: ${t.message}
|
|
2
|
+
${t.stack}`:r}function z(t){t<132||(p[t]=m,m=t);}function D(t,e){return t=t>>>0,w().subarray(t/1,t/1+e)}function u(){return (b===null||b.buffer.detached===true||b.buffer.detached===void 0&&b.buffer!==o.memory.buffer)&&(b=new DataView(o.memory.buffer)),b}function x(t,e){return t=t>>>0,Z(t,e)}function w(){return (h===null||h.byteLength===0)&&(h=new Uint8Array(o.memory.buffer)),h}function a(t){return p[t]}function g(t){return t==null}function R(t,e){let n=e(t.length*1,1)>>>0;return w().set(t,n/1),_=t.length,n}function A(t,e,n){if(n===void 0){let l=v.encode(t),y=e(l.length,1)>>>0;return w().subarray(y,y+l.length).set(l),_=l.length,y}let r=t.length,s=e(r,1)>>>0,i=w(),c=0;for(;c<r;c++){let l=t.charCodeAt(c);if(l>127)break;i[s+c]=l;}if(c!==r){c!==0&&(t=t.slice(c)),s=n(s,r,r=c+t.length*3,1)>>>0;let l=w().subarray(s+c,s+r),y=v.encodeInto(t,l);c+=y.written,s=n(s,r,c,1)>>>0;}return _=c,s}function d(t){let e=a(t);return z(t),e}function Z(t,e){return k+=e,k>=H&&(S=new TextDecoder("utf-8",{ignoreBOM:true,fatal:true}),S.decode(),k=e),S.decode(w().subarray(t,t+e))}function P(t,e){return o=t.exports,b=null,h=null,o.__wbindgen_start(),o}async function X(t,e){if(typeof Response=="function"&&t instanceof Response){if(typeof WebAssembly.instantiateStreaming=="function")try{return await WebAssembly.instantiateStreaming(t,e)}catch(s){if(t.ok&&n(t.type)&&t.headers.get("Content-Type")!=="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",s);else throw s}let r=await t.arrayBuffer();return await WebAssembly.instantiate(r,e)}else {let r=await WebAssembly.instantiate(t,e);return r instanceof WebAssembly.Instance?{instance:r,module:t}:r}function n(r){switch(r){case "basic":case "cors":case "default":return true}return false}}function J(t){if(o!==void 0)return o;t!==void 0&&(Object.getPrototypeOf(t)===Object.prototype?{module:t}=t:console.warn("using deprecated parameters for `initSync()`; pass a single object instead"));let e=L();t instanceof WebAssembly.Module||(t=new WebAssembly.Module(t));let n=new WebAssembly.Instance(t,e);return P(n)}async function Y(t){if(o!==void 0)return o;t!==void 0&&(Object.getPrototypeOf(t)===Object.prototype?{module_or_path:t}=t:console.warn("using deprecated parameters for the initialization function; pass a single object instead")),t===void 0&&(t=new URL("excelsaurus_bg.wasm",import.meta.url));let e=L();(typeof t=="string"||typeof Request=="function"&&t instanceof Request||typeof URL=="function"&&t instanceof URL)&&(t=fetch(t));let{instance:n,module:r}=await X(await t,e);return P(n)}var b,h,p,m,S,H,k,v,_,o,T=M(()=>{b=null;h=null;p=new Array(128).fill(void 0);p.push(void 0,null,true,false);m=p.length;S=new TextDecoder("utf-8",{ignoreBOM:true,fatal:true});S.decode();H=2146435072,k=0;v=new TextEncoder;"encodeInto"in v||(v.encodeInto=function(t,e){let n=v.encode(t);return e.set(n),{read:t.length,written:n.length}});_=0;});var E=null,C=null;async function G(){E||(C||(C=(async()=>{let t=await Promise.resolve().then(()=>(T(),O));await t.default(),E=t;})()),await C);}async function K(){if(await G(),!E)throw new Error("Failed to initialize ExcelSaurus Wasm module");return E}async function j(t,e={}){let n=await K(),r=await Q(t);return n.parseExcel(r,{sheet:e.sheet?.toString(),limit:e.limit,skipRows:e.skipRows,hasHeaders:e.hasHeaders})}async function Q(t){if(t instanceof Uint8Array)return t;if(t instanceof ArrayBuffer)return new Uint8Array(t);let e=await t.arrayBuffer();return new Uint8Array(e)}var F=class extends HTMLElement{input=null;dropZone=null;statusEl=null;static get observedAttributes(){return ["accept","disabled","on-complete","on-error"]}constructor(){super(),this.attachShadow({mode:"open"});}connectedCallback(){this.render(),this.setupListeners();}disconnectedCallback(){}render(){let e=this.getAttribute("accept")||".xlsx,.xls,.xlsm,.xlsb,.ods";this.shadowRoot.innerHTML=`
|
|
3
3
|
<style>
|
|
4
4
|
:host {
|
|
5
5
|
display: block;
|
|
@@ -86,5 +86,5 @@ ${t.stack}`:r}function z(t){t<132||(d[t]=m,m=t);}function D(t,e){return t=t>>>0,
|
|
|
86
86
|
<input type="file" accept="${e}" />
|
|
87
87
|
</div>
|
|
88
88
|
<div class="status"></div>
|
|
89
|
-
`,this.input=this.shadowRoot.querySelector('input[type="file"]'),this.dropZone=this.shadowRoot.querySelector(".drop-zone"),this.statusEl=this.shadowRoot.querySelector(".status");}setupListeners(){!this.input||!this.dropZone||(this.dropZone.addEventListener("click",()=>{this.input?.click();}),this.input.addEventListener("change",e=>{let n=e.target.files?.[0];n&&this.handleFile(n);}),this.dropZone.addEventListener("dragover",e=>{e.preventDefault(),this.dropZone?.classList.add("drag-over");}),this.dropZone.addEventListener("dragleave",()=>{this.dropZone?.classList.remove("drag-over");}),this.dropZone.addEventListener("drop",e=>{e.preventDefault(),this.dropZone?.classList.remove("drag-over");let n=e.dataTransfer?.files[0];n&&this.handleFile(n);}));}async handleFile(e){this.dropZone?.classList.add("loading"),this.setStatus("Parsing...","");try{let n={},r=this.getAttribute("sheet");r&&(n.sheet=r);let s=this.getAttribute("limit");s&&(n.limit=parseInt(s,10));let i=await
|
|
89
|
+
`,this.input=this.shadowRoot.querySelector('input[type="file"]'),this.dropZone=this.shadowRoot.querySelector(".drop-zone"),this.statusEl=this.shadowRoot.querySelector(".status");}setupListeners(){!this.input||!this.dropZone||(this.dropZone.addEventListener("click",()=>{this.input?.click();}),this.input.addEventListener("change",e=>{let n=e.target.files?.[0];n&&this.handleFile(n);}),this.dropZone.addEventListener("dragover",e=>{e.preventDefault(),this.dropZone?.classList.add("drag-over");}),this.dropZone.addEventListener("dragleave",()=>{this.dropZone?.classList.remove("drag-over");}),this.dropZone.addEventListener("drop",e=>{e.preventDefault(),this.dropZone?.classList.remove("drag-over");let n=e.dataTransfer?.files[0];n&&this.handleFile(n);}));}async handleFile(e){this.dropZone?.classList.add("loading"),this.setStatus("Parsing...","");try{let n={},r=this.getAttribute("sheet");r&&(n.sheet=r);let s=this.getAttribute("limit");s&&(n.limit=parseInt(s,10));let i=await j(e,n);this.setStatus(`\u2713 Parsed ${i.rowCount} rows from "${i.sheetName}"`,"success");let c=new CustomEvent("complete",{detail:i,bubbles:!0,composed:!0});this.dispatchEvent(c);let l=this.getAttribute("on-complete");l&&typeof window[l]=="function"&&window[l](i);}catch(n){let r=n instanceof Error?n.message:"Unknown error";this.setStatus(`\u2717 Error: ${r}`,"error");let s=new CustomEvent("error",{detail:n,bubbles:true,composed:true});this.dispatchEvent(s);let i=this.getAttribute("on-error");i&&typeof window[i]=="function"&&window[i](n);}finally{this.dropZone?.classList.remove("loading");}}setStatus(e,n){this.statusEl&&(this.statusEl.textContent=e,this.statusEl.className=`status ${n}`);}};export{F as ExcelImporter};//# sourceMappingURL=astro.js.map
|
|
90
90
|
//# sourceMappingURL=astro.js.map
|