Files
webTemplate/src/render.rs

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))
}
}
}