-
Notifications
You must be signed in to change notification settings - Fork 1
Releases: ABCrimson/modern-xlsx
v1.0.0 — Stable Release
v1.0.0 — Stable Release
First stable release. API frozen, production-ready.
Install
npm install modern-xlsx
Highlights
- 10 Chart Types — bar, column, line, pie, doughnut, scatter, area, radar, bubble, stock with fluent ChartBuilder API
- Formula Engine — 54 built-in Excel functions (SUM, VLOOKUP, IF, INDEX/MATCH, etc.)
- Encryption — Read/write password-protected files (ECMA-376 Standard & Agile AES-256)
- Pivot Tables — Full read/write with PivotTableBuilder API
- Threaded Comments — Modern Excel comment threads with reply support
- Slicers & Timelines — Interactive filtering controls (read/write)
- Streaming Writer — 100K+ row output with O(unique strings) memory
- Rich Text —
RichTextBuilderfor inline cell formatting with full roundtrip - Image Embedding — PNG/JPEG support in worksheets
- CLI Tool —
modern-xlsx infoandmodern-xlsx convert - Error System —
ModernXlsxErrorwith 18 machine-readable error codes
Full Feature Set
Everything SheetJS Pro charges for — free and open source:
| Feature | modern-xlsx | SheetJS CE | SheetJS Pro |
|---|---|---|---|
| Cell styling | Free | No | Paid |
| Data validation | Free | No | Paid |
| Conditional formatting | Free | No | Paid |
| Rich text | Free | No | Paid |
| Charts (10 types) | Free | No | Paid |
| Pivot tables | Free | No | Paid |
| Encryption | Free | No | No |
| Formula engine | Free | No | No |
| Streaming writer | Free | No | Paid |
| Image embedding | Free | No | Paid |
| Excel Tables | Free | No | Paid |
Performance
| Operation | modern-xlsx | SheetJS CE | Factor |
|---|---|---|---|
| Read 100K rows | 472 ms | 1,901 ms | 4.0x faster |
| Write 100K (batch) | 232 ms | 1,950 ms | 8.4x faster |
| Read 10K rows | 69 ms | 170 ms | 2.5x faster |
Stats
- Rust: 424 tests (402 unit + 12 golden + 5 security + 4 bench + 1 doctest)
- TypeScript: 1,287 tests across 58 files
- WASM binary: ~2.0 MB (1.1 MB with lite build)
- Zero runtime dependencies
Links
Assets 2
v1.0.0-rc.1 — Release Candidate 1
v1.0.0-rc.1 — Release Candidate 1
API frozen, production-ready feature set. All tests passing.
Highlights
New Features
- PivotTableBuilder — fluent builder API following the ChartBuilder pattern
- Auto-Filter Custom Filters —
CustomFilterData/CustomFiltersDatawith full roundtrip - Page Breaks —
PageBreaksDatawith row/column break parsing, writing, and convenience methods - Rich Text Cells —
Cell.richTextgetter/setter,RichTextBuilderfluent API, full WASM roundtrip - Image Embedding — PNG/JPEG support in worksheets
- Error System —
ModernXlsxErrorclass withfromWasmError()parser and 18 machine-readable error codes
Improvements
- API Audit — naming consistency, parameter types, return types across all public APIs
- JSDoc Coverage — comprehensive documentation across 11 source files with
@exampletags - README — 5-line quick start, improved onboarding
- Error Messages — context-rich, actionable errors across Rust core (ZIP, XML, OLE2, cell, style)
- Expanded Builders — ChartBuilder, StyleBuilder with additional JSDoc and methods
Verification
- Rust: 424 tests (402 unit + 12 golden + 5 security + 4 bench + 1 doctest), clippy clean
- TypeScript: 1287 tests across 58 files, typecheck clean
- WASM binary: ~2.0 MB
Audit Reports
- API Surface Audit — 6 critical, 7 important, 11 minor findings for post-RC
- Rust Code Audit — safety (
ascasts in OLE2), performance (writer rels re-parsing), modernization - TypeScript Code Audit — dedup opportunities (wasm-loader), helper extraction, error class consistency
Full Changelog: v0.9.2...v1.0.0-rc.1
Assets 2
v0.9.2 — Streaming Writer, Pivot/Slicer/Timeline Write APIs
What's New
Streaming XLSX Writer
StreamingXlsxWriterfor writing 100K+ row files with O(unique strings) memory- Backed by Rust/WASM
StreamingWriterCorewith incremental ZIP entry writing - Methods:
create(),startSheet(),writeRow(),setStylesXml(),finish()
Pivot Table / Slicer / Timeline Write APIs
- Pivot Tables:
ws.addPivotTable(),ws.removePivotTable(),wb.addPivotCache(),wb.addPivotCacheRecords() - Slicers:
ws.addSlicer(),ws.removeSlicer(),wb.addSlicerCache() - Timelines:
ws.addTimeline(),ws.removeTimeline(),wb.addTimelineCache() - New types:
PivotCacheDefinitionData,PivotCacheRecordsData, discriminatedCacheValueunions
WASM Lite Build
- Feature-gated encryption for smaller WASM binary via
modern-xlsx/liteimport
Parser Refactoring
worksheet/parser.rsreduced from 2,891 → 2,202 lines- 20 extracted helper functions for XML attribute parsing
CLI Modernization
- Node 24
parseArgs()+ asyncnode:fs/promises
Security & Documentation
- Comprehensive ECMA-376 crypto audit (
docs/SECURITY-AUDIT.md) - Interactive demo site + 4 example projects (sales report, CSV converter, encrypted payroll, chart dashboard)
- Deno/Bun compatibility test harnesses
- CHANGELOG.md with full version history
Verification
- 406 Rust tests — all passing
- 1,259 TypeScript tests across 57 files — all passing
- Clippy clean, TypeScript typecheck clean, Biome lint clean
Assets 2
v0.9.1 — Performance, Quality & Maintainability Overhaul
35-Point Improvement Release
Rust Performance
- ryu crate for 2-6x faster f64 formatting in XML/JSON hot paths
- Byte-level JSON escaping — scans bytes and batch-copies non-escape slices instead of per-char iteration
make_rid()helper withitoa::Buffer— eliminated 21format!()heap allocations in writerCow<'static, str>onRelationshipfields — zero-allocation for static OOXML constantsFrom<serde_json::Error>forModernXlsxError— 16.map_err()calls replaced with plain?- if-let chains (Rust 2024 edition idiom)
Rust 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 - Removed unused
serde-wasm-bindgendependency - Added
--vacuous-dropsto wasm-opt flags
TypeScript Performance & Quality
- Split
barcode.ts(1,828 lines) → 11 tree-shakeable codec modules - O(1) sheet name cache via
Map<string, number>in Workbook - Discriminated union types for Worker messages (type-safe exhaustive switching)
- Replaced custom
at()helpers with native methods - Eliminated production
astype casts - Vitest pool:
forks→threads(faster test execution)
CI/CD
- Security scanning:
cargo-audit+npm auditin every CI run - WASM binary size tracking with >2MB warning threshold
- Matrix testing: Node 24 + 25 ×ばつ ubuntu + windows (4 combinations)
- WASM artifact caching keyed on Cargo.lock + Rust sources
GitHub Presence
- Added
dependabot.yml(Cargo + npm + GitHub Actions, weekly) - Added
CODEOWNERS,FUNDING.yml - Fixed documentation: test counts, Rust version, SECURITY.md version table
- Added v0.9.0 feature documentation (pivot tables, threaded comments, slicers, timelines, CLI)
Verification
- 389 Rust tests — all passing, clippy clean (0 warnings)
- 1,230 TypeScript tests — all passing across 55 test files
- TypeScript typecheck: 0 errors
- Biome lint: 0 errors
Full Changelog: v0.9.0...v0.9.1
Assets 2
v0.9.0 — Pivot Tables, Threaded Comments, Slicers & Timelines
What's New
Pivot Tables (read-only)
Full OOXML pivot table parsing — definitions, fields, axes, items, subtotals, cache definitions, and cache records. Access via ws.pivotTables.
Threaded Comments (read + write)
Modern Excel threaded comments with person management. Create new threads with ws.addThreadedComment() and reply with ws.replyToComment().
Slicers (read-only)
Slicer definitions and caches for pivot table filtering. Access via ws.slicers.
Timelines (read-only)
Timeline definitions and caches for date-based pivot filtering. Access via ws.timelines.
CLI Tool
npx modern-xlsx info report.xlsx # sheet names, dimensions, row counts npx modern-xlsx convert data.xlsx out.json # XLSX → JSON npx modern-xlsx convert data.xlsx out.csv --sheet 0 --format csv
Performance
- XML writer buffer pre-allocation for faster writes
- 4-8x faster than SheetJS for bulk read/write operations
- Honest benchmarks: SheetJS is faster for cell-by-cell writes and small utility conversions
Feature-Gated WASM
encryption and charts Cargo features — opt out of crypto deps for smaller WASM bundles.
API Improvements
ModernXlsxErrorwith.codeproperty for structured error handling- Readonly arrays throughout the API
ws.dimensionandws.rowCountgetters
Codebase Quality
- Full Rust 1.95 modernization (
cold_path(),.find(),#[inline]) - TypeScript 6.0 patterns (
satisfies, type guards) - Zero clippy warnings
Stats
- 389 Rust tests | 1,230 TypeScript tests | 55 test files
- All passing ✅
Full Changelog: v0.8.6...v0.9.0
Assets 2
v0.8.6 — Rust 1.95 Modernization
Rust 1.95 Modernization
Deep Rust modernization targeting Rust 1.95-beta features and idiomatic patterns across all 34 Rust source files (~30,760 lines).
Rust 1.95 Features
core::hint::cold_path()on all error/panic branches (23 files) — compiler branch layout optimizationrust-versionbumped to 1.95.0 in workspace Cargo.toml
Iterator Modernization
- 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
Performance Annotations
#[inline]on 3 hot-path streaming JSON helpers (worksheet.rs)#[inline]on 12 chart enumxml_val()methods (charts.rs)
Code Quality
- 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
Verification
- 357 Rust tests pass (340 unit + 12 golden + 5 security)
- 1210 TypeScript tests pass across 50 test files
- Zero clippy warnings
Full Changelog: v0.8.5...v0.8.6
Assets 2
v0.8.5 — Comprehensive Audit & Modernization
Deep audit across the entire codebase: critical bug fixes, lint cleanup, Rust & TypeScript modernization, and expanded test coverage.
Bug Fixes
- CRITICAL: Merge image + chart drawing XML to prevent silent data loss when sheets have both images and charts
- Restore
ChartAxis.fontSizewith proper<c:txPr>writer/parser - Parse
oneCellAnchorcharts from drawing XML (not justtwoCellAnchor) - Combo chart roundtrip — parse
secondary_chartcorrectly - WASM boundary validation for chart data before crossing to Rust
Rust Modernization
- Eliminated all
panic!()calls in encryption — returnResultinstead - Iterator combinators replace manual loops across charts, styles, tables, theme
#[derive(Default)]on 7 builder structs, removing deadnew()methods- Let-else patterns,
Option::take()for zero-clone operations - Zero clippy warnings across entire codebase
TypeScript 6.0 Modernization
satisfiesoperator for compile-time validation of constant mapsreadonlyon 16 interface array fields for immutability safety- Cached
Intl.NumberFormat— 10x faster numeric formatting - Single-pass
escapeHtml— replaces 4-chained.replaceAll() - Worker crash memory leak fix (pending promises rejected on terminate)
??=nullish coalescing assignment throughout- Eliminated all 19
noNonNullAssertionlint errors with safe array accessors
Test Coverage
- Rust: 357 tests (expanded golden tests from 2 to 12 scenarios)
- TypeScript: 1,210 tests (added chart API, chart type, and roundtrip tests)
- Total: 1,567 tests
Full Changelog: v0.8.1...v0.8.5
Assets 2
v0.8.1 — Audit Patch
Bug fixes from comprehensive v0.8.0 charts audit.
Rust Fixes
- CRITICAL:
<drawing>now emitted before<tableParts>per ECMA-376 CT_Worksheet schema — fixes strict validator rejections when worksheets have both charts and tables - CRITICAL:
<c:style>now emitted before<c:chart>per CT_ChartSpace schema write_f64_elementskips NaN/Infinity values (consistent withwrite_f64_jsonfix from v0.5.1)- Remove dead
ChartAxis.font_sizefield (was never parsed or written) DataLabelsBuilder::build_and_reset()usesOption::take()for zero-clone operation
TypeScript Fixes
buildAxisTitleuses== nullinstead of!title(preserves empty string titles)- Remove
ChartAxisData.fontSize(dead field, matches Rust removal) - Lint fixes: non-null assertions, formatting, cognitive complexity
Full Changelog: v0.8.0...v0.8.1
Assets 2
v0.8.0 — Charts & Visualizations
Charts & Visualizations
modern-xlsx now supports full chart creation, reading, and roundtrip — programmatically generate Excel charts with titles, legends, data labels, trendlines, and more.
New Features
Chart Data Model (0.8.0)
- 10 chart types: Bar, Column, Line, Pie, Doughnut, Scatter, Area, Radar, Bubble, Stock
- Full data model:
ChartData,ChartSeries,ChartAxis,ChartLegend,DataLabels,ChartAnchor - Serde roundtrip between Rust structs and JSON (WASM boundary)
Chart XML Writer (0.8.2–0.8.5)
- Complete ECMA-376 DrawingML Chart XML generation (
c:chartSpace,c:chart,c:plotArea) - All chart type elements:
c:barChart,c:lineChart,c:pieChart,c:scatterChart, etc. - Series with fill/line colors, markers, smooth lines, explosion (pie)
- Axis configuration: scaling (min/max/log), gridlines, tick marks, number formats, axis titles
- Chart titles with rich text formatting (bold, font size, color)
- Data labels: showVal, showCatName, showPercent, number format, leader lines
- Legend with position (top/bottom/left/right/topRight) and overlay
- Drawing anchors:
xdr:twoCellAnchorwith cell coordinates and EMU offsets
Chart Drawing & Packaging (0.8.4)
xl/charts/chart{n}.xmlZIP entries with content typesxl/drawings/drawing{n}.xmlwith chart anchors- Drawing relationships (
_rels) linking charts to drawings - Worksheet
<drawing r:id="..."/>reference - Global chart numbering across sheets
TypeScript ChartBuilder API (0.8.6)
- Fluent builder:
new ChartBuilder('bar').title('Sales').addSeries({...}).legend('bottom').build() Worksheet.addChart(type, configure)callback patternWorksheet.chartsgetter,addChartData(),removeChart()- Full axis configuration, data labels, scatter/radar styles, doughnut hole size
Chart XML Reader (0.8.7)
- Full SAX parser for chart XML →
ChartDatastructs - Drawing anchor parser for
xdr:twoCellAnchorelements resolve_charts()two-step resolution: sheet.rels → drawing → chart- Charts transition from opaque
preserved_entriesto structured typed data
Roundtrip & Style Presets (0.8.8)
- 7 end-to-end WASM write/read roundtrip tests
CHART_STYLE_PALETTES— 8 predefined Excel color palettesgetChartStylePalette(styleId)helper
Advanced Features (0.8.9)
- Trendlines: Linear, Exponential, Logarithmic, Polynomial, Power, Moving Average
- Error Bars: FixedVal, Percentage, StdDev, StdErr with direction (Both/Plus/Minus)
- 3D Rotation: rotX, rotY, perspective, right-angle axes
- Data Table: show data table below chart
- Combo Charts: secondary chart type + secondary value axis (via
secondaryChartfield)
Example
import { initWasm, Workbook, ChartBuilder } from 'modern-xlsx'; await initWasm(); const wb = new Workbook(); const ws = wb.addSheet('Sales'); // ... populate data ... ws.addChart('bar', (b) => { b.title('Monthly Revenue', { bold: true, fontSize: 1400 }) .addSeries({ name: 'Revenue', catRef: 'Sales!$A2ドル:$A13ドル', valRef: 'Sales!$B2ドル:$B13ドル', fillColor: '4472C4' }) .catAxis({ title: 'Month' }) .valAxis({ title: 'Amount ($)', majorGridlines: true, numFmt: '#,##0' }) .legend('bottom') .grouping('clustered') .anchor({ col: 4, row: 0 }, { col: 14, row: 20 }); }); await wb.toFile('report.xlsx');
Stats
- Rust: 337 tests (330 unit + 2 golden + 5 security)
- TypeScript: 1171 tests across 47 files
- Zero clippy warnings, zero type errors
Assets 2
v0.7.1 — Audit Patch
Comprehensive Codebase Audit
Bug fixes, security hardening, and precision improvements discovered through deep audit of every Rust and TypeScript file.
Rust Fixes
- JSON injection prevention — cell references in the streaming JSON path are now properly escaped via
json_escape_to, preventing malformed JSON from adversarial XLSX files - Whitespace preservation in SST —
<t>elements in shared strings now includexml:space="preserve"when values start/end with whitespace, preventing Excel from stripping significant spaces - Path traversal defense —
resolve_relative_pathno longer allows..segments to escape below the root directory in crafted.relstargets - Overflow protection — frozen pane
topLeftCellcomputation usessaturating_addto prevent u32 overflow on adversarial input - Writer performance — ZIP entries
Veccapacity improved from6 + sheetsto10 + sheets*3 + preserved, reducing reallocations for complex workbooks
TypeScript Fixes
- ROUND precision —
ROUND(1.005, 2)now correctly returns1.01(fixed floating-point multiplication issue with epsilon adjustment) - ROUND/ROUNDUP/ROUNDDOWN — negative fractional digit arguments now use
Math.truncinstead ofMath.floor, matching Excel semantics - Cross-sheet ranges —
resolveRangenow propagatesstart.sheettoend.sheet, fixing silent wrong-sheet resolution for formulas likeSheet2!A1:B10 - Tokenizer — invalid exponents (e.g.,
1e+) now backtrack instead of emittingNaNtokens - sheetToJson — fixed off-by-one in
collectRowsthat could include a spurious extra row past the data bounds - SUMIF/COUNTIF — string criteria comparisons now use
localeComparefor consistency with the formula evaluator
Stats
- 299 Rust tests + 1142 TypeScript tests passing
- Zero clippy warnings, zero lint errors, zero type errors