Skip to content

fix(render): make LibreOffice rendering and file:// images work on Windows - #32

Merged
kklimuk merged 2 commits into
mainfrom
fix/windows-render-file-urls
Oct 31, 2026
Merged

kklimuk merged 2 commits into
mainfrom
fix/windows-render-file-urls

Conversation

@kklimuk

@kklimuk kklimuk commented Oct 30, 2026

Copy link
Copy Markdown
Owner

Summary

Running real commands on GitHub's Windows runners found two bugs. This fixes them and adds CI so they stay fixed. It's independent of #26.

Problem on Windows Cause Fix
Every LibreOffice render failed with Executable not found Bun.spawn can't launch soffice.com, which where soffice lists first and our fallbacks named Use soffice.exe
With that fixed, soffice hung file://C:\... isn't a valid profile URL Build it with pathToFileURL
--image file:///C:/x.png wasn't found Stripping the prefix left /C:/x.png fileURLToPath

Also:

  • The LibreOffice engine now has a 150s cap, matching Word for Windows, because it could wait forever on a stuck soffice. The timeout path itself hasn't been run.
  • %20 in a file:// URL now decodes on every platform.
  • A file:// URL with a host keeps its old meaning. On Windows, converting it would produce a UNC path from an attacker-influenced --image.
  • render.test.ts asks the engine whether LibreOffice is available instead of spawning /bin/sh, which crashed the whole file on Windows.
  • New windows-render CI job: installs LibreOffice, runs the render and image tests, then renders with the compiled binary.

Test plan

  • bun run check and the full bun test on macOS
  • Render through LibreOffice on macOS, including a temp path with a space
  • windows-render on this PR
  • Word on Windows: not available on runners, not touched here

🤖 Generated with Claude Code

kklimuk and others added 2 commits October 30, 2026 14:58
…ndows

Every LibreOffice render failed on Windows: Bun.spawn can't launch
soffice.com, the path both `where soffice` and our fallbacks returned. With
that fixed, soffice then hung on the file://C:\... profile URL, so the URL
now comes from pathToFileURL. The engine also gets a 150s cap, matching Word
for Windows, so a stuck soffice fails rather than blocking forever.

file:///C:/x.png became /C:/x.png, and %20 stayed literal on every platform.
Host-less file URLs now convert properly. One with a host keeps its old
meaning, since converting it on Windows would make a UNC path out of an
attacker-influenced --image.

render.test.ts now asks the engine whether LibreOffice is available, instead
of spawning /bin/sh, which crashed the whole file on Windows. A new
windows-render CI job keeps all of this covered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docx can't fix this itself: on a Windows runner, PowerShell kept decoding as
IBM437 even after the child process called SetConsoleOutputCP(65001), and the
child still saw 65001, so it can't detect the mismatch either. Setting the
encoding in PowerShell does fix it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kklimuk

kklimuk commented Oct 30, 2026

Copy link
Copy Markdown
Owner Author

@xsvm one request and one heads-up, since you have Word on real Windows and our CI runners don't.

Could you try these with a binary built from this branch? Word on Windows has never been run by us, and auto picks it first.

  1. docx render doc.docx --out pages --engine word, on a document with a table, an image and an equation. Do the pages look right?
  2. With that document open in Word, run docx edit doc.docx --at p0 --text "x". We expect an error and an untouched file. We only simulated this lock, and the error is currently a bare EBUSY.
  3. In an interactive PowerShell, without changing any settings, run docx read on a document with non-ASCII text. Is it garbled? What does [Console]::OutputEncoding say?

Just reporting what you see is plenty; no need to change anything.

Heads-up on #26: three commits (cc0f4ed, 875523f, 3f90a6f) were pushed to your feat/upgrade-windows branch, so please pull before doing anything else there. They hash from stdin in install.sh, pin shell scripts to LF (v0.28.0's Windows binary embeds a CRLF install.sh), tighten the swap's error handling, and add a Windows CI job. Its real upgrade passes on a GitHub runner.

🤖 Generated with Claude Code

@kklimuk
kklimuk merged commit 22e3e2f into main Oct 31, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant