The wonders of serde default, take 2
This commit is contained in:
parent
cbb2c59b91
commit
bcf42a0c10
|
@ -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),
|
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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" }
|
||||||
|
|
Loading…
Reference in a new issue