A static site generator written in Rust
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

post.rs 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. ).unwrap();
  58. }
  59. let mut expected_paths: Vec<String> = uuids
  60. .into_iter()
  61. .map(|uuid| {
  62. String::from(
  63. cwd.join("posts")
  64. .join(format!("{}.md", uuid))
  65. .to_str()
  66. .unwrap(),
  67. )
  68. }).collect();
  69. expected_paths.sort();
  70. let mut actual_paths: Vec<String> = read_posts_dir(&cwd.join("posts"))
  71. .into_iter()
  72. .map(|dir_entry| String::from(dir_entry.path().to_str().unwrap()))
  73. .collect();
  74. actual_paths.sort();
  75. assert_eq!(expected_paths, actual_paths);
  76. fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
  77. }
  78. #[test]
  79. fn test_parse_post() {
  80. let temp_dir = env::temp_dir();
  81. let working_dir = temp_dir.join(&Uuid::new_v4().to_string());
  82. fs::create_dir(&working_dir).unwrap();
  83. env::set_current_dir(&working_dir).unwrap();
  84. let cwd = env::current_dir().unwrap();
  85. fs::create_dir(cwd.join("posts")).unwrap();
  86. let slug = Uuid::new_v4().to_string();
  87. let filename = format!("{}.md", slug);
  88. fs::write(
  89. cwd.join("posts").join(&filename),
  90. "# This is a post\n\nHere is some content that goes in the post",
  91. ).unwrap();
  92. let post = parse_post(cwd.join("posts").join(&filename));
  93. assert_eq!("This is a post", post.title);
  94. assert_eq!("Here is some content that goes in the post", post.body);
  95. assert_eq!(slug, post.slug);
  96. fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
  97. }
  98. #[test]
  99. fn test_post_with_multiple_paragraphs() {
  100. let temp_dir = env::temp_dir();
  101. let working_dir = temp_dir.join(&Uuid::new_v4().to_string());
  102. fs::create_dir(&working_dir).unwrap();
  103. env::set_current_dir(&working_dir).unwrap();
  104. let cwd = env::current_dir().unwrap();
  105. fs::create_dir(cwd.join("posts")).unwrap();
  106. let slug = Uuid::new_v4().to_string();
  107. let filename = format!("{}.md", slug);
  108. fs::write(
  109. cwd.join("posts").join(&filename),
  110. "# This is a post\n\nHere is a line\n\nHere is another line\n\nAnd a third",
  111. ).unwrap();
  112. let post = parse_post(cwd.join("posts").join(&filename));
  113. assert_eq!("This is a post", post.title);
  114. assert_eq!(
  115. "Here is a line\n\nHere is another line\n\nAnd a third",
  116. post.body
  117. );
  118. assert_eq!(slug, post.slug);
  119. fs::remove_dir_all(temp_dir.join(&working_dir)).unwrap();
  120. }
  121. }