Wordcount + reading time

This commit is contained in:
Vincent Prouillet 2017-03-06 22:45:33 +09:00
parent 4acce865b4
commit e5367453d7

View file

@ -73,6 +73,7 @@ impl Page {
} }
} }
/// Get the URL (without the base URL) to that page
pub fn get_url(&self) -> String { pub fn get_url(&self) -> String {
if let Some(ref u) = self.meta.url { if let Some(ref u) = self.meta.url {
return u.to_string(); return u.to_string();
@ -85,6 +86,16 @@ impl Page {
format!("/{}", self.get_slug()) format!("/{}", self.get_slug())
} }
// 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 // Parse a page given the content of the .md file
// Files without front matter or with invalid front matter are considered // Files without front matter or with invalid front matter are considered
// erroneous // erroneous
@ -149,6 +160,7 @@ impl Page {
} }
} }
/// Renders the page using the default layout, unless specified in front-matter
pub fn render_html(&self, tera: &Tera, config: &Config) -> Result<String> { pub fn render_html(&self, tera: &Tera, config: &Config) -> Result<String> {
let tpl = self.get_layout_name(); let tpl = self.get_layout_name();
let mut context = Context::new(); let mut context = Context::new();
@ -162,7 +174,7 @@ impl Page {
impl ser::Serialize for Page { impl ser::Serialize for Page {
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error> where S: ser::Serializer { fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error> where S: ser::Serializer {
let mut state = serializer.serialize_struct("page", 10)?; let mut state = serializer.serialize_struct("page", 12)?;
state.serialize_field("content", &self.content)?; state.serialize_field("content", &self.content)?;
state.serialize_field("title", &self.meta.title)?; state.serialize_field("title", &self.meta.title)?;
state.serialize_field("description", &self.meta.description)?; state.serialize_field("description", &self.meta.description)?;
@ -173,6 +185,9 @@ impl ser::Serialize for Page {
state.serialize_field("draft", &self.meta.draft)?; state.serialize_field("draft", &self.meta.draft)?;
state.serialize_field("category", &self.meta.category)?; state.serialize_field("category", &self.meta.category)?;
state.serialize_field("extra", &self.meta.extra)?; state.serialize_field("extra", &self.meta.extra)?;
let (word_count, reading_time) = self.get_reading_analytics();
state.serialize_field("word_count", &word_count)?;
state.serialize_field("reading_time", &reading_time)?;
state.end() state.end()
} }
} }
@ -313,4 +328,39 @@ Hello world"#;
let page = res.unwrap(); let page = res.unwrap();
assert_eq!(page.get_slug(), "file-with-space"); assert_eq!(page.get_slug(), "file-with-space");
} }
#[test]
fn test_reading_analytics_short() {
let content = r#"
+++
title = "Hello"
description = "hey there"
+++
Hello world"#;
let res = Page::parse("file with space.md", content);
assert!(res.is_ok());
let page = res.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("hello.md", &content);
assert!(res.is_ok());
let page = res.unwrap();
let (word_count, reading_time) = page.get_reading_analytics();
assert_eq!(word_count, 2002);
assert_eq!(reading_time, 10);
}
} }