cliptabular
v1.3.0
Published
Parse and stringify clipboard data from Excel, CSV, and other delimited formats. Handles tabs, commas, quotes, currency, percentages, and negative numbers.
Downloads
118
Maintainers
Readme
cliptabular 📋↔️📊
Parse and stringify clipboard data from Excel, CSV, and other delimited formats. Handles tabs, commas, quotes, currency, percentages, and negative numbers.
Features
- Smart delimiter detection (tabs, commas, semicolons, pipes, spaces)
- Automatically prefers Excel’s tab-delimited format
- Ignores delimiters inside quotes
- Handles quoted fields, escaped quotes, and messy numeric values
- Supports currency, grouping, negatives, and percentages
- Handles empty cells and empty rows cleanly
- Bidirectional: parse → arrays, stringify → clipboard text
- Zero dependencies
Install
npm install cliptabular
# or
pnpm add cliptabularUsage
Parsing
import { parse } from "cliptabular";
const text = await navigator.clipboard.readText();
const rows = parse(text);Examples
// Excel (tab-delimited)
parse("Name\tAge\nJohn\t30");
// => [["Name","Age"],["John","30"]]// CSV with quoted commas
parse('"Smith, John","New York, NY"');
// => [["Smith, John", "New York, NY"]]// Numeric + currency — comma stays inside the value
parse("Item,Price\nWidget,$1,234.56");
// => [["Item","Price"],["Widget","$1,234.56"]]// Empty cells become null by default
parse("A,,C");
// => [["A", null, "C"]]Stringifying
import { stringify } from "cliptabular";
const data = [
["Name", "Age"],
["John", "30"],
];
const text = stringify(data);
// "Name\tAge\nJohn\t30"
await navigator.clipboard.writeText(text);Example
// Tab-delimited by default (Excel-friendly)
stringify([
["A", "B"],
["C", "D"],
]);
// => "A\tB\nC\tD"Delimiter Detection
parse analyzes the first lines of text:
- Tabs (Excel) take priority
- Commas, semicolons, pipes, and spaces detected heuristically
- Delimiters inside quotes are ignored
- Header-shaped rows improve accuracy
- Safe fallback to comma
Return Type
parse("A,,B");
// => (string | null)[][]
parse("A,,B", { emptyValue: "" });
// => string[][]
parse("A,,B", { emptyValue: "EMPTY" });
// => (string | "EMPTY")[][]Parse Options
emptyValue
Value used when a cell is empty.
Default: null
parse("A,,C", { emptyValue: "N/A" });
// => [["A", "N/A", "C"]]padRows
Pads rows to equal width using emptyValue.
Default: false
parse("A,B\nC", { padRows: true });
// => [["A","B"],["C",null]]skipEmptyRows
Drops fully empty rows.
Default: false
parse("A,B\n\nC,D", { skipEmptyRows: true });
// => [["A","B"],["C","D"]]skipEmptyCells
Removes empty cells within rows (after trimming).
Takes precedence over padRows.
Default: false
parse("A,,C\n,B,", { skipEmptyCells: true });
// => [["A","C"],["B"]]trim
Trims whitespace inside each cell.
Default: true
parse(" A , B ");
// => [["A","B"]]Stringify Options
delimiter
Default: \t
stringify([["A", "B"]], { delimiter: "," });
// => "A,B"alwaysQuote
Quote every cell.
Default: false
stringify([["A", "B"]], { delimiter: ",", alwaysQuote: true });
// => "\"A\",\"B\""lineEnding
Default: \n
stringify([["A"], ["B"]], { lineEnding: "\r\n" });
// => "A\r\nB"emptyValue
Value considered “empty” in your data.
Default: null
stringify([["A", null, "C"]], { delimiter: "," });
// => "A,,C"emptyOutput
String to output for empty cells.
Default: ""
stringify([["A", null, "C"]], {
delimiter: ",",
emptyValue: null,
emptyOutput: "N/A",
});
// => "A,N/A,C"