document-cli 5.1.7 → 5.2.1
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
|
[](https://github.com/ExaDev/documents.js/tree/main/packages/document-cli) [](https://www.npmjs.com/package/document-cli) [](https://www.npmjs.com/package/document-cli) [](https://github.com/ExaDev/documents.js/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/csv/svg/markdown conversion, bridge, and editor documents.js exposes, plus the outline projection [`document-outline.js`](../document-outline.js/README.md) builds over any readable document, 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/rtf conversion, bridge, and editor documents.js exposes, plus the outline projection [`document-outline.js`](../document-outline.js/README.md) builds over any readable document, 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
|
|
|
@@ -143,7 +143,7 @@ document-cli pdf-inspect report.pdf
|
|
|
143
143
|
document-cli pdf-inspect report.pdf --json
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
-
**`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:
|
|
146
|
+
**`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, rtf), naming it:
|
|
147
147
|
|
|
148
148
|
```sh
|
|
149
149
|
document-cli fonts report.docx
|
|
@@ -155,7 +155,7 @@ document-cli fonts report.docx
|
|
|
155
155
|
document-cli docx-extras report.docx
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
**`metadata <input>`** — prints a document's own title/author/subject/keywords/creator/producer/created/modified metadata, for any of the
|
|
158
|
+
**`metadata <input>`** — prints a document's own title/author/subject/keywords/creator/producer/created/modified metadata, for any of the thirteen supported formats (docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, rtf, pdf); csv and svg carry no metadata container of their own, so they always report none. `--json` emits the raw metadata object:
|
|
159
159
|
|
|
160
160
|
```sh
|
|
161
161
|
document-cli metadata report.pdf
|
|
@@ -231,7 +231,7 @@ It supports the same seven formats documents.js's live-view editors cover — do
|
|
|
231
231
|
|
|
232
232
|
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.
|
|
233
233
|
|
|
234
|
-
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 `.
|
|
234
|
+
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`, `.svg`, or `.rtf` opens as a converted PDF preview — documents.js has no spreadsheet, svg, or rtf editor to hold a live view into, so opening one runs `xlsxToPdf`, `csvToPdf`, `svgToPdf`, or `rtfToPdf` 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.
|
|
235
235
|
|
|
236
236
|
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.
|
|
237
237
|
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
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-DX5OkaeR.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";
|
|
@@ -139,7 +139,7 @@ function createFilesystemMarkdownImageResolver(baseDir) {
|
|
|
139
139
|
}
|
|
140
140
|
//#endregion
|
|
141
141
|
//#region src/commands/shared.ts
|
|
142
|
-
const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, pdf";
|
|
142
|
+
const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, rtf, pdf";
|
|
143
143
|
function resolveTargetFormat(output, out, to) {
|
|
144
144
|
if (to !== void 0) {
|
|
145
145
|
if (!isDocumentFormat(to)) return { errorMessage: `unknown --to format '${to}'; expected one of ${KNOWN_DOCUMENT_FORMATS}` };
|
|
@@ -1175,8 +1175,8 @@ function registerSetMetadataCommand(program) {
|
|
|
1175
1175
|
const command = program.command("set-metadata <input> [output]").description("patch a document's own title/author/subject/keywords, leaving every other field and every other flag as-is").addHelpText("after", [
|
|
1176
1176
|
"",
|
|
1177
1177
|
"Two write paths: a pdf source/target patches the metadata directly on the parsed PDF (writePdf), with no layout engine",
|
|
1178
|
-
"involved at all -- genuinely lossless for everything else on the page. Every other supported format (docx, pptx,
|
|
1179
|
-
"odp, ods, odg, markdown) rebuilds a fresh package from that format's own ContentDocument -- for docx specifically,",
|
|
1178
|
+
"involved at all -- genuinely lossless for everything else on the page. Every other supported format (docx, pptx, xlsx,",
|
|
1179
|
+
"odt, odp, ods, odg, markdown, rtf) rebuilds a fresh package from that format's own ContentDocument -- for docx specifically,",
|
|
1180
1180
|
"this is LOSSY: it drops anything docx-extras covers (comments, footnotes, headers/footers, numbering definitions),",
|
|
1181
1181
|
"since buildDocxPackage builds a fresh package from the ContentDocument alone, with no way to carry that data through.",
|
|
1182
1182
|
"",
|
|
@@ -1199,12 +1199,12 @@ function registerSetMetadataCommand(program) {
|
|
|
1199
1199
|
}
|
|
1200
1200
|
//#endregion
|
|
1201
1201
|
//#region package.json
|
|
1202
|
-
var version = "5.1
|
|
1202
|
+
var version = "5.2.1";
|
|
1203
1203
|
//#endregion
|
|
1204
1204
|
//#region src/program.ts
|
|
1205
1205
|
function createProgram() {
|
|
1206
1206
|
const program = new Command("document-cli");
|
|
1207
|
-
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");
|
|
1207
|
+
program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown/rtf conversion, bridge, and inspector as a scriptable command");
|
|
1208
1208
|
program.version(version);
|
|
1209
1209
|
program.exitOverride((error) => {
|
|
1210
1210
|
process.exitCode = error.exitCode === 0 ? 0 : 2;
|
|
@@ -1227,7 +1227,7 @@ function createProgram() {
|
|
|
1227
1227
|
//#region src/cli.ts
|
|
1228
1228
|
async function launchTui(startPath, signal) {
|
|
1229
1229
|
try {
|
|
1230
|
-
const { runTui } = await import("./tui-
|
|
1230
|
+
const { runTui } = await import("./tui-BIN_wCkn.js");
|
|
1231
1231
|
await runTui({
|
|
1232
1232
|
startPath,
|
|
1233
1233
|
signal
|
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ const EXTENSION_TO_FORMAT = {
|
|
|
31
31
|
svg: "svg",
|
|
32
32
|
markdown: "markdown",
|
|
33
33
|
md: "markdown",
|
|
34
|
+
rtf: "rtf",
|
|
34
35
|
pdf: "pdf"
|
|
35
36
|
};
|
|
36
37
|
const FORMAT_TO_EXTENSION = {
|
|
@@ -45,6 +46,7 @@ const FORMAT_TO_EXTENSION = {
|
|
|
45
46
|
csv: "csv",
|
|
46
47
|
svg: "svg",
|
|
47
48
|
markdown: "md",
|
|
49
|
+
rtf: "rtf",
|
|
48
50
|
pdf: "pdf"
|
|
49
51
|
};
|
|
50
52
|
function isDocumentFormat(value) {
|
|
@@ -257,7 +259,7 @@ function resolveDefaultOutputPath(inputPath, targetFormat) {
|
|
|
257
259
|
}
|
|
258
260
|
//#endregion
|
|
259
261
|
//#region src/commands/shared.ts
|
|
260
|
-
const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, pdf";
|
|
262
|
+
const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, rtf, pdf";
|
|
261
263
|
function resolveTargetFormat(output, out, to) {
|
|
262
264
|
if (to !== void 0) {
|
|
263
265
|
if (!isDocumentFormat(to)) return { errorMessage: `unknown --to format '${to}'; expected one of ${KNOWN_DOCUMENT_FORMATS}` };
|
|
@@ -1513,8 +1515,8 @@ function registerSetMetadataCommand(program) {
|
|
|
1513
1515
|
const command = program.command("set-metadata <input> [output]").description("patch a document's own title/author/subject/keywords, leaving every other field and every other flag as-is").addHelpText("after", [
|
|
1514
1516
|
"",
|
|
1515
1517
|
"Two write paths: a pdf source/target patches the metadata directly on the parsed PDF (writePdf), with no layout engine",
|
|
1516
|
-
"involved at all -- genuinely lossless for everything else on the page. Every other supported format (docx, pptx,
|
|
1517
|
-
"odp, ods, odg, markdown) rebuilds a fresh package from that format's own ContentDocument -- for docx specifically,",
|
|
1518
|
+
"involved at all -- genuinely lossless for everything else on the page. Every other supported format (docx, pptx, xlsx,",
|
|
1519
|
+
"odt, odp, ods, odg, markdown, rtf) rebuilds a fresh package from that format's own ContentDocument -- for docx specifically,",
|
|
1518
1520
|
"this is LOSSY: it drops anything docx-extras covers (comments, footnotes, headers/footers, numbering definitions),",
|
|
1519
1521
|
"since buildDocxPackage builds a fresh package from the ContentDocument alone, with no way to carry that data through.",
|
|
1520
1522
|
"",
|
|
@@ -1537,12 +1539,12 @@ function registerSetMetadataCommand(program) {
|
|
|
1537
1539
|
}
|
|
1538
1540
|
//#endregion
|
|
1539
1541
|
//#region package.json
|
|
1540
|
-
var version = "5.1
|
|
1542
|
+
var version = "5.2.1";
|
|
1541
1543
|
//#endregion
|
|
1542
1544
|
//#region src/program.ts
|
|
1543
1545
|
function createProgram() {
|
|
1544
1546
|
const program = new commander.Command("document-cli");
|
|
1545
|
-
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");
|
|
1547
|
+
program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown/rtf conversion, bridge, and inspector as a scriptable command");
|
|
1546
1548
|
program.version(version);
|
|
1547
1549
|
program.exitOverride((error) => {
|
|
1548
1550
|
process.exitCode = error.exitCode === 0 ? 0 : 2;
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ const EXTENSION_TO_FORMAT = {
|
|
|
30
30
|
svg: "svg",
|
|
31
31
|
markdown: "markdown",
|
|
32
32
|
md: "markdown",
|
|
33
|
+
rtf: "rtf",
|
|
33
34
|
pdf: "pdf"
|
|
34
35
|
};
|
|
35
36
|
const FORMAT_TO_EXTENSION = {
|
|
@@ -44,6 +45,7 @@ const FORMAT_TO_EXTENSION = {
|
|
|
44
45
|
csv: "csv",
|
|
45
46
|
svg: "svg",
|
|
46
47
|
markdown: "md",
|
|
48
|
+
rtf: "rtf",
|
|
47
49
|
pdf: "pdf"
|
|
48
50
|
};
|
|
49
51
|
function isDocumentFormat(value) {
|
|
@@ -256,7 +258,7 @@ function resolveDefaultOutputPath(inputPath, targetFormat) {
|
|
|
256
258
|
}
|
|
257
259
|
//#endregion
|
|
258
260
|
//#region src/commands/shared.ts
|
|
259
|
-
const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, pdf";
|
|
261
|
+
const KNOWN_DOCUMENT_FORMATS = "docx, pptx, xlsx, odt, odp, ods, odg, svg, odf, csv, markdown, rtf, pdf";
|
|
260
262
|
function resolveTargetFormat(output, out, to) {
|
|
261
263
|
if (to !== void 0) {
|
|
262
264
|
if (!isDocumentFormat(to)) return { errorMessage: `unknown --to format '${to}'; expected one of ${KNOWN_DOCUMENT_FORMATS}` };
|
|
@@ -1512,8 +1514,8 @@ function registerSetMetadataCommand(program) {
|
|
|
1512
1514
|
const command = program.command("set-metadata <input> [output]").description("patch a document's own title/author/subject/keywords, leaving every other field and every other flag as-is").addHelpText("after", [
|
|
1513
1515
|
"",
|
|
1514
1516
|
"Two write paths: a pdf source/target patches the metadata directly on the parsed PDF (writePdf), with no layout engine",
|
|
1515
|
-
"involved at all -- genuinely lossless for everything else on the page. Every other supported format (docx, pptx,
|
|
1516
|
-
"odp, ods, odg, markdown) rebuilds a fresh package from that format's own ContentDocument -- for docx specifically,",
|
|
1517
|
+
"involved at all -- genuinely lossless for everything else on the page. Every other supported format (docx, pptx, xlsx,",
|
|
1518
|
+
"odt, odp, ods, odg, markdown, rtf) rebuilds a fresh package from that format's own ContentDocument -- for docx specifically,",
|
|
1517
1519
|
"this is LOSSY: it drops anything docx-extras covers (comments, footnotes, headers/footers, numbering definitions),",
|
|
1518
1520
|
"since buildDocxPackage builds a fresh package from the ContentDocument alone, with no way to carry that data through.",
|
|
1519
1521
|
"",
|
|
@@ -1536,12 +1538,12 @@ function registerSetMetadataCommand(program) {
|
|
|
1536
1538
|
}
|
|
1537
1539
|
//#endregion
|
|
1538
1540
|
//#region package.json
|
|
1539
|
-
var version = "5.1
|
|
1541
|
+
var version = "5.2.1";
|
|
1540
1542
|
//#endregion
|
|
1541
1543
|
//#region src/program.ts
|
|
1542
1544
|
function createProgram() {
|
|
1543
1545
|
const program = new Command("document-cli");
|
|
1544
|
-
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");
|
|
1546
|
+
program.description("every documents.js docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/csv/svg/markdown/rtf conversion, bridge, and inspector as a scriptable command");
|
|
1545
1547
|
program.version(version);
|
|
1546
1548
|
program.exitOverride((error) => {
|
|
1547
1549
|
process.exitCode = error.exitCode === 0 ? 0 : 2;
|
|
@@ -26,6 +26,7 @@ const EXTENSION_TO_FORMAT = {
|
|
|
26
26
|
svg: "svg",
|
|
27
27
|
markdown: "markdown",
|
|
28
28
|
md: "markdown",
|
|
29
|
+
rtf: "rtf",
|
|
29
30
|
pdf: "pdf"
|
|
30
31
|
};
|
|
31
32
|
const FORMAT_TO_EXTENSION = {
|
|
@@ -40,6 +41,7 @@ const FORMAT_TO_EXTENSION = {
|
|
|
40
41
|
csv: "csv",
|
|
41
42
|
svg: "svg",
|
|
42
43
|
markdown: "md",
|
|
44
|
+
rtf: "rtf",
|
|
43
45
|
pdf: "pdf"
|
|
44
46
|
};
|
|
45
47
|
function isDocumentFormat(value) {
|
|
@@ -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-
|
|
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-DX5OkaeR.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, 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";
|
|
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, rtfToPdf, 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";
|
|
@@ -57,6 +57,11 @@ async function exportToPdf(openDocument, destinationPath, options) {
|
|
|
57
57
|
await writeFile(destinationPath, pdfBytes);
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
|
+
if (openDocument.format === "rtf") {
|
|
61
|
+
const pdfBytes = rtfToPdf(openDocument.bytes, pdfOptions);
|
|
62
|
+
await writeFile(destinationPath, pdfBytes);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
60
65
|
const bytes = openDocument.editor.toBytes();
|
|
61
66
|
const pdfBytes = convert(openDocument.format, bytes, pdfOptions);
|
|
62
67
|
await writeFile(destinationPath, pdfBytes);
|
|
@@ -170,6 +175,12 @@ async function openDocumentAtPath(path, options = {}) {
|
|
|
170
175
|
bytes,
|
|
171
176
|
path
|
|
172
177
|
};
|
|
178
|
+
case "rtf": return {
|
|
179
|
+
format,
|
|
180
|
+
layout: readPdf(rtfToPdf(bytes)),
|
|
181
|
+
bytes,
|
|
182
|
+
path
|
|
183
|
+
};
|
|
173
184
|
case "odf": throw new Error("A standalone .odf formula document has no editor; convert it to PDF (odfToPdf) instead");
|
|
174
185
|
}
|
|
175
186
|
}
|
|
@@ -217,7 +228,7 @@ function createNewDocument(format) {
|
|
|
217
228
|
}
|
|
218
229
|
}
|
|
219
230
|
async function saveDocumentTo(openDocument, path) {
|
|
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`);
|
|
231
|
+
if (openDocument.format === "odb" || openDocument.format === "xlsx" || openDocument.format === "csv" || openDocument.format === "svg" || openDocument.format === "rtf") throw new Error(`A ${openDocument.format} document is opened read-only and cannot be written back`);
|
|
221
232
|
if (openDocument.format === "markdown") {
|
|
222
233
|
await writeFile(path, encodeMarkdownText(openDocument.editor.toMarkdownText()));
|
|
223
234
|
return;
|
|
@@ -301,7 +312,8 @@ function rootScreenForFormat(format) {
|
|
|
301
312
|
case "pdf":
|
|
302
313
|
case "xlsx":
|
|
303
314
|
case "csv":
|
|
304
|
-
case "svg":
|
|
315
|
+
case "svg":
|
|
316
|
+
case "rtf": return { kind: "pdfPageList" };
|
|
305
317
|
}
|
|
306
318
|
}
|
|
307
319
|
function currentScreen(state) {
|
|
@@ -450,6 +462,12 @@ function documentWithPath(doc, path) {
|
|
|
450
462
|
bytes: doc.bytes,
|
|
451
463
|
path
|
|
452
464
|
};
|
|
465
|
+
case "rtf": return {
|
|
466
|
+
format: "rtf",
|
|
467
|
+
layout: doc.layout,
|
|
468
|
+
bytes: doc.bytes,
|
|
469
|
+
path
|
|
470
|
+
};
|
|
453
471
|
}
|
|
454
472
|
}
|
|
455
473
|
function reopenEditable(doc, bytes) {
|
|
@@ -768,7 +786,7 @@ function appReducer(state, action) {
|
|
|
768
786
|
selection: {},
|
|
769
787
|
errorDetail: void 0,
|
|
770
788
|
stack: [rootScreenForFormat(action.doc.format)]
|
|
771
|
-
}, "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}`);
|
|
789
|
+
}, "info", action.doc.format === "xlsx" || action.doc.format === "csv" || action.doc.format === "svg" || action.doc.format === "rtf" ? `Opened ${action.path} as a read-only PDF preview -- press ':' then 'export pdf' to save it as a real PDF` : `Opened ${action.path}`);
|
|
772
790
|
case "OPEN_FILE_ERROR": return withStatus({
|
|
773
791
|
...state,
|
|
774
792
|
errorDetail: {
|
|
@@ -1363,7 +1381,7 @@ function appReducer(state, action) {
|
|
|
1363
1381
|
case "UNDO": {
|
|
1364
1382
|
const doc = state.openDocument;
|
|
1365
1383
|
if (doc === void 0) return withStatus(state, "info", "There is nothing to undo");
|
|
1366
|
-
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`);
|
|
1384
|
+
if (doc.format === "odb" || doc.format === "xlsx" || doc.format === "csv" || doc.format === "svg" || doc.format === "rtf") return withStatus(state, "warning", `A ${doc.format} document is read-only, so it has no history to undo`);
|
|
1367
1385
|
const snapshot = state.undoStack.at(-1);
|
|
1368
1386
|
if (snapshot === void 0) return withStatus(state, "info", "There is nothing to undo");
|
|
1369
1387
|
const restored = doc.format === "markdown" ? {
|
|
@@ -7207,7 +7225,7 @@ function OdtBodyListScreen() {
|
|
|
7207
7225
|
//#endregion
|
|
7208
7226
|
//#region src/tui/screens/editors/pdf/shared.ts
|
|
7209
7227
|
function requirePdfDocument(openDocument) {
|
|
7210
|
-
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
|
|
7228
|
+
if (openDocument?.format !== "pdf" && openDocument?.format !== "xlsx" && openDocument?.format !== "csv" && openDocument?.format !== "svg" && openDocument?.format !== "rtf") throw new Error("A PDF inspection screen rendered without an open PDF, xlsx, csv, svg, or rtf document; the app router only reaches this screen group from pdfPageList, which is only ever the root screen of one of those five formats.");
|
|
7211
7229
|
return openDocument;
|
|
7212
7230
|
}
|
|
7213
7231
|
function isEditablePdfDocument(doc) {
|
|
@@ -8871,7 +8889,7 @@ function LauncherScreen() {
|
|
|
8871
8889
|
}),
|
|
8872
8890
|
/* @__PURE__ */ jsx(Text, {
|
|
8873
8891
|
dimColor: true,
|
|
8874
|
-
children: "A terminal editor for docx, pptx, odt, odp, ods, odg, markdown, odb and pdf -- xlsx, csv and
|
|
8892
|
+
children: "A terminal editor for docx, pptx, odt, odp, ods, odg, markdown, odb and pdf -- xlsx, csv, svg and rtf open as read-only PDF previews."
|
|
8875
8893
|
}),
|
|
8876
8894
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
8877
8895
|
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
@@ -9038,7 +9056,8 @@ function metadataFor(doc) {
|
|
|
9038
9056
|
case "pdf":
|
|
9039
9057
|
case "xlsx":
|
|
9040
9058
|
case "csv":
|
|
9041
|
-
case "svg":
|
|
9059
|
+
case "svg":
|
|
9060
|
+
case "rtf": return doc.layout.metadata;
|
|
9042
9061
|
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.");
|
|
9043
9062
|
}
|
|
9044
9063
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-cli",
|
|
3
|
-
"version": "5.1
|
|
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.",
|
|
3
|
+
"version": "5.2.1",
|
|
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/rtf conversion, bridge, and editor as a scriptable command or a terminal app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"commander": "^15.0.0",
|
|
93
93
|
"document-outline.js": "^3.2.1",
|
|
94
94
|
"document-schema.js": "^5.4.0",
|
|
95
|
-
"documents.js": "^6.
|
|
95
|
+
"documents.js": "^6.3.1",
|
|
96
96
|
"ink": "^7.1.1",
|
|
97
97
|
"ink-text-input": "^6.0.0",
|
|
98
98
|
"react": "^19.2.8"
|