document-cli 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{tui-BzdX4QQg.js → tui-BCl5_L4H.js} +463 -67
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1194,7 +1194,7 @@ function registerSetMetadataCommand(program) {
|
|
|
1194
1194
|
}
|
|
1195
1195
|
//#endregion
|
|
1196
1196
|
//#region package.json
|
|
1197
|
-
var version = "1.
|
|
1197
|
+
var version = "1.8.0";
|
|
1198
1198
|
//#endregion
|
|
1199
1199
|
//#region src/program.ts
|
|
1200
1200
|
function createProgram() {
|
|
@@ -1221,7 +1221,7 @@ function createProgram() {
|
|
|
1221
1221
|
//#region src/cli.ts
|
|
1222
1222
|
async function launchTui(startPath, signal) {
|
|
1223
1223
|
try {
|
|
1224
|
-
const { runTui } = await import("./tui-
|
|
1224
|
+
const { runTui } = await import("./tui-BCl5_L4H.js");
|
|
1225
1225
|
await runTui({
|
|
1226
1226
|
startPath,
|
|
1227
1227
|
signal
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as formatDocxExtrasLines, f as loadProvidedFonts, i as formatOdbReportLines, l as readInput, m as inferFormatFromExtension, n as describeOdbReport, o as formatMetadataLines, p as formatToExtension, r as formatOdbFormLines, t as describeOdbForm } from "./odb-structure-Du1w_hOU.js";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { buildDocxPackage, buildOdtPackage, convertWordprocessingToLayout, createDocx, createFontMeasurer, createFontRegistry, createOdg, createOdp, createOds, createOdt, createPptx, decodeMarkdownText, docxToPdf, encodeMarkdownText, encodePackage, hsqldbCellDisplayText, markdownToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDocx, openOdg, openOdp, openOds, openOdt, openPptx, pptxToPdf, readDocxContent, readDocxExtras, readMarkdownContent, readOdbForms, readOdbReportContent, readOdbReports, readOdbTables, readOdgContent, readOdpContent, readOdsContent, readOdtContent, readPdf, readPptxContent, rgbHexToColor, writePdf, xlsxToPdf } from "documents.js";
|
|
3
|
+
import { buildDocxPackage, buildOdtPackage, convertWordprocessingToLayout, createDocx, createFontMeasurer, createFontRegistry, createOdg, createOdp, createOds, createOdt, createPptx, decodeMarkdownText, docxToPdf, encodeMarkdownText, encodePackage, hsqldbCellDisplayText, markdownToPdf, odgToPdf, odpToPdf, odsToPdf, odtToPdf, openDocx, openOdg, openOdp, openOds, openOdt, openPptx, parseXml, pptxToPdf, readDocxContent, readDocxExtras, readMarkdownContent, readOdbForms, readOdbReportContent, readOdbReports, readOdbTables, readOdgContent, readOdpContent, readOdsContent, readOdtContent, readPdf, readPptxContent, rgbHexToColor, writePdf, xlsxToPdf } from "documents.js";
|
|
4
4
|
import { basename, dirname, extname, join } from "node:path";
|
|
5
5
|
import { cellReference, columnIndexToLetters, decodePackage as decodePackage$1, encodePackage as encodePackage$1 } from "odf.js";
|
|
6
6
|
import { readdirSync } from "node:fs";
|
|
@@ -569,6 +569,31 @@ function setTextContainerText(container, text) {
|
|
|
569
569
|
function setCellText(cell, text) {
|
|
570
570
|
setTextContainerText(cell, text);
|
|
571
571
|
}
|
|
572
|
+
function mutableMathMlNode(node) {
|
|
573
|
+
if (node.type === "element") return {
|
|
574
|
+
type: "element",
|
|
575
|
+
tag: node.tag,
|
|
576
|
+
attributes: [...node.attributes],
|
|
577
|
+
children: node.children.map(mutableMathMlNode)
|
|
578
|
+
};
|
|
579
|
+
if (node.type === "text") return {
|
|
580
|
+
type: "text",
|
|
581
|
+
value: node.value
|
|
582
|
+
};
|
|
583
|
+
if (node.type === "cdata" || node.type === "comment") return {
|
|
584
|
+
type: node.type,
|
|
585
|
+
value: ""
|
|
586
|
+
};
|
|
587
|
+
if (node.type === "declaration") return {
|
|
588
|
+
type: "declaration",
|
|
589
|
+
attributes: []
|
|
590
|
+
};
|
|
591
|
+
return {
|
|
592
|
+
type: "pi",
|
|
593
|
+
target: "",
|
|
594
|
+
content: ""
|
|
595
|
+
};
|
|
596
|
+
}
|
|
572
597
|
function appReducer(state, action) {
|
|
573
598
|
switch (action.type) {
|
|
574
599
|
case "PUSH_SCREEN": return {
|
|
@@ -775,6 +800,39 @@ function appReducer(state, action) {
|
|
|
775
800
|
setTextContainerText(item, action.text);
|
|
776
801
|
});
|
|
777
802
|
}
|
|
803
|
+
case "INSERT_PARAGRAPH_IMAGE": {
|
|
804
|
+
const doc = wordprocessingDocument(state);
|
|
805
|
+
if (doc === void 0) return wrongDocument(state, "a docx or odt document");
|
|
806
|
+
const paragraph = paragraphAt(doc, action.blockIndex);
|
|
807
|
+
if (paragraph === void 0) return withStatus(state, "warning", `There is no paragraph at index ${action.blockIndex}`);
|
|
808
|
+
return mutate(state, doc, () => {
|
|
809
|
+
paragraph.insertImageAfter({
|
|
810
|
+
format: action.format,
|
|
811
|
+
bytes: action.bytes,
|
|
812
|
+
widthPt: action.widthPt,
|
|
813
|
+
heightPt: action.heightPt,
|
|
814
|
+
altText: action.altText
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
case "INSERT_DOCX_FORMULA": {
|
|
819
|
+
const doc = state.openDocument;
|
|
820
|
+
if (doc?.format !== "docx") return wrongDocument(state, "a docx document");
|
|
821
|
+
const paragraph = doc.editor.paragraphs()[action.blockIndex];
|
|
822
|
+
if (paragraph === void 0) return withStatus(state, "warning", `There is no paragraph at index ${action.blockIndex}`);
|
|
823
|
+
let written = true;
|
|
824
|
+
const nextState = mutate(state, doc, () => {
|
|
825
|
+
written = paragraph.appendOfficeMath(action.mathml).written;
|
|
826
|
+
});
|
|
827
|
+
return written ? nextState : withStatus(nextState, "warning", "The formula produced no OMML content and was not written");
|
|
828
|
+
}
|
|
829
|
+
case "INSERT_ODT_FORMULA": {
|
|
830
|
+
const doc = state.openDocument;
|
|
831
|
+
if (doc?.format !== "odt") return wrongDocument(state, "an odt document");
|
|
832
|
+
return mutate(state, doc, () => {
|
|
833
|
+
doc.editor.body.appendFormula({ mathml: action.mathml.map(mutableMathMlNode) }, action.frame);
|
|
834
|
+
});
|
|
835
|
+
}
|
|
778
836
|
case "ADD_SLIDE": {
|
|
779
837
|
const doc = presentationDocument(state);
|
|
780
838
|
if (doc === void 0) return wrongDocument(state, "a pptx or odp document");
|
|
@@ -1668,6 +1726,220 @@ function StatusLine() {
|
|
|
1668
1726
|
] });
|
|
1669
1727
|
}
|
|
1670
1728
|
//#endregion
|
|
1729
|
+
//#region src/tui/screens/shared/field-wizard.tsx
|
|
1730
|
+
function requireFieldValue(values, key) {
|
|
1731
|
+
const value = values[key];
|
|
1732
|
+
if (value === void 0) throw new Error(`Field wizard field '${key}' was never recorded before building the action.`);
|
|
1733
|
+
return value;
|
|
1734
|
+
}
|
|
1735
|
+
function FieldWizard(props) {
|
|
1736
|
+
const [stepIndex, setStepIndex] = useState(0);
|
|
1737
|
+
const [collected, setCollected] = useState({});
|
|
1738
|
+
const initialField = props.fields[0];
|
|
1739
|
+
const [draft, setDraft] = useState(initialField === void 0 ? "" : initialField.defaultValue);
|
|
1740
|
+
const field = props.fields[stepIndex];
|
|
1741
|
+
if (field === void 0) throw new Error(`FieldWizard stepIndex ${stepIndex} is out of range for ${props.fields.length} fields -- onComplete always fires before stepIndex can advance past the last field, so this indicates a bug in that advance.`);
|
|
1742
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
1743
|
+
flexDirection: "column",
|
|
1744
|
+
borderStyle: "round",
|
|
1745
|
+
paddingX: 1,
|
|
1746
|
+
children: [
|
|
1747
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1748
|
+
bold: true,
|
|
1749
|
+
children: field.label
|
|
1750
|
+
}),
|
|
1751
|
+
/* @__PURE__ */ jsx(TextField, {
|
|
1752
|
+
value: draft,
|
|
1753
|
+
isFocused: true,
|
|
1754
|
+
onChange: setDraft,
|
|
1755
|
+
onCancel: props.onCancel,
|
|
1756
|
+
onSubmit: (value) => {
|
|
1757
|
+
const recorded = {
|
|
1758
|
+
...collected,
|
|
1759
|
+
[field.key]: value
|
|
1760
|
+
};
|
|
1761
|
+
const nextIndex = stepIndex + 1;
|
|
1762
|
+
const nextField = props.fields[nextIndex];
|
|
1763
|
+
if (nextField === void 0) {
|
|
1764
|
+
props.onComplete(recorded);
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
setCollected(recorded);
|
|
1768
|
+
setDraft(nextField.defaultValue);
|
|
1769
|
+
setStepIndex(nextIndex);
|
|
1770
|
+
}
|
|
1771
|
+
}),
|
|
1772
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1773
|
+
dimColor: true,
|
|
1774
|
+
children: [
|
|
1775
|
+
"Step ",
|
|
1776
|
+
stepIndex + 1,
|
|
1777
|
+
" of ",
|
|
1778
|
+
props.fields.length,
|
|
1779
|
+
" -- Enter to continue, Esc to cancel"
|
|
1780
|
+
]
|
|
1781
|
+
})
|
|
1782
|
+
]
|
|
1783
|
+
});
|
|
1784
|
+
}
|
|
1785
|
+
//#endregion
|
|
1786
|
+
//#region src/tui/screens/shared/formula-presets.ts
|
|
1787
|
+
function element(tag, children = []) {
|
|
1788
|
+
return {
|
|
1789
|
+
type: "element",
|
|
1790
|
+
tag,
|
|
1791
|
+
attributes: [],
|
|
1792
|
+
children
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
function text(value) {
|
|
1796
|
+
return {
|
|
1797
|
+
type: "text",
|
|
1798
|
+
value
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
function mi(name) {
|
|
1802
|
+
return element("mi", [text(name)]);
|
|
1803
|
+
}
|
|
1804
|
+
function mn(value) {
|
|
1805
|
+
return element("mn", [text(value)]);
|
|
1806
|
+
}
|
|
1807
|
+
function mo(operator) {
|
|
1808
|
+
return element("mo", [text(operator)]);
|
|
1809
|
+
}
|
|
1810
|
+
const FORMULA_PRESETS = [
|
|
1811
|
+
{
|
|
1812
|
+
label: "Fraction: x / 2",
|
|
1813
|
+
mathml: [element("mfrac", [mi("x"), mn("2")])]
|
|
1814
|
+
},
|
|
1815
|
+
{
|
|
1816
|
+
label: "Power: x^2",
|
|
1817
|
+
mathml: [element("msup", [mi("x"), mn("2")])]
|
|
1818
|
+
},
|
|
1819
|
+
{
|
|
1820
|
+
label: "Subscript: x_i",
|
|
1821
|
+
mathml: [element("msub", [mi("x"), mi("i")])]
|
|
1822
|
+
},
|
|
1823
|
+
{
|
|
1824
|
+
label: "Square root: sqrt(x)",
|
|
1825
|
+
mathml: [element("msqrt", [mi("x")])]
|
|
1826
|
+
},
|
|
1827
|
+
{
|
|
1828
|
+
label: "Summation: sum(i=1..n) i",
|
|
1829
|
+
mathml: [element("munderover", [
|
|
1830
|
+
mo("∑"),
|
|
1831
|
+
element("mrow", [
|
|
1832
|
+
mi("i"),
|
|
1833
|
+
mo("="),
|
|
1834
|
+
mn("1")
|
|
1835
|
+
]),
|
|
1836
|
+
mi("n")
|
|
1837
|
+
])]
|
|
1838
|
+
},
|
|
1839
|
+
{
|
|
1840
|
+
label: "Quadratic formula",
|
|
1841
|
+
mathml: [element("mrow", [
|
|
1842
|
+
mi("x"),
|
|
1843
|
+
mo("="),
|
|
1844
|
+
element("mfrac", [element("mrow", [
|
|
1845
|
+
mo("-"),
|
|
1846
|
+
mi("b"),
|
|
1847
|
+
mo("±"),
|
|
1848
|
+
element("msqrt", [element("mrow", [
|
|
1849
|
+
element("msup", [mi("b"), mn("2")]),
|
|
1850
|
+
mo("-"),
|
|
1851
|
+
mn("4"),
|
|
1852
|
+
mi("a"),
|
|
1853
|
+
mi("c")
|
|
1854
|
+
])])
|
|
1855
|
+
]), element("mrow", [mn("2"), mi("a")])])
|
|
1856
|
+
])]
|
|
1857
|
+
}
|
|
1858
|
+
];
|
|
1859
|
+
//#endregion
|
|
1860
|
+
//#region src/tui/screens/shared/formula-picker.tsx
|
|
1861
|
+
const RAW_ENTRY_LABEL = "Raw MathML...";
|
|
1862
|
+
const PICKER_ROWS = [...FORMULA_PRESETS.map((preset) => ({
|
|
1863
|
+
label: preset.label,
|
|
1864
|
+
mathml: preset.mathml
|
|
1865
|
+
})), {
|
|
1866
|
+
label: RAW_ENTRY_LABEL,
|
|
1867
|
+
mathml: void 0
|
|
1868
|
+
}];
|
|
1869
|
+
function FormulaPicker(props) {
|
|
1870
|
+
const [rawInput, setRawInput] = useState(void 0);
|
|
1871
|
+
const { selectedIndex } = useNavigationInput({
|
|
1872
|
+
itemCount: PICKER_ROWS.length,
|
|
1873
|
+
isActive: props.isActive && rawInput === void 0,
|
|
1874
|
+
onBack: props.onCancel,
|
|
1875
|
+
onSelect: (index) => {
|
|
1876
|
+
const row = PICKER_ROWS[index];
|
|
1877
|
+
if (row === void 0) return;
|
|
1878
|
+
if (row.mathml === void 0) {
|
|
1879
|
+
setRawInput("");
|
|
1880
|
+
return;
|
|
1881
|
+
}
|
|
1882
|
+
props.onMathml(row.mathml);
|
|
1883
|
+
}
|
|
1884
|
+
});
|
|
1885
|
+
if (rawInput !== void 0) return /* @__PURE__ */ jsxs(Box, {
|
|
1886
|
+
flexDirection: "column",
|
|
1887
|
+
borderStyle: "round",
|
|
1888
|
+
paddingX: 1,
|
|
1889
|
+
children: [
|
|
1890
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1891
|
+
bold: true,
|
|
1892
|
+
children: "Raw MathML (the children of the <math> root, e.g. <mfrac>...</mfrac>)"
|
|
1893
|
+
}),
|
|
1894
|
+
/* @__PURE__ */ jsx(TextField, {
|
|
1895
|
+
value: rawInput,
|
|
1896
|
+
isFocused: true,
|
|
1897
|
+
onChange: setRawInput,
|
|
1898
|
+
onCancel: () => {
|
|
1899
|
+
setRawInput(void 0);
|
|
1900
|
+
},
|
|
1901
|
+
onSubmit: (value) => {
|
|
1902
|
+
try {
|
|
1903
|
+
const parsed = parseXml(value);
|
|
1904
|
+
props.onMathml(parsed);
|
|
1905
|
+
} catch (error) {
|
|
1906
|
+
props.onInvalidRawMathml(describeError(error));
|
|
1907
|
+
}
|
|
1908
|
+
setRawInput(void 0);
|
|
1909
|
+
}
|
|
1910
|
+
}),
|
|
1911
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1912
|
+
dimColor: true,
|
|
1913
|
+
children: "Enter to insert, Esc to cancel"
|
|
1914
|
+
})
|
|
1915
|
+
]
|
|
1916
|
+
});
|
|
1917
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
1918
|
+
flexDirection: "column",
|
|
1919
|
+
borderStyle: "round",
|
|
1920
|
+
paddingX: 1,
|
|
1921
|
+
children: [
|
|
1922
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1923
|
+
bold: true,
|
|
1924
|
+
children: "Insert formula -- choose a preset or write raw MathML"
|
|
1925
|
+
}),
|
|
1926
|
+
/* @__PURE__ */ jsx(ListView, {
|
|
1927
|
+
items: PICKER_ROWS,
|
|
1928
|
+
selectedIndex,
|
|
1929
|
+
reservedRows: PICKER_ROWS.length + 2,
|
|
1930
|
+
renderItem: (row, isSelected) => /* @__PURE__ */ jsxs(Text, {
|
|
1931
|
+
color: isSelected ? "cyan" : void 0,
|
|
1932
|
+
children: [isSelected ? "> " : " ", row.label]
|
|
1933
|
+
})
|
|
1934
|
+
}),
|
|
1935
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1936
|
+
dimColor: true,
|
|
1937
|
+
children: "Enter to choose, Esc to cancel"
|
|
1938
|
+
})
|
|
1939
|
+
]
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
//#endregion
|
|
1671
1943
|
//#region src/tui/screens/shared/text.ts
|
|
1672
1944
|
function truncatePreview(text, maxLength) {
|
|
1673
1945
|
const singleLine = text.replace(/\s+/gu, " ").trim();
|
|
@@ -1682,6 +1954,10 @@ function parseNonNegativeIntField(raw, fallback) {
|
|
|
1682
1954
|
const parsed = Number.parseInt(raw, 10);
|
|
1683
1955
|
return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback;
|
|
1684
1956
|
}
|
|
1957
|
+
function parseNumberField(raw, fallback) {
|
|
1958
|
+
const parsed = Number.parseFloat(raw);
|
|
1959
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
1960
|
+
}
|
|
1685
1961
|
//#endregion
|
|
1686
1962
|
//#region src/tui/screens/shared/paragraph-family.tsx
|
|
1687
1963
|
function paragraphFamilyDocument(openDocument) {
|
|
@@ -1747,6 +2023,36 @@ function listSummary(list, index) {
|
|
|
1747
2023
|
}
|
|
1748
2024
|
const DEFAULT_TABLE_ROWS$1 = 2;
|
|
1749
2025
|
const DEFAULT_TABLE_COLUMNS$1 = 2;
|
|
2026
|
+
const FORMULA_FRAME_FIELDS = [
|
|
2027
|
+
{
|
|
2028
|
+
key: "xPt",
|
|
2029
|
+
label: "X (pt)",
|
|
2030
|
+
defaultValue: "40"
|
|
2031
|
+
},
|
|
2032
|
+
{
|
|
2033
|
+
key: "yPt",
|
|
2034
|
+
label: "Y (pt)",
|
|
2035
|
+
defaultValue: "40"
|
|
2036
|
+
},
|
|
2037
|
+
{
|
|
2038
|
+
key: "widthPt",
|
|
2039
|
+
label: "Width (pt)",
|
|
2040
|
+
defaultValue: "120"
|
|
2041
|
+
},
|
|
2042
|
+
{
|
|
2043
|
+
key: "heightPt",
|
|
2044
|
+
label: "Height (pt)",
|
|
2045
|
+
defaultValue: "40"
|
|
2046
|
+
}
|
|
2047
|
+
];
|
|
2048
|
+
function readFormulaFrame(values) {
|
|
2049
|
+
return {
|
|
2050
|
+
xPt: parseNumberField(requireFieldValue(values, "xPt"), 0),
|
|
2051
|
+
yPt: parseNumberField(requireFieldValue(values, "yPt"), 0),
|
|
2052
|
+
widthPt: parseNumberField(requireFieldValue(values, "widthPt"), 120),
|
|
2053
|
+
heightPt: parseNumberField(requireFieldValue(values, "heightPt"), 40)
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
1750
2056
|
function ParagraphFamilyBodyList(props) {
|
|
1751
2057
|
const { adapter } = props;
|
|
1752
2058
|
const state = useAppState();
|
|
@@ -1797,6 +2103,9 @@ function ParagraphFamilyBodyList(props) {
|
|
|
1797
2103
|
const [wizardStartColumn, setWizardStartColumn] = useState(0);
|
|
1798
2104
|
const [wizardRowSpan, setWizardRowSpan] = useState(1);
|
|
1799
2105
|
const wizardOpen = tableWizard !== "closed";
|
|
2106
|
+
const [formulaFlow, setFormulaFlow] = useState("closed");
|
|
2107
|
+
const [pendingFormulaMathml, setPendingFormulaMathml] = useState(void 0);
|
|
2108
|
+
const formulaFlowOpen = formulaFlow !== "closed";
|
|
1800
2109
|
const closeWizard = () => {
|
|
1801
2110
|
setTableWizard("closed");
|
|
1802
2111
|
};
|
|
@@ -1822,7 +2131,10 @@ function ParagraphFamilyBodyList(props) {
|
|
|
1822
2131
|
setWizardDraft(String(DEFAULT_TABLE_ROWS$1));
|
|
1823
2132
|
setTableWizard("rows");
|
|
1824
2133
|
}
|
|
1825
|
-
}, { isActive: !anyOverlayOpen(state) && !wizardOpen });
|
|
2134
|
+
}, { isActive: !anyOverlayOpen(state) && !wizardOpen && !formulaFlowOpen });
|
|
2135
|
+
useInput((input) => {
|
|
2136
|
+
if (input === "m" && adapter.formatLabel === "odt") setFormulaFlow("picking");
|
|
2137
|
+
}, { isActive: !anyOverlayOpen(state) && !wizardOpen && !formulaFlowOpen });
|
|
1826
2138
|
useInput((input, key) => {
|
|
1827
2139
|
if (key.escape) {
|
|
1828
2140
|
closeWizard();
|
|
@@ -1870,7 +2182,7 @@ function ParagraphFamilyBodyList(props) {
|
|
|
1870
2182
|
};
|
|
1871
2183
|
const { selectedIndex } = usePersistedSelection(selectionKeyFor({ kind: "bodyList" }), {
|
|
1872
2184
|
itemCount: selectableRowIndices.length,
|
|
1873
|
-
isActive: !anyOverlayOpen(state) && !wizardOpen,
|
|
2185
|
+
isActive: !anyOverlayOpen(state) && !wizardOpen && !formulaFlowOpen,
|
|
1874
2186
|
onBack: () => {
|
|
1875
2187
|
dispatch({ type: "POP_SCREEN" });
|
|
1876
2188
|
},
|
|
@@ -2037,9 +2349,46 @@ function ParagraphFamilyBodyList(props) {
|
|
|
2037
2349
|
onSubmit: submitWizardMergeColSpan,
|
|
2038
2350
|
onCancel: closeWizard
|
|
2039
2351
|
})] }) : void 0,
|
|
2040
|
-
/* @__PURE__ */ jsx(
|
|
2352
|
+
formulaFlow === "picking" ? /* @__PURE__ */ jsx(FormulaPicker, {
|
|
2353
|
+
isActive: !anyOverlayOpen(state),
|
|
2354
|
+
onCancel: () => {
|
|
2355
|
+
setFormulaFlow("closed");
|
|
2356
|
+
},
|
|
2357
|
+
onMathml: (mathml) => {
|
|
2358
|
+
setPendingFormulaMathml(mathml);
|
|
2359
|
+
setFormulaFlow("frame");
|
|
2360
|
+
},
|
|
2361
|
+
onInvalidRawMathml: (message) => {
|
|
2362
|
+
dispatch({
|
|
2363
|
+
type: "SET_STATUS",
|
|
2364
|
+
severity: "warning",
|
|
2365
|
+
text: `Could not parse MathML: ${message}`
|
|
2366
|
+
});
|
|
2367
|
+
}
|
|
2368
|
+
}) : void 0,
|
|
2369
|
+
formulaFlow === "frame" ? /* @__PURE__ */ jsx(FieldWizard, {
|
|
2370
|
+
fields: FORMULA_FRAME_FIELDS,
|
|
2371
|
+
onCancel: () => {
|
|
2372
|
+
setFormulaFlow("closed");
|
|
2373
|
+
setPendingFormulaMathml(void 0);
|
|
2374
|
+
},
|
|
2375
|
+
onComplete: (values) => {
|
|
2376
|
+
if (pendingFormulaMathml !== void 0) dispatch({
|
|
2377
|
+
type: "INSERT_ODT_FORMULA",
|
|
2378
|
+
mathml: pendingFormulaMathml,
|
|
2379
|
+
frame: readFormulaFrame(values)
|
|
2380
|
+
});
|
|
2381
|
+
setFormulaFlow("closed");
|
|
2382
|
+
setPendingFormulaMathml(void 0);
|
|
2383
|
+
}
|
|
2384
|
+
}) : void 0,
|
|
2385
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2041
2386
|
dimColor: true,
|
|
2042
|
-
children:
|
|
2387
|
+
children: [
|
|
2388
|
+
"Enter to open, a to append a paragraph, T to append a table",
|
|
2389
|
+
adapter.formatLabel === "odt" ? ", m to insert a formula" : "",
|
|
2390
|
+
", Esc back"
|
|
2391
|
+
]
|
|
2043
2392
|
})
|
|
2044
2393
|
]
|
|
2045
2394
|
});
|
|
@@ -2059,6 +2408,66 @@ function isValidHexColorInput(input) {
|
|
|
2059
2408
|
}
|
|
2060
2409
|
//#endregion
|
|
2061
2410
|
//#region src/tui/screens/editors/docx/paragraph-detail.tsx
|
|
2411
|
+
const IMAGE_FIELDS = [
|
|
2412
|
+
{
|
|
2413
|
+
key: "path",
|
|
2414
|
+
label: "Image file path (.png/.jpg/.jpeg)",
|
|
2415
|
+
defaultValue: ""
|
|
2416
|
+
},
|
|
2417
|
+
{
|
|
2418
|
+
key: "widthPt",
|
|
2419
|
+
label: "Width (pt)",
|
|
2420
|
+
defaultValue: "100"
|
|
2421
|
+
},
|
|
2422
|
+
{
|
|
2423
|
+
key: "heightPt",
|
|
2424
|
+
label: "Height (pt)",
|
|
2425
|
+
defaultValue: "60"
|
|
2426
|
+
},
|
|
2427
|
+
{
|
|
2428
|
+
key: "altText",
|
|
2429
|
+
label: "Alt text, blank for none",
|
|
2430
|
+
defaultValue: ""
|
|
2431
|
+
}
|
|
2432
|
+
];
|
|
2433
|
+
function inferImageFormat$1(path) {
|
|
2434
|
+
const extension = path.slice(path.lastIndexOf(".") + 1).toLowerCase();
|
|
2435
|
+
if (extension === "png") return "png";
|
|
2436
|
+
if (extension === "jpg" || extension === "jpeg") return "jpeg";
|
|
2437
|
+
}
|
|
2438
|
+
async function applyInsertImage(blockIndex, values, dispatch) {
|
|
2439
|
+
const path = requireFieldValue(values, "path");
|
|
2440
|
+
const format = inferImageFormat$1(path);
|
|
2441
|
+
if (format === void 0) {
|
|
2442
|
+
dispatch({
|
|
2443
|
+
type: "SET_STATUS",
|
|
2444
|
+
severity: "warning",
|
|
2445
|
+
text: `${path} is not a .png or .jpg/.jpeg file -- image not inserted`
|
|
2446
|
+
});
|
|
2447
|
+
return;
|
|
2448
|
+
}
|
|
2449
|
+
try {
|
|
2450
|
+
const bytes = new Uint8Array(await readInput(path));
|
|
2451
|
+
const widthPt = parseNumberField(requireFieldValue(values, "widthPt"), 100);
|
|
2452
|
+
const heightPt = parseNumberField(requireFieldValue(values, "heightPt"), 60);
|
|
2453
|
+
const altTextRaw = requireFieldValue(values, "altText").trim();
|
|
2454
|
+
dispatch({
|
|
2455
|
+
type: "INSERT_PARAGRAPH_IMAGE",
|
|
2456
|
+
blockIndex,
|
|
2457
|
+
format,
|
|
2458
|
+
bytes,
|
|
2459
|
+
widthPt,
|
|
2460
|
+
heightPt,
|
|
2461
|
+
altText: altTextRaw.length === 0 ? void 0 : altTextRaw
|
|
2462
|
+
});
|
|
2463
|
+
} catch (error) {
|
|
2464
|
+
dispatch({
|
|
2465
|
+
type: "SET_STATUS",
|
|
2466
|
+
severity: "error",
|
|
2467
|
+
text: `Could not read ${path}: ${describeError(error)}`
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2062
2471
|
function ParagraphRunsView(props) {
|
|
2063
2472
|
if (props.runs.length === 0) return /* @__PURE__ */ jsx(Text, {
|
|
2064
2473
|
dimColor: true,
|
|
@@ -2078,6 +2487,8 @@ function ParagraphDetailScreen() {
|
|
|
2078
2487
|
const dispatch = useAppDispatch();
|
|
2079
2488
|
const [runIndex, setRunIndex] = useState(0);
|
|
2080
2489
|
const [colorInput, setColorInput] = useState(void 0);
|
|
2490
|
+
const [imageWizardOpen, setImageWizardOpen] = useState(false);
|
|
2491
|
+
const [formulaPickerOpen, setFormulaPickerOpen] = useState(false);
|
|
2081
2492
|
const screen = currentScreen(state);
|
|
2082
2493
|
const doc = paragraphFamilyDocument(state.openDocument);
|
|
2083
2494
|
const paragraph = screen.kind === "paragraphDetail" && doc !== void 0 ? liveParagraphAt(doc, screen.blockIndex) : void 0;
|
|
@@ -2140,6 +2551,14 @@ function ParagraphDetailScreen() {
|
|
|
2140
2551
|
});
|
|
2141
2552
|
return;
|
|
2142
2553
|
}
|
|
2554
|
+
if (input === "I") {
|
|
2555
|
+
setImageWizardOpen(true);
|
|
2556
|
+
return;
|
|
2557
|
+
}
|
|
2558
|
+
if (input === "m" && doc?.format === "docx") {
|
|
2559
|
+
setFormulaPickerOpen(true);
|
|
2560
|
+
return;
|
|
2561
|
+
}
|
|
2143
2562
|
if (selectedRun === void 0) return;
|
|
2144
2563
|
if (input === "b") {
|
|
2145
2564
|
dispatch({
|
|
@@ -2166,7 +2585,7 @@ function ParagraphDetailScreen() {
|
|
|
2166
2585
|
return;
|
|
2167
2586
|
}
|
|
2168
2587
|
if (input === "c") setColorInput(selectedRun.color === void 0 ? "" : layoutColorToHex(selectedRun.color).slice(1));
|
|
2169
|
-
}, { isActive: !anyOverlayOpen(state) && colorInput === void 0 });
|
|
2588
|
+
}, { isActive: !anyOverlayOpen(state) && colorInput === void 0 && !imageWizardOpen && !formulaPickerOpen });
|
|
2170
2589
|
if (screen.kind !== "paragraphDetail") return /* @__PURE__ */ jsx(Text, {
|
|
2171
2590
|
color: "red",
|
|
2172
2591
|
children: "ParagraphDetailScreen rendered outside a paragraphDetail screen."
|
|
@@ -2224,9 +2643,45 @@ function ParagraphDetailScreen() {
|
|
|
2224
2643
|
setColorInput(void 0);
|
|
2225
2644
|
}
|
|
2226
2645
|
})] }),
|
|
2227
|
-
/* @__PURE__ */ jsx(
|
|
2646
|
+
imageWizardOpen ? /* @__PURE__ */ jsx(FieldWizard, {
|
|
2647
|
+
fields: IMAGE_FIELDS,
|
|
2648
|
+
onCancel: () => {
|
|
2649
|
+
setImageWizardOpen(false);
|
|
2650
|
+
},
|
|
2651
|
+
onComplete: (values) => {
|
|
2652
|
+
applyInsertImage(blockIndex, values, dispatch).then(() => {
|
|
2653
|
+
setImageWizardOpen(false);
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
}) : void 0,
|
|
2657
|
+
formulaPickerOpen ? /* @__PURE__ */ jsx(FormulaPicker, {
|
|
2658
|
+
isActive: !anyOverlayOpen(state),
|
|
2659
|
+
onCancel: () => {
|
|
2660
|
+
setFormulaPickerOpen(false);
|
|
2661
|
+
},
|
|
2662
|
+
onMathml: (mathml) => {
|
|
2663
|
+
dispatch({
|
|
2664
|
+
type: "INSERT_DOCX_FORMULA",
|
|
2665
|
+
blockIndex,
|
|
2666
|
+
mathml
|
|
2667
|
+
});
|
|
2668
|
+
setFormulaPickerOpen(false);
|
|
2669
|
+
},
|
|
2670
|
+
onInvalidRawMathml: (message) => {
|
|
2671
|
+
dispatch({
|
|
2672
|
+
type: "SET_STATUS",
|
|
2673
|
+
severity: "warning",
|
|
2674
|
+
text: `Could not parse MathML: ${message}`
|
|
2675
|
+
});
|
|
2676
|
+
}
|
|
2677
|
+
}) : void 0,
|
|
2678
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2228
2679
|
dimColor: true,
|
|
2229
|
-
children:
|
|
2680
|
+
children: [
|
|
2681
|
+
"<- / -> move, Enter edit text, b/i/u toggle, c colour, a append run, I image",
|
|
2682
|
+
doc.format === "docx" ? ", m formula" : "",
|
|
2683
|
+
", Esc back"
|
|
2684
|
+
]
|
|
2230
2685
|
})
|
|
2231
2686
|
]
|
|
2232
2687
|
});
|
|
@@ -3365,10 +3820,6 @@ function describeFillStroke(vector) {
|
|
|
3365
3820
|
if (vector.stroke !== void 0) parts.push(`stroke ${formatColor$1(vector.stroke.color)} ${formatPt(vector.stroke.widthPt)}pt`);
|
|
3366
3821
|
return parts.length === 0 ? "no fill or stroke" : parts.join(", ");
|
|
3367
3822
|
}
|
|
3368
|
-
function parseNumberField(raw, fallback) {
|
|
3369
|
-
const parsed = Number.parseFloat(raw);
|
|
3370
|
-
return Number.isFinite(parsed) ? parsed : fallback;
|
|
3371
|
-
}
|
|
3372
3823
|
function parseColorField(raw) {
|
|
3373
3824
|
const trimmed = raw.trim();
|
|
3374
3825
|
if (trimmed.length === 0) return;
|
|
@@ -3425,11 +3876,6 @@ function defaultTriangleSubpaths(widthPt, heightPt) {
|
|
|
3425
3876
|
closed: true
|
|
3426
3877
|
}];
|
|
3427
3878
|
}
|
|
3428
|
-
function requireFieldValue(values, key) {
|
|
3429
|
-
const value = values[key];
|
|
3430
|
-
if (value === void 0) throw new Error(`Add-item field '${key}' was never recorded before building the action.`);
|
|
3431
|
-
return value;
|
|
3432
|
-
}
|
|
3433
3879
|
//#endregion
|
|
3434
3880
|
//#region src/tui/screens/editors/odg/page-list.tsx
|
|
3435
3881
|
function OdgPageListScreen() {
|
|
@@ -3736,56 +4182,6 @@ async function applyAddKind(kind, pageIndex, doc, values, dispatch) {
|
|
|
3736
4182
|
}
|
|
3737
4183
|
}
|
|
3738
4184
|
}
|
|
3739
|
-
function FieldWizard(props) {
|
|
3740
|
-
const [stepIndex, setStepIndex] = useState(0);
|
|
3741
|
-
const [collected, setCollected] = useState({});
|
|
3742
|
-
const initialField = props.fields[0];
|
|
3743
|
-
const [draft, setDraft] = useState(initialField === void 0 ? "" : initialField.defaultValue);
|
|
3744
|
-
const field = props.fields[stepIndex];
|
|
3745
|
-
if (field === void 0) throw new Error(`FieldWizard stepIndex ${stepIndex} is out of range for ${props.fields.length} fields -- onComplete always fires before stepIndex can advance past the last field, so this indicates a bug in that advance.`);
|
|
3746
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
3747
|
-
flexDirection: "column",
|
|
3748
|
-
borderStyle: "round",
|
|
3749
|
-
paddingX: 1,
|
|
3750
|
-
children: [
|
|
3751
|
-
/* @__PURE__ */ jsx(Text, {
|
|
3752
|
-
bold: true,
|
|
3753
|
-
children: field.label
|
|
3754
|
-
}),
|
|
3755
|
-
/* @__PURE__ */ jsx(TextField, {
|
|
3756
|
-
value: draft,
|
|
3757
|
-
isFocused: true,
|
|
3758
|
-
onChange: setDraft,
|
|
3759
|
-
onCancel: props.onCancel,
|
|
3760
|
-
onSubmit: (value) => {
|
|
3761
|
-
const recorded = {
|
|
3762
|
-
...collected,
|
|
3763
|
-
[field.key]: value
|
|
3764
|
-
};
|
|
3765
|
-
const nextIndex = stepIndex + 1;
|
|
3766
|
-
const nextField = props.fields[nextIndex];
|
|
3767
|
-
if (nextField === void 0) {
|
|
3768
|
-
props.onComplete(recorded);
|
|
3769
|
-
return;
|
|
3770
|
-
}
|
|
3771
|
-
setCollected(recorded);
|
|
3772
|
-
setDraft(nextField.defaultValue);
|
|
3773
|
-
setStepIndex(nextIndex);
|
|
3774
|
-
}
|
|
3775
|
-
}),
|
|
3776
|
-
/* @__PURE__ */ jsxs(Text, {
|
|
3777
|
-
dimColor: true,
|
|
3778
|
-
children: [
|
|
3779
|
-
"Step ",
|
|
3780
|
-
stepIndex + 1,
|
|
3781
|
-
" of ",
|
|
3782
|
-
props.fields.length,
|
|
3783
|
-
" -- Enter to continue, Esc to cancel"
|
|
3784
|
-
]
|
|
3785
|
-
})
|
|
3786
|
-
]
|
|
3787
|
-
});
|
|
3788
|
-
}
|
|
3789
4185
|
function AddItemFlow(props) {
|
|
3790
4186
|
const dispatch = useAppDispatch();
|
|
3791
4187
|
const [kind, setKind] = useState(void 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "CLI and interactive Ink TUI for documents.js: every docx/pptx/odt/odp/ods/odg/odf/pdf/odm/odb/xlsx/markdown conversion, bridge, and editor as a scriptable command or a terminal app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"packageManager": "pnpm@11.6.0",
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"commander": "^15.0.0",
|
|
75
|
-
"documents.js": "^1.
|
|
75
|
+
"documents.js": "^1.75.1",
|
|
76
76
|
"ink": "^7.1.1",
|
|
77
77
|
"ink-text-input": "^6.0.0",
|
|
78
78
|
"odf.js": "^2.2.0",
|