102 lines
3.4 KiB
Rust
102 lines
3.4 KiB
Rust
mod index;
|
|
mod parse_md;
|
|
|
|
use std::{collections::BTreeMap, fs, io::Error as IoError, path::Path};
|
|
use minijinja::{Environment, Error as JinjaError, Value, context};
|
|
use index::indexer::Error as IndexError;
|
|
use yaml_rust2::Yaml;
|
|
use crate::render::{index::indexer::split_params, parse_md::{Parser, Error as ParserError}};
|
|
|
|
pub use index::indexer::{IndexItem, Template};
|
|
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
NoSrc,
|
|
Io(IoError),
|
|
Jinja(JinjaError),
|
|
Indexer(IndexError),
|
|
Parser(ParserError),
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Renderer<'a> {
|
|
pub site: IndexItem,
|
|
templates: Vec<Template>,
|
|
jinja_env: Environment<'a>,
|
|
}
|
|
impl<'a> Renderer<'a> {
|
|
pub fn index(path: &Path) -> Result<Option<Renderer>, Error> {
|
|
if let Some(site_index) = IndexItem::index(&path).or_else(|e| Err(Error::Indexer(e)))? {
|
|
let templates = Template::index(&path.join("templates")).or_else(|e| Err(Error::Indexer(e)))?;
|
|
let mut jinja_env = Environment::new();
|
|
for tmpl in templates.iter() {
|
|
tmpl.add_to_jinja_env(&mut jinja_env).or_else(|e| Err(Error::Jinja(e)))?;
|
|
};
|
|
Ok(Some(Renderer {
|
|
site: site_index,
|
|
templates,
|
|
jinja_env,
|
|
}))
|
|
}
|
|
else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
fn convert_yaml(yaml: Yaml) -> Value {
|
|
match yaml {
|
|
Yaml::Real(val) => Value::from(val),
|
|
Yaml::Integer(val) => Value::from(val),
|
|
Yaml::String(val) => Value::from(val),
|
|
Yaml::Boolean(val) => Value::from(val),
|
|
Yaml::Array(val) => {
|
|
let mut list: Vec<Value> = Vec::new();
|
|
for item in val {
|
|
list.push(Renderer::convert_yaml(item));
|
|
}
|
|
Value::from(list)
|
|
},
|
|
Yaml::Hash(val) => {
|
|
let mut list: BTreeMap<String, Value> = BTreeMap::new();
|
|
for (key, val) in val {
|
|
if let Yaml::String(key) = key {
|
|
list.insert(key, Renderer::convert_yaml(val));
|
|
}
|
|
else {
|
|
todo!()
|
|
}
|
|
}
|
|
Value::from(list)
|
|
},
|
|
Yaml::Alias(val) => Value::from(val),
|
|
Yaml::Null => Value::UNDEFINED,
|
|
Yaml::BadValue => Value::UNDEFINED,
|
|
}
|
|
}
|
|
|
|
pub fn render_page(&self, page: &IndexItem) -> Result<String, Error> {
|
|
if page.src == None {
|
|
return Err(Error::NoSrc);
|
|
};
|
|
let content = fs::read_to_string(page.src.as_ref().unwrap()).or_else(|e| Err(Error::Io(e)))?;
|
|
let split = split_params(content);
|
|
let mut parser = Parser::new(&split.md, &self.templates);
|
|
match parser.render() {
|
|
Ok(body) => {
|
|
let template = self.jinja_env.get_template(&page.template).or_else(|e| Err(Error::Jinja(e)))?;
|
|
let html = template.render(context! {
|
|
index => self.site.to_minijinja(),
|
|
is_error_not_found => false,
|
|
url => page.get_url(),
|
|
body,
|
|
params => Renderer::convert_yaml(split.yaml)
|
|
}).or_else(|e| Err(Error::Jinja(e)))?;
|
|
|
|
Ok(html)
|
|
},
|
|
Err(e) => Err(Error::Parser(e))
|
|
}
|
|
}
|
|
}
|