Move stuff around a bit more
This commit is contained in:
parent
07f11755d6
commit
c35b76406e
|
@ -96,8 +96,7 @@ pub fn after_content_change(site: &mut Site, path: &Path) -> Result<()> {
|
|||
// - any page that was referencing the section (index, etc)
|
||||
let relative_path = site.pages[path].relative_path.clone();
|
||||
site.permalinks.remove(&relative_path);
|
||||
match site.pages.remove(path) {
|
||||
Some(p) => {
|
||||
if let Some(p) = site.pages.remove(path) {
|
||||
if p.meta.has_tags() || p.meta.category.is_some() {
|
||||
site.populate_tags_and_categories();
|
||||
}
|
||||
|
@ -105,8 +104,6 @@ pub fn after_content_change(site: &mut Site, path: &Path) -> Result<()> {
|
|||
if site.find_parent_section(&p).is_some() {
|
||||
site.populate_sections();
|
||||
}
|
||||
},
|
||||
None => ()
|
||||
};
|
||||
}
|
||||
// Deletion is something that doesn't happen all the time so we
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
mod page;
|
||||
mod pagination;
|
||||
mod section;
|
||||
mod sorting;
|
||||
mod utils;
|
||||
|
||||
pub use self::page::{Page, sort_pages, populate_previous_and_next_pages};
|
||||
pub use self::page::{Page};
|
||||
pub use self::section::{Section};
|
||||
pub use self::pagination::{Paginator, Pager};
|
||||
pub use self::sorting::{SortBy, sort_pages, populate_previous_and_next_pages};
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/// A page, can be a blog post or a basic page
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{read_dir};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::result::Result as StdResult;
|
||||
|
||||
|
@ -11,32 +10,12 @@ use slug::slugify;
|
|||
|
||||
use errors::{Result, ResultExt};
|
||||
use config::Config;
|
||||
use front_matter::{PageFrontMatter, SortBy, split_page_content};
|
||||
use front_matter::{PageFrontMatter, split_page_content};
|
||||
use markdown::markdown_to_html;
|
||||
use utils::{read_file, find_content_components};
|
||||
use content::utils::{find_related_assets, get_reading_analytics};
|
||||
|
||||
|
||||
/// Looks into the current folder for the path and see if there's anything that is not a .md
|
||||
/// file. Those will be copied next to the rendered .html file
|
||||
fn find_related_assets(path: &Path) -> Vec<PathBuf> {
|
||||
let mut assets = vec![];
|
||||
|
||||
for entry in read_dir(path).unwrap().filter_map(|e| e.ok()) {
|
||||
let entry_path = entry.path();
|
||||
if entry_path.is_file() {
|
||||
match entry_path.extension() {
|
||||
Some(e) => match e.to_str() {
|
||||
Some("md") => continue,
|
||||
_ => assets.push(entry_path.to_path_buf()),
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assets
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Page {
|
||||
|
@ -102,20 +81,6 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_date(&self) -> bool {
|
||||
self.meta.date.is_some()
|
||||
}
|
||||
|
||||
/// Get word count and estimated reading time
|
||||
pub fn get_reading_analytics(&self) -> (usize, usize) {
|
||||
// Only works for latin language but good enough for a start
|
||||
let word_count: usize = self.raw_content.split_whitespace().count();
|
||||
|
||||
// https://help.medium.com/hc/en-us/articles/214991667-Read-time
|
||||
// 275 seems a bit too high though
|
||||
(word_count, (word_count / 200))
|
||||
}
|
||||
|
||||
/// Parse a page given the content of the .md file
|
||||
/// Files without front matter or with invalid front matter are considered
|
||||
/// erroneous
|
||||
|
@ -253,7 +218,7 @@ impl ser::Serialize for Page {
|
|||
state.serialize_field("draft", &self.meta.draft)?;
|
||||
state.serialize_field("category", &self.meta.category)?;
|
||||
state.serialize_field("extra", &self.meta.extra)?;
|
||||
let (word_count, reading_time) = self.get_reading_analytics();
|
||||
let (word_count, reading_time) = get_reading_analytics(&self.raw_content);
|
||||
state.serialize_field("word_count", &word_count)?;
|
||||
state.serialize_field("reading_time", &reading_time)?;
|
||||
state.serialize_field("previous", &self.previous)?;
|
||||
|
@ -261,182 +226,3 @@ impl ser::Serialize for Page {
|
|||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
/// Sort pages using the method for the given section
|
||||
///
|
||||
/// 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<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) {
|
||||
match sort_by {
|
||||
SortBy::Date => {
|
||||
let mut can_be_sorted = vec![];
|
||||
let mut cannot_be_sorted = vec![];
|
||||
for page in pages {
|
||||
if page.meta.date.is_some() {
|
||||
can_be_sorted.push(page);
|
||||
} else {
|
||||
cannot_be_sorted.push(page);
|
||||
}
|
||||
}
|
||||
can_be_sorted.sort_by(|a, b| b.meta.date().unwrap().cmp(&a.meta.date().unwrap()));
|
||||
|
||||
(can_be_sorted, cannot_be_sorted)
|
||||
},
|
||||
SortBy::Order => {
|
||||
let mut can_be_sorted = vec![];
|
||||
let mut cannot_be_sorted = vec![];
|
||||
for page in pages {
|
||||
if page.meta.order.is_some() {
|
||||
can_be_sorted.push(page);
|
||||
} else {
|
||||
cannot_be_sorted.push(page);
|
||||
}
|
||||
}
|
||||
can_be_sorted.sort_by(|a, b| b.meta.order().cmp(&a.meta.order()));
|
||||
|
||||
(can_be_sorted, cannot_be_sorted)
|
||||
},
|
||||
SortBy::None => (pages, vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// Horribly inefficient way to set previous and next on each pages
|
||||
/// So many clones
|
||||
pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec<Page> {
|
||||
let pages = input.to_vec();
|
||||
let mut res = Vec::new();
|
||||
|
||||
// the input is already sorted
|
||||
// We might put prev/next randomly if a page is missing date/order, probably fine
|
||||
for (i, page) in input.iter().enumerate() {
|
||||
let mut new_page = page.clone();
|
||||
|
||||
if i > 0 {
|
||||
let next = &pages[i - 1];
|
||||
new_page.next = Some(Box::new(next.clone()));
|
||||
}
|
||||
|
||||
if i < input.len() - 1 {
|
||||
let previous = &pages[i + 1];
|
||||
new_page.previous = Some(Box::new(previous.clone()));
|
||||
}
|
||||
res.push(new_page);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs::File;
|
||||
|
||||
use tempdir::TempDir;
|
||||
|
||||
use front_matter::{PageFrontMatter, SortBy};
|
||||
use super::{Page, find_related_assets, sort_pages, populate_previous_and_next_pages};
|
||||
|
||||
fn create_page_with_date(date: &str) -> Page {
|
||||
let mut front_matter = PageFrontMatter::default();
|
||||
front_matter.date = Some(date.to_string());
|
||||
Page::new(front_matter)
|
||||
}
|
||||
|
||||
fn create_page_with_order(order: usize) -> Page {
|
||||
let mut front_matter = PageFrontMatter::default();
|
||||
front_matter.order = Some(order);
|
||||
Page::new(front_matter)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_find_related_assets() {
|
||||
let tmp_dir = TempDir::new("example").expect("create temp dir");
|
||||
File::create(tmp_dir.path().join("index.md")).unwrap();
|
||||
File::create(tmp_dir.path().join("example.js")).unwrap();
|
||||
File::create(tmp_dir.path().join("graph.jpg")).unwrap();
|
||||
File::create(tmp_dir.path().join("fail.png")).unwrap();
|
||||
|
||||
let assets = find_related_assets(tmp_dir.path());
|
||||
assert_eq!(assets.len(), 3);
|
||||
assert_eq!(assets.iter().filter(|p| p.extension().unwrap() != "md").count(), 3);
|
||||
assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "example.js").count(), 1);
|
||||
assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "graph.jpg").count(), 1);
|
||||
assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "fail.png").count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_sort_by_dates() {
|
||||
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, 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");
|
||||
assert_eq!(pages[2].clone().meta.date.unwrap(), "2017-01-01");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_sort_by_order() {
|
||||
let input = vec![
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(3),
|
||||
create_page_with_order(1),
|
||||
];
|
||||
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);
|
||||
assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_sort_by_none() {
|
||||
let input = vec![
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(3),
|
||||
create_page_with_order(1),
|
||||
];
|
||||
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);
|
||||
assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_page_with_missing_field() {
|
||||
let input = vec![
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(3),
|
||||
create_page_with_date("2019-01-01"),
|
||||
];
|
||||
let (pages, unsorted) = sort_pages(input, SortBy::Order);
|
||||
assert_eq!(pages.len(), 2);
|
||||
assert_eq!(unsorted.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_populate_previous_and_next_pages() {
|
||||
let input = vec![
|
||||
create_page_with_order(3),
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(1),
|
||||
];
|
||||
let pages = populate_previous_and_next_pages(input.as_slice());
|
||||
|
||||
assert!(pages[0].clone().next.is_none());
|
||||
assert!(pages[0].clone().previous.is_some());
|
||||
assert_eq!(pages[0].clone().previous.unwrap().meta.order.unwrap(), 2);
|
||||
|
||||
assert!(pages[1].clone().next.is_some());
|
||||
assert!(pages[1].clone().previous.is_some());
|
||||
assert_eq!(pages[1].clone().next.unwrap().meta.order.unwrap(), 3);
|
||||
assert_eq!(pages[1].clone().previous.unwrap().meta.order.unwrap(), 1);
|
||||
|
||||
assert!(pages[2].clone().next.is_some());
|
||||
assert!(pages[2].clone().previous.is_none());
|
||||
assert_eq!(pages[2].clone().next.unwrap().meta.order.unwrap(), 2);
|
||||
}
|
||||
}
|
||||
|
|
169
src/content/sorting.rs
Normal file
169
src/content/sorting.rs
Normal file
|
@ -0,0 +1,169 @@
|
|||
use content::Page;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SortBy {
|
||||
Date,
|
||||
Order,
|
||||
None,
|
||||
}
|
||||
|
||||
/// Sort pages using the method for the given section
|
||||
///
|
||||
/// 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<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) {
|
||||
match sort_by {
|
||||
SortBy::Date => {
|
||||
let mut can_be_sorted = vec![];
|
||||
let mut cannot_be_sorted = vec![];
|
||||
for page in pages {
|
||||
if page.meta.date.is_some() {
|
||||
can_be_sorted.push(page);
|
||||
} else {
|
||||
cannot_be_sorted.push(page);
|
||||
}
|
||||
}
|
||||
can_be_sorted.sort_by(|a, b| b.meta.date().unwrap().cmp(&a.meta.date().unwrap()));
|
||||
|
||||
(can_be_sorted, cannot_be_sorted)
|
||||
},
|
||||
SortBy::Order => {
|
||||
let mut can_be_sorted = vec![];
|
||||
let mut cannot_be_sorted = vec![];
|
||||
for page in pages {
|
||||
if page.meta.order.is_some() {
|
||||
can_be_sorted.push(page);
|
||||
} else {
|
||||
cannot_be_sorted.push(page);
|
||||
}
|
||||
}
|
||||
can_be_sorted.sort_by(|a, b| b.meta.order().cmp(&a.meta.order()));
|
||||
|
||||
(can_be_sorted, cannot_be_sorted)
|
||||
},
|
||||
SortBy::None => (pages, vec![])
|
||||
}
|
||||
}
|
||||
|
||||
/// Horribly inefficient way to set previous and next on each pages
|
||||
/// So many clones
|
||||
pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec<Page> {
|
||||
let pages = input.to_vec();
|
||||
let mut res = Vec::new();
|
||||
|
||||
// the input is already sorted
|
||||
// We might put prev/next randomly if a page is missing date/order, probably fine
|
||||
for (i, page) in input.iter().enumerate() {
|
||||
let mut new_page = page.clone();
|
||||
|
||||
if i > 0 {
|
||||
let next = &pages[i - 1];
|
||||
new_page.next = Some(Box::new(next.clone()));
|
||||
}
|
||||
|
||||
if i < input.len() - 1 {
|
||||
let previous = &pages[i + 1];
|
||||
new_page.previous = Some(Box::new(previous.clone()));
|
||||
}
|
||||
res.push(new_page);
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use front_matter::{PageFrontMatter};
|
||||
use content::Page;
|
||||
use super::{SortBy, sort_pages, populate_previous_and_next_pages};
|
||||
|
||||
fn create_page_with_date(date: &str) -> Page {
|
||||
let mut front_matter = PageFrontMatter::default();
|
||||
front_matter.date = Some(date.to_string());
|
||||
Page::new(front_matter)
|
||||
}
|
||||
|
||||
fn create_page_with_order(order: usize) -> Page {
|
||||
let mut front_matter = PageFrontMatter::default();
|
||||
front_matter.order = Some(order);
|
||||
Page::new(front_matter)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_sort_by_dates() {
|
||||
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, 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");
|
||||
assert_eq!(pages[2].clone().meta.date.unwrap(), "2017-01-01");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_sort_by_order() {
|
||||
let input = vec![
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(3),
|
||||
create_page_with_order(1),
|
||||
];
|
||||
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);
|
||||
assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_sort_by_none() {
|
||||
let input = vec![
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(3),
|
||||
create_page_with_order(1),
|
||||
];
|
||||
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);
|
||||
assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_page_with_missing_field() {
|
||||
let input = vec![
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(3),
|
||||
create_page_with_date("2019-01-01"),
|
||||
];
|
||||
let (pages, unsorted) = sort_pages(input, SortBy::Order);
|
||||
assert_eq!(pages.len(), 2);
|
||||
assert_eq!(unsorted.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_populate_previous_and_next_pages() {
|
||||
let input = vec![
|
||||
create_page_with_order(3),
|
||||
create_page_with_order(2),
|
||||
create_page_with_order(1),
|
||||
];
|
||||
let pages = populate_previous_and_next_pages(input.as_slice());
|
||||
|
||||
assert!(pages[0].clone().next.is_none());
|
||||
assert!(pages[0].clone().previous.is_some());
|
||||
assert_eq!(pages[0].clone().previous.unwrap().meta.order.unwrap(), 2);
|
||||
|
||||
assert!(pages[1].clone().next.is_some());
|
||||
assert!(pages[1].clone().previous.is_some());
|
||||
assert_eq!(pages[1].clone().next.unwrap().meta.order.unwrap(), 3);
|
||||
assert_eq!(pages[1].clone().previous.unwrap().meta.order.unwrap(), 1);
|
||||
|
||||
assert!(pages[2].clone().next.is_some());
|
||||
assert!(pages[2].clone().previous.is_none());
|
||||
assert_eq!(pages[2].clone().next.unwrap().meta.order.unwrap(), 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
use std::fs::read_dir;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Looks into the current folder for the path and see if there's anything that is not a .md
|
||||
/// file. Those will be copied next to the rendered .html file
|
||||
pub fn find_related_assets(path: &Path) -> Vec<PathBuf> {
|
||||
let mut assets = vec![];
|
||||
|
||||
for entry in read_dir(path).unwrap().filter_map(|e| e.ok()) {
|
||||
let entry_path = entry.path();
|
||||
if entry_path.is_file() {
|
||||
match entry_path.extension() {
|
||||
Some(e) => match e.to_str() {
|
||||
Some("md") => continue,
|
||||
_ => assets.push(entry_path.to_path_buf()),
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assets
|
||||
}
|
||||
|
||||
/// Get word count and estimated reading time
|
||||
pub fn get_reading_analytics(content: &str) -> (usize, usize) {
|
||||
// Only works for latin language but good enough for a start
|
||||
let word_count: usize = content.split_whitespace().count();
|
||||
|
||||
// https://help.medium.com/hc/en-us/articles/214991667-Read-time
|
||||
// 275 seems a bit too high though
|
||||
(word_count, (word_count / 200))
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs::File;
|
||||
|
||||
use tempdir::TempDir;
|
||||
|
||||
use super::{find_related_assets, get_reading_analytics};
|
||||
|
||||
#[test]
|
||||
fn can_find_related_assets() {
|
||||
let tmp_dir = TempDir::new("example").expect("create temp dir");
|
||||
File::create(tmp_dir.path().join("index.md")).unwrap();
|
||||
File::create(tmp_dir.path().join("example.js")).unwrap();
|
||||
File::create(tmp_dir.path().join("graph.jpg")).unwrap();
|
||||
File::create(tmp_dir.path().join("fail.png")).unwrap();
|
||||
|
||||
let assets = find_related_assets(tmp_dir.path());
|
||||
assert_eq!(assets.len(), 3);
|
||||
assert_eq!(assets.iter().filter(|p| p.extension().unwrap() != "md").count(), 3);
|
||||
assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "example.js").count(), 1);
|
||||
assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "graph.jpg").count(), 1);
|
||||
assert_eq!(assets.iter().filter(|p| p.file_name().unwrap() == "fail.png").count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reading_analytics_short_text() {
|
||||
let (word_count, reading_time) = get_reading_analytics("Hello World");
|
||||
assert_eq!(word_count, 2);
|
||||
assert_eq!(reading_time, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reading_analytics_long_text() {
|
||||
let mut content = String::new();
|
||||
for _ in 0..1000 {
|
||||
content.push_str(" Hello world");
|
||||
}
|
||||
let (word_count, reading_time) = get_reading_analytics(&content);
|
||||
assert_eq!(word_count, 2000);
|
||||
assert_eq!(reading_time, 10);
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ mod page;
|
|||
mod section;
|
||||
|
||||
pub use self::page::PageFrontMatter;
|
||||
pub use self::section::{SectionFrontMatter, SortBy};
|
||||
pub use self::section::{SectionFrontMatter};
|
||||
|
||||
lazy_static! {
|
||||
static ref PAGE_RE: Regex = Regex::new(r"^[[:space:]]*\+\+\+\r?\n((?s).*?(?-s))\+\+\+\r?\n?((?s).*(?-s))$").unwrap();
|
||||
|
@ -30,7 +30,7 @@ fn split_content(file_path: &Path, content: &str) -> Result<(String, String)> {
|
|||
}
|
||||
|
||||
/// Split a file between the front matter and its content.
|
||||
/// Returns a parsed SectionFrontMatter and the rest of the content
|
||||
/// Returns a parsed `SectionFrontMatter` and the rest of the content
|
||||
pub fn split_section_content(file_path: &Path, content: &str) -> Result<(SectionFrontMatter, String)> {
|
||||
let (front_matter, content) = split_content(file_path, content)?;
|
||||
let meta = SectionFrontMatter::parse(&front_matter)
|
||||
|
@ -39,7 +39,7 @@ pub fn split_section_content(file_path: &Path, content: &str) -> Result<(Section
|
|||
}
|
||||
|
||||
/// Split a file between the front matter and its content
|
||||
/// Returns a parsed PageFrontMatter and the rest of the content
|
||||
/// Returns a parsed `PageFrontMatter` and the rest of the content
|
||||
pub fn split_page_content(file_path: &Path, content: &str) -> Result<(PageFrontMatter, String)> {
|
||||
let (front_matter, content) = split_content(file_path, content)?;
|
||||
let meta = PageFrontMatter::parse(&front_matter)
|
||||
|
|
|
@ -4,16 +4,10 @@ use tera::Value;
|
|||
use toml;
|
||||
|
||||
use errors::{Result};
|
||||
use content::SortBy;
|
||||
|
||||
static DEFAULT_PAGINATE_PATH: &'static str = "page";
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SortBy {
|
||||
Date,
|
||||
Order,
|
||||
None,
|
||||
}
|
||||
|
||||
/// The front matter of every section
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
|
|
|
@ -31,7 +31,7 @@ mod templates;
|
|||
|
||||
pub use site::{Site};
|
||||
pub use config::{Config, get_config};
|
||||
pub use front_matter::{PageFrontMatter, SectionFrontMatter, split_page_content, split_section_content, SortBy};
|
||||
pub use content::{Page, Section, sort_pages};
|
||||
pub use front_matter::{PageFrontMatter, SectionFrontMatter, split_page_content, split_section_content};
|
||||
pub use content::{Page, Section, SortBy, sort_pages, populate_previous_and_next_pages};
|
||||
pub use utils::{create_file};
|
||||
pub use markdown::markdown_to_html;
|
||||
|
|
|
@ -11,8 +11,7 @@ use walkdir::WalkDir;
|
|||
use errors::{Result, ResultExt};
|
||||
use config::{Config, get_config};
|
||||
use utils::{create_file, create_directory};
|
||||
use content::{Page, Section, Paginator, populate_previous_and_next_pages, sort_pages};
|
||||
use front_matter::{SortBy};
|
||||
use content::{Page, Section, Paginator, SortBy, populate_previous_and_next_pages, sort_pages};
|
||||
use templates::{GUTENBERG_TERA, global_fns, render_redirect_template};
|
||||
|
||||
|
||||
|
@ -239,7 +238,7 @@ impl Site {
|
|||
/// Sorts the pages of the section at the given path
|
||||
/// By default will sort all sections but can be made to only sort a single one by providing a path
|
||||
pub fn sort_sections_pages(&mut self, only: Option<&Path>) {
|
||||
for (path, section) in self.sections.iter_mut() {
|
||||
for (path, section) in &mut self.sections {
|
||||
if let Some(p) = only {
|
||||
if p != path {
|
||||
continue;
|
||||
|
|
|
@ -21,7 +21,6 @@ pub fn create_directory<P: AsRef<Path>>(path: P) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
/// Return the content of a file, with error handling added
|
||||
pub fn read_file<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
let path = path.as_ref();
|
||||
|
|
|
@ -163,43 +163,6 @@ Hello world"#;
|
|||
assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "file-with-space"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reading_analytics_short() {
|
||||
let content = r#"
|
||||
+++
|
||||
title = "Hello"
|
||||
description = "hey there"
|
||||
+++
|
||||
Hello world"#;
|
||||
let res = Page::parse(Path::new("hello.md"), content, &Config::default());
|
||||
assert!(res.is_ok());
|
||||
let mut page = res.unwrap();
|
||||
page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap();
|
||||
let (word_count, reading_time) = page.get_reading_analytics();
|
||||
assert_eq!(word_count, 2);
|
||||
assert_eq!(reading_time, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reading_analytics_long() {
|
||||
let mut content = r#"
|
||||
+++
|
||||
title = "Hello"
|
||||
description = "hey there"
|
||||
+++
|
||||
Hello world"#.to_string();
|
||||
for _ in 0..1000 {
|
||||
content.push_str(" Hello world");
|
||||
}
|
||||
let res = Page::parse(Path::new("hello.md"), &content, &Config::default());
|
||||
assert!(res.is_ok());
|
||||
let mut page = res.unwrap();
|
||||
page.render_markdown(&HashMap::default(), &Tera::default(), &Config::default()).unwrap();
|
||||
let (word_count, reading_time) = page.get_reading_analytics();
|
||||
assert_eq!(word_count, 2002);
|
||||
assert_eq!(reading_time, 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_automatic_summary_is_empty_string() {
|
||||
let content = r#"
|
||||
|
|
Loading…
Reference in a new issue