A pure Rust DOCX library — create, read, and modify Word documents programmatically. Additionally, render pixel-identical PDFs and export to HTML and Markdown, all from the same document object. No LibreOffice, no unoconv, no C dependencies.
Most DOCX solutions in the ecosystem shell out to LibreOffice or wrap C/C++ libraries. rdocx is written entirely in Rust, so it compiles to a single binary with zero runtime dependencies. It works everywhere Rust does — including WASM.
The core focus is DOCX: a high-level, python-docx-inspired API for building and editing Word documents with paragraphs, tables, images, headers/footers, styles, and lists. On top of that, rdocx includes a built-in layout engine that paginates your document and can render it to PDF (with font subsetting, bookmarks, and selectable text) or export to HTML and Markdown — so you get faithful output in every format without leaving Rust.
- Read & write DOCX files with a high-level API
- Tables with merged cells, borders, shading, and content-based column sizing
- Images — inline and anchored, with header/footer background images
- Headers & footers with first-page support and per-section overrides
- Styles — paragraph and character styles, theme color resolution
- Lists with automatic numbering ID management
- Custom lists with independent definitions, per-level number formats, and configurable starting values
- Composable links and line breaks inside paragraphs and table cells
- Template engine with placeholder replacement (plain text and regex)
- TOC generation with internal hyperlinks and dot-leader tabs
- Document merging with style deduplication and numbering remapping
- PDF — built-in layout engine with text shaping (rustybuzz), Unicode line breaking, multi-section pagination, font subsetting, ToUnicode CMap, bookmarks, and images
- HTML — semantic mapping from OOXML with CSS styling and base64-embedded images
- Markdown — GFM-compatible output with pipe tables and formatting
- PNG — page-to-image rendering via tiny-skia rasterizer
- WASM support via standalone
rdocx-wasmcrate - CLI tool (
rdocx-cli) — inspect, convert, diff, replace, validate, render
[dependencies]
rdocx = "0.6"Bundled metric-compatible fonts are always available through the deterministic rendering methods. The default feature adds system font discovery. Disable it when an application should use only deterministic bundled fonts:
[dependencies]
rdocx = { version = "0.6", default-features = false }use rdocx::{Document, Length};
let mut doc = Document::new();
doc.add_paragraph("Hello, World!");
let mut para = doc.add_paragraph("");
para.add_run("Bold text").bold(true);
para.add_run(" and ");
para.add_run("italic text").italic(true);
doc.add_table(3, 4);
doc.save("output.docx").unwrap();use rdocx::Document;
let doc = Document::open("report.docx").unwrap();
for para in doc.paragraphs() {
println!("{}", para.text());
}
for table in doc.tables() {
for row_index in 0..table.row_count() {
let Some(row) = table.row(row_index) else {
continue;
};
for cell_index in 0..row.cell_count() {
let Some(cell) = row.cell(cell_index) else {
continue;
};
print!("{}\t", cell.text());
}
println!();
}
}use rdocx::Document;
let doc = Document::open("report.docx").unwrap();
doc.save_pdf("report.pdf").unwrap();
// Or get bytes directly
let pdf_bytes = doc.to_pdf().unwrap();use rdocx::Document;
let doc = Document::open("report.docx").unwrap();
let html = doc.to_html();
let markdown = doc.to_markdown();use rdocx::Document;
use std::collections::HashMap;
let mut doc = Document::open("template.docx").unwrap();
let mut replacements = HashMap::new();
replacements.insert("{{name}}", "Jane Doe");
replacements.insert("{{date}}", "2025-01-15");
doc.replace_all(&replacements);
doc.save("filled.docx").unwrap();use rdocx::{Document, SectionBreak};
let mut doc = Document::open("part1.docx").unwrap();
let part2 = Document::open("part2.docx").unwrap();
doc.append_with_break(&part2, SectionBreak::NextPage);
doc.save("combined.docx").unwrap();use rdocx::{Document, Length, ListLevel};
let mut doc = Document::new();
let list_id = doc.add_list_definition(&[
ListLevel::bullet(),
ListLevel::decimal().start(3),
]);
doc.add_paragraph("A bullet").set_numbering(list_id, 0);
doc.add_paragraph("Starts at three")
.set_numbering(list_id, 1);
let relationship_id = doc.add_hyperlink_relationship("https://docs.rs/rdocx");
let mut paragraph = doc.add_paragraph("");
paragraph
.add_hyperlink("rdocx API documentation", &relationship_id)
.bold(true);
paragraph.add_line_break();
paragraph.add_run("Continue on a new line.");
let mut table = doc.add_table(1, 2);
assert!(table.set_column_width(0, Length::inches(2.0)));
assert!(table.set_column_width(1, Length::inches(3.0)));
doc.save("authoring.docx")?;
# Ok::<(), rdocx::Error>(())Most applications should depend only on rdocx. The companion crates expose
lower-level boundaries for tools that already own parsed WordprocessingML or
layout data.
| Crate | Use it when |
|---|---|
rdocx |
Creating, reading, editing, or rendering complete DOCX packages |
rdocx-oxml |
Working directly with typed WordprocessingML elements |
rdocx-layout |
Paginating an already assembled LayoutInput |
rdocx-html |
Converting parsed Word content to HTML or Markdown |
rdocx-cli |
Inspecting, converting, validating, or rendering documents from a shell |
rdocx-opc |
Maintaining legacy imports while migrating to oxml-opc |
rdocx-pdf |
Maintaining legacy imports while migrating to oxml-pdf |
Install the CLI:
cargo install rdocx-cli# Inspect document structure
rdocx inspect report.docx
# Extract plain text
rdocx text report.docx
# Convert to PDF
rdocx convert report.docx --to pdf -o report.pdf
# Convert to HTML or Markdown
rdocx convert report.docx --to html -o report.html
rdocx convert report.docx --to md -o report.md
# Find and replace text
rdocx replace report.docx --placeholder "Draft" --value "Final" -o final.docx
# Diff two documents
rdocx diff v1.docx v2.docx| rdocx | python-docx | docx2pdf | pypandoc | |
|---|---|---|---|---|
| Create DOCX | Yes | Yes | -- | -- |
| Read DOCX | Yes | Yes | -- | -- |
| DOCX to PDF | Yes (built-in) | No | Via MS Word | Via Pandoc + LaTeX |
| DOCX to HTML | Yes (built-in) | No | No | Yes (lossy) |
| DOCX to Markdown | Yes (built-in) | No | No | Yes (lossy) |
| Layout engine | Yes | None | Delegates to Word | Delegates to LaTeX |
| External runtime | None | None (but no PDF) | MS Word required | Pandoc + LaTeX |
| Install size | 4 MB binary | ~5 MB | ~31 KB + Word | 300-650 MB |
| Runs in Docker / CI | Yes | Yes (no PDF) | No | Yes (huge image) |
| WASM / browser | Yes | No | No | No |
python-docx is the most popular DOCX library in any language (~14M PyPI downloads/month), but it has zero conversion capabilities — no PDF, no HTML, no Markdown. Users who need PDF must bolt on a separate tool like LibreOffice (~500 MB) or a commercial API. rdocx gives you the same read/write API plus built-in conversion in a single 4 MB binary.
| rdocx | Apache POI | docx4j | Aspose.Words | |
|---|---|---|---|---|
| Create DOCX | Yes | Yes | Yes | Yes |
| Read DOCX | Yes | Yes | Yes | Yes |
| PDF (built-in) | Yes | No | Via FOP (limited) | Yes (high fidelity) |
| HTML (built-in) | Yes | No | Yes | Yes |
| License | MIT / Apache-2.0 | Apache-2.0 | Apache-2.0 | $1,199+ |
| Total dependency size | 4 MB | 18-28 MB + JRE | 50-80 MB + JRE | 14 MB + JRE |
| Typical memory (moderate doc) | 10-50 MB | 256 MB - 1 GB | 256 MB - 2 GB | 50-300 MB |
| Cold start | < 10 ms | 2-5 sec | 2-5 sec | 2-5 sec |
| Runtime required | None | JVM (~200 MB) | JVM (~200 MB) | JVM (~200 MB) |
Java solutions carry the JVM's baseline overhead: 50-100 MB of RAM before a single document is loaded, and 2-5 second cold starts from class loading. Apache POI has no built-in PDF at all. docx4j's FOP pipeline is acknowledged by its own maintainer as limited in fidelity. Aspose has excellent PDF output but costs $1,199+ per developer. rdocx delivers comparable capabilities as a zero-dependency native binary.
| rdocx | docx-rs | docx-rust | ooxmlsdk | |
|---|---|---|---|---|
| Create DOCX | Yes | Yes | Yes | Low-level |
| Read DOCX | Yes | Yes | Yes | Low-level |
| Round-trip preservation | Yes | Limited | Limited | N/A |
| Tables, images, headers | Yes | Yes | Basic | Raw XML |
| PDF conversion | Yes | No | No | No |
| HTML / Markdown export | Yes | No | No | No |
| Layout engine | Yes | No | No | No |
| Page-to-image rendering | Yes | No | No | No |
| Template engine | Yes | No | No | No |
| Document merging | Yes | No | No | No |
| Regex find/replace | Yes | No | No | No |
| CLI tool | Yes | No | No | No |
| WASM | Yes | Yes | No | No |
docx-rs (1M+ downloads, 500+ stars) is the most popular Rust DOCX crate, but it is a read/write library only — no conversion, no layout engine, no PDF. The same is true for every other Rust DOCX crate. rdocx is the only Rust crate that combines DOCX read/write with a built-in layout engine and multi-format output (PDF, HTML, Markdown, PNG).
| Metric | rdocx (native) | Python + LibreOffice | Java (POI + FOP) |
|---|---|---|---|
| Binary / install size | 4 MB | ~500 MB | ~250 MB (JARs + JRE) |
| Memory (moderate document) | 10-50 MB | ~200-500 MB | ~300 MB - 1.5 GB |
| Cold start | < 10 ms | ~2-4 sec (LibreOffice) | ~2-5 sec (JVM) |
| Serverless / Lambda friendly | Yes | Difficult | Difficult |
| Docker image overhead | ~10 MB (musl static) | ~500 MB+ | ~250 MB+ |
| WASM compatible | Yes | No | No |
Migration guidance for the shared crate cutover is in the Unreleased CHANGELOG.
| Family | Crate | Purpose |
|---|---|---|
| Shared | oxml-core |
Units, XML helpers, and document properties |
| Shared | oxml-opc |
OPC package, relationships, and content types |
| Shared | oxml-media |
Image detection, dimensions, and media naming |
| Shared | oxml-drawing |
DrawingML colors, geometry, fills, lines, effects, themes, and text bodies |
| Shared | oxml-layout |
Layout output types, fonts, and line breaking |
| Shared | oxml-pdf |
PDF and PNG rendering backends |
| Shared | oxml-sml |
Minimal SpreadsheetML writer for chart workbooks |
| Word | rdocx |
High-level Document API |
| Word | rdocx-opc |
Deprecated compatibility shim over oxml-opc |
| Word | rdocx-oxml |
WordprocessingML types and oxml-core compatibility re-exports |
| Word | rdocx-layout |
Word flow engine, pagination, blocks, tables, and style resolution |
| Word | rdocx-pdf |
Deprecated compatibility shim over oxml-pdf |
| Word | rdocx-html |
HTML and Markdown conversion |
| Word | rdocx-cli |
CLI binary |
| Word | rdocx-wasm |
WASM bindings |
| PowerPoint | rpptx |
High-level Presentation API |
| PowerPoint | rpptx-oxml |
PresentationML types |
| PowerPoint | rpptx-layout |
Inheritance resolver and flattener |
| PowerPoint | rpptx-render |
Slide renderer |
| PowerPoint | rpptx-chart |
ChartML model and renderer |
1.93 (edition 2024)
Licensed under either of
- MIT license (LICENSE or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
at your option.