v0.6.0
v0.6.0 closes out the entire remaining roadmap — every tracked issue is now done. This release adds three new input formats, true streaming, password protection, and full chart composition, all zero-dependency and built on web-standard APIs.
npm i hucre@0.6.0✨ Highlights
🔐 Password-protected workbooks (read + write)
Read and write encrypted .xlsx using ECMA-376 Agile encryption (the Excel 2010+ scheme) — on WebCrypto, so it stays zero-dependency everywhere (Node, Deno, Bun, Workers, browsers).
import { writeXlsx, readXlsx } from "hucre"
const encrypted = await writeXlsx({
sheets: [{ name: "Secret", rows: [["pin", 1234]] }],
encryption: { password: "hunter2" },
})
const wb = await readXlsx(encrypted, { password: "hunter2" })Works through every read entry point (read / readObjects / streamXlsxRows); wrong password → DecryptionError, missing password → EncryptedFileError.
→ #329 (closes #156, #31)
📖 XLSB (binary workbook) read
Read .xlsb — the compact, fast binary Excel format — into the same model as .xlsx. Auto-detected.
import { read, readXlsb } from "hucre"
const wb = await readXlsb(bytes) // shared strings, RK/float numbers, dates, formulas…
const same = await read(bytes) // auto-detected🗂️ XLS (legacy Excel 97-2003) read
Read legacy .xls (BIFF8 / OLE2) files — for the archives that never went away.
import { read, readXls } from "hucre"
const wb = await readXls(bytes) // SST (+CONTINUE), RK/MULRK, bools, errors, dates, merges
const same = await read(bytes) // auto-detected🌊 True streaming XLSX reader
streamXlsxRows now accepts a ReadableStream and parses the ZIP front-to-back from local headers, piping the target worksheet straight into the SAX parser — the whole archive is never buffered.
const res = await fetch("https://example.com/huge.xlsx")
for await (const row of streamXlsxRows(res.body!)) {
console.log(row.index, row.values)
}📊 Chart composition through the roundtrip
saveXlsx now serializes model charts (not just preserves originals), so you can clone template charts onto new/copied sheets and save them — copySheetToWorkbook carries charts across workbooks too.
import { openXlsx, getCharts, cloneChart, addChart, writeXlsx } from "hucre"
const template = await openXlsx(templateBytes)
const [lineChart] = getCharts(template)
const dashboard = { name: "Dashboard", rows: data }
addChart(dashboard, cloneChart(lineChart.chart, {
title: "Revenue",
series: [{ name: "Revenue", values: "B2:B13", categories: "A2:A13", color: "1070CA" }],
anchor: { from: { row: 14, col: 0 } },
}))
await writeXlsx({ sheets: [dashboard] })🔗 Inline hyperlinks in data rows
Rich link values can sit directly inside data rows via the link() helper — no parallel cells map needed. #-prefixed targets become internal references.
import { link, writeXlsx } from "hucre"
await writeXlsx({
sheets: [{
name: "Links",
columns: [{ key: "name" }, { key: "site" }],
data: [
{ name: "Anthropic", site: link("Visit", "https://anthropic.com") },
{ name: "Jump", site: link("Go to Sheet2", "#Sheet2!A1", "internal ref") },
],
}],
})Plus chart theme-color refs (schemeClr) and per-host line cap/compound. → #322
⚠️ Notes on the binary / crypto formats
The encryption, XLSB, and XLS code follows the Microsoft specs and is covered by round-trip / builder tests, but hasn't yet been verified against a broad corpus of real Excel-produced files. Treat them as solid-but-new; please file issues with any file that doesn't read cleanly. XLSB/XLS are read-only in this release.
📋 Pull requests in this release
- #322 — chart theme colors (
schemeClr) + line cap/compound - #326 — inline hyperlinks in data rows
- #327 — chart composition through
saveXlsx(#136) - #328 — true streaming XLSX reader (#77)
- #329 — password-protected workbooks (#156, #31)
- #330 — XLSB read (#154, #51)
- #331 — XLS BIFF8 read (#153, #30)
Full changelog: v0.5.1...v0.6.0