@@ -96,17 +96,14 @@ 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 p.meta.has_tags() || p.meta.category.is_some() { | |||
site.populate_tags_and_categories(); | |||
} | |||
if let Some(p) = site.pages.remove(path) { | |||
if p.meta.has_tags() || p.meta.category.is_some() { | |||
site.populate_tags_and_categories(); | |||
} | |||
if site.find_parent_section(&p).is_some() { | |||
site.populate_sections(); | |||
} | |||
}, | |||
None => () | |||
if site.find_parent_section(&p).is_some() { | |||
site.populate_sections(); | |||
} | |||
}; | |||
} | |||
// 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); | |||
} | |||
} |
@@ -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#" | |||