use maudit::content::{ContentEntry, Entry};
use maudit::route::prelude::*;
use maudit::{
content::{ContentSourceInternal, ContentSources},
coronate,
route::{prelude::Params, FullRoute},
};
pub use maudit::{content_sources, routes, BuildOptions, BuildOutput};
pub mod archetypes {
pub mod blog;
}
pub mod layouts {
mod layout;
pub use layout::layout;
}
pub mod components {}
#[derive(Debug, Clone)]
pub enum Archetype {
Blog,
MarkdownDoc,
}
#[macro_export]
macro_rules! archetypes {
($(($name:expr, $ident:ident, $arch:expr, $glob:expr)),* $(,)?) => {{
let mut vec = Vec::new();
$(
let tuple = match $arch {
oubli::Archetype::Blog => {
// Generate the content source
let content_source = maudit::content::ContentSource::new(
stringify!($ident),
Box::new({
let glob = $glob.to_string();
move || maudit::content::glob_markdown::<oubli::archetypes::blog::BlogEntryContent>(&glob, None)
}),
);
mod $ident {
use maudit::route::prelude::*;
use oubli::archetypes::blog::*;
#[route(stringify!($ident))]
pub struct Index;
impl Route for Index {
fn render(&self, ctx: &mut PageContext) -> impl Into<RenderResult> {
blog_index_content::<Entry>(Entry, ctx, $name, stringify!($ident))
}
}
#[route(concat!(stringify!($ident), "/[entry]"))]
pub struct Entry;
impl Route<BlogEntryParams> for Entry {
fn render(&self, ctx: &mut PageContext) -> impl Into<RenderResult> {
blog_entry_render(ctx, $name, stringify!($ident))
}
fn pages(&self, ctx: &mut DynamicRouteContext) -> Pages<BlogEntryParams> {
blog_entry_routes(ctx, stringify!($ident))
}
}
}
($name, stringify!($ident), vec![&$ident::Index as &dyn maudit::route::FullRoute, &$ident::Entry as &dyn maudit::route::FullRoute], Box::new(content_source) as Box<dyn maudit::content::ContentSourceInternal>)
},
oubli::Archetype::MarkdownDoc => {
todo!();
}
};
vec.push(tuple);
)*
vec
}};
}
#[allow(clippy::type_complexity)]
pub fn forget(
archetypes: Vec<(
&str,
&str,
Vec<&dyn FullRoute>,
Box<dyn ContentSourceInternal>,
)>,
routes: &[&dyn FullRoute],
mut content_sources: ContentSources,
options: BuildOptions,
) -> Result<BuildOutput, Box<dyn std::error::Error>> {
let mut combined_routes = routes.to_vec();
let mut content_sources_archetypes = Vec::new();
content_sources
.sources_mut()
.push(generate_archetype_store(&archetypes));
for (_name, _stringified_ident, pages, content_source) in archetypes {
content_sources_archetypes.push(content_source);
combined_routes.extend(pages);
}
content_sources
.sources_mut()
.extend(content_sources_archetypes);
coronate(&combined_routes, content_sources, options)
}
fn generate_archetype_store(archetypes: &Vec<ArchetypeTuple>) -> Box<dyn ContentSourceInternal> {
let names: Vec<(String, String)> = archetypes
.iter()
.map(|(name, stringified_ident, _, _)| (name.to_string(), stringified_ident.to_string()))
.collect();
let archetype_store = maudit::content::ContentSource::new(
"archetype_store",
Box::new(move || {
let mut entries = Vec::new();
for (name, stringified_ident) in names.iter() {
entries.push(Entry::create(
stringified_ident.to_string(),
None,
None,
ArchetypeStoreEntry {
title: name.to_string(),
},
None,
));
}
entries
}),
);
Box::new(archetype_store)
}
#[derive(Params)]
pub struct ArchetypeStoreEntry {
pub title: String,
}
type ArchetypeTuple<'a> = (
&'a str,
&'a str,
Vec<&'a dyn FullRoute>,
Box<dyn ContentSourceInternal>,
);