xlsx-for-ai 1.5.2 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +12 -3
  2. package/WHY.md +0 -1
  3. package/index.js +10 -37
  4. package/package.json +4 -4
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 👋 **New here? Not a programmer?** → [Read WHY.md for the plain-English version](WHY.md). The README below is the technical reference.
4
4
 
5
- **The bidirectional bridge between spreadsheets and AI agents.** Reads `.xlsx` (and `.xls`, `.xlsb`, `.ods`, `.csv`, `.tsv`) into the formats LLMs actually consume — markdown, JSON, text, SQL — and writes spreadsheets back out from AI-generated specs. Same tool, both directions.
5
+ **The bidirectional bridge between spreadsheets and AI agents.** Reads `.xlsx` (plus `.csv`, `.tsv`) into the formats LLMs actually consume — markdown, JSON, text, SQL — and writes spreadsheets back out from AI-generated specs. Same tool, both directions.
6
6
 
7
7
  AI tools — Claude, Cursor, Copilot, ChatGPT, and other LLM coding agents — can read text files but **not** `.xlsx` binaries. This CLI closes the loop:
8
8
 
@@ -10,7 +10,7 @@ AI tools — Claude, Cursor, Copilot, ChatGPT, and other LLM coding agents — c
10
10
 
11
11
  **✍️ Write mode (`xlsx-for-ai write`)** — turn an AI-generated JSON or markdown spec into a real `.xlsx` file. Closes the round-trip so an agent that *reviews* your spreadsheet can also *deliver the corrected file*. The output includes a `_xlsx-for-ai` review tab explaining every structural change the round-trip made (with risks, tradeoffs, and overrides) — the supervisor model: AI does the work, the human stays in control of every decision. Verified lossless on 29/30 real workbooks.
12
12
 
13
- **Input formats:** `.xlsx` `.xls` `.xlsb` `.ods` `.csv` `.tsv`
13
+ **Input formats:** `.xlsx` `.csv` `.tsv` (legacy `.xls` / `.xlsb` / `.ods` removed in 1.5.4 — convert to `.xlsx` first; see [#26](https://github.com/senoff/xlsx-for-ai/issues/26))
14
14
 
15
15
  **Output modes:** text dump, markdown tables (best LLM comprehension per token), JSON, SQL `CREATE TABLE`+`INSERT`, inferred schema, workbook diff, real `.xlsx` (write mode).
16
16
 
@@ -315,7 +315,16 @@ The CLI install (`npm install -g xlsx-for-ai`) is clean — no deprecation warni
315
315
 
316
316
  Run `rm -rf node_modules package-lock.json && npm install` and the warnings will clear. xlsx-for-ai's tests pass against these versions, so the upgrade is safe.
317
317
 
318
- A future release may apply these dep upgrades via `patch-package` so they travel through the dep graph automatically. The infrastructure is in place; the patches haven't been needed urgently because most installs are CLI-direct.
318
+ `patch-package` is in `devDependencies` for authoring patches. The postinstall hook is *not* wired today no patches exist, and a hook that tries to invoke a missing dev-only binary would break consumer installs. When the first patch lands, the hook is added in the same commit as the patch file.
319
+
320
+ ### Audit findings on install
321
+
322
+ As of 1.5.4, `npm install xlsx-for-ai` finds **no inherited audit advisories**. The previous `xlsx` (sheetJS) and `uuid` findings were closed by:
323
+
324
+ - **`xlsx` removed in 1.5.4** — see [#26](https://github.com/senoff/xlsx-for-ai/issues/26). The legacy `.xls` / `.xlsb` / `.ods` input path that depended on it is no longer supported; the modern `@protobi/exceljs` engine handles `.xlsx` (and CSV / TSV continue to use `papaparse`).
325
+ - **`uuid` bumped to ^14 via `overrides`** — clears the `GHSA-w5hq-g745-h8pq` advisory inherited transitively from ExcelJS. Mirrors the upstream protobi/exceljs gift PR locally.
326
+
327
+ The triage workflow lives in [`.github/audit-allowlist.json`](.github/audit-allowlist.json) (currently empty) and `audit.yml` for whenever a future advisory needs accepting.
319
328
 
320
329
  ## Reporting bugs
321
330
 
package/WHY.md CHANGED
@@ -30,7 +30,6 @@ A few examples people find useful:
30
30
  - **Compare two versions of the same spreadsheet** ("what changed between V11 and V14?") and get a list of every cell that moved.
31
31
  - **Turn a CSV export from QuickBooks into a clean SQL database table** in one command, with the column types figured out automatically.
32
32
  - **Walk through a 50-tab model someone else built** and have the AI explain how the sheets reference each other.
33
- - **Process a folder of legacy `.xls` files** that won't even open in modern Excel without complaint.
34
33
 
35
34
  But the biggest unlock is the next thing.
36
35
 
package/index.js CHANGED
@@ -31,8 +31,7 @@ const engine = require('./lib/engine');
31
31
 
32
32
  // Lazy-load heavy deps only when their feature is used (keeps cold start fast
33
33
  // for the common --stdout / --json / --md path that needs none of them).
34
- let _xlsxLib, _papaLib, _formulaJsLib, _tokenizerLib;
35
- const lazyXlsx = () => (_xlsxLib ??= require('xlsx'));
34
+ let _papaLib, _formulaJsLib, _tokenizerLib;
36
35
  const lazyPapa = () => (_papaLib ??= require('papaparse'));
37
36
  const lazyFormulaJs = () => (_formulaJsLib ??= require('@formulajs/formulajs'));
38
37
  const lazyTokenizer = () => (_tokenizerLib ??= require('gpt-tokenizer'));
@@ -108,7 +107,7 @@ coding agents can read. Preserves values, formulas, formatting, layout.
108
107
  The 'write' sub-command does the reverse: takes a JSON or markdown spec and
109
108
  produces an .xlsx file. Run 'xlsx-for-ai write --help' for details.
110
109
 
111
- Input formats: .xlsx .xls .xlsb .ods .csv .tsv
110
+ Input formats: .xlsx .csv .tsv
112
111
 
113
112
  Output modes (mutually exclusive; default = text):
114
113
  --md Markdown tables — best LLM comprehension per token
@@ -1081,40 +1080,14 @@ async function loadAnyWorkbook(filePath) {
1081
1080
  return wb;
1082
1081
  }
1083
1082
  if (ext === '.xls' || ext === '.xlsb' || ext === '.ods') {
1084
- return loadViaSheetJS(filePath);
1085
- }
1086
- throw new Error(`Unsupported extension: ${ext}. Supported: .xlsx .xls .xlsb .ods .csv .tsv`);
1087
- }
1088
-
1089
- // Read a non-xlsx spreadsheet via SheetJS, materialize into the engine's
1090
- // workbook representation so the rest of the code (dump/markdown/json/sql/
1091
- // schema) works unchanged. Loses some formatting; preserves values + formulas.
1092
- function loadViaSheetJS(filePath) {
1093
- const XLSX = lazyXlsx();
1094
- const sheetJsWb = XLSX.readFile(filePath, { cellFormula: true, cellDates: true });
1095
- const wb = engine.createWorkbook();
1096
- for (const name of sheetJsWb.SheetNames) {
1097
- const sjsSheet = sheetJsWb.Sheets[name];
1098
- const ws = wb.addWorksheet(name);
1099
- if (!sjsSheet['!ref']) continue;
1100
- const range = XLSX.utils.decode_range(sjsSheet['!ref']);
1101
- for (let r = range.s.r; r <= range.e.r; r++) {
1102
- for (let c = range.s.c; c <= range.e.c; c++) {
1103
- const addr = XLSX.utils.encode_cell({ r, c });
1104
- const cell = sjsSheet[addr];
1105
- if (!cell) continue;
1106
- const target = ws.getRow(r + 1).getCell(c + 1);
1107
- if (cell.f) {
1108
- target.value = { formula: cell.f, result: cell.v };
1109
- } else if (cell.t === 'd') {
1110
- target.value = cell.v instanceof Date ? cell.v : new Date(cell.v);
1111
- } else {
1112
- target.value = cell.v;
1113
- }
1114
- }
1115
- }
1083
+ throw new Error(
1084
+ `Legacy format ${ext} is no longer supported. Convert to .xlsx first ` +
1085
+ `(e.g. open in Excel/LibreOffice and Save As .xlsx). See ` +
1086
+ `https://github.com/senoff/xlsx-for-ai/issues/26 for the discussion of ` +
1087
+ `whether to restore native support.`
1088
+ );
1116
1089
  }
1117
- return wb;
1090
+ throw new Error(`Unsupported extension: ${ext}. Supported: .xlsx .csv .tsv`);
1118
1091
  }
1119
1092
 
1120
1093
  // ---------------------------------------------------------------------------
@@ -1938,7 +1911,7 @@ async function main() {
1938
1911
  }
1939
1912
  // Min 22 bytes (zip EOCD) only meaningful for binary formats; CSV/TSV can be smaller.
1940
1913
  const ext = path.extname(filePath).toLowerCase();
1941
- const isBinary = ext === '.xlsx' || ext === '.xls' || ext === '.xlsb' || ext === '.ods';
1914
+ const isBinary = ext === '.xlsx';
1942
1915
  if (isBinary && stat.size < 22) {
1943
1916
  console.error(`File is too small (${stat.size} bytes) to be a valid spreadsheet: ${filePath}`);
1944
1917
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xlsx-for-ai",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "description": "CLI that converts .xlsx files into rich text or JSON dumps that AI coding agents (Claude, Cursor, Copilot, ChatGPT, etc.) can read — preserving values, formulas, formatting, colors, column widths, frozen panes, named ranges, tables, and more.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -51,8 +51,7 @@
51
51
  "@protobi/exceljs": "^4.4.0-protobi.9",
52
52
  "gpt-tokenizer": "^3.4.0",
53
53
  "jszip": "^3.10.1",
54
- "papaparse": "^5.5.3",
55
- "xlsx": "^0.18.5"
54
+ "papaparse": "^5.5.3"
56
55
  },
57
56
  "devDependencies": {
58
57
  "patch-package": "^8.0.1"
@@ -61,6 +60,7 @@
61
60
  "glob": "^13.0.0",
62
61
  "rimraf": "^5.0.10",
63
62
  "unzipper": "^0.12.3",
64
- "fast-csv": "^5.0.2"
63
+ "fast-csv": "^5.0.2",
64
+ "uuid": "^14.0.0"
65
65
  }
66
66
  }