Doc Preview (VS Code)
VS Code port of the Obsidian Doc Preview plugin. Previews PowerPoint, Word, and Excel files via a local LibreOffice install, auto-refreshing when the file changes on disk.
Status
Ported and building, with the LibreOffice pipeline verified end-to-end against a real install (detectLibreOffice → convertToPdf → text re-extracted from the resulting PDF, all correct).
Architecture
Obsidian plugins run inside Electron's renderer, which has both a full DOM and direct Node (fs/child_process) access — that's a hybrid environment a VS Code extension doesn't have. A VS Code extension host is plain Node (no DOM); a VS Code webview is a real, sandboxed browser context (DOM, but no filesystem access). This plugin's code split cleanly along that line:
src/ — runs in the extension host (Node). libreoffice/{detect,convert,install,miniZip,xlsxSheets}.ts are copied from the Obsidian plugin almost verbatim — they were already pure Node (spawning soffice, reading files, parsing a .xlsx's zip/XML directly), aside from convert.ts's window.setTimeout/clearTimeout calls, which needed to become plain setTimeout/clearTimeout (no window in the extension host). extension.ts is new: it implements CustomReadonlyEditorProvider, converts the source file to a cached PDF, and talks to the webview over postMessage.
webview/ — runs inside the webview (a real Chromium context, bundled separately with platform: "browser"). pdfviewer.ts is the Obsidian plugin's PdfViewer.ts — canvas rendering, zoom/rotate/pan, thumbnails, sheet tabs, the Blob-URL worker trick — almost unchanged, since a webview supports the same Blob/Worker/Canvas APIs Obsidian's renderer does. Three things had to change: it reads the PDF via pdfjsLib.getDocument({ url }) against a vscode-webview-resource: URI instead of fs.readFileSync (webviews have no filesystem access); obsidian's setIcon() is replaced by hand-drawn SVGs in icons.ts; and the Electron-native save dialog is replaced by a postMessage({type: "download"}) round-trip to the host, which does have fs/vscode.window.showSaveDialog. dom-helpers.ts shims Obsidian's createDiv/addClass/etc. onto Element.prototype so the rest of pdfviewer.ts didn't need line-by-line rewriting.
Host and webview are two separate esbuild bundles (dist/extension.js, dist/webview.js) built by the same esbuild.config.mjs.
Configuration
docPreview.customInstallDir — custom LibreOffice install directory, checked before default OS locations.
- Command Doc Preview: Install LibreOffice — downloads and installs LibreOffice into that directory (or a suggested default), with progress in a notification.
Development
npm install
npm run dev # esbuild watch mode (both bundles)
Press F5 in VS Code to launch an Extension Development Host, then open a .pptx/.docx/.xlsx file with "Reopen With → Doc Preview" (priority is option, not default).
Build & Package
npm run build
npm run package # produces a .vsix via vsce
Both pdfjs-dist and https-proxy-agent are fully bundled into dist/ by esbuild — unlike convert-to-markdown, nothing needs to ship as a real node_modules dependency, so .vscodeignore excludes node_modules entirely.