document-cli 2.0.0 → 2.1.0

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.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/document-cli) [![npm](https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/document-cli) [![Release](https://img.shields.io/github/v/release/ExaDev/document-cli)](https://github.com/ExaDev/document-cli/releases/latest) [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/document-cli/ci.yml?branch=main)](https://github.com/ExaDev/document-cli/actions)
4
4
 
5
- > A command-line interface and an interactive terminal (Ink) app for [`documents.js`](https://github.com/ExaDev/documents.js): every docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/markdown conversion, bridge, and editor documents.js exposes, wired up as a scriptable subcommand or a full-screen terminal editor. Installs as either `document-cli` or `doculi`.
5
+ > A command-line interface and an interactive terminal (Ink) app for [`documents.js`](https://github.com/ExaDev/documents.js): every docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown conversion, bridge, and editor documents.js exposes, wired up as a scriptable subcommand or a full-screen terminal editor. Installs as either `document-cli` or `doculi`.
6
6
 
7
7
  `document-cli` adds no conversion or editing logic of its own — it is a dispatch layer over `documents.js`'s existing conversion functions, `DocumentConverter` port, live-view editors, and `.odb`/PDF readers. What it adds is two ways to drive them without writing TypeScript: a scriptable, Unix-shaped CLI (stdin/stdout, exit codes, `--json` diagnostics) for pipelines, and a full-screen Ink terminal app for browsing and editing a document interactively.
8
8
 
@@ -79,7 +79,7 @@ cat report.docx | document-cli docx-to-pdf - - > report.pdf
79
79
 
80
80
  ### Commands
81
81
 
82
- **The explicit `<source>-to-<target>` conversions** — one command per pair `createLocalDocumentConverter().conversions` declares in `documents.js` (confirmed by running the built CLI's own `formats` command, not assumed): the nine `<format>-to-pdf` conversions `docx-to-pdf`, `pptx-to-pdf`, `odt-to-pdf`, `odp-to-pdf`, `ods-to-pdf`, `odg-to-pdf`, `odf-to-pdf`, `xlsx-to-pdf`, `markdown-to-pdf`; the eight `pdf-to-<format>` reverse conversions `pdf-to-docx`, `pdf-to-pptx`, `pdf-to-odt`, `pdf-to-odp`, `pdf-to-ods`, `pdf-to-odg`, `pdf-to-xlsx`, `pdf-to-markdown` (`odf-to-pdf` is one-way — there is no `pdf-to-odf` see documents.js's own README); and sixteen PDF-bypassing bridges — ten same-variant pairs that copy content directly between formats sharing one `ContentDocument` variant (`odt-to-docx`, `docx-to-odt`, `odp-to-pptx`, `pptx-to-odp`, `ods-to-xlsx`, `xlsx-to-ods`, `markdown-to-docx`, `docx-to-markdown`, `markdown-to-odt`, `odt-to-markdown`), plus six cross-variant pairs that swap a document's content variant through a semantic transform (`docx-to-pptx`, `pptx-to-docx`, `odt-to-odp`, `odp-to-odt`, `xlsx-to-markdown`, `markdown-to-xlsx`). Each takes `<input> [output]`:
82
+ **The explicit `<source>-to-<target>` conversions** — one command per pair `createLocalDocumentConverter().conversions` declares in `documents.js` (confirmed by running the built CLI's own `formats` command, not assumed): every ordered pair of the ten content formats docx, pptx, xlsx, odt, odp, ods, odg, svg, csv, markdown — in both directions as a PDF-bypassing bridge (a pair whose formats share one `ContentDocument` variant, like `odt-to-docx` or `ods-to-xlsx`, copies content across directly; a cross-variant pair, like `docx-to-pptx`, `xlsx-to-markdown`, or `odg-to-svg`, swaps the document's content variant through a semantic transform); each of those ten plus `odf` into pdf (`docx-to-pdf`, `xlsx-to-pdf`, `csv-to-pdf`, `svg-to-pdf`, `odf-to-pdf`, ...); and pdf back into the same ten (`pdf-to-docx`, `pdf-to-xlsx`, `pdf-to-csv`, `pdf-to-svg`, ... — there is no `pdf-to-odf`; `odf-to-pdf` is one-way, see documents.js's own README). Each takes `<input> [output]`:
83
83
 
84
84
  ```sh
85
85
  document-cli docx-to-pdf report.docx report.pdf
@@ -95,7 +95,7 @@ document-cli convert report.docx - --to pdf > report.pdf
95
95
 
96
96
  **`formats`** — lists every `source -> target` pair the commands above support (`--json` for a machine-readable array), plus a pointer to the commands not on that list because they don't fit the source/target shape (`odm-to-pdf`, `odb-to-csv`, `odb-to-xlsx`, `odb-tables`, `odb-forms`, `odb-reports`, `pdf-inspect`, `from-package`, `fonts`, `docx-extras`, `metadata`, `set-metadata`).
97
97
 
98
- **`from-package <input> [output]`** — reads back a `DocumentPackage` JSON file a previous conversion wrote via `--dump-package` (below) and exports it to a real target format, closing the round trip `--dump-package` otherwise has no return path for. Target resolution matches `convert`: an output path's own extension, or `--to <format>` when it doesn't have one. `pdf` rebuilds the layout from the package's own recorded positions — each content node's `frames` plus the package's `pages` geometry (`layoutDocumentFromPackage` → `writePdf`; a package no longer carries a separate `layout` half at all); every other format builds a fresh package from the `content` half through the identical `buildXPackage` function the matching `pdf-to-X`/bridge conversion already uses — `xlsx` included, via `ooxml.js`'s own `buildXlsxPackage`. `odf` is the one target rejected outright, since a standalone formula document has no write path from `ContentDocument` at all. Only a file genuinely written by a current `--dump-package` round-trips here; anything else fails with its `$schema` mismatch named, and a dump from the documents.js 1.x `formatVersion` 1 shape (content plus a separate `layout` half) is rejected with an error naming the version change rather than silently accepted:
98
+ **`from-package <input> [output]`** — reads back a `DocumentPackage` JSON file a previous conversion wrote via `--dump-package` (below) and exports it to a real target format, closing the round trip `--dump-package` otherwise has no return path for. Target resolution matches `convert`: an output path's own extension, or `--to <format>` when it doesn't have one. `pdf` rebuilds the layout from the package's own recorded positions — each content node's `frames` plus the package's `pages` geometry (`layoutDocumentFromPackage` → `writePdf`; a package no longer carries a separate `layout` half at all); every other format builds a fresh package from the `content` half through the identical `buildXPackage` function the matching `pdf-to-X`/bridge conversion already uses — `xlsx` included, via `ooxml.js`'s own `buildXlsxPackage`. `odf` is the one target rejected outright, since a standalone formula document has no write path from `ContentDocument` at all; a `csv` or `svg` target is written through the identical `buildCsvText`/`buildSvgText` functions the codec registry's own write wrappers call, so the `--delimiter`/`--sheet`/`--page` selection flags below reach it exactly as they do a live conversion. Only a file genuinely written by a current `--dump-package` round-trips here; anything else fails with its `$schema` mismatch named, and a dump from the documents.js 1.x `formatVersion` 1 shape (content plus a separate `layout` half) is rejected with an error naming the version change rather than silently accepted:
99
99
 
100
100
  ```sh
101
101
  document-cli docx-to-pdf report.docx report.pdf --dump-package report.package.json
@@ -139,7 +139,7 @@ document-cli pdf-inspect report.pdf
139
139
  document-cli pdf-inspect report.pdf --json
140
140
  ```
141
141
 
142
- **`fonts <input>`** — lists every source-embedded font face a docx/pptx/odt/odp/ods/odg document carries (family, weight/style, byte length) — the same embedded faces every `<format>-to-pdf` conversion already extracts and renders through automatically (see [Real fonts](#real-fonts) below); this command just reports what's there without converting anything. Rejects a format with no source-embedded-font concept at all (xlsx, pdf, markdown, odf), naming it:
142
+ **`fonts <input>`** — lists every source-embedded font face a docx/pptx/odt/odp/ods/odg document carries (family, weight/style, byte length) — the same embedded faces every `<format>-to-pdf` conversion already extracts and renders through automatically (see [Real fonts](#real-fonts) below); this command just reports what's there without converting anything. Rejects a format with no source-embedded-font concept at all (xlsx, csv, svg, pdf, markdown, odf), naming it:
143
143
 
144
144
  ```sh
145
145
  document-cli fonts report.docx
@@ -151,13 +151,13 @@ document-cli fonts report.docx
151
151
  document-cli docx-extras report.docx
152
152
  ```
153
153
 
154
- **`metadata <input>`** — prints a document's own title/author/subject/keywords/creator/producer/created/modified metadata, for any of the ten supported formats (docx, pptx, xlsx, odt, odp, ods, odg, odf, markdown, pdf). `--json` emits the raw metadata object:
154
+ **`metadata <input>`** — prints a document's own title/author/subject/keywords/creator/producer/created/modified metadata, for any of the twelve supported formats (docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, pdf); csv and svg carry no metadata container of their own, so they always report none. `--json` emits the raw metadata object:
155
155
 
156
156
  ```sh
157
157
  document-cli metadata report.pdf
158
158
  ```
159
159
 
160
- **`set-metadata <input> [output]`** — patches a document's own title/author/subject/keywords, leaving every other field untouched (`--set-title`, `--set-author`, `--set-subject`, `--set-keywords` — the last a comma-separated list); source and target format must match, so run `convert`/`from-package` first if a different target format is also needed. A `pdf` source/target patches the parsed PDF directly (`writePdf`) with no layout engine involved — genuinely lossless for everything else on the page; every other format rebuilds a fresh package from that format's own `ContentDocument`, which for docx specifically is lossy (it drops everything `docx-extras` covers, since `buildDocxPackage` has no way to carry that data through a `ContentDocument`-only rebuild):
160
+ **`set-metadata <input> [output]`** — patches a document's own title/author/subject/keywords, leaving every other field untouched (`--set-title`, `--set-author`, `--set-subject`, `--set-keywords` — the last a comma-separated list); source and target format must match, so run `convert`/`from-package` first if a different target format is also needed. A `pdf` source/target patches the parsed PDF directly (`writePdf`) with no layout engine involved — genuinely lossless for everything else on the page; every other format rebuilds a fresh package from that format's own `ContentDocument`, which for docx specifically is lossy (it drops everything `docx-extras` covers, since `buildDocxPackage` has no way to carry that data through a `ContentDocument`-only rebuild); a `csv` or `svg` source/target is rejected outright, since plain text has no metadata container and a rebuild would silently drop the override:
161
161
 
162
162
  ```sh
163
163
  document-cli set-metadata report.docx report.docx --set-title "Q3 Report" --set-author "Finance"
@@ -178,7 +178,9 @@ The explicit conversions, `convert`, `odm-to-pdf`, `odb-to-xlsx`, `odb-to-csv`,
178
178
  | `-q, --quiet` | Suppress diagnostic and summary output (the JSON result-summary line still prints in `--json` mode, so a script consuming NDJSON always gets a terminating record). |
179
179
  | `--verbose` | Include a full stack trace in the error line when the run fails. |
180
180
 
181
- `--dump-package <file>` is one flag further, registered only on the explicit conversions and `convert` it writes the intermediate `DocumentPackage` (content carrying its own per-node rendered `frames`, plus the `pages` geometry those frames index into) that conversion built to a JSON file, tagged with its own `$schema` so `from-package` (above) can read it back in. Every conversion populates one, `odf-to-pdf` included its dump carries a `formula`-kind content and the one A4 page it renders (the formula's glyphs travel through the PDF writer's own positioned-formula channel rather than as frame-stamped page content); the sixteen PDF-bypassing bridges (the ten same-variant pairs `odt-to-docx`/`docx-to-odt`, `odp-to-pptx`/`pptx-to-odp`, `ods-to-xlsx`/`xlsx-to-ods`, `markdown-to-docx`/`docx-to-markdown`, `markdown-to-odt`/`odt-to-markdown`, plus the six cross-variant pairs `docx-to-pptx`/`pptx-to-docx`, `odt-to-odp`/`odp-to-odt`, `xlsx-to-markdown`/`markdown-to-xlsx`) populate one too, just with `pages` always absent, since a bridge never runs a layout engine. `odm-to-pdf`/`odb-*`/`set-metadata` don't expose the flag at all, since none of them goes through `DocumentConverter.convert` in the first place. `odb-tables`, `odb-forms`, `odb-reports`, `fonts`, `docx-extras`, `metadata`, `formats`, and `pdf-inspect` each take only their own `--json` (plus `pdf-inspect`'s own `--full`); `odb-query` takes `--sql <text>`/`--query <savedName>` (mutually exclusive) alongside its own `--json`, with none of the shared flags above since it only reads and writes nothing; `from-package` and `set-metadata` each take `--to <format>` alongside the shared flags in this table; `odb-render-report` takes `--report <name>` and `--to <format>` alongside the shared flags and the font flags below; `tui` takes no flags at all, only an optional positional file.
181
+ Three further flags select what a csv or svg edge of a conversion works on, threaded straight into documents.js's own `ConversionOptions`: `--delimiter <char>` (the field delimiter a csv source reads with, or a csv target writes with default `,`), `--sheet <name>` (the sheet a csv target writes, required when the source document has more than one), and `--page <index>` (the 0-based page an svg target draws, required when the source document has more than one). On the explicit commands they are registered only where the pair can reach the edge in question `--delimiter` on any pair with a csv edge, `--sheet` on a csv target, `--page` on an svg target and unconditionally on `convert` and `from-package`, whose target is only known once the output path or `--to` resolves at run time (the same registration reasoning the font flags below document). Leaving `--sheet` or `--page` unanswered on an ambiguous document fails with exit `3`, naming the sheets or page count to pick from:
182
+
183
+ `--dump-package <file>` is one flag further, registered only on the explicit conversions and `convert` — it writes the intermediate `DocumentPackage` (content carrying its own per-node rendered `frames`, plus the `pages` geometry those frames index into) that conversion built to a JSON file, tagged with its own `$schema` so `from-package` (above) can read it back in. Every conversion populates one, `odf-to-pdf` included — its dump carries a `formula`-kind content and the one A4 page it renders (the formula's glyphs travel through the PDF writer's own positioned-formula channel rather than as frame-stamped page content); every PDF-bypassing bridge (`ods-to-xlsx`, `docx-to-pptx`, `odg-to-svg`, and every other content-format pair above) populates one too, just with `pages` always absent, since a bridge never runs a layout engine. `odm-to-pdf`/`odb-*`/`set-metadata` don't expose the flag at all, since none of them goes through `DocumentConverter.convert` in the first place. `odb-tables`, `odb-forms`, `odb-reports`, `fonts`, `docx-extras`, `metadata`, `formats`, and `pdf-inspect` each take only their own `--json` (plus `pdf-inspect`'s own `--full`); `odb-query` takes `--sql <text>`/`--query <savedName>` (mutually exclusive) alongside its own `--json`, with none of the shared flags above since it only reads and writes nothing; `from-package` and `set-metadata` each take `--to <format>` alongside the shared flags in this table; `odb-render-report` takes `--report <name>` and `--to <format>` alongside the shared flags and the font flags below; `tui` takes no flags at all, only an optional positional file.
182
184
 
183
185
  ### Real fonts
184
186
 
@@ -195,7 +197,7 @@ The flag is repeatable, takes a `.ttf`/`.otf` path, and needs **no accompanying
195
197
 
196
198
  `--report-font-substitutions` prints each face that resolved to something other than what the document asked for, as it happens, with its structured fields intact (`--json` makes it one more NDJSON record: `{"type":"font-substitution","requestedFamily":"Calibri",…}`). Without it, the same fallbacks are still reported — the `font/substituted` diagnostic lines every conversion already emits — just as rendered messages after the fact rather than structured events as they occur.
197
199
 
198
- Both flags are registered only where they can do something: the nine `<format>-to-pdf` conversions, `convert`, `odm-to-pdf`, and `odb-render-report`. The last two register them unconditionally (like `convert`, whose target isn't known until the output path or `--to` resolves) even though a `docx`/`odt` render has nothing to resolve fonts against — the same non-pdf no-op every other command in this list already documents. A `pdf-to-<format>` reconstruction reads a PDF's own already-positioned glyphs and a format-to-format bridge runs no layout engine at all, so neither resolves a typeface and neither advertises the flags.
200
+ Both flags are registered only where they can do something: the `<format>-to-pdf` conversions, `convert`, `odm-to-pdf`, and `odb-render-report`. The last two register them unconditionally (like `convert`, whose target isn't known until the output path or `--to` resolves) even though a `docx`/`odt` render has nothing to resolve fonts against — the same non-pdf no-op every other command in this list already documents. A `pdf-to-<format>` reconstruction reads a PDF's own already-positioned glyphs and a format-to-format bridge runs no layout engine at all, so neither resolves a typeface and neither advertises the flags.
199
201
 
200
202
  Diagnostics and the summary line always go to stderr; stdout is reserved for the converted bytes on any command writing to `-`.
201
203
 
@@ -206,7 +208,7 @@ Diagnostics and the summary line always go to stderr; stdout is reserved for the
206
208
  | `0` | Success. |
207
209
  | `1` | The input was unusable — a malformed or encrypted PDF, or any other conversion failure not covered by the codes below. |
208
210
  | `2` | A usage error — bad flags, conflicting output destinations, an unrecognised format, or (for a bare/`--help`/`--version` invocation) commander's own exit path. |
209
- | `3` | documents.js needs more information to finish, not a different file — an unresolved `.odm` chapter, a `.odb` table that wasn't specified (or wasn't found, or has no embedded engine at all, or uses an unsupported HSQLDB script serialisation), or a `.odb` report that wasn't specified when the database declares more than one. |
211
+ | `3` | documents.js needs more information to finish, not a different file — an unresolved `.odm` chapter, a `.odb` table that wasn't specified (or wasn't found, or has no embedded engine at all, or uses an unsupported HSQLDB script serialisation), a `.odb` report that wasn't specified when the database declares more than one, a csv target whose source carries more than one sheet (or a `--sheet` that names one it doesn't), or an svg target whose source carries more than one page (or a `--page` that indexes past the last). |
210
212
  | `124` | The run's own `--timeout` elapsed before it finished. |
211
213
  | `130` | Interrupted by `SIGINT` (Ctrl+C). |
212
214
 
@@ -218,7 +220,7 @@ It supports the same seven formats documents.js's live-view editors cover — do
218
220
 
219
221
  Markdown (`.md`/`.markdown`) shares the same paragraph/run/table body-list screens docx and odt already use, through documents.js's own `MarkdownEditor` (`openMarkdown`/`createMarkdownEditor`) — a genuine live view over a mutable `ContentDocument`, the same live-view contract every other editor here follows, even though there is no `XmlElement` tree underneath it the way there is for docx/odt (`MarkdownEditor.toMarkdownText()` re-serialises the whole document fresh on every call, rather than exposing a `toBytes()`). Appending a paragraph, appending a run, and toggling bold/italic all go through the identical reducer actions docx/odt use; a markdown run has no underline, colour, font family, or font size at all (CommonMark/GFM has no construct for any of the four), so those keys — along with image insertion, which `MarkdownParagraph` has no counterpart for — are simply absent from a markdown paragraph's own key hints rather than opening a prompt that could only end in a warning. A markdown table can be created and its cells edited through the same 'T' wizard and table-view screens docx/odt use, but GFM tables have no cell-merge concept, so a merge requested alongside table creation still creates the table (unmerged) and reports why the merge itself didn't happen. `:view-source` (markdown documents only) shows the literal text the document was opened with side by side with what a save would write right now — these can genuinely differ even with no edits made this session, from a heading-style, bullet-marker, or line-ending choice the writer normalises. Every save re-serialises the whole document fresh through `buildMarkdownText`, a deliberate, permanent consequence of structured editing rather than something to work around. Diagnostics from the read side (a clamped heading level, a dropped front-matter key, a fenced code block's own info string with nowhere to go, …) now surface into the same diagnostics panel a PDF export's own substitutions already populate, the moment a `.md` file is opened, not only on export. documents.js's own `createMarkdownEditor()` exists now, but this TUI does not yet wire a "new markdown document" flow into `:new`/the new-document picker, so a markdown document can still only be opened from an existing file.
220
222
 
221
- Three further formats open read-only: a `.odb` browses its tables and rows with no write path at all (documents.js's own `.odb` support has no write direction to offer), a `.pdf` browses its pages and positioned items rather than being edited in place, and a `.xlsx` opens as a converted PDF preview — documents.js has no xlsx editor to hold a live view into, so opening one runs `xlsxToPdf` once at open time and browses the result through the identical page-list/page-items/item-detail screens a real `.pdf` uses, with the original bytes kept alongside so a later export re-runs `xlsxToPdf` with the caller's own fonts and diagnostics rather than reusing the fixed preview conversion. A `.odb` additionally browses its *structure* alongside its data: `f` from the table list opens the form browser and `r` the report browser, each listing what the database declares and opening one to show it in full — a form's own data source and field-bound controls (sub-forms nested under their parent), a report's data-source command, band and group structure, and every `rpt:` formula. Both are rendered through the same `src/odb-structure.ts` the `odb-forms`/`odb-reports` commands print, so the two views cannot drift apart, and search filters by line (`/SUM` narrows a long report to its aggregate expressions). `Enter` on a report's own detail screen renders it — its data-source command resolved, its `rpt:` formulas evaluated, its bands laid out — to a real `docx`/`odt`/`pdf` file, through the same two-field destination-path-then-font-list form the PDF-export screen below uses; the TUI counterpart to the `odb-render-report` command. A standalone `.odf` formula document has no TUI editor either — nothing to edit interactively, only a PDF conversion.
223
+ Three further kinds of format open read-only: a `.odb` browses its tables and rows with no write path at all (documents.js's own `.odb` support has no write direction to offer), a `.pdf` browses its pages and positioned items rather than being edited in place, and a `.xlsx`, `.csv`, or `.svg` opens as a converted PDF preview — documents.js has no spreadsheet or svg editor to hold a live view into, so opening one runs `xlsxToPdf`, `csvToPdf`, or `svgToPdf` once at open time and browses the result through the identical page-list/page-items/item-detail screens a real `.pdf` uses, with the original bytes kept alongside so a later export re-runs the same conversion with the caller's own fonts and diagnostics rather than reusing the fixed preview conversion. A `.odb` additionally browses its *structure* alongside its data: `f` from the table list opens the form browser and `r` the report browser, each listing what the database declares and opening one to show it in full — a form's own data source and field-bound controls (sub-forms nested under their parent), a report's data-source command, band and group structure, and every `rpt:` formula. Both are rendered through the same `src/odb-structure.ts` the `odb-forms`/`odb-reports` commands print, so the two views cannot drift apart, and search filters by line (`/SUM` narrows a long report to its aggregate expressions). `Enter` on a report's own detail screen renders it — its data-source command resolved, its `rpt:` formulas evaluated, its bands laid out — to a real `docx`/`odt`/`pdf` file, through the same two-field destination-path-then-font-list form the PDF-export screen below uses; the TUI counterpart to the `odb-render-report` command. A standalone `.odf` formula document has no TUI editor either — nothing to edit interactively, only a PDF conversion.
222
224
 
223
225
  The export-to-PDF screen (`e` from any editor screen) is a two-field form: a destination path, then an optional comma-separated list of local `.ttf`/`.otf` paths, which are the same `--font-file` faces the CLI takes and are derived the same way — each font's family, weight, and slope come from the file itself. `Enter` on the path field moves to the fonts field and `Enter` there exports, so leaving fonts empty is still "type a path, press Enter twice". Comma-separated rather than space-separated because a font path routinely contains spaces and almost never a comma. A face falling back to a substitute is reported into the same diagnostics panel a character substitution already is, and a bad font path fails the export with the file named, before anything is written to the destination.
224
226
 
package/dist/cli.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { a as odbFormSummary, c as formatDocxExtrasLines, d as writeOutput, f as loadProvidedFonts, h as isDocumentFormat, i as formatOdbReportLines, l as readInput, m as inferFormatFromExtension, n as describeOdbReport, o as formatMetadataLines, r as formatOdbFormLines, s as presentMetadataEntries, t as describeOdbForm, u as resolveDefaultOutputPath } from "./odb-structure-DePnGZAI.js";
2
+ import { a as odbFormSummary, c as formatDocxExtrasLines, d as writeOutput, f as loadProvidedFonts, h as isDocumentFormat, i as formatOdbReportLines, l as readInput, m as inferFormatFromExtension, n as describeOdbReport, o as formatMetadataLines, r as formatOdbFormLines, s as presentMetadataEntries, t as describeOdbForm, u as resolveDefaultOutputPath } from "./odb-structure-B1ygPCEa.js";
3
3
  import { Command, CommanderError, InvalidArgumentError } from "commander";
4
4
  import { writeFile } from "node:fs/promises";
5
5
  import { basename, dirname, extname, join, resolve } from "node:path";
6
- import { HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError, OdbNoEmbeddedDataSourceError, OdbReportNotSpecifiedError, OdbTableNotFoundError, OdbTableNotSpecifiedError, OdbUnsupportedFormatError, OdmUnresolvedSectionError, PdfEncryptedError, PdfParseError, UnrecognizedDocumentSchemaError, UnsupportedFontSourceFormatError, buildDocumentBytes, createLocalDocumentConverter, decodeOdbPackage, decodePackage, documentFromJson, documentPackageWithSchema, documentSchemaKindOf, evaluateSelect, extractSourceFontsForFormat, hsqldbCellDisplayText, layoutDocumentWithSchema, odbReportToDocx, odbReportToOdt, odbReportToPdf, odbToCsv, odbToXlsx, odmToPdf, parseSelect, readDocumentMetadata, readDocxExtras, readOdbForms, readOdbInventory, readOdbReportContent, readOdbReports, readOdbTables, readPdf, setDocumentMetadata } from "documents.js";
6
+ import { CsvSheetNotFoundError, CsvSheetNotSpecifiedError, HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError, OdbNoEmbeddedDataSourceError, OdbReportNotSpecifiedError, OdbTableNotFoundError, OdbTableNotSpecifiedError, OdbUnsupportedFormatError, OdmUnresolvedSectionError, PdfEncryptedError, PdfParseError, SvgMultiPageNotSpecifiedError, SvgPageNotFoundError, UnrecognizedDocumentSchemaError, UnsupportedFontSourceFormatError, buildCsvText, buildDocumentBytes, buildSvgText, createLocalDocumentConverter, decodeOdbPackage, decodePackage, documentFromJson, documentPackageWithSchema, documentSchemaKindOf, encodeCsvText, encodeSvgText, evaluateSelect, extractSourceFontsForFormat, hsqldbCellDisplayText, layoutDocumentWithSchema, odbReportToDocx, odbReportToOdt, odbReportToPdf, odbToCsv, odbToXlsx, odmToPdf, parseSelect, readDocumentMetadata, readDocxExtras, readOdbForms, readOdbInventory, readOdbReportContent, readOdbReports, readOdbTables, readPdf, setDocumentMetadata } from "documents.js";
7
7
  import { existsSync, readFileSync } from "node:fs";
8
8
  //#region src/runtime/abort.ts
9
9
  function combineSignals(a, b) {
@@ -113,7 +113,7 @@ function pdfDiagnosticToDiagnostic(diagnostic) {
113
113
  function mapErrorToExit(error, abortReason) {
114
114
  if (abortReason === "interrupt") return 130;
115
115
  if (abortReason === "timeout") return 124;
116
- if (error instanceof OdmUnresolvedSectionError || error instanceof OdbTableNotSpecifiedError || error instanceof OdbTableNotFoundError || error instanceof OdbNoEmbeddedDataSourceError || error instanceof OdbUnsupportedFormatError || error instanceof OdbReportNotSpecifiedError) return 3;
116
+ if (error instanceof OdmUnresolvedSectionError || error instanceof OdbTableNotSpecifiedError || error instanceof OdbTableNotFoundError || error instanceof OdbNoEmbeddedDataSourceError || error instanceof OdbUnsupportedFormatError || error instanceof OdbReportNotSpecifiedError || error instanceof CsvSheetNotSpecifiedError || error instanceof CsvSheetNotFoundError || error instanceof SvgMultiPageNotSpecifiedError || error instanceof SvgPageNotFoundError) return 3;
117
117
  if (error instanceof HsqldbSqlUnsupportedError || error instanceof HsqldbSqlParseError || error instanceof HsqldbSqlEvaluationError) return 1;
118
118
  if (error instanceof UnsupportedFontSourceFormatError) return 2;
119
119
  if (error instanceof PdfEncryptedError || error instanceof PdfParseError) return 1;
@@ -133,7 +133,7 @@ function createFilesystemMarkdownImageResolver(baseDir) {
133
133
  }
134
134
  //#endregion
135
135
  //#region src/commands/shared.ts
136
- const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, odf, markdown, pdf";
136
+ const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, pdf";
137
137
  function resolveTargetFormat(output, out, to) {
138
138
  if (to !== void 0) {
139
139
  if (!isDocumentFormat(to)) return { errorMessage: `unknown --to format '${to}'; expected one of ${KNOWN_DOCUMENT_FORMATS}` };
@@ -176,7 +176,10 @@ function buildConversionAction(source, target) {
176
176
  quiet: options.quiet,
177
177
  command
178
178
  }) : void 0,
179
- images: createFilesystemMarkdownImageResolver(input === "-" ? "." : dirname(resolve(input)))
179
+ images: createFilesystemMarkdownImageResolver(input === "-" ? "." : dirname(resolve(input))),
180
+ delimiter: options.delimiter,
181
+ sheet: options.sheet,
182
+ page: options.page
180
183
  });
181
184
  await writeOutput(resolvedOutput, result.document.bytes);
182
185
  const reporter = createDiagnosticReporter({
@@ -235,6 +238,15 @@ function addConversionFlags(command) {
235
238
  addVerboseOption(command);
236
239
  return command;
237
240
  }
241
+ function addDelimiterOption(command) {
242
+ return command.option("--delimiter <char>", "field delimiter a csv source reads with, or a csv target writes with (default ',')");
243
+ }
244
+ function addSheetOption(command) {
245
+ return command.option("--sheet <name>", "the sheet a csv target writes, when the source document has more than one");
246
+ }
247
+ function addPageOption(command) {
248
+ return command.option("--page <index>", "the 0-based page an svg target draws, when the source document has more than one", (value) => Number.parseInt(value, 10));
249
+ }
238
250
  //#endregion
239
251
  //#region src/commands/convert.ts
240
252
  function toConversionCommandOptions(options) {
@@ -246,7 +258,10 @@ function toConversionCommandOptions(options) {
246
258
  verbose: options.verbose,
247
259
  dumpPackage: options.dumpPackage,
248
260
  fontFiles: options.fontFile,
249
- reportFontSubstitutions: options.reportFontSubstitutions
261
+ reportFontSubstitutions: options.reportFontSubstitutions,
262
+ delimiter: options.delimiter,
263
+ sheet: options.sheet,
264
+ page: options.page
250
265
  };
251
266
  }
252
267
  async function runGenericConvert(input, output, options) {
@@ -279,6 +294,9 @@ function registerConversionCommands(program) {
279
294
  addConversionFlags(command);
280
295
  addDumpPackageOption(command);
281
296
  if (target === "pdf") addFontOptions(command);
297
+ if (source === "csv" || target === "csv") addDelimiterOption(command);
298
+ if (target === "csv") addSheetOption(command);
299
+ if (target === "svg") addPageOption(command);
282
300
  command.action(async (input, output, options) => {
283
301
  process.exitCode = await buildConversionAction(source, target)(input, output, toConversionCommandOptions(options));
284
302
  });
@@ -287,6 +305,9 @@ function registerConversionCommands(program) {
287
305
  addConversionFlags(generic);
288
306
  addDumpPackageOption(generic);
289
307
  addFontOptions(generic);
308
+ addDelimiterOption(generic);
309
+ addSheetOption(generic);
310
+ addPageOption(generic);
290
311
  generic.option("--to <format>", `target format when it cannot be inferred from the output path (${KNOWN_DOCUMENT_FORMATS})`);
291
312
  generic.action(async (input, output, options) => {
292
313
  process.exitCode = await runGenericConvert(input, output, options);
@@ -411,7 +432,10 @@ async function runFromPackage(input, output, options) {
411
432
  process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentPackage -- only a file written by --dump-package can be read back by this command\n`);
412
433
  return 2;
413
434
  }
414
- const bytes = buildDocumentBytes(result.value, target.format);
435
+ const bytes = target.format === "csv" ? encodeCsvText(buildCsvText(result.value.content, {
436
+ delimiter: options.delimiter,
437
+ sheet: options.sheet
438
+ })) : target.format === "svg" ? encodeSvgText(buildSvgText(result.value.content, { page: options.page })) : buildDocumentBytes(result.value, target.format);
415
439
  await writeOutput(resolvedOutput, bytes);
416
440
  createDiagnosticReporter({
417
441
  json: options.json,
@@ -439,6 +463,9 @@ function registerFromPackageCommand(program) {
439
463
  addJsonOption(command);
440
464
  addQuietOption(command);
441
465
  addVerboseOption(command);
466
+ addDelimiterOption(command);
467
+ addSheetOption(command);
468
+ addPageOption(command);
442
469
  command.option("--to <format>", `target format when it cannot be inferred from the output path (${KNOWN_DOCUMENT_FORMATS})`);
443
470
  command.action(async (input, output, options) => {
444
471
  process.exitCode = await runFromPackage(input, output, options);
@@ -1068,12 +1095,12 @@ function registerSetMetadataCommand(program) {
1068
1095
  }
1069
1096
  //#endregion
1070
1097
  //#region package.json
1071
- var version = "2.0.0";
1098
+ var version = "2.1.0";
1072
1099
  //#endregion
1073
1100
  //#region src/program.ts
1074
1101
  function createProgram() {
1075
1102
  const program = new Command("document-cli");
1076
- program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/markdown conversion, bridge, and inspector as a scriptable command");
1103
+ program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown conversion, bridge, and inspector as a scriptable command");
1077
1104
  program.version(version);
1078
1105
  program.exitOverride((error) => {
1079
1106
  process.exitCode = error.exitCode === 0 ? 0 : 2;
@@ -1095,7 +1122,7 @@ function createProgram() {
1095
1122
  //#region src/cli.ts
1096
1123
  async function launchTui(startPath, signal) {
1097
1124
  try {
1098
- const { runTui } = await import("./tui-Bg4JfhRZ.js");
1125
+ const { runTui } = await import("./tui-tT3An-cI.js");
1099
1126
  await runTui({
1100
1127
  startPath,
1101
1128
  signal
package/dist/index.cjs CHANGED
@@ -25,6 +25,8 @@ const EXTENSION_TO_FORMAT = {
25
25
  otg: "odg",
26
26
  odf: "odf",
27
27
  otf: "odf",
28
+ csv: "csv",
29
+ svg: "svg",
28
30
  markdown: "markdown",
29
31
  md: "markdown",
30
32
  pdf: "pdf"
@@ -38,6 +40,8 @@ const FORMAT_TO_EXTENSION = {
38
40
  ods: "ods",
39
41
  odg: "odg",
40
42
  odf: "odf",
43
+ csv: "csv",
44
+ svg: "svg",
41
45
  markdown: "md",
42
46
  pdf: "pdf"
43
47
  };
@@ -172,7 +176,7 @@ const EXIT_INTERRUPTED = 130;
172
176
  function mapErrorToExit(error, abortReason) {
173
177
  if (abortReason === "interrupt") return 130;
174
178
  if (abortReason === "timeout") return 124;
175
- if (error instanceof documents_js.OdmUnresolvedSectionError || error instanceof documents_js.OdbTableNotSpecifiedError || error instanceof documents_js.OdbTableNotFoundError || error instanceof documents_js.OdbNoEmbeddedDataSourceError || error instanceof documents_js.OdbUnsupportedFormatError || error instanceof documents_js.OdbReportNotSpecifiedError) return 3;
179
+ if (error instanceof documents_js.OdmUnresolvedSectionError || error instanceof documents_js.OdbTableNotSpecifiedError || error instanceof documents_js.OdbTableNotFoundError || error instanceof documents_js.OdbNoEmbeddedDataSourceError || error instanceof documents_js.OdbUnsupportedFormatError || error instanceof documents_js.OdbReportNotSpecifiedError || error instanceof documents_js.CsvSheetNotSpecifiedError || error instanceof documents_js.CsvSheetNotFoundError || error instanceof documents_js.SvgMultiPageNotSpecifiedError || error instanceof documents_js.SvgPageNotFoundError) return 3;
176
180
  if (error instanceof documents_js.HsqldbSqlUnsupportedError || error instanceof documents_js.HsqldbSqlParseError || error instanceof documents_js.HsqldbSqlEvaluationError) return 1;
177
181
  if (error instanceof documents_js.UnsupportedFontSourceFormatError) return 2;
178
182
  if (error instanceof documents_js.PdfEncryptedError || error instanceof documents_js.PdfParseError) return 1;
@@ -247,7 +251,7 @@ function resolveDefaultOutputPath(inputPath, targetFormat) {
247
251
  }
248
252
  //#endregion
249
253
  //#region src/commands/shared.ts
250
- const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, odf, markdown, pdf";
254
+ const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, pdf";
251
255
  function resolveTargetFormat(output, out, to) {
252
256
  if (to !== void 0) {
253
257
  if (!isDocumentFormat(to)) return { errorMessage: `unknown --to format '${to}'; expected one of ${KNOWN_DOCUMENT_FORMATS}` };
@@ -290,7 +294,10 @@ function buildConversionAction(source, target) {
290
294
  quiet: options.quiet,
291
295
  command
292
296
  }) : void 0,
293
- images: createFilesystemMarkdownImageResolver(input === "-" ? "." : (0, node_path.dirname)((0, node_path.resolve)(input)))
297
+ images: createFilesystemMarkdownImageResolver(input === "-" ? "." : (0, node_path.dirname)((0, node_path.resolve)(input))),
298
+ delimiter: options.delimiter,
299
+ sheet: options.sheet,
300
+ page: options.page
294
301
  });
295
302
  await writeOutput(resolvedOutput, result.document.bytes);
296
303
  const reporter = createDiagnosticReporter({
@@ -349,6 +356,15 @@ function addConversionFlags(command) {
349
356
  addVerboseOption(command);
350
357
  return command;
351
358
  }
359
+ function addDelimiterOption(command) {
360
+ return command.option("--delimiter <char>", "field delimiter a csv source reads with, or a csv target writes with (default ',')");
361
+ }
362
+ function addSheetOption(command) {
363
+ return command.option("--sheet <name>", "the sheet a csv target writes, when the source document has more than one");
364
+ }
365
+ function addPageOption(command) {
366
+ return command.option("--page <index>", "the 0-based page an svg target draws, when the source document has more than one", (value) => Number.parseInt(value, 10));
367
+ }
352
368
  //#endregion
353
369
  //#region src/commands/convert.ts
354
370
  function toConversionCommandOptions(options) {
@@ -360,7 +376,10 @@ function toConversionCommandOptions(options) {
360
376
  verbose: options.verbose,
361
377
  dumpPackage: options.dumpPackage,
362
378
  fontFiles: options.fontFile,
363
- reportFontSubstitutions: options.reportFontSubstitutions
379
+ reportFontSubstitutions: options.reportFontSubstitutions,
380
+ delimiter: options.delimiter,
381
+ sheet: options.sheet,
382
+ page: options.page
364
383
  };
365
384
  }
366
385
  async function runGenericConvert(input, output, options) {
@@ -393,6 +412,9 @@ function registerConversionCommands(program) {
393
412
  addConversionFlags(command);
394
413
  addDumpPackageOption(command);
395
414
  if (target === "pdf") addFontOptions(command);
415
+ if (source === "csv" || target === "csv") addDelimiterOption(command);
416
+ if (target === "csv") addSheetOption(command);
417
+ if (target === "svg") addPageOption(command);
396
418
  command.action(async (input, output, options) => {
397
419
  process.exitCode = await buildConversionAction(source, target)(input, output, toConversionCommandOptions(options));
398
420
  });
@@ -401,6 +423,9 @@ function registerConversionCommands(program) {
401
423
  addConversionFlags(generic);
402
424
  addDumpPackageOption(generic);
403
425
  addFontOptions(generic);
426
+ addDelimiterOption(generic);
427
+ addSheetOption(generic);
428
+ addPageOption(generic);
404
429
  generic.option("--to <format>", `target format when it cannot be inferred from the output path (${KNOWN_DOCUMENT_FORMATS})`);
405
430
  generic.action(async (input, output, options) => {
406
431
  process.exitCode = await runGenericConvert(input, output, options);
@@ -583,7 +608,10 @@ async function runFromPackage(input, output, options) {
583
608
  process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentPackage -- only a file written by --dump-package can be read back by this command\n`);
584
609
  return 2;
585
610
  }
586
- const bytes = (0, documents_js.buildDocumentBytes)(result.value, target.format);
611
+ const bytes = target.format === "csv" ? (0, documents_js.encodeCsvText)((0, documents_js.buildCsvText)(result.value.content, {
612
+ delimiter: options.delimiter,
613
+ sheet: options.sheet
614
+ })) : target.format === "svg" ? (0, documents_js.encodeSvgText)((0, documents_js.buildSvgText)(result.value.content, { page: options.page })) : (0, documents_js.buildDocumentBytes)(result.value, target.format);
587
615
  await writeOutput(resolvedOutput, bytes);
588
616
  createDiagnosticReporter({
589
617
  json: options.json,
@@ -611,6 +639,9 @@ function registerFromPackageCommand(program) {
611
639
  addJsonOption(command);
612
640
  addQuietOption(command);
613
641
  addVerboseOption(command);
642
+ addDelimiterOption(command);
643
+ addSheetOption(command);
644
+ addPageOption(command);
614
645
  command.option("--to <format>", `target format when it cannot be inferred from the output path (${KNOWN_DOCUMENT_FORMATS})`);
615
646
  command.action(async (input, output, options) => {
616
647
  process.exitCode = await runFromPackage(input, output, options);
@@ -1396,12 +1427,12 @@ function registerSetMetadataCommand(program) {
1396
1427
  }
1397
1428
  //#endregion
1398
1429
  //#region package.json
1399
- var version = "2.0.0";
1430
+ var version = "2.1.0";
1400
1431
  //#endregion
1401
1432
  //#region src/program.ts
1402
1433
  function createProgram() {
1403
1434
  const program = new commander.Command("document-cli");
1404
- program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/markdown conversion, bridge, and inspector as a scriptable command");
1435
+ program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown conversion, bridge, and inspector as a scriptable command");
1405
1436
  program.version(version);
1406
1437
  program.exitOverride((error) => {
1407
1438
  process.exitCode = error.exitCode === 0 ? 0 : 2;
package/dist/index.d.cts CHANGED
@@ -15,6 +15,9 @@ interface ConversionCommandOptions {
15
15
  readonly dumpPackage?: string;
16
16
  readonly fontFiles?: readonly string[];
17
17
  readonly reportFontSubstitutions?: boolean;
18
+ readonly delimiter?: string;
19
+ readonly sheet?: string;
20
+ readonly page?: number;
18
21
  }
19
22
  declare function formatError(error: unknown, verbose: boolean): string;
20
23
  declare function buildConversionAction(source: DocumentFormat, target: DocumentFormat): (input: string, output: string | undefined, options: ConversionCommandOptions) => Promise<number>;
package/dist/index.d.ts CHANGED
@@ -15,6 +15,9 @@ interface ConversionCommandOptions {
15
15
  readonly dumpPackage?: string;
16
16
  readonly fontFiles?: readonly string[];
17
17
  readonly reportFontSubstitutions?: boolean;
18
+ readonly delimiter?: string;
19
+ readonly sheet?: string;
20
+ readonly page?: number;
18
21
  }
19
22
  declare function formatError(error: unknown, verbose: boolean): string;
20
23
  declare function buildConversionAction(source: DocumentFormat, target: DocumentFormat): (input: string, output: string | undefined, options: ConversionCommandOptions) => Promise<number>;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { readFile, writeFile } from "node:fs/promises";
2
2
  import { basename, dirname, extname, join, resolve } from "node:path";
3
- import { HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError, OdbNoEmbeddedDataSourceError, OdbReportNotSpecifiedError, OdbTableNotFoundError, OdbTableNotSpecifiedError, OdbUnsupportedFormatError, OdmUnresolvedSectionError, PdfEncryptedError, PdfParseError, UnrecognizedDocumentSchemaError, UnsupportedFontSourceFormatError, buildDocumentBytes, createLocalDocumentConverter, decodeOdbPackage, decodePackage, describeFontFace, documentFromJson, documentPackageWithSchema, documentSchemaKindOf, evaluateSelect, extractSourceFontsForFormat, hsqldbCellDisplayText, layoutDocumentWithSchema, odbReportToDocx, odbReportToOdt, odbReportToPdf, odbToCsv, odbToXlsx, odmToPdf, parseSelect, readDocumentMetadata, readDocxExtras, readOdbForms, readOdbInventory, readOdbReportContent, readOdbReports, readOdbTables, readPdf, setDocumentMetadata } from "documents.js";
3
+ import { CsvSheetNotFoundError, CsvSheetNotSpecifiedError, HsqldbSqlEvaluationError, HsqldbSqlParseError, HsqldbSqlUnsupportedError, OdbNoEmbeddedDataSourceError, OdbReportNotSpecifiedError, OdbTableNotFoundError, OdbTableNotSpecifiedError, OdbUnsupportedFormatError, OdmUnresolvedSectionError, PdfEncryptedError, PdfParseError, SvgMultiPageNotSpecifiedError, SvgPageNotFoundError, UnrecognizedDocumentSchemaError, UnsupportedFontSourceFormatError, buildCsvText, buildDocumentBytes, buildSvgText, createLocalDocumentConverter, decodeOdbPackage, decodePackage, describeFontFace, documentFromJson, documentPackageWithSchema, documentSchemaKindOf, encodeCsvText, encodeSvgText, evaluateSelect, extractSourceFontsForFormat, hsqldbCellDisplayText, layoutDocumentWithSchema, odbReportToDocx, odbReportToOdt, odbReportToPdf, odbToCsv, odbToXlsx, odmToPdf, parseSelect, readDocumentMetadata, readDocxExtras, readOdbForms, readOdbInventory, readOdbReportContent, readOdbReports, readOdbTables, readPdf, setDocumentMetadata } from "documents.js";
4
4
  import { existsSync, readFileSync } from "node:fs";
5
5
  import { Command, InvalidArgumentError } from "commander";
6
6
  //#region src/format.ts
@@ -24,6 +24,8 @@ const EXTENSION_TO_FORMAT = {
24
24
  otg: "odg",
25
25
  odf: "odf",
26
26
  otf: "odf",
27
+ csv: "csv",
28
+ svg: "svg",
27
29
  markdown: "markdown",
28
30
  md: "markdown",
29
31
  pdf: "pdf"
@@ -37,6 +39,8 @@ const FORMAT_TO_EXTENSION = {
37
39
  ods: "ods",
38
40
  odg: "odg",
39
41
  odf: "odf",
42
+ csv: "csv",
43
+ svg: "svg",
40
44
  markdown: "md",
41
45
  pdf: "pdf"
42
46
  };
@@ -171,7 +175,7 @@ const EXIT_INTERRUPTED = 130;
171
175
  function mapErrorToExit(error, abortReason) {
172
176
  if (abortReason === "interrupt") return 130;
173
177
  if (abortReason === "timeout") return 124;
174
- if (error instanceof OdmUnresolvedSectionError || error instanceof OdbTableNotSpecifiedError || error instanceof OdbTableNotFoundError || error instanceof OdbNoEmbeddedDataSourceError || error instanceof OdbUnsupportedFormatError || error instanceof OdbReportNotSpecifiedError) return 3;
178
+ if (error instanceof OdmUnresolvedSectionError || error instanceof OdbTableNotSpecifiedError || error instanceof OdbTableNotFoundError || error instanceof OdbNoEmbeddedDataSourceError || error instanceof OdbUnsupportedFormatError || error instanceof OdbReportNotSpecifiedError || error instanceof CsvSheetNotSpecifiedError || error instanceof CsvSheetNotFoundError || error instanceof SvgMultiPageNotSpecifiedError || error instanceof SvgPageNotFoundError) return 3;
175
179
  if (error instanceof HsqldbSqlUnsupportedError || error instanceof HsqldbSqlParseError || error instanceof HsqldbSqlEvaluationError) return 1;
176
180
  if (error instanceof UnsupportedFontSourceFormatError) return 2;
177
181
  if (error instanceof PdfEncryptedError || error instanceof PdfParseError) return 1;
@@ -246,7 +250,7 @@ function resolveDefaultOutputPath(inputPath, targetFormat) {
246
250
  }
247
251
  //#endregion
248
252
  //#region src/commands/shared.ts
249
- const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, odf, markdown, pdf";
253
+ const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, pdf";
250
254
  function resolveTargetFormat(output, out, to) {
251
255
  if (to !== void 0) {
252
256
  if (!isDocumentFormat(to)) return { errorMessage: `unknown --to format '${to}'; expected one of ${KNOWN_DOCUMENT_FORMATS}` };
@@ -289,7 +293,10 @@ function buildConversionAction(source, target) {
289
293
  quiet: options.quiet,
290
294
  command
291
295
  }) : void 0,
292
- images: createFilesystemMarkdownImageResolver(input === "-" ? "." : dirname(resolve(input)))
296
+ images: createFilesystemMarkdownImageResolver(input === "-" ? "." : dirname(resolve(input))),
297
+ delimiter: options.delimiter,
298
+ sheet: options.sheet,
299
+ page: options.page
293
300
  });
294
301
  await writeOutput(resolvedOutput, result.document.bytes);
295
302
  const reporter = createDiagnosticReporter({
@@ -348,6 +355,15 @@ function addConversionFlags(command) {
348
355
  addVerboseOption(command);
349
356
  return command;
350
357
  }
358
+ function addDelimiterOption(command) {
359
+ return command.option("--delimiter <char>", "field delimiter a csv source reads with, or a csv target writes with (default ',')");
360
+ }
361
+ function addSheetOption(command) {
362
+ return command.option("--sheet <name>", "the sheet a csv target writes, when the source document has more than one");
363
+ }
364
+ function addPageOption(command) {
365
+ return command.option("--page <index>", "the 0-based page an svg target draws, when the source document has more than one", (value) => Number.parseInt(value, 10));
366
+ }
351
367
  //#endregion
352
368
  //#region src/commands/convert.ts
353
369
  function toConversionCommandOptions(options) {
@@ -359,7 +375,10 @@ function toConversionCommandOptions(options) {
359
375
  verbose: options.verbose,
360
376
  dumpPackage: options.dumpPackage,
361
377
  fontFiles: options.fontFile,
362
- reportFontSubstitutions: options.reportFontSubstitutions
378
+ reportFontSubstitutions: options.reportFontSubstitutions,
379
+ delimiter: options.delimiter,
380
+ sheet: options.sheet,
381
+ page: options.page
363
382
  };
364
383
  }
365
384
  async function runGenericConvert(input, output, options) {
@@ -392,6 +411,9 @@ function registerConversionCommands(program) {
392
411
  addConversionFlags(command);
393
412
  addDumpPackageOption(command);
394
413
  if (target === "pdf") addFontOptions(command);
414
+ if (source === "csv" || target === "csv") addDelimiterOption(command);
415
+ if (target === "csv") addSheetOption(command);
416
+ if (target === "svg") addPageOption(command);
395
417
  command.action(async (input, output, options) => {
396
418
  process.exitCode = await buildConversionAction(source, target)(input, output, toConversionCommandOptions(options));
397
419
  });
@@ -400,6 +422,9 @@ function registerConversionCommands(program) {
400
422
  addConversionFlags(generic);
401
423
  addDumpPackageOption(generic);
402
424
  addFontOptions(generic);
425
+ addDelimiterOption(generic);
426
+ addSheetOption(generic);
427
+ addPageOption(generic);
403
428
  generic.option("--to <format>", `target format when it cannot be inferred from the output path (${KNOWN_DOCUMENT_FORMATS})`);
404
429
  generic.action(async (input, output, options) => {
405
430
  process.exitCode = await runGenericConvert(input, output, options);
@@ -582,7 +607,10 @@ async function runFromPackage(input, output, options) {
582
607
  process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentPackage -- only a file written by --dump-package can be read back by this command\n`);
583
608
  return 2;
584
609
  }
585
- const bytes = buildDocumentBytes(result.value, target.format);
610
+ const bytes = target.format === "csv" ? encodeCsvText(buildCsvText(result.value.content, {
611
+ delimiter: options.delimiter,
612
+ sheet: options.sheet
613
+ })) : target.format === "svg" ? encodeSvgText(buildSvgText(result.value.content, { page: options.page })) : buildDocumentBytes(result.value, target.format);
586
614
  await writeOutput(resolvedOutput, bytes);
587
615
  createDiagnosticReporter({
588
616
  json: options.json,
@@ -610,6 +638,9 @@ function registerFromPackageCommand(program) {
610
638
  addJsonOption(command);
611
639
  addQuietOption(command);
612
640
  addVerboseOption(command);
641
+ addDelimiterOption(command);
642
+ addSheetOption(command);
643
+ addPageOption(command);
613
644
  command.option("--to <format>", `target format when it cannot be inferred from the output path (${KNOWN_DOCUMENT_FORMATS})`);
614
645
  command.action(async (input, output, options) => {
615
646
  process.exitCode = await runFromPackage(input, output, options);
@@ -1395,12 +1426,12 @@ function registerSetMetadataCommand(program) {
1395
1426
  }
1396
1427
  //#endregion
1397
1428
  //#region package.json
1398
- var version = "2.0.0";
1429
+ var version = "2.1.0";
1399
1430
  //#endregion
1400
1431
  //#region src/program.ts
1401
1432
  function createProgram() {
1402
1433
  const program = new Command("document-cli");
1403
- program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/markdown conversion, bridge, and inspector as a scriptable command");
1434
+ program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown conversion, bridge, and inspector as a scriptable command");
1404
1435
  program.version(version);
1405
1436
  program.exitOverride((error) => {
1406
1437
  process.exitCode = error.exitCode === 0 ? 0 : 2;
@@ -22,6 +22,8 @@ const EXTENSION_TO_FORMAT = {
22
22
  otg: "odg",
23
23
  odf: "odf",
24
24
  otf: "odf",
25
+ csv: "csv",
26
+ svg: "svg",
25
27
  markdown: "markdown",
26
28
  md: "markdown",
27
29
  pdf: "pdf"
@@ -35,6 +37,8 @@ const FORMAT_TO_EXTENSION = {
35
37
  ods: "ods",
36
38
  odg: "odg",
37
39
  odf: "odf",
40
+ csv: "csv",
41
+ svg: "svg",
38
42
  markdown: "md",
39
43
  pdf: "pdf"
40
44
  };
@@ -1,7 +1,7 @@
1
- import { c as formatDocxExtrasLines, f as loadProvidedFonts, i as formatOdbReportLines, l as readInput, m as inferFormatFromExtension, n as describeOdbReport, o as formatMetadataLines, p as formatToExtension, r as formatOdbFormLines, t as describeOdbForm } from "./odb-structure-DePnGZAI.js";
1
+ import { c as formatDocxExtrasLines, f as loadProvidedFonts, i as formatOdbReportLines, l as readInput, m as inferFormatFromExtension, n as describeOdbReport, o as formatMetadataLines, p as formatToExtension, r as formatOdbFormLines, t as describeOdbForm } from "./odb-structure-B1ygPCEa.js";
2
2
  import { readFile, writeFile } from "node:fs/promises";
3
3
  import { basename, dirname, extname, join } from "node:path";
4
- import { bytesToBase64, cellReference, columnIndexToLetters, createDocx, createOdg, createOdp, createOds, createOdt, createPdf, createPptx, decodeMarkdownText, decodeOdbPackage, docxToPdf, encodeMarkdownText, hsqldbCellDisplayText, markdownToPdf, odbReportToDocx, odbReportToOdt, odbReportToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDocx, openMarkdown, openOdg, openOdp, openOds, openOdt, openPdf, openPptx, parseXml, pptxToPdf, readDocxContent, readDocxExtras, readMarkdownContent, readOdbForms, readOdbReportContent, readOdbReports, readOdbTables, readOdgContent, readOdpContent, readOdsContent, readOdtContent, readPdf, readPptxContent, rgbHexToColor, xlsxToPdf } from "documents.js";
4
+ import { bytesToBase64, cellReference, columnIndexToLetters, createDocx, createOdg, createOdp, createOds, createOdt, createPdf, createPptx, csvToPdf, decodeMarkdownText, decodeOdbPackage, docxToPdf, encodeMarkdownText, hsqldbCellDisplayText, markdownToPdf, odbReportToDocx, odbReportToOdt, odbReportToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDocx, openMarkdown, openOdg, openOdp, openOds, openOdt, openPdf, openPptx, parseXml, pptxToPdf, readDocxContent, readDocxExtras, readMarkdownContent, readOdbForms, readOdbReportContent, readOdbReports, readOdbTables, readOdgContent, readOdpContent, readOdsContent, readOdtContent, readPdf, readPptxContent, rgbHexToColor, svgToPdf, xlsxToPdf } from "documents.js";
5
5
  import { readdirSync } from "node:fs";
6
6
  import { Box, Text, render, useApp, useInput, useWindowSize } from "ink";
7
7
  import { createContext, useContext, useEffect, useReducer, useState } from "react";
@@ -47,6 +47,16 @@ async function exportToPdf(openDocument, destinationPath, options) {
47
47
  await writeFile(destinationPath, pdfBytes);
48
48
  return;
49
49
  }
50
+ if (openDocument.format === "csv") {
51
+ const pdfBytes = csvToPdf(openDocument.bytes, pdfOptions);
52
+ await writeFile(destinationPath, pdfBytes);
53
+ return;
54
+ }
55
+ if (openDocument.format === "svg") {
56
+ const pdfBytes = svgToPdf(openDocument.bytes, pdfOptions);
57
+ await writeFile(destinationPath, pdfBytes);
58
+ return;
59
+ }
50
60
  const bytes = openDocument.editor.toBytes();
51
61
  const pdfBytes = convert(openDocument.format, bytes, pdfOptions);
52
62
  await writeFile(destinationPath, pdfBytes);
@@ -148,6 +158,18 @@ async function openDocumentAtPath(path, options = {}) {
148
158
  bytes,
149
159
  path
150
160
  };
161
+ case "csv": return {
162
+ format,
163
+ layout: readPdf(csvToPdf(bytes)),
164
+ bytes,
165
+ path
166
+ };
167
+ case "svg": return {
168
+ format,
169
+ layout: readPdf(svgToPdf(bytes)),
170
+ bytes,
171
+ path
172
+ };
151
173
  case "odf": throw new Error("A standalone .odf formula document has no editor; convert it to PDF (odfToPdf) instead");
152
174
  }
153
175
  }
@@ -195,7 +217,7 @@ function createNewDocument(format) {
195
217
  }
196
218
  }
197
219
  async function saveDocumentTo(openDocument, path) {
198
- if (openDocument.format === "odb" || openDocument.format === "xlsx") throw new Error(`A ${openDocument.format} document is opened read-only and cannot be written back`);
220
+ if (openDocument.format === "odb" || openDocument.format === "xlsx" || openDocument.format === "csv" || openDocument.format === "svg") throw new Error(`A ${openDocument.format} document is opened read-only and cannot be written back`);
199
221
  if (openDocument.format === "markdown") {
200
222
  await writeFile(path, encodeMarkdownText(openDocument.editor.toMarkdownText()));
201
223
  return;
@@ -277,7 +299,9 @@ function rootScreenForFormat(format) {
277
299
  case "odg": return { kind: "pageList" };
278
300
  case "odb": return { kind: "odbTableList" };
279
301
  case "pdf":
280
- case "xlsx": return { kind: "pdfPageList" };
302
+ case "xlsx":
303
+ case "csv":
304
+ case "svg": return { kind: "pdfPageList" };
281
305
  }
282
306
  }
283
307
  function currentScreen(state) {
@@ -414,6 +438,18 @@ function documentWithPath(doc, path) {
414
438
  bytes: doc.bytes,
415
439
  path
416
440
  };
441
+ case "csv": return {
442
+ format: "csv",
443
+ layout: doc.layout,
444
+ bytes: doc.bytes,
445
+ path
446
+ };
447
+ case "svg": return {
448
+ format: "svg",
449
+ layout: doc.layout,
450
+ bytes: doc.bytes,
451
+ path
452
+ };
417
453
  }
418
454
  }
419
455
  function reopenEditable(doc, bytes) {
@@ -731,7 +767,7 @@ function appReducer(state, action) {
731
767
  selection: {},
732
768
  errorDetail: void 0,
733
769
  stack: [rootScreenForFormat(action.doc.format)]
734
- }, "info", action.doc.format === "xlsx" ? `Opened ${action.path} as a read-only PDF preview -- press ':' then 'export pdf' to save it as a real PDF` : `Opened ${action.path}`);
770
+ }, "info", action.doc.format === "xlsx" || action.doc.format === "csv" || action.doc.format === "svg" ? `Opened ${action.path} as a read-only PDF preview -- press ':' then 'export pdf' to save it as a real PDF` : `Opened ${action.path}`);
735
771
  case "OPEN_FILE_ERROR": return withStatus({
736
772
  ...state,
737
773
  errorDetail: {
@@ -1317,7 +1353,7 @@ function appReducer(state, action) {
1317
1353
  case "UNDO": {
1318
1354
  const doc = state.openDocument;
1319
1355
  if (doc === void 0) return withStatus(state, "info", "There is nothing to undo");
1320
- if (doc.format === "odb" || doc.format === "xlsx") return withStatus(state, "warning", `A ${doc.format} document is read-only, so it has no history to undo`);
1356
+ if (doc.format === "odb" || doc.format === "xlsx" || doc.format === "csv" || doc.format === "svg") return withStatus(state, "warning", `A ${doc.format} document is read-only, so it has no history to undo`);
1321
1357
  const snapshot = state.undoStack.at(-1);
1322
1358
  if (snapshot === void 0) return withStatus(state, "info", "There is nothing to undo");
1323
1359
  const restored = doc.format === "markdown" ? {
@@ -7149,7 +7185,7 @@ function OdtBodyListScreen() {
7149
7185
  //#endregion
7150
7186
  //#region src/tui/screens/editors/pdf/shared.ts
7151
7187
  function requirePdfDocument(openDocument) {
7152
- if (openDocument?.format !== "pdf" && openDocument?.format !== "xlsx") throw new Error("A PDF inspection screen rendered without an open PDF or xlsx document; the app router only reaches this screen group from pdfPageList, which is only ever the root screen of one of those two formats.");
7188
+ if (openDocument?.format !== "pdf" && openDocument?.format !== "xlsx" && openDocument?.format !== "csv" && openDocument?.format !== "svg") throw new Error("A PDF inspection screen rendered without an open PDF, xlsx, csv, or svg document; the app router only reaches this screen group from pdfPageList, which is only ever the root screen of one of those four formats.");
7153
7189
  return openDocument;
7154
7190
  }
7155
7191
  function isEditablePdfDocument(doc) {
@@ -8712,7 +8748,7 @@ function LauncherScreen() {
8712
8748
  }),
8713
8749
  /* @__PURE__ */ jsx(Text, {
8714
8750
  dimColor: true,
8715
- children: "A terminal editor for docx, pptx, odt, odp, ods, odg, markdown, odb and pdf -- xlsx opens as a read-only PDF preview."
8751
+ children: "A terminal editor for docx, pptx, odt, odp, ods, odg, markdown, odb and pdf -- xlsx, csv and svg open as read-only PDF previews."
8716
8752
  }),
8717
8753
  /* @__PURE__ */ jsx(Text, { children: " " }),
8718
8754
  /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
@@ -8877,7 +8913,9 @@ function metadataFor(doc) {
8877
8913
  case "odg": return readOdgContent(doc.editor.toPackage()).metadata;
8878
8914
  case "markdown": return readMarkdownContent(doc.editor.toMarkdownText()).metadata;
8879
8915
  case "pdf":
8880
- case "xlsx": return doc.layout.metadata;
8916
+ case "xlsx":
8917
+ case "csv":
8918
+ case "svg": return doc.layout.metadata;
8881
8919
  case "odb": throw new Error("A .odb database has no document-level metadata -- it is a table/form/report container, not a single document with its own title/author/etc.");
8882
8920
  }
8883
8921
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "document-cli",
3
- "version": "2.0.0",
4
- "description": "CLI and interactive Ink TUI for documents.js: every docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/markdown conversion, bridge, and editor as a scriptable command or a terminal app.",
3
+ "version": "2.1.0",
4
+ "description": "CLI and interactive Ink TUI for documents.js: every docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown conversion, bridge, and editor as a scriptable command or a terminal app.",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -88,7 +88,7 @@
88
88
  "packageManager": "pnpm@11.6.0",
89
89
  "dependencies": {
90
90
  "commander": "^15.0.0",
91
- "documents.js": "^2.0.0",
91
+ "documents.js": "^2.3.0",
92
92
  "ink": "^7.1.1",
93
93
  "ink-text-input": "^6.0.0",
94
94
  "react": "^19.2.8"