-
Notifications
You must be signed in to change notification settings - Fork 1
Changelog
First stable release — API frozen, production-ready feature set. 1,711 tests (424 Rust + 1,287 TypeScript).
- PivotTableBuilder — fluent builder API for pivot tables
-
Auto-Filter Custom Filters —
CustomFilterData/CustomFiltersDatawith full roundtrip -
Page Breaks —
PageBreaksDatawith row/column break parsing and writing -
Rich Text Cells —
Cell.richTextgetter/setter,RichTextBuilderfluent API -
Error System —
ModernXlsxErrorwith 18 machine-readable error codes - Image Embedding — PNG/JPEG support in worksheets
- v0.6.0 — Full ECMA-376 encryption (read + write), OLE2 support
- v0.7.0 — Formula engine with 54 built-in functions
- v0.8.0 — 10 chart types with ChartBuilder API, trendlines, error bars, 3D
- v0.9.0 — Pivot tables, threaded comments, slicers, timelines, CLI tool
- v0.9.2 — Streaming writer, pivot/slicer/timeline write APIs, security audit
See the full changelog in packages/modern-xlsx/CHANGELOG.md.
Rust Performance:
-
ryucrate for 2-6x faster f64 formatting in hot paths - Byte-level JSON escaping (batch-copies vs char-by-char)
-
make_rid()helper withitoa::Buffer— 21format!()allocations eliminated -
Cow<'static, str>on Relationship fields — zero-alloc for static constants -
From<serde_json::Error>— 16.map_err()calls →? - if-let chains (Rust 2024 edition)
Code Organization:
- Split
worksheet.rs(7,173 lines) →worksheet/{mod,parser,writer,json}.rs - Split
charts.rs(4,862 lines) →charts/{mod,types,parser,writer}.rs - Split
barcode.ts(1,828 lines) → 11 tree-shakeable modules - Removed unused
serde-wasm-bindgendependency
TypeScript Improvements:
- O(1) sheet name cache via
Mapin Workbook - Discriminated union types for Worker messages
- Replaced custom
at()helpers with native methods - Vitest pool:
forks→threads
CI/CD:
-
cargo-audit+npm auditsecurity scanning - WASM binary size tracking (>2MB warning)
- Matrix testing: Node 24+25 × ubuntu+windows
- WASM artifact caching
-
dependabot.yml,CODEOWNERS,FUNDING.yml
Docs: Fixed test counts, Rust version, SECURITY.md; added pivot table/threaded comment/slicer/timeline/CLI examples.
Major feature release adding advanced Excel features, CLI tool, performance optimizations, and feature-gated WASM.
- Full OOXML pivot table definition parsing — PivotTableData, PivotFieldData, PivotDataFieldData, PivotPageFieldData
- Pivot field axes (axisRow/axisCol/axisPage/axisValues) and 11 subtotal functions
- Pivot cache definition and records parsing/writing (CacheSource, CacheFieldData, CacheValue)
-
ws.pivotTablesread-only API for pivot table metadata - OOXML parts:
xl/pivotTables/,xl/pivotCache/
- Modern threaded comment parsing/writing (
xl/threadedComments/) - Person management with
xl/persons/person.xml -
ws.addThreadedComment(cell, text, author)— create new comment thread -
ws.replyToComment(commentId, text, author)— reply to existing thread - Auto-generates GUIDs and ISO 8601 timestamps
- Coexists with legacy
xl/comments*.xml
- Slicer definition and cache parsing/writing
- SlicerData, SlicerCacheData, SlicerItem types
-
ws.slicersread-only API - OOXML parts:
xl/slicers/,xl/slicerCaches/
- Timeline definition and cache parsing/writing
- TimelineData, TimelineCacheData, TimelineLevel enum (Years/Quarters/Months/Days)
-
ws.timelinesread-only API - OOXML parts:
xl/timelines/,xl/timelineCache/
-
modern-xlsx info <file>— sheet names, dimensions, row counts -
modern-xlsx convert <file> <output>— XLSX to JSON -
modern-xlsx convert <file> <output> --sheet N --format csv— single sheet to CSV - Installed via
npx modern-xlsxor global install
- XML writer buffer pre-allocation based on data size estimates
- 4-8x faster than SheetJS for bulk read/write operations
- Benchmark integration tests for 10K and 100K row workloads
- Cargo features:
encryptionandcharts(both on by default) - 9 crypto dependencies made optional via
#[cfg(feature = "encryption")] - Smaller WASM bundles possible by disabling unused features
-
ModernXlsxErrorclass with.codeproperty (INVALID_CELL_REF, WASM_INIT_FAILED, SHEET_NOT_FOUND, COMMENT_NOT_FOUND, INVALID_ARGUMENT) - Readonly arrays throughout the public API surface
-
ws.dimensionandws.rowCountgetters - Null consistency across all optional properties
- Full Rust 1.95 modernization (cold_path, .find(), #[inline], match guards)
- TypeScript 6.0 patterns (satisfies, type guards, no
ascasts) - Zero clippy warnings (collapsible_match, derivable_impls, unnecessary_sort_by fixed)
- Removed obsolete
#![allow(clippy::...)]directives
- 389 Rust tests pass (368 unit + 4 benchmark + 12 golden + 5 security)
- 1230 TypeScript tests pass across 55 test files
- Zero clippy warnings, zero TypeScript type errors
Deep Rust modernization targeting Rust 1.95-beta features and idiomatic patterns across all 34 Rust source files (~30,760 lines).
-
core::hint::cold_path()on all error/panic branches (23 files) — compiler branch layout optimization -
rust-versionbumped to 1.95.0 in workspace Cargo.toml
- 58 single-attribute
forloops replaced with.find()iterator pattern across all OOXML parsers - 3 index-based loops replaced with
zip()iteration in reader.rs -
next_r_id()extracted as method onRelationships— deduplicates closure + inline expression in writer.rs
-
#[inline]on 3 hot-path streaming JSON helpers (worksheet.rs) -
#[inline]on 12 chart enumxml_val()methods (charts.rs)
- Shared serde helpers (
is_false,is_true,default_true) extracted toooxml/mod.rs— removes 22 lines of duplication across 5 files - WASM bridge:
parse_workbook()+to_js_err()helpers deduplicate 6 JSON parse patterns
- 357 Rust tests pass (340 unit + 12 golden + 5 security)
- 1210 TypeScript tests pass across 50 test files
- Zero clippy warnings
Deep audit across entire codebase: bug fixes, lint cleanup, Rust & TypeScript modernization, expanded test coverage.
- CRITICAL: Merge image + chart drawing XML to prevent silent data loss
- Restore ChartAxis.fontSize with proper c:txPr writer/parser
- Parse oneCellAnchor charts from drawing XML
- Combo chart roundtrip — parse secondary_chart correctly
- WASM boundary validation for chart data
- Eliminated all panic!() calls in encryption
- Iterator combinators replace manual loops across charts, styles, tables, theme
- #[derive(Default)] on 7 builder structs
- Let-else patterns, Option::take() for zero-clone operations
- Zero clippy warnings
- satisfies operator for compile-time validation of constant maps
- readonly on 16 interface array fields
- Cached Intl.NumberFormat — 10x faster numeric formatting
- Single-pass escapeHtml — replaces 4 chained .replaceAll()
- Worker crash memory leak fix
- Eliminated all 19 noNonNullAssertion lint errors
- Rust: 357 tests (expanded golden tests from 2 to 12 scenarios)
- TypeScript: 1210 tests (added chart API and roundtrip tests)
Bug fixes from comprehensive v0.8.0 charts audit.
-
CRITICAL:
<drawing>now emitted before<tableParts>per ECMA-376 CT_Worksheet schema -
CRITICAL:
<c:style>now emitted before<c:chart>per CT_ChartSpace schema -
write_f64_elementskips NaN/Infinity values - Remove dead
ChartAxis.font_sizefield -
DataLabelsBuilder::build_and_reset()usesOption::take()(zero-clone)
-
buildAxisTitleuses== nullinstead of!title(preserves empty string titles) - Remove
ChartAxisData.fontSize(dead field, matches Rust removal)
Full chart creation, reading, and roundtrip for 10 chart types. ChartBuilder fluent API, chart style presets, trendlines, error bars, 3D rotation, combo charts, and data tables. 337 Rust tests + 1171 TypeScript tests.
- Bar — horizontal bars with clustered/stacked/percentStacked grouping
- Column — vertical bars with clustered/stacked/percentStacked grouping
- Line — line charts with standard/stacked/percentStacked grouping
- Pie — single-series pie charts
- Doughnut — pie with configurable hole size
- Scatter — XY scatter with lineMarker/smoothMarker/line/smooth styles
- Area — area charts with standard/stacked/percentStacked grouping
- Radar — radar/spider charts with radar/filled styles
- Bubble — bubble charts with bubble size series
- Stock — OHLC stock charts (open-high-low-close)
import { ChartBuilder } from 'modern-xlsx';
const chart = new ChartBuilder('bar')
.title('Q1 Sales')
.addSeries({
name: 'Revenue',
categories: 'Sheet1!$A$2:$A$5',
values: 'Sheet1!$B$2:$B$5',
})
.catAxis({ title: 'Product' })
.valAxis({ title: 'Revenue ($)' })
.legend('bottom')
.build();
ws.addChartData(chart);ws.addChart('line', (b) => {
b.title('Monthly Trend')
.addSeries({ name: 'Sales', values: 'Sheet1!$B$2:$B$13' })
.legend('right');
});- Trendlines — linear, exponential, logarithmic, polynomial, power, movingAverage
- Error bars — fixed, percentage, stdDev, stdErr, custom with plus/minus values
-
3D rotation —
rotX,rotY,perspective,rAngAxviaview3d()builder - Combo charts — secondary chart type + secondary value axis
-
Data tables — show data table below chart with
showDataTable() -
Style presets — 8 color palettes via
getChartStylePalette()
Charts written by modern-xlsx can be read back with full fidelity — all chart data, series, axes, labels, trendlines, and styling are preserved through write → read roundtrip.
-
ChartData,ChartSeries,ChartAxis,ChartLegendstructs with serde -
ChartData::to_xml()— ECMA-376 DrawingML chart XML generator -
ChartData::parse()— SAX parser with state machine (25 parse states) -
ChartAnchor::generate_drawing_xml()— two-cell anchor drawing XML -
parse_drawing_anchors()— extracts chart rIds from drawing XML -
resolve_charts()— two-step resolution (sheet.rels → drawing → chart) - 33+ chart-specific tests
Bug fixes, security hardening, and precision improvements from comprehensive codebase audit.
- JSON injection prevention in streaming path (cell refs now escaped)
-
xml:space="preserve"on SST<t>elements (whitespace-padded strings) - Path traversal defense in
resolve_relative_path - Saturating add for frozen pane topLeftCell
- Writer entries Vec capacity improvement
- ROUND precision (epsilon adjustment for 1.005-style edge cases)
- ROUND/ROUNDUP/ROUNDDOWN use
Math.truncfor negative digit args - Cross-sheet range resolver propagation
- Tokenizer backtrack on invalid exponents (e.g.,
1e+) -
sheetToJsonoff-by-one fix incollectRows - SUMIF/COUNTIF
localeCompareconsistency
Complete formula tokenizer, parser, evaluator, and 54 built-in Excel functions — enabling modern-xlsx to compute cell values without Excel. 1142 TypeScript tests.
- Tokenizer — single-pass lexer producing typed tokens (24 token types)
- Parser — recursive descent with operator precedence (12 AST node types)
- Serializer — AST to formula string with precedence-aware parenthesization
-
Reference Resolver — resolves A1 refs and ranges to cell values via
EvalContext -
Reference Rewriter — adjusts refs on row/column insert/delete, generates
#REF!for deleted - Shared Formula Expansion — derives child formulas from master + row/col offset
- Evaluator — tree-walk interpreter with Excel-compatible type coercion and error propagation
String & Logical (20): IF, AND, OR, NOT, IFERROR, CONCATENATE, LEFT, RIGHT, MID, LEN, TRIM, UPPER, LOWER, TEXT, VALUE, EXACT, SUBSTITUTE, REPT, FIND, SEARCH
Math & Statistical (25): SUM, AVERAGE, MIN, MAX, COUNT, COUNTA, COUNTBLANK, ROUND, ROUNDUP, ROUNDDOWN, ABS, SQRT, MOD, INT, CEILING, FLOOR, POWER, LOG, LN, PI, RAND, SUMIF, COUNTIF, AVERAGEIF, SUMPRODUCT
Lookup (9): VLOOKUP, HLOOKUP, INDEX, MATCH, CHOOSE, ROW, COLUMN, ROWS, COLUMNS
import { evaluateFormula, createDefaultFunctions } from 'modern-xlsx';
const functions = createDefaultFunctions();
const result = evaluateFormula('SUM(A1:A3)*2', {
currentSheet: 'Sheet1',
functions,
getCell: (sheet, col, row) => { /* return cell value */ },
});Full ECMA-376 encryption support — read and write password-protected XLSX files. Agile Encryption (AES-256-CBC, SHA-512) for modern files, Standard Encryption (AES-128-ECB, SHA-1) for legacy compatibility. OLE2 compound document read/write. 299 Rust tests + 583 TypeScript tests.
- OLE2 compound document detection — magic byte analysis distinguishes encrypted XLSX, legacy XLS, and normal ZIP
- EncryptionInfo parser — Agile (v4.4) and Standard (v2.2/3.2/4.2) encryption method identification
- SHA-512/SHA-256/SHA-1 key derivation — per ECMA-376 SS2.3.6.2 with configurable spin count (100K default)
- AES-256-CBC segment decryption — 4096-byte segment-based decryption with per-segment IV derivation
- AES-128-ECB decryption — Standard Encryption verifier decryption using raw block cipher
- HMAC-SHA-512 integrity — tamper detection via encrypt-then-MAC verification
- Password verification — constant-time comparison for Agile and Standard encryption
-
readBuffer(data, { password })— simple API to read encrypted files -
readFile(path, { password })— file-based encrypted read (Node.js/Bun/Deno)
- OLE2 compound document writer — v3 format (512-byte sectors), FAT chains, directory entries
- Agile Encryption pipeline — random salt/key generation, segment-based AES-256-CBC encryption
- HMAC integrity embedding — compute-and-encrypt HMAC for post-write tamper detection
- EncryptionInfo XML generation — produces spec-compliant Agile encryption descriptor
-
wb.toBuffer({ password })— simple API to write encrypted files -
wb.toFile(path, { password })— file-based encrypted write (Node.js/Bun/Deno)
-
SensitiveKey RAII wrapper —
#[derive(Zeroize, ZeroizeOnDrop)]for automatic key material cleanup -
No key leaks on error paths — all derived keys wrapped in SensitiveKey (immune to
?operator bypass) -
Constant-time comparisons —
constant_time_eqat all 3 secret comparison sites - Error message safety — no key material, hash values, or intermediate state in error strings
-
Cryptographically secure random —
getrandomwithwasm_jsfeature for WASM targets
-
sha10.10 — SHA-1 hash for Standard Encryption -
getrandom0.3 — CSPRNG for salt/key generation (WASM-compatible)
- 42 new Rust tests (OLE2 detection, encryption info, key derivation, AES, HMAC, OLE2 writer, security)
- 30+ new TypeScript tests (encryption read/write, roundtrip, edge cases, 10K-row performance)
Encryption support for the Worker API, OLE2 code deduplication, and crypto helper consolidation.
-
worker.readBuffer(data, { password })— read encrypted files in Web Worker thread -
worker.writeBuffer(data, { password })— write encrypted files in Web Worker thread - Backward compatible — password parameter is optional, existing code unchanged
-
OLE2_MAGIC consolidation — deduplicated constant from
detect.rsandwriter.rsintoole2/mod.rs -
Generic hash dispatcher —
with_hash_algeliminates triplicated SHA-512/SHA-256/SHA-1 match blocks -
HMAC computation helper —
compute_hmacdeduplicates HMAC dispatch between verify and encrypt paths -
DIFAT documentation — enhanced
write_ole2doc comments explaining 109-entry DIFAT limitation
-
digest0.10 (withallocfeature) —DynDigesttrait for generic hash dispatch
Critical bug fixes found during comprehensive codebase audit.
-
Image embedding broken —
generateDrawingXmlrId off-by-one causing images to silently fail -
Frozen panes: wrong
activePane— column-only freeze wrote"bottomLeft"instead of"topRight" -
Invalid JSON for NaN/Infinity —
write_f64_jsonnow writesnullinstead of crashing JSON.parse -
Custom numFmt ID collision —
resolveNumFmtIdnow always assigns IDs >= 164 per ECMA-376
-
HashMap::with_capacityin ZIP reader -
col_index_to_letterdelegates to optimizedcol_to_letters -
TextEncoderhoisted to module-level constant
Closed 7 SheetJS advantage categories + added native Excel Tables, headers/footers, row/column grouping, and print layout. 704 tests (217 Rust + 487 TypeScript).
-
encodeRow()— convert 0-based row index to 1-based string -
decodeRow()— convert 1-based row string to 0-based index -
splitCellRef()— decompose$A$1into{ col, row, absCol, absRow }
-
appVersion— roundtrip<AppVersion>from app.xml -
hyperlinkBase— roundtrip<HyperlinkBase>from app.xml -
revision— roundtrip<cp:revision>from core.xml -
application,company,manager— now fully parsed and written
-
sheetToTxt()— tab-separated text output (reuses CSV engine with\tdelimiter) -
sheetToFormulae()— extract all cell values and formulas as["A1=100", "A3='SUM(A1:A2)"]
-
Conditional sections — parse
[>100]#,##0;[<=100]0.00with condition evaluation -
Bracket color codes — extract
[Red],[Blue],[Color3]–[Color56]from format strings -
formatCellRich()— returns{ text, color }with color metadata -
loadFormat()— register custom format code at runtime -
loadFormatTable()— bulk-register format codes by ID
-
ws.usedRange— computed getter returning cell extent (e.g.,"B2:D5") ornull -
ws.tabColor— getter/setter for sheet tab RGB hex color, roundtrips through WASM
-
cell.numberFormat— resolves style index → numFmtId → format code string -
cell.dateValue— returnsDateif cell contains a date-formatted number -
Stub cell type —
'stub'inCellTypeunion for explicitly empty cells (SheetJS type"z")
-
dynamicArray— roundtripcm="1"attribute on<f>element for SPILL/dynamic array formulas
| Category | v0.4.0 | v0.5.0 |
|---|---|---|
| Worksheet operations | Tie | modern-xlsx wins |
| Cell operations | Tie | modern-xlsx wins |
| Formulas | Tie | modern-xlsx wins |
| Document properties | SheetJS wins | modern-xlsx wins |
| Cell ref utilities | SheetJS wins | Tie |
| Number formatting | SheetJS wins | modern-xlsx wins |
| Sheet conversion | SheetJS wins | SheetJS (gap narrowed) |
-
Full OOXML Table read/write — native
xl/tables/table{n}.xmlsupport with SAX parser and XML writer -
ws.tables— getter returning all tables on a worksheet -
ws.getTable(name)— find table by name -
ws.addTable(opts)— create table with name, ref, columns, style, totalsRow, autoFilter -
ws.removeTable(name)— delete table by name -
60 built-in table styles —
TABLE_STYLES.light(1-21),.medium(1-28),.dark(1-11) -
VALID_TABLE_STYLES— ReadonlySet for style name validation -
TotalsRowFunction— type for totals row calculations (sum, count, average, etc.)
-
ws.headerFooter— getter/setter forHeaderFooterDatawith odd/even/first header/footer -
HeaderFooterBuilder— fluent builder withleft(),center(),right(),build() -
Static formatting helpers —
pageNumber(),totalPages(),date(),time(),fileName(),sheetName(),filePath() -
Text formatting —
bold(),italic(),underline(),strikethrough(),fontSize(),fontName(),color()
-
ws.groupRows(start, end, level?)— set outline level (0-7) on row range -
ws.ungroupRows(start, end)— remove outline level from rows -
ws.collapseRows(start, end)— collapse grouped rows -
ws.expandRows(start, end)— expand collapsed rows -
ws.groupColumns(start, end, level?)— set outline level on column range -
ws.ungroupColumns(start, end)— remove outline level from columns -
ws.outlineProperties— getter/setter for summary row/column position
-
wb.setPrintTitles(sheet, opts)— set repeating rows/columns via_xlnm.Print_Titlesdefined name -
wb.getPrintTitles(sheet)— get current print title configuration -
wb.setPrintArea(sheet, area)— set print area via_xlnm.Print_Areadefined name -
wb.getPrintArea(sheet)— get current print area
Declarative table generation API with styled headers, zebra striping, auto-width, merge cells, and multi-table composition. Critical bug fixes across WASM init, writer performance, and sheet conversion utilities.
-
drawTable(wb, ws, opts)— generate styled XLSX tables from declarative options, no manual cell coordinate math -
drawTableFromData(wb, ws, data, opts?)— create tables from JSON arrays with auto-extracted headers andheaderMapdisplay names -
Header styling — customizable font, background color, and alignment with sensible defaults (bold white on
#4472C4) -
Body styling — zebra striping via
alternateRowColor, configurable borders, font, and alignment - Auto-width — content-aware column width calculation with CJK double-width character support
-
Per-cell style overrides —
cellStylesmap with"row,col"keys for targeted formatting on top of base styles -
Merge cells — row and column spanning via
mergesarray (0-based, relative to data area) -
Column definitions —
TableColumnwith per-column width, alignment, and number format (e.g.'$#,##0.00') -
Freeze header —
freezeHeader: truefreezes the header row for scrolling -
Auto-filter —
autoFilter: trueadds filter dropdown arrows to header cells -
Nested composition — use
TableResult.lastDataRowto stack tables vertically with gap rows -
Side-by-side composition — use
origincolumn offsets to place tables horizontally
-
jsonToSheetstartCol —writeDataRownow respects thestartColparameter instead of ignoring it -
resolveNumFmtIdsort assumption — no longer assumes thenumFmtarray is sorted, uses correct lookup -
initWasmSyncrace condition — concurrentinitWasmcalls no longer conflict with synchronous initialization -
frozenPanefield names — table engine uses correctrows/colsfield names for frozen pane data -
WASM reader HashSet rebuild — eliminated unnecessary
HashSetreconstruction on every read operation -
Comments clone — removed avoidable
.clone()in comments path handling -
Writer insert shift — replaced
Vec::insert(0, ...)O(n) shift with efficient prepend pattern
-
columnToLetter/letterToColumn— corrected examples that used wrong indices -
serialToDate— fixed example showing wrong return type -
addValidation— corrected example using wrong field name - Rich text — fixed example that accessed private fields
Pure TypeScript barcode/QR generation with 9 formats, PNG renderer, and XLSX embedding. Full codebase audit with critical bug fixes. 437 tests (157 Rust + 280 TypeScript).
- 9 barcode formats — Code 39, Code 128, EAN-13, UPC-A, ITF-14, GS1-128, QR Code, Data Matrix, PDF417
-
renderBarcodePNG()— pure TypeScript PNG renderer (no external dependencies) -
generateBarcode()— one-call XLSX embedding with drawing XML and relationships -
generateDrawingXml()/generateDrawingRels()— low-level drawing XML generation - Multi-image accumulation — multiple images per sheet without data loss
-
Unicode panic —
validate.rsbyte-indexing multi-byte characters →chars().take(n).collect() -
Multi-image data loss —
addImage()now accumulates via Maps instead of overwriting drawing XML -
SST insert performance — Entry API replaces double hash lookup in
shared_strings.rs -
Comments author dedup — Entry::Vacant pattern eliminates double lookup in
comments.rs -
DXF diagonal attrs — eliminated redundant UTF-8 decoding in
styles.rs
- GF(256) lookup tables hoisted to module-level constants (Data Matrix encoder)
-
Array.prototype.at(-1)for O(1) sorted-array access (utils.ts,style-builder.ts) -
split_once(':')replacessplit(':').collect::<Vec<>>()in validators - Single
TextEncoderinstance in QR encoder (was creating two)
- All docs updated for v0.3.0 accuracy
- Barcode generation examples in playground
- Migration guides updated with barcode comparison
Browser-first release with IIFE bundle, CDN distribution, Web Worker support, and framework examples. 419 tests (171 Rust + 248 TypeScript).
-
IIFE build — self-contained
modern-xlsx.min.js(~29 KB) exposingwindow.ModernXlsx - CDN distribution — available on jsDelivr and unpkg, no bundler required
-
detectWasmUrl()— auto-detection of WASM binary URL fromdocument.currentScript.src -
initWasmSync(module)— synchronous WASM initialization from pre-loaded buffer -
ensureReady()— lazy auto-initialization on first use (cached Promise pattern) -
Source maps —
.mapfiles generated for all build outputs (ESM, IIFE, Worker)
-
createXlsxWorker()— off-thread XLSX read/write via Web Worker message passing -
modern-xlsx.worker.js— dedicated worker script with auto WASM init -
Transferable buffers — zero-copy transfer of
Uint8Arrayresults back to main thread
- tsdown 3-build config — ESM (primary), IIFE (browser), Worker (off-thread)
-
Package exports —
"."(ESM),"./browser"(IIFE),"./worker"(Worker script) -
browser/unpkg/jsdelivrfields in package.json for CDN auto-resolution
-
Interactive browser playground at
docs/site/playground.html - 6 built-in examples: Hello World, Styled Workbook, Read & Inspect, Batch Data, JSON to Sheet, Formulas & Dates
- Live WASM status indicator, Ctrl+Enter execution, download integration
-
React — hooks-based integration with
useEffectWASM init -
Vue 3 — Composition API with
onMountedWASM init -
Svelte 5 —
$effectrune-based WASM init - Angular — service-based WASM init with standalone components
- Cloudflare Workers — XLSX generation at the edge
- Deno Deploy — server-side XLSX with Deno-native imports
- Service Worker — offline XLSX generation with custom WASM URL
Complete 0.1.x hardening series. 419 tests (171 Rust + 248 TypeScript).
- Style roundtrip: gradient fills, diagonal borders, DXF styles, cell named styles
- Formula metadata: array formulas, shared formulas, formulaRef, sharedIndex
- Feature roundtrip: hyperlinks, comments, data validation, conditional formatting, sheet protection, page setup
- Edge cases: empty workbooks, malformed XML, boundary values
- Error handling: corrupted files, invalid inputs, graceful degradation
- Streaming & benchmarks: 100K row read/write, parallel parsing, buffer scaling
- Utilities: cell refs, dates, format codes, CSV/HTML/JSON conversion
-
push_entity()— zero-allocation XML entity resolution -
Vec::with_capacity()on all XML parse buffers (11 sites) -
from_utf8().unwrap_or_default()replacesfrom_utf8_lossy()(6 sites) -
entries.remove()in StreamingReader — moves data instead of cloning -
drain()incollect_preserved()— moves preserved entries -
#[non_exhaustive]on error enum
- Module-scoped
CELL_REF_REregex (hoisted from hot loop) -
isolatedDeclarations: truein tsconfig - Shared WASM init via
__tests__/setup.ts
- Migration guide: SheetJS
- Migration guide: ExcelJS
- Usage examples cookbook
- Release roadmap
- GitHub Actions pinned to stable versions
- Rust toolchain:
@stable - Node.js engine:
>=24.0.0
First public release.
- Full XLSX read/write with Rust WASM core
- Cell styling — fonts, fills, borders, alignment, number formats via StyleBuilder
- Data validation — list, number, date, text length, custom formula
- Conditional formatting — color scales, data bars, icon sets, formula-based rules
- Frozen panes, hyperlinks, comments, sheet protection, page setup
- Rich text with RichTextBuilder
- Named ranges, document properties, workbook views, calc chain
- Streaming reader/writer for large files
- Parallel sheet parsing (rayon)
- Cell reference utilities, date utilities, format utilities
- Sheet conversion utilities (JSON, CSV, HTML, array-of-arrays)
- Browser Blob download support
- 342 tests (170 Rust + 172 TypeScript)
| Operation | modern-xlsx | SheetJS CE | Factor |
|---|---|---|---|
| Read 100K | 1,155 ms | 4,927 ms | 4.3x faster |
| Write 100K | 5,048 ms | 5,048 ms | 1.0x |
| sheetToJson 10K | 54 ms | 103 ms | 1.9x faster |
modern-xlsx v1.0.0
Getting Started
Guides
- Charts & Visualizations
- Formula Engine
- Table Layout Engine
- Tables & Print Layout
- Encryption
- Feature Comparison
Reference
Migration
Project