Skip to main content

office2pdf/
lib.rs

1//! Pure-Rust conversion of Office documents (DOCX, PPTX, XLSX) to PDF.
2//!
3//! # Quick start (native only)
4//!
5//! ```no_run
6//! # #[cfg(not(target_arch = "wasm32"))]
7//! # {
8//! let result = office2pdf::convert("report.docx").unwrap();
9//! std::fs::write("report.pdf", &result.pdf).unwrap();
10//! # }
11//! ```
12//!
13//! # With options (native only)
14//!
15//! ```no_run
16//! # #[cfg(not(target_arch = "wasm32"))]
17//! # {
18//! use office2pdf::config::{ConvertOptions, PaperSize, SlideRange};
19//!
20//! let options = ConvertOptions {
21//!     paper_size: Some(PaperSize::A4),
22//!     slide_range: Some(SlideRange::new(1, 5)),
23//!     ..Default::default()
24//! };
25//! let result = office2pdf::convert_with_options("slides.pptx", &options).unwrap();
26//! std::fs::write("slides.pdf", &result.pdf).unwrap();
27//! # }
28//! ```
29//!
30//! # In-memory conversion (works on all targets including WASM)
31//!
32//! ```no_run
33//! use office2pdf::config::{ConvertOptions, Format};
34//!
35//! let docx_bytes = std::fs::read("report.docx").unwrap();
36//! let result = office2pdf::convert_bytes(&docx_bytes, Format::Docx, &ConvertOptions::default()).unwrap();
37//! std::fs::write("report.pdf", &result.pdf).unwrap();
38//! ```
39
40pub mod config;
41pub(crate) mod defaults;
42pub mod error;
43pub mod ir;
44pub(crate) mod parser;
45#[cfg(feature = "pdf-ops")]
46pub mod pdf_ops;
47pub(crate) mod render;
48#[cfg(feature = "wasm")]
49pub mod wasm;
50
51/// Implementation details re-exported for this crate's own integration tests.
52///
53/// Not part of the public API — no semver guarantees. Use [`convert`],
54/// [`convert_bytes`], or [`render_document`] instead.
55#[doc(hidden)]
56pub mod internal {
57    pub use crate::parser::Parser;
58    pub use crate::parser::docx::DocxParser;
59    pub use crate::parser::pptx::PptxParser;
60    pub use crate::parser::xlsx::XlsxParser;
61    pub use crate::render::typst_gen::{TypstOutput, generate_typst};
62}
63
64use config::{ConvertOptions, Format};
65use error::{ConvertError, ConvertResult};
66#[path = "lib_pipeline.rs"]
67mod pipeline;
68#[cfg(test)]
69#[path = "lib_test_support.rs"]
70pub(crate) mod test_support;
71
72#[cfg(test)]
73fn is_ole2(data: &[u8]) -> bool {
74    pipeline::is_ole2(data)
75}
76
77#[cfg(not(target_arch = "wasm32"))]
78#[cfg(test)]
79fn should_resolve_font_context(doc: &ir::Document, options: &ConvertOptions) -> bool {
80    pipeline::should_resolve_font_context(doc, options, false)
81}
82
83/// Convert a file at the given path to PDF bytes with warnings.
84///
85/// Detects the format from the file extension (`.docx`, `.pptx`, `.xlsx`).
86///
87/// This function is not available on `wasm32` targets because it reads from the
88/// filesystem. Use [`convert_bytes`] for in-memory conversion on WASM.
89///
90/// # Errors
91///
92/// Returns [`ConvertError::UnsupportedFormat`] if the extension is unrecognized,
93/// [`ConvertError::Io`] if the file cannot be read, or other variants for
94/// parse/render failures.
95#[cfg(not(target_arch = "wasm32"))]
96pub fn convert(path: impl AsRef<std::path::Path>) -> Result<ConvertResult, ConvertError> {
97    pipeline::convert(path)
98}
99
100/// Convert a file at the given path to PDF bytes with options.
101///
102/// See [`ConvertOptions`] for available settings (paper size, sheet filter, etc.).
103///
104/// This function is not available on `wasm32` targets because it reads from the
105/// filesystem. Use [`convert_bytes`] for in-memory conversion on WASM.
106///
107/// # Errors
108///
109/// Returns [`ConvertError`] on unsupported format, I/O, parse, or render failure.
110#[cfg(not(target_arch = "wasm32"))]
111pub fn convert_with_options(
112    path: impl AsRef<std::path::Path>,
113    options: &ConvertOptions,
114) -> Result<ConvertResult, ConvertError> {
115    pipeline::convert_with_options(path, options)
116}
117
118/// Convert raw bytes of a known format to PDF bytes with warnings.
119///
120/// Use this when you already have the file contents in memory and know the
121/// [`Format`].
122///
123/// When `options.streaming` is `true` and the format is XLSX, the conversion
124/// processes rows in chunks to bound peak memory during Typst compilation.
125/// This requires the `pdf-ops` feature for PDF merging.
126///
127/// # Errors
128///
129/// Returns [`ConvertError`] on parse or render failure.
130pub fn convert_bytes(
131    data: &[u8],
132    format: Format,
133    options: &ConvertOptions,
134) -> Result<ConvertResult, ConvertError> {
135    pipeline::convert_bytes(data, format, options)
136}
137
138/// Render an IR Document to PDF bytes.
139///
140///// Render an IR [`Document`](ir::Document) directly to PDF bytes.
141///
142/// Takes a fully constructed [`ir::Document`] and runs it through
143/// the Typst codegen → PDF compilation pipeline.
144///
145/// # Errors
146///
147/// Returns [`ConvertError::Render`] if Typst compilation or PDF export fails.
148pub fn render_document(doc: &ir::Document) -> Result<Vec<u8>, ConvertError> {
149    pipeline::render_document(doc)
150}
151
152#[cfg(test)]
153#[path = "lib_pipeline_tests.rs"]
154mod pipeline_tests;
155
156#[cfg(test)]
157#[path = "lib_render_tests.rs"]
158mod render_tests;
159
160#[cfg(test)]
161#[path = "lib_conversion_tests.rs"]
162mod conversion_tests;
163
164#[cfg(test)]
165#[path = "lib_robustness_tests.rs"]
166mod robustness_tests;
167
168#[cfg(all(test, feature = "typescript"))]
169#[path = "lib_ts_integration_tests.rs"]
170mod ts_integration_tests;
171
172#[cfg(all(test, feature = "pdf-ops"))]
173#[path = "lib_streaming_tests.rs"]
174mod streaming_tests;