doculi 3.1.7 → 5.7.10
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/LICENSE +21 -0
- package/README.md +62 -58
- package/dist/cli.js +47 -49
- package/dist/index.cjs +66 -50
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +67 -51
- package/dist/{odb-structure-B1ygPCEa.js → odb-structure-CItnH50p.js} +24 -6
- package/dist/{tui-tT3An-cI.js → tui-CGo4rAhe.js} +1256 -333
- package/package.json +37 -38
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
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-CItnH50p.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, 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";
|
|
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";
|
|
8
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
import TextInput from "ink-text-input";
|
|
10
10
|
//#region src/tui/errors.ts
|
|
11
11
|
function describeError(error) {
|
|
@@ -57,6 +57,36 @@ 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
|
+
}
|
|
65
|
+
if (openDocument.format === "wpd") {
|
|
66
|
+
const pdfBytes = convertDocument("wpd", "pdf", openDocument.bytes, pdfOptions);
|
|
67
|
+
await writeFile(destinationPath, pdfBytes);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (openDocument.format === "doc") {
|
|
71
|
+
const pdfBytes = docToPdf(openDocument.editor.toBytes(), pdfOptions);
|
|
72
|
+
await writeFile(destinationPath, pdfBytes);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (openDocument.format === "xls") {
|
|
76
|
+
const pdfBytes = xlsToPdf(openDocument.editor.toBytes(), pdfOptions);
|
|
77
|
+
await writeFile(destinationPath, pdfBytes);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (openDocument.format === "ppt") {
|
|
81
|
+
const pdfBytes = pptToPdf(openDocument.editor.toBytes(), pdfOptions);
|
|
82
|
+
await writeFile(destinationPath, pdfBytes);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (openDocument.format === "epub") {
|
|
86
|
+
const pdfBytes = epubToPdf(openDocument.bytes, pdfOptions);
|
|
87
|
+
await writeFile(destinationPath, pdfBytes);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
60
90
|
const bytes = openDocument.editor.toBytes();
|
|
61
91
|
const pdfBytes = convert(openDocument.format, bytes, pdfOptions);
|
|
62
92
|
await writeFile(destinationPath, pdfBytes);
|
|
@@ -170,6 +200,39 @@ async function openDocumentAtPath(path, options = {}) {
|
|
|
170
200
|
bytes,
|
|
171
201
|
path
|
|
172
202
|
};
|
|
203
|
+
case "rtf": return {
|
|
204
|
+
format,
|
|
205
|
+
layout: readPdf(rtfToPdf(bytes)),
|
|
206
|
+
bytes,
|
|
207
|
+
path
|
|
208
|
+
};
|
|
209
|
+
case "wpd": return {
|
|
210
|
+
format,
|
|
211
|
+
layout: readPdf(convertDocument("wpd", "pdf", bytes)),
|
|
212
|
+
bytes,
|
|
213
|
+
path
|
|
214
|
+
};
|
|
215
|
+
case "doc": return {
|
|
216
|
+
format,
|
|
217
|
+
editor: openDoc(bytes),
|
|
218
|
+
path
|
|
219
|
+
};
|
|
220
|
+
case "xls": return {
|
|
221
|
+
format,
|
|
222
|
+
editor: openXls(bytes),
|
|
223
|
+
path
|
|
224
|
+
};
|
|
225
|
+
case "ppt": return {
|
|
226
|
+
format,
|
|
227
|
+
editor: openPpt(bytes),
|
|
228
|
+
path
|
|
229
|
+
};
|
|
230
|
+
case "epub": return {
|
|
231
|
+
format,
|
|
232
|
+
layout: readPdf(epubToPdf(bytes)),
|
|
233
|
+
bytes,
|
|
234
|
+
path
|
|
235
|
+
};
|
|
173
236
|
case "odf": throw new Error("A standalone .odf formula document has no editor; convert it to PDF (odfToPdf) instead");
|
|
174
237
|
}
|
|
175
238
|
}
|
|
@@ -180,6 +243,12 @@ function createNewDocument(format) {
|
|
|
180
243
|
editor: createDocx(),
|
|
181
244
|
path: void 0
|
|
182
245
|
};
|
|
246
|
+
case "markdown": return {
|
|
247
|
+
format,
|
|
248
|
+
editor: createMarkdownEditor(),
|
|
249
|
+
originalText: void 0,
|
|
250
|
+
path: void 0
|
|
251
|
+
};
|
|
183
252
|
case "pptx": return {
|
|
184
253
|
format,
|
|
185
254
|
editor: createPptx(),
|
|
@@ -205,6 +274,21 @@ function createNewDocument(format) {
|
|
|
205
274
|
editor: createOdg(),
|
|
206
275
|
path: void 0
|
|
207
276
|
};
|
|
277
|
+
case "doc": return {
|
|
278
|
+
format,
|
|
279
|
+
editor: createDoc(),
|
|
280
|
+
path: void 0
|
|
281
|
+
};
|
|
282
|
+
case "xls": return {
|
|
283
|
+
format,
|
|
284
|
+
editor: createXls(),
|
|
285
|
+
path: void 0
|
|
286
|
+
};
|
|
287
|
+
case "ppt": return {
|
|
288
|
+
format,
|
|
289
|
+
editor: createPpt(),
|
|
290
|
+
path: void 0
|
|
291
|
+
};
|
|
208
292
|
case "pdf": {
|
|
209
293
|
const editor = createPdf();
|
|
210
294
|
return {
|
|
@@ -217,7 +301,7 @@ function createNewDocument(format) {
|
|
|
217
301
|
}
|
|
218
302
|
}
|
|
219
303
|
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`);
|
|
304
|
+
if (openDocument.format === "odb" || openDocument.format === "xlsx" || openDocument.format === "csv" || openDocument.format === "svg" || openDocument.format === "rtf" || openDocument.format === "wpd" || openDocument.format === "epub") throw new Error(`A ${openDocument.format} document is opened read-only and cannot be written back`);
|
|
221
305
|
if (openDocument.format === "markdown") {
|
|
222
306
|
await writeFile(path, encodeMarkdownText(openDocument.editor.toMarkdownText()));
|
|
223
307
|
return;
|
|
@@ -233,7 +317,10 @@ const EDITABLE_FORMATS = {
|
|
|
233
317
|
odp: true,
|
|
234
318
|
ods: true,
|
|
235
319
|
odg: true,
|
|
236
|
-
pdf: true
|
|
320
|
+
pdf: true,
|
|
321
|
+
doc: true,
|
|
322
|
+
xls: true,
|
|
323
|
+
ppt: true
|
|
237
324
|
};
|
|
238
325
|
const WRITABLE_FORMATS = {
|
|
239
326
|
...EDITABLE_FORMATS,
|
|
@@ -242,6 +329,9 @@ const WRITABLE_FORMATS = {
|
|
|
242
329
|
function isEditableFormat(value) {
|
|
243
330
|
return value in EDITABLE_FORMATS;
|
|
244
331
|
}
|
|
332
|
+
function isEditableDocument(document) {
|
|
333
|
+
return isEditableFormat(document.format);
|
|
334
|
+
}
|
|
245
335
|
function isWritableFormat(value) {
|
|
246
336
|
return value in WRITABLE_FORMATS;
|
|
247
337
|
}
|
|
@@ -292,16 +382,22 @@ function rootScreenForFormat(format) {
|
|
|
292
382
|
switch (format) {
|
|
293
383
|
case "docx":
|
|
294
384
|
case "odt":
|
|
295
|
-
case "markdown":
|
|
385
|
+
case "markdown":
|
|
386
|
+
case "doc": return { kind: "bodyList" };
|
|
296
387
|
case "pptx":
|
|
297
|
-
case "odp":
|
|
298
|
-
case "
|
|
388
|
+
case "odp":
|
|
389
|
+
case "ppt": return { kind: "slideList" };
|
|
390
|
+
case "ods":
|
|
391
|
+
case "xls": return { kind: "sheetList" };
|
|
299
392
|
case "odg": return { kind: "pageList" };
|
|
300
393
|
case "odb": return { kind: "odbTableList" };
|
|
301
394
|
case "pdf":
|
|
302
395
|
case "xlsx":
|
|
303
396
|
case "csv":
|
|
304
|
-
case "svg":
|
|
397
|
+
case "svg":
|
|
398
|
+
case "rtf":
|
|
399
|
+
case "wpd":
|
|
400
|
+
case "epub": return { kind: "pdfPageList" };
|
|
305
401
|
}
|
|
306
402
|
}
|
|
307
403
|
function currentScreen(state) {
|
|
@@ -450,6 +546,39 @@ function documentWithPath(doc, path) {
|
|
|
450
546
|
bytes: doc.bytes,
|
|
451
547
|
path
|
|
452
548
|
};
|
|
549
|
+
case "rtf": return {
|
|
550
|
+
format: "rtf",
|
|
551
|
+
layout: doc.layout,
|
|
552
|
+
bytes: doc.bytes,
|
|
553
|
+
path
|
|
554
|
+
};
|
|
555
|
+
case "wpd": return {
|
|
556
|
+
format: "wpd",
|
|
557
|
+
layout: doc.layout,
|
|
558
|
+
bytes: doc.bytes,
|
|
559
|
+
path
|
|
560
|
+
};
|
|
561
|
+
case "doc": return {
|
|
562
|
+
format: "doc",
|
|
563
|
+
editor: doc.editor,
|
|
564
|
+
path
|
|
565
|
+
};
|
|
566
|
+
case "xls": return {
|
|
567
|
+
format: "xls",
|
|
568
|
+
editor: doc.editor,
|
|
569
|
+
path
|
|
570
|
+
};
|
|
571
|
+
case "ppt": return {
|
|
572
|
+
format: "ppt",
|
|
573
|
+
editor: doc.editor,
|
|
574
|
+
path
|
|
575
|
+
};
|
|
576
|
+
case "epub": return {
|
|
577
|
+
format: "epub",
|
|
578
|
+
layout: doc.layout,
|
|
579
|
+
bytes: doc.bytes,
|
|
580
|
+
path
|
|
581
|
+
};
|
|
453
582
|
}
|
|
454
583
|
}
|
|
455
584
|
function reopenEditable(doc, bytes) {
|
|
@@ -484,6 +613,21 @@ function reopenEditable(doc, bytes) {
|
|
|
484
613
|
editor: openOdg(bytes),
|
|
485
614
|
path: doc.path
|
|
486
615
|
};
|
|
616
|
+
case "doc": return {
|
|
617
|
+
format: "doc",
|
|
618
|
+
editor: openDoc(bytes),
|
|
619
|
+
path: doc.path
|
|
620
|
+
};
|
|
621
|
+
case "xls": return {
|
|
622
|
+
format: "xls",
|
|
623
|
+
editor: openXls(bytes),
|
|
624
|
+
path: doc.path
|
|
625
|
+
};
|
|
626
|
+
case "ppt": return {
|
|
627
|
+
format: "ppt",
|
|
628
|
+
editor: openPpt(bytes),
|
|
629
|
+
path: doc.path
|
|
630
|
+
};
|
|
487
631
|
case "pdf": {
|
|
488
632
|
const editor = openPdf(bytes);
|
|
489
633
|
return {
|
|
@@ -545,24 +689,39 @@ function wrongDocument(state, expected) {
|
|
|
545
689
|
function wordprocessingDocument(state) {
|
|
546
690
|
const doc = state.openDocument;
|
|
547
691
|
if (doc === void 0) return;
|
|
548
|
-
return doc.format === "docx" || doc.format === "odt" || doc.format === "markdown" ? doc : void 0;
|
|
692
|
+
return doc.format === "docx" || doc.format === "odt" || doc.format === "markdown" || doc.format === "doc" ? doc : void 0;
|
|
549
693
|
}
|
|
550
694
|
function styledWordprocessingDocument(state) {
|
|
695
|
+
const doc = state.openDocument;
|
|
696
|
+
if (doc === void 0) return;
|
|
697
|
+
return doc.format === "docx" || doc.format === "odt" || doc.format === "doc" ? doc : void 0;
|
|
698
|
+
}
|
|
699
|
+
function docxOdtDocument(state) {
|
|
551
700
|
const doc = state.openDocument;
|
|
552
701
|
if (doc === void 0) return;
|
|
553
702
|
return doc.format === "docx" || doc.format === "odt" ? doc : void 0;
|
|
554
703
|
}
|
|
555
|
-
function
|
|
704
|
+
function richPresentationDocument(state) {
|
|
556
705
|
const doc = state.openDocument;
|
|
557
706
|
if (doc === void 0) return;
|
|
558
707
|
return doc.format === "pptx" || doc.format === "odp" ? doc : void 0;
|
|
559
708
|
}
|
|
709
|
+
function presentationDocument(state) {
|
|
710
|
+
const doc = state.openDocument;
|
|
711
|
+
if (doc === void 0) return;
|
|
712
|
+
return doc.format === "pptx" || doc.format === "odp" || doc.format === "ppt" ? doc : void 0;
|
|
713
|
+
}
|
|
560
714
|
function shapeHostDocument(state) {
|
|
561
715
|
const doc = state.openDocument;
|
|
562
716
|
if (doc === void 0) return;
|
|
563
717
|
return doc.format === "pptx" || doc.format === "odp" || doc.format === "odg" ? doc : void 0;
|
|
564
718
|
}
|
|
565
719
|
function spreadsheetDocument(state) {
|
|
720
|
+
const doc = state.openDocument;
|
|
721
|
+
if (doc === void 0) return;
|
|
722
|
+
return doc.format === "ods" || doc.format === "xls" ? doc : void 0;
|
|
723
|
+
}
|
|
724
|
+
function odsDocument$1(state) {
|
|
566
725
|
const doc = state.openDocument;
|
|
567
726
|
if (doc === void 0) return;
|
|
568
727
|
return doc.format === "ods" ? doc : void 0;
|
|
@@ -606,6 +765,7 @@ const isPdfLineItem = (item) => item.kind === "line";
|
|
|
606
765
|
const isPdfPathItem = (item) => item.kind === "path";
|
|
607
766
|
const isPdfImageItem = (item) => item.kind === "image";
|
|
608
767
|
const isPdfLinkItem = (item) => item.kind === "link";
|
|
768
|
+
const isPdfInternalLinkItem = (item) => item.kind === "internalLink";
|
|
609
769
|
function vectorHostDocument(state) {
|
|
610
770
|
const doc = state.openDocument;
|
|
611
771
|
if (doc === void 0) return;
|
|
@@ -627,6 +787,9 @@ function shapeAt(doc, containerIndex, shapeIndex) {
|
|
|
627
787
|
function sheetAt(doc, sheetIndex) {
|
|
628
788
|
return doc.editor.sheets()[sheetIndex];
|
|
629
789
|
}
|
|
790
|
+
function odsSheetAt(doc, sheetIndex) {
|
|
791
|
+
return doc.editor.sheets()[sheetIndex];
|
|
792
|
+
}
|
|
630
793
|
function withRun(state, blockIndex, runIndex, apply) {
|
|
631
794
|
const doc = wordprocessingDocument(state);
|
|
632
795
|
if (doc === void 0) return wrongDocument(state, "a docx, odt or markdown document");
|
|
@@ -640,7 +803,7 @@ function withRun(state, blockIndex, runIndex, apply) {
|
|
|
640
803
|
}
|
|
641
804
|
function withStyledRun(state, blockIndex, runIndex, apply) {
|
|
642
805
|
const doc = styledWordprocessingDocument(state);
|
|
643
|
-
if (doc === void 0) return wrongDocument(state, "a docx or
|
|
806
|
+
if (doc === void 0) return wrongDocument(state, "a docx, odt or doc document");
|
|
644
807
|
const paragraph = doc.editor.paragraphs()[blockIndex];
|
|
645
808
|
if (paragraph === void 0) return withStatus(state, "warning", `There is no paragraph at index ${blockIndex}`);
|
|
646
809
|
const run = paragraph.runs()[runIndex];
|
|
@@ -658,15 +821,35 @@ function withShape(state, containerIndex, shapeIndex, apply) {
|
|
|
658
821
|
apply(shape);
|
|
659
822
|
});
|
|
660
823
|
}
|
|
824
|
+
function shapeWideAt(doc, containerIndex, shapeIndex) {
|
|
825
|
+
if (doc.format === "odg") return doc.editor.pages()[containerIndex]?.shapes()[shapeIndex];
|
|
826
|
+
return doc.editor.slides()[containerIndex]?.shapes()[shapeIndex];
|
|
827
|
+
}
|
|
828
|
+
function withWideShape(state, containerIndex, shapeIndex, apply) {
|
|
829
|
+
const doc = drawingDocument(state) ?? presentationDocument(state);
|
|
830
|
+
if (doc === void 0) return wrongDocument(state, "a pptx, odp, ppt or odg document");
|
|
831
|
+
const shape = shapeWideAt(doc, containerIndex, shapeIndex);
|
|
832
|
+
if (shape === void 0) return withStatus(state, "warning", `There is no shape ${shapeIndex} on ${doc.format === "odg" ? "page" : "slide"} ${containerIndex}`);
|
|
833
|
+
return mutate(state, doc, () => {
|
|
834
|
+
apply(shape);
|
|
835
|
+
});
|
|
836
|
+
}
|
|
661
837
|
function withSheet(state, sheetIndex, apply) {
|
|
662
838
|
const doc = spreadsheetDocument(state);
|
|
663
|
-
if (doc === void 0) return wrongDocument(state, "an ods document");
|
|
839
|
+
if (doc === void 0) return wrongDocument(state, "an ods or xls document");
|
|
664
840
|
const sheet = sheetAt(doc, sheetIndex);
|
|
665
841
|
if (sheet === void 0) return withStatus(state, "warning", `There is no sheet at index ${sheetIndex}`);
|
|
666
842
|
return mutate(state, doc, () => {
|
|
667
843
|
apply(sheet);
|
|
668
844
|
});
|
|
669
845
|
}
|
|
846
|
+
function withOdsSheet(state, doc, sheetIndex, apply) {
|
|
847
|
+
const sheet = odsSheetAt(doc, sheetIndex);
|
|
848
|
+
if (sheet === void 0) return withStatus(state, "warning", `There is no sheet at index ${sheetIndex}`);
|
|
849
|
+
return mutate(state, doc, () => {
|
|
850
|
+
apply(sheet);
|
|
851
|
+
});
|
|
852
|
+
}
|
|
670
853
|
function setTextContainerText(container, text) {
|
|
671
854
|
const paragraph = container.paragraphs()[0] ?? container.appendParagraph();
|
|
672
855
|
const runs = paragraph.runs();
|
|
@@ -767,7 +950,7 @@ function appReducer(state, action) {
|
|
|
767
950
|
selection: {},
|
|
768
951
|
errorDetail: void 0,
|
|
769
952
|
stack: [rootScreenForFormat(action.doc.format)]
|
|
770
|
-
}, "info", action.doc.format === "xlsx" || action.doc.format === "csv" || action.doc.format === "svg" ? `Opened ${action.path} as a read-only PDF preview -- press ':' then 'export pdf' to save it as a real PDF` : `Opened ${action.path}`);
|
|
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}`);
|
|
771
954
|
case "OPEN_FILE_ERROR": return withStatus({
|
|
772
955
|
...state,
|
|
773
956
|
errorDetail: {
|
|
@@ -868,7 +1051,7 @@ function appReducer(state, action) {
|
|
|
868
1051
|
case "APPEND_TABLE": {
|
|
869
1052
|
const doc = wordprocessingDocument(state);
|
|
870
1053
|
if (doc === void 0) return wrongDocument(state, "a docx, odt or markdown document");
|
|
871
|
-
|
|
1054
|
+
const merge = { unsupported: false };
|
|
872
1055
|
const nextState = mutateGuarded(state, doc, () => {
|
|
873
1056
|
const table = doc.editor.body.appendTable({
|
|
874
1057
|
rows: action.rows,
|
|
@@ -876,12 +1059,12 @@ function appReducer(state, action) {
|
|
|
876
1059
|
});
|
|
877
1060
|
if (action.merge === void 0) return;
|
|
878
1061
|
if (!("mergeCells" in table)) {
|
|
879
|
-
|
|
1062
|
+
merge.unsupported = true;
|
|
880
1063
|
return;
|
|
881
1064
|
}
|
|
882
1065
|
table.mergeCells(action.merge.startRow, action.merge.startColumn, action.merge.rowSpan, action.merge.colSpan);
|
|
883
1066
|
});
|
|
884
|
-
return
|
|
1067
|
+
return merge.unsupported ? withStatus(nextState, "warning", "Markdown tables do not support merged cells -- the table was created without merging") : nextState;
|
|
885
1068
|
}
|
|
886
1069
|
case "MERGE_TABLE_CELLS": {
|
|
887
1070
|
const doc = wordprocessingDocument(state);
|
|
@@ -935,6 +1118,16 @@ function appReducer(state, action) {
|
|
|
935
1118
|
setTextContainerText(item, action.text);
|
|
936
1119
|
});
|
|
937
1120
|
}
|
|
1121
|
+
case "INDENT_LIST_ITEM": {
|
|
1122
|
+
const doc = wordprocessingDocument(state);
|
|
1123
|
+
if (doc === void 0) return wrongDocument(state, "a docx, odt or markdown document");
|
|
1124
|
+
if (doc.format !== "odt") return wrongDocument(state, "an odt document (lists are an odt-only concept)");
|
|
1125
|
+
const list = doc.editor.lists()[action.blockIndex];
|
|
1126
|
+
if (list === void 0) return withStatus(state, "warning", `There is no list at index ${action.blockIndex}`);
|
|
1127
|
+
return mutateGuarded(state, doc, () => {
|
|
1128
|
+
list.indentItem(action.itemIndex);
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
938
1131
|
case "ADD_LIST": {
|
|
939
1132
|
const doc = wordprocessingDocument(state);
|
|
940
1133
|
if (doc === void 0) return wrongDocument(state, "a docx, odt or markdown document");
|
|
@@ -944,7 +1137,7 @@ function appReducer(state, action) {
|
|
|
944
1137
|
});
|
|
945
1138
|
}
|
|
946
1139
|
case "INSERT_PARAGRAPH_IMAGE": {
|
|
947
|
-
const doc =
|
|
1140
|
+
const doc = docxOdtDocument(state);
|
|
948
1141
|
if (doc === void 0) return wrongDocument(state, "a docx or odt document");
|
|
949
1142
|
const paragraph = doc.editor.paragraphs()[action.blockIndex];
|
|
950
1143
|
if (paragraph === void 0) return withStatus(state, "warning", `There is no paragraph at index ${action.blockIndex}`);
|
|
@@ -963,11 +1156,11 @@ function appReducer(state, action) {
|
|
|
963
1156
|
if (doc?.format !== "docx") return wrongDocument(state, "a docx document");
|
|
964
1157
|
const paragraph = doc.editor.paragraphs()[action.blockIndex];
|
|
965
1158
|
if (paragraph === void 0) return withStatus(state, "warning", `There is no paragraph at index ${action.blockIndex}`);
|
|
966
|
-
|
|
1159
|
+
const omml = { written: true };
|
|
967
1160
|
const nextState = mutate(state, doc, () => {
|
|
968
|
-
written = paragraph.appendOfficeMath(action.mathml).written;
|
|
1161
|
+
omml.written = paragraph.appendOfficeMath(action.mathml).written;
|
|
969
1162
|
});
|
|
970
|
-
return written ? nextState : withStatus(nextState, "warning", "The formula produced no OMML content and was not written");
|
|
1163
|
+
return omml.written ? nextState : withStatus(nextState, "warning", "The formula produced no OMML content and was not written");
|
|
971
1164
|
}
|
|
972
1165
|
case "INSERT_ODT_FORMULA": {
|
|
973
1166
|
const doc = state.openDocument;
|
|
@@ -984,7 +1177,7 @@ function appReducer(state, action) {
|
|
|
984
1177
|
});
|
|
985
1178
|
}
|
|
986
1179
|
case "ADD_SLIDE_TABLE": {
|
|
987
|
-
const doc =
|
|
1180
|
+
const doc = richPresentationDocument(state);
|
|
988
1181
|
if (doc === void 0) return wrongDocument(state, "a pptx or odp document");
|
|
989
1182
|
const slide = doc.editor.slides()[action.slideIndex];
|
|
990
1183
|
if (slide === void 0) return withStatus(state, "warning", `There is no slide at index ${action.slideIndex}`);
|
|
@@ -999,7 +1192,7 @@ function appReducer(state, action) {
|
|
|
999
1192
|
});
|
|
1000
1193
|
}
|
|
1001
1194
|
case "MERGE_SLIDE_TABLE_CELLS": {
|
|
1002
|
-
const doc =
|
|
1195
|
+
const doc = richPresentationDocument(state);
|
|
1003
1196
|
if (doc === void 0) return wrongDocument(state, "a pptx or odp document");
|
|
1004
1197
|
if (doc.format === "odp") {
|
|
1005
1198
|
const entry = doc.editor.slides()[action.slideIndex]?.tables()[action.tableIndex];
|
|
@@ -1015,18 +1208,19 @@ function appReducer(state, action) {
|
|
|
1015
1208
|
});
|
|
1016
1209
|
}
|
|
1017
1210
|
case "ADD_TEXTBOX": {
|
|
1018
|
-
const
|
|
1019
|
-
if (
|
|
1020
|
-
|
|
1021
|
-
const page = doc.editor.pages()[action.containerIndex];
|
|
1211
|
+
const drawing = drawingDocument(state);
|
|
1212
|
+
if (drawing !== void 0) {
|
|
1213
|
+
const page = drawing.editor.pages()[action.containerIndex];
|
|
1022
1214
|
if (page === void 0) return withStatus(state, "warning", `There is no page at index ${action.containerIndex}`);
|
|
1023
|
-
return mutate(state,
|
|
1215
|
+
return mutate(state, drawing, () => {
|
|
1024
1216
|
page.addTextBox({
|
|
1025
1217
|
frame: action.frame,
|
|
1026
1218
|
text: action.text
|
|
1027
1219
|
});
|
|
1028
1220
|
});
|
|
1029
1221
|
}
|
|
1222
|
+
const doc = presentationDocument(state);
|
|
1223
|
+
if (doc === void 0) return wrongDocument(state, "a pptx, odp, ppt or odg document");
|
|
1030
1224
|
const slide = doc.editor.slides()[action.containerIndex];
|
|
1031
1225
|
if (slide === void 0) return withStatus(state, "warning", `There is no slide at index ${action.containerIndex}`);
|
|
1032
1226
|
return mutate(state, doc, () => {
|
|
@@ -1058,10 +1252,10 @@ function appReducer(state, action) {
|
|
|
1058
1252
|
slide.addImage(image);
|
|
1059
1253
|
});
|
|
1060
1254
|
}
|
|
1061
|
-
case "SET_SHAPE_TEXT": return
|
|
1255
|
+
case "SET_SHAPE_TEXT": return withWideShape(state, action.containerIndex, action.shapeIndex, (shape) => {
|
|
1062
1256
|
shape.text = action.text;
|
|
1063
1257
|
});
|
|
1064
|
-
case "SET_SHAPE_FRAME": return
|
|
1258
|
+
case "SET_SHAPE_FRAME": return withWideShape(state, action.containerIndex, action.shapeIndex, (shape) => {
|
|
1065
1259
|
shape.frame = action.frame;
|
|
1066
1260
|
});
|
|
1067
1261
|
case "SET_SHAPE_ROTATION": return withShape(state, action.containerIndex, action.shapeIndex, (shape) => {
|
|
@@ -1078,7 +1272,7 @@ function appReducer(state, action) {
|
|
|
1078
1272
|
}
|
|
1079
1273
|
case "ADD_SHEET": {
|
|
1080
1274
|
const doc = spreadsheetDocument(state);
|
|
1081
|
-
if (doc === void 0) return wrongDocument(state, "an ods document");
|
|
1275
|
+
if (doc === void 0) return wrongDocument(state, "an ods or xls document");
|
|
1082
1276
|
return mutate(state, doc, () => {
|
|
1083
1277
|
doc.editor.addSheet(action.name);
|
|
1084
1278
|
});
|
|
@@ -1086,27 +1280,37 @@ function appReducer(state, action) {
|
|
|
1086
1280
|
case "SET_CELL_VALUE": return withSheet(state, action.sheetIndex, (sheet) => {
|
|
1087
1281
|
sheet.cell(action.row, action.column).value = action.value;
|
|
1088
1282
|
});
|
|
1089
|
-
case "SET_CELL_FORMULA":
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
sheet
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
base64: bytesToBase64(action.bytes),
|
|
1097
|
-
widthPt: action.widthPt,
|
|
1098
|
-
heightPt: action.heightPt,
|
|
1099
|
-
altText: action.altText,
|
|
1100
|
-
anchorRow: action.anchorRow,
|
|
1101
|
-
anchorColumn: action.anchorColumn,
|
|
1102
|
-
offsetXPt: action.offsetXPt,
|
|
1103
|
-
offsetYPt: action.offsetYPt
|
|
1283
|
+
case "SET_CELL_FORMULA": {
|
|
1284
|
+
const doc = odsDocument$1(state);
|
|
1285
|
+
if (doc === void 0) return wrongDocument(state, "an ods document");
|
|
1286
|
+
const sheet = odsSheetAt(doc, action.sheetIndex);
|
|
1287
|
+
if (sheet === void 0) return withStatus(state, "warning", `There is no sheet at index ${action.sheetIndex}`);
|
|
1288
|
+
return mutate(state, doc, () => {
|
|
1289
|
+
sheet.cell(action.row, action.column).formula = action.formula;
|
|
1104
1290
|
});
|
|
1105
|
-
}
|
|
1291
|
+
}
|
|
1292
|
+
case "ADD_SHEET_IMAGE": {
|
|
1293
|
+
const ods = odsDocument$1(state);
|
|
1294
|
+
if (ods === void 0) return wrongDocument(state, "an ods document");
|
|
1295
|
+
return withOdsSheet(state, ods, action.sheetIndex, (sheet) => {
|
|
1296
|
+
sheet.addImage({
|
|
1297
|
+
kind: "image",
|
|
1298
|
+
format: action.format,
|
|
1299
|
+
base64: bytesToBase64(action.bytes),
|
|
1300
|
+
widthPt: action.widthPt,
|
|
1301
|
+
heightPt: action.heightPt,
|
|
1302
|
+
altText: action.altText,
|
|
1303
|
+
anchorRow: action.anchorRow,
|
|
1304
|
+
anchorColumn: action.anchorColumn,
|
|
1305
|
+
offsetXPt: action.offsetXPt,
|
|
1306
|
+
offsetYPt: action.offsetYPt
|
|
1307
|
+
});
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1106
1310
|
case "MERGE_CELLS": {
|
|
1107
|
-
const doc =
|
|
1311
|
+
const doc = odsDocument$1(state);
|
|
1108
1312
|
if (doc === void 0) return wrongDocument(state, "an ods document");
|
|
1109
|
-
const sheet =
|
|
1313
|
+
const sheet = odsSheetAt(doc, action.sheetIndex);
|
|
1110
1314
|
if (sheet === void 0) return withStatus(state, "warning", `There is no sheet at index ${action.sheetIndex}`);
|
|
1111
1315
|
return mutateGuarded(state, doc, () => {
|
|
1112
1316
|
sheet.mergeCells(action.startRow, action.startColumn, action.rowSpan, action.colSpan);
|
|
@@ -1325,6 +1529,22 @@ function appReducer(state, action) {
|
|
|
1325
1529
|
item.widthPt = action.widthPt;
|
|
1326
1530
|
item.heightPt = action.heightPt;
|
|
1327
1531
|
});
|
|
1532
|
+
case "SET_PDF_INTERNAL_LINK_DESTINATION": return withPdfItemMatching(state, action.pageIndex, action.itemIndex, isPdfInternalLinkItem, "internalLink", (item) => {
|
|
1533
|
+
item.destination = action.destination;
|
|
1534
|
+
});
|
|
1535
|
+
case "SET_PDF_INTERNAL_LINK_FRAME": return withPdfItemMatching(state, action.pageIndex, action.itemIndex, isPdfInternalLinkItem, "internalLink", (item) => {
|
|
1536
|
+
item.xPt = action.xPt;
|
|
1537
|
+
item.yPt = action.yPt;
|
|
1538
|
+
item.widthPt = action.widthPt;
|
|
1539
|
+
item.heightPt = action.heightPt;
|
|
1540
|
+
});
|
|
1541
|
+
case "SET_METADATA": {
|
|
1542
|
+
const doc = state.openDocument;
|
|
1543
|
+
if (doc === void 0 || !isEditableDocument(doc)) return wrongDocument(state, "an editable document");
|
|
1544
|
+
return mutate(state, doc, () => {
|
|
1545
|
+
doc.editor.metadata = action.overrides;
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1328
1548
|
case "APPEND_DIAGNOSTIC": return {
|
|
1329
1549
|
...state,
|
|
1330
1550
|
diagnostics: [...state.diagnostics, action.diagnostic]
|
|
@@ -1353,7 +1573,7 @@ function appReducer(state, action) {
|
|
|
1353
1573
|
case "UNDO": {
|
|
1354
1574
|
const doc = state.openDocument;
|
|
1355
1575
|
if (doc === void 0) return withStatus(state, "info", "There is nothing to undo");
|
|
1356
|
-
if (doc.format === "odb" || doc.format === "xlsx" || doc.format === "csv" || doc.format === "svg") return withStatus(state, "warning", `A ${doc.format} document is read-only, so it has no history to undo`);
|
|
1576
|
+
if (doc.format === "odb" || doc.format === "xlsx" || doc.format === "csv" || doc.format === "svg" || doc.format === "rtf" || doc.format === "wpd" || doc.format === "doc" || doc.format === "xls" || doc.format === "ppt" || doc.format === "epub") return withStatus(state, "warning", `A ${doc.format} document is read-only, so it has no history to undo`);
|
|
1357
1577
|
const snapshot = state.undoStack.at(-1);
|
|
1358
1578
|
if (snapshot === void 0) return withStatus(state, "info", "There is nothing to undo");
|
|
1359
1579
|
const restored = doc.format === "markdown" ? {
|
|
@@ -2057,7 +2277,8 @@ function StatusLine() {
|
|
|
2057
2277
|
showDiagnosticsBadge ? /* @__PURE__ */ jsxs(Text, {
|
|
2058
2278
|
color: "yellow",
|
|
2059
2279
|
children: [
|
|
2060
|
-
"
|
|
2280
|
+
" ",
|
|
2281
|
+
"⚠ ",
|
|
2061
2282
|
state.diagnostics.length,
|
|
2062
2283
|
" diagnostics -- Ctrl+D"
|
|
2063
2284
|
]
|
|
@@ -2304,7 +2525,7 @@ function supportsRunStyleExtras(run) {
|
|
|
2304
2525
|
}
|
|
2305
2526
|
function paragraphFamilyDocument(openDocument) {
|
|
2306
2527
|
if (openDocument === void 0) return;
|
|
2307
|
-
return openDocument.format === "docx" || openDocument.format === "odt" || openDocument.format === "markdown" ? openDocument : void 0;
|
|
2528
|
+
return openDocument.format === "docx" || openDocument.format === "odt" || openDocument.format === "markdown" || openDocument.format === "doc" ? openDocument : void 0;
|
|
2308
2529
|
}
|
|
2309
2530
|
function liveParagraphAt(doc, blockIndex) {
|
|
2310
2531
|
return doc.editor.paragraphs()[blockIndex];
|
|
@@ -2653,7 +2874,8 @@ function ParagraphFamilyBodyList(props) {
|
|
|
2653
2874
|
children: [
|
|
2654
2875
|
"Merge start row (0-",
|
|
2655
2876
|
Math.max(0, wizardRows - 1),
|
|
2656
|
-
"):
|
|
2877
|
+
"):",
|
|
2878
|
+
" "
|
|
2657
2879
|
]
|
|
2658
2880
|
}), /* @__PURE__ */ jsx(TextField, {
|
|
2659
2881
|
value: wizardDraft,
|
|
@@ -2667,7 +2889,8 @@ function ParagraphFamilyBodyList(props) {
|
|
|
2667
2889
|
children: [
|
|
2668
2890
|
"Merge start column (0-",
|
|
2669
2891
|
Math.max(0, wizardColumns - 1),
|
|
2670
|
-
"):
|
|
2892
|
+
"):",
|
|
2893
|
+
" "
|
|
2671
2894
|
]
|
|
2672
2895
|
}), /* @__PURE__ */ jsx(TextField, {
|
|
2673
2896
|
value: wizardDraft,
|
|
@@ -2681,7 +2904,8 @@ function ParagraphFamilyBodyList(props) {
|
|
|
2681
2904
|
children: [
|
|
2682
2905
|
"Merge row span (1-",
|
|
2683
2906
|
Math.max(1, wizardRows - wizardStartRow),
|
|
2684
|
-
"):
|
|
2907
|
+
"):",
|
|
2908
|
+
" "
|
|
2685
2909
|
]
|
|
2686
2910
|
}), /* @__PURE__ */ jsx(TextField, {
|
|
2687
2911
|
value: wizardDraft,
|
|
@@ -2695,7 +2919,8 @@ function ParagraphFamilyBodyList(props) {
|
|
|
2695
2919
|
children: [
|
|
2696
2920
|
"Merge column span (1-",
|
|
2697
2921
|
Math.max(1, wizardColumns - wizardStartColumn),
|
|
2698
|
-
"):
|
|
2922
|
+
"):",
|
|
2923
|
+
" "
|
|
2699
2924
|
]
|
|
2700
2925
|
}), /* @__PURE__ */ jsx(TextField, {
|
|
2701
2926
|
value: wizardDraft,
|
|
@@ -3332,7 +3557,7 @@ function TableViewScreen() {
|
|
|
3332
3557
|
children: "This table has no rows."
|
|
3333
3558
|
}) : rows.map((row, rowIndex) => /* @__PURE__ */ jsx(Box, { children: row.cells().map((cell, columnIndex) => {
|
|
3334
3559
|
const isSelected = rowIndex === clampedRow && columnIndex === clampedColumn;
|
|
3335
|
-
const isAnchor = rowIndex === mergeAnchor?.row && columnIndex === mergeAnchor
|
|
3560
|
+
const isAnchor = rowIndex === mergeAnchor?.row && columnIndex === mergeAnchor.column;
|
|
3336
3561
|
return /* @__PURE__ */ jsx(Box, {
|
|
3337
3562
|
width: CELL_WIDTH$2,
|
|
3338
3563
|
borderStyle: "single",
|
|
@@ -3385,7 +3610,8 @@ function TableCellDetailScreen() {
|
|
|
3385
3610
|
screen.row,
|
|
3386
3611
|
", column ",
|
|
3387
3612
|
screen.col,
|
|
3388
|
-
" of table
|
|
3613
|
+
" of table",
|
|
3614
|
+
" ",
|
|
3389
3615
|
screen.blockIndex,
|
|
3390
3616
|
"."
|
|
3391
3617
|
]
|
|
@@ -3450,7 +3676,8 @@ function DocxBodyListScreen() {
|
|
|
3450
3676
|
if (doc?.format !== "docx") return /* @__PURE__ */ jsxs(Text, {
|
|
3451
3677
|
color: "red",
|
|
3452
3678
|
children: [
|
|
3453
|
-
"DocxBodyListScreen requires an open docx document, found
|
|
3679
|
+
"DocxBodyListScreen requires an open docx document, found",
|
|
3680
|
+
" ",
|
|
3454
3681
|
doc === void 0 ? "no open document" : doc.format,
|
|
3455
3682
|
"."
|
|
3456
3683
|
]
|
|
@@ -3486,7 +3713,8 @@ function DocxExtrasScreen() {
|
|
|
3486
3713
|
if (!isDocx) return /* @__PURE__ */ jsxs(Text, {
|
|
3487
3714
|
color: "red",
|
|
3488
3715
|
children: [
|
|
3489
|
-
"DocxExtrasScreen requires an open docx document, found
|
|
3716
|
+
"DocxExtrasScreen requires an open docx document, found",
|
|
3717
|
+
" ",
|
|
3490
3718
|
doc === void 0 ? "no open document" : doc.format,
|
|
3491
3719
|
"."
|
|
3492
3720
|
]
|
|
@@ -3499,7 +3727,8 @@ function DocxExtrasScreen() {
|
|
|
3499
3727
|
children: [
|
|
3500
3728
|
"Comments, footnotes, headers, footers, numbering (",
|
|
3501
3729
|
lines.length,
|
|
3502
|
-
" of
|
|
3730
|
+
" of",
|
|
3731
|
+
" ",
|
|
3503
3732
|
allLines.length,
|
|
3504
3733
|
" lines)"
|
|
3505
3734
|
]
|
|
@@ -3570,7 +3799,8 @@ function MarkdownBodyListScreen() {
|
|
|
3570
3799
|
if (doc?.format !== "markdown") return /* @__PURE__ */ jsxs(Text, {
|
|
3571
3800
|
color: "red",
|
|
3572
3801
|
children: [
|
|
3573
|
-
"MarkdownBodyListScreen requires an open markdown document, found
|
|
3802
|
+
"MarkdownBodyListScreen requires an open markdown document, found",
|
|
3803
|
+
" ",
|
|
3574
3804
|
doc === void 0 ? "no open document" : doc.format,
|
|
3575
3805
|
"."
|
|
3576
3806
|
]
|
|
@@ -4012,7 +4242,8 @@ function OdbTableListScreen() {
|
|
|
4012
4242
|
table.tableName,
|
|
4013
4243
|
" (",
|
|
4014
4244
|
table.columns.length,
|
|
4015
|
-
" columns,
|
|
4245
|
+
" columns,",
|
|
4246
|
+
" ",
|
|
4016
4247
|
table.rows.length,
|
|
4017
4248
|
" rows)"
|
|
4018
4249
|
]
|
|
@@ -4655,20 +4886,17 @@ function OdgPageDetailScreen() {
|
|
|
4655
4886
|
//#region src/tui/screens/editors/odg/shape-or-vector-detail.tsx
|
|
4656
4887
|
function buildVectorRows(vector, liveVector, dispatch) {
|
|
4657
4888
|
const rows = [];
|
|
4658
|
-
if (vector.kind !== "line" && liveVector.kind !== "line") {
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
}
|
|
4670
|
-
});
|
|
4671
|
-
}
|
|
4889
|
+
if (vector.kind !== "line" && liveVector.kind !== "line") rows.push({
|
|
4890
|
+
label: `Fill: ${vector.fill === void 0 ? "none" : formatColor$1(vector.fill)}`,
|
|
4891
|
+
currentValue: vector.fill === void 0 ? "" : `${vector.fill.r} ${vector.fill.g} ${vector.fill.b}`,
|
|
4892
|
+
commit: (raw) => {
|
|
4893
|
+
dispatch({
|
|
4894
|
+
type: "SET_VECTOR_FILL",
|
|
4895
|
+
vector: liveVector,
|
|
4896
|
+
fill: parseColorField(raw)
|
|
4897
|
+
});
|
|
4898
|
+
}
|
|
4899
|
+
});
|
|
4672
4900
|
rows.push({
|
|
4673
4901
|
label: `Stroke: ${vector.stroke === void 0 ? "none" : `${formatColor$1(vector.stroke.color)} ${formatPt$1(vector.stroke.widthPt)}pt`}`,
|
|
4674
4902
|
currentValue: vector.stroke === void 0 ? "" : `${vector.stroke.color.r} ${vector.stroke.color.g} ${vector.stroke.color.b} ${vector.stroke.widthPt}`,
|
|
@@ -4995,8 +5223,15 @@ function buildPptxSlideFamilyAdapter(editor) {
|
|
|
4995
5223
|
function buildOdpSlideFamilyAdapter(editor) {
|
|
4996
5224
|
return buildSlideFamilyAdapter("odp", editor);
|
|
4997
5225
|
}
|
|
5226
|
+
function buildPptSlideFamilyAdapter(editor) {
|
|
5227
|
+
return buildSlideFamilyAdapter("ppt", editor);
|
|
5228
|
+
}
|
|
4998
5229
|
function assertPresentationDocument(doc) {
|
|
4999
|
-
if (doc === void 0 || doc.format !== "pptx" && doc.format !== "odp") throw new Error("Expected an open pptx or
|
|
5230
|
+
if (doc === void 0 || doc.format !== "pptx" && doc.format !== "odp" && doc.format !== "ppt") throw new Error("Expected an open pptx, odp or ppt document here; the screen router in app.tsx should only reach a slide-family screen for one of those formats.");
|
|
5231
|
+
return doc;
|
|
5232
|
+
}
|
|
5233
|
+
function assertRichPresentationDocument(doc) {
|
|
5234
|
+
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.");
|
|
5000
5235
|
return doc;
|
|
5001
5236
|
}
|
|
5002
5237
|
const DEFAULT_FRAME_MARGIN_FRACTION = .1;
|
|
@@ -5079,8 +5314,9 @@ function SlideFamilySlideList(props) {
|
|
|
5079
5314
|
/* @__PURE__ */ jsxs(Text, {
|
|
5080
5315
|
bold: true,
|
|
5081
5316
|
children: [
|
|
5082
|
-
props.adapter.formatLabel === "
|
|
5083
|
-
"
|
|
5317
|
+
props.adapter.formatLabel === "odp" ? "Impress" : props.adapter.formatLabel === "ppt" ? "PowerPoint 97-2003" : "PowerPoint",
|
|
5318
|
+
" ",
|
|
5319
|
+
"slides (",
|
|
5084
5320
|
rows.length,
|
|
5085
5321
|
")"
|
|
5086
5322
|
]
|
|
@@ -5224,7 +5460,7 @@ function ShapeEditorScreen(props) {
|
|
|
5224
5460
|
const state = useAppState();
|
|
5225
5461
|
const dispatch = useAppDispatch();
|
|
5226
5462
|
const overlayOpen = anyOverlayOpen(state);
|
|
5227
|
-
const doc =
|
|
5463
|
+
const doc = assertRichPresentationDocument(state.openDocument);
|
|
5228
5464
|
const { slideIndex, shapeIndex } = props.screen;
|
|
5229
5465
|
const shape = doc.editor.slides()[slideIndex]?.shapes()[shapeIndex];
|
|
5230
5466
|
const [editingField, setEditingField] = useState(void 0);
|
|
@@ -5566,7 +5802,7 @@ function SlideDetailScreen(props) {
|
|
|
5566
5802
|
const state = useAppState();
|
|
5567
5803
|
const dispatch = useAppDispatch();
|
|
5568
5804
|
const overlayOpen = anyOverlayOpen(state);
|
|
5569
|
-
const doc =
|
|
5805
|
+
const doc = assertRichPresentationDocument(state.openDocument);
|
|
5570
5806
|
const { slideIndex } = props.screen;
|
|
5571
5807
|
const slide = doc.editor.slides()[slideIndex];
|
|
5572
5808
|
const shapes = slide === void 0 ? [] : slide.shapes();
|
|
@@ -5779,7 +6015,8 @@ function SlideDetailScreen(props) {
|
|
|
5779
6015
|
inverse: isSelected,
|
|
5780
6016
|
children: [
|
|
5781
6017
|
row.index + 1,
|
|
5782
|
-
".
|
|
6018
|
+
".",
|
|
6019
|
+
" ",
|
|
5783
6020
|
describeSlideFamilyShape({
|
|
5784
6021
|
text: row.text,
|
|
5785
6022
|
frame: row.frame
|
|
@@ -5875,7 +6112,7 @@ const CELL_WIDTH$1 = 16;
|
|
|
5875
6112
|
function SlideTableDetailScreen(props) {
|
|
5876
6113
|
const state = useAppState();
|
|
5877
6114
|
const dispatch = useAppDispatch();
|
|
5878
|
-
const doc =
|
|
6115
|
+
const doc = assertRichPresentationDocument(state.openDocument);
|
|
5879
6116
|
const { slideIndex, tableIndex } = props.screen;
|
|
5880
6117
|
const [cursor, setCursor] = useState({
|
|
5881
6118
|
row: 0,
|
|
@@ -5990,7 +6227,7 @@ function SlideTableDetailScreen(props) {
|
|
|
5990
6227
|
children: "This table has no rows."
|
|
5991
6228
|
}) : rows.map((row, rowIndex) => /* @__PURE__ */ jsx(Box, { children: row.cells.map((cell, columnIndex) => {
|
|
5992
6229
|
const isCursor = rowIndex === clampedRow && columnIndex === clampedColumn;
|
|
5993
|
-
const isAnchor = rowIndex === mergeAnchor?.row && columnIndex === mergeAnchor
|
|
6230
|
+
const isAnchor = rowIndex === mergeAnchor?.row && columnIndex === mergeAnchor.column;
|
|
5994
6231
|
return /* @__PURE__ */ jsx(Box, {
|
|
5995
6232
|
width: CELL_WIDTH$1,
|
|
5996
6233
|
borderStyle: "single",
|
|
@@ -6087,6 +6324,29 @@ function OdpSlideListScreen() {
|
|
|
6087
6324
|
return /* @__PURE__ */ jsx(SlideFamilySlideList, { adapter: buildOdpSlideFamilyAdapter(doc.editor) });
|
|
6088
6325
|
}
|
|
6089
6326
|
//#endregion
|
|
6327
|
+
//#region src/tui/screens/editors/doc/index.tsx
|
|
6328
|
+
function DocBodyListScreen() {
|
|
6329
|
+
const state = useAppState();
|
|
6330
|
+
const dispatch = useAppDispatch();
|
|
6331
|
+
const doc = state.openDocument;
|
|
6332
|
+
if (doc?.format !== "doc") return /* @__PURE__ */ jsxs(Text, {
|
|
6333
|
+
color: "red",
|
|
6334
|
+
children: [
|
|
6335
|
+
"DocBodyListScreen requires an open doc document, found",
|
|
6336
|
+
" ",
|
|
6337
|
+
doc === void 0 ? "no open document" : doc.format,
|
|
6338
|
+
"."
|
|
6339
|
+
]
|
|
6340
|
+
});
|
|
6341
|
+
const adapter = createParagraphFamilyAdapter({
|
|
6342
|
+
formatLabel: "doc",
|
|
6343
|
+
paragraphs: () => doc.editor.paragraphs(),
|
|
6344
|
+
tables: () => doc.editor.tables(),
|
|
6345
|
+
dispatch
|
|
6346
|
+
});
|
|
6347
|
+
return /* @__PURE__ */ jsx(ParagraphFamilyBodyList, { adapter });
|
|
6348
|
+
}
|
|
6349
|
+
//#endregion
|
|
6090
6350
|
//#region src/tui/screens/editors/ods/shared.ts
|
|
6091
6351
|
function odsDocument(state) {
|
|
6092
6352
|
const doc = state.openDocument;
|
|
@@ -6914,7 +7174,8 @@ function OdsSpreadsheetGridScreen() {
|
|
|
6914
7174
|
padCell(row.address, COMPACT_ADDRESS_WIDTH),
|
|
6915
7175
|
"[",
|
|
6916
7176
|
row.badge,
|
|
6917
|
-
"]
|
|
7177
|
+
"]",
|
|
7178
|
+
" ",
|
|
6918
7179
|
row.displayText
|
|
6919
7180
|
]
|
|
6920
7181
|
})
|
|
@@ -6931,7 +7192,7 @@ function OdsSpreadsheetGridScreen() {
|
|
|
6931
7192
|
children: [`${row + 1}`.padStart(4), " "]
|
|
6932
7193
|
}), visibleColumns.map((column) => {
|
|
6933
7194
|
const isCursor = row === clampedRow && column === clampedColumn;
|
|
6934
|
-
const isAnchor = row === mergeAnchor?.row && column === mergeAnchor
|
|
7195
|
+
const isAnchor = row === mergeAnchor?.row && column === mergeAnchor.column;
|
|
6935
7196
|
const cell = cells.get(cellKey(row, column));
|
|
6936
7197
|
return /* @__PURE__ */ jsx(Text, {
|
|
6937
7198
|
inverse: isCursor,
|
|
@@ -7015,51 +7276,491 @@ function OdsSpreadsheetGridScreen() {
|
|
|
7015
7276
|
});
|
|
7016
7277
|
}
|
|
7017
7278
|
//#endregion
|
|
7018
|
-
//#region src/tui/screens/editors/
|
|
7019
|
-
function
|
|
7279
|
+
//#region src/tui/screens/editors/ppt/index.tsx
|
|
7280
|
+
function pptDocument(state) {
|
|
7281
|
+
const doc = state.openDocument;
|
|
7282
|
+
if (doc?.format !== "ppt") throw new Error("A ppt screen rendered without an open ppt document; check the screen router in app.tsx.");
|
|
7283
|
+
return doc;
|
|
7284
|
+
}
|
|
7285
|
+
function PptSlideListScreen() {
|
|
7286
|
+
const doc = pptDocument(useAppState());
|
|
7287
|
+
return /* @__PURE__ */ jsx(SlideFamilySlideList, { adapter: buildPptSlideFamilyAdapter(doc.editor) });
|
|
7288
|
+
}
|
|
7289
|
+
const TEXTBOX_FIELDS = [
|
|
7290
|
+
{
|
|
7291
|
+
key: "xPt",
|
|
7292
|
+
label: "x (pt)",
|
|
7293
|
+
defaultValue: "40"
|
|
7294
|
+
},
|
|
7295
|
+
{
|
|
7296
|
+
key: "yPt",
|
|
7297
|
+
label: "y (pt)",
|
|
7298
|
+
defaultValue: "30"
|
|
7299
|
+
},
|
|
7300
|
+
{
|
|
7301
|
+
key: "widthPt",
|
|
7302
|
+
label: "width (pt)",
|
|
7303
|
+
defaultValue: "640"
|
|
7304
|
+
},
|
|
7305
|
+
{
|
|
7306
|
+
key: "heightPt",
|
|
7307
|
+
label: "height (pt)",
|
|
7308
|
+
defaultValue: "80"
|
|
7309
|
+
},
|
|
7310
|
+
{
|
|
7311
|
+
key: "text",
|
|
7312
|
+
label: "text",
|
|
7313
|
+
defaultValue: ""
|
|
7314
|
+
}
|
|
7315
|
+
];
|
|
7316
|
+
function PptSlideDetailScreen(props) {
|
|
7020
7317
|
const state = useAppState();
|
|
7021
7318
|
const dispatch = useAppDispatch();
|
|
7319
|
+
const doc = pptDocument(state);
|
|
7022
7320
|
const overlayOpen = anyOverlayOpen(state);
|
|
7023
|
-
const
|
|
7024
|
-
const [
|
|
7025
|
-
const [
|
|
7026
|
-
const
|
|
7027
|
-
const
|
|
7028
|
-
const
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7321
|
+
const slide = doc.editor.slides()[props.slideIndex];
|
|
7322
|
+
const [draft, setDraft] = useState(void 0);
|
|
7323
|
+
const [draftShape, setDraftShape] = useState(void 0);
|
|
7324
|
+
const [addingTextbox, setAddingTextbox] = useState(false);
|
|
7325
|
+
const shapes = slide?.shapes() ?? [];
|
|
7326
|
+
const rows = [...shapes.map((shape, index) => {
|
|
7327
|
+
const frame = shape.frame;
|
|
7328
|
+
return {
|
|
7329
|
+
kind: "shape",
|
|
7330
|
+
index,
|
|
7331
|
+
label: `${`${frame.xPt.toFixed(0)},${frame.yPt.toFixed(0)} ${frame.widthPt.toFixed(0)}x${frame.heightPt.toFixed(0)}pt`} ${shape.text === "" ? "(empty shape)" : shape.text}`
|
|
7332
|
+
};
|
|
7333
|
+
}), {
|
|
7334
|
+
kind: "notes",
|
|
7335
|
+
index: shapes.length,
|
|
7336
|
+
label: slide === void 0 || slide.notes === "" ? "Notes: (none)" : `Notes: ${slide.notes}`
|
|
7337
|
+
}];
|
|
7036
7338
|
const { selectedIndex } = useNavigationInput({
|
|
7037
|
-
itemCount,
|
|
7038
|
-
isActive:
|
|
7339
|
+
itemCount: rows.length,
|
|
7340
|
+
isActive: !overlayOpen && draft === void 0 && !addingTextbox,
|
|
7039
7341
|
onBack: () => {
|
|
7040
7342
|
dispatch({ type: "POP_SCREEN" });
|
|
7041
7343
|
},
|
|
7042
7344
|
onSelect: (index) => {
|
|
7043
|
-
|
|
7345
|
+
const row = rows[index];
|
|
7346
|
+
if (row === void 0) return;
|
|
7347
|
+
if (row.kind === "notes") {
|
|
7348
|
+
dispatch({
|
|
7349
|
+
type: "PUSH_SCREEN",
|
|
7350
|
+
screen: {
|
|
7351
|
+
kind: "notesEditor",
|
|
7352
|
+
slideIndex: props.slideIndex
|
|
7353
|
+
}
|
|
7354
|
+
});
|
|
7355
|
+
return;
|
|
7356
|
+
}
|
|
7357
|
+
setDraft(shapes[row.index]?.text ?? "");
|
|
7358
|
+
setDraftShape(row.index);
|
|
7044
7359
|
},
|
|
7045
7360
|
onAppend: () => {
|
|
7046
|
-
|
|
7361
|
+
setAddingTextbox(true);
|
|
7047
7362
|
}
|
|
7048
7363
|
});
|
|
7049
|
-
useInput((input
|
|
7050
|
-
if (
|
|
7051
|
-
type: "
|
|
7052
|
-
|
|
7053
|
-
|
|
7364
|
+
useInput((input) => {
|
|
7365
|
+
if (input === "n" && slide !== void 0) dispatch({
|
|
7366
|
+
type: "PUSH_SCREEN",
|
|
7367
|
+
screen: {
|
|
7368
|
+
kind: "notesEditor",
|
|
7369
|
+
slideIndex: props.slideIndex
|
|
7370
|
+
}
|
|
7054
7371
|
});
|
|
7055
|
-
}, { isActive:
|
|
7056
|
-
if (
|
|
7057
|
-
color: "red",
|
|
7058
|
-
children: "ListEditorScreen rendered outside a listEditor screen."
|
|
7059
|
-
});
|
|
7060
|
-
if (doc?.format !== "odt") return /* @__PURE__ */ jsx(Text, {
|
|
7372
|
+
}, { isActive: !overlayOpen && draft === void 0 && !addingTextbox });
|
|
7373
|
+
if (slide === void 0) return /* @__PURE__ */ jsxs(Text, {
|
|
7061
7374
|
color: "red",
|
|
7062
|
-
children:
|
|
7375
|
+
children: [
|
|
7376
|
+
"There is no slide at index ",
|
|
7377
|
+
props.slideIndex,
|
|
7378
|
+
" in this presentation."
|
|
7379
|
+
]
|
|
7380
|
+
});
|
|
7381
|
+
if (draft !== void 0 && draftShape !== void 0) return /* @__PURE__ */ jsxs(Box, {
|
|
7382
|
+
flexDirection: "column",
|
|
7383
|
+
children: [
|
|
7384
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
7385
|
+
bold: true,
|
|
7386
|
+
children: [
|
|
7387
|
+
"Shape ",
|
|
7388
|
+
draftShape,
|
|
7389
|
+
" text"
|
|
7390
|
+
]
|
|
7391
|
+
}),
|
|
7392
|
+
/* @__PURE__ */ jsx(TextField, {
|
|
7393
|
+
value: draft,
|
|
7394
|
+
isFocused: !overlayOpen,
|
|
7395
|
+
placeholder: "Shape text",
|
|
7396
|
+
onChange: setDraft,
|
|
7397
|
+
onSubmit: (value) => {
|
|
7398
|
+
dispatch({
|
|
7399
|
+
type: "SET_SHAPE_TEXT",
|
|
7400
|
+
containerIndex: props.slideIndex,
|
|
7401
|
+
shapeIndex: draftShape,
|
|
7402
|
+
text: value
|
|
7403
|
+
});
|
|
7404
|
+
setDraft(void 0);
|
|
7405
|
+
setDraftShape(void 0);
|
|
7406
|
+
},
|
|
7407
|
+
onCancel: () => {
|
|
7408
|
+
setDraft(void 0);
|
|
7409
|
+
setDraftShape(void 0);
|
|
7410
|
+
}
|
|
7411
|
+
}),
|
|
7412
|
+
/* @__PURE__ */ jsx(Text, {
|
|
7413
|
+
dimColor: true,
|
|
7414
|
+
children: "Enter to save, Esc to cancel"
|
|
7415
|
+
})
|
|
7416
|
+
]
|
|
7417
|
+
});
|
|
7418
|
+
if (addingTextbox) return /* @__PURE__ */ jsx(FieldWizard, {
|
|
7419
|
+
fields: TEXTBOX_FIELDS,
|
|
7420
|
+
onCancel: () => {
|
|
7421
|
+
setAddingTextbox(false);
|
|
7422
|
+
},
|
|
7423
|
+
onComplete: (values) => {
|
|
7424
|
+
dispatch({
|
|
7425
|
+
type: "ADD_TEXTBOX",
|
|
7426
|
+
containerIndex: props.slideIndex,
|
|
7427
|
+
frame: {
|
|
7428
|
+
xPt: parseNumberField(requireFieldValue(values, "xPt"), 40),
|
|
7429
|
+
yPt: parseNumberField(requireFieldValue(values, "yPt"), 30),
|
|
7430
|
+
widthPt: parseNumberField(requireFieldValue(values, "widthPt"), 640),
|
|
7431
|
+
heightPt: parseNumberField(requireFieldValue(values, "heightPt"), 80)
|
|
7432
|
+
},
|
|
7433
|
+
text: requireFieldValue(values, "text")
|
|
7434
|
+
});
|
|
7435
|
+
setAddingTextbox(false);
|
|
7436
|
+
}
|
|
7437
|
+
});
|
|
7438
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
7439
|
+
flexDirection: "column",
|
|
7440
|
+
children: [
|
|
7441
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
7442
|
+
bold: true,
|
|
7443
|
+
children: ["Slide ", props.slideIndex + 1]
|
|
7444
|
+
}),
|
|
7445
|
+
rows.map((row, index) => /* @__PURE__ */ jsx(Text, {
|
|
7446
|
+
color: index === selectedIndex ? "cyan" : void 0,
|
|
7447
|
+
inverse: index === selectedIndex,
|
|
7448
|
+
children: row.kind === "notes" ? row.label : ` ${row.label}`
|
|
7449
|
+
}, `${row.kind}:${row.index}`)),
|
|
7450
|
+
/* @__PURE__ */ jsx(Text, {
|
|
7451
|
+
dimColor: true,
|
|
7452
|
+
children: "Enter: edit text / notes n: notes a: add text box Esc: back"
|
|
7453
|
+
})
|
|
7454
|
+
]
|
|
7455
|
+
});
|
|
7456
|
+
}
|
|
7457
|
+
//#endregion
|
|
7458
|
+
//#region src/tui/screens/editors/xls/index.tsx
|
|
7459
|
+
function xlsDocument(state) {
|
|
7460
|
+
const doc = state.openDocument;
|
|
7461
|
+
if (doc?.format !== "xls") throw new Error("An xls screen rendered without an open xls document; check the screen router in app.tsx.");
|
|
7462
|
+
return doc;
|
|
7463
|
+
}
|
|
7464
|
+
function XlsSheetListScreen() {
|
|
7465
|
+
const state = useAppState();
|
|
7466
|
+
const dispatch = useAppDispatch();
|
|
7467
|
+
const doc = xlsDocument(state);
|
|
7468
|
+
const [draftName, setDraftName] = useState(void 0);
|
|
7469
|
+
const isAdding = draftName !== void 0;
|
|
7470
|
+
const isActive = !anyOverlayOpen(state) && !isAdding;
|
|
7471
|
+
const query = state.searchQuery.trim().toLowerCase();
|
|
7472
|
+
const rows = doc.editor.sheets().map((sheet, index) => ({
|
|
7473
|
+
index,
|
|
7474
|
+
name: sheet.name
|
|
7475
|
+
})).filter((row) => query.length === 0 || row.name.toLowerCase().includes(query));
|
|
7476
|
+
const commitAdd = (name) => {
|
|
7477
|
+
const trimmed = name.trim();
|
|
7478
|
+
if (trimmed.length === 0) {
|
|
7479
|
+
dispatch({
|
|
7480
|
+
type: "SET_STATUS",
|
|
7481
|
+
severity: "warning",
|
|
7482
|
+
text: "A sheet needs a name"
|
|
7483
|
+
});
|
|
7484
|
+
return;
|
|
7485
|
+
}
|
|
7486
|
+
dispatch({
|
|
7487
|
+
type: "ADD_SHEET",
|
|
7488
|
+
name: trimmed
|
|
7489
|
+
});
|
|
7490
|
+
setDraftName(void 0);
|
|
7491
|
+
};
|
|
7492
|
+
const { selectedIndex } = useNavigationInput({
|
|
7493
|
+
itemCount: rows.length,
|
|
7494
|
+
onSelect: (index) => {
|
|
7495
|
+
const row = rows[index];
|
|
7496
|
+
if (row === void 0) return;
|
|
7497
|
+
dispatch({
|
|
7498
|
+
type: "PUSH_SCREEN",
|
|
7499
|
+
screen: {
|
|
7500
|
+
kind: "spreadsheetGrid",
|
|
7501
|
+
sheetIndex: row.index
|
|
7502
|
+
}
|
|
7503
|
+
});
|
|
7504
|
+
},
|
|
7505
|
+
onBack: () => {
|
|
7506
|
+
dispatch({ type: "POP_SCREEN" });
|
|
7507
|
+
},
|
|
7508
|
+
onAppend: () => {
|
|
7509
|
+
setDraftName("");
|
|
7510
|
+
},
|
|
7511
|
+
isActive
|
|
7512
|
+
});
|
|
7513
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
7514
|
+
flexDirection: "column",
|
|
7515
|
+
children: [
|
|
7516
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
7517
|
+
bold: true,
|
|
7518
|
+
children: [
|
|
7519
|
+
"Sheets (",
|
|
7520
|
+
rows.length,
|
|
7521
|
+
")"
|
|
7522
|
+
]
|
|
7523
|
+
}),
|
|
7524
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
7525
|
+
items: rows,
|
|
7526
|
+
selectedIndex,
|
|
7527
|
+
emptyMessage: "This workbook has no sheets yet -- press 'a' to add one.",
|
|
7528
|
+
renderItem: (row, isSelected) => /* @__PURE__ */ jsx(Text, {
|
|
7529
|
+
color: isSelected ? "cyan" : void 0,
|
|
7530
|
+
inverse: isSelected,
|
|
7531
|
+
children: row.name
|
|
7532
|
+
})
|
|
7533
|
+
}),
|
|
7534
|
+
draftName === void 0 ? /* @__PURE__ */ jsx(Text, {
|
|
7535
|
+
dimColor: true,
|
|
7536
|
+
children: "Enter to open, a to add a sheet, Esc to go back"
|
|
7537
|
+
}) : /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
|
|
7538
|
+
color: "cyan",
|
|
7539
|
+
children: "New sheet name: "
|
|
7540
|
+
}), /* @__PURE__ */ jsx(TextField, {
|
|
7541
|
+
value: draftName,
|
|
7542
|
+
isFocused: !anyOverlayOpen(state),
|
|
7543
|
+
placeholder: "Sheet name",
|
|
7544
|
+
onChange: setDraftName,
|
|
7545
|
+
onSubmit: commitAdd,
|
|
7546
|
+
onCancel: () => {
|
|
7547
|
+
setDraftName(void 0);
|
|
7548
|
+
}
|
|
7549
|
+
})] })
|
|
7550
|
+
]
|
|
7551
|
+
});
|
|
7552
|
+
}
|
|
7553
|
+
function columnLetters(column) {
|
|
7554
|
+
let value = column;
|
|
7555
|
+
let letters = "";
|
|
7556
|
+
do {
|
|
7557
|
+
letters = String.fromCharCode(value % 26 + 65) + letters;
|
|
7558
|
+
value = Math.floor(value / 26) - 1;
|
|
7559
|
+
} while (value >= 0);
|
|
7560
|
+
return letters;
|
|
7561
|
+
}
|
|
7562
|
+
const GRID_ROWS = 10;
|
|
7563
|
+
const GRID_COLUMNS = 6;
|
|
7564
|
+
function XlsSpreadsheetGridScreen(props) {
|
|
7565
|
+
const state = useAppState();
|
|
7566
|
+
const dispatch = useAppDispatch();
|
|
7567
|
+
const doc = xlsDocument(state);
|
|
7568
|
+
const overlayOpen = anyOverlayOpen(state);
|
|
7569
|
+
const [compact, setCompact] = useState(false);
|
|
7570
|
+
const [cursor, setCursor] = useState({
|
|
7571
|
+
row: 0,
|
|
7572
|
+
column: 0
|
|
7573
|
+
});
|
|
7574
|
+
const [editSession, setEditSession] = useState(void 0);
|
|
7575
|
+
const editing = editSession !== void 0;
|
|
7576
|
+
const sheet = doc.editor.sheets()[props.sheetIndex];
|
|
7577
|
+
useInput((input, key) => {
|
|
7578
|
+
if (sheet === void 0) return;
|
|
7579
|
+
const move = (dRow, dColumn) => {
|
|
7580
|
+
setCursor((current) => ({
|
|
7581
|
+
row: Math.max(0, current.row + dRow),
|
|
7582
|
+
column: Math.max(0, current.column + dColumn)
|
|
7583
|
+
}));
|
|
7584
|
+
};
|
|
7585
|
+
if (key.escape) {
|
|
7586
|
+
if (editing) {
|
|
7587
|
+
setEditSession(void 0);
|
|
7588
|
+
return;
|
|
7589
|
+
}
|
|
7590
|
+
dispatch({ type: "POP_SCREEN" });
|
|
7591
|
+
return;
|
|
7592
|
+
}
|
|
7593
|
+
if (key.upArrow || input === "k") {
|
|
7594
|
+
move(-1, 0);
|
|
7595
|
+
return;
|
|
7596
|
+
}
|
|
7597
|
+
if (key.downArrow || input === "j") {
|
|
7598
|
+
move(1, 0);
|
|
7599
|
+
return;
|
|
7600
|
+
}
|
|
7601
|
+
if (key.leftArrow || input === "h") {
|
|
7602
|
+
move(0, -1);
|
|
7603
|
+
return;
|
|
7604
|
+
}
|
|
7605
|
+
if (key.rightArrow || input === "l") {
|
|
7606
|
+
move(0, 1);
|
|
7607
|
+
return;
|
|
7608
|
+
}
|
|
7609
|
+
if (key.return) {
|
|
7610
|
+
const existing = sheet.cells().find((cell) => cell.row === cursor.row && cell.column === cursor.column);
|
|
7611
|
+
setEditSession({
|
|
7612
|
+
seedText: existing?.displayText ?? "",
|
|
7613
|
+
seedKind: existing?.value.kind ?? "empty"
|
|
7614
|
+
});
|
|
7615
|
+
return;
|
|
7616
|
+
}
|
|
7617
|
+
if (input === "t") setCompact((value) => !value);
|
|
7618
|
+
}, { isActive: !overlayOpen });
|
|
7619
|
+
if (sheet === void 0) return /* @__PURE__ */ jsxs(Text, {
|
|
7620
|
+
color: "red",
|
|
7621
|
+
children: [
|
|
7622
|
+
"There is no sheet at index ",
|
|
7623
|
+
props.sheetIndex,
|
|
7624
|
+
" in this workbook."
|
|
7625
|
+
]
|
|
7626
|
+
});
|
|
7627
|
+
const cells = new Map(sheet.cells().map((cell) => [`${cell.row}:${cell.column}`, cell]));
|
|
7628
|
+
const cursorAddress = `${columnLetters(cursor.column)}${cursor.row + 1}`;
|
|
7629
|
+
const cursorCell = cells.get(`${cursor.row}:${cursor.column}`);
|
|
7630
|
+
if (compact) {
|
|
7631
|
+
const entries = sheet.cells();
|
|
7632
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
7633
|
+
flexDirection: "column",
|
|
7634
|
+
children: [
|
|
7635
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
7636
|
+
bold: true,
|
|
7637
|
+
children: [
|
|
7638
|
+
sheet.name,
|
|
7639
|
+
" -- non-empty cells (",
|
|
7640
|
+
entries.length,
|
|
7641
|
+
") -- 't' back to grid"
|
|
7642
|
+
]
|
|
7643
|
+
}),
|
|
7644
|
+
entries.length === 0 ? /* @__PURE__ */ jsx(Text, {
|
|
7645
|
+
dimColor: true,
|
|
7646
|
+
children: "No cells carry a value yet."
|
|
7647
|
+
}) : entries.slice(0, 200).map((cell) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
7648
|
+
columnLetters(cell.column),
|
|
7649
|
+
cell.row + 1,
|
|
7650
|
+
":",
|
|
7651
|
+
" ",
|
|
7652
|
+
cell.displayText === "" ? "(empty)" : cell.displayText
|
|
7653
|
+
] }, `${cell.row}:${cell.column}`)),
|
|
7654
|
+
/* @__PURE__ */ jsx(Text, {
|
|
7655
|
+
dimColor: true,
|
|
7656
|
+
children: "t: full grid Esc: back"
|
|
7657
|
+
})
|
|
7658
|
+
]
|
|
7659
|
+
});
|
|
7660
|
+
}
|
|
7661
|
+
const windowStartRow = Math.min(Math.max(0, cursor.row - 9), Math.max(0, cursor.row));
|
|
7662
|
+
const windowStartColumn = Math.min(Math.max(0, cursor.column - 5), Math.max(0, cursor.column));
|
|
7663
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
7664
|
+
flexDirection: "column",
|
|
7665
|
+
children: [
|
|
7666
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
7667
|
+
bold: true,
|
|
7668
|
+
children: [
|
|
7669
|
+
sheet.name,
|
|
7670
|
+
" (",
|
|
7671
|
+
cells.size,
|
|
7672
|
+
" cells)"
|
|
7673
|
+
]
|
|
7674
|
+
}),
|
|
7675
|
+
Array.from({ length: GRID_ROWS }, (_, r) => windowStartRow + r).map((row) => /* @__PURE__ */ jsx(Text, { children: Array.from({ length: GRID_COLUMNS }, (_, c) => windowStartColumn + c).map((column) => {
|
|
7676
|
+
const cell = cells.get(`${row}:${column}`);
|
|
7677
|
+
const isCursor = row === cursor.row && column === cursor.column;
|
|
7678
|
+
const padded = (cell?.displayText ?? "").slice(0, 12).padEnd(12, " ");
|
|
7679
|
+
return isCursor ? `[${padded.slice(0, 12)}]` : ` ${padded} `;
|
|
7680
|
+
}).join("") }, row)),
|
|
7681
|
+
editSession === void 0 ? /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsxs(Text, {
|
|
7682
|
+
color: "cyan",
|
|
7683
|
+
children: [cursorAddress, " "]
|
|
7684
|
+
}), /* @__PURE__ */ jsx(Text, { children: cursorCell === void 0 ? "(empty)" : cursorCell.displayText })] }) : /* @__PURE__ */ jsx(OdsCellEditor, {
|
|
7685
|
+
address: cursorAddress,
|
|
7686
|
+
initialText: editSession.seedText,
|
|
7687
|
+
initialKind: editSession.seedKind,
|
|
7688
|
+
isActive: !overlayOpen,
|
|
7689
|
+
onCommit: (value) => {
|
|
7690
|
+
dispatch({
|
|
7691
|
+
type: "SET_CELL_VALUE",
|
|
7692
|
+
sheetIndex: props.sheetIndex,
|
|
7693
|
+
row: cursor.row,
|
|
7694
|
+
column: cursor.column,
|
|
7695
|
+
value
|
|
7696
|
+
});
|
|
7697
|
+
setEditSession(void 0);
|
|
7698
|
+
},
|
|
7699
|
+
onCancel: () => {
|
|
7700
|
+
setEditSession(void 0);
|
|
7701
|
+
}
|
|
7702
|
+
}),
|
|
7703
|
+
/* @__PURE__ */ jsx(Text, {
|
|
7704
|
+
dimColor: true,
|
|
7705
|
+
children: "hjkl/arrows: move Enter: edit t: non-empty list Esc: back"
|
|
7706
|
+
})
|
|
7707
|
+
]
|
|
7708
|
+
});
|
|
7709
|
+
}
|
|
7710
|
+
//#endregion
|
|
7711
|
+
//#region src/tui/screens/editors/odt/list-editor.tsx
|
|
7712
|
+
function ListEditorScreen() {
|
|
7713
|
+
const state = useAppState();
|
|
7714
|
+
const dispatch = useAppDispatch();
|
|
7715
|
+
const overlayOpen = anyOverlayOpen(state);
|
|
7716
|
+
const [isAdding, setIsAdding] = useState(false);
|
|
7717
|
+
const [newItemText, setNewItemText] = useState("");
|
|
7718
|
+
const [editingIndex, setEditingIndex] = useState(void 0);
|
|
7719
|
+
const screen = currentScreen(state);
|
|
7720
|
+
const doc = paragraphFamilyDocument(state.openDocument);
|
|
7721
|
+
const blockIndex = screen.kind === "listEditor" ? screen.blockIndex : void 0;
|
|
7722
|
+
const list = blockIndex !== void 0 && doc?.format === "odt" ? doc.editor.lists()[blockIndex] : void 0;
|
|
7723
|
+
const items = list === void 0 ? [] : list.items();
|
|
7724
|
+
const rows = items.map((item, index) => ({
|
|
7725
|
+
item,
|
|
7726
|
+
index
|
|
7727
|
+
}));
|
|
7728
|
+
const itemCount = items.length;
|
|
7729
|
+
const isNavigationActive = !overlayOpen && !isAdding && editingIndex === void 0;
|
|
7730
|
+
const { selectedIndex } = useNavigationInput({
|
|
7731
|
+
itemCount,
|
|
7732
|
+
isActive: isNavigationActive,
|
|
7733
|
+
onBack: () => {
|
|
7734
|
+
dispatch({ type: "POP_SCREEN" });
|
|
7735
|
+
},
|
|
7736
|
+
onSelect: (index) => {
|
|
7737
|
+
setEditingIndex(index);
|
|
7738
|
+
},
|
|
7739
|
+
onAppend: () => {
|
|
7740
|
+
setIsAdding(true);
|
|
7741
|
+
}
|
|
7742
|
+
});
|
|
7743
|
+
useInput((input, key) => {
|
|
7744
|
+
if (key.tab || input === ">") {
|
|
7745
|
+
if (blockIndex === void 0) return;
|
|
7746
|
+
dispatch({
|
|
7747
|
+
type: "INDENT_LIST_ITEM",
|
|
7748
|
+
blockIndex,
|
|
7749
|
+
itemIndex: selectedIndex
|
|
7750
|
+
});
|
|
7751
|
+
} else if (input === "<") dispatch({
|
|
7752
|
+
type: "SET_STATUS",
|
|
7753
|
+
severity: "warning",
|
|
7754
|
+
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"
|
|
7755
|
+
});
|
|
7756
|
+
}, { isActive: isNavigationActive });
|
|
7757
|
+
if (screen.kind !== "listEditor") return /* @__PURE__ */ jsx(Text, {
|
|
7758
|
+
color: "red",
|
|
7759
|
+
children: "ListEditorScreen rendered outside a listEditor screen."
|
|
7760
|
+
});
|
|
7761
|
+
if (doc?.format !== "odt") return /* @__PURE__ */ jsx(Text, {
|
|
7762
|
+
color: "red",
|
|
7763
|
+
children: "ListEditorScreen requires an open odt document."
|
|
7063
7764
|
});
|
|
7064
7765
|
if (list === void 0) return /* @__PURE__ */ jsxs(Text, {
|
|
7065
7766
|
color: "red",
|
|
@@ -7125,7 +7826,8 @@ function ListEditorScreen() {
|
|
|
7125
7826
|
inverse: isSelected,
|
|
7126
7827
|
children: [
|
|
7127
7828
|
row.index + 1,
|
|
7128
|
-
".
|
|
7829
|
+
".",
|
|
7830
|
+
" ",
|
|
7129
7831
|
trimmed.length === 0 ? "(empty)" : row.item.text
|
|
7130
7832
|
]
|
|
7131
7833
|
});
|
|
@@ -7154,7 +7856,7 @@ function ListEditorScreen() {
|
|
|
7154
7856
|
}
|
|
7155
7857
|
})] }) : /* @__PURE__ */ jsx(Text, {
|
|
7156
7858
|
dimColor: true,
|
|
7157
|
-
children: "Enter to edit an item, a to add, Esc back"
|
|
7859
|
+
children: "Enter to edit an item, a to add, Tab/> to indent, Esc back"
|
|
7158
7860
|
})
|
|
7159
7861
|
]
|
|
7160
7862
|
});
|
|
@@ -7168,7 +7870,8 @@ function OdtBodyListScreen() {
|
|
|
7168
7870
|
if (doc?.format !== "odt") return /* @__PURE__ */ jsxs(Text, {
|
|
7169
7871
|
color: "red",
|
|
7170
7872
|
children: [
|
|
7171
|
-
"OdtBodyListScreen requires an open odt document, found
|
|
7873
|
+
"OdtBodyListScreen requires an open odt document, found",
|
|
7874
|
+
" ",
|
|
7172
7875
|
doc === void 0 ? "no open document" : doc.format,
|
|
7173
7876
|
"."
|
|
7174
7877
|
]
|
|
@@ -7185,7 +7888,7 @@ function OdtBodyListScreen() {
|
|
|
7185
7888
|
//#endregion
|
|
7186
7889
|
//#region src/tui/screens/editors/pdf/shared.ts
|
|
7187
7890
|
function requirePdfDocument(openDocument) {
|
|
7188
|
-
if (openDocument?.format !== "pdf" && openDocument?.format !== "xlsx" && openDocument?.format !== "csv" && openDocument?.format !== "svg") throw new Error("A PDF inspection screen rendered without an open PDF, xlsx, csv, or
|
|
7891
|
+
if (openDocument?.format !== "pdf" && openDocument?.format !== "xlsx" && openDocument?.format !== "csv" && openDocument?.format !== "svg" && openDocument?.format !== "rtf" && openDocument?.format !== "wpd" && openDocument?.format !== "epub") throw new Error("A PDF inspection screen rendered without an open PDF, xlsx, csv, svg, rtf, wpd, or epub document; the app router only reaches this screen group from pdfPageList, which is only ever the root screen of one of those formats.");
|
|
7189
7892
|
return openDocument;
|
|
7190
7893
|
}
|
|
7191
7894
|
function isEditablePdfDocument(doc) {
|
|
@@ -7374,9 +8077,15 @@ function fieldsFor(item) {
|
|
|
7374
8077
|
fields.push(["Position", formatPoint(item.xPt, item.yPt)]);
|
|
7375
8078
|
fields.push(["Size", formatSize(item.widthPt, item.heightPt)]);
|
|
7376
8079
|
break;
|
|
8080
|
+
case "internalLink":
|
|
8081
|
+
fields.push(["Destination", item.destination]);
|
|
8082
|
+
if (item.title !== void 0) fields.push(["Title", item.title]);
|
|
8083
|
+
fields.push(["Position", formatPoint(item.xPt, item.yPt)]);
|
|
8084
|
+
fields.push(["Size", formatSize(item.widthPt, item.heightPt)]);
|
|
8085
|
+
break;
|
|
7377
8086
|
default: return item;
|
|
7378
8087
|
}
|
|
7379
|
-
if (item.sourcePath !== void 0) fields.push(["Source path", item.sourcePath]);
|
|
8088
|
+
if (item.kind !== "internalLink" && item.sourcePath !== void 0) fields.push(["Source path", item.sourcePath]);
|
|
7380
8089
|
return fields;
|
|
7381
8090
|
}
|
|
7382
8091
|
function ReadOnlyItemDetail(props) {
|
|
@@ -7412,34 +8121,42 @@ function buildFrameRows(frame, onFrameChange) {
|
|
|
7412
8121
|
{
|
|
7413
8122
|
label: `X: ${formatPt(frame.xPt)}pt`,
|
|
7414
8123
|
currentValue: String(frame.xPt),
|
|
7415
|
-
commit: (raw) =>
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
8124
|
+
commit: (raw) => {
|
|
8125
|
+
onFrameChange({
|
|
8126
|
+
...frame,
|
|
8127
|
+
xPt: parseNumberField(raw, frame.xPt)
|
|
8128
|
+
});
|
|
8129
|
+
}
|
|
7419
8130
|
},
|
|
7420
8131
|
{
|
|
7421
8132
|
label: `Y: ${formatPt(frame.yPt)}pt`,
|
|
7422
8133
|
currentValue: String(frame.yPt),
|
|
7423
|
-
commit: (raw) =>
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
8134
|
+
commit: (raw) => {
|
|
8135
|
+
onFrameChange({
|
|
8136
|
+
...frame,
|
|
8137
|
+
yPt: parseNumberField(raw, frame.yPt)
|
|
8138
|
+
});
|
|
8139
|
+
}
|
|
7427
8140
|
},
|
|
7428
8141
|
{
|
|
7429
8142
|
label: `Width: ${formatPt(frame.widthPt)}pt`,
|
|
7430
8143
|
currentValue: String(frame.widthPt),
|
|
7431
|
-
commit: (raw) =>
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
8144
|
+
commit: (raw) => {
|
|
8145
|
+
onFrameChange({
|
|
8146
|
+
...frame,
|
|
8147
|
+
widthPt: parseNumberField(raw, frame.widthPt)
|
|
8148
|
+
});
|
|
8149
|
+
}
|
|
7435
8150
|
},
|
|
7436
8151
|
{
|
|
7437
8152
|
label: `Height: ${formatPt(frame.heightPt)}pt`,
|
|
7438
8153
|
currentValue: String(frame.heightPt),
|
|
7439
|
-
commit: (raw) =>
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
8154
|
+
commit: (raw) => {
|
|
8155
|
+
onFrameChange({
|
|
8156
|
+
...frame,
|
|
8157
|
+
heightPt: parseNumberField(raw, frame.heightPt)
|
|
8158
|
+
});
|
|
8159
|
+
}
|
|
7443
8160
|
}
|
|
7444
8161
|
];
|
|
7445
8162
|
}
|
|
@@ -7447,11 +8164,15 @@ function buildFillStrokeRows(fill, stroke, onFillChange, onStrokeChange) {
|
|
|
7447
8164
|
return [{
|
|
7448
8165
|
label: `Fill: ${fill === void 0 ? "none" : formatColor(fill)}`,
|
|
7449
8166
|
currentValue: fill === void 0 ? "" : `${fill.r} ${fill.g} ${fill.b}`,
|
|
7450
|
-
commit: (raw) =>
|
|
8167
|
+
commit: (raw) => {
|
|
8168
|
+
onFillChange(parseColorField(raw));
|
|
8169
|
+
}
|
|
7451
8170
|
}, {
|
|
7452
8171
|
label: `Stroke: ${stroke === void 0 ? "none" : formatStroke(stroke)}`,
|
|
7453
8172
|
currentValue: stroke === void 0 ? "" : `${stroke.color.r} ${stroke.color.g} ${stroke.color.b} ${stroke.widthPt}`,
|
|
7454
|
-
commit: (raw) =>
|
|
8173
|
+
commit: (raw) => {
|
|
8174
|
+
onStrokeChange(parseStrokeField(raw));
|
|
8175
|
+
}
|
|
7455
8176
|
}];
|
|
7456
8177
|
}
|
|
7457
8178
|
function buildTextRows(item, pageIndex, itemIndex, dispatch) {
|
|
@@ -7459,34 +8180,40 @@ function buildTextRows(item, pageIndex, itemIndex, dispatch) {
|
|
|
7459
8180
|
{
|
|
7460
8181
|
label: `Text: ${item.text}`,
|
|
7461
8182
|
currentValue: item.text,
|
|
7462
|
-
commit: (raw) =>
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
8183
|
+
commit: (raw) => {
|
|
8184
|
+
dispatch({
|
|
8185
|
+
type: "SET_PDF_TEXT_TEXT",
|
|
8186
|
+
pageIndex,
|
|
8187
|
+
itemIndex,
|
|
8188
|
+
text: raw
|
|
8189
|
+
});
|
|
8190
|
+
}
|
|
7468
8191
|
},
|
|
7469
8192
|
{
|
|
7470
8193
|
label: `X: ${formatPt(item.xPt)}pt`,
|
|
7471
8194
|
currentValue: String(item.xPt),
|
|
7472
|
-
commit: (raw) =>
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
8195
|
+
commit: (raw) => {
|
|
8196
|
+
dispatch({
|
|
8197
|
+
type: "SET_PDF_TEXT_POSITION",
|
|
8198
|
+
pageIndex,
|
|
8199
|
+
itemIndex,
|
|
8200
|
+
xPt: parseNumberField(raw, item.xPt),
|
|
8201
|
+
yPt: item.yPt
|
|
8202
|
+
});
|
|
8203
|
+
}
|
|
7479
8204
|
},
|
|
7480
8205
|
{
|
|
7481
8206
|
label: `Y: ${formatPt(item.yPt)}pt`,
|
|
7482
8207
|
currentValue: String(item.yPt),
|
|
7483
|
-
commit: (raw) =>
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
8208
|
+
commit: (raw) => {
|
|
8209
|
+
dispatch({
|
|
8210
|
+
type: "SET_PDF_TEXT_POSITION",
|
|
8211
|
+
pageIndex,
|
|
8212
|
+
itemIndex,
|
|
8213
|
+
xPt: item.xPt,
|
|
8214
|
+
yPt: parseNumberField(raw, item.yPt)
|
|
8215
|
+
});
|
|
8216
|
+
}
|
|
7490
8217
|
},
|
|
7491
8218
|
{
|
|
7492
8219
|
label: `Font family: ${item.font.family}`,
|
|
@@ -7507,181 +8234,219 @@ function buildTextRows(item, pageIndex, itemIndex, dispatch) {
|
|
|
7507
8234
|
{
|
|
7508
8235
|
label: `Font weight: ${item.font.weight} (Enter to toggle)`,
|
|
7509
8236
|
currentValue: "",
|
|
7510
|
-
activate: () =>
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
8237
|
+
activate: () => {
|
|
8238
|
+
dispatch({
|
|
8239
|
+
type: "SET_PDF_TEXT_FONT",
|
|
8240
|
+
pageIndex,
|
|
8241
|
+
itemIndex,
|
|
8242
|
+
font: {
|
|
8243
|
+
...item.font,
|
|
8244
|
+
weight: item.font.weight === "bold" ? "normal" : "bold"
|
|
8245
|
+
}
|
|
8246
|
+
});
|
|
8247
|
+
}
|
|
7519
8248
|
},
|
|
7520
8249
|
{
|
|
7521
8250
|
label: `Font style: ${item.font.style} (Enter to toggle)`,
|
|
7522
8251
|
currentValue: "",
|
|
7523
|
-
activate: () =>
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
8252
|
+
activate: () => {
|
|
8253
|
+
dispatch({
|
|
8254
|
+
type: "SET_PDF_TEXT_FONT",
|
|
8255
|
+
pageIndex,
|
|
8256
|
+
itemIndex,
|
|
8257
|
+
font: {
|
|
8258
|
+
...item.font,
|
|
8259
|
+
style: item.font.style === "italic" ? "normal" : "italic"
|
|
8260
|
+
}
|
|
8261
|
+
});
|
|
8262
|
+
}
|
|
7532
8263
|
},
|
|
7533
8264
|
{
|
|
7534
8265
|
label: `Size: ${item.sizePt}pt`,
|
|
7535
8266
|
currentValue: String(item.sizePt),
|
|
7536
|
-
commit: (raw) =>
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
8267
|
+
commit: (raw) => {
|
|
8268
|
+
dispatch({
|
|
8269
|
+
type: "SET_PDF_TEXT_SIZE",
|
|
8270
|
+
pageIndex,
|
|
8271
|
+
itemIndex,
|
|
8272
|
+
sizePt: parseNumberField(raw, item.sizePt)
|
|
8273
|
+
});
|
|
8274
|
+
}
|
|
7542
8275
|
},
|
|
7543
8276
|
{
|
|
7544
8277
|
label: `Colour: ${formatColor(item.color)}`,
|
|
7545
8278
|
currentValue: `${item.color.r} ${item.color.g} ${item.color.b}`,
|
|
7546
|
-
commit: (raw) =>
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
8279
|
+
commit: (raw) => {
|
|
8280
|
+
dispatch({
|
|
8281
|
+
type: "SET_PDF_TEXT_COLOR",
|
|
8282
|
+
pageIndex,
|
|
8283
|
+
itemIndex,
|
|
8284
|
+
color: parseRequiredColorField(raw, item.color)
|
|
8285
|
+
});
|
|
8286
|
+
}
|
|
7552
8287
|
},
|
|
7553
8288
|
{
|
|
7554
8289
|
label: `Width: ${item.widthPt === void 0 ? "unset" : `${item.widthPt}pt`}`,
|
|
7555
8290
|
currentValue: item.widthPt === void 0 ? "" : String(item.widthPt),
|
|
7556
|
-
commit: (raw) =>
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
8291
|
+
commit: (raw) => {
|
|
8292
|
+
dispatch({
|
|
8293
|
+
type: "SET_PDF_TEXT_WIDTH",
|
|
8294
|
+
pageIndex,
|
|
8295
|
+
itemIndex,
|
|
8296
|
+
widthPt: parseOptionalNumberField(raw)
|
|
8297
|
+
});
|
|
8298
|
+
}
|
|
7562
8299
|
},
|
|
7563
8300
|
{
|
|
7564
8301
|
label: `Rotation: ${item.rotationDeg === void 0 ? "unset" : `${item.rotationDeg}°`}`,
|
|
7565
8302
|
currentValue: item.rotationDeg === void 0 ? "" : String(item.rotationDeg),
|
|
7566
|
-
commit: (raw) =>
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
8303
|
+
commit: (raw) => {
|
|
8304
|
+
dispatch({
|
|
8305
|
+
type: "SET_PDF_TEXT_ROTATION",
|
|
8306
|
+
pageIndex,
|
|
8307
|
+
itemIndex,
|
|
8308
|
+
rotationDeg: parseOptionalNumberField(raw)
|
|
8309
|
+
});
|
|
8310
|
+
}
|
|
7572
8311
|
},
|
|
7573
8312
|
{
|
|
7574
8313
|
label: `Underline: ${item.underline === true ? "yes" : "no"} (Enter to toggle)`,
|
|
7575
8314
|
currentValue: "",
|
|
7576
|
-
activate: () =>
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
8315
|
+
activate: () => {
|
|
8316
|
+
dispatch({
|
|
8317
|
+
type: "TOGGLE_PDF_TEXT_UNDERLINE",
|
|
8318
|
+
pageIndex,
|
|
8319
|
+
itemIndex
|
|
8320
|
+
});
|
|
8321
|
+
}
|
|
7581
8322
|
}
|
|
7582
8323
|
];
|
|
7583
8324
|
}
|
|
7584
8325
|
function buildRectRows(item, pageIndex, itemIndex, dispatch) {
|
|
7585
|
-
return [...buildFrameRows(item, (frame) =>
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
8326
|
+
return [...buildFrameRows(item, (frame) => {
|
|
8327
|
+
dispatch({
|
|
8328
|
+
type: "SET_PDF_RECT_FRAME",
|
|
8329
|
+
pageIndex,
|
|
8330
|
+
itemIndex,
|
|
8331
|
+
...frame
|
|
8332
|
+
});
|
|
8333
|
+
}), ...buildFillStrokeRows(item.fill, item.stroke, (fill) => {
|
|
8334
|
+
dispatch({
|
|
8335
|
+
type: "SET_PDF_RECT_FILL",
|
|
8336
|
+
pageIndex,
|
|
8337
|
+
itemIndex,
|
|
8338
|
+
fill
|
|
8339
|
+
});
|
|
8340
|
+
}, (stroke) => {
|
|
8341
|
+
dispatch({
|
|
8342
|
+
type: "SET_PDF_RECT_STROKE",
|
|
8343
|
+
pageIndex,
|
|
8344
|
+
itemIndex,
|
|
8345
|
+
stroke
|
|
8346
|
+
});
|
|
8347
|
+
})];
|
|
7601
8348
|
}
|
|
7602
8349
|
function buildEllipseRows(item, pageIndex, itemIndex, dispatch) {
|
|
7603
|
-
return [...buildFrameRows(item, (frame) =>
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
8350
|
+
return [...buildFrameRows(item, (frame) => {
|
|
8351
|
+
dispatch({
|
|
8352
|
+
type: "SET_PDF_ELLIPSE_FRAME",
|
|
8353
|
+
pageIndex,
|
|
8354
|
+
itemIndex,
|
|
8355
|
+
...frame
|
|
8356
|
+
});
|
|
8357
|
+
}), ...buildFillStrokeRows(item.fill, item.stroke, (fill) => {
|
|
8358
|
+
dispatch({
|
|
8359
|
+
type: "SET_PDF_ELLIPSE_FILL",
|
|
8360
|
+
pageIndex,
|
|
8361
|
+
itemIndex,
|
|
8362
|
+
fill
|
|
8363
|
+
});
|
|
8364
|
+
}, (stroke) => {
|
|
8365
|
+
dispatch({
|
|
8366
|
+
type: "SET_PDF_ELLIPSE_STROKE",
|
|
8367
|
+
pageIndex,
|
|
8368
|
+
itemIndex,
|
|
8369
|
+
stroke
|
|
8370
|
+
});
|
|
8371
|
+
})];
|
|
7619
8372
|
}
|
|
7620
8373
|
function buildLineRows(item, pageIndex, itemIndex, dispatch) {
|
|
7621
8374
|
return [
|
|
7622
8375
|
{
|
|
7623
8376
|
label: `From X: ${formatPt(item.x1Pt)}pt`,
|
|
7624
8377
|
currentValue: String(item.x1Pt),
|
|
7625
|
-
commit: (raw) =>
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
8378
|
+
commit: (raw) => {
|
|
8379
|
+
dispatch({
|
|
8380
|
+
type: "SET_PDF_LINE_FROM",
|
|
8381
|
+
pageIndex,
|
|
8382
|
+
itemIndex,
|
|
8383
|
+
x1Pt: parseNumberField(raw, item.x1Pt),
|
|
8384
|
+
y1Pt: item.y1Pt
|
|
8385
|
+
});
|
|
8386
|
+
}
|
|
7632
8387
|
},
|
|
7633
8388
|
{
|
|
7634
8389
|
label: `From Y: ${formatPt(item.y1Pt)}pt`,
|
|
7635
8390
|
currentValue: String(item.y1Pt),
|
|
7636
|
-
commit: (raw) =>
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
8391
|
+
commit: (raw) => {
|
|
8392
|
+
dispatch({
|
|
8393
|
+
type: "SET_PDF_LINE_FROM",
|
|
8394
|
+
pageIndex,
|
|
8395
|
+
itemIndex,
|
|
8396
|
+
x1Pt: item.x1Pt,
|
|
8397
|
+
y1Pt: parseNumberField(raw, item.y1Pt)
|
|
8398
|
+
});
|
|
8399
|
+
}
|
|
7643
8400
|
},
|
|
7644
8401
|
{
|
|
7645
8402
|
label: `To X: ${formatPt(item.x2Pt)}pt`,
|
|
7646
8403
|
currentValue: String(item.x2Pt),
|
|
7647
|
-
commit: (raw) =>
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
8404
|
+
commit: (raw) => {
|
|
8405
|
+
dispatch({
|
|
8406
|
+
type: "SET_PDF_LINE_TO",
|
|
8407
|
+
pageIndex,
|
|
8408
|
+
itemIndex,
|
|
8409
|
+
x2Pt: parseNumberField(raw, item.x2Pt),
|
|
8410
|
+
y2Pt: item.y2Pt
|
|
8411
|
+
});
|
|
8412
|
+
}
|
|
7654
8413
|
},
|
|
7655
8414
|
{
|
|
7656
8415
|
label: `To Y: ${formatPt(item.y2Pt)}pt`,
|
|
7657
8416
|
currentValue: String(item.y2Pt),
|
|
7658
|
-
commit: (raw) =>
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
8417
|
+
commit: (raw) => {
|
|
8418
|
+
dispatch({
|
|
8419
|
+
type: "SET_PDF_LINE_TO",
|
|
8420
|
+
pageIndex,
|
|
8421
|
+
itemIndex,
|
|
8422
|
+
x2Pt: item.x2Pt,
|
|
8423
|
+
y2Pt: parseNumberField(raw, item.y2Pt)
|
|
8424
|
+
});
|
|
8425
|
+
}
|
|
7665
8426
|
},
|
|
7666
8427
|
{
|
|
7667
8428
|
label: `Colour: ${formatColor(item.color)}`,
|
|
7668
8429
|
currentValue: `${item.color.r} ${item.color.g} ${item.color.b}`,
|
|
7669
|
-
commit: (raw) =>
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
8430
|
+
commit: (raw) => {
|
|
8431
|
+
dispatch({
|
|
8432
|
+
type: "SET_PDF_LINE_COLOR",
|
|
8433
|
+
pageIndex,
|
|
8434
|
+
itemIndex,
|
|
8435
|
+
color: parseRequiredColorField(raw, item.color)
|
|
8436
|
+
});
|
|
8437
|
+
}
|
|
7675
8438
|
},
|
|
7676
8439
|
{
|
|
7677
8440
|
label: `Width: ${item.widthPt}pt`,
|
|
7678
8441
|
currentValue: String(item.widthPt),
|
|
7679
|
-
commit: (raw) =>
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
8442
|
+
commit: (raw) => {
|
|
8443
|
+
dispatch({
|
|
8444
|
+
type: "SET_PDF_LINE_WIDTH",
|
|
8445
|
+
pageIndex,
|
|
8446
|
+
itemIndex,
|
|
8447
|
+
widthPt: Math.max(parseNumberField(raw, item.widthPt), Number.EPSILON)
|
|
8448
|
+
});
|
|
8449
|
+
}
|
|
7685
8450
|
}
|
|
7686
8451
|
];
|
|
7687
8452
|
}
|
|
@@ -7689,41 +8454,51 @@ function buildPathRows(item, pageIndex, itemIndex, dispatch) {
|
|
|
7689
8454
|
return [{
|
|
7690
8455
|
label: `Fill rule: ${item.fillRule ?? "nonzero (default)"} (Enter to cycle)`,
|
|
7691
8456
|
currentValue: "",
|
|
7692
|
-
activate: () =>
|
|
7693
|
-
|
|
8457
|
+
activate: () => {
|
|
8458
|
+
dispatch({
|
|
8459
|
+
type: "SET_PDF_PATH_FILL_RULE",
|
|
8460
|
+
pageIndex,
|
|
8461
|
+
itemIndex,
|
|
8462
|
+
fillRule: item.fillRule === "evenodd" ? void 0 : item.fillRule === "nonzero" ? "evenodd" : "nonzero"
|
|
8463
|
+
});
|
|
8464
|
+
}
|
|
8465
|
+
}, ...buildFillStrokeRows(item.fill, item.stroke, (fill) => {
|
|
8466
|
+
dispatch({
|
|
8467
|
+
type: "SET_PDF_PATH_FILL",
|
|
7694
8468
|
pageIndex,
|
|
7695
8469
|
itemIndex,
|
|
7696
|
-
|
|
7697
|
-
})
|
|
7698
|
-
},
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
itemIndex,
|
|
7707
|
-
stroke
|
|
7708
|
-
}))];
|
|
8470
|
+
fill
|
|
8471
|
+
});
|
|
8472
|
+
}, (stroke) => {
|
|
8473
|
+
dispatch({
|
|
8474
|
+
type: "SET_PDF_PATH_STROKE",
|
|
8475
|
+
pageIndex,
|
|
8476
|
+
itemIndex,
|
|
8477
|
+
stroke
|
|
8478
|
+
});
|
|
8479
|
+
})];
|
|
7709
8480
|
}
|
|
7710
8481
|
function buildImageRows(item, pageIndex, itemIndex, dispatch, onReplaceImage) {
|
|
7711
8482
|
return [
|
|
7712
|
-
...buildFrameRows(item, (frame) =>
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
8483
|
+
...buildFrameRows(item, (frame) => {
|
|
8484
|
+
dispatch({
|
|
8485
|
+
type: "SET_PDF_IMAGE_FRAME",
|
|
8486
|
+
pageIndex,
|
|
8487
|
+
itemIndex,
|
|
8488
|
+
...frame
|
|
8489
|
+
});
|
|
8490
|
+
}),
|
|
7718
8491
|
{
|
|
7719
8492
|
label: `Rotation: ${item.rotationDeg === void 0 ? "unset" : `${item.rotationDeg}°`}`,
|
|
7720
8493
|
currentValue: item.rotationDeg === void 0 ? "" : String(item.rotationDeg),
|
|
7721
|
-
commit: (raw) =>
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
8494
|
+
commit: (raw) => {
|
|
8495
|
+
dispatch({
|
|
8496
|
+
type: "SET_PDF_IMAGE_ROTATION",
|
|
8497
|
+
pageIndex,
|
|
8498
|
+
itemIndex,
|
|
8499
|
+
rotationDeg: parseOptionalNumberField(raw)
|
|
8500
|
+
});
|
|
8501
|
+
}
|
|
7727
8502
|
},
|
|
7728
8503
|
{
|
|
7729
8504
|
label: "Replace image...",
|
|
@@ -7736,18 +8511,43 @@ function buildLinkRows(item, pageIndex, itemIndex, dispatch) {
|
|
|
7736
8511
|
return [{
|
|
7737
8512
|
label: `URI: ${item.uri}`,
|
|
7738
8513
|
currentValue: item.uri,
|
|
7739
|
-
commit: (raw) =>
|
|
7740
|
-
|
|
8514
|
+
commit: (raw) => {
|
|
8515
|
+
dispatch({
|
|
8516
|
+
type: "SET_PDF_LINK_URI",
|
|
8517
|
+
pageIndex,
|
|
8518
|
+
itemIndex,
|
|
8519
|
+
uri: raw
|
|
8520
|
+
});
|
|
8521
|
+
}
|
|
8522
|
+
}, ...buildFrameRows(item, (frame) => {
|
|
8523
|
+
dispatch({
|
|
8524
|
+
type: "SET_PDF_LINK_FRAME",
|
|
7741
8525
|
pageIndex,
|
|
7742
8526
|
itemIndex,
|
|
7743
|
-
|
|
7744
|
-
})
|
|
7745
|
-
}
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
8527
|
+
...frame
|
|
8528
|
+
});
|
|
8529
|
+
})];
|
|
8530
|
+
}
|
|
8531
|
+
function buildInternalLinkRows(item, pageIndex, itemIndex, dispatch) {
|
|
8532
|
+
return [{
|
|
8533
|
+
label: `Destination: ${item.destination}`,
|
|
8534
|
+
currentValue: item.destination,
|
|
8535
|
+
commit: (raw) => {
|
|
8536
|
+
dispatch({
|
|
8537
|
+
type: "SET_PDF_INTERNAL_LINK_DESTINATION",
|
|
8538
|
+
pageIndex,
|
|
8539
|
+
itemIndex,
|
|
8540
|
+
destination: raw
|
|
8541
|
+
});
|
|
8542
|
+
}
|
|
8543
|
+
}, ...buildFrameRows(item, (frame) => {
|
|
8544
|
+
dispatch({
|
|
8545
|
+
type: "SET_PDF_INTERNAL_LINK_FRAME",
|
|
8546
|
+
pageIndex,
|
|
8547
|
+
itemIndex,
|
|
8548
|
+
...frame
|
|
8549
|
+
});
|
|
8550
|
+
})];
|
|
7751
8551
|
}
|
|
7752
8552
|
function buildRowsFor(item, pageIndex, itemIndex, dispatch, onReplaceImage) {
|
|
7753
8553
|
switch (item.kind) {
|
|
@@ -7758,6 +8558,7 @@ function buildRowsFor(item, pageIndex, itemIndex, dispatch, onReplaceImage) {
|
|
|
7758
8558
|
case "path": return buildPathRows(item, pageIndex, itemIndex, dispatch);
|
|
7759
8559
|
case "image": return buildImageRows(item, pageIndex, itemIndex, dispatch, onReplaceImage);
|
|
7760
8560
|
case "link": return buildLinkRows(item, pageIndex, itemIndex, dispatch);
|
|
8561
|
+
case "internalLink": return buildInternalLinkRows(item, pageIndex, itemIndex, dispatch);
|
|
7761
8562
|
}
|
|
7762
8563
|
}
|
|
7763
8564
|
function pathSummary(item) {
|
|
@@ -7797,7 +8598,9 @@ function EditableItemDetail(props) {
|
|
|
7797
8598
|
const [draft, setDraft] = useState("");
|
|
7798
8599
|
const [replacingImage, setReplacingImage] = useState(false);
|
|
7799
8600
|
const item = doc.editor.page(pageIndex)?.items()[itemIndex];
|
|
7800
|
-
const rows = item === void 0 ? [] : buildRowsFor(item, pageIndex, itemIndex, dispatch, () =>
|
|
8601
|
+
const rows = item === void 0 ? [] : buildRowsFor(item, pageIndex, itemIndex, dispatch, () => {
|
|
8602
|
+
setReplacingImage(true);
|
|
8603
|
+
});
|
|
7801
8604
|
const { selectedIndex } = useNavigationInput({
|
|
7802
8605
|
itemCount: rows.length,
|
|
7803
8606
|
isActive: props.isActive && editingField === void 0 && !replacingImage,
|
|
@@ -7972,6 +8775,7 @@ function previewFor(item) {
|
|
|
7972
8775
|
switch (item.kind) {
|
|
7973
8776
|
case "text": return truncate(item.text, TEXT_PREVIEW_MAX_CHARS);
|
|
7974
8777
|
case "link": return item.uri;
|
|
8778
|
+
case "internalLink": return `→ ${item.destination}`;
|
|
7975
8779
|
case "image":
|
|
7976
8780
|
case "rect":
|
|
7977
8781
|
case "ellipse": return formatSize(item.widthPt, item.heightPt);
|
|
@@ -8748,7 +9552,7 @@ function LauncherScreen() {
|
|
|
8748
9552
|
}),
|
|
8749
9553
|
/* @__PURE__ */ jsx(Text, {
|
|
8750
9554
|
dimColor: true,
|
|
8751
|
-
children: "A terminal editor for docx, pptx, odt, odp, ods, odg, markdown, odb and pdf -- xlsx, csv and
|
|
9555
|
+
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."
|
|
8752
9556
|
}),
|
|
8753
9557
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
8754
9558
|
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
@@ -8796,6 +9600,22 @@ const CREATABLE_FORMATS = [
|
|
|
8796
9600
|
{
|
|
8797
9601
|
format: "odg",
|
|
8798
9602
|
description: "Vector drawing (OpenDocument)"
|
|
9603
|
+
},
|
|
9604
|
+
{
|
|
9605
|
+
format: "doc",
|
|
9606
|
+
description: "Word-processing document (Word 97-2003)"
|
|
9607
|
+
},
|
|
9608
|
+
{
|
|
9609
|
+
format: "xls",
|
|
9610
|
+
description: "Spreadsheet workbook (Excel 97-2003)"
|
|
9611
|
+
},
|
|
9612
|
+
{
|
|
9613
|
+
format: "ppt",
|
|
9614
|
+
description: "Presentation slide deck (PowerPoint 97-2003)"
|
|
9615
|
+
},
|
|
9616
|
+
{
|
|
9617
|
+
format: "markdown",
|
|
9618
|
+
description: "Markdown document"
|
|
8799
9619
|
}
|
|
8800
9620
|
];
|
|
8801
9621
|
const EXTENSION_COLUMN_WIDTH = 8;
|
|
@@ -8912,22 +9732,73 @@ function metadataFor(doc) {
|
|
|
8912
9732
|
case "ods": return readOdsContent(doc.editor.toPackage()).metadata;
|
|
8913
9733
|
case "odg": return readOdgContent(doc.editor.toPackage()).metadata;
|
|
8914
9734
|
case "markdown": return readMarkdownContent(doc.editor.toMarkdownText()).metadata;
|
|
9735
|
+
case "doc":
|
|
9736
|
+
case "xls":
|
|
9737
|
+
case "ppt": return doc.editor.metadata;
|
|
8915
9738
|
case "pdf":
|
|
8916
9739
|
case "xlsx":
|
|
8917
9740
|
case "csv":
|
|
8918
|
-
case "svg":
|
|
9741
|
+
case "svg":
|
|
9742
|
+
case "rtf":
|
|
9743
|
+
case "wpd":
|
|
9744
|
+
case "epub": return doc.layout.metadata;
|
|
8919
9745
|
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.");
|
|
8920
9746
|
}
|
|
8921
9747
|
}
|
|
8922
9748
|
//#endregion
|
|
8923
9749
|
//#region src/tui/screens/shared/metadata.tsx
|
|
9750
|
+
const EDITABLE_FIELDS = [
|
|
9751
|
+
{
|
|
9752
|
+
key: "title",
|
|
9753
|
+
label: "title"
|
|
9754
|
+
},
|
|
9755
|
+
{
|
|
9756
|
+
key: "author",
|
|
9757
|
+
label: "author"
|
|
9758
|
+
},
|
|
9759
|
+
{
|
|
9760
|
+
key: "subject",
|
|
9761
|
+
label: "subject"
|
|
9762
|
+
},
|
|
9763
|
+
{
|
|
9764
|
+
key: "keywords",
|
|
9765
|
+
label: "keywords"
|
|
9766
|
+
}
|
|
9767
|
+
];
|
|
9768
|
+
function parseKeywords(text) {
|
|
9769
|
+
return text.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
9770
|
+
}
|
|
9771
|
+
function overridesFor(field, text) {
|
|
9772
|
+
switch (field) {
|
|
9773
|
+
case "title": return { title: text };
|
|
9774
|
+
case "author": return { author: text };
|
|
9775
|
+
case "subject": return { subject: text };
|
|
9776
|
+
case "keywords": return { keywords: parseKeywords(text) };
|
|
9777
|
+
}
|
|
9778
|
+
}
|
|
8924
9779
|
function MetadataScreen() {
|
|
8925
9780
|
const state = useAppState();
|
|
8926
9781
|
const dispatch = useAppDispatch();
|
|
8927
9782
|
const doc = state.openDocument;
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
9783
|
+
const editable = doc !== void 0 && isEditableDocument(doc);
|
|
9784
|
+
const [editingField, setEditingField] = useState(void 0);
|
|
9785
|
+
const [draft, setDraft] = useState("");
|
|
9786
|
+
const isNavigationActive = doc !== void 0 && !anyOverlayOpen(state) && editingField === void 0;
|
|
9787
|
+
const { selectedIndex } = useNavigationInput({
|
|
9788
|
+
itemCount: editable ? EDITABLE_FIELDS.length : 0,
|
|
9789
|
+
isActive: isNavigationActive,
|
|
9790
|
+
onBack: () => {
|
|
9791
|
+
dispatch({ type: "POP_SCREEN" });
|
|
9792
|
+
},
|
|
9793
|
+
onSelect: (index) => {
|
|
9794
|
+
if (doc === void 0 || !editable) return;
|
|
9795
|
+
const field = EDITABLE_FIELDS[index];
|
|
9796
|
+
if (field === void 0) return;
|
|
9797
|
+
const currentValue = metadataFor(doc)[field.key];
|
|
9798
|
+
setDraft(currentValue === void 0 ? "" : formatMetadataValue(currentValue));
|
|
9799
|
+
setEditingField(field.key);
|
|
9800
|
+
}
|
|
9801
|
+
});
|
|
8931
9802
|
if (doc === void 0) return /* @__PURE__ */ jsx(Text, {
|
|
8932
9803
|
color: "red",
|
|
8933
9804
|
children: "MetadataScreen requires an open document."
|
|
@@ -8939,6 +9810,37 @@ function MetadataScreen() {
|
|
|
8939
9810
|
} catch (error) {
|
|
8940
9811
|
errorMessage = error instanceof Error ? error.message : String(error);
|
|
8941
9812
|
}
|
|
9813
|
+
if (editingField !== void 0) {
|
|
9814
|
+
const field = EDITABLE_FIELDS.find((f) => f.key === editingField);
|
|
9815
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
9816
|
+
flexDirection: "column",
|
|
9817
|
+
children: [
|
|
9818
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
9819
|
+
bold: true,
|
|
9820
|
+
children: ["Editing ", field?.label ?? editingField]
|
|
9821
|
+
}),
|
|
9822
|
+
editingField === "keywords" ? /* @__PURE__ */ jsx(Text, {
|
|
9823
|
+
dimColor: true,
|
|
9824
|
+
children: "Comma-separated"
|
|
9825
|
+
}) : void 0,
|
|
9826
|
+
/* @__PURE__ */ jsx(TextField, {
|
|
9827
|
+
value: draft,
|
|
9828
|
+
isFocused: true,
|
|
9829
|
+
onChange: setDraft,
|
|
9830
|
+
onSubmit: (text) => {
|
|
9831
|
+
dispatch({
|
|
9832
|
+
type: "SET_METADATA",
|
|
9833
|
+
overrides: overridesFor(editingField, text)
|
|
9834
|
+
});
|
|
9835
|
+
setEditingField(void 0);
|
|
9836
|
+
},
|
|
9837
|
+
onCancel: () => {
|
|
9838
|
+
setEditingField(void 0);
|
|
9839
|
+
}
|
|
9840
|
+
})
|
|
9841
|
+
]
|
|
9842
|
+
});
|
|
9843
|
+
}
|
|
8942
9844
|
return /* @__PURE__ */ jsxs(Box, {
|
|
8943
9845
|
flexDirection: "column",
|
|
8944
9846
|
children: [
|
|
@@ -8957,9 +9859,27 @@ function MetadataScreen() {
|
|
|
8957
9859
|
dimColor: true,
|
|
8958
9860
|
children: "This document carries no metadata."
|
|
8959
9861
|
}),
|
|
8960
|
-
/* @__PURE__ */
|
|
9862
|
+
editable ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9863
|
+
/* @__PURE__ */ jsx(Text, {
|
|
9864
|
+
bold: true,
|
|
9865
|
+
children: "Edit a field"
|
|
9866
|
+
}),
|
|
9867
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
9868
|
+
items: EDITABLE_FIELDS,
|
|
9869
|
+
selectedIndex,
|
|
9870
|
+
renderItem: (field, isSelected) => /* @__PURE__ */ jsx(Text, {
|
|
9871
|
+
color: isSelected ? "cyan" : void 0,
|
|
9872
|
+
inverse: isSelected,
|
|
9873
|
+
children: field.label
|
|
9874
|
+
})
|
|
9875
|
+
}),
|
|
9876
|
+
/* @__PURE__ */ jsx(Text, {
|
|
9877
|
+
dimColor: true,
|
|
9878
|
+
children: "Enter to edit, Esc / ← / h to go back"
|
|
9879
|
+
})
|
|
9880
|
+
] }) : /* @__PURE__ */ jsx(Text, {
|
|
8961
9881
|
dimColor: true,
|
|
8962
|
-
children: "Esc / ← / h to go back"
|
|
9882
|
+
children: "This document's metadata is read-only. Esc / ← / h to go back"
|
|
8963
9883
|
})
|
|
8964
9884
|
]
|
|
8965
9885
|
});
|
|
@@ -8980,6 +9900,7 @@ function ScreenBody({ screen }) {
|
|
|
8980
9900
|
case "newDocumentPicker": return /* @__PURE__ */ jsx(NewDocumentPickerScreen, {});
|
|
8981
9901
|
case "bodyList":
|
|
8982
9902
|
if (format === "odt") return /* @__PURE__ */ jsx(OdtBodyListScreen, {});
|
|
9903
|
+
if (format === "doc") return /* @__PURE__ */ jsx(DocBodyListScreen, {});
|
|
8983
9904
|
return format === "markdown" ? /* @__PURE__ */ jsx(MarkdownBodyListScreen, {}) : /* @__PURE__ */ jsx(DocxBodyListScreen, {});
|
|
8984
9905
|
case "docxExtras": return /* @__PURE__ */ jsx(DocxExtrasScreen, {});
|
|
8985
9906
|
case "paragraphDetail": return /* @__PURE__ */ jsx(ParagraphDetailScreen, {});
|
|
@@ -8987,13 +9908,15 @@ function ScreenBody({ screen }) {
|
|
|
8987
9908
|
case "tableView": return /* @__PURE__ */ jsx(TableViewScreen, {});
|
|
8988
9909
|
case "tableCellDetail": return /* @__PURE__ */ jsx(TableCellDetailScreen, {});
|
|
8989
9910
|
case "listEditor": return /* @__PURE__ */ jsx(ListEditorScreen, {});
|
|
8990
|
-
case "slideList":
|
|
8991
|
-
|
|
9911
|
+
case "slideList":
|
|
9912
|
+
if (format === "ppt") return /* @__PURE__ */ jsx(PptSlideListScreen, {});
|
|
9913
|
+
return format === "odp" ? /* @__PURE__ */ jsx(OdpSlideListScreen, {}) : /* @__PURE__ */ jsx(PptxSlideListScreen, {});
|
|
9914
|
+
case "slideDetail": return format === "ppt" ? /* @__PURE__ */ jsx(PptSlideDetailScreen, { slideIndex: screen.slideIndex }) : /* @__PURE__ */ jsx(SlideDetailScreen, { screen });
|
|
8992
9915
|
case "shapeEditor": return /* @__PURE__ */ jsx(ShapeEditorScreen, { screen });
|
|
8993
9916
|
case "slideTableDetail": return /* @__PURE__ */ jsx(SlideTableDetailScreen, { screen });
|
|
8994
9917
|
case "notesEditor": return /* @__PURE__ */ jsx(NotesEditorScreen, { screen });
|
|
8995
|
-
case "sheetList": return /* @__PURE__ */ jsx(OdsSheetListScreen, {});
|
|
8996
|
-
case "spreadsheetGrid": return /* @__PURE__ */ jsx(OdsSpreadsheetGridScreen, {});
|
|
9918
|
+
case "sheetList": return format === "xls" ? /* @__PURE__ */ jsx(XlsSheetListScreen, {}) : /* @__PURE__ */ jsx(OdsSheetListScreen, {});
|
|
9919
|
+
case "spreadsheetGrid": return format === "xls" ? /* @__PURE__ */ jsx(XlsSpreadsheetGridScreen, { sheetIndex: screen.sheetIndex }) : /* @__PURE__ */ jsx(OdsSpreadsheetGridScreen, {});
|
|
8997
9920
|
case "cellDetail": return /* @__PURE__ */ jsx(Text, { children: "cellDetail is rendered inline by spreadsheetGrid and is never pushed as its own screen." });
|
|
8998
9921
|
case "printSettingsEditor": return /* @__PURE__ */ jsx(OdsPrintSettingsEditorScreen, {});
|
|
8999
9922
|
case "pageList": return /* @__PURE__ */ jsx(OdgPageListScreen, {});
|
|
@@ -9049,7 +9972,7 @@ function AppShell({ startPath }) {
|
|
|
9049
9972
|
const overlayOpen = anyOverlayOpen(state);
|
|
9050
9973
|
useEffect(() => {
|
|
9051
9974
|
if (startPath === void 0) return;
|
|
9052
|
-
|
|
9975
|
+
const lifecycle = { cancelled: false };
|
|
9053
9976
|
(async () => {
|
|
9054
9977
|
try {
|
|
9055
9978
|
const doc = await openDocumentAtPath(startPath, { onDiagnostic: (diagnostic) => {
|
|
@@ -9058,13 +9981,13 @@ function AppShell({ startPath }) {
|
|
|
9058
9981
|
diagnostic
|
|
9059
9982
|
});
|
|
9060
9983
|
} });
|
|
9061
|
-
if (!cancelled) dispatch({
|
|
9984
|
+
if (!lifecycle.cancelled) dispatch({
|
|
9062
9985
|
type: "OPEN_FILE_SUCCESS",
|
|
9063
9986
|
path: startPath,
|
|
9064
9987
|
doc
|
|
9065
9988
|
});
|
|
9066
9989
|
} catch (error) {
|
|
9067
|
-
if (!cancelled) dispatch({
|
|
9990
|
+
if (!lifecycle.cancelled) dispatch({
|
|
9068
9991
|
type: "OPEN_FILE_ERROR",
|
|
9069
9992
|
message: `Could not open ${startPath}`,
|
|
9070
9993
|
detail: describeError(error)
|
|
@@ -9072,7 +9995,7 @@ function AppShell({ startPath }) {
|
|
|
9072
9995
|
}
|
|
9073
9996
|
})();
|
|
9074
9997
|
return () => {
|
|
9075
|
-
cancelled = true;
|
|
9998
|
+
lifecycle.cancelled = true;
|
|
9076
9999
|
};
|
|
9077
10000
|
}, [startPath, dispatch]);
|
|
9078
10001
|
useEffect(() => {
|