A static site generator written in Rust
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

post.rs 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. use std::fs;
  2. use std::path;
  3. use regex::Regex;
  4. #[derive(Debug)]
  5. pub struct Post {
  6. pub title: String,
  7. pub body: String,
  8. pub slug: String,
  9. }
  10. pub fn read_posts_dir(cwd: &path::PathBuf) -> Vec<fs::DirEntry> {
  11. match fs::read_dir(cwd) {
  12. Ok(posts) => posts.into_iter().map(|post| post.unwrap()).collect(),
  13. Err(err) => panic!(err),
  14. }
  15. }
  16. pub fn parse_post(path: path::PathBuf) -> Post {
  17. let contents = fs::read_to_string(&path).expect("Couldn't read post file");
  18. lazy_static! {
  19. static ref re: Regex = Regex::new(r"^# (?P<title>.*)\n\n(?s)(?P<body>.*)").unwrap();
  20. static ref slug_re: Regex = Regex::new(r"(?P<slug>\S+).md").unwrap();
  21. }
  22. let title = &re.captures(&contents).expect("Couldn't parse title")["title"];
  23. let body = &re.captures(&contents).expect("Couldn't parse body")["body"];
  24. let filename = &path.file_name().unwrap().to_str().unwrap();
  25. let slug = &slug_re.captures(filename).expect("Couldn't parse slug")["slug"];
  26. Post {
  27. title: String::from(title),
  28. body: String::from(body),
  29. slug: String::from(slug),
  30. }
  31. }
  32. #[cfg(test)]
  33. mod tests {
  34. #[allow(unused_imports)]
  35. use super::*;
  36. #[allow(unused_imports)]
  37. #[allow(unused_imports)]
  38. use std::{env, fs, path};
  39. #[allow(unused_imports)]
  40. use uuid::Uuid;
  41. #[test]
  42. fn test_read_posts_dir() {
  43. let temp_dir = env::temp_dir();
  44. let working_dir = temp_dir.join(&Uuid::new_v4().to_string());
  45. fs::create_dir(&working_dir).unwrap();
  46. env::set_current_dir(&working_dir).unwrap();
  47. let cwd = env::current_dir().unwrap();
  48. fs::create_dir(cwd.join("posts")).unwrap();
  49. let post_body = "# This is a post\n\nHere is some content that goes in the post";
  50. let mut uuids: Vec<String> = vec![];
  51. for _ in 1..11 {
  52. let uuid = String::from(Uuid::new_v4().to_string());
  53. uuids.push(uuid.clone());
  54. fs::write(
  55. cwd.join("posts").join(format!("{}.md", &uuid)),
  56. &String::from(post_body),
  57. )
  58. .unwrap();
  59. }
  60. let mut expected_paths: Vec<String> = uuids
  61. .into_iter()
  62. .map(|uuid| {
  63. String::from(
  64. cwd.join("posts")
  65. .join(format!("{}.md", uuid))
  66. .to_str()
  67. .unwrap(),
  68. )
  69. })
  70. .collect();
  71. expected_paths.sort();
  72. let mut actual_paths: Vec<String> = read_posts_dir(&cwd.join("posts"))
  73. .into_iter()
  74. .map(|dir_entry| String::from(dir_entry.path().to_str().unwrap()))
  75. .collect();
  76. actual_paths.sort();
  77. assert_eq!(expected_paths, actual_paths);
  78. fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
  79. }
  80. #[test]
  81. fn test_parse_post() {
  82. let temp_dir = env::temp_dir();
  83. let working_dir = temp_dir.join(&Uuid::new_v4().to_string());
  84. fs::create_dir(&working_dir).unwrap();
  85. env::set_current_dir(&working_dir).unwrap();
  86. let cwd = env::current_dir().unwrap();
  87. fs::create_dir(cwd.join("posts")).unwrap();
  88. let slug = Uuid::new_v4().to_string();
  89. let filename = format!("{}.md", slug);
  90. fs::write(
  91. cwd.join("posts").join(&filename),
  92. "# This is a post\n\nHere is some content that goes in the post",
  93. )
  94. .unwrap();
  95. let post = parse_post(cwd.join("posts").join(&filename));
  96. assert_eq!("This is a post", post.title);
  97. assert_eq!("Here is some content that goes in the post", post.body);
  98. assert_eq!(slug, post.slug);
  99. fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
  100. }
  101. #[test]
  102. fn test_post_with_multiple_paragraphs() {
  103. let temp_dir = env::temp_dir();
  104. let working_dir = temp_dir.join(&Uuid::new_v4().to_string());
  105. fs::create_dir(&working_dir).unwrap();
  106. env::set_current_dir(&working_dir).unwrap();
  107. let cwd = env::current_dir().unwrap();
  108. fs::create_dir(cwd.join("posts")).unwrap();
  109. let slug = Uuid::new_v4().to_string();
  110. let filename = format!("{}.md", slug);
  111. fs::write(
  112. cwd.join("posts").join(&filename),
  113. "# This is a post\n\nHere is a line\n\nHere is another line\n\nAnd a third",
  114. )
  115. .unwrap();
  116. let post = parse_post(cwd.join("posts").join(&filename));
  117. assert_eq!("This is a post", post.title);
  118. assert_eq!(
  119. "Here is a line\n\nHere is another line\n\nAnd a third",
  120. post.body
  121. );
  122. assert_eq!(slug, post.slug);
  123. fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
  124. }
  125. }