The wonders of serde default, take 2

This commit is contained in:
Vincent Prouillet 2018-03-14 18:22:24 +01:00
parent cbb2c59b91
commit bcf42a0c10
17 changed files with 44 additions and 76 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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), sort_by: SortBy::None,
weight: Some(0), weight: 0,
template: None, template: None,
paginate_by: None, paginate_by: None,
paginate_path: Some(DEFAULT_PAGINATE_PATH.to_string()), paginate_path: DEFAULT_PAGINATE_PATH.to_string(),
render: Some(true), render: true,
redirect_to: None, redirect_to: None,
insert_anchor_links: Some(InsertAnchor::None), insert_anchor_links: InsertAnchor::None,
extra: None, in_search_index: true,
extra: HashMap::new(),
} }
} }
} }

View file

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

View file

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

View file

@ -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();

View file

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

View file

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

View file

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

View file

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

View file

@ -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(&section.pages, section); let paginator = Paginator::new(&section.pages, section);
let folder_path = output_path.join(&paginate_path); let folder_path = output_path.join(&section.meta.paginate_path);
create_directory(&folder_path)?; create_directory(&folder_path)?;
paginator paginator

View file

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

View file

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

View file

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