@@ -49,7 +49,7 @@ name = "backtrace-sys" | |||||
version = "0.1.5" | version = "0.1.5" | ||||
source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
dependencies = [ | dependencies = [ | ||||
"gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
"gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", | "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
] | ] | ||||
@@ -129,7 +129,7 @@ dependencies = [ | |||||
[[package]] | [[package]] | ||||
name = "gcc" | name = "gcc" | ||||
version = "0.3.39" | |||||
version = "0.3.40" | |||||
source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
[[package]] | [[package]] | ||||
@@ -330,7 +330,7 @@ dependencies = [ | |||||
[[package]] | [[package]] | ||||
name = "tera" | name = "tera" | ||||
version = "0.4.1" | version = "0.4.1" | ||||
source = "git+https://github.com/Keats/tera.git?branch=v0.5#6fc3c61fc58c010abc26f3272badea1b9bc13963" | |||||
source = "git+https://github.com/Keats/tera.git?branch=v0.5#f6047453e06ea507f4b0d9a4c9b1cb3f3f874aac" | |||||
dependencies = [ | dependencies = [ | ||||
"error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | "error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", | "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
@@ -472,7 +472,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" | "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" | ||||
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d" | "checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d" | ||||
"checksum error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd681735364a04cd5d69f01a4f6768e70473941f8d86d8c224faf6955a75799" | "checksum error-chain 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cd681735364a04cd5d69f01a4f6768e70473941f8d86d8c224faf6955a75799" | ||||
"checksum gcc 0.3.39 (registry+https://github.com/rust-lang/crates.io-index)" = "771e4a97ff6f237cf0f7d5f5102f6e28bb9743814b6198d684da5c58b76c11e0" | |||||
"checksum gcc 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "872db9e59486ef2b14f8e8c10e9ef02de2bccef6363d7f34835dedb386b3d950" | |||||
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" | "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" | ||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" | "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" | ||||
"checksum humansize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ec9e8cc78ff5f1f18be53b9a0295dce25c668c10cd60c4d3e535b8882a88f77" | "checksum humansize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ec9e8cc78ff5f1f18be53b9a0295dce25c668c10cd60c4d3e535b8882a88f77" | ||||
@@ -1,12 +1,13 @@ | |||||
use std::collections::HashMap; | |||||
use std::fs::{create_dir, remove_dir_all}; | use std::fs::{create_dir, remove_dir_all}; | ||||
use std::path::Path; | use std::path::Path; | ||||
use glob::glob; | use glob::glob; | ||||
use tera::Tera; | |||||
use tera::{Tera, Context}; | |||||
use config:: Config; | use config:: Config; | ||||
use errors::{Result, ResultExt}; | use errors::{Result, ResultExt}; | ||||
use page::Page; | |||||
use page::{Page, order_pages}; | |||||
use utils::create_file; | use utils::create_file; | ||||
@@ -18,33 +19,62 @@ pub fn build(config: Config) -> Result<()> { | |||||
} | } | ||||
let tera = Tera::new("layouts/**/*").chain_err(|| "Error parsing templates")?; | let tera = Tera::new("layouts/**/*").chain_err(|| "Error parsing templates")?; | ||||
// let mut pages: Vec<Page> = vec![]; | |||||
// ok we got all the pages HTML, time to write them down to disk | // ok we got all the pages HTML, time to write them down to disk | ||||
create_dir("public")?; | create_dir("public")?; | ||||
let public = Path::new("public"); | let public = Path::new("public"); | ||||
let mut pages: Vec<Page> = vec![]; | |||||
let mut sections: HashMap<String, Vec<Page>> = HashMap::new(); | |||||
// First step: do all the articles and group article by sections | |||||
// hardcoded pattern so can't error | // hardcoded pattern so can't error | ||||
for entry in glob("content/**/*.md").unwrap().filter_map(|e| e.ok()) { | for entry in glob("content/**/*.md").unwrap().filter_map(|e| e.ok()) { | ||||
let path = entry.as_path(); | let path = entry.as_path(); | ||||
let mut page = Page::from_file(&path)?; | let mut page = Page::from_file(&path)?; | ||||
let mut current_path = public.clone().to_path_buf(); | let mut current_path = public.clone().to_path_buf(); | ||||
for section in &page.sections { | for section in &page.sections { | ||||
current_path.push(section); | current_path.push(section); | ||||
//current_path = current_path.join(section).as_path(); | |||||
if !current_path.exists() { | if !current_path.exists() { | ||||
println!("Creating {:?} folder", current_path); | |||||
create_dir(¤t_path)?; | create_dir(¤t_path)?; | ||||
// TODO: create section index.html | |||||
// create_file(current_path.join("index.html"), ""); | |||||
} | } | ||||
let str_path = current_path.as_path().to_string_lossy().to_string(); | |||||
if sections.contains_key(&str_path) { | |||||
sections.get_mut(&str_path).unwrap().push(page.clone()); | |||||
} else { | |||||
sections.insert(str_path, vec![page.clone()]); | |||||
} | |||||
} | } | ||||
current_path.push(&page.filename); | current_path.push(&page.filename); | ||||
create_dir(¤t_path)?; | create_dir(¤t_path)?; | ||||
create_file(current_path.join("index.html"), &page.render_html(&tera, &config)?)?; | create_file(current_path.join("index.html"), &page.render_html(&tera, &config)?)?; | ||||
pages.push(page); | |||||
} | |||||
for (section, pages) in sections { | |||||
render_section_index(section, pages, &tera, &config)?; | |||||
} | } | ||||
Ok(()) | Ok(()) | ||||
} | } | ||||
fn render_section_index(section: String, pages: Vec<Page>, tera: &Tera, config: &Config) -> Result<()> { | |||||
let path = Path::new(§ion); | |||||
let mut context = Context::new(); | |||||
context.add("pages", &order_pages(pages)); | |||||
context.add("config", &config); | |||||
let section_name = match path.components().into_iter().last() { | |||||
Some(s) => s.as_ref().to_string_lossy().to_string(), | |||||
None => bail!("Couldn't find a section name in {:?}", path.display()) | |||||
}; | |||||
create_file(path.join("index.html"), &tera.render(&format!("{}.html", section_name), context)?) | |||||
} |
@@ -20,23 +20,27 @@ lazy_static! { | |||||
} | } | ||||
#[derive(Debug, PartialEq, Serialize, Deserialize)] | |||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] | |||||
pub struct Page { | pub struct Page { | ||||
// .md filepath, excluding the content/ bit | // .md filepath, excluding the content/ bit | ||||
#[serde(skip_serializing)] | |||||
pub filepath: String, | pub filepath: String, | ||||
// the name of the .md file | // the name of the .md file | ||||
#[serde(skip_serializing)] | |||||
pub filename: String, | pub filename: String, | ||||
// the directories above our .md file are called sections | // the directories above our .md file are called sections | ||||
// for example a file at content/kb/solutions/blabla.md will have 2 sections: | // for example a file at content/kb/solutions/blabla.md will have 2 sections: | ||||
// `kb` and `solutions` | // `kb` and `solutions` | ||||
#[serde(skip_serializing)] | |||||
pub sections: Vec<String>, | pub sections: Vec<String>, | ||||
// the actual content of the page, in markdown | |||||
#[serde(skip_serializing)] | |||||
pub raw_content: String, | |||||
// <title> of the page | // <title> of the page | ||||
pub title: String, | pub title: String, | ||||
// The page slug | // The page slug | ||||
pub slug: String, | pub slug: String, | ||||
// the actual content of the page | |||||
pub raw_content: String, | |||||
// the HTML rendered of the page | // the HTML rendered of the page | ||||
pub content: String, | pub content: String, | ||||
@@ -55,6 +59,7 @@ pub struct Page { | |||||
// optional date if we want to order pages (ie blog post) | // optional date if we want to order pages (ie blog post) | ||||
pub date: Option<String>, | pub date: Option<String>, | ||||
// optional layout, if we want to specify which tpl to render for that page | // optional layout, if we want to specify which tpl to render for that page | ||||
#[serde(skip_serializing)] | |||||
pub layout: Option<String>, | pub layout: Option<String>, | ||||
// description that appears when linked, e.g. on twitter | // description that appears when linked, e.g. on twitter | ||||
pub description: Option<String>, | pub description: Option<String>, | ||||
@@ -158,6 +163,12 @@ impl Page { | |||||
} | } | ||||
// Order pages by date, no-op for now | |||||
pub fn order_pages(pages: Vec<Page>) -> Vec<Page> { | |||||
pages | |||||
} | |||||
#[cfg(test)] | #[cfg(test)] | ||||
mod tests { | mod tests { | ||||
use super::{Page}; | use super::{Page}; | ||||