Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions crates/office2pdf/examples/custom_options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! Convert with custom options (paper size, slide range, sheet filter).
//!
//! Usage:
//! cargo run --example custom_options -- input.pptx output.pdf

use std::env;
use std::fs;
use std::process;

use office2pdf::config::{ConvertOptions, PaperSize, SlideRange};

fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
eprintln!("Usage: {} <input> <output.pdf>", args[0]);
process::exit(1);
}

let input = &args[1];
let output = &args[2];

let options = ConvertOptions {
// Use A4 paper
paper_size: Some(PaperSize::A4),
// Only include slides 1 through 3 (for PPTX)
slide_range: Some(SlideRange::new(1, 3)),
// Only include these sheets (for XLSX)
sheet_names: Some(vec!["Summary".to_string(), "Data".to_string()]),
// Force landscape orientation
landscape: Some(true),
..Default::default()
};

match office2pdf::convert_with_options(input, &options) {
Ok(result) => {
fs::write(output, &result.pdf).expect("failed to write PDF");
println!("Wrote {} bytes to {output}", result.pdf.len());
}
Err(e) => {
eprintln!("Conversion failed: {e}");
process::exit(1);
}
}
}
48 changes: 48 additions & 0 deletions crates/office2pdf/examples/from_bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Convert from in-memory bytes instead of a file path.
//!
//! Usage:
//! cargo run --example from_bytes -- input.xlsx output.pdf

use std::env;
use std::fs;
use std::process;

use office2pdf::config::{ConvertOptions, Format};

fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
eprintln!("Usage: {} <input> <output.pdf>", args[0]);
process::exit(1);
}

let input = &args[1];
let output = &args[2];

// Read file into memory
let data = fs::read(input).expect("failed to read input file");

// Detect format from extension
let ext = input.rsplit('.').next().unwrap_or("");
let format = Format::from_extension(ext).unwrap_or_else(|| {
eprintln!("Unsupported extension: .{ext}");
process::exit(1);
});

// Convert from bytes
match office2pdf::convert_bytes(&data, format, &ConvertOptions::default()) {
Ok(result) => {
fs::write(output, &result.pdf).expect("failed to write PDF");
println!(
"Converted {} bytes of {:?} → {} bytes of PDF",
data.len(),
format,
result.pdf.len()
);
}
Err(e) => {
eprintln!("Conversion failed: {e}");
process::exit(1);
}
}
}
37 changes: 37 additions & 0 deletions crates/office2pdf/examples/simple_convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Convert an Office document to PDF.
//!
//! Usage:
//! cargo run --example simple_convert -- input.docx output.pdf

use std::env;
use std::fs;
use std::process;

fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
eprintln!("Usage: {} <input> <output.pdf>", args[0]);
eprintln!(" Supported formats: .docx, .pptx, .xlsx");
process::exit(1);
}

let input = &args[1];
let output = &args[2];

match office2pdf::convert(input) {
Ok(result) => {
if !result.warnings.is_empty() {
eprintln!("{} warning(s):", result.warnings.len());
for w in &result.warnings {
eprintln!(" - {w}");
}
}
fs::write(output, &result.pdf).expect("failed to write PDF");
println!("Wrote {} bytes to {output}", result.pdf.len());
}
Err(e) => {
eprintln!("Conversion failed: {e}");
process::exit(1);
}
}
}
3 changes: 3 additions & 0 deletions crates/office2pdf/src/ir/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@ pub struct Color {
}

impl Color {
/// Create a color from RGB components.
pub fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}

/// Black (`#000000`).
pub fn black() -> Self {
Self { r: 0, g: 0, b: 0 }
}

/// White (`#FFFFFF`).
pub fn white() -> Self {
Self {
r: 255,
Expand Down
60 changes: 60 additions & 0 deletions crates/office2pdf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
//! Pure-Rust conversion of Office documents (DOCX, PPTX, XLSX) to PDF.
//!
//! # Quick start
//!
//! ```no_run
//! let result = office2pdf::convert("report.docx").unwrap();
//! std::fs::write("report.pdf", &result.pdf).unwrap();
//! ```
//!
//! # With options
//!
//! ```no_run
//! use office2pdf::config::{ConvertOptions, PaperSize, SlideRange};
//!
//! let options = ConvertOptions {
//! paper_size: Some(PaperSize::A4),
//! slide_range: Some(SlideRange::new(1, 5)),
//! ..Default::default()
//! };
//! let result = office2pdf::convert_with_options("slides.pptx", &options).unwrap();
//! std::fs::write("slides.pdf", &result.pdf).unwrap();
//! ```
//!
//! # In-memory conversion
//!
//! ```no_run
//! use office2pdf::config::{ConvertOptions, Format};
//!
//! let docx_bytes = std::fs::read("report.docx").unwrap();
//! let result = office2pdf::convert_bytes(&docx_bytes, Format::Docx, &ConvertOptions::default()).unwrap();
//! std::fs::write("report.pdf", &result.pdf).unwrap();
//! ```

pub mod config;
pub mod error;
pub mod ir;
Expand All @@ -11,11 +44,25 @@ use error::{ConvertError, ConvertResult};
use parser::Parser;

/// Convert a file at the given path to PDF bytes with warnings.
///
/// Detects the format from the file extension (`.docx`, `.pptx`, `.xlsx`).
///
/// # Errors
///
/// Returns [`ConvertError::UnsupportedFormat`] if the extension is unrecognized,
/// [`ConvertError::Io`] if the file cannot be read, or other variants for
/// parse/render failures.
pub fn convert(path: impl AsRef<Path>) -> Result<ConvertResult, ConvertError> {
convert_with_options(path, &ConvertOptions::default())
}

/// Convert a file at the given path to PDF bytes with options.
///
/// See [`ConvertOptions`] for available settings (paper size, sheet filter, etc.).
///
/// # Errors
///
/// Returns [`ConvertError`] on unsupported format, I/O, parse, or render failure.
pub fn convert_with_options(
path: impl AsRef<Path>,
options: &ConvertOptions,
Expand All @@ -34,6 +81,13 @@ pub fn convert_with_options(
}

/// Convert raw bytes of a known format to PDF bytes with warnings.
///
/// Use this when you already have the file contents in memory and know the
/// [`Format`].
///
/// # Errors
///
/// Returns [`ConvertError`] on parse or render failure.
pub fn convert_bytes(
data: &[u8],
format: Format,
Expand All @@ -58,8 +112,14 @@ pub fn convert_bytes(

/// Render an IR Document to PDF bytes.
///
///// Render an IR [`Document`](ir::Document) directly to PDF bytes.
///
/// Takes a fully constructed [`ir::Document`] and runs it through
/// the Typst codegen → PDF compilation pipeline.
///
/// # Errors
///
/// Returns [`ConvertError::Render`] if Typst compilation or PDF export fails.
pub fn render_document(doc: &ir::Document) -> Result<Vec<u8>, ConvertError> {
let output = render::typst_gen::generate_typst(doc)?;
render::pdf::compile_to_pdf(&output.source, &output.images, None, &[])
Expand Down
1 change: 1 addition & 0 deletions crates/office2pdf/src/parser/docx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::ir::{
};
use crate::parser::Parser;

/// Parser for DOCX (Office Open XML Word) documents.
pub struct DocxParser;

/// Map from relationship ID → PNG image bytes.
Expand Down
1 change: 1 addition & 0 deletions crates/office2pdf/src/parser/pptx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum SolidFillCtx {
RunFill,
}

/// Parser for PPTX (Office Open XML PowerPoint) presentations.
pub struct PptxParser;

/// Parsed theme data from ppt/theme/theme1.xml.
Expand Down
1 change: 1 addition & 0 deletions crates/office2pdf/src/parser/xlsx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::parser::Parser;
use crate::parser::chart::parse_chart_xml;
use crate::parser::cond_fmt::build_cond_fmt_overrides;

/// Parser for XLSX (Office Open XML Excel) spreadsheets.
pub struct XlsxParser;

/// Default column width in Excel character units.
Expand Down
2 changes: 1 addition & 1 deletion scripts/ralph/prd.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
"cargo clippy --workspace -- -D warnings passes"
],
"priority": 10,
"passes": false,
"passes": true,
"notes": ""
}
]
Expand Down
28 changes: 28 additions & 0 deletions scripts/ralph/progress.txt
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,31 @@ Started: 2026년 2월 27일 금요일 12시 19분 03초 KST
- scripts/ralph/prd.json (US-048 passes: true)
- Dependencies added: none
---

## US-049: API documentation and examples
- Status: DONE
- Added crate-level documentation to lib.rs with three usage examples (quick start, with options, in-memory)
- Added doc comments to all previously undocumented public items:
- DocxParser, PptxParser, XlsxParser structs
- Color::new(), Color::black(), Color::white() methods
- Enhanced convert(), convert_with_options(), convert_bytes(), render_document() with Errors sections
- Created 3 example programs:
- examples/simple_convert.rs: basic file-to-PDF conversion
- examples/custom_options.rs: ConvertOptions usage (paper size, slide range, sheet filter, landscape)
- examples/from_bytes.rs: in-memory byte conversion with Format detection
- 3 doc tests pass (compile-only, from crate-level examples)
- cargo doc -p office2pdf --no-deps: clean (no warnings)
- cargo doc --workspace --no-deps: only known cargo filename collision bug (#6313)
- All quality checks pass: 485 lib + 7 CLI + 3 doc tests, clippy clean, fmt clean
- Files changed:
- crates/office2pdf/src/lib.rs (crate-level docs, enhanced function docs)
- crates/office2pdf/src/ir/style.rs (Color method docs)
- crates/office2pdf/src/parser/docx.rs (DocxParser doc)
- crates/office2pdf/src/parser/pptx.rs (PptxParser doc)
- crates/office2pdf/src/parser/xlsx.rs (XlsxParser doc)
- crates/office2pdf/examples/simple_convert.rs (new)
- crates/office2pdf/examples/custom_options.rs (new)
- crates/office2pdf/examples/from_bytes.rs (new)
- scripts/ralph/prd.json (US-049 passes: true)
- Dependencies added: none
---