You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.0KB

  1. use std::collections::HashMap;
  2. use unicode_segmentation::UnicodeSegmentation;
  3. use errors::Result;
  4. /// Get word count and estimated reading time
  5. pub fn get_reading_analytics(content: &str) -> (usize, usize) {
  6. let word_count: usize = content.unicode_words().count();
  7. // https://help.medium.com/hc/en-us/articles/214991667-Read-time
  8. // 275 seems a bit too high though
  9. (word_count, (word_count / 200))
  10. }
  11. /// Resolves an internal link (of the `./posts/something.md#hey` sort) to its absolute link
  12. pub fn resolve_internal_link(link: &str, permalinks: &HashMap<String, String>) -> Result<String> {
  13. // First we remove the ./ since that's zola specific
  14. let clean_link = link.replacen("./", "", 1);
  15. // Then we remove any potential anchor
  16. // parts[0] will be the file path and parts[1] the anchor if present
  17. let parts = clean_link.split('#').collect::<Vec<_>>();
  18. match permalinks.get(parts[0]) {
  19. Some(p) => {
  20. if parts.len() > 1 {
  21. Ok(format!("{}#{}", p, parts[1]))
  22. } else {
  23. Ok(p.to_string())
  24. }
  25. }
  26. None => bail!(format!("Relative link {} not found.", link)),
  27. }
  28. }
  29. #[cfg(test)]
  30. mod tests {
  31. use std::collections::HashMap;
  32. use super::{get_reading_analytics, resolve_internal_link};
  33. #[test]
  34. fn can_resolve_valid_internal_link() {
  35. let mut permalinks = HashMap::new();
  36. permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string());
  37. let res = resolve_internal_link("./pages/about.md", &permalinks).unwrap();
  38. assert_eq!(res, "https://vincent.is/about");
  39. }
  40. #[test]
  41. fn can_resolve_valid_root_internal_link() {
  42. let mut permalinks = HashMap::new();
  43. permalinks.insert("about.md".to_string(), "https://vincent.is/about".to_string());
  44. let res = resolve_internal_link("./about.md", &permalinks).unwrap();
  45. assert_eq!(res, "https://vincent.is/about");
  46. }
  47. #[test]
  48. fn can_resolve_internal_links_with_anchors() {
  49. let mut permalinks = HashMap::new();
  50. permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string());
  51. let res = resolve_internal_link("./pages/about.md#hello", &permalinks).unwrap();
  52. assert_eq!(res, "https://vincent.is/about#hello");
  53. }
  54. #[test]
  55. fn errors_resolve_inexistant_internal_link() {
  56. let res = resolve_internal_link("./pages/about.md#hello", &HashMap::new());
  57. assert!(res.is_err());
  58. }
  59. #[test]
  60. fn reading_analytics_short_text() {
  61. let (word_count, reading_time) = get_reading_analytics("Hello World");
  62. assert_eq!(word_count, 2);
  63. assert_eq!(reading_time, 0);
  64. }
  65. #[test]
  66. fn reading_analytics_long_text() {
  67. let mut content = String::new();
  68. for _ in 0..1000 {
  69. content.push_str(" Hello world");
  70. }
  71. let (word_count, reading_time) = get_reading_analytics(&content);
  72. assert_eq!(word_count, 2000);
  73. assert_eq!(reading_time, 10);
  74. }
  75. }