Browse Source

Wordcount + reading time

index-subcmd
Vincent Prouillet 7 years ago
parent
commit
e5367453d7
1 changed files with 51 additions and 1 deletions
  1. +51
    -1
      src/page.rs

+ 51
- 1
src/page.rs 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);
}
} }

Loading…
Cancel
Save