teascade-generator/src/renderer.rs

201 lines
6.6 KiB
Rust

use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::error::Error as STDError;
use pulldown_cmark::{html, Parser};
use regex::{Captures, Regex};
use config::{Config, SinglePageConfigs};
use template::Template;
use error::Error;
use logger::{LogLevel, Logger};
use config_toml::InjectionToml;
fn get_file_contents(path: Option<String>) -> Result<String, Error> {
match path {
Some(url) => match File::open(PathBuf::from(&url)) {
Ok(mut file) => {
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
Ok(content)
}
Err(err) => Err(Error::new(
LogLevel::WARNING,
format!("Failed to open {}, {}", url, err.description().to_owned()),
)),
},
None => Ok(String::new()),
}
}
pub fn render_injections(
logger: &Logger,
config: &SinglePageConfigs,
) -> Result<(String, String, String), Error> {
let before_navbar_url = match config.page_config.page.before_navbar_url.clone() {
Some(url) => Some(url),
None => config.global_config.website.before_navbar_url.clone(),
};
let before_content_url = match config.page_config.page.before_content_url.clone() {
Some(url) => Some(url),
None => config.global_config.website.before_content_url.clone(),
};
let after_content_url = match config.page_config.page.after_content_url.clone() {
Some(url) => Some(url),
None => config.global_config.website.after_content_url.clone(),
};
let before_navbar = match get_file_contents(before_navbar_url) {
Ok(content) => content,
Err(error) => {
logger.log(error.severity(), error.description());
String::new()
}
};
let before_content = match get_file_contents(before_content_url) {
Ok(content) => content,
Err(error) => {
logger.log(error.severity(), error.description());
String::new()
}
};
let after_content = match get_file_contents(after_content_url) {
Ok(content) => content,
Err(error) => {
logger.log(error.severity(), error.description());
String::new()
}
};
Ok((before_navbar, before_content, after_content))
}
pub fn render_navbar(
config: &Config,
item_template: Template,
image_item_template: Template,
) -> Result<String, Error> {
let mut navbar_str = String::new();
if let Some(navbar) = config.global_config.navbar.clone() {
for item_str in navbar.items {
if let Some(item) = navbar.item_map.get(&item_str) {
let data = Template::navbar_item_data_from(item.clone());
if item.image_url.is_some() {
navbar_str += &*image_item_template.render(&data);
} else {
navbar_str += &*item_template.render(&data);
}
} else {
return Err(Error::new(
LogLevel::SEVERE,
format!("Navbar item does not exist: navbar.item.{}", item_str),
));
}
}
Ok(navbar_str)
} else {
Err(Error::new(
LogLevel::SEVERE,
"Attempted to render navbar without navbar".to_owned(),
))
}
}
pub fn render_markdown_content(config: &SinglePageConfigs) -> Result<String, Error> {
if let Some(parent) = config.page_config_path.parent() {
let path = parent.join(&config.page_config.page.content_path);
match File::open(&path) {
Ok(mut file) => {
let mut content = String::new();
file.read_to_string(&mut content).ok();
let parser = Parser::new(&content);
let mut markdown = String::new();
html::push_html(&mut markdown, parser);
Ok(markdown)
}
Err(_) => Err(Error::new(
LogLevel::SEVERE,
format!("Failed to open file: {}", path.to_str().unwrap()),
)),
}
} else {
Err(Error::new(
LogLevel::SEVERE,
format!(
"Failed to get page config parent: {}",
config.page_config_path.to_str().unwrap()
),
))
}
}
pub fn render_custom_markdown(rendered_markdown: String) -> Result<String, Error> {
let regex = Regex::new(r"\[from_toml\$(?P<path>.*)\]").unwrap();
Ok(regex
.replace_all(
&rendered_markdown,
|caps: &Captures| match InjectionToml::get_from(&PathBuf::from(&caps["path"])) {
Ok(config) => replace(config),
Err(err) => format!(
"(Failed to get injection toml at {}: {})",
&caps["path"],
err.description()
),
},
)
.to_string())
}
fn replace(config: InjectionToml) -> String {
match File::open(config.meta.template.clone()) {
Ok(mut file) => {
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
let template = Template::new(content);
let mut to_return = String::new();
if config.meta.is_list {
to_return += &*format!("<ul class=\"{}\">", config.meta.list_classes);
}
for item in config.meta.rendered {
match config.list.get(&item) {
Some(data) => {
if config.meta.is_list {
to_return += "<li>";
to_return += &*template.render(data);
to_return += "</li>";
} else {
to_return = template.render(data);
}
}
None => {
if config.meta.is_list {
to_return += "<li>";
to_return += &*format!("Could not find item {}", item);
to_return += "</li>";
} else {
to_return = format!("Could not find item {}", item);
}
}
}
}
if config.meta.is_list {
to_return += "</ul>";
}
to_return
}
Err(err) => format!(
"Failed to get template for custom markdown: {}, {}",
config.meta.template,
err.description().to_owned(),
),
}
}