docx-to-md reads DOCX and ODT packages with a namespace-tolerant pull parser. It exposes a structured
document model and renders that model to Markdown.
The parser does not evaluate fields, macros, track changes, charts, embedded objects, content controls, or page layout.
- DOCX and ODT support: Detects and reads Microsoft Word
.docxand OpenDocument Text.odtpackages. - Markdown and structured output: Renders documents to Markdown and exposes a reusable document model for custom processing.
- Document blocks: Parses titles, subtitles, paragraphs, headings, block quotes, nested ordered and unordered lists, and tables.
- Inline content and formatting: Preserves text, hyperlinks, line breaks, bold, italic, underline, strikethrough, superscript, and subscript where supported by the source format.
- Images: Loads referenced image resources and can embed them as base64
data:URLs, retain them for custom handling, or save and link them with absolutefile:URLs. - Annotations and stories: Optionally includes DOCX and ODT headers, footers, comments, footnotes, endnotes, and section associations.
- Metadata and provenance: Provides common document metadata as well as source-part, story, section, and style information for parsed elements.
The DocumentContainer struct provides a convenient interface to the
document model.
use docx_to_md::{DocumentContainer, ParserConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let package = DocumentContainer::open("report.docx", ParserConfig::default())?;
let markdown = package.convert_to_md()?;
std::fs::write("report.md", markdown)?;
Ok(())
}The DocumentContainer struct also provides access to the document metadata.
Metadata can be read without parsing the main story:
use docx_to_md::{DocumentContainer, ParserConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let package = DocumentContainer::open("report.docx", ParserConfig::default())?;
println!("{:?}", package.metadata().title);
Ok(())
}The DocumentContainer struct also provides access to the main story blocks.
iter_blocks uses the same event parser as parse_all and returns main-story
blocks in source order. parse_all additionally resolves headers, footers,
comments, footnotes, endnotes, sections, and image resources.
use docx_to_md::{DocumentContainer, ParserConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let package = DocumentContainer::open("report.docx", ParserConfig::default())?;
for block in package.iter_blocks()? {
println!("{:?}", block?);
}
Ok(())
}iter_pages lazily reads the main XML story and yields self-contained,
one-based DocumentPage values. Boundaries are block-aligned: a marker inside
a paragraph, a list, or a table cell takes effect only after the complete
top-level block. iter_pages_with(PageBoundaryMode) can select explicit
breaks, stored renderer hints, or both.
use docx_to_md::{DocumentContainer, ParserConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let document = DocumentContainer::open("report.docx", ParserConfig::default())?;
for page in document.iter_pages()? {
let page = page?;
println!("Page {}", page.page_number);
println!("{}", page.to_markdown()?);
}
Ok(())
}DOCX lastRenderedPageBreak and ODT soft-page-break values are stored
layout hints. The crate does not run Word, LibreOffice, or another layout
engine, so streamed pages are a structural approximation rather than newly
calculated physical pages.
Images default to embedded data URLs. To save and link them instead:
use docx_to_md::{DocumentContainer, ImageHandlingMode, ParserConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = ParserConfig::builder()
.image_handling_mode(ImageHandlingMode::Save)
.image_output_path("output/images")
.build();
let package = DocumentContainer::open("report.docx", config)?;
let markdown = package.convert_to_md()?;
std::fs::write("output/report.md", markdown)?;
Ok(())
}For a separate extraction workflow, parse once and call
document.extract_images("output/images"); ImageResource::base64() is also
available for custom storage.
for more usage examples, see the examples directory.
| Parameter | Type | Default | Description |
|---|---|---|---|
extract_images |
bool |
true |
Whether referenced image resources are loaded into the document. When false, image references and image data are omitted. |
compress_images |
bool |
true |
Whether non-SVG images are converted to JPEG while loading; this also affects images saved or accessed from the document model. |
quality |
u8 |
80 |
JPEG quality used when compress_images is enabled. The builder caps values at 100; higher values favor quality over file size. |
image_handling_mode |
ImageHandlingMode |
InMarkdown |
Determines whether loaded images are embedded in Markdown, omitted from it, or saved and linked with file: URLs. |
image_output_path |
Option<PathBuf> |
None |
Directory used by ImageHandlingMode::Save; required in save mode. |
include_document_metadata |
bool |
true |
Whether document metadata is rendered as an HTML comment at the beginning of the Markdown. |
include_headers_footers |
bool |
true |
Whether headers and footers are parsed and rendered in a Headers and Footers section. |
include_footnotes |
bool |
true |
Whether footnotes are parsed and rendered as Markdown footnote references and definitions. |
include_endnotes |
bool |
true |
Whether endnotes are parsed and rendered as Markdown footnote references and definitions. |
include_comments |
bool |
false |
Whether comments are parsed, referenced inline, and rendered in a Comments blockquote section. |
include_page_number_as_comment |
bool |
true |
Prefixes page-local Markdown with <!-- Page n -->; full-document Markdown ignores this option. |
| Member | Description |
|---|---|
InMarkdown |
Images are embedded in Markdown image syntax as base64 data: URLs. |
Manually |
Image bytes remain in the structured document model but image markup is omitted from Markdown. |
Save |
Images are saved to image_output_path and referenced in Markdown image syntax with absolute file: URLs. |
Include the following line in your Cargo.toml dependencies section:
[dependencies]
docx-to-md = "0.1.0"This project is licensed under the MIT-License and Apache 2.0-Licence.
Feel free to contribute or suggest improvements! π