Add custom markdown
This commit is contained in:
parent
a61c8b6e13
commit
2c78966fe8
@ -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(),
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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) {
|
||||||
|
@ -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,
|
||||||
|
127
src/renderer.rs
127
src/renderer.rs
@ -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(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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]
|
11
test_page/resources/some_list.toml
Normal file
11
test_page/resources/some_list.toml
Normal 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"
|
1
test_page/resources/template.html
Normal file
1
test_page/resources/template.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<b>A Thing: {{thing}}</b>
|
Loading…
Reference in New Issue
Block a user