ferrisume_core/export/
pdf.rs1use std::fmt::Debug;
2use std::io;
3use std::io::Write;
4
5use anyhow::Result;
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8use wkhtmltopdf::{Orientation, PageSize, PdfApplication, Size};
9
10#[derive(Error, Debug)]
11pub enum PdfExportError {
12 #[error("Invalid paper size {0}")]
13 InvalidPaperSize(String),
14 #[error("Invalid margin definition '{0}'")]
15 InvalidMarginDefinition(String),
16 #[error("Invalid margin value: {0}")]
17 InvalidMarginValue(std::num::ParseFloatError),
18 #[error("Headless chrome error: {0}")]
19 HeadlessChromeError(#[from] anyhow::Error),
20 #[error("IO error: {0}")]
21 IoError(#[from] io::Error),
22 #[error("wkhtmltopdf error: {0}")]
23 WkHtmlToPdfError(#[from] wkhtmltopdf::Error),
24}
25
26#[derive(Serialize, Deserialize)]
27pub struct PdfExportOptions {
28 pub paper_size: String,
29 pub margins: Vec<String>,
30}
31
32pub fn export_to_pdf(
33 html_content: &str,
34 output_path: &str,
35 options: &PdfExportOptions,
36) -> Result<(), PdfExportError> {
37 let pdf_app = PdfApplication::new()?;
38
39 let mut pdf = &mut pdf_app.builder();
40
41 pdf = pdf
42 .orientation(Orientation::Portrait)
43 .margin(Size::Inches(options.margins[0].parse().unwrap_or(10)))
44 .title("Resume");
45
46 match options.paper_size.to_lowercase().as_str() {
47 "a4" => pdf = pdf.page_size(PageSize::A4),
48 "letter" => pdf = pdf.page_size(PageSize::Letter),
49 _ => return Err(PdfExportError::InvalidPaperSize(options.paper_size.clone())),
50 }
51
52 pdf.build_from_html(html_content)?.save(&output_path)?;
53
54 Ok(())
55}