RC RANDOM CHAOS

The .docx in your webmail preview pane

A read-only OOXML viewer written entirely by AI agents: Rust-in-WASM parsers that render DOCX, XLSX and PPTX without running macros, formulas or fields.

· 4 min read
The .docx in your webmail preview pane

No human wrote the application code in this project. The Rust parsers, the TypeScript renderers, the tests, the tooling: all of it was produced by AI coding agents, mainly Claude and Codex, through iterative prompting. The author’s claim is that @silurus/ooxml, a browser viewer for Office Open XML, exists because generative AI finally made the economics work.

The argument for why it took AI goes like this. OOXML’s behaviour is pinned by a written spec (ECMA-376 / ISO-29500), and there is a reference oracle to check against, which is Word, Excel and PowerPoint themselves. Anyone patient enough could build a faithful viewer. For more than a decade nobody did in open source, because reading and implementing the spec faithfully costs more effort than volunteers spend; the commercial libraries with decent fidelity price themselves out of casual use. A viewer turns out to be a good fit for iterative AI work: a spec to read, a correct output to match, refine until the pixels line up. The author says it already reproduces desktop Office more faithfully than some commercial libraries for certain documents, and occasionally beats the Microsoft 365 web apps.

What it is, concretely: Rust parsers compiled to WebAssembly, rendering to an HTML Canvas through the Canvas 2D API. One package covers DOCX, XLSX and PPTX, each with a viewer and a headless engine you can point at your own canvas. There are scroll viewers for a PDF-reader-style surface, a worker mode that renders inside a Web Worker and hands back an ImageBitmap so the main thread only paints, and framework examples for React, Vue, Svelte and Solid.

The part that matters if you render documents you did not create is how little the viewer does with them. Editing, mutation, saving and round-tripping are explicitly out of scope; the author frames read-only as dodging the worst thing an Office library can do, which is corrupt a user’s files. The useful property for anyone putting a viewer in front of untrusted input is what the parsers refuse to do. The experimental legacy binary readers (.doc, .xls, .ppt) do not execute macros, fields, formulas, actions or embedded objects, and they reject content outside their supported subset with a typed error rather than showing a partial document. Hyperlinks are scheme-sanitised to http, https, mailto and tel, and opened with noopener. The MathJax equation engine is self-contained and served from your own origin with no cross-origin requests. The offline Region Map renderer is deterministic and network-free, built on a pinned Natural Earth dataset, and fails closed for layouts its bounded model cannot represent safely. The selection-context API that hands a user’s current focus to an AI assistant returns a detached, JSON-serialisable snapshot with hard size limits and never sends anything over the network.

That is close to the behaviour you want behind a preview pane. A Word file lands, gets rendered automatically, and nothing inside it runs. Parsing happens inside WASM, rendering goes to a canvas, and the OOXML features that make Office documents a perennial malware vector are either out of scope or stubbed to a placeholder.

Two things temper that. The optional-module design does keep the default graph small: MathJax, ChartEx, 3-D charts, Region Map and TIFF decoding stay outside the application graph unless you import them, so you ship and expose only the renderers you asked for. But the whole thing is a parser for attacker-controllable input, and that parser was written by language models with no human author. Rust buys memory safety against a class of bugs; it does not buy correct handling of malformed input, and a preview pane is exactly where malformed input arrives on purpose. The legacy readers are flagged narrow and experimental, and some of their native budgets surface as untyped errors. Fuzz the parsers before you point them at anything hostile.

Install is npm install @silurus/ooxml. The WASM ships as real .wasm asset files referenced with new URL('...', import.meta.url) and streaming-compiled at load, and it works with zero config on webpack 5, Next.js, Vite 8 and a bare <script type="module">. Vite 7’s dev server needs optimizeDeps: { exclude: ['@silurus/ooxml'] }, and esbuild-based builders including the Angular CLI need you to copy the *_parser_bg.wasm asset into your served output and point the viewer at it with the wasmUrl load option, which also lets you serve the parser from a CDN.

Share

Keep Reading

Latest on the Wire

Full wire →

New signal daily · RSS

Stay in the loop

New writing delivered when it's ready. No schedule, no spam.