pub mod code;
pub mod cover;
pub mod diff;
pub mod fonts;
pub mod layout;
pub mod toc;
pub mod tree;
pub mod user_activity;
pub mod user_cover;
pub mod user_repos;
use std::path::Path;
use printpdf::{Mm, PdfDocument, PdfSaveOptions};
use crate::types::{Config, PaperSize, UserReportConfig};
use layout::{FontSet, PageBuilder};
fn paper_dimensions(config: &Config) -> (Mm, Mm) {
let (w, h) = match config.paper_size {
PaperSize::A4 => (Mm(210.0), Mm(297.0)),
PaperSize::Letter => (Mm(215.9), Mm(279.4)),
PaperSize::Legal => (Mm(215.9), Mm(355.6)),
};
if config.landscape { (h, w) } else { (w, h) }
}
pub fn create_builder(config: &Config, fonts: FontSet) -> PageBuilder {
create_builder_at_page(config, fonts, 1)
}
pub fn create_builder_at_page(
config: &Config,
fonts: FontSet,
starting_page: usize,
) -> PageBuilder {
let (w, h) = paper_dimensions(config);
let line_height = config.font_size as f32 + 2.0;
PageBuilder::new(w, h, Mm(10.0), line_height, fonts, starting_page)
}
pub fn create_user_builder(config: &UserReportConfig, fonts: FontSet) -> PageBuilder {
create_user_builder_at_page(config, fonts, 1)
}
pub fn create_user_builder_at_page(
config: &UserReportConfig,
fonts: FontSet,
starting_page: usize,
) -> PageBuilder {
let (w, h) = match config.paper_size {
PaperSize::A4 => (Mm(210.0), Mm(297.0)),
PaperSize::Letter => (Mm(215.9), Mm(279.4)),
PaperSize::Legal => (Mm(215.9), Mm(355.6)),
};
let (w, h) = if config.landscape { (h, w) } else { (w, h) };
let line_height = config.font_size as f32 + 2.0;
PageBuilder::new(w, h, Mm(10.0), line_height, fonts, starting_page)
}
pub async fn save_pdf(doc: &PdfDocument, path: &Path) -> anyhow::Result<()> {
let mut warnings = Vec::new();
let bytes = doc.save(&PdfSaveOptions::default(), &mut warnings);
tokio::fs::write(path, bytes).await.map_err(Into::into)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::Config;
#[test]
fn paper_dimensions_a4() {
let config = Config::test_default();
let (w, h) = paper_dimensions(&config);
assert_eq!(w.0, 210.0);
assert_eq!(h.0, 297.0);
}
#[test]
fn paper_dimensions_letter() {
let mut config = Config::test_default();
config.paper_size = PaperSize::Letter;
let (w, h) = paper_dimensions(&config);
assert_eq!(w.0, 215.9);
assert_eq!(h.0, 279.4);
}
#[test]
fn paper_dimensions_landscape() {
let mut config = Config::test_default();
config.landscape = true;
let (w, h) = paper_dimensions(&config);
assert_eq!(w.0, 297.0);
assert_eq!(h.0, 210.0);
}
#[tokio::test]
async fn save_pdf_to_tempfile() {
let mut doc = PdfDocument::new("test");
let fonts = fonts::load_fonts(&mut doc).unwrap();
let config = Config::test_default();
let builder = create_builder(&config, fonts);
doc.with_pages(builder.finish());
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("test.pdf");
assert!(save_pdf(&doc, &path).await.is_ok());
assert!(path.exists());
assert!(std::fs::metadata(&path).unwrap().len() > 0);
}
#[tokio::test]
async fn save_pdf_invalid_path() {
let mut doc = PdfDocument::new("test");
let _ = fonts::load_fonts(&mut doc).unwrap();
let result = save_pdf(&doc, Path::new("/nonexistent/dir/test.pdf")).await;
assert!(result.is_err());
}
}