use std::io;
#[cfg(feature = "fs")]
use std::path::Path;
use crate::adapters::resources::ClosureResolver;
use crate::api::options::{
ConvertOptions, MarkdownSource, OutputTarget, PdfOutput, RenderBackendSelection,
};
use crate::composition::ensure_renderer;
use crate::core::ports::{RenderBackend, ResourceResolver};
use crate::core::{BuiltInTheme, LayoutMode, PageSize, ThemeConfig};
use crate::core::{ForgeError, Result};
use crate::pipeline::convert::convert;
pub struct Forge<'a> {
options: ConvertOptions<'a>,
}
impl<'a> Default for Forge<'a> {
fn default() -> Self {
Self::new()
}
}
impl<'a> Forge<'a> {
pub fn new() -> Self {
Self {
options: ConvertOptions::default(),
}
}
pub fn with_options(mut self, options: ConvertOptions<'a>) -> Self {
self.options = options;
self
}
#[cfg(feature = "fs")]
pub fn from_path(mut self, path: &'a Path) -> Self {
self.options.source = Some(MarkdownSource::Path(path));
self
}
pub fn from_text(mut self, text: &'a str) -> Self {
self.options.source = Some(MarkdownSource::Text(text));
self
}
pub fn from_bytes(mut self, bytes: &'a [u8]) -> Self {
self.options.source = Some(MarkdownSource::Bytes(bytes));
self
}
#[cfg(feature = "fs")]
pub fn to_file(mut self, path: &'a Path) -> Self {
self.options.output = Some(OutputTarget::File(path));
self
}
#[cfg(feature = "fs")]
pub fn to_directory(mut self, path: &'a Path) -> Self {
self.options.output = Some(OutputTarget::Directory(path));
self
}
pub fn to_memory(mut self) -> Self {
self.options.output = Some(OutputTarget::Memory);
self
}
pub fn with_output_file_name(mut self, file_name: &'a str) -> Self {
self.options.output_file_name = Some(file_name);
self
}
pub fn with_page_size(mut self, page_size: PageSize) -> Self {
self.options.page_size = page_size;
self
}
pub fn with_layout_mode(mut self, layout_mode: LayoutMode) -> Self {
self.options.layout_mode = layout_mode;
self
}
pub fn with_theme(mut self, theme: BuiltInTheme) -> Self {
self.options.theme.built_in = Some(theme);
self
}
pub fn with_theme_config(mut self, theme: ThemeConfig) -> Self {
self.options.theme = theme;
self
}
pub fn with_backend(mut self, backend: RenderBackendSelection) -> Self {
self.options.backend = backend;
self.options.renderer = None;
self
}
pub fn with_resource_adapter<R>(mut self, resolver: R) -> Self
where
R: ResourceResolver + 'static,
{
self.options.resource_resolver = Some(Box::new(resolver));
self
}
pub fn with_resource_resolver<F>(self, resolver: F) -> Self
where
F: Fn(&str) -> io::Result<Vec<u8>> + Send + Sync + 'static,
{
self.with_resource_adapter(ClosureResolver::new(resolver))
}
pub fn with_renderer<R>(mut self, renderer: R) -> Self
where
R: RenderBackend + 'static,
{
self.options.renderer = Some(Box::new(renderer));
self
}
pub fn convert(mut self) -> Result<PdfOutput> {
if self.options.source.is_none() {
return Err(ForgeError::MissingSource);
}
if self.options.output.is_none() {
return Err(ForgeError::MissingOutput);
}
ensure_renderer(&mut self.options);
convert(&self.options)
}
}