xlsx-for-ai 1.5.3 → 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 +8 -20
  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,28 +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
319
 
320
- ### Audit findings on install (what's inherited from upstream)
320
+ ### Audit findings on install
321
321
 
322
- When you `npm install xlsx-for-ai` (especially as a library dep, not the top-level project), `npm audit` may surface one or more advisories. Most are inherited transitively from `@protobi/exceljs` and the legacy `xlsx` fallback parser. Each one has been triaged and is documented in [`.github/audit-allowlist.json`](.github/audit-allowlist.json), which is the canonical list our CI's `audit.yml` job reads.
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
323
 
324
- Each allowlist entry includes:
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.
325
326
 
326
- - **`ghsa`** the advisory ID (e.g. `GHSA-w5hq-g745-h8pq`).
327
- - **`package`** — the dependency the advisory lives on.
328
- - **`severity`** — the advisory's published severity.
329
- - **`reason`** — why the finding is accepted, including the code path's reachability in our usage.
330
- - **`reassess`** — the date by which we will re-evaluate (typically a quarterly cadence).
331
- - **`owner`** — who owns the re-evaluation.
332
-
333
- The current set covers two `xlsx` advisories (the npm-published 0.18.5 line is unmaintained; we carry it as a fallback parser only) and one `uuid` advisory inherited from ExcelJS (`v4()` call sites in ExcelJS do not pass a pre-allocated buffer, so the bounds-check gap is unreachable here). An upstream gift PR is open to bump uuid in the protobi fork; once merged and released, the `uuid` line will drop on the next `@protobi/exceljs` update.
334
-
335
- If you embed xlsx-for-ai in a product with stricter audit policies than ours, you have three clean options:
336
-
337
- 1. **Mirror the allowlist entries** into your own audit configuration (e.g. `npm audit --omit=dev` filters, Snyk policy file, GitHub Dependabot ignore rules) using the same `ghsa` IDs.
338
- 2. **Pin to a future xlsx-for-ai release** that bumps `@protobi/exceljs` past the upstream uuid bump (will drop the `uuid` advisory automatically; tracked in the allowlist's `reassess` date).
339
- 3. **Vendor the parser path you actually use** — if you only need the modern `@protobi/exceljs` engine and not the legacy `xlsx` fallback, you can disable the fallback in your wrapper and the `xlsx` advisories cease to apply to your dep graph.
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.
340
328
 
341
329
  ## Reporting bugs
342
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.3",
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
  }