From 5bfe1c213b2539908dc75c5aeaccfb329f8a3952 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 8 May 2017 17:39:31 +0900 Subject: [PATCH 1/7] Clippy run --- Cargo.lock | 30 +++++++++++++++--------------- src/pagination.rs | 10 ++++------ src/section.rs | 4 ++-- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83554080..c03739a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ name = "gutenberg" version = "0.0.4" dependencies = [ - "base64 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.23.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.24.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -19,7 +19,7 @@ dependencies = [ "staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tera 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tera 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "term-painter 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.0 (git+https://github.com/alexcrichton/toml-rs)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -74,7 +74,7 @@ dependencies = [ [[package]] name = "base64" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -155,7 +155,7 @@ dependencies = [ [[package]] name = "clap" -version = "2.23.3" +version = "2.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -421,7 +421,7 @@ dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -439,7 +439,7 @@ dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -450,7 +450,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -461,7 +461,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -482,7 +482,7 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -820,7 +820,7 @@ dependencies = [ [[package]] name = "tera" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1072,7 +1072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" "checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80" "checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842" -"checksum base64 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "124e5332dfc4e387b4ca058909aa175c0c3eccf03846b7c1a969b9ad067b8df2" +"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" "checksum bincode 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "55eb0b7fd108527b0c77860f75eca70214e11a8b4c6ef05148c54c05a25d48ad" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" @@ -1084,7 +1084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" "checksum chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d9123be86fd2a8f627836c235ecdf331fdd067ecf7ac05aa1a68fbcf2429f056" -"checksum clap 2.23.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f57e9b63057a545ad2ecd773ea61e49422ed1b1d63d74d5da5ecaee55b3396cd" +"checksum clap 2.24.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7541069be0b8aec41030802abe8b5cdef0490070afaa55418adea93b1e431e0" "checksum cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "d18d68987ed4c516dcc3e7913659bfa4076f5182eea4a7e0038bb060953e76ac" "checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8" "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" @@ -1123,7 +1123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" "checksum mount 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32245731923cd096899502fc4c4317cfd09f121e80e73f7f576cf3777a824256" -"checksum net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "18b9642ad6222faf5ce46f6966f59b71b9775ad5758c9e09fcf0a6c8061972b4" +"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" "checksum notify 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "298d4401ff2c6cebb7f8944c90288647c89ce59029d43b439444cf1067df55e1" "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" @@ -1165,7 +1165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum syntect 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24204b1f4bdd49f84e5f4b219d0bf1dc45ac2fd7fc46320ab6627b537d6d4b69" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum tera 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "462408d239ffff6439089628a5fa7fec1bce31e6a633780baea93d31c64070af" +"checksum tera 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d09d7a9a4ef4da73121c89842ab00213528804b9992001955871cd6ee49d66c" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" "checksum term-painter 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ab900bf2f05175932b13d4fc12f8ff09ef777715b04998791ab2c930841e496b" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" diff --git a/src/pagination.rs b/src/pagination.rs index 1d8bc8f4..b7215c60 100644 --- a/src/pagination.rs +++ b/src/pagination.rs @@ -66,10 +66,10 @@ impl<'a> Paginator<'a> { } let mut pagers = vec![]; - for index in 0..pages.len() { + for (index, page) in pages.iter().enumerate() { // First page has no pagination path if index == 0 { - pagers.push(Pager::new(1, pages[index].clone(), section.permalink.clone(), section.path.clone())); + pagers.push(Pager::new(1, page.clone(), section.permalink.clone(), section.path.clone())); continue; } @@ -81,14 +81,12 @@ impl<'a> Paginator<'a> { }; pagers.push(Pager::new( index + 1, - pages[index].clone(), + page.clone(), permalink, - if section.is_index() { format!("{}", page_path) } else { format!("{}/{}", section.path, page_path) } + if section.is_index() { page_path } else { format!("{}/{}", section.path, page_path) } )); } - //println!("{:?}", pagers); - Paginator { all_pages: all_pages, pagers: pagers, diff --git a/src/section.rs b/src/section.rs index 12e5eb63..a187f8c3 100644 --- a/src/section.rs +++ b/src/section.rs @@ -56,7 +56,7 @@ impl Section { section.components = find_content_components(§ion.file_path); section.path = section.components.join("/"); section.permalink = config.make_permalink(§ion.path); - if section.components.len() == 0 { + if section.components.is_empty() { section.relative_path = "_index.md".to_string(); } else { section.relative_path = format!("{}/_index.md", section.components.join("/")); @@ -100,7 +100,7 @@ impl Section { } pub fn is_index(&self) -> bool { - self.components.len() == 0 + self.components.is_empty() } } From 2d4cba5b2d0f6ed9f4b4148a9e82fee82762ee75 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Mon, 8 May 2017 19:29:37 +0900 Subject: [PATCH 2/7] Make index a section like any other --- CHANGELOG.md | 2 +- benches/gutenberg.rs | 3 +- src/console.rs | 4 + src/front_matter.rs | 13 +- src/page.rs | 72 +------- src/section.rs | 21 ++- src/site.rs | 184 +++++++++------------ test_site/content/hello.md | 2 + test_site/templates/index.html | 2 +- test_site/templates/section_paginated.html | 2 +- tests/front_matter.rs | 4 +- tests/site.rs | 42 ++--- 12 files changed, 134 insertions(+), 217 deletions(-) create mode 100644 test_site/content/hello.md diff --git a/CHANGELOG.md b/CHANGELOG.md index e42c3774..7d190a7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ - Fix XML templates overriding and reloading - `title` and `description` are now optional in the front matter - Add GenericConfig, Vim syntax -- Add `_index.md` for homepage as well +- Add `_index.md` for homepage as well and make that into a normal section - Allow sorting by `none`, `date` and `order` for sections - Add pagination diff --git a/benches/gutenberg.rs b/benches/gutenberg.rs index 969d34b0..6f5f4b33 100644 --- a/benches/gutenberg.rs +++ b/benches/gutenberg.rs @@ -41,8 +41,7 @@ fn bench_populate_previous_and_next_pages(b: &mut test::Bencher) { path.push("test_site"); let mut site = Site::new(&path, "config.toml").unwrap(); site.load().unwrap(); - let mut pages = site.pages.values().cloned().collect::>(); - pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); + let pages = site.pages.values().cloned().collect::>(); b.iter(|| populate_previous_and_next_pages(pages.as_slice())); } diff --git a/src/console.rs b/src/console.rs index 41329711..b758bd53 100644 --- a/src/console.rs +++ b/src/console.rs @@ -6,6 +6,10 @@ pub fn info(message: &str) { println!("{}", NotSet.bold().paint(message)); } +pub fn warn(message: &str) { + println!("{}", Yellow.bold().paint(message)); +} + pub fn success(message: &str) { println!("{}", Green.bold().paint(message)); } diff --git a/src/front_matter.rs b/src/front_matter.rs index 1e437fb1..09da15ec 100644 --- a/src/front_matter.rs +++ b/src/front_matter.rs @@ -14,7 +14,7 @@ lazy_static! { static ref PAGE_RE: Regex = Regex::new(r"^\r?\n?\+\+\+\r?\n((?s).*?(?-s))\+\+\+\r?\n?((?s).*(?-s))$").unwrap(); } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum SortBy { Date, @@ -64,10 +64,6 @@ pub struct FrontMatter { impl FrontMatter { pub fn parse(toml: &str) -> Result { - if toml.trim() == "" { - bail!("Front matter of file is missing"); - } - let mut f: FrontMatter = match toml::from_str(toml) { Ok(d) => d, Err(e) => bail!(e), @@ -89,8 +85,6 @@ impl FrontMatter { f.paginate_path = Some("page".to_string()); } - - Ok(f) } @@ -112,10 +106,11 @@ impl FrontMatter { self.order.unwrap() } + /// Returns the current sorting method, defaults to `None` (== no sorting) pub fn sort_by(&self) -> SortBy { match self.sort_by { - Some(ref s) => s.clone(), - None => SortBy::Date, + Some(ref s) => *s, + None => SortBy::None, } } diff --git a/src/page.rs b/src/page.rs index 6fdad491..06d83e72 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,5 +1,4 @@ /// A page, can be a blog post or a basic page -use std::cmp::Ordering; use std::collections::HashMap; use std::fs::{read_dir}; use std::path::{Path, PathBuf}; @@ -13,7 +12,6 @@ use slug::slugify; use errors::{Result, ResultExt}; use config::Config; use front_matter::{FrontMatter, SortBy, split_content}; -use section::Section; use markdown::markdown_to_html; use utils::{read_file, find_content_components}; @@ -243,13 +241,7 @@ impl ser::Serialize for Page { /// /// Any pages that doesn't have a date when the sorting method is date or order /// when the sorting method is order will be ignored. -pub fn sort_pages(pages: Vec, section: Option<&Section>) -> (Vec, Vec) { - let sort_by = if let Some(s) = section { - s.meta.sort_by() - } else { - SortBy::None - }; - +pub fn sort_pages(pages: Vec, sort_by: SortBy) -> (Vec, Vec) { match sort_by { SortBy::Date => { let mut can_be_sorted = vec![]; @@ -290,32 +282,6 @@ pub fn sort_pages(pages: Vec, section: Option<&Section>) -> (Vec, Ve } } -/// Used only by the RSS feed (I think) -impl PartialOrd for Page { - fn partial_cmp(&self, other: &Page) -> Option { - if self.meta.date.is_none() { - return Some(Ordering::Less); - } - - if other.meta.date.is_none() { - return Some(Ordering::Greater); - } - - let this_date = self.meta.date().unwrap(); - let other_date = other.meta.date().unwrap(); - - if this_date > other_date { - return Some(Ordering::Less); - } - if this_date < other_date { - return Some(Ordering::Greater); - } - - Some(Ordering::Equal) - } -} - - /// Horribly inefficient way to set previous and next on each pages /// So many clones pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec { @@ -347,10 +313,8 @@ mod tests { use tempdir::TempDir; use std::fs::File; - use std::path::Path; use front_matter::{FrontMatter, SortBy}; - use section::Section; use super::{Page, find_related_assets, sort_pages, populate_previous_and_next_pages}; fn create_page_with_date(date: &str) -> Page { @@ -381,20 +345,6 @@ mod tests { assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "fail.png").count(), 1); } - #[test] - fn test_can_default_sort() { - let input = vec![ - create_page_with_date("2018-01-01"), - create_page_with_date("2017-01-01"), - create_page_with_date("2019-01-01"), - ]; - let (pages, _) = sort_pages(input, None); - // Should be sorted by date - assert_eq!(pages[0].clone().meta.date.unwrap(), "2018-01-01"); - assert_eq!(pages[1].clone().meta.date.unwrap(), "2017-01-01"); - assert_eq!(pages[2].clone().meta.date.unwrap(), "2019-01-01"); - } - #[test] fn test_can_sort_dates() { let input = vec![ @@ -402,10 +352,7 @@ mod tests { create_page_with_date("2017-01-01"), create_page_with_date("2019-01-01"), ]; - let mut front_matter = FrontMatter::default(); - front_matter.sort_by = Some(SortBy::Date); - let section = Section::new(Path::new("hey"), front_matter); - let (pages, _) = sort_pages(input, Some(§ion)); + let (pages, _) = sort_pages(input, SortBy::Date); // Should be sorted by date assert_eq!(pages[0].clone().meta.date.unwrap(), "2019-01-01"); assert_eq!(pages[1].clone().meta.date.unwrap(), "2018-01-01"); @@ -419,10 +366,7 @@ mod tests { create_page_with_order(3), create_page_with_order(1), ]; - let mut front_matter = FrontMatter::default(); - front_matter.sort_by = Some(SortBy::Order); - let section = Section::new(Path::new("hey"), front_matter); - let (pages, _) = sort_pages(input, Some(§ion)); + let (pages, _) = sort_pages(input, SortBy::Order); // Should be sorted by date assert_eq!(pages[0].clone().meta.order.unwrap(), 3); assert_eq!(pages[1].clone().meta.order.unwrap(), 2); @@ -436,10 +380,7 @@ mod tests { create_page_with_order(3), create_page_with_order(1), ]; - let mut front_matter = FrontMatter::default(); - front_matter.sort_by = Some(SortBy::None); - let section = Section::new(Path::new("hey"), front_matter); - let (pages, _) = sort_pages(input, Some(§ion)); + let (pages, _) = sort_pages(input, SortBy::None); // Should be sorted by date assert_eq!(pages[0].clone().meta.order.unwrap(), 2); assert_eq!(pages[1].clone().meta.order.unwrap(), 3); @@ -453,10 +394,7 @@ mod tests { create_page_with_order(3), create_page_with_date("2019-01-01"), ]; - let mut front_matter = FrontMatter::default(); - front_matter.sort_by = Some(SortBy::Order); - let section = Section::new(Path::new("hey"), front_matter); - let (pages, unsorted) = sort_pages(input, Some(§ion)); + let (pages, unsorted) = sort_pages(input, SortBy::Order); assert_eq!(pages.len(), 2); assert_eq!(unsorted.len(), 1); } diff --git a/src/section.rs b/src/section.rs index a187f8c3..fa865c67 100644 --- a/src/section.rs +++ b/src/section.rs @@ -8,7 +8,7 @@ use config::Config; use front_matter::{FrontMatter, split_content}; use errors::{Result, ResultExt}; use utils::{read_file, find_content_components}; -use page::{Page, sort_pages}; +use page::{Page}; #[derive(Clone, Debug, PartialEq)] @@ -29,6 +29,8 @@ pub struct Section { pub meta: FrontMatter, /// All direct pages of that section pub pages: Vec, + /// All pages that cannot be sorted in this section + pub ignored_pages: Vec, /// All direct subsections pub subsections: Vec
, } @@ -46,6 +48,7 @@ impl Section { permalink: "".to_string(), meta: meta, pages: vec![], + ignored_pages: vec![], subsections: vec![], } } @@ -86,7 +89,7 @@ impl Section { } /// Renders the page using the default layout, unless specified in front-matter - pub fn render_html(&self, tera: &Tera, config: &Config) -> Result { + pub fn render_html(&self, sections: &[&Section], tera: &Tera, config: &Config) -> Result { let tpl_name = self.get_template_name(); let mut context = Context::new(); @@ -94,14 +97,25 @@ impl Section { context.add("section", self); context.add("current_url", &self.permalink); context.add("current_path", &self.path); + if self.is_index() { + context.add("sections", §ions); + } tera.render(&tpl_name, &context) .chain_err(|| format!("Failed to render section '{}'", self.file_path.display())) } + /// Is this the index section? pub fn is_index(&self) -> bool { self.components.is_empty() } + + pub fn all_pages_path(&self) -> Vec { + let mut paths = vec![]; + paths.extend(self.pages.iter().map(|p| p.file_path.clone())); + paths.extend(self.ignored_pages.iter().map(|p| p.file_path.clone())); + paths + } } impl ser::Serialize for Section { @@ -111,8 +125,7 @@ impl ser::Serialize for Section { state.serialize_field("description", &self.meta.description)?; state.serialize_field("path", &format!("/{}", self.path))?; state.serialize_field("permalink", &self.permalink)?; - let (sorted_pages, _) = sort_pages(self.pages.clone(), Some(self)); - state.serialize_field("pages", &sorted_pages)?; + state.serialize_field("pages", &self.pages)?; state.serialize_field("subsections", &self.subsections)?; state.end() } diff --git a/src/site.rs b/src/site.rs index fccdf353..5af17759 100644 --- a/src/site.rs +++ b/src/site.rs @@ -14,6 +14,7 @@ use page::{Page, populate_previous_and_next_pages, sort_pages}; use pagination::Paginator; use utils::{create_file, create_directory}; use section::{Section}; +use front_matter::{SortBy}; use filters; @@ -77,7 +78,6 @@ pub struct Site { pub config: Config, pub pages: HashMap, pub sections: BTreeMap, - pub index: Option
, pub tera: Tera, live_reload: bool, output_path: PathBuf, @@ -105,7 +105,6 @@ impl Site { config: get_config(path, config_file), pages: HashMap::new(), sections: BTreeMap::new(), - index: None, tera: tera, live_reload: false, output_path: path.join("public"), @@ -140,13 +139,7 @@ impl Site { for entry in glob(&content_glob).unwrap().filter_map(|e| e.ok()) { let path = entry.as_path(); if path.file_name().unwrap() == "_index.md" { - // Index section - if path.parent().unwrap() == self.base_path.join("content") { - self.index = Some(Section::from_file(path, &self.config)?); - } else { - // all the other sections - self.add_section(path)?; - } + self.add_section(path)?; } else { self.add_page(path)?; } @@ -214,8 +207,10 @@ impl Site { for (parent_path, section) in &mut self.sections { // TODO: avoid this clone - let (sorted_pages, _) = sort_pages(section.pages.clone(), Some(section)); + let (mut sorted_pages, cannot_be_sorted_pages) = sort_pages(section.pages.clone(), section.meta.sort_by()); + sorted_pages = populate_previous_and_next_pages(&sorted_pages); section.pages = sorted_pages; + section.ignored_pages = cannot_be_sorted_pages; match grandparent_paths.get(parent_path) { Some(paths) => section.subsections.extend(paths.clone()), @@ -257,6 +252,14 @@ impl Site { html } + pub fn ensure_public_directory_exists(&self) -> Result<()> { + let public = self.output_path.clone(); + if !public.exists() { + create_directory(&public)?; + } + Ok(()) + } + /// Copy static file to public directory. pub fn copy_static_file>(&self, path: P) -> Result<()> { let relative_path = path.as_ref().strip_prefix(&self.static_path).unwrap(); @@ -298,39 +301,29 @@ impl Site { pub fn rebuild_after_content_change(&mut self, path: &Path) -> Result<()> { let is_section = path.ends_with("_index.md"); - let is_index_section = if is_section { - path.parent().unwrap() == self.base_path.join("content") - } else { - false - }; if path.exists() { // file exists, either a new one or updating content if is_section { - if is_index_section { - self.index = Some(Section::from_file(path, &self.config)?); - } else { - self.add_section(path)?; - } + self.add_section(path)?; } else { // probably just an update so just re-parse that page + // TODO: we can compare the frontmatter of the existing and new one + // to see if we need to update re-build the whole thing or just that + // page self.add_page_and_render(path)?; } } else if is_section { // File doesn't exist -> a deletion so we remove it from everything - if !is_index_section { - let relative_path = self.sections[path].relative_path.clone(); - self.sections.remove(path); - self.permalinks.remove(&relative_path); - } else { - self.index = None; - } + let relative_path = self.sections[path].relative_path.clone(); + self.sections.remove(path); + self.permalinks.remove(&relative_path); } else { let relative_path = self.pages[path].relative_path.clone(); self.pages.remove(path); self.permalinks.remove(&relative_path); } - + // TODO: probably no need to do that, we should be able to only re-render a page or a section. self.populate_sections(); self.populate_tags_and_categories(); self.build() @@ -341,19 +334,16 @@ impl Site { match path.file_name().unwrap().to_str().unwrap() { "sitemap.xml" => self.render_sitemap(), "rss.xml" => self.render_rss_feed(), - _ => self.build_pages() + _ => self.build() // TODO: change that } } /// Renders a single content page pub fn render_page(&self, page: &Page) -> Result<()> { - let public = self.output_path.clone(); - if !public.exists() { - create_directory(&public)?; - } + self.ensure_public_directory_exists()?; // Copy the nesting of the content directory if we have sections for that page - let mut current_path = public.to_path_buf(); + let mut current_path = self.output_path.to_path_buf(); for component in page.path.split('/') { current_path.push(component); @@ -379,26 +369,16 @@ impl Site { Ok(()) } - /// Renders all content, categories, tags and index pages - pub fn build_pages(&self) -> Result<()> { - let public = self.output_path.clone(); - if !public.exists() { - create_directory(&public)?; + /// Builds the site to the `public` directory after deleting it + pub fn build(&self) -> Result<()> { + self.clean()?; + self.render_sections()?; + self.render_orphan_pages()?; + self.render_sitemap()?; + if self.config.generate_rss.unwrap() { + self.render_rss_feed()?; } - - // Sort the pages first - // TODO: avoid the clone() - let (mut sorted_pages, cannot_sort_pages) = sort_pages(self.pages.values().cloned().collect(), self.index.as_ref()); - - sorted_pages = populate_previous_and_next_pages(&sorted_pages); - for page in &sorted_pages { - self.render_page(page)?; - } - for page in &cannot_sort_pages { - self.render_page(page)?; - } - - // Outputting categories and pages + self.render_robots()?; if self.config.generate_categories_pages.unwrap() { self.render_categories_and_tags(RenderList::Categories)?; } @@ -406,49 +386,12 @@ impl Site { self.render_categories_and_tags(RenderList::Tags)?; } - // And finally the index page - let mut rendered_index = false; - // Try to render the index as a paginated page first if needed - if let Some(ref i) = self.index { - if i.meta.is_paginated() { - self.render_paginated(&self.output_path, i)?; - rendered_index = true; - } - } - - // Otherwise render the default index page - if !rendered_index { - let mut context = Context::new(); - context.add("pages", &sorted_pages); - context.add("sections", &self.sections.values().collect::>()); - context.add("config", &self.config); - context.add("current_url", &self.config.base_url); - context.add("current_path", &""); - let index = self.tera.render("index.html", &context)?; - create_file(public.join("index.html"), &self.inject_livereload(index))?; - } - - Ok(()) - } - - /// Builds the site to the `public` directory after deleting it - pub fn build(&self) -> Result<()> { - self.clean()?; - self.build_pages()?; - self.render_sitemap()?; - - if self.config.generate_rss.unwrap() { - self.render_rss_feed()?; - } - - self.render_robots()?; - - self.render_sections()?; self.copy_static_directory() } /// Renders robots.txt fn render_robots(&self) -> Result<()> { + self.ensure_public_directory_exists()?; create_file( self.output_path.join("robots.txt"), &self.tera.render("robots.txt", &Context::new())? @@ -472,6 +415,7 @@ impl Site { } else { ("tags.html", "tag.html", "tags", "tag") }; + self.ensure_public_directory_exists()?; // Create the categories/tags directory first let public = self.output_path.clone(); @@ -497,7 +441,7 @@ impl Site { // Now, each individual item for (item_name, pages_paths) in items.iter() { - let mut pages: Vec<&Page> = self.pages + let pages: Vec<&Page> = self.pages .iter() .filter(|&(path, _)| pages_paths.contains(path)) .map(|(_, page)| page) @@ -505,8 +449,7 @@ impl Site { // TODO: how to sort categories and tag content? // Have a setting in config.toml or a _category.md and _tag.md // The latter is more in line with the rest of Gutenberg but order ordering - // doesn't really work across sections so default to partial ordering for now (date) - pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); + // doesn't really work across sections. let mut context = Context::new(); let slug = slugify(&item_name); @@ -529,6 +472,7 @@ impl Site { } fn render_sitemap(&self) -> Result<()> { + self.ensure_public_directory_exists()?; let mut context = Context::new(); context.add("pages", &self.pages.values().collect::>()); context.add("sections", &self.sections.values().collect::>()); @@ -563,20 +507,22 @@ impl Site { } fn render_rss_feed(&self) -> Result<()> { + self.ensure_public_directory_exists()?; + let mut context = Context::new(); - let mut pages = self.pages.values() + let pages = self.pages.values() .filter(|p| p.meta.date.is_some()) .take(15) // limit to the last 15 elements - .collect::>(); + .map(|p| p.clone()) + .collect::>(); // Don't generate a RSS feed if none of the pages has a date if pages.is_empty() { return Ok(()); } - - pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); - context.add("pages", &pages); context.add("last_build_date", &pages[0].meta.date); + let (sorted_pages, _) = sort_pages(pages, SortBy::Date); + context.add("pages", &sorted_pages); context.add("config", &self.config); let rss_feed_url = if self.config.base_url.ends_with('/') { @@ -594,6 +540,7 @@ impl Site { } fn render_sections(&self) -> Result<()> { + self.ensure_public_directory_exists()?; let public = self.output_path.clone(); for section in self.sections.values() { @@ -609,9 +556,34 @@ impl Site { if section.meta.is_paginated() { self.render_paginated(&output_path, section)?; } else { - let output = section.render_html(&self.tera, &self.config)?; + let output = section.render_html( + &self.sections.values().collect::>(), + &self.tera, + &self.config, + )?; create_file(output_path.join("index.html"), &self.inject_livereload(output))?; } + + for page in §ion.pages { + self.render_page(page)?; + } + } + + Ok(()) + } + + /// Renders all pages that do not belong to any sections + fn render_orphan_pages(&self) -> Result<()> { + self.ensure_public_directory_exists()?; + let mut pages_in_sections = vec![]; + for s in self.sections.values() { + pages_in_sections.extend(s.all_pages_path()); + } + + for page in self.pages.values() { + if !pages_in_sections.contains(&page.file_path) { + self.render_page(page)?; + } } Ok(()) @@ -619,20 +591,14 @@ impl Site { /// Renders a list of pages when the section/index is wanting pagination. fn render_paginated(&self, output_path: &Path, section: &Section) -> Result<()> { + self.ensure_public_directory_exists()?; + let paginate_path = match section.meta.paginate_path { Some(ref s) => s.clone(), None => unreachable!() }; - // this will sort too many times! - // TODO: make sorting happen once for everything so we don't need to sort all the time - let sorted_pages = if section.is_index() { - sort_pages(self.pages.values().cloned().collect(), self.index.as_ref()).0 - } else { - sort_pages(section.pages.clone(), Some(section)).0 - }; - - let paginator = Paginator::new(&sorted_pages, section); + let paginator = Paginator::new(§ion.pages, section); for (i, pager) in paginator.pagers.iter().enumerate() { let folder_path = output_path.join(&paginate_path); diff --git a/test_site/content/hello.md b/test_site/content/hello.md new file mode 100644 index 00000000..ac36e062 --- /dev/null +++ b/test_site/content/hello.md @@ -0,0 +1,2 @@ ++++ ++++ diff --git a/test_site/templates/index.html b/test_site/templates/index.html index b00fd1f8..bd9bca00 100644 --- a/test_site/templates/index.html +++ b/test_site/templates/index.html @@ -15,7 +15,7 @@
{% block content %}
- {% for page in pages %} + {% for page in section.pages %} diff --git a/test_site/templates/section_paginated.html b/test_site/templates/section_paginated.html index cf745143..820e4244 100644 --- a/test_site/templates/section_paginated.html +++ b/test_site/templates/section_paginated.html @@ -7,7 +7,7 @@ {% for pager in paginator.pagers %} {{pager.index}}: {{pager.path | safe }} {% endfor %} - Num pages: {{ paginator.pages | length }} + Num pagers: {{ paginator.pagers | length }} Page size: {{ paginator.paginate_by }} Current index: {{ paginator.current_index }} First: {{ paginator.first | safe }} diff --git a/tests/front_matter.rs b/tests/front_matter.rs index 9467779a..cb09953a 100644 --- a/tests/front_matter.rs +++ b/tests/front_matter.rs @@ -74,10 +74,10 @@ url = "hello-world""#; } #[test] -fn test_errors_with_empty_front_matter() { +fn test_is_ok_with_empty_front_matter() { let content = r#" "#; let res = FrontMatter::parse(content); - assert!(res.is_err()); + assert!(res.is_ok()); } #[test] diff --git a/tests/site.rs b/tests/site.rs index 03ed8665..def308a2 100644 --- a/tests/site.rs +++ b/tests/site.rs @@ -19,12 +19,9 @@ fn test_can_parse_site() { site.load().unwrap(); // Correct number of pages (sections are pages too) - assert_eq!(site.pages.len(), 10); + assert_eq!(site.pages.len(), 11); let posts_path = path.join("content").join("posts"); - // We have an index page - assert!(site.index.is_some()); - // Make sure we remove all the pwd + content from the sections let basic = &site.pages[&posts_path.join("simple.md")]; assert_eq!(basic.components, vec!["posts".to_string()]); @@ -38,12 +35,16 @@ fn test_can_parse_site() { assert_eq!(asset_folder_post.components, vec!["posts".to_string()]); // That we have the right number of sections - assert_eq!(site.sections.len(), 4); + assert_eq!(site.sections.len(), 5); // And that the sections are correct + let index_section = &site.sections[&path.join("content")]; + assert_eq!(index_section.subsections.len(), 1); + assert_eq!(index_section.pages.len(), 1); + let posts_section = &site.sections[&posts_path]; assert_eq!(posts_section.subsections.len(), 1); - assert_eq!(posts_section.pages.len(), 4); + assert_eq!(posts_section.pages.len(), 5); let tutorials_section = &site.sections[&posts_path.join("tutorials")]; assert_eq!(tutorials_section.subsections.len(), 2); @@ -108,6 +109,7 @@ fn test_can_build_site_without_live_reload() { assert!(file_exists!(public, "posts/python/index.html")); assert!(file_exists!(public, "posts/tutorials/devops/nix/index.html")); assert!(file_exists!(public, "posts/with-assets/index.html")); + assert!(file_exists!(public, "posts/no-section/simple/index.html")); // Sections assert!(file_exists!(public, "posts/index.html")); @@ -126,9 +128,6 @@ fn test_can_build_site_without_live_reload() { // Both pages and sections are in the sitemap assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/posts/simple")); assert!(file_contains!(public, "sitemap.xml", "https://replace-this-with-your-url.com/posts")); - - assert!(file_contains!(public, "a-fixed-url/index.html", "Previous article: ")); - assert!(file_contains!(public, "a-fixed-url/index.html", "Next article: ")); } #[test] @@ -323,22 +322,22 @@ fn test_can_build_site_with_pagination_for_section() { "posts/page/1/index.html", "http-equiv=\"refresh\" content=\"0;url=https://replace-this-with-your-url.com/posts\"" )); - assert!(file_contains!(public, "posts/index.html", "Num pages: 2")); + assert!(file_contains!(public, "posts/index.html", "Num pagers: 3")); assert!(file_contains!(public, "posts/index.html", "Page size: 2")); assert!(file_contains!(public, "posts/index.html", "Current index: 1")); assert!(file_contains!(public, "posts/index.html", "has_next")); assert!(file_contains!(public, "posts/index.html", "First: https://replace-this-with-your-url.com/posts")); - assert!(file_contains!(public, "posts/index.html", "Last: https://replace-this-with-your-url.com/posts/page/2")); + assert!(file_contains!(public, "posts/index.html", "Last: https://replace-this-with-your-url.com/posts/page/3")); assert_eq!(file_contains!(public, "posts/index.html", "has_prev"), false); assert!(file_exists!(public, "posts/page/2/index.html")); - assert!(file_contains!(public, "posts/page/2/index.html", "Num pages: 2")); + assert!(file_contains!(public, "posts/page/2/index.html", "Num pagers: 3")); assert!(file_contains!(public, "posts/page/2/index.html", "Page size: 2")); assert!(file_contains!(public, "posts/page/2/index.html", "Current index: 2")); assert!(file_contains!(public, "posts/page/2/index.html", "has_prev")); - assert_eq!(file_contains!(public, "posts/page/2/index.html", "has_next"), false); + assert!(file_contains!(public, "posts/page/2/index.html", "has_next")); assert!(file_contains!(public, "posts/page/2/index.html", "First: https://replace-this-with-your-url.com/posts")); - assert!(file_contains!(public, "posts/page/2/index.html", "Last: https://replace-this-with-your-url.com/posts/page/2")); + assert!(file_contains!(public, "posts/page/2/index.html", "Last: https://replace-this-with-your-url.com/posts/page/3")); } #[test] @@ -347,10 +346,11 @@ fn test_can_build_site_with_pagination_for_index() { path.push("test_site"); let mut site = Site::new(&path, "config.toml").unwrap(); site.load().unwrap(); - let mut index = site.index.unwrap(); - index.meta.paginate_by = Some(2); - index.meta.template = Some("index_paginated.html".to_string()); - site.index = Some(index); + { + let mut index = site.sections.get_mut(&path.join("content")).unwrap(); + index.meta.paginate_by = Some(2); + index.meta.template = Some("index_paginated.html".to_string()); + } let tmp_dir = TempDir::new("example").expect("create temp dir"); let public = &tmp_dir.path().join("public"); site.set_output_path(&public); @@ -374,11 +374,11 @@ fn test_can_build_site_with_pagination_for_index() { "page/1/index.html", "http-equiv=\"refresh\" content=\"0;url=https://replace-this-with-your-url.com/\"" )); - assert!(file_contains!(public, "index.html", "Num pages: 2")); + assert!(file_contains!(public, "index.html", "Num pages: 1")); assert!(file_contains!(public, "index.html", "Current index: 1")); - assert!(file_contains!(public, "index.html", "has_next")); assert!(file_contains!(public, "index.html", "First: https://replace-this-with-your-url.com/")); - assert!(file_contains!(public, "index.html", "Last: https://replace-this-with-your-url.com/page/2")); + assert!(file_contains!(public, "index.html", "Last: https://replace-this-with-your-url.com/")); assert_eq!(file_contains!(public, "index.html", "has_prev"), false); + assert_eq!(file_contains!(public, "index.html", "has_next"), false); } From 4df9752b54dbf2f70916c15d463a9d8b65319cab Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Tue, 9 May 2017 20:24:44 +0900 Subject: [PATCH 3/7] Pass the to the index --- Cargo.lock | 14 +++++++------- src/section.rs | 5 +++-- src/site.rs | 12 ++++++++---- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c03739a4..406f4b9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,15 +282,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.10.9" +version = "0.10.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -333,7 +333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -726,7 +726,7 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -831,7 +831,7 @@ dependencies = [ "pest 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1101,7 +1101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" "checksum humansize 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92d211e6e70b05749dce515b47684f29a3c8c38bbbb21c50b30aff9eca1b0bd3" -"checksum hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)" = "94da93321c171e26481afeebe8288757b0501901b7c5492648163d8ec4942ec5" +"checksum hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "36e108e0b1fa2d17491cbaac4bc460dc0956029d10ccf83c913dd0e5db3e7f07" "checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be" @@ -1154,7 +1154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3b46a59dd63931010fdb1d88538513f3279090d88b5c22ef4fe8440cfffcc6e3" "checksum serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c06b68790963518008b8ae0152d48be4bbbe77015d2c717f6282eea1824be9a" "checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" -"checksum serde_json 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c62115693d0a9ed8c32d1c760f0fdbe7d4b05cb13c135b9b54137ac0d59fccb" +"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" diff --git a/src/section.rs b/src/section.rs index fa865c67..678b1caf 100644 --- a/src/section.rs +++ b/src/section.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::result::Result as StdResult; @@ -89,7 +90,7 @@ impl Section { } /// Renders the page using the default layout, unless specified in front-matter - pub fn render_html(&self, sections: &[&Section], tera: &Tera, config: &Config) -> Result { + pub fn render_html(&self, sections: &HashMap, tera: &Tera, config: &Config) -> Result { let tpl_name = self.get_template_name(); let mut context = Context::new(); @@ -98,7 +99,7 @@ impl Section { context.add("current_url", &self.permalink); context.add("current_path", &self.path); if self.is_index() { - context.add("sections", §ions); + context.add("sections", sections); } tera.render(&tpl_name, &context) diff --git a/src/site.rs b/src/site.rs index 5af17759..43340a32 100644 --- a/src/site.rs +++ b/src/site.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, HashMap}; +use std::collections::{HashMap}; use std::iter::FromIterator; use std::fs::{remove_dir_all, copy, create_dir_all}; use std::path::{Path, PathBuf}; @@ -77,7 +77,7 @@ pub struct Site { pub base_path: PathBuf, pub config: Config, pub pages: HashMap, - pub sections: BTreeMap, + pub sections: HashMap, pub tera: Tera, live_reload: bool, output_path: PathBuf, @@ -104,7 +104,7 @@ impl Site { base_path: path.to_path_buf(), config: get_config(path, config_file), pages: HashMap::new(), - sections: BTreeMap::new(), + sections: HashMap::new(), tera: tera, live_reload: false, output_path: path.join("public"), @@ -542,6 +542,10 @@ impl Site { fn render_sections(&self) -> Result<()> { self.ensure_public_directory_exists()?; let public = self.output_path.clone(); + let sections: HashMap = self.sections + .values() + .map(|s| (s.components.join("/"), s.clone())) + .collect(); for section in self.sections.values() { let mut output_path = public.to_path_buf(); @@ -557,7 +561,7 @@ impl Site { self.render_paginated(&output_path, section)?; } else { let output = section.render_html( - &self.sections.values().collect::>(), + §ions, &self.tera, &self.config, )?; From 7099fc8ac291b9d671ae6d09ec4c7c7d34d30f10 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Tue, 9 May 2017 20:39:40 +0900 Subject: [PATCH 4/7] Add frontmatter flag to not render a section Useful if you're creating a section only to access it in the index but do not want a section page for it --- Cargo.lock | 6 +++--- src/front_matter.rs | 12 ++++++++++++ src/site.rs | 3 +++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 406f4b9f..5737d73a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,7 +19,7 @@ dependencies = [ "staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tera 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tera 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "term-painter 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.0 (git+https://github.com/alexcrichton/toml-rs)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -820,7 +820,7 @@ dependencies = [ [[package]] name = "tera" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1165,7 +1165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum syntect 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24204b1f4bdd49f84e5f4b219d0bf1dc45ac2fd7fc46320ab6627b537d6d4b69" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum tera 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d09d7a9a4ef4da73121c89842ab00213528804b9992001955871cd6ee49d66c" +"checksum tera 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86bc1156f5502b5eb3904348f4bea155d728e51fec7c981c44b3f1d10b8e574b" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" "checksum term-painter 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ab900bf2f05175932b13d4fc12f8ff09ef777715b04998791ab2c930841e496b" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" diff --git a/src/front_matter.rs b/src/front_matter.rs index 09da15ec..c53e2f54 100644 --- a/src/front_matter.rs +++ b/src/front_matter.rs @@ -58,6 +58,9 @@ pub struct FrontMatter { /// Path to be used by pagination: the page number will be appended after it. Defaults to `page`. #[serde(skip_serializing)] pub paginate_path: Option, + /// Whether to render that page/section or not. Defaults to `true`. + #[serde(skip_serializing)] + pub render: Option, /// Any extra parameter present in the front matter pub extra: Option>, } @@ -85,6 +88,10 @@ impl FrontMatter { f.paginate_path = Some("page".to_string()); } + if f.render.is_none() { + f.render = Some(true); + } + Ok(f) } @@ -121,6 +128,10 @@ impl FrontMatter { None => false } } + + pub fn should_render(&self) -> bool { + self.render.unwrap() + } } impl Default for FrontMatter { @@ -139,6 +150,7 @@ impl Default for FrontMatter { template: None, paginate_by: None, paginate_path: None, + render: None, extra: None, } } diff --git a/src/site.rs b/src/site.rs index 43340a32..f5ffdaae 100644 --- a/src/site.rs +++ b/src/site.rs @@ -548,6 +548,9 @@ impl Site { .collect(); for section in self.sections.values() { + if !section.meta.should_render() { + continue; + } let mut output_path = public.to_path_buf(); for component in §ion.components { output_path.push(component); From f3edef26407461492a4651e01822abf62a161b51 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Tue, 9 May 2017 21:12:10 +0900 Subject: [PATCH 5/7] Warn about ignored pages --- src/cmd/build.rs | 3 ++- src/cmd/mod.rs | 21 +++++++++++++++++++++ src/cmd/serve.rs | 3 ++- src/site.rs | 7 +++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 580439e4..6f65f672 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -7,6 +7,7 @@ use gutenberg::Site; pub fn build(config_file: &str) -> Result<()> { let mut site = Site::new(env::current_dir().unwrap(), config_file)?; site.load()?; - println!("-> Creating {} pages and {} sections", site.pages.len(), site.sections.len()); + super::notify_site_size(&site); + super::warn_about_ignored_pages(&site); site.build() } diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index e3c62b5e..33360fa5 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -5,3 +5,24 @@ mod serve; pub use self::init::create_new_project; pub use self::build::build; pub use self::serve::serve; + +use gutenberg::Site; + +use console::warn; + +fn notify_site_size(site: &Site) { + println!("-> Creating {} pages and {} sections", site.pages.len(), site.sections.len()); +} + +fn warn_about_ignored_pages(site: &Site) { + let ignored_pages = site.get_ignored_pages(); + if !ignored_pages.is_empty() { + warn(&format!( + "{} page(s) ignored (missing date or order in a sorted section):", + ignored_pages.len() + )); + for path in site.get_ignored_pages() { + warn(&format!("- {}", path.display())); + } + } +} diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs index fb16ee2f..115f65e6 100644 --- a/src/cmd/serve.rs +++ b/src/cmd/serve.rs @@ -67,7 +67,8 @@ pub fn serve(interface: &str, port: &str, config_file: &str) -> Result<()> { site.load()?; site.enable_live_reload(); - println!("-> Creating {} pages and {} sections", site.pages.len(), site.sections.len()); + super::notify_site_size(&site); + super::warn_about_ignored_pages(&site); site.build()?; report_elapsed_time(start); diff --git a/src/site.rs b/src/site.rs index f5ffdaae..5cd91272 100644 --- a/src/site.rs +++ b/src/site.rs @@ -122,6 +122,13 @@ impl Site { self.live_reload = true; } + pub fn get_ignored_pages(&self) -> Vec { + self.sections + .values() + .flat_map(|s| s.ignored_pages.iter().map(|p| p.file_path.clone())) + .collect() + } + /// Used by tests to change the output path to a tmp dir #[doc(hidden)] pub fn set_output_path>(&mut self, path: P) { From c989ab607c4aac084c9fe4cbc19aae5a904a439d Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Tue, 9 May 2017 21:47:02 +0900 Subject: [PATCH 6/7] Add orphan in print notice and fix orphan with assets and url --- src/cmd/mod.rs | 7 ++++++- src/page.rs | 16 ++++++++++------ src/site.rs | 29 +++++++++++++++++++++-------- tests/page.rs | 25 ++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 33360fa5..d99fa6a3 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -11,7 +11,12 @@ use gutenberg::Site; use console::warn; fn notify_site_size(site: &Site) { - println!("-> Creating {} pages and {} sections", site.pages.len(), site.sections.len()); + println!( + "-> Creating {} pages ({} orphan) and {} sections", + site.pages.len(), + site.get_all_orphan_pages().len(), + site.sections.len() + ); } fn warn_about_ignored_pages(site: &Site) { diff --git a/src/page.rs b/src/page.rs index 06d83e72..c63f63ca 100644 --- a/src/page.rs +++ b/src/page.rs @@ -143,23 +143,27 @@ impl Page { // 4. Find sections // Pages with custom urls exists outside of sections + let mut path_set = false; if let Some(ref u) = page.meta.url { page.path = u.trim().to_string(); - } else if !page.components.is_empty() { + path_set = true; + } + + if !page.components.is_empty() { // If we have a folder with an asset, don't consider it as a component if page.file_name == "index" { page.components.pop(); // also set parent_path to grandparent instead page.parent_path = page.parent_path.parent().unwrap().to_path_buf(); } - - // Don't add a trailing slash to sections - page.path = format!("{}/{}", page.components.join("/"), page.slug); - } else { + if !path_set { + // Don't add a trailing slash to sections + page.path = format!("{}/{}", page.components.join("/"), page.slug); + } + } else if !path_set { page.path = page.slug.clone(); } - page.permalink = config.make_permalink(&page.path); Ok(page) diff --git a/src/site.rs b/src/site.rs index 5cd91272..27d2373d 100644 --- a/src/site.rs +++ b/src/site.rs @@ -122,6 +122,7 @@ impl Site { self.live_reload = true; } + /// Gets the path of all ignored pages in the site pub fn get_ignored_pages(&self) -> Vec { self.sections .values() @@ -129,6 +130,24 @@ impl Site { .collect() } + /// Get all the orphan (== without section) pages in the site + pub fn get_all_orphan_pages(&self) -> Vec<&Page> { + let mut pages_in_sections = vec![]; + let mut orphans = vec![]; + + for s in self.sections.values() { + pages_in_sections.extend(s.all_pages_path()); + } + + for page in self.pages.values() { + if !pages_in_sections.contains(&page.file_path) { + orphans.push(page); + } + } + + orphans + } + /// Used by tests to change the output path to a tmp dir #[doc(hidden)] pub fn set_output_path>(&mut self, path: P) { @@ -589,15 +608,9 @@ impl Site { /// Renders all pages that do not belong to any sections fn render_orphan_pages(&self) -> Result<()> { self.ensure_public_directory_exists()?; - let mut pages_in_sections = vec![]; - for s in self.sections.values() { - pages_in_sections.extend(s.all_pages_path()); - } - for page in self.pages.values() { - if !pages_in_sections.contains(&page.file_path) { - self.render_page(page)?; - } + for page in self.get_all_orphan_pages() { + self.render_page(page)?; } Ok(()) diff --git a/tests/page.rs b/tests/page.rs index 29c5ee13..5833ce0e 100644 --- a/tests/page.rs +++ b/tests/page.rs @@ -3,7 +3,7 @@ extern crate tera; extern crate tempdir; use std::collections::HashMap; -use std::fs::File; +use std::fs::{File, create_dir}; use std::path::Path; use tempdir::TempDir; @@ -252,6 +252,29 @@ Hey there assert!(page.content.starts_with(" Date: Tue, 9 May 2017 23:10:27 +0900 Subject: [PATCH 7/7] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58f0bb1b..c2066ffb 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Each kind of page get their own variables: // TODO: detail the schema of the variables -- index.html: gets `pages` that contain all pages in the site +- index.html: gets `section` representing the index section and all `sections` - page.html: gets `page` that contains the data for that page - section.html: gets `section` that contains the data for pages in it and its subsections - tags.html: gets `tags`