pub mod assemble;
pub mod compile;
pub mod latex;
pub mod walk;
use crate::zimignore::ZimIgnore;
use std::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
pub struct GenerateOptions {
pub root: PathBuf,
pub output: PathBuf,
pub title: String,
pub author: Option<String>,
pub keep_tex: bool,
}
pub struct GenerateStats {
pub num_files: usize,
pub num_dirs: usize,
pub output: PathBuf,
pub kept_tex: Option<PathBuf>,
}
pub fn generate(opts: &GenerateOptions) -> Result<GenerateStats, Box<dyn Error>> {
let zimignore = ZimIgnore::load_for_directory(&opts.root);
let tree = walk::walk(&opts.root, &zimignore)?;
if tree.is_empty() {
return Err(format!("no .md files found under {}", opts.root.display()).into());
}
let num_dirs = tree.len();
let num_files: usize = tree.iter().map(|d| d.file_count()).sum();
let latex_source = assemble::build_latex(
&tree,
&assemble::PdfOptions {
title: opts.title.clone(),
author: opts.author.clone(),
},
)?;
let work_dir = std::env::temp_dir().join(format!("zim-pdf-{}", std::process::id()));
let pdf_path = compile::compile(&latex_source, &work_dir)?;
if let Some(parent) = opts.output.parent()
&& !parent.as_os_str().is_empty()
{
fs::create_dir_all(parent)?;
}
fs::copy(&pdf_path, &opts.output)?;
let kept_tex = if opts.keep_tex {
let target = sibling(&opts.output, "tex");
fs::copy(compile::tex_path(&work_dir), &target)?;
Some(target)
} else {
None
};
let _ = fs::remove_dir_all(&work_dir);
Ok(GenerateStats {
num_files,
num_dirs,
output: opts.output.clone(),
kept_tex,
})
}
fn sibling(p: &Path, ext: &str) -> PathBuf {
let mut s = p.to_path_buf();
s.set_extension(ext);
s
}