Skip to content

Repository files navigation

rdocx

CI crates.io docs.rs License: MIT/Apache-2.0 MSRV: 1.93

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.

Why rdocx?

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.

DOCX Features

  • 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

Output Formats

  • 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

Extras

  • WASM support via standalone rdocx-wasm crate
  • CLI tool (rdocx-cli) — inspect, convert, diff, replace, validate, render

Installation

[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 }

Quick Start

Create a document

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();

Read a document

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!();
    }
}

Convert to PDF

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();

Convert to HTML / Markdown

use rdocx::Document;

let doc = Document::open("report.docx").unwrap();

let html = doc.to_html();
let markdown = doc.to_markdown();

Template replacement

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();

Merge documents

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();

Custom lists, links, and fixed table columns

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>(())

Stable crate family

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

CLI

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

How rdocx Compares

vs. Python Libraries

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.

vs. Java Libraries

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.

vs. Other Rust Crates

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).

Resource Footprint

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

Crate Architecture

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

Minimum Supported Rust Version

1.93 (edition 2024)

License

Licensed under either of

at your option.

About

No description, website, or topics provided.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages