document-cli 5.11.51 → 5.11.52

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
@@ -277,8 +277,8 @@ pnpm typecheck # turbo run _typecheck -> tsc --noEmit
277
277
  pnpm lint # turbo run _lint -> eslint . --fix --cache --max-warnings 0
278
278
  pnpm test # turbo run _test -> vitest run --project unit
279
279
  pnpm test:watch # vitest --project unit
280
- pnpm test:smoke # turbo run _test:smoke -> tsdown, then vitest run --project smoke -- spawns the built dist/cli.js as a real child process
281
- pnpm test:workers # turbo run _test:workers -> vitest run --config vitest.workers.config.ts -- runs the thin isomorphic slice (src/sql-result-format.ts, src/runtime/exit-codes.ts) under the real Cloudflare Workers runtime (workerd), proving the wrapped documents.js paths execute inside a workerd isolate with no Node-only API usage
280
+ pnpm test:smoke # turbo run _test:smoke -> tsdown, then vitest run --project smoke — spawns the built dist/cli.js as a real child process
281
+ pnpm test:workers # turbo run _test:workers -> vitest run --config vitest.workers.config.ts — runs the thin isomorphic slice (src/sql-result-format.ts, src/runtime/exit-codes.ts) under the real Cloudflare Workers runtime (workerd), proving the wrapped documents.js paths execute inside a workerd isolate with no Node-only API usage
282
282
  ```
283
283
 
284
284
  ## Gotchas
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as odbFormSummary, c as presentMetadataEntries, d as resolveDefaultOutputPath, f as writeOutput, g as isDocumentFormat, h as inferFormatFromExtension, i as formatOdbReportLines, l as formatDocxExtrasLines, n as describeOdbReport, o as formatMetadataLines, p as loadProvidedFonts, r as formatOdbFormLines, t as describeOdbForm, u as readInput } from "./odb-structure-yc8OHoC0.js";
2
+ import { a as odbFormSummary, c as presentMetadataEntries, d as resolveDefaultOutputPath, f as writeOutput, g as isDocumentFormat, h as inferFormatFromExtension, i as formatOdbReportLines, l as formatDocxExtrasLines, n as describeOdbReport, o as formatMetadataLines, p as loadProvidedFonts, r as formatOdbFormLines, t as describeOdbForm, u as readInput } from "./odb-structure-Crz3Yzzb.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";
@@ -142,7 +142,7 @@ function resolveTargetFormat(output, out, to) {
142
142
  return { format: to };
143
143
  }
144
144
  const destination = output ?? out;
145
- if (destination === void 0) return { errorMessage: "cannot infer a target format -- pass an output path with a recognised extension, --out with one, or --to <format>" };
145
+ if (destination === void 0) return { errorMessage: "cannot infer a target format — pass an output path with a recognised extension, --out with one, or --to <format>" };
146
146
  const inferred = inferFormatFromExtension(destination);
147
147
  if (inferred === void 0) return { errorMessage: `cannot infer a target format from '${destination}'; pass --to <format> instead` };
148
148
  return { format: inferred };
@@ -275,11 +275,11 @@ function toConversionCommandOptions(options) {
275
275
  async function runGenericConvert(input, output, options) {
276
276
  const extension = extname(input).toLowerCase();
277
277
  if (extension === ".odm") {
278
- process.stderr.write("convert: '.odm' master documents are not supported by the generic convert command -- use 'odm-to-pdf' instead\n");
278
+ process.stderr.write("convert: '.odm' master documents are not supported by the generic convert command — use 'odm-to-pdf' instead\n");
279
279
  return 2;
280
280
  }
281
281
  if (extension === ".odb") {
282
- process.stderr.write("convert: '.odb' embedded databases are not supported by the generic convert command -- use 'odb-to-csv', 'odb-to-xlsx', or 'odb-tables' instead\n");
282
+ process.stderr.write("convert: '.odb' embedded databases are not supported by the generic convert command — use 'odb-to-csv', 'odb-to-xlsx', or 'odb-tables' instead\n");
283
283
  return 2;
284
284
  }
285
285
  const source = inferFormatFromExtension(input);
@@ -342,7 +342,7 @@ async function runDocxExtras(input, options) {
342
342
  }
343
343
  }
344
344
  function registerDocxExtrasCommand(program) {
345
- program.command("docx-extras <input>").description("print a docx's own comments, footnotes, headers, footers, and numbering definitions -- data readDocxContent's ContentDocument cannot carry").option("--json", "emit the raw DocxExtras object as JSON instead of a human-readable report", false).action(async (input, options) => {
345
+ program.command("docx-extras <input>").description("print a docx's own comments, footnotes, headers, footers, and numbering definitions — data readDocxContent's ContentDocument cannot carry").option("--json", "emit the raw DocxExtras object as JSON instead of a human-readable report", false).action(async (input, options) => {
346
346
  process.exitCode = await runDocxExtras(input, options);
347
347
  });
348
348
  }
@@ -374,7 +374,7 @@ async function runFonts(input, options) {
374
374
  }
375
375
  for (const face of summaries) {
376
376
  const style = [face.bold ? "bold" : void 0, face.italic ? "italic" : void 0].filter((value) => value !== void 0).join(" ");
377
- process.stdout.write(`${face.family}${style === "" ? "" : ` (${style})`} -- ${face.byteLength} bytes\n`);
377
+ process.stdout.write(`${face.family}${style === "" ? "" : ` (${style})`} — ${face.byteLength} bytes\n`);
378
378
  }
379
379
  return 0;
380
380
  } catch (error) {
@@ -439,7 +439,7 @@ async function runFromPackage(input, output, options) {
439
439
  }
440
440
  const result = documentFromJson(parsed);
441
441
  if (result.kind !== "DocumentTree") {
442
- process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentTree -- only a file written by --dump-package can be read back by this command\n`);
442
+ process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentTree — only a file written by --dump-package can be read back by this command\n`);
443
443
  return 2;
444
444
  }
445
445
  const content = flattenTree(result.value);
@@ -460,19 +460,19 @@ async function runFromPackage(input, output, options) {
460
460
  return 0;
461
461
  } catch (error) {
462
462
  if (error instanceof UnrecognizedDocumentSchemaError) {
463
- process.stderr.write(`[${command}] '${input}' has no recognised $schema -- only a file written by --dump-package can be read back by this command\n`);
463
+ process.stderr.write(`[${command}] '${input}' has no recognised $schema — only a file written by --dump-package can be read back by this command\n`);
464
464
  return 1;
465
465
  }
466
466
  if (isSchemaVersionMismatchError(error)) {
467
- process.stderr.write(`[${command}] '${input}' is a DocumentTree dump from document-schema.js@${error.dumpVersion}, but this CLI's documents.js reads only @${error.installedVersion}-major dumps -- 4.0.0 replaced the flat { formatVersion, content, pages } shape with the tree-form DocumentTree (ExaDev/document-schema.js#20); re-run the source conversion with --dump-package to write a current dump\n`);
467
+ process.stderr.write(`[${command}] '${input}' is a DocumentTree dump from document-schema.js@${error.dumpVersion}, but this CLI's documents.js reads only @${error.installedVersion}-major dumps — 4.0.0 replaced the flat { formatVersion, content, pages } shape with the tree-form DocumentTree (ExaDev/document-schema.js#20); re-run the source conversion with --dump-package to write a current dump\n`);
468
468
  return 1;
469
469
  }
470
470
  if (isLayoutSchemaDemotedError(error)) {
471
- process.stderr.write(`[${command}] '${input}' is a LayoutDocument dump -- LayoutDocument moved to pdf-codec in document-schema.js 4.0.0 and is no longer a schema-stamped input; re-run the source conversion with --dump-package and read that package back instead\n`);
471
+ process.stderr.write(`[${command}] '${input}' is a LayoutDocument dump — LayoutDocument moved to pdf-codec in document-schema.js 4.0.0 and is no longer a schema-stamped input; re-run the source conversion with --dump-package and read that package back instead\n`);
472
472
  return 1;
473
473
  }
474
474
  if (isDocumentPackageRenamedError(error)) {
475
- process.stderr.write(`[${command}] '${input}' is a document-package dump -- DocumentPackage was renamed to DocumentTree in document-schema.js 5.0.0 (ExaDev/documents.js#661); re-run the source conversion with --dump-package to write a current tree-form DocumentTree dump\n`);
475
+ process.stderr.write(`[${command}] '${input}' is a document-package dump — DocumentPackage was renamed to DocumentTree in document-schema.js 5.0.0 (ExaDev/documents.js#661); re-run the source conversion with --dump-package to write a current tree-form DocumentTree dump\n`);
476
476
  return 1;
477
477
  }
478
478
  process.stderr.write(`${formatError(error, options.verbose)}\n`);
@@ -666,7 +666,7 @@ function resolveQuerySql(pkg, options) {
666
666
  const saved = inventory.queries.find((candidate) => candidate.name === queryName);
667
667
  if (saved === void 0) {
668
668
  const available = inventory.queries.map((candidate) => candidate.name);
669
- return { errorMessage: `this .odb declares no saved query named '${queryName}'${available.length === 0 ? "" : ` -- available: ${available.join(", ")}`}` };
669
+ return { errorMessage: `this .odb declares no saved query named '${queryName}'${available.length === 0 ? "" : ` — available: ${available.join(", ")}`}` };
670
670
  }
671
671
  return { sql: saved.command };
672
672
  }
@@ -833,7 +833,7 @@ function registerOdbToCsvCommand(program) {
833
833
  addJsonOption(command);
834
834
  addQuietOption(command);
835
835
  addVerboseOption(command);
836
- command.option("--table <name>", "the table to export -- required when the .odb declares more than one table");
836
+ command.option("--table <name>", "the table to export — required when the .odb declares more than one table");
837
837
  command.action(async (input, output, options) => {
838
838
  process.exitCode = await runOdbToCsv(input, output, options);
839
839
  });
@@ -854,19 +854,19 @@ function registerOdbReportsCommand(program) {
854
854
  });
855
855
  }
856
856
  function registerOdbQueryCommand(program) {
857
- program.command("odb-query <input>").description("run a bounded SELECT over an embedded .odb database's own extracted tables, given directly or by naming one of its saved queries").option("--sql <text>", "the SELECT statement to run -- mutually exclusive with --query").option("--query <savedName>", "the name of one of the .odb's own saved queries to run -- mutually exclusive with --sql").option("--json", "emit the result set as JSON ({ columns, rows }) instead of a plain-text table", false).action(async (input, options) => {
857
+ program.command("odb-query <input>").description("run a bounded SELECT over an embedded .odb database's own extracted tables, given directly or by naming one of its saved queries").option("--sql <text>", "the SELECT statement to run — mutually exclusive with --query").option("--query <savedName>", "the name of one of the .odb's own saved queries to run — mutually exclusive with --sql").option("--json", "emit the result set as JSON ({ columns, rows }) instead of a plain-text table", false).action(async (input, options) => {
858
858
  process.exitCode = await runOdbQuery(input, options);
859
859
  });
860
860
  }
861
861
  function registerOdbRenderReportCommand(program) {
862
- const command = program.command("odb-render-report <input> [output]").description("render one of an .odb's own reports -- its query resolved, its rpt: formulas evaluated, its bands laid out -- to docx, odt, or pdf");
862
+ const command = program.command("odb-render-report <input> [output]").description("render one of an .odb's own reports — its query resolved, its rpt: formulas evaluated, its bands laid out — to docx, odt, or pdf");
863
863
  addOutOption(command);
864
864
  addTimeoutOption(command);
865
865
  addJsonOption(command);
866
866
  addQuietOption(command);
867
867
  addVerboseOption(command);
868
868
  addFontOptions(command);
869
- command.option("--report <name>", "the report to render -- required only when the .odb declares more than one report");
869
+ command.option("--report <name>", "the report to render — required only when the .odb declares more than one report");
870
870
  command.option("--to <format>", "target format when it cannot be inferred from the output path (docx, odt, pdf)");
871
871
  command.action(async (input, output, options) => {
872
872
  process.exitCode = await runOdbRenderReport(input, output, options);
@@ -1037,7 +1037,7 @@ async function runOutline(input, options) {
1037
1037
  }
1038
1038
  }
1039
1039
  function registerOutlineCommand(program) {
1040
- const command = program.command("outline <input>").description(`print a document's outline -- headings, list items, and slide/sheet/page groups as indented text (${KNOWN_DOCUMENT_FORMATS})`);
1040
+ const command = program.command("outline <input>").description(`print a document's outline — headings, list items, and slide/sheet/page groups as indented text (${KNOWN_DOCUMENT_FORMATS})`);
1041
1041
  addTimeoutOption(command);
1042
1042
  command.option("--json", "emit the outline tree as JSON instead of indented text (diagnostics as NDJSON on stderr)", false);
1043
1043
  addQuietOption(command);
@@ -1171,12 +1171,12 @@ function registerSetMetadataCommand(program) {
1171
1171
  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", [
1172
1172
  "",
1173
1173
  "Three write paths: a pdf source/target patches the metadata directly on the parsed PDF (writePdf), and a docx source/target",
1174
- "patches docProps/core.xml directly on the decoded package -- both with no layout engine or ContentDocument rebuild involved",
1175
- "at all, so everything else on the page (pdf) or in the package (docx -- comments, footnotes, headers/footers, numbering",
1174
+ "patches docProps/core.xml directly on the decoded package — both with no layout engine or ContentDocument rebuild involved",
1175
+ "at all, so everything else on the page (pdf) or in the package (docx — comments, footnotes, headers/footers, numbering",
1176
1176
  "definitions included) survives byte-faithful. Every other supported format (pptx, xlsx, odt, odp, ods, odg, markdown, rtf)",
1177
1177
  "rebuilds a fresh package from that format's own ContentDocument instead.",
1178
1178
  "",
1179
- "set-metadata does not convert format -- source and target must match. Run convert/from-package first, then",
1179
+ "set-metadata does not convert format — source and target must match. Run convert/from-package first, then",
1180
1180
  "set-metadata on the result, if you need a different target format."
1181
1181
  ].join("\n"));
1182
1182
  addOutOption(command);
@@ -1195,7 +1195,7 @@ function registerSetMetadataCommand(program) {
1195
1195
  }
1196
1196
  //#endregion
1197
1197
  //#region package.json
1198
- var version = "5.11.51";
1198
+ var version = "5.11.52";
1199
1199
  //#endregion
1200
1200
  //#region src/program.ts
1201
1201
  function createProgram() {
@@ -1223,7 +1223,7 @@ function createProgram() {
1223
1223
  //#region src/cli-main.ts
1224
1224
  async function launchTui(startPath, signal) {
1225
1225
  try {
1226
- const { runTui } = await import("./tui-CogHEvyJ.js");
1226
+ const { runTui } = await import("./tui-y8MLtP8W.js");
1227
1227
  await runTui({
1228
1228
  startPath,
1229
1229
  signal
@@ -1238,7 +1238,7 @@ function findStartPath(args) {
1238
1238
  return args.find((arg) => !arg.startsWith("-"));
1239
1239
  }
1240
1240
  /**
1241
- * The real, full-featured CLI entry logic -- `src/cli.ts` (the published npm `bin`, run under a real Node.js install) awaits this at its own top level. The SEA build (`src/sea-entry.ts`) does NOT use this function; it uses `src/cli-main-sea.ts`'s own TUI-free equivalent instead, so that Ink's module graph is never reachable from the SEA bundle's own entry at all -- see this file's own top comment.
1241
+ * The real, full-featured CLI entry logic — `src/cli.ts` (the published npm `bin`, run under a real Node.js install) awaits this at its own top level. The SEA build (`src/sea-entry.ts`) does NOT use this function; it uses `src/cli-main-sea.ts`'s own TUI-free equivalent instead, so that Ink's module graph is never reachable from the SEA bundle's own entry at all — see this file's own top comment.
1242
1242
  */
1243
1243
  async function main() {
1244
1244
  const { signal } = createRuntimeSignal({});
package/dist/index.cjs CHANGED
@@ -273,7 +273,7 @@ function resolveTargetFormat(output, out, to) {
273
273
  return { format: to };
274
274
  }
275
275
  const destination = output ?? out;
276
- if (destination === void 0) return { errorMessage: "cannot infer a target format -- pass an output path with a recognised extension, --out with one, or --to <format>" };
276
+ if (destination === void 0) return { errorMessage: "cannot infer a target format — pass an output path with a recognised extension, --out with one, or --to <format>" };
277
277
  const inferred = inferFormatFromExtension(destination);
278
278
  if (inferred === void 0) return { errorMessage: `cannot infer a target format from '${destination}'; pass --to <format> instead` };
279
279
  return { format: inferred };
@@ -406,11 +406,11 @@ function toConversionCommandOptions(options) {
406
406
  async function runGenericConvert(input, output, options) {
407
407
  const extension = (0, node_path.extname)(input).toLowerCase();
408
408
  if (extension === ".odm") {
409
- process.stderr.write("convert: '.odm' master documents are not supported by the generic convert command -- use 'odm-to-pdf' instead\n");
409
+ process.stderr.write("convert: '.odm' master documents are not supported by the generic convert command — use 'odm-to-pdf' instead\n");
410
410
  return 2;
411
411
  }
412
412
  if (extension === ".odb") {
413
- process.stderr.write("convert: '.odb' embedded databases are not supported by the generic convert command -- use 'odb-to-csv', 'odb-to-xlsx', or 'odb-tables' instead\n");
413
+ process.stderr.write("convert: '.odb' embedded databases are not supported by the generic convert command — use 'odb-to-csv', 'odb-to-xlsx', or 'odb-tables' instead\n");
414
414
  return 2;
415
415
  }
416
416
  const source = inferFormatFromExtension(input);
@@ -537,7 +537,7 @@ async function runDocxExtras(input, options) {
537
537
  }
538
538
  }
539
539
  function registerDocxExtrasCommand(program) {
540
- program.command("docx-extras <input>").description("print a docx's own comments, footnotes, headers, footers, and numbering definitions -- data readDocxContent's ContentDocument cannot carry").option("--json", "emit the raw DocxExtras object as JSON instead of a human-readable report", false).action(async (input, options) => {
540
+ program.command("docx-extras <input>").description("print a docx's own comments, footnotes, headers, footers, and numbering definitions — data readDocxContent's ContentDocument cannot carry").option("--json", "emit the raw DocxExtras object as JSON instead of a human-readable report", false).action(async (input, options) => {
541
541
  process.exitCode = await runDocxExtras(input, options);
542
542
  });
543
543
  }
@@ -569,7 +569,7 @@ async function runFonts(input, options) {
569
569
  }
570
570
  for (const face of summaries) {
571
571
  const style = [face.bold ? "bold" : void 0, face.italic ? "italic" : void 0].filter((value) => value !== void 0).join(" ");
572
- process.stdout.write(`${face.family}${style === "" ? "" : ` (${style})`} -- ${face.byteLength} bytes\n`);
572
+ process.stdout.write(`${face.family}${style === "" ? "" : ` (${style})`} — ${face.byteLength} bytes\n`);
573
573
  }
574
574
  return 0;
575
575
  } catch (error) {
@@ -634,7 +634,7 @@ async function runFromPackage(input, output, options) {
634
634
  }
635
635
  const result = (0, documents_js.documentFromJson)(parsed);
636
636
  if (result.kind !== "DocumentTree") {
637
- process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentTree -- only a file written by --dump-package can be read back by this command\n`);
637
+ process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentTree — only a file written by --dump-package can be read back by this command\n`);
638
638
  return 2;
639
639
  }
640
640
  const content = (0, document_schema_js.flattenTree)(result.value);
@@ -655,19 +655,19 @@ async function runFromPackage(input, output, options) {
655
655
  return 0;
656
656
  } catch (error) {
657
657
  if (error instanceof documents_js.UnrecognizedDocumentSchemaError) {
658
- process.stderr.write(`[${command}] '${input}' has no recognised $schema -- only a file written by --dump-package can be read back by this command\n`);
658
+ process.stderr.write(`[${command}] '${input}' has no recognised $schema — only a file written by --dump-package can be read back by this command\n`);
659
659
  return 1;
660
660
  }
661
661
  if (isSchemaVersionMismatchError(error)) {
662
- process.stderr.write(`[${command}] '${input}' is a DocumentTree dump from document-schema.js@${error.dumpVersion}, but this CLI's documents.js reads only @${error.installedVersion}-major dumps -- 4.0.0 replaced the flat { formatVersion, content, pages } shape with the tree-form DocumentTree (ExaDev/document-schema.js#20); re-run the source conversion with --dump-package to write a current dump\n`);
662
+ process.stderr.write(`[${command}] '${input}' is a DocumentTree dump from document-schema.js@${error.dumpVersion}, but this CLI's documents.js reads only @${error.installedVersion}-major dumps — 4.0.0 replaced the flat { formatVersion, content, pages } shape with the tree-form DocumentTree (ExaDev/document-schema.js#20); re-run the source conversion with --dump-package to write a current dump\n`);
663
663
  return 1;
664
664
  }
665
665
  if (isLayoutSchemaDemotedError(error)) {
666
- process.stderr.write(`[${command}] '${input}' is a LayoutDocument dump -- LayoutDocument moved to pdf-codec in document-schema.js 4.0.0 and is no longer a schema-stamped input; re-run the source conversion with --dump-package and read that package back instead\n`);
666
+ process.stderr.write(`[${command}] '${input}' is a LayoutDocument dump — LayoutDocument moved to pdf-codec in document-schema.js 4.0.0 and is no longer a schema-stamped input; re-run the source conversion with --dump-package and read that package back instead\n`);
667
667
  return 1;
668
668
  }
669
669
  if (isDocumentPackageRenamedError(error)) {
670
- process.stderr.write(`[${command}] '${input}' is a document-package dump -- DocumentPackage was renamed to DocumentTree in document-schema.js 5.0.0 (ExaDev/documents.js#661); re-run the source conversion with --dump-package to write a current tree-form DocumentTree dump\n`);
670
+ process.stderr.write(`[${command}] '${input}' is a document-package dump — DocumentPackage was renamed to DocumentTree in document-schema.js 5.0.0 (ExaDev/documents.js#661); re-run the source conversion with --dump-package to write a current tree-form DocumentTree dump\n`);
671
671
  return 1;
672
672
  }
673
673
  process.stderr.write(`${formatError(error, options.verbose)}\n`);
@@ -775,7 +775,7 @@ function countOdbFormDefinitionBoundControls(definition) {
775
775
  function describeOdbForm(form) {
776
776
  const controlCount = form.forms.reduce((total, definition) => total + countOdbFormDefinitionControls(definition), 0);
777
777
  const boundCount = form.forms.reduce((total, definition) => total + countOdbFormDefinitionBoundControls(definition), 0);
778
- return `${form.name} [${form.href}] -- ${form.forms.length} form${form.forms.length === 1 ? "" : "s"}, ${controlCount} control${controlCount === 1 ? "" : "s"} (${boundCount} bound)`;
778
+ return `${form.name} [${form.href}] — ${form.forms.length} form${form.forms.length === 1 ? "" : "s"}, ${controlCount} control${controlCount === 1 ? "" : "s"} (${boundCount} bound)`;
779
779
  }
780
780
  function formControlLines(control, depth) {
781
781
  const parts = [control.tag];
@@ -825,7 +825,7 @@ function describeOdbReport(report) {
825
825
  const groupCount = countReportGroups(report.groups);
826
826
  const elementCount = countReportBandElements(report.reportHeader) + countReportBandElements(report.pageHeader) + countReportBandElements(report.detail) + countReportBandElements(report.pageFooter) + countReportBandElements(report.reportFooter) + report.groups.reduce((total, group) => total + countReportGroupElements(group), 0);
827
827
  const source = dataSource === void 0 ? "no data source" : `on ${dataSource}`;
828
- return `${report.name} [${report.href}] -- ${source}, ${groupCount} group${groupCount === 1 ? "" : "s"}, ${elementCount} element${elementCount === 1 ? "" : "s"}`;
828
+ return `${report.name} [${report.href}] — ${source}, ${groupCount} group${groupCount === 1 ? "" : "s"}, ${elementCount} element${elementCount === 1 ? "" : "s"}`;
829
829
  }
830
830
  function reportElementLine(element, depth) {
831
831
  const parts = [element.tag];
@@ -1017,7 +1017,7 @@ function resolveQuerySql(pkg, options) {
1017
1017
  const saved = inventory.queries.find((candidate) => candidate.name === queryName);
1018
1018
  if (saved === void 0) {
1019
1019
  const available = inventory.queries.map((candidate) => candidate.name);
1020
- return { errorMessage: `this .odb declares no saved query named '${queryName}'${available.length === 0 ? "" : ` -- available: ${available.join(", ")}`}` };
1020
+ return { errorMessage: `this .odb declares no saved query named '${queryName}'${available.length === 0 ? "" : ` — available: ${available.join(", ")}`}` };
1021
1021
  }
1022
1022
  return { sql: saved.command };
1023
1023
  }
@@ -1184,7 +1184,7 @@ function registerOdbToCsvCommand(program) {
1184
1184
  addJsonOption(command);
1185
1185
  addQuietOption(command);
1186
1186
  addVerboseOption(command);
1187
- command.option("--table <name>", "the table to export -- required when the .odb declares more than one table");
1187
+ command.option("--table <name>", "the table to export — required when the .odb declares more than one table");
1188
1188
  command.action(async (input, output, options) => {
1189
1189
  process.exitCode = await runOdbToCsv(input, output, options);
1190
1190
  });
@@ -1205,19 +1205,19 @@ function registerOdbReportsCommand(program) {
1205
1205
  });
1206
1206
  }
1207
1207
  function registerOdbQueryCommand(program) {
1208
- program.command("odb-query <input>").description("run a bounded SELECT over an embedded .odb database's own extracted tables, given directly or by naming one of its saved queries").option("--sql <text>", "the SELECT statement to run -- mutually exclusive with --query").option("--query <savedName>", "the name of one of the .odb's own saved queries to run -- mutually exclusive with --sql").option("--json", "emit the result set as JSON ({ columns, rows }) instead of a plain-text table", false).action(async (input, options) => {
1208
+ program.command("odb-query <input>").description("run a bounded SELECT over an embedded .odb database's own extracted tables, given directly or by naming one of its saved queries").option("--sql <text>", "the SELECT statement to run — mutually exclusive with --query").option("--query <savedName>", "the name of one of the .odb's own saved queries to run — mutually exclusive with --sql").option("--json", "emit the result set as JSON ({ columns, rows }) instead of a plain-text table", false).action(async (input, options) => {
1209
1209
  process.exitCode = await runOdbQuery(input, options);
1210
1210
  });
1211
1211
  }
1212
1212
  function registerOdbRenderReportCommand(program) {
1213
- const command = program.command("odb-render-report <input> [output]").description("render one of an .odb's own reports -- its query resolved, its rpt: formulas evaluated, its bands laid out -- to docx, odt, or pdf");
1213
+ const command = program.command("odb-render-report <input> [output]").description("render one of an .odb's own reports — its query resolved, its rpt: formulas evaluated, its bands laid out — to docx, odt, or pdf");
1214
1214
  addOutOption(command);
1215
1215
  addTimeoutOption(command);
1216
1216
  addJsonOption(command);
1217
1217
  addQuietOption(command);
1218
1218
  addVerboseOption(command);
1219
1219
  addFontOptions(command);
1220
- command.option("--report <name>", "the report to render -- required only when the .odb declares more than one report");
1220
+ command.option("--report <name>", "the report to render — required only when the .odb declares more than one report");
1221
1221
  command.option("--to <format>", "target format when it cannot be inferred from the output path (docx, odt, pdf)");
1222
1222
  command.action(async (input, output, options) => {
1223
1223
  process.exitCode = await runOdbRenderReport(input, output, options);
@@ -1388,7 +1388,7 @@ async function runOutline(input, options) {
1388
1388
  }
1389
1389
  }
1390
1390
  function registerOutlineCommand(program) {
1391
- const command = program.command("outline <input>").description(`print a document's outline -- headings, list items, and slide/sheet/page groups as indented text (${KNOWN_DOCUMENT_FORMATS})`);
1391
+ const command = program.command("outline <input>").description(`print a document's outline — headings, list items, and slide/sheet/page groups as indented text (${KNOWN_DOCUMENT_FORMATS})`);
1392
1392
  addTimeoutOption(command);
1393
1393
  command.option("--json", "emit the outline tree as JSON instead of indented text (diagnostics as NDJSON on stderr)", false);
1394
1394
  addQuietOption(command);
@@ -1522,12 +1522,12 @@ function registerSetMetadataCommand(program) {
1522
1522
  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", [
1523
1523
  "",
1524
1524
  "Three write paths: a pdf source/target patches the metadata directly on the parsed PDF (writePdf), and a docx source/target",
1525
- "patches docProps/core.xml directly on the decoded package -- both with no layout engine or ContentDocument rebuild involved",
1526
- "at all, so everything else on the page (pdf) or in the package (docx -- comments, footnotes, headers/footers, numbering",
1525
+ "patches docProps/core.xml directly on the decoded package — both with no layout engine or ContentDocument rebuild involved",
1526
+ "at all, so everything else on the page (pdf) or in the package (docx — comments, footnotes, headers/footers, numbering",
1527
1527
  "definitions included) survives byte-faithful. Every other supported format (pptx, xlsx, odt, odp, ods, odg, markdown, rtf)",
1528
1528
  "rebuilds a fresh package from that format's own ContentDocument instead.",
1529
1529
  "",
1530
- "set-metadata does not convert format -- source and target must match. Run convert/from-package first, then",
1530
+ "set-metadata does not convert format — source and target must match. Run convert/from-package first, then",
1531
1531
  "set-metadata on the result, if you need a different target format."
1532
1532
  ].join("\n"));
1533
1533
  addOutOption(command);
@@ -1546,7 +1546,7 @@ function registerSetMetadataCommand(program) {
1546
1546
  }
1547
1547
  //#endregion
1548
1548
  //#region package.json
1549
- var version = "5.11.51";
1549
+ var version = "5.11.52";
1550
1550
  //#endregion
1551
1551
  //#region src/program.ts
1552
1552
  function createProgram() {
package/dist/index.js CHANGED
@@ -272,7 +272,7 @@ function resolveTargetFormat(output, out, to) {
272
272
  return { format: to };
273
273
  }
274
274
  const destination = output ?? out;
275
- if (destination === void 0) return { errorMessage: "cannot infer a target format -- pass an output path with a recognised extension, --out with one, or --to <format>" };
275
+ if (destination === void 0) return { errorMessage: "cannot infer a target format — pass an output path with a recognised extension, --out with one, or --to <format>" };
276
276
  const inferred = inferFormatFromExtension(destination);
277
277
  if (inferred === void 0) return { errorMessage: `cannot infer a target format from '${destination}'; pass --to <format> instead` };
278
278
  return { format: inferred };
@@ -405,11 +405,11 @@ function toConversionCommandOptions(options) {
405
405
  async function runGenericConvert(input, output, options) {
406
406
  const extension = extname(input).toLowerCase();
407
407
  if (extension === ".odm") {
408
- process.stderr.write("convert: '.odm' master documents are not supported by the generic convert command -- use 'odm-to-pdf' instead\n");
408
+ process.stderr.write("convert: '.odm' master documents are not supported by the generic convert command — use 'odm-to-pdf' instead\n");
409
409
  return 2;
410
410
  }
411
411
  if (extension === ".odb") {
412
- process.stderr.write("convert: '.odb' embedded databases are not supported by the generic convert command -- use 'odb-to-csv', 'odb-to-xlsx', or 'odb-tables' instead\n");
412
+ process.stderr.write("convert: '.odb' embedded databases are not supported by the generic convert command — use 'odb-to-csv', 'odb-to-xlsx', or 'odb-tables' instead\n");
413
413
  return 2;
414
414
  }
415
415
  const source = inferFormatFromExtension(input);
@@ -536,7 +536,7 @@ async function runDocxExtras(input, options) {
536
536
  }
537
537
  }
538
538
  function registerDocxExtrasCommand(program) {
539
- program.command("docx-extras <input>").description("print a docx's own comments, footnotes, headers, footers, and numbering definitions -- data readDocxContent's ContentDocument cannot carry").option("--json", "emit the raw DocxExtras object as JSON instead of a human-readable report", false).action(async (input, options) => {
539
+ program.command("docx-extras <input>").description("print a docx's own comments, footnotes, headers, footers, and numbering definitions — data readDocxContent's ContentDocument cannot carry").option("--json", "emit the raw DocxExtras object as JSON instead of a human-readable report", false).action(async (input, options) => {
540
540
  process.exitCode = await runDocxExtras(input, options);
541
541
  });
542
542
  }
@@ -568,7 +568,7 @@ async function runFonts(input, options) {
568
568
  }
569
569
  for (const face of summaries) {
570
570
  const style = [face.bold ? "bold" : void 0, face.italic ? "italic" : void 0].filter((value) => value !== void 0).join(" ");
571
- process.stdout.write(`${face.family}${style === "" ? "" : ` (${style})`} -- ${face.byteLength} bytes\n`);
571
+ process.stdout.write(`${face.family}${style === "" ? "" : ` (${style})`} — ${face.byteLength} bytes\n`);
572
572
  }
573
573
  return 0;
574
574
  } catch (error) {
@@ -633,7 +633,7 @@ async function runFromPackage(input, output, options) {
633
633
  }
634
634
  const result = documentFromJson(parsed);
635
635
  if (result.kind !== "DocumentTree") {
636
- process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentTree -- only a file written by --dump-package can be read back by this command\n`);
636
+ process.stderr.write(`[${command}] '${input}' is a ${result.kind}, not a DocumentTree — only a file written by --dump-package can be read back by this command\n`);
637
637
  return 2;
638
638
  }
639
639
  const content = flattenTree(result.value);
@@ -654,19 +654,19 @@ async function runFromPackage(input, output, options) {
654
654
  return 0;
655
655
  } catch (error) {
656
656
  if (error instanceof UnrecognizedDocumentSchemaError) {
657
- process.stderr.write(`[${command}] '${input}' has no recognised $schema -- only a file written by --dump-package can be read back by this command\n`);
657
+ process.stderr.write(`[${command}] '${input}' has no recognised $schema — only a file written by --dump-package can be read back by this command\n`);
658
658
  return 1;
659
659
  }
660
660
  if (isSchemaVersionMismatchError(error)) {
661
- process.stderr.write(`[${command}] '${input}' is a DocumentTree dump from document-schema.js@${error.dumpVersion}, but this CLI's documents.js reads only @${error.installedVersion}-major dumps -- 4.0.0 replaced the flat { formatVersion, content, pages } shape with the tree-form DocumentTree (ExaDev/document-schema.js#20); re-run the source conversion with --dump-package to write a current dump\n`);
661
+ process.stderr.write(`[${command}] '${input}' is a DocumentTree dump from document-schema.js@${error.dumpVersion}, but this CLI's documents.js reads only @${error.installedVersion}-major dumps — 4.0.0 replaced the flat { formatVersion, content, pages } shape with the tree-form DocumentTree (ExaDev/document-schema.js#20); re-run the source conversion with --dump-package to write a current dump\n`);
662
662
  return 1;
663
663
  }
664
664
  if (isLayoutSchemaDemotedError(error)) {
665
- process.stderr.write(`[${command}] '${input}' is a LayoutDocument dump -- LayoutDocument moved to pdf-codec in document-schema.js 4.0.0 and is no longer a schema-stamped input; re-run the source conversion with --dump-package and read that package back instead\n`);
665
+ process.stderr.write(`[${command}] '${input}' is a LayoutDocument dump — LayoutDocument moved to pdf-codec in document-schema.js 4.0.0 and is no longer a schema-stamped input; re-run the source conversion with --dump-package and read that package back instead\n`);
666
666
  return 1;
667
667
  }
668
668
  if (isDocumentPackageRenamedError(error)) {
669
- process.stderr.write(`[${command}] '${input}' is a document-package dump -- DocumentPackage was renamed to DocumentTree in document-schema.js 5.0.0 (ExaDev/documents.js#661); re-run the source conversion with --dump-package to write a current tree-form DocumentTree dump\n`);
669
+ process.stderr.write(`[${command}] '${input}' is a document-package dump — DocumentPackage was renamed to DocumentTree in document-schema.js 5.0.0 (ExaDev/documents.js#661); re-run the source conversion with --dump-package to write a current tree-form DocumentTree dump\n`);
670
670
  return 1;
671
671
  }
672
672
  process.stderr.write(`${formatError(error, options.verbose)}\n`);
@@ -774,7 +774,7 @@ function countOdbFormDefinitionBoundControls(definition) {
774
774
  function describeOdbForm(form) {
775
775
  const controlCount = form.forms.reduce((total, definition) => total + countOdbFormDefinitionControls(definition), 0);
776
776
  const boundCount = form.forms.reduce((total, definition) => total + countOdbFormDefinitionBoundControls(definition), 0);
777
- return `${form.name} [${form.href}] -- ${form.forms.length} form${form.forms.length === 1 ? "" : "s"}, ${controlCount} control${controlCount === 1 ? "" : "s"} (${boundCount} bound)`;
777
+ return `${form.name} [${form.href}] — ${form.forms.length} form${form.forms.length === 1 ? "" : "s"}, ${controlCount} control${controlCount === 1 ? "" : "s"} (${boundCount} bound)`;
778
778
  }
779
779
  function formControlLines(control, depth) {
780
780
  const parts = [control.tag];
@@ -824,7 +824,7 @@ function describeOdbReport(report) {
824
824
  const groupCount = countReportGroups(report.groups);
825
825
  const elementCount = countReportBandElements(report.reportHeader) + countReportBandElements(report.pageHeader) + countReportBandElements(report.detail) + countReportBandElements(report.pageFooter) + countReportBandElements(report.reportFooter) + report.groups.reduce((total, group) => total + countReportGroupElements(group), 0);
826
826
  const source = dataSource === void 0 ? "no data source" : `on ${dataSource}`;
827
- return `${report.name} [${report.href}] -- ${source}, ${groupCount} group${groupCount === 1 ? "" : "s"}, ${elementCount} element${elementCount === 1 ? "" : "s"}`;
827
+ return `${report.name} [${report.href}] — ${source}, ${groupCount} group${groupCount === 1 ? "" : "s"}, ${elementCount} element${elementCount === 1 ? "" : "s"}`;
828
828
  }
829
829
  function reportElementLine(element, depth) {
830
830
  const parts = [element.tag];
@@ -1016,7 +1016,7 @@ function resolveQuerySql(pkg, options) {
1016
1016
  const saved = inventory.queries.find((candidate) => candidate.name === queryName);
1017
1017
  if (saved === void 0) {
1018
1018
  const available = inventory.queries.map((candidate) => candidate.name);
1019
- return { errorMessage: `this .odb declares no saved query named '${queryName}'${available.length === 0 ? "" : ` -- available: ${available.join(", ")}`}` };
1019
+ return { errorMessage: `this .odb declares no saved query named '${queryName}'${available.length === 0 ? "" : ` — available: ${available.join(", ")}`}` };
1020
1020
  }
1021
1021
  return { sql: saved.command };
1022
1022
  }
@@ -1183,7 +1183,7 @@ function registerOdbToCsvCommand(program) {
1183
1183
  addJsonOption(command);
1184
1184
  addQuietOption(command);
1185
1185
  addVerboseOption(command);
1186
- command.option("--table <name>", "the table to export -- required when the .odb declares more than one table");
1186
+ command.option("--table <name>", "the table to export — required when the .odb declares more than one table");
1187
1187
  command.action(async (input, output, options) => {
1188
1188
  process.exitCode = await runOdbToCsv(input, output, options);
1189
1189
  });
@@ -1204,19 +1204,19 @@ function registerOdbReportsCommand(program) {
1204
1204
  });
1205
1205
  }
1206
1206
  function registerOdbQueryCommand(program) {
1207
- program.command("odb-query <input>").description("run a bounded SELECT over an embedded .odb database's own extracted tables, given directly or by naming one of its saved queries").option("--sql <text>", "the SELECT statement to run -- mutually exclusive with --query").option("--query <savedName>", "the name of one of the .odb's own saved queries to run -- mutually exclusive with --sql").option("--json", "emit the result set as JSON ({ columns, rows }) instead of a plain-text table", false).action(async (input, options) => {
1207
+ program.command("odb-query <input>").description("run a bounded SELECT over an embedded .odb database's own extracted tables, given directly or by naming one of its saved queries").option("--sql <text>", "the SELECT statement to run — mutually exclusive with --query").option("--query <savedName>", "the name of one of the .odb's own saved queries to run — mutually exclusive with --sql").option("--json", "emit the result set as JSON ({ columns, rows }) instead of a plain-text table", false).action(async (input, options) => {
1208
1208
  process.exitCode = await runOdbQuery(input, options);
1209
1209
  });
1210
1210
  }
1211
1211
  function registerOdbRenderReportCommand(program) {
1212
- const command = program.command("odb-render-report <input> [output]").description("render one of an .odb's own reports -- its query resolved, its rpt: formulas evaluated, its bands laid out -- to docx, odt, or pdf");
1212
+ const command = program.command("odb-render-report <input> [output]").description("render one of an .odb's own reports — its query resolved, its rpt: formulas evaluated, its bands laid out — to docx, odt, or pdf");
1213
1213
  addOutOption(command);
1214
1214
  addTimeoutOption(command);
1215
1215
  addJsonOption(command);
1216
1216
  addQuietOption(command);
1217
1217
  addVerboseOption(command);
1218
1218
  addFontOptions(command);
1219
- command.option("--report <name>", "the report to render -- required only when the .odb declares more than one report");
1219
+ command.option("--report <name>", "the report to render — required only when the .odb declares more than one report");
1220
1220
  command.option("--to <format>", "target format when it cannot be inferred from the output path (docx, odt, pdf)");
1221
1221
  command.action(async (input, output, options) => {
1222
1222
  process.exitCode = await runOdbRenderReport(input, output, options);
@@ -1387,7 +1387,7 @@ async function runOutline(input, options) {
1387
1387
  }
1388
1388
  }
1389
1389
  function registerOutlineCommand(program) {
1390
- const command = program.command("outline <input>").description(`print a document's outline -- headings, list items, and slide/sheet/page groups as indented text (${KNOWN_DOCUMENT_FORMATS})`);
1390
+ const command = program.command("outline <input>").description(`print a document's outline — headings, list items, and slide/sheet/page groups as indented text (${KNOWN_DOCUMENT_FORMATS})`);
1391
1391
  addTimeoutOption(command);
1392
1392
  command.option("--json", "emit the outline tree as JSON instead of indented text (diagnostics as NDJSON on stderr)", false);
1393
1393
  addQuietOption(command);
@@ -1521,12 +1521,12 @@ function registerSetMetadataCommand(program) {
1521
1521
  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", [
1522
1522
  "",
1523
1523
  "Three write paths: a pdf source/target patches the metadata directly on the parsed PDF (writePdf), and a docx source/target",
1524
- "patches docProps/core.xml directly on the decoded package -- both with no layout engine or ContentDocument rebuild involved",
1525
- "at all, so everything else on the page (pdf) or in the package (docx -- comments, footnotes, headers/footers, numbering",
1524
+ "patches docProps/core.xml directly on the decoded package — both with no layout engine or ContentDocument rebuild involved",
1525
+ "at all, so everything else on the page (pdf) or in the package (docx — comments, footnotes, headers/footers, numbering",
1526
1526
  "definitions included) survives byte-faithful. Every other supported format (pptx, xlsx, odt, odp, ods, odg, markdown, rtf)",
1527
1527
  "rebuilds a fresh package from that format's own ContentDocument instead.",
1528
1528
  "",
1529
- "set-metadata does not convert format -- source and target must match. Run convert/from-package first, then",
1529
+ "set-metadata does not convert format — source and target must match. Run convert/from-package first, then",
1530
1530
  "set-metadata on the result, if you need a different target format."
1531
1531
  ].join("\n"));
1532
1532
  addOutOption(command);
@@ -1545,7 +1545,7 @@ function registerSetMetadataCommand(program) {
1545
1545
  }
1546
1546
  //#endregion
1547
1547
  //#region package.json
1548
- var version = "5.11.51";
1548
+ var version = "5.11.52";
1549
1549
  //#endregion
1550
1550
  //#region src/program.ts
1551
1551
  function createProgram() {
@@ -240,7 +240,7 @@ function countOdbFormDefinitionBoundControls(definition) {
240
240
  function describeOdbForm(form) {
241
241
  const controlCount = form.forms.reduce((total, definition) => total + countOdbFormDefinitionControls(definition), 0);
242
242
  const boundCount = form.forms.reduce((total, definition) => total + countOdbFormDefinitionBoundControls(definition), 0);
243
- return `${form.name} [${form.href}] -- ${form.forms.length} form${form.forms.length === 1 ? "" : "s"}, ${controlCount} control${controlCount === 1 ? "" : "s"} (${boundCount} bound)`;
243
+ return `${form.name} [${form.href}] — ${form.forms.length} form${form.forms.length === 1 ? "" : "s"}, ${controlCount} control${controlCount === 1 ? "" : "s"} (${boundCount} bound)`;
244
244
  }
245
245
  function formControlLines(control, depth) {
246
246
  const parts = [control.tag];
@@ -290,7 +290,7 @@ function describeOdbReport(report) {
290
290
  const groupCount = countReportGroups(report.groups);
291
291
  const elementCount = countReportBandElements(report.reportHeader) + countReportBandElements(report.pageHeader) + countReportBandElements(report.detail) + countReportBandElements(report.pageFooter) + countReportBandElements(report.reportFooter) + report.groups.reduce((total, group) => total + countReportGroupElements(group), 0);
292
292
  const source = dataSource === void 0 ? "no data source" : `on ${dataSource}`;
293
- return `${report.name} [${report.href}] -- ${source}, ${groupCount} group${groupCount === 1 ? "" : "s"}, ${elementCount} element${elementCount === 1 ? "" : "s"}`;
293
+ return `${report.name} [${report.href}] — ${source}, ${groupCount} group${groupCount === 1 ? "" : "s"}, ${elementCount} element${elementCount === 1 ? "" : "s"}`;
294
294
  }
295
295
  function reportElementLine(element, depth) {
296
296
  const parts = [element.tag];
@@ -1,4 +1,4 @@
1
- import { h as inferFormatFromExtension, i as formatOdbReportLines, l as formatDocxExtrasLines, m as formatToExtension, n as describeOdbReport, o as formatMetadataLines, p as loadProvidedFonts, r as formatOdbFormLines, s as formatMetadataValue, t as describeOdbForm, u as readInput } from "./odb-structure-yc8OHoC0.js";
1
+ import { h as inferFormatFromExtension, i as formatOdbReportLines, l as formatDocxExtrasLines, m as formatToExtension, n as describeOdbReport, o as formatMetadataLines, p as loadProvidedFonts, r as formatOdbFormLines, s as formatMetadataValue, t as describeOdbForm, u as readInput } from "./odb-structure-Crz3Yzzb.js";
2
2
  import { readFile, writeFile } from "node:fs/promises";
3
3
  import { basename, dirname, extname, join } from "node:path";
4
4
  import { bytesToBase64, cellReference, columnIndexToLetters, convertDocument, createDoc, createDocx, createMarkdownEditor, createOdg, createOdp, createOds, createOdt, createPdf, createPpt, createPptx, createXls, csvToPdf, decodeMarkdownText, decodeOdbPackage, docToPdf, docxToPdf, encodeMarkdownText, epubToPdf, hsqldbCellDisplayText, markdownToPdf, odbReportToDocx, odbReportToOdt, odbReportToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDoc, openDocx, openMarkdown, openOdg, openOdp, openOds, openOdt, openPdf, openPpt, openPptx, openXls, parseXml, pptToPdf, pptxToPdf, readDocxContent, readDocxExtras, readMarkdownContent, readOdbForms, readOdbReportContent, readOdbReports, readOdbTables, readOdgContent, readOdpContent, readOdsContent, readOdtContent, readPdf, readPptxContent, rgbHexToColor, rtfToPdf, svgToPdf, xlsToPdf, xlsxToPdf } from "documents.js";
@@ -36,7 +36,7 @@ function toPdfOptions(options, fonts) {
36
36
  };
37
37
  }
38
38
  async function exportToPdf(openDocument, destinationPath, options) {
39
- if (openDocument.format === "odb" || openDocument.format === "pdf") throw new Error(`A ${openDocument.format} document has no export-to-PDF path -- ${openDocument.format === "pdf" ? "save it directly instead" : "it is a read-only source with nothing to convert"}`);
39
+ if (openDocument.format === "odb" || openDocument.format === "pdf") throw new Error(`A ${openDocument.format} document has no export-to-PDF path — ${openDocument.format === "pdf" ? "save it directly instead" : "it is a read-only source with nothing to convert"}`);
40
40
  const pdfOptions = toPdfOptions(options, await loadProvidedFonts(options.fontFiles ?? [], { signal: options.signal }));
41
41
  if (openDocument.format === "markdown") {
42
42
  const pdfBytes = markdownToPdf(encodeMarkdownText(openDocument.editor.toMarkdownText()), pdfOptions);
@@ -950,7 +950,7 @@ function appReducer(state, action) {
950
950
  selection: {},
951
951
  errorDetail: void 0,
952
952
  stack: [rootScreenForFormat(action.doc.format)]
953
- }, "info", action.doc.format === "xlsx" || action.doc.format === "csv" || action.doc.format === "svg" || action.doc.format === "rtf" || action.doc.format === "wpd" || action.doc.format === "doc" || action.doc.format === "xls" || action.doc.format === "ppt" || action.doc.format === "epub" ? `Opened ${action.path} as a read-only PDF preview -- press ':' then 'export pdf' to save it as a real PDF` : `Opened ${action.path}`);
953
+ }, "info", action.doc.format === "xlsx" || action.doc.format === "csv" || action.doc.format === "svg" || action.doc.format === "rtf" || action.doc.format === "wpd" || action.doc.format === "doc" || action.doc.format === "xls" || action.doc.format === "ppt" || action.doc.format === "epub" ? `Opened ${action.path} as a read-only PDF preview — press ':' then 'export pdf' to save it as a real PDF` : `Opened ${action.path}`);
954
954
  case "OPEN_FILE_ERROR": return withStatus({
955
955
  ...state,
956
956
  errorDetail: {
@@ -1057,7 +1057,7 @@ function appReducer(state, action) {
1057
1057
  }
1058
1058
  table.mergeCells(action.merge.startRow, action.merge.startColumn, action.merge.rowSpan, action.merge.colSpan);
1059
1059
  });
1060
- return merge.unsupported ? withStatus(nextState, "warning", "Markdown tables do not support merged cells -- the table was created without merging") : nextState;
1060
+ return merge.unsupported ? withStatus(nextState, "warning", "Markdown tables do not support merged cells — the table was created without merging") : nextState;
1061
1061
  }
1062
1062
  case "MERGE_TABLE_CELLS": {
1063
1063
  const doc = wordprocessingDocument(state);
@@ -2279,7 +2279,7 @@ function StatusLine() {
2279
2279
  " ",
2280
2280
  "⚠ ",
2281
2281
  state.diagnostics.length,
2282
- " diagnostics -- Ctrl+D"
2282
+ " diagnostics — Ctrl+D"
2283
2283
  ]
2284
2284
  }) : void 0
2285
2285
  ] });
@@ -2294,7 +2294,7 @@ function requireFieldValue(values, key) {
2294
2294
  function FieldWizard(props) {
2295
2295
  const [stepIndex, setStepIndex] = useState(0);
2296
2296
  const field = props.fields[stepIndex];
2297
- if (field === void 0) throw new Error(`FieldWizard stepIndex ${stepIndex} is out of range for ${props.fields.length} fields -- onComplete always fires before stepIndex can advance past the last field, so this indicates a bug in that advance.`);
2297
+ if (field === void 0) throw new Error(`FieldWizard stepIndex ${stepIndex} is out of range for ${props.fields.length} fields — onComplete always fires before stepIndex can advance past the last field, so this indicates a bug in that advance.`);
2298
2298
  const [collected, setCollected] = useState({});
2299
2299
  const [draft, setDraft] = useState(field.defaultValue);
2300
2300
  return /* @__PURE__ */ jsxs(Box, {
@@ -2334,7 +2334,7 @@ function FieldWizard(props) {
2334
2334
  stepIndex + 1,
2335
2335
  " of ",
2336
2336
  props.fields.length,
2337
- " -- Enter to continue, Esc to cancel"
2337
+ " — Enter to continue, Esc to cancel"
2338
2338
  ]
2339
2339
  })
2340
2340
  ]
@@ -2481,7 +2481,7 @@ function FormulaPicker(props) {
2481
2481
  children: [
2482
2482
  /* @__PURE__ */ jsx(Text, {
2483
2483
  bold: true,
2484
- children: "Insert formula -- choose a preset or write raw MathML"
2484
+ children: "Insert formula — choose a preset or write raw MathML"
2485
2485
  }),
2486
2486
  /* @__PURE__ */ jsx(ListView, {
2487
2487
  items: PICKER_ROWS,
@@ -2819,7 +2819,7 @@ function ParagraphFamilyBodyList(props) {
2819
2819
  /* @__PURE__ */ jsx(ListView, {
2820
2820
  items: rows,
2821
2821
  selectedIndex: listSelectedIndex,
2822
- emptyMessage: "No paragraphs or tables yet -- press 'a' to append a paragraph.",
2822
+ emptyMessage: "No paragraphs or tables yet — press 'a' to append a paragraph.",
2823
2823
  renderItem: (row, isSelected) => {
2824
2824
  if (row.kind === "header") return /* @__PURE__ */ jsx(Text, {
2825
2825
  bold: true,
@@ -3022,7 +3022,7 @@ async function applyInsertImage(blockIndex, values, dispatch) {
3022
3022
  dispatch({
3023
3023
  type: "SET_STATUS",
3024
3024
  severity: "warning",
3025
- text: `${path} is not a .png or .jpg/.jpeg file -- image not inserted`
3025
+ text: `${path} is not a .png or .jpg/.jpeg file — image not inserted`
3026
3026
  });
3027
3027
  return;
3028
3028
  }
@@ -3051,7 +3051,7 @@ async function applyInsertImage(blockIndex, values, dispatch) {
3051
3051
  function ParagraphRunsView(props) {
3052
3052
  if (props.runs.length === 0) return /* @__PURE__ */ jsx(Text, {
3053
3053
  dimColor: true,
3054
- children: "(no runs -- press 'a' to append one)"
3054
+ children: "(no runs — press 'a' to append one)"
3055
3055
  });
3056
3056
  return /* @__PURE__ */ jsx(Box, { children: props.runs.map((run, index) => {
3057
3057
  const styled = supportsRunStyleExtras(run);
@@ -4072,7 +4072,7 @@ function isReportRenderTargetFormat(format) {
4072
4072
  }
4073
4073
  async function renderOdbReportTo(doc, destinationPath, options) {
4074
4074
  const format = detectFormat(destinationPath);
4075
- if (!isReportRenderTargetFormat(format)) throw new Error(`Cannot tell whether to render "${options.reportName}" as docx, odt, or pdf from '${destinationPath}' -- give the destination one of those three extensions`);
4075
+ if (!isReportRenderTargetFormat(format)) throw new Error(`Cannot tell whether to render "${options.reportName}" as docx, odt, or pdf from '${destinationPath}' — give the destination one of those three extensions`);
4076
4076
  const fonts = await loadProvidedFonts(options.fontFiles ?? [], { signal: options.signal });
4077
4077
  const pkg = decodeOdbPackage(new Uint8Array(await readFile(doc.path)));
4078
4078
  const content = readOdbReportContent(pkg, { report: options.reportName });
@@ -4161,7 +4161,7 @@ function OdbReportRenderScreen() {
4161
4161
  }), /* @__PURE__ */ jsx(TextField, {
4162
4162
  value: fontFiles,
4163
4163
  isFocused: isActive && field === "fonts",
4164
- placeholder: "optional .ttf/.otf paths, comma-separated -- pdf only",
4164
+ placeholder: "optional .ttf/.otf paths, comma-separated — pdf only",
4165
4165
  onChange: setFontFiles,
4166
4166
  onSubmit: submit,
4167
4167
  onCancel: cancel
@@ -4383,17 +4383,17 @@ function defaultTriangleSubpaths(widthPt, heightPt) {
4383
4383
  //#region src/tui/screens/editors/odg/shared.ts
4384
4384
  function requireOdgDocument(state) {
4385
4385
  const doc = state.openDocument;
4386
- if (doc?.format !== "odg") throw new Error(`An odg screen rendered with the open document being ${doc === void 0 ? "no document" : `a '${doc.format}' document`} -- pageList/pageDetail/shapeOrVectorDetail only ever get pushed from odg-routed navigation (rootScreenForFormat maps 'odg' to 'pageList', and every deeper push originates from that screen or its own descendants), so this indicates a routing bug elsewhere, not a state this screen should render around.`);
4386
+ if (doc?.format !== "odg") throw new Error(`An odg screen rendered with the open document being ${doc === void 0 ? "no document" : `a '${doc.format}' document`} — pageList/pageDetail/shapeOrVectorDetail only ever get pushed from odg-routed navigation (rootScreenForFormat maps 'odg' to 'pageList', and every deeper push originates from that screen or its own descendants), so this indicates a routing bug elsewhere, not a state this screen should render around.`);
4387
4387
  return doc;
4388
4388
  }
4389
4389
  function requirePageDetailScreen(state) {
4390
4390
  const screen = currentScreen(state);
4391
- if (screen.kind !== "pageDetail") throw new Error(`OdgPageDetailScreen rendered while the top of the stack is '${screen.kind}', not 'pageDetail' -- app.tsx's ScreenBody switch only mounts this component for that screen kind, so this cannot happen without a routing bug.`);
4391
+ if (screen.kind !== "pageDetail") throw new Error(`OdgPageDetailScreen rendered while the top of the stack is '${screen.kind}', not 'pageDetail' — app.tsx's ScreenBody switch only mounts this component for that screen kind, so this cannot happen without a routing bug.`);
4392
4392
  return screen;
4393
4393
  }
4394
4394
  function requireShapeOrVectorDetailScreen(state) {
4395
4395
  const screen = currentScreen(state);
4396
- if (screen.kind !== "shapeOrVectorDetail") throw new Error(`OdgShapeOrVectorDetailScreen rendered while the top of the stack is '${screen.kind}', not 'shapeOrVectorDetail' -- app.tsx's ScreenBody switch only mounts this component for that screen kind, so this cannot happen without a routing bug.`);
4396
+ if (screen.kind !== "shapeOrVectorDetail") throw new Error(`OdgShapeOrVectorDetailScreen rendered while the top of the stack is '${screen.kind}', not 'shapeOrVectorDetail' — app.tsx's ScreenBody switch only mounts this component for that screen kind, so this cannot happen without a routing bug.`);
4397
4397
  return screen;
4398
4398
  }
4399
4399
  function vectorsParityMatch(liveVectors, contentVectors) {
@@ -4404,9 +4404,9 @@ function buildPageItems(doc, pageIndex) {
4404
4404
  const page = doc.editor.pages()[pageIndex];
4405
4405
  if (page === void 0) return [];
4406
4406
  const content = readOdgContent(doc.editor.toPackage());
4407
- if (content.kind !== "drawing") throw new Error(`readOdgContent(doc.editor.toPackage()) returned a '${content.kind}' ContentDocument for an odg-format open document -- an odg package should always read back as the 'drawing' variant, so this indicates a real inconsistency in documents.js's own reader, not a state this screen should paper over.`);
4407
+ if (content.kind !== "drawing") throw new Error(`readOdgContent(doc.editor.toPackage()) returned a '${content.kind}' ContentDocument for an odg-format open document — an odg package should always read back as the 'drawing' variant, so this indicates a real inconsistency in documents.js's own reader, not a state this screen should paper over.`);
4408
4408
  const contentPage = content.pages[pageIndex];
4409
- if (contentPage === void 0) throw new Error(`readOdgContent found no page at index ${pageIndex}, but doc.editor.pages() has a page there -- the two read the same live package, so they should always agree on page count.`);
4409
+ if (contentPage === void 0) throw new Error(`readOdgContent found no page at index ${pageIndex}, but doc.editor.pages() has a page there — the two read the same live package, so they should always agree on page count.`);
4410
4410
  const liveVectors = page.vectors();
4411
4411
  const parityOk = vectorsParityMatch(liveVectors, contentPage.vectors);
4412
4412
  const vectorItems = contentPage.vectors.map((vector, index) => ({
@@ -4494,7 +4494,7 @@ function OdgPageListScreen() {
4494
4494
  }), /* @__PURE__ */ jsx(ListView, {
4495
4495
  items: pageIndices,
4496
4496
  selectedIndex,
4497
- emptyMessage: "No pages yet -- press 'a' to add one",
4497
+ emptyMessage: "No pages yet — press 'a' to add one",
4498
4498
  renderItem: (pageIndex, isSelected) => {
4499
4499
  const page = pages[pageIndex];
4500
4500
  const shapeCount = page === void 0 ? 0 : page.shapes().length;
@@ -4639,7 +4639,7 @@ function warnVectorIsViewOnly(dispatch, label) {
4639
4639
  dispatch({
4640
4640
  type: "SET_STATUS",
4641
4641
  severity: "info",
4642
- text: `${label} added -- but this page also has a vector element documents.js's OdgPage.vectors() cannot wrap, so every vector on it (including this one) shows read-only in this list rather than risk pairing the wrong live handle to the wrong row.`
4642
+ text: `${label} added — but this page also has a vector element documents.js's OdgPage.vectors() cannot wrap, so every vector on it (including this one) shows read-only in this list rather than risk pairing the wrong live handle to the wrong row.`
4643
4643
  });
4644
4644
  }
4645
4645
  function warnIfVectorAddedReadOnly(doc, pageIndex, dispatch, label) {
@@ -4733,7 +4733,7 @@ async function applyAddKind$1(kind, pageIndex, doc, values, dispatch) {
4733
4733
  dispatch({
4734
4734
  type: "SET_STATUS",
4735
4735
  severity: "warning",
4736
- text: `${path} is not a .png or .jpg/.jpeg file -- image not added`
4736
+ text: `${path} is not a .png or .jpg/.jpeg file — image not added`
4737
4737
  });
4738
4738
  return;
4739
4739
  }
@@ -4778,7 +4778,7 @@ function AddItemFlow$1(props) {
4778
4778
  paddingX: 1,
4779
4779
  children: [/* @__PURE__ */ jsx(Text, {
4780
4780
  bold: true,
4781
- children: "Add item -- choose a kind"
4781
+ children: "Add item — choose a kind"
4782
4782
  }), /* @__PURE__ */ jsx(ListView, {
4783
4783
  items: ADD_KIND_OPTIONS$1,
4784
4784
  selectedIndex,
@@ -4863,7 +4863,7 @@ function OdgPageDetailScreen() {
4863
4863
  children: [
4864
4864
  "Page ",
4865
4865
  pageIndex + 1,
4866
- " -- ",
4866
+ " — ",
4867
4867
  items.length,
4868
4868
  " item",
4869
4869
  items.length === 1 ? "" : "s"
@@ -4871,7 +4871,7 @@ function OdgPageDetailScreen() {
4871
4871
  }), /* @__PURE__ */ jsx(ListView, {
4872
4872
  items: rows,
4873
4873
  selectedIndex,
4874
- emptyMessage: "No items yet -- press 'a' to add one",
4874
+ emptyMessage: "No items yet — press 'a' to add one",
4875
4875
  renderItem: (row, isSelected) => /* @__PURE__ */ jsxs(Text, {
4876
4876
  color: selectedColor(isSelected),
4877
4877
  children: [isSelected ? "> " : " ", describeItem(row.item)]
@@ -4903,7 +4903,7 @@ function buildVectorRows(vector, liveVector, dispatch) {
4903
4903
  dispatch({
4904
4904
  type: "SET_STATUS",
4905
4905
  severity: "warning",
4906
- text: "A vector stroke cannot be cleared to none through this editor -- enter \"r g b widthPt\" (0-1 colour, pt width) instead"
4906
+ text: "A vector stroke cannot be cleared to none through this editor — enter \"r g b widthPt\" (0-1 colour, pt width) instead"
4907
4907
  });
4908
4908
  return;
4909
4909
  }
@@ -4946,7 +4946,7 @@ function VectorDetail(props) {
4946
4946
  /* @__PURE__ */ jsx(Text, { children: describeFillStroke(vector) }),
4947
4947
  /* @__PURE__ */ jsx(Text, {
4948
4948
  color: "yellow",
4949
- children: "This page's live vectors (documents.js's `OdgPage.vectors()`) don't line up one-to-one with what odf.js's own reader found here -- likely a `draw:circle`/`polygon`/`polyline`/`custom-shape` element the live accessor has no wrapper for, sitting alongside a plain rect/ellipse/line/path it does. Rather than risk pairing the wrong live handle to this row, every vector on this page is shown read-only until that mismatch is resolved outside this TUI. Open the file in a real ODF editor to change it."
4949
+ children: "This page's live vectors (documents.js's `OdgPage.vectors()`) don't line up one-to-one with what odf.js's own reader found here — likely a `draw:circle`/`polygon`/`polyline`/`custom-shape` element the live accessor has no wrapper for, sitting alongside a plain rect/ellipse/line/path it does. Rather than risk pairing the wrong live handle to this row, every vector on this page is shown read-only until that mismatch is resolved outside this TUI. Open the file in a real ODF editor to change it."
4950
4950
  }),
4951
4951
  /* @__PURE__ */ jsx(Text, {
4952
4952
  dimColor: true,
@@ -4956,7 +4956,7 @@ function VectorDetail(props) {
4956
4956
  });
4957
4957
  if (editingField !== void 0) {
4958
4958
  const row = rows[editingField];
4959
- if (row === void 0) throw new Error(`VectorDetail is editing field index ${editingField}, but there are only ${rows.length} rows -- selecting a row always sets editingField to a valid index from that same rows array, so this indicates a bug in that selection.`);
4959
+ if (row === void 0) throw new Error(`VectorDetail is editing field index ${editingField}, but there are only ${rows.length} rows — selecting a row always sets editingField to a valid index from that same rows array, so this indicates a bug in that selection.`);
4960
4960
  return /* @__PURE__ */ jsxs(Box, {
4961
4961
  flexDirection: "column",
4962
4962
  borderStyle: "round",
@@ -5115,7 +5115,7 @@ function ShapeDetail(props) {
5115
5115
  });
5116
5116
  if (editingField !== void 0) {
5117
5117
  const row = rows[editingField];
5118
- if (row === void 0) throw new Error(`ShapeDetail is editing field index ${editingField}, but there are only ${rows.length} rows -- selecting a row always sets editingField to a valid index from that same rows array, so this indicates a bug in that selection.`);
5118
+ if (row === void 0) throw new Error(`ShapeDetail is editing field index ${editingField}, but there are only ${rows.length} rows — selecting a row always sets editingField to a valid index from that same rows array, so this indicates a bug in that selection.`);
5119
5119
  return /* @__PURE__ */ jsxs(Box, {
5120
5120
  flexDirection: "column",
5121
5121
  borderStyle: "round",
@@ -5228,7 +5228,7 @@ function assertPresentationDocument(doc) {
5228
5228
  return doc;
5229
5229
  }
5230
5230
  function assertRichPresentationDocument(doc) {
5231
- if (doc === void 0 || doc.format !== "pptx" && doc.format !== "odp") throw new Error("Expected an open pptx or odp document here; the screen router in app.tsx should only reach this rich slide-family screen for one of those formats -- a ppt document routes to its own narrower detail screen.");
5231
+ if (doc === void 0 || doc.format !== "pptx" && doc.format !== "odp") throw new Error("Expected an open pptx or odp document here; the screen router in app.tsx should only reach this rich slide-family screen for one of those formats — a ppt document routes to its own narrower detail screen.");
5232
5232
  return doc;
5233
5233
  }
5234
5234
  const DEFAULT_FRAME_MARGIN_FRACTION = .1;
@@ -5321,7 +5321,7 @@ function SlideFamilySlideList(props) {
5321
5321
  /* @__PURE__ */ jsx(ListView, {
5322
5322
  items: rows,
5323
5323
  selectedIndex,
5324
- emptyMessage: "No slides yet -- press 'a' to add one",
5324
+ emptyMessage: "No slides yet — press 'a' to add one",
5325
5325
  renderItem: (row, isSelected) => /* @__PURE__ */ jsx(SlideRowView, {
5326
5326
  row,
5327
5327
  isSelected
@@ -5581,7 +5581,7 @@ function ShapeEditorScreen(props) {
5581
5581
  ]
5582
5582
  }), /* @__PURE__ */ jsx(Text, {
5583
5583
  color: "yellow",
5584
- children: "This shape no longer exists -- press Esc to go back"
5584
+ children: "This shape no longer exists — press Esc to go back"
5585
5585
  })]
5586
5586
  });
5587
5587
  return /* @__PURE__ */ jsxs(Box, {
@@ -5847,7 +5847,7 @@ function imageFormatFromPath(path) {
5847
5847
  }
5848
5848
  async function readImageForShape(path) {
5849
5849
  const format = imageFormatFromPath(path);
5850
- if (format === void 0) throw new Error(`${path} does not look like a .png or .jpg/.jpeg file -- ADD_IMAGE only accepts those two formats`);
5850
+ if (format === void 0) throw new Error(`${path} does not look like a .png or .jpg/.jpeg file — ADD_IMAGE only accepts those two formats`);
5851
5851
  return {
5852
5852
  format,
5853
5853
  bytes: new Uint8Array(await readFile(path))
@@ -6028,7 +6028,7 @@ function SlideDetailScreen(props) {
6028
6028
  children: [
6029
6029
  "Slide ",
6030
6030
  slideIndex + 1,
6031
- " -- ",
6031
+ " — ",
6032
6032
  shapes.length,
6033
6033
  " shape",
6034
6034
  shapes.length === 1 ? "" : "s"
@@ -6036,11 +6036,11 @@ function SlideDetailScreen(props) {
6036
6036
  }),
6037
6037
  slide === void 0 ? /* @__PURE__ */ jsx(Text, {
6038
6038
  color: "yellow",
6039
- children: "This slide no longer exists -- press Esc to go back"
6039
+ children: "This slide no longer exists — press Esc to go back"
6040
6040
  }) : /* @__PURE__ */ jsx(ListView, {
6041
6041
  items: rows,
6042
6042
  selectedIndex: listSelectedIndex,
6043
- emptyMessage: "No shapes yet -- press 'a' to add one",
6043
+ emptyMessage: "No shapes yet — press 'a' to add one",
6044
6044
  renderItem: (row, isSelected) => {
6045
6045
  if (row.kind === "tablesHeader") return /* @__PURE__ */ jsxs(Text, {
6046
6046
  bold: true,
@@ -6261,7 +6261,7 @@ function SlideTableDetailScreen(props) {
6261
6261
  ]
6262
6262
  }), /* @__PURE__ */ jsx(Text, {
6263
6263
  color: "yellow",
6264
- children: "This table no longer exists -- press Esc to go back"
6264
+ children: "This table no longer exists — press Esc to go back"
6265
6265
  })]
6266
6266
  });
6267
6267
  return /* @__PURE__ */ jsxs(Box, {
@@ -6342,7 +6342,7 @@ function NotesEditorScreen(props) {
6342
6342
  ]
6343
6343
  }), /* @__PURE__ */ jsx(Text, {
6344
6344
  color: "yellow",
6345
- children: "This slide no longer exists -- press Esc to go back"
6345
+ children: "This slide no longer exists — press Esc to go back"
6346
6346
  })]
6347
6347
  });
6348
6348
  return /* @__PURE__ */ jsxs(Box, {
@@ -6622,7 +6622,7 @@ function OdsSheetListScreen() {
6622
6622
  /* @__PURE__ */ jsx(ListView, {
6623
6623
  items: rows,
6624
6624
  selectedIndex,
6625
- emptyMessage: "This workbook has no sheets yet -- press 'a' to add one.",
6625
+ emptyMessage: "This workbook has no sheets yet — press 'a' to add one.",
6626
6626
  renderItem: (row, isSelected) => /* @__PURE__ */ jsx(Text, {
6627
6627
  color: selectedColor(isSelected),
6628
6628
  inverse: isSelected,
@@ -6826,7 +6826,7 @@ function OdsPrintSettingsEditorScreen() {
6826
6826
  children: [
6827
6827
  /* @__PURE__ */ jsxs(Text, {
6828
6828
  bold: true,
6829
- children: ["Print settings -- ", sheet.name]
6829
+ children: ["Print settings — ", sheet.name]
6830
6830
  }),
6831
6831
  /* @__PURE__ */ jsx(ListView, {
6832
6832
  items: FIELD_ROWS,
@@ -6913,7 +6913,7 @@ function OdsCellEditor(props) {
6913
6913
  dispatch({
6914
6914
  type: "SET_STATUS",
6915
6915
  severity: "warning",
6916
- text: `"${text}" is not a valid ${kind} value -- Tab to change kind`
6916
+ text: `"${text}" is not a valid ${kind} value — Tab to change kind`
6917
6917
  });
6918
6918
  return;
6919
6919
  }
@@ -7003,7 +7003,7 @@ async function applyAddSheetImage(sheetIndex, anchorRow, anchorColumn, values, d
7003
7003
  dispatch({
7004
7004
  type: "SET_STATUS",
7005
7005
  severity: "warning",
7006
- text: `${path} is not a .png or .jpg/.jpeg file -- image not added`
7006
+ text: `${path} is not a .png or .jpg/.jpeg file — image not added`
7007
7007
  });
7008
7008
  return;
7009
7009
  }
@@ -7228,7 +7228,7 @@ function OdsSpreadsheetGridScreen() {
7228
7228
  items: filteredCompactRows,
7229
7229
  selectedIndex: compactSelectedIndex,
7230
7230
  reservedRows: GRID_CHROME_ROWS,
7231
- emptyMessage: "No populated cells yet -- press 't' to go back to the grid and start typing.",
7231
+ emptyMessage: "No populated cells yet — press 't' to go back to the grid and start typing.",
7232
7232
  renderItem: (row, isSelected) => /* @__PURE__ */ jsxs(Text, {
7233
7233
  color: selectedColor(isSelected),
7234
7234
  inverse: isSelected,
@@ -7586,7 +7586,7 @@ function XlsSheetListScreen() {
7586
7586
  /* @__PURE__ */ jsx(ListView, {
7587
7587
  items: rows,
7588
7588
  selectedIndex,
7589
- emptyMessage: "This workbook has no sheets yet -- press 'a' to add one.",
7589
+ emptyMessage: "This workbook has no sheets yet — press 'a' to add one.",
7590
7590
  renderItem: (row, isSelected) => /* @__PURE__ */ jsx(Text, {
7591
7591
  color: selectedColor(isSelected),
7592
7592
  inverse: isSelected,
@@ -7698,9 +7698,9 @@ function XlsSpreadsheetGridScreen(props) {
7698
7698
  bold: true,
7699
7699
  children: [
7700
7700
  sheet.name,
7701
- " -- non-empty cells (",
7701
+ " — non-empty cells (",
7702
7702
  entries.length,
7703
- ") -- 't' back to grid"
7703
+ ") — 't' back to grid"
7704
7704
  ]
7705
7705
  }),
7706
7706
  entries.length === 0 ? /* @__PURE__ */ jsx(Text, {
@@ -7813,7 +7813,7 @@ function ListEditorScreen() {
7813
7813
  } else if (input === "<") dispatch({
7814
7814
  type: "SET_STATUS",
7815
7815
  severity: "warning",
7816
- text: "Outdenting isn't reachable from this screen yet -- it only browses top-level lists, with no route into an item's own nested list"
7816
+ text: "Outdenting isn't reachable from this screen yet — it only browses top-level lists, with no route into an item's own nested list"
7817
7817
  });
7818
7818
  }, { isActive: isNavigationActive });
7819
7819
  if (screen.kind !== "listEditor") return /* @__PURE__ */ jsx(Text, {
@@ -7834,7 +7834,7 @@ function ListEditorScreen() {
7834
7834
  });
7835
7835
  if (editingIndex !== void 0) {
7836
7836
  const item = items[editingIndex];
7837
- if (item === void 0) throw new Error(`ListEditorScreen is editing item index ${editingIndex}, but list ${screen.blockIndex} only has ${items.length} items -- selecting a row always sets editingIndex to a valid index from that same items array, so this indicates a bug in that selection.`);
7837
+ if (item === void 0) throw new Error(`ListEditorScreen is editing item index ${editingIndex}, but list ${screen.blockIndex} only has ${items.length} items — selecting a row always sets editingIndex to a valid index from that same items array, so this indicates a bug in that selection.`);
7838
7838
  return /* @__PURE__ */ jsxs(Box, {
7839
7839
  flexDirection: "column",
7840
7840
  children: [/* @__PURE__ */ jsxs(Text, {
@@ -7880,7 +7880,7 @@ function ListEditorScreen() {
7880
7880
  /* @__PURE__ */ jsx(ListView, {
7881
7881
  items: rows,
7882
7882
  selectedIndex,
7883
- emptyMessage: "This list has no items yet -- press 'a' to add one.",
7883
+ emptyMessage: "This list has no items yet — press 'a' to add one.",
7884
7884
  renderItem: (row, isSelected) => {
7885
7885
  const trimmed = row.item.text.trim();
7886
7886
  return /* @__PURE__ */ jsxs(Text, {
@@ -8079,7 +8079,7 @@ function PdfPageListScreen() {
8079
8079
  children: [
8080
8080
  "Page ",
8081
8081
  pageIndex + 1,
8082
- " -- ",
8082
+ " — ",
8083
8083
  pageSummaryText(page)
8084
8084
  ]
8085
8085
  })
@@ -8623,7 +8623,7 @@ function buildRowsFor(item, pageIndex, itemIndex, dispatch, onReplaceImage) {
8623
8623
  }
8624
8624
  function pathSummary(item) {
8625
8625
  const segmentCount = item.subpaths.reduce((total, subpath) => total + subpath.segments.length, 0);
8626
- return `${item.subpaths.length} subpath${item.subpaths.length === 1 ? "" : "s"}, ${segmentCount} segment${segmentCount === 1 ? "" : "s"} (not editable here -- see documents.js's own PdfPathItem doc comment)`;
8626
+ return `${item.subpaths.length} subpath${item.subpaths.length === 1 ? "" : "s"}, ${segmentCount} segment${segmentCount === 1 ? "" : "s"} (not editable here — see documents.js's own PdfPathItem doc comment)`;
8627
8627
  }
8628
8628
  async function applyImageReplace(pageIndex, itemIndex, path, dispatch) {
8629
8629
  const format = inferImageFormat(path);
@@ -8631,7 +8631,7 @@ async function applyImageReplace(pageIndex, itemIndex, path, dispatch) {
8631
8631
  dispatch({
8632
8632
  type: "SET_STATUS",
8633
8633
  severity: "warning",
8634
- text: `${path} is not a .png or .jpg/.jpeg file -- image not replaced`
8634
+ text: `${path} is not a .png or .jpg/.jpeg file — image not replaced`
8635
8635
  });
8636
8636
  return;
8637
8637
  }
@@ -8711,7 +8711,7 @@ function EditableItemDetail(props) {
8711
8711
  });
8712
8712
  if (editingField !== void 0) {
8713
8713
  const row = rows[editingField];
8714
- if (row === void 0) throw new Error(`EditableItemDetail is editing field index ${editingField}, but there are only ${rows.length} rows -- selecting a row always sets editingField to a valid index from that same rows array, so this indicates a bug in that selection.`);
8714
+ if (row === void 0) throw new Error(`EditableItemDetail is editing field index ${editingField}, but there are only ${rows.length} rows — selecting a row always sets editingField to a valid index from that same rows array, so this indicates a bug in that selection.`);
8715
8715
  return /* @__PURE__ */ jsxs(Box, {
8716
8716
  flexDirection: "column",
8717
8717
  borderStyle: "round",
@@ -8743,7 +8743,7 @@ function EditableItemDetail(props) {
8743
8743
  pageIndex + 1,
8744
8744
  ", item ",
8745
8745
  itemIndex + 1,
8746
- " -- ",
8746
+ " — ",
8747
8747
  item.kind
8748
8748
  ]
8749
8749
  }),
@@ -9090,7 +9090,7 @@ async function applyAddKind(kind, pageIndex, values, dispatch) {
9090
9090
  dispatch({
9091
9091
  type: "SET_STATUS",
9092
9092
  severity: "warning",
9093
- text: `${path} is not a .png or .jpg/.jpeg file -- image not added`
9093
+ text: `${path} is not a .png or .jpg/.jpeg file — image not added`
9094
9094
  });
9095
9095
  return;
9096
9096
  }
@@ -9147,7 +9147,7 @@ function AddItemFlow(props) {
9147
9147
  paddingX: 1,
9148
9148
  children: [/* @__PURE__ */ jsx(Text, {
9149
9149
  bold: true,
9150
- children: "Add item -- choose a kind"
9150
+ children: "Add item — choose a kind"
9151
9151
  }), /* @__PURE__ */ jsx(ListView, {
9152
9152
  items: ADD_KIND_OPTIONS,
9153
9153
  selectedIndex,
@@ -9243,7 +9243,7 @@ function PdfPageItemsScreen() {
9243
9243
  /* @__PURE__ */ jsx(ListView, {
9244
9244
  items,
9245
9245
  selectedIndex,
9246
- emptyMessage: query === "" ? editable ? "This page has no items -- press 'a' to add one" : "This page has no items." : `No items match "${state.searchQuery}".`,
9246
+ emptyMessage: query === "" ? editable ? "This page has no items — press 'a' to add one" : "This page has no items." : `No items match "${state.searchQuery}".`,
9247
9247
  renderItem: ({ item, itemIndex }, isSelected) => /* @__PURE__ */ jsxs(Text, {
9248
9248
  color: selectedColor(isSelected),
9249
9249
  inverse: isSelected,
@@ -9251,7 +9251,7 @@ function PdfPageItemsScreen() {
9251
9251
  itemIndex + 1,
9252
9252
  ". ",
9253
9253
  item.kind,
9254
- " -- ",
9254
+ " — ",
9255
9255
  previewFor(item)
9256
9256
  ]
9257
9257
  })
@@ -9543,7 +9543,7 @@ function FilePickerScreen() {
9543
9543
  bold: true,
9544
9544
  children: [
9545
9545
  titleFor(purpose),
9546
- " -- ",
9546
+ " — ",
9547
9547
  currentDir
9548
9548
  ]
9549
9549
  }),
@@ -9612,7 +9612,7 @@ function LauncherScreen() {
9612
9612
  }),
9613
9613
  /* @__PURE__ */ jsx(Text, {
9614
9614
  dimColor: true,
9615
- children: "A terminal editor for docx, pptx, odt, odp, ods, odg, doc, xls, ppt, markdown, odb and pdf -- xlsx, csv, svg, rtf, wpd and epub open as read-only PDF previews."
9615
+ children: "A terminal editor for docx, pptx, odt, odp, ods, odg, doc, xls, ppt, markdown, odb and pdf — xlsx, csv, svg, rtf, wpd and epub open as read-only PDF previews."
9616
9616
  }),
9617
9617
  /* @__PURE__ */ jsx(Text, { children: " " }),
9618
9618
  /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
@@ -9802,7 +9802,7 @@ function metadataFor(doc) {
9802
9802
  case "rtf":
9803
9803
  case "wpd":
9804
9804
  case "epub": return doc.layout.metadata;
9805
- 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.");
9805
+ 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.");
9806
9806
  }
9807
9807
  }
9808
9808
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document-cli",
3
- "version": "5.11.51",
3
+ "version": "5.11.52",
4
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": {
@@ -92,9 +92,9 @@
92
92
  "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
93
93
  "dependencies": {
94
94
  "commander": "15.0.0",
95
- "document-outline.js": "3.9.22",
96
- "document-schema.js": "7.14.0",
97
- "documents.js": "14.1.0",
95
+ "document-outline.js": "3.9.23",
96
+ "document-schema.js": "7.14.1",
97
+ "documents.js": "14.1.1",
98
98
  "ink": "7.1.1",
99
99
  "ink-text-input": "6.0.0",
100
100
  "react": "19.2.8"
@@ -111,7 +111,7 @@
111
111
  "eslint": "10.8.1",
112
112
  "husky": "9.1.7",
113
113
  "ink-testing-library": "4.0.0",
114
- "odf.js": "11.0.0",
114
+ "odf.js": "11.0.1",
115
115
  "publint": "0.3.22",
116
116
  "semantic-release": "25.0.9",
117
117
  "tsdown": "0.22.14",