mirror of
https://github.com/C4illin/ConvertX.git
synced 2026-09-12 09:57:46 +02:00
fix(libreoffice): don't force MS Word 97 infilter on .wps (#585)
* fix(libreoffice): don't force MS Word 97 infilter on .wps .wps is Microsoft Works, not MS Word 97/.doc. Forcing that infilter makes soffice reject a genuine Works document with "source file could not be loaded", even though the same file converts fine when no --infilter is passed at all (LibreOffice auto-detects it correctly). Fixes #582 * test: lock in wps export direction; document why null covers both sides Per review: the filter map feeds both --infilter and the --convert-to suffix, so wps: null also affects exporting TO wps. That is deliberate and behavior-preserving: LibreOffice has no Works export filter (its MS_Works filter is import-only), and bare `--convert-to wps` falls back to LibreOffice's default export filter for the extension - "MS Word 97", the exact filter this map pinned before, so export output is unchanged. Adds a regression test asserting the docx -> wps invocation. --------- Co-authored-by: tr3lane <182920672+tr3lane@users.noreply.github.com>
This commit is contained in:
@@ -77,7 +77,7 @@ export const properties = {
|
|||||||
|
|
||||||
type FileCategories = "text" | "calc";
|
type FileCategories = "text" | "calc";
|
||||||
|
|
||||||
const filters: Record<FileCategories, Record<string, string>> = {
|
const filters: Record<FileCategories, Record<string, string | null>> = {
|
||||||
text: {
|
text: {
|
||||||
"602": "T602Document",
|
"602": "T602Document",
|
||||||
abw: "AbiWord",
|
abw: "AbiWord",
|
||||||
@@ -113,7 +113,20 @@ const filters: Record<FileCategories, Record<string, string>> = {
|
|||||||
txt: "Text",
|
txt: "Text",
|
||||||
wn: "WriteNow",
|
wn: "WriteNow",
|
||||||
wpd: "WordPerfect",
|
wpd: "WordPerfect",
|
||||||
wps: "MS Word 97",
|
// .wps is Microsoft Works, not MS Word 97/.doc - forcing the "MS Word 97"
|
||||||
|
// filter makes soffice reject a genuine Works document with "source file
|
||||||
|
// could not be loaded", even though it converts the same file fine with
|
||||||
|
// no --infilter at all (LibreOffice auto-detects it correctly).
|
||||||
|
//
|
||||||
|
// null is deliberate for BOTH directions here, not just the import side:
|
||||||
|
// this map feeds both --infilter (import) and the --convert-to suffix
|
||||||
|
// (export). On import, null lets LibreOffice auto-detect - its Works
|
||||||
|
// import filter (MS_Works, libwps-backed) is import-only, so it can only
|
||||||
|
// be reached via auto-detection anyway. On export, LibreOffice has no
|
||||||
|
// Works export filter at all; bare `--convert-to wps` falls back to its
|
||||||
|
// default export filter for the extension, which is "MS Word 97" - the
|
||||||
|
// exact filter this map pinned before, so export output is unchanged.
|
||||||
|
wps: null,
|
||||||
wpt: "MS Word 97 Vorlage",
|
wpt: "MS Word 97 Vorlage",
|
||||||
wri: "MS_Write",
|
wri: "MS_Write",
|
||||||
xhtml: "HTML (StarWriter)",
|
xhtml: "HTML (StarWriter)",
|
||||||
|
|||||||
@@ -102,6 +102,49 @@ test("uses only infilter when convertTo has no out filter (e.g., docx -> pdf)",
|
|||||||
expect(args.slice(-2)).toEqual(["out", "in.docx"]);
|
expect(args.slice(-2)).toEqual(["out", "in.docx"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("does not force an infilter for wps (Microsoft Works, not MS Word 97)", async () => {
|
||||||
|
// Regression test for https://github.com/C4illin/ConvertX/issues/582 -
|
||||||
|
// forcing --infilter="MS Word 97" on a genuine .wps file makes soffice
|
||||||
|
// reject it with "source file could not be loaded". No forced infilter
|
||||||
|
// lets LibreOffice auto-detect the real format instead.
|
||||||
|
await convert("in.wps", "wps", "docx", "out/out.docx", undefined, mockExecFile);
|
||||||
|
|
||||||
|
const { args } = requireDefined(calls[0], "Expected at least one execFile call");
|
||||||
|
|
||||||
|
expect(args).toEqual([
|
||||||
|
"--headless",
|
||||||
|
"--convert-to",
|
||||||
|
"docx:MS Word 2007 XML",
|
||||||
|
"--outdir",
|
||||||
|
"out",
|
||||||
|
"in.wps",
|
||||||
|
]);
|
||||||
|
expect(args.some((a) => a.startsWith("--infilter"))).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("does not force an outfilter for wps as an export target either", async () => {
|
||||||
|
// wps shares one filter-map entry for both directions (see the comment in
|
||||||
|
// libreoffice.ts) - docx's own infilter is still emitted (that describes
|
||||||
|
// the real source file), but no --convert-to wps:<filter> suffix is
|
||||||
|
// forced. Verified against a real soffice: this exact invocation succeeds,
|
||||||
|
// with LibreOffice's default export filter for .wps ("MS Word 97" - the
|
||||||
|
// same filter the map pinned before this change, so output is unchanged).
|
||||||
|
// LibreOffice has no Works export filter, so no suffix could do better.
|
||||||
|
await convert("in.docx", "docx", "wps", "out/out.wps", undefined, mockExecFile);
|
||||||
|
|
||||||
|
const { args } = requireDefined(calls[0], "Expected at least one execFile call");
|
||||||
|
|
||||||
|
expect(args).toEqual([
|
||||||
|
"--headless",
|
||||||
|
"--infilter=MS Word 2007 XML",
|
||||||
|
"--convert-to",
|
||||||
|
"wps",
|
||||||
|
"--outdir",
|
||||||
|
"out",
|
||||||
|
"in.docx",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("strips leading './' from outdir", async () => {
|
test("strips leading './' from outdir", async () => {
|
||||||
await convert("in.txt", "txt", "docx", "./out/out.docx", undefined, mockExecFile);
|
await convert("in.txt", "txt", "docx", "./out/out.docx", undefined, mockExecFile);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user