Add custom markdown

This commit is contained in:
Sofia 2018-04-20 02:52:48 +03:00
parent a61c8b6e13
commit 2c78966fe8
10 changed files with 181 additions and 98 deletions

View File

@ -118,6 +118,7 @@ pub fn build(logger: &Logger, opt: &Opt, _: &BuildOpt) -> Result<(), Error> {
logger.log(LogLevel::DETAILER, "Rendering"); logger.log(LogLevel::DETAILER, "Rendering");
let markdown = renderer::render_markdown_content(&config)?; let markdown = renderer::render_markdown_content(&config)?;
let markdown = renderer::render_custom_markdown(markdown)?;
let data = Template::page_data_from( let data = Template::page_data_from(
config.clone(), config.clone(),
navbar_content.clone(), navbar_content.clone(),

View File

@ -1,13 +1,8 @@
use toml;
use std::path::PathBuf; use std::path::PathBuf;
use std::fs::File;
use std::io::Read;
use std::error::Error as STDError;
use std::collections::HashMap; use std::collections::HashMap;
use logger::LogLevel;
use error::Error; use error::Error;
use file_writer;
#[derive(Deserialize, Serialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
pub struct GlobalConfigToml { pub struct GlobalConfigToml {
@ -75,25 +70,7 @@ pub struct NavbarItem {
impl GlobalConfigToml { impl GlobalConfigToml {
pub fn get_config() -> Result<GlobalConfigToml, Error> { pub fn get_config() -> Result<GlobalConfigToml, Error> {
let mut file = File::open("config.toml")?; file_writer::get_toml(&PathBuf::from("config.toml"))
let mut contents = String::new();
file.read_to_string(&mut contents)?;
match toml::from_str(&contents) {
Ok(config) => Ok(config),
Err(err) => {
if let Some((line, col)) = err.line_col() {
Err(Error::new(
LogLevel::SEVERE,
format!("Erronous config.toml at {}:{}", line, col),
))
} else {
Err(Error::new(
LogLevel::SEVERE,
format!("Failed to parse config.toml correctly. Check variable names!"),
))
}
}
}
} }
} }
@ -104,45 +81,7 @@ pub struct PageConfigToml {
impl PageConfigToml { impl PageConfigToml {
pub fn get_from(path: &PathBuf) -> Result<PageConfigToml, Error> { pub fn get_from(path: &PathBuf) -> Result<PageConfigToml, Error> {
let path_str = match path.to_str() { file_writer::get_toml(path)
Some(path_str) => path_str,
None => "",
};
let mut file = match File::open(path.as_path()) {
Ok(file) => file,
Err(err) => {
return Err(Error::new(
LogLevel::SEVERE,
format!(
"Failed to open page config: {}, Reason: {}",
path.to_str().unwrap(),
err.description().to_owned()
),
))
}
};
let mut contents = String::new();
file.read_to_string(&mut contents)?;
match toml::from_str(&contents) {
Ok(config) => Ok(config),
Err(err) => {
if let Some((line, col)) = err.line_col() {
Err(Error::new(
LogLevel::SEVERE,
format!("Erronous toml: {} at {}:{}", path_str, line, col),
))
} else {
Err(Error::new(
LogLevel::SEVERE,
format!(
"Failed to parse toml correctly: {}. Check variable names!",
path_str
),
))
}
}
}
} }
} }
@ -159,3 +98,23 @@ pub struct PageConfig {
pub javascript: Option<Vec<String>>, pub javascript: Option<Vec<String>>,
pub css: Option<Vec<String>>, pub css: Option<Vec<String>>,
} }
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct InjectionToml {
pub meta: MetaInjectionToml,
pub list: HashMap<String, HashMap<String, String>>,
}
#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct MetaInjectionToml {
pub rendered: Vec<String>,
pub template: String,
pub list_classes: String,
pub is_list: bool,
}
impl InjectionToml {
pub fn get_from(path: &PathBuf) -> Result<InjectionToml, Error> {
file_writer::get_toml(path)
}
}

View File

@ -4,6 +4,7 @@ use std::error::Error as STDError;
use logger::LogLevel; use logger::LogLevel;
#[derive(Debug)]
pub struct Error { pub struct Error {
description: String, description: String,
severity: LogLevel, severity: LogLevel,

View File

@ -4,6 +4,7 @@ use std::path::{Path, PathBuf};
use std::error::Error as STDError; use std::error::Error as STDError;
use serde::Serialize; use serde::Serialize;
use serde::de::DeserializeOwned;
use toml; use toml;
use error::Error; use error::Error;
@ -12,6 +13,47 @@ use logger::LogLevel;
pub fn add_to_beginning<T: Into<String>>(path: PathBuf, to_add: T) -> PathBuf { pub fn add_to_beginning<T: Into<String>>(path: PathBuf, to_add: T) -> PathBuf {
Path::new(&to_add.into()).join(path) Path::new(&to_add.into()).join(path)
} }
pub fn get_toml<T: DeserializeOwned>(path: &PathBuf) -> Result<T, Error> {
let path_str = match path.to_str() {
Some(path_str) => path_str,
None => "",
};
let mut file = match File::open(path.as_path()) {
Ok(file) => file,
Err(err) => {
return Err(Error::new(
LogLevel::SEVERE,
format!(
"Failed to open toml: {}, Reason: {}",
path.to_str().unwrap(),
err.description().to_owned()
),
))
}
};
let mut contents: String = String::new();
file.read_to_string(&mut contents)?;
match toml::from_str(&contents) {
Ok(config) => Ok(config),
Err(err) => {
if let Some((line, col)) = err.line_col() {
Err(Error::new(
LogLevel::SEVERE,
format!("Erronous toml: {} at {}:{}", path_str, line, col),
))
} else {
Err(Error::new(
LogLevel::SEVERE,
format!(
"Failed to parse toml correctly: {}. Check variable names!",
path_str
),
))
}
}
}
}
pub fn write_toml<T: Serialize>(path: &PathBuf, data: &T, overwrite: bool) -> Result<(), Error> { pub fn write_toml<T: Serialize>(path: &PathBuf, data: &T, overwrite: bool) -> Result<(), Error> {
match toml::ser::to_string(data) { match toml::ser::to_string(data) {

View File

@ -24,7 +24,7 @@ impl Logger {
} }
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Clone)] #[derive(Clone, Debug)]
#[repr(u8)] #[repr(u8)]
pub enum LogLevel { pub enum LogLevel {
QUIET = 0, QUIET = 0,

View File

@ -4,11 +4,13 @@ use std::path::PathBuf;
use std::error::Error as STDError; use std::error::Error as STDError;
use pulldown_cmark::{html, Parser}; use pulldown_cmark::{html, Parser};
use regex::{Captures, Regex};
use config::{Config, SinglePageConfigs}; use config::{Config, SinglePageConfigs};
use template::Template; use template::Template;
use error::Error; use error::Error;
use logger::{LogLevel, Logger}; use logger::{LogLevel, Logger};
use config_toml::InjectionToml;
fn get_file_contents(path: Option<String>) -> Result<String, Error> { fn get_file_contents(path: Option<String>) -> Result<String, Error> {
match path { match path {
@ -69,35 +71,6 @@ pub fn render_injections(
Ok((before_navbar, before_content, after_content)) Ok((before_navbar, before_content, after_content))
} }
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_navbar( pub fn render_navbar(
config: &Config, config: &Config,
item_template: Template, item_template: Template,
@ -129,3 +102,99 @@ pub fn render_navbar(
)) ))
} }
} }
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(),
),
}
}

View File

@ -84,16 +84,15 @@ nav li:not(.image) a {
} }
nav li:first-child a { nav li:first-child a {
border-left: solid 5px var(--color-navbar-button-hover); border-left: solid 3px var(--color-navbar-button-hover);
} }
nav li:last-child a { nav li:last-child a {
border-right: solid 5px var(--color-navbar-button-hover); border-right: solid 3px var(--color-navbar-button-hover);
} }
nav ul a:hover { nav ul a:hover {
background-color: var(--color-navbar-button-hover); background-color: var(--color-navbar-button-hover);
border-left: solid 5px var(--color-navbar-button-hover);
} }
nav ul a:focus { nav ul a:focus {

View File

@ -6,4 +6,4 @@ Example stuff that makes this site different:
[Hello! This is an internal link](/) [Hello! This is an internal link](/)
[from_toml$/test_page/config.toml] [from_toml$test_page/resources/some_list.toml]

View File

@ -0,0 +1,11 @@
[meta]
rendered = ["one_thing", "another_thing"]
template = "test_page/resources/template.html"
list_classes = "test_class"
is_list = true
[list.one_thing]
thing = "jotain"
[list.another_thing]
thing = "jotain muuta"

View File

@ -0,0 +1 @@
<b>A Thing: {{thing}}</b>