@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "config" | name = "config" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
toml = "0.4" | toml = "0.4" | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "content" | name = "content" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
tera = "0.11" | tera = "0.11" | ||||
@@ -104,7 +104,7 @@ impl Section { | |||||
config.highlight_theme.clone(), | config.highlight_theme.clone(), | ||||
&self.permalink, | &self.permalink, | ||||
permalinks, | permalinks, | ||||
self.meta.insert_anchor_links.unwrap() | |||||
self.meta.insert_anchor_links, | |||||
); | ); | ||||
let res = markdown_to_html(&self.raw_content, &context)?; | let res = markdown_to_html(&self.raw_content, &context)?; | ||||
self.content = res.0; | self.content = res.0; | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "errors" | name = "errors" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
error-chain = "0.11" | error-chain = "0.11" | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "front_matter" | name = "front_matter" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
tera = "0.11" | tera = "0.11" | ||||
@@ -12,6 +12,7 @@ static DEFAULT_PAGINATE_PATH: &'static str = "page"; | |||||
/// The front matter of every section | /// The front matter of every section | ||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | ||||
#[serde(default)] | |||||
pub struct SectionFrontMatter { | pub struct SectionFrontMatter { | ||||
/// <title> of the page | /// <title> of the page | ||||
pub title: Option<String>, | pub title: Option<String>, | ||||
@@ -19,11 +20,11 @@ pub struct SectionFrontMatter { | |||||
pub description: Option<String>, | pub description: Option<String>, | ||||
/// Whether to sort by "date", "order", "weight" or "none". Defaults to `none`. | /// Whether to sort by "date", "order", "weight" or "none". Defaults to `none`. | ||||
#[serde(skip_serializing)] | #[serde(skip_serializing)] | ||||
pub sort_by: Option<SortBy>, | |||||
pub sort_by: SortBy, | |||||
/// Used by the parent section to order its subsections. | /// Used by the parent section to order its subsections. | ||||
/// Higher values means it will be at the end. | |||||
/// Higher values means it will be at the end. Defaults to `0` | |||||
#[serde(skip_serializing)] | #[serde(skip_serializing)] | ||||
pub weight: Option<usize>, | |||||
pub weight: usize, | |||||
/// Optional template, if we want to specify which template to render for that section | /// Optional template, if we want to specify which template to render for that section | ||||
#[serde(skip_serializing)] | #[serde(skip_serializing)] | ||||
pub template: Option<String>, | pub template: Option<String>, | ||||
@@ -32,59 +33,38 @@ pub struct SectionFrontMatter { | |||||
pub paginate_by: Option<usize>, | pub paginate_by: Option<usize>, | ||||
/// Path to be used by pagination: the page number will be appended after it. Defaults to `page`. | /// Path to be used by pagination: the page number will be appended after it. Defaults to `page`. | ||||
#[serde(skip_serializing)] | #[serde(skip_serializing)] | ||||
pub paginate_path: Option<String>, | |||||
pub paginate_path: String, | |||||
/// Whether to insert a link for each header like the ones you can see in this site if you hover one | /// Whether to insert a link for each header like the ones you can see in this site if you hover one | ||||
/// The default template can be overridden by creating a `anchor-link.html` in the `templates` directory | /// The default template can be overridden by creating a `anchor-link.html` in the `templates` directory | ||||
pub insert_anchor_links: Option<InsertAnchor>, | |||||
pub insert_anchor_links: InsertAnchor, | |||||
/// Whether to render that section or not. Defaults to `true`. | /// Whether to render that section or not. Defaults to `true`. | ||||
/// Useful when the section is only there to organize things but is not meant | /// Useful when the section is only there to organize things but is not meant | ||||
/// to be used directly, like a posts section in a personal site | /// to be used directly, like a posts section in a personal site | ||||
#[serde(skip_serializing)] | #[serde(skip_serializing)] | ||||
pub render: Option<bool>, | |||||
pub render: bool, | |||||
/// Whether to redirect when landing on that section. Defaults to `None`. | /// Whether to redirect when landing on that section. Defaults to `None`. | ||||
/// Useful for the same reason as `render` but when you don't want a 404 when | /// Useful for the same reason as `render` but when you don't want a 404 when | ||||
/// landing on the root section page | /// landing on the root section page | ||||
#[serde(skip_serializing)] | #[serde(skip_serializing)] | ||||
pub redirect_to: Option<String>, | pub redirect_to: Option<String>, | ||||
/// Whether the section content and its pages/subsections are included in the index. | |||||
/// Defaults to `true` but is only used if search if explicitely enabled in the config. | |||||
#[serde(skip_serializing)] | |||||
pub in_search_index: bool, | |||||
/// Any extra parameter present in the front matter | /// Any extra parameter present in the front matter | ||||
pub extra: Option<HashMap<String, Value>>, | |||||
pub extra: HashMap<String, Value>, | |||||
} | } | ||||
impl SectionFrontMatter { | impl SectionFrontMatter { | ||||
pub fn parse(toml: &str) -> Result<SectionFrontMatter> { | pub fn parse(toml: &str) -> Result<SectionFrontMatter> { | ||||
let mut f: SectionFrontMatter = match toml::from_str(toml) { | |||||
let f: SectionFrontMatter = match toml::from_str(toml) { | |||||
Ok(d) => d, | Ok(d) => d, | ||||
Err(e) => bail!(e), | Err(e) => bail!(e), | ||||
}; | }; | ||||
if f.paginate_path.is_none() { | |||||
f.paginate_path = Some(DEFAULT_PAGINATE_PATH.to_string()); | |||||
} | |||||
if f.render.is_none() { | |||||
f.render = Some(true); | |||||
} | |||||
if f.sort_by.is_none() { | |||||
f.sort_by = Some(SortBy::None); | |||||
} | |||||
if f.insert_anchor_links.is_none() { | |||||
f.insert_anchor_links = Some(InsertAnchor::None); | |||||
} | |||||
if f.weight.is_none() { | |||||
f.weight = Some(0); | |||||
} | |||||
Ok(f) | Ok(f) | ||||
} | } | ||||
/// Returns the current sorting method, defaults to `None` (== no sorting) | |||||
pub fn sort_by(&self) -> SortBy { | |||||
self.sort_by.unwrap() | |||||
} | |||||
/// Only applies to section, whether it is paginated or not. | /// Only applies to section, whether it is paginated or not. | ||||
pub fn is_paginated(&self) -> bool { | pub fn is_paginated(&self) -> bool { | ||||
match self.paginate_by { | match self.paginate_by { | ||||
@@ -92,10 +72,6 @@ impl SectionFrontMatter { | |||||
None => false | None => false | ||||
} | } | ||||
} | } | ||||
pub fn should_render(&self) -> bool { | |||||
self.render.unwrap() | |||||
} | |||||
} | } | ||||
impl Default for SectionFrontMatter { | impl Default for SectionFrontMatter { | ||||
@@ -103,15 +79,16 @@ impl Default for SectionFrontMatter { | |||||
SectionFrontMatter { | SectionFrontMatter { | ||||
title: None, | title: None, | ||||
description: None, | description: None, | ||||
sort_by: Some(SortBy::None), | |||||
weight: Some(0), | |||||
sort_by: SortBy::None, | |||||
weight: 0, | |||||
template: None, | template: None, | ||||
paginate_by: None, | paginate_by: None, | ||||
paginate_path: Some(DEFAULT_PAGINATE_PATH.to_string()), | |||||
render: Some(true), | |||||
paginate_path: DEFAULT_PAGINATE_PATH.to_string(), | |||||
render: true, | |||||
redirect_to: None, | redirect_to: None, | ||||
insert_anchor_links: Some(InsertAnchor::None), | |||||
extra: None, | |||||
insert_anchor_links: InsertAnchor::None, | |||||
in_search_index: true, | |||||
extra: HashMap::new(), | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "highlighting" | name = "highlighting" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
lazy_static = "1" | lazy_static = "1" | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "pagination" | name = "pagination" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
tera = "0.11" | tera = "0.11" | ||||
@@ -72,13 +72,9 @@ impl<'a> Paginator<'a> { | |||||
/// It will always at least create one pager (the first) even if there are no pages to paginate | /// It will always at least create one pager (the first) even if there are no pages to paginate | ||||
pub fn new(all_pages: &'a [Page], section: &'a Section) -> Paginator<'a> { | pub fn new(all_pages: &'a [Page], section: &'a Section) -> Paginator<'a> { | ||||
let paginate_by = section.meta.paginate_by.unwrap(); | let paginate_by = section.meta.paginate_by.unwrap(); | ||||
let paginate_path = match section.meta.paginate_path { | |||||
Some(ref p) => p, | |||||
None => unreachable!(), | |||||
}; | |||||
let mut pages = vec![]; | let mut pages = vec![]; | ||||
let mut current_page = vec![]; | let mut current_page = vec![]; | ||||
for page in all_pages { | for page in all_pages { | ||||
current_page.push(page); | current_page.push(page); | ||||
@@ -99,7 +95,7 @@ impl<'a> Paginator<'a> { | |||||
continue; | continue; | ||||
} | } | ||||
let page_path = format!("{}/{}/", paginate_path, index + 1); | |||||
let page_path = format!("{}/{}/", section.meta.paginate_path, index + 1); | |||||
let permalink = format!("{}{}", section.permalink, page_path); | let permalink = format!("{}{}", section.permalink, page_path); | ||||
let pager_path = if section.is_index() { | let pager_path = if section.is_index() { | ||||
page_path | page_path | ||||
@@ -189,7 +185,7 @@ mod tests { | |||||
fn create_section(is_index: bool) -> Section { | fn create_section(is_index: bool) -> Section { | ||||
let mut f = SectionFrontMatter::default(); | let mut f = SectionFrontMatter::default(); | ||||
f.paginate_by = Some(2); | f.paginate_by = Some(2); | ||||
f.paginate_path = Some("page".to_string()); | |||||
f.paginate_path = "page".to_string(); | |||||
let mut s = Section::new("content/_index.md", f); | let mut s = Section::new("content/_index.md", f); | ||||
if !is_index { | if !is_index { | ||||
s.path = "posts/".to_string(); | s.path = "posts/".to_string(); | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "rebuild" | name = "rebuild" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
errors = { path = "../errors" } | errors = { path = "../errors" } | ||||
@@ -60,7 +60,7 @@ fn find_section_front_matter_changes(current: &SectionFrontMatter, new: &Section | |||||
// We want to hide the section | // We want to hide the section | ||||
// TODO: what to do on redirect_path change? | // TODO: what to do on redirect_path change? | ||||
if current.should_render() && !new.should_render() { | |||||
if current.render && !new.render { | |||||
changes_needed.push(SectionChangesNeeded::Delete); | changes_needed.push(SectionChangesNeeded::Delete); | ||||
// Nothing else we can do | // Nothing else we can do | ||||
return changes_needed; | return changes_needed; | ||||
@@ -383,14 +383,14 @@ mod tests { | |||||
#[test] | #[test] | ||||
fn can_find_sort_changes_in_section_frontmatter() { | fn can_find_sort_changes_in_section_frontmatter() { | ||||
let new = SectionFrontMatter { sort_by: Some(SortBy::Date), ..SectionFrontMatter::default() }; | |||||
let new = SectionFrontMatter { sort_by: SortBy::Date, ..SectionFrontMatter::default() }; | |||||
let changes = find_section_front_matter_changes(&SectionFrontMatter::default(), &new); | let changes = find_section_front_matter_changes(&SectionFrontMatter::default(), &new); | ||||
assert_eq!(changes, vec![SectionChangesNeeded::Sort, SectionChangesNeeded::Render]); | assert_eq!(changes, vec![SectionChangesNeeded::Sort, SectionChangesNeeded::Render]); | ||||
} | } | ||||
#[test] | #[test] | ||||
fn can_find_render_changes_in_section_frontmatter() { | fn can_find_render_changes_in_section_frontmatter() { | ||||
let new = SectionFrontMatter { render: Some(false), ..SectionFrontMatter::default() }; | |||||
let new = SectionFrontMatter { render: false, ..SectionFrontMatter::default() }; | |||||
let changes = find_section_front_matter_changes(&SectionFrontMatter::default(), &new); | let changes = find_section_front_matter_changes(&SectionFrontMatter::default(), &new); | ||||
assert_eq!(changes, vec![SectionChangesNeeded::Delete]); | assert_eq!(changes, vec![SectionChangesNeeded::Delete]); | ||||
} | } | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "rendering" | name = "rendering" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
tera = "0.11" | tera = "0.11" | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "site" | name = "site" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
tera = "0.11" | tera = "0.11" | ||||
@@ -308,7 +308,7 @@ impl Site { | |||||
/// Defaults to `AnchorInsert::None` if no parent section found | /// Defaults to `AnchorInsert::None` if no parent section found | ||||
pub fn find_parent_section_insert_anchor(&self, parent_path: &PathBuf) -> InsertAnchor { | pub fn find_parent_section_insert_anchor(&self, parent_path: &PathBuf) -> InsertAnchor { | ||||
match self.sections.get(&parent_path.join("_index.md")) { | match self.sections.get(&parent_path.join("_index.md")) { | ||||
Some(s) => s.meta.insert_anchor_links.unwrap(), | |||||
Some(s) => s.meta.insert_anchor_links, | |||||
None => InsertAnchor::None | None => InsertAnchor::None | ||||
} | } | ||||
} | } | ||||
@@ -350,7 +350,7 @@ impl Site { | |||||
.map(|p| sections[p].clone()) | .map(|p| sections[p].clone()) | ||||
.collect::<Vec<_>>(); | .collect::<Vec<_>>(); | ||||
section.subsections | section.subsections | ||||
.sort_by(|a, b| a.meta.weight.unwrap().cmp(&b.meta.weight.unwrap())); | |||||
.sort_by(|a, b| a.meta.weight.cmp(&b.meta.weight)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -365,7 +365,7 @@ impl Site { | |||||
} | } | ||||
} | } | ||||
let pages = mem::replace(&mut section.pages, vec![]); | let pages = mem::replace(&mut section.pages, vec![]); | ||||
let (sorted_pages, cannot_be_sorted_pages) = sort_pages(pages, section.meta.sort_by()); | |||||
let (sorted_pages, cannot_be_sorted_pages) = sort_pages(pages, section.meta.sort_by); | |||||
section.pages = populate_previous_and_next_pages(&sorted_pages); | section.pages = populate_previous_and_next_pages(&sorted_pages); | ||||
section.ignored_pages = cannot_be_sorted_pages; | section.ignored_pages = cannot_be_sorted_pages; | ||||
} | } | ||||
@@ -773,7 +773,7 @@ impl Site { | |||||
.reduce(|| Ok(()), Result::and)?; | .reduce(|| Ok(()), Result::and)?; | ||||
} | } | ||||
if !section.meta.should_render() { | |||||
if !section.meta.render { | |||||
return Ok(()); | return Ok(()); | ||||
} | } | ||||
@@ -827,13 +827,8 @@ impl Site { | |||||
pub fn render_paginated(&self, output_path: &Path, section: &Section) -> Result<()> { | pub fn render_paginated(&self, output_path: &Path, section: &Section) -> Result<()> { | ||||
ensure_directory_exists(&self.output_path)?; | ensure_directory_exists(&self.output_path)?; | ||||
let paginate_path = match section.meta.paginate_path { | |||||
Some(ref s) => s.clone(), | |||||
None => unreachable!() | |||||
}; | |||||
let paginator = Paginator::new(§ion.pages, section); | let paginator = Paginator::new(§ion.pages, section); | ||||
let folder_path = output_path.join(&paginate_path); | |||||
let folder_path = output_path.join(§ion.meta.paginate_path); | |||||
create_directory(&folder_path)?; | create_directory(&folder_path)?; | ||||
paginator | paginator | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "taxonomies" | name = "taxonomies" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
tera = "0.11" | tera = "0.11" | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "templates" | name = "templates" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
tera = "0.11" | tera = "0.11" | ||||
@@ -1,7 +1,7 @@ | |||||
[package] | [package] | ||||
name = "utils" | name = "utils" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | |||||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] | |||||
[dependencies] | [dependencies] | ||||
errors = { path = "../errors" } | errors = { path = "../errors" } | ||||