Browse Source

Change Site::section and fix empty paginated sections

index-subcmd
Vincent Prouillet 7 years ago
parent
commit
8711c9a3c0
7 changed files with 57 additions and 25 deletions
  1. +1
    -1
      src/front_matter.rs
  2. +11
    -4
      src/pagination.rs
  3. +1
    -1
      src/section.rs
  4. +21
    -10
      src/site.rs
  5. +4
    -0
      test_site/content/paginated/_index.md
  6. +2
    -1
      test_site/content/posts/_index.md
  7. +17
    -8
      tests/site.rs

+ 1
- 1
src/front_matter.rs View File

@@ -149,7 +149,7 @@ impl Default for FrontMatter {
order: None, order: None,
template: None, template: None,
paginate_by: None, paginate_by: None,
paginate_path: None,
paginate_path: Some("page".to_string()),
render: Some(true), render: Some(true),
extra: None, extra: None,
} }


+ 11
- 4
src/pagination.rs View File

@@ -23,10 +23,10 @@ pub struct Pager<'a> {
impl<'a> Pager<'a> { impl<'a> Pager<'a> {
fn new(index: usize, pages: Vec<&'a Page>, permalink: String, path: String) -> Pager<'a> { fn new(index: usize, pages: Vec<&'a Page>, permalink: String, path: String) -> Pager<'a> {
Pager { Pager {
index: index,
permalink: permalink,
path: path,
pages: pages,
index,
permalink,
path,
pages,
} }
} }
} }
@@ -44,6 +44,8 @@ pub struct Paginator<'a> {
} }


impl<'a> Paginator<'a> { impl<'a> Paginator<'a> {
/// Create a new paginator
/// 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 { let paginate_path = match section.meta.paginate_path {
@@ -87,6 +89,11 @@ impl<'a> Paginator<'a> {
)); ));
} }


// We always have the index one at least
if pagers.is_empty() {
pagers.push(Pager::new(1, vec![], section.permalink.clone(), section.path.clone()));
}

Paginator { Paginator {
all_pages: all_pages, all_pages: all_pages,
pagers: pagers, pagers: pagers,


+ 1
- 1
src/section.rs View File

@@ -149,7 +149,7 @@ impl ser::Serialize for Section {
} }


impl Default for Section { impl Default for Section {
/// Used to create a default index section if there is no _index.md
/// Used to create a default index section if there is no _index.md in the root content directory
fn default() -> Section { fn default() -> Section {
Section { Section {
file_path: PathBuf::new(), file_path: PathBuf::new(),


+ 21
- 10
src/site.rs View File

@@ -173,9 +173,11 @@ impl Site {
} }
// Insert a default index section so we don't need to create a _index.md to render // Insert a default index section so we don't need to create a _index.md to render
// the index page // the index page
let index_path = self.base_path.join("content");
let index_path = self.base_path.join("content").join("_index.md");
if !self.sections.contains_key(&index_path) { if !self.sections.contains_key(&index_path) {
self.sections.insert(index_path, Section::default());
let mut index_section = Section::default();
index_section.permalink = self.config.make_permalink("");
self.sections.insert(index_path, index_section);
} }


// A map of all .md files (section and pages) and their permalink // A map of all .md files (section and pages) and their permalink
@@ -217,7 +219,16 @@ impl Site {
/// Simple wrapper fn to avoid repeating that code in several places /// Simple wrapper fn to avoid repeating that code in several places
fn add_section(&mut self, path: &Path) -> Result<()> { fn add_section(&mut self, path: &Path) -> Result<()> {
let section = Section::from_file(path, &self.config)?; let section = Section::from_file(path, &self.config)?;
self.sections.insert(section.parent_path.clone(), section);
self.sections.insert(section.file_path.clone(), section);
Ok(())
}

/// Called in serve, add the section and render it
fn add_section_and_render(&mut self, path: &Path) -> Result<()> {
self.add_section(path)?;
let mut section = self.sections.get_mut(path).unwrap();
self.permalinks.insert(section.relative_path.clone(), section.permalink.clone());
section.render_markdown(&self.permalinks, &self.tera, &self.config)?;
Ok(()) Ok(())
} }


@@ -239,10 +250,10 @@ impl Site {


/// Find out the direct subsections of each subsection if there are some /// Find out the direct subsections of each subsection if there are some
/// as well as the pages for each section /// as well as the pages for each section
fn populate_sections(&mut self) {
pub fn populate_sections(&mut self) {
for page in self.pages.values() { for page in self.pages.values() {
if self.sections.contains_key(&page.parent_path) {
self.sections.get_mut(&page.parent_path).unwrap().pages.push(page.clone());
if self.sections.contains_key(&page.parent_path.join("_index.md")) {
self.sections.get_mut(&page.parent_path.join("_index.md")).unwrap().pages.push(page.clone());
} }
} }


@@ -253,14 +264,14 @@ impl Site {
} }
} }


for (parent_path, section) in &mut self.sections {
for section in self.sections.values_mut() {
// TODO: avoid this clone // TODO: avoid this clone
let (mut sorted_pages, cannot_be_sorted_pages) = sort_pages(section.pages.clone(), section.meta.sort_by()); 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); sorted_pages = populate_previous_and_next_pages(&sorted_pages);
section.pages = sorted_pages; section.pages = sorted_pages;
section.ignored_pages = cannot_be_sorted_pages; section.ignored_pages = cannot_be_sorted_pages;


match grandparent_paths.get(parent_path) {
match grandparent_paths.get(&section.parent_path) {
Some(paths) => section.subsections.extend(paths.clone()), Some(paths) => section.subsections.extend(paths.clone()),
None => continue, None => continue,
}; };
@@ -353,7 +364,8 @@ impl Site {
if path.exists() { if path.exists() {
// file exists, either a new one or updating content // file exists, either a new one or updating content
if is_section { if is_section {
self.add_section(path)?;
self.add_section_and_render(path)?;
self.render_sections()?;
} else { } else {
// probably just an update so just re-parse that page // probably just an update so just re-parse that page
let (frontmatter_changed, page) = self.add_page_and_render(path)?; let (frontmatter_changed, page) = self.add_page_and_render(path)?;
@@ -661,7 +673,6 @@ impl Site {
}; };


let paginator = Paginator::new(&section.pages, section); let paginator = Paginator::new(&section.pages, section);

for (i, pager) in paginator.pagers.iter().enumerate() { for (i, pager) in paginator.pagers.iter().enumerate() {
let folder_path = output_path.join(&paginate_path); let folder_path = output_path.join(&paginate_path);
let page_path = folder_path.join(&format!("{}", i + 1)); let page_path = folder_path.join(&format!("{}", i + 1));


+ 4
- 0
test_site/content/paginated/_index.md View File

@@ -0,0 +1,4 @@
+++
paginate_by = 10
template = "section_paginated.html"
+++

+ 2
- 1
test_site/content/posts/_index.md View File

@@ -1,4 +1,5 @@
+++ +++
title = "Posts" title = "Posts"
description = ""
paginate_by = 2
template = "section_paginated.html"
+++ +++

+ 17
- 8
tests/site.rs View File

@@ -35,26 +35,26 @@ fn test_can_parse_site() {
assert_eq!(asset_folder_post.components, vec!["posts".to_string()]); assert_eq!(asset_folder_post.components, vec!["posts".to_string()]);


// That we have the right number of sections // That we have the right number of sections
assert_eq!(site.sections.len(), 5);
assert_eq!(site.sections.len(), 6);


// And that the sections are correct // And that the sections are correct
let index_section = &site.sections[&path.join("content")];
assert_eq!(index_section.subsections.len(), 1);
let index_section = &site.sections[&path.join("content").join("_index.md")];
assert_eq!(index_section.subsections.len(), 2);
assert_eq!(index_section.pages.len(), 1); assert_eq!(index_section.pages.len(), 1);


let posts_section = &site.sections[&posts_path];
let posts_section = &site.sections[&posts_path.join("_index.md")];
assert_eq!(posts_section.subsections.len(), 1); assert_eq!(posts_section.subsections.len(), 1);
assert_eq!(posts_section.pages.len(), 5); assert_eq!(posts_section.pages.len(), 5);


let tutorials_section = &site.sections[&posts_path.join("tutorials")];
let tutorials_section = &site.sections[&posts_path.join("tutorials").join("_index.md")];
assert_eq!(tutorials_section.subsections.len(), 2); assert_eq!(tutorials_section.subsections.len(), 2);
assert_eq!(tutorials_section.pages.len(), 0); assert_eq!(tutorials_section.pages.len(), 0);


let devops_section = &site.sections[&posts_path.join("tutorials").join("devops")];
let devops_section = &site.sections[&posts_path.join("tutorials").join("devops").join("_index.md")];
assert_eq!(devops_section.subsections.len(), 0); assert_eq!(devops_section.subsections.len(), 0);
assert_eq!(devops_section.pages.len(), 2); assert_eq!(devops_section.pages.len(), 2);


let prog_section = &site.sections[&posts_path.join("tutorials").join("programming")];
let prog_section = &site.sections[&posts_path.join("tutorials").join("programming").join("_index.md")];
assert_eq!(prog_section.subsections.len(), 0); assert_eq!(prog_section.subsections.len(), 0);
assert_eq!(prog_section.pages.len(), 2); assert_eq!(prog_section.pages.len(), 2);
} }
@@ -294,6 +294,9 @@ fn test_can_build_site_with_pagination_for_section() {
let mut site = Site::new(&path, "config.toml").unwrap(); let mut site = Site::new(&path, "config.toml").unwrap();
site.load().unwrap(); site.load().unwrap();
for section in site.sections.values_mut(){ for section in site.sections.values_mut(){
if section.is_index() {
continue;
}
section.meta.paginate_by = Some(2); section.meta.paginate_by = Some(2);
section.meta.template = Some("section_paginated.html".to_string()); section.meta.template = Some("section_paginated.html".to_string());
} }
@@ -316,6 +319,9 @@ fn test_can_build_site_with_pagination_for_section() {
assert!(file_exists!(public, "posts/index.html")); assert!(file_exists!(public, "posts/index.html"));
// And pagination! // And pagination!
assert!(file_exists!(public, "posts/page/1/index.html")); assert!(file_exists!(public, "posts/page/1/index.html"));
// even if there is no pages, only the section!
assert!(file_exists!(public, "paginated/page/1/index.html"));
assert!(file_exists!(public, "paginated/index.html"));
// should redirect to posts/ // should redirect to posts/
assert!(file_contains!( assert!(file_contains!(
public, public,
@@ -347,7 +353,7 @@ fn test_can_build_site_with_pagination_for_index() {
let mut site = Site::new(&path, "config.toml").unwrap(); let mut site = Site::new(&path, "config.toml").unwrap();
site.load().unwrap(); site.load().unwrap();
{ {
let mut index = site.sections.get_mut(&path.join("content")).unwrap();
let mut index = site.sections.get_mut(&path.join("content").join("_index.md")).unwrap();
index.meta.paginate_by = Some(2); index.meta.paginate_by = Some(2);
index.meta.template = Some("index_paginated.html".to_string()); index.meta.template = Some("index_paginated.html".to_string());
} }
@@ -368,6 +374,9 @@ fn test_can_build_site_with_pagination_for_index() {


// And pagination! // And pagination!
assert!(file_exists!(public, "page/1/index.html")); assert!(file_exists!(public, "page/1/index.html"));
// even if there is no pages, only the section!
assert!(file_exists!(public, "paginated/page/1/index.html"));
assert!(file_exists!(public, "paginated/index.html"));
// should redirect to index // should redirect to index
assert!(file_contains!( assert!(file_contains!(
public, public,


Loading…
Cancel
Save