npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

excelstream_wasm

v0.1.1

Published

WASM adapter for excelstream (CSV parsing) - demo package for npm

Downloads

34

Readme

excelstream_wasm

WebAssembly adapter for excelstream — parse CSV and XLSX files directly in the browser with near-native performance.

npm License: MIT

Installation

npm install excelstream_wasm

Quick Start

import init, { parse_csv_full } from 'excelstream_wasm';

// Initialize the WASM module first (required once)
await init();

const rows = parse_csv_full("name,age\nAlice,30\nBob,25");
console.log(rows);
// [["name", "age"], ["Alice", "30"], ["Bob", "25"]]

CSV Parsing

Parse a full CSV string

import init, { parse_csv_full } from 'excelstream_wasm';

await init();

const csv = `id,name,score
1,Alice,95
2,Bob,87
3,Charlie,92`;

const rows = parse_csv_full(csv);
// rows[0] → ["id", "name", "score"]  (header)
// rows[1] → ["1", "Alice", "95"]

Parse CSV from a file input

import init, { parse_csv_full } from 'excelstream_wasm';

await init();

document.querySelector('#file-input').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  const text = await file.text();
  const rows = parse_csv_full(text);
  console.log(`Parsed ${rows.length} rows`);
});

Parse CSV from URL (fetch)

import init, { parse_csv_full } from 'excelstream_wasm';

await init();

const res = await fetch('/data/report.csv');
const text = await res.text();
const rows = parse_csv_full(text);

Streaming CSV (line by line with callback)

Use this for large files or when you want to process rows as they arrive:

import init, { init_parser, register_callback, feed_line } from 'excelstream_wasm';

await init();

// delimiter = 44 (','), quote = 34 ('"')
init_parser(44, 34);

const results = [];
register_callback((fields) => {
  results.push(fields);
});

// Feed lines one by one
feed_line("name,age,city");
feed_line("Alice,30,Hanoi");
feed_line("Bob,25,HCMC");

console.log(results);
// [["name","age","city"], ["Alice","30","Hanoi"], ["Bob","25","HCMC"]]

Custom delimiters:

// Tab-separated values (TSV)
init_parser(9, 34);   // delimiter='\t', quote='"'

// Semicolon-separated (common in European locales)
init_parser(59, 34);  // delimiter=';', quote='"'

XLSX Parsing

XLSX files are ZIP archives containing XML files. You need to unzip them first (e.g., with fflate or JSZip), then pass the XML content to this library.

Install a ZIP library

npm install fflate

Parse XLSX from a file input

import init, { load_shared_strings, parse_sheet_xml } from 'excelstream_wasm';
import { unzipSync, strFromU8 } from 'fflate';

await init();

document.querySelector('#file-input').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  const buffer = await file.arrayBuffer();
  const unzipped = unzipSync(new Uint8Array(buffer));

  // Load shared strings (string table used by XLSX)
  const sharedStringsXml = strFromU8(unzipped['xl/sharedStrings.xml'] ?? new Uint8Array());
  load_shared_strings(sharedStringsXml);

  // Parse the first sheet
  const sheetXml = strFromU8(unzipped['xl/worksheets/sheet1.xml']);
  const rows = parse_sheet_xml(sheetXml);

  console.log(`Parsed ${rows.length} rows`);
  console.log('Header:', rows[0]);
  console.log('First data row:', rows[1]);
});

Parse XLSX from URL (fetch)

import init, { load_shared_strings, parse_sheet_xml } from 'excelstream_wasm';
import { unzipSync, strFromU8 } from 'fflate';

await init();

const res = await fetch('/data/report.xlsx');
const buffer = await res.arrayBuffer();
const unzipped = unzipSync(new Uint8Array(buffer));

load_shared_strings(strFromU8(unzipped['xl/sharedStrings.xml'] ?? new Uint8Array()));
const rows = parse_sheet_xml(strFromU8(unzipped['xl/worksheets/sheet1.xml']));

Parse multiple sheets

// List available sheets from workbook.xml
const workbookXml = strFromU8(unzipped['xl/workbook.xml']);
const sheetNames = [...workbookXml.matchAll(/name="([^"]+)"/g)].map(m => m[1]);

// Parse sheet2
load_shared_strings(strFromU8(unzipped['xl/sharedStrings.xml'] ?? new Uint8Array()));
const sheet2Rows = parse_sheet_xml(strFromU8(unzipped['xl/worksheets/sheet2.xml']));

Framework Examples

React

import { useState, useEffect } from 'react';
import init, { parse_csv_full } from 'excelstream_wasm';

export function CsvParser() {
  const [ready, setReady] = useState(false);
  const [rows, setRows] = useState([]);

  useEffect(() => {
    init().then(() => setReady(true));
  }, []);

  const handleFile = async (e) => {
    const text = await e.target.files[0].text();
    setRows(parse_csv_full(text));
  };

  return (
    <div>
      <input type="file" accept=".csv" onChange={handleFile} disabled={!ready} />
      <p>{rows.length} rows parsed</p>
    </div>
  );
}

Vue 3

<script setup>
import { ref, onMounted } from 'vue';
import init, { parse_csv_full } from 'excelstream_wasm';

const rows = ref([]);
onMounted(() => init());

async function handleFile(e) {
  const text = await e.target.files[0].text();
  rows.value = parse_csv_full(text);
}
</script>

<template>
  <input type="file" accept=".csv" @change="handleFile" />
  <p>{{ rows.length }} rows parsed</p>
</template>

API Reference

init()

Initialize the WASM module. Must be called once before using any other function.

await init();

parse_csv_full(contents: string): string[][]

Parse a complete CSV string. Returns an array of rows, each row is an array of field strings.

| Parameter | Type | Description | |-----------|------|-------------| | contents | string | Full CSV content |

Returns: string[][] — array of rows

const rows = parse_csv_full("a,b\n1,2");
// [["a","b"], ["1","2"]]

Uses comma (,) as delimiter and double-quote (") as quote character. For custom delimiters, use the streaming API.


init_parser(delimiter: number, quote: number)

Initialize the streaming CSV parser with custom delimiter and quote characters.

| Parameter | Type | Description | |-----------|------|-------------| | delimiter | number | ASCII code of delimiter (e.g. 44 for ,, 9 for tab, 59 for ;) | | quote | number | ASCII code of quote character (e.g. 34 for ") |

init_parser(44, 34); // comma + double-quote

register_callback(fn: (fields: string[]) => void)

Register a callback invoked for each line fed to the streaming parser.

register_callback((fields) => {
  console.log(fields); // string[] for each parsed line
});

feed_line(line: string)

Feed a single line to the streaming parser. The registered callback is called immediately.

feed_line("Alice,30,Hanoi");

load_shared_strings(xml: string)

Load the XLSX shared strings table (xl/sharedStrings.xml). Must be called before parse_sheet_xml if the sheet references shared strings.

| Parameter | Type | Description | |-----------|------|-------------| | xml | string | Content of xl/sharedStrings.xml |

load_shared_strings(sharedStringsXmlContent);

parse_sheet_xml(xml: string): string[][]

Parse an XLSX worksheet XML (xl/worksheets/sheetN.xml). Returns all rows as string arrays.

| Parameter | Type | Description | |-----------|------|-------------| | xml | string | Content of xl/worksheets/sheet1.xml |

Returns: string[][] — array of rows

const rows = parse_sheet_xml(sheetXmlContent);

Notes

  • All cell values are returned as strings. Type conversion (number, date, boolean) is left to the caller.
  • XLSX dates are stored as numeric serial values (e.g. 44927 = Jan 1 2023). Convert with: new Date(Date.UTC(1899, 11, 30) + value * 86400000).
  • The WASM binary is ~36 KB — suitable for browser use without bundling concerns.
  • Supports all modern browsers and Node.js 18+.

Related

License

MIT