use std::fmt::Debug;
use serde::{Deserialize, Serialize};
use anyhow::{anyhow, Context};
use cdoc_parser::ast::Ast;
use cdoc_parser::document::{Document, Metadata};
use cdoc_parser::notebook::{notebook_to_doc, Notebook};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum LoaderError {
#[error(transparent)]
Anyhow(#[from] anyhow::Error),
#[error(transparent)]
Std(#[from] Box<dyn std::error::Error + Send + Sync>),
#[error(transparent)]
Json(#[from] serde_json::Error),
}
#[typetag::serde(tag = "type")]
pub trait Loader: Debug {
fn load(&self, input: &str, accept_draft: bool) -> anyhow::Result<Option<Document<Ast>>>;
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NotebookLoader;
#[typetag::serde(name = "notebook_loader")]
impl Loader for NotebookLoader {
fn load(&self, input: &str, accept_draft: bool) -> anyhow::Result<Option<Document<Ast>>> {
let nb: Notebook =
serde_json::from_str(input).context(anyhow!("deserializing notebook"))?;
notebook_to_doc(nb, accept_draft)
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MarkdownLoader;
#[typetag::serde(name = "markdown_loader")]
impl Loader for MarkdownLoader {
fn load(&self, input: &str, accept_draft: bool) -> anyhow::Result<Option<Document<Ast>>> {
if accept_draft {
Some(Document::try_from(input)).transpose()
} else {
let doc: yaml_front_matter::Document<Metadata> =
yaml_front_matter::YamlFrontMatter::parse(input)
.map_err(|_| anyhow!("Missing or invalid YAML header"))?;
if !doc.metadata.draft {
Some(Document::try_from(input)).transpose()
} else {
Ok(None)
}
}
}
}
#[cfg(test)]
mod tests {
}