Render section pages

This commit is contained in:
Vincent Prouillet 2016-12-13 18:05:59 +09:00
parent a147e68f78
commit c09cfe2de4
3 changed files with 55 additions and 14 deletions

8
Cargo.lock generated
View file

@ -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"

View file

@ -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(&current_path)?; create_dir(&current_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(&current_path)?; create_dir(&current_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(&section);
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)?)
}

View file

@ -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};