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";
|
||||
|
||||
const filters: Record<FileCategories, Record<string, string>> = {
|
||||
const filters: Record<FileCategories, Record<string, string | null>> = {
|
||||
text: {
|
||||
"602": "T602Document",
|
||||
abw: "AbiWord",
|
||||
@@ -113,7 +113,20 @@ const filters: Record<FileCategories, Record<string, string>> = {
|
||||
txt: "Text",
|
||||
wn: "WriteNow",
|
||||
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",
|
||||
wri: "MS_Write",
|
||||
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"]);
|
||||
});
|
||||
|
||||
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 () => {
|
||||
await convert("in.txt", "txt", "docx", "./out/out.docx", undefined, mockExecFile);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user