📝 A .docx file writer with Rust/WebAssembly.
See the code
Read and write .docx files with Rust, WebAssembly, and JavaScript.
[dependencies]
docx-rs = "0.4"
pnpm add docx-wasm
The browser example below also uses file-saver.
pnpm add file-saver
Docx::pack writes the package directly to the output file. Use
Docx::build().pack(...) only when you need access to the rendered XML package
before it is archived.
use docx_rs::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = std::fs::File::create("./hello.docx")?;
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.pack(file)?;
Ok(())
}
read_docx parses a DOCX package into the same Docx model used by the writer.
The model can also be serialized to JSON. Packages whose ASCII ZIP part names
conflict with their resolved filenames are rejected.
use docx_rs::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bytes = std::fs::read("./hello.docx")?;
let docx = read_docx(&bytes)?;
println!("{}", docx.json());
Ok(())
}
Image previews are generated by default. If you only need the original embedded image bytes, disable preview generation to avoid decoding and re-encoding them:
let docx = read_docx_with_options(
&bytes,
ReadDocxOptions::default().with_image_previews(false),
)?;
import { saveAs } from "file-saver";
import("docx-wasm").then((w) => {
const buffer = new w.Docx()
.addParagraph(
new w.Paragraph().addRun(new w.Run().addText("Hello world!"))
)
.build();
saveAs(new Blob([buffer]), "hello.docx");
});
const w = require("docx-wasm");
const { writeFileSync } = require("fs");
const buffer = new w.Docx()
.addParagraph(new w.Paragraph().addRun(new w.Run().addText("Hello world!")))
.build();
writeFileSync("hello.docx", Buffer.from(buffer));
const { readFileSync } = require("fs");
const { readDocx } = require("docx-wasm");
const document = readDocx(readFileSync("./hello.docx"));
console.log(document);
The Rust API supports both document generation and parsing, including:
The WebAssembly package exposes document generation and DOCX-to-JSON parsing for browser and Node.js applications. OOXML is a large specification, so support is not exhaustive.
See the Rust API documentation and examples directory for the full API and focused examples.
rust-toolchain)Run examples from the workspace root:
cargo run -p docx-rs --example hello
The hello example writes output/examples/hello.docx.
Run the Rust test suite and lints from the workspace root:
make test
make lint
Review changed Rust snapshots with:
cargo insta review
Run the WebAssembly/JavaScript tests with:
corepack enable
cd docx-wasm
pnpm install --frozen-lockfile
pnpm test
Update Jest snapshots when an intentional output change requires it:
pnpm test -- --updateSnapshot
See CONTRIBUTING.md for the pull request workflow.
Overall
Maintained
Code review
crates.io
Latest release
Releases this year
195 followers · starred Feb 2026
341 followers · starred Apr 2026
448 followers · starred Nov 2025
443 followers · starred Jan 2023
📝 A .docx file writer with Rust/WebAssembly.
See the code
Read and write .docx files with Rust, WebAssembly, and JavaScript.
[dependencies]
docx-rs = "0.4"
pnpm add docx-wasm
The browser example below also uses file-saver.
pnpm add file-saver
Docx::pack writes the package directly to the output file. Use
Docx::build().pack(...) only when you need access to the rendered XML package
before it is archived.
use docx_rs::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let file = std::fs::File::create("./hello.docx")?;
Docx::new()
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.pack(file)?;
Ok(())
}
read_docx parses a DOCX package into the same Docx model used by the writer.
The model can also be serialized to JSON. Packages whose ASCII ZIP part names
conflict with their resolved filenames are rejected.
use docx_rs::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bytes = std::fs::read("./hello.docx")?;
let docx = read_docx(&bytes)?;
println!("{}", docx.json());
Ok(())
}
Image previews are generated by default. If you only need the original embedded image bytes, disable preview generation to avoid decoding and re-encoding them:
let docx = read_docx_with_options(
&bytes,
ReadDocxOptions::default().with_image_previews(false),
)?;
import { saveAs } from "file-saver";
import("docx-wasm").then((w) => {
const buffer = new w.Docx()
.addParagraph(
new w.Paragraph().addRun(new w.Run().addText("Hello world!"))
)
.build();
saveAs(new Blob([buffer]), "hello.docx");
});
const w = require("docx-wasm");
const { writeFileSync } = require("fs");
const buffer = new w.Docx()
.addParagraph(new w.Paragraph().addRun(new w.Run().addText("Hello world!")))
.build();
writeFileSync("hello.docx", Buffer.from(buffer));
const { readFileSync } = require("fs");
const { readDocx } = require("docx-wasm");
const document = readDocx(readFileSync("./hello.docx"));
console.log(document);
The Rust API supports both document generation and parsing, including:
The WebAssembly package exposes document generation and DOCX-to-JSON parsing for browser and Node.js applications. OOXML is a large specification, so support is not exhaustive.
See the Rust API documentation and examples directory for the full API and focused examples.
rust-toolchain)Run examples from the workspace root:
cargo run -p docx-rs --example hello
The hello example writes output/examples/hello.docx.
Run the Rust test suite and lints from the workspace root:
make test
make lint
Review changed Rust snapshots with:
cargo insta review
Run the WebAssembly/JavaScript tests with:
corepack enable
cd docx-wasm
pnpm install --frozen-lockfile
pnpm test
Update Jest snapshots when an intentional output change requires it:
pnpm test -- --updateSnapshot
See CONTRIBUTING.md for the pull request workflow.
Overall
Maintained
Code review
crates.io
Latest release
Releases this year
195 followers · starred Feb 2026
341 followers · starred Apr 2026
448 followers · starred Nov 2025
443 followers · starred Jan 2023