A static site generator written in Rust
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.

rss.rs 2.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. use chrono::{DateTime, Utc};
  2. use htmlescape::encode_minimal;
  3. use config::Config;
  4. use entry::{Entry, EntryKind};
  5. pub fn generate_post_rss(config: &Config, post: &Entry) -> String {
  6. let raw_date = post.date.unwrap().and_hms_opt(0, 0, 0).unwrap();
  7. let date: DateTime<Utc> = DateTime::from_utc(raw_date, Utc);
  8. let date_string = date.format("%a, %d %b %Y %H:%M:%S %z").to_string();
  9. let url = format!("{}/posts/{}/", config.url, post.slug);
  10. format!(
  11. "<item><title>{}</title><description>{}</description><guid>{}</guid><link>{}</link><pubDate>{}</pubDate></item>",
  12. post.title, encode_minimal(&post.render("<article>{{ body }}</article>", config)), url, url, date_string
  13. )
  14. }
  15. pub fn generate_rss(config: &Config, posts: Vec<Entry>) -> String {
  16. let items = posts
  17. .iter()
  18. .filter(|post| post.kind == EntryKind::Post)
  19. .map(|post| generate_post_rss(config, post))
  20. .collect::<Vec<String>>()
  21. .join("");
  22. format!(
  23. "<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\"><channel><atom:link href=\"{}/rss.xml\" rel=\"self\" /><title>{}</title><description>{}</description><link>{}</link>{}</channel></rss>",
  24. config.url, config.site_name, config.description, config.url, items
  25. )
  26. }
  27. #[cfg(test)]
  28. mod tests {
  29. use chrono::NaiveDate;
  30. use super::generate_rss;
  31. use config::Config;
  32. use entry::{Entry, EntryKind};
  33. #[test]
  34. fn generates_rss_feed() {
  35. let config = Config {
  36. site_name: String::from("Lorem Ipsum"),
  37. url: String::from("https://www.loremipsum.com"),
  38. description: String::from("recent posts from loremipsum.com"),
  39. };
  40. let posts: Vec<Entry> = vec![Entry {
  41. title: String::from("Hello World"),
  42. body: String::from("lorem ipsum dolor sit amet"),
  43. slug: String::from("hello-world"),
  44. date: Some(NaiveDate::from_ymd(2019, 1, 1)),
  45. kind: EntryKind::Post,
  46. }];
  47. assert_eq!(
  48. generate_rss(&config, posts),
  49. "<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\"><channel><atom:link href=\"https://www.loremipsum.com/rss.xml\" rel=\"self\" /><title>Lorem Ipsum</title><description>recent posts from loremipsum.com</description><link>https://www.loremipsum.com</link><item><title>Hello World</title><description>&lt;article&gt;&lt;p&gt;lorem ipsum dolor sit amet&lt;/p&gt;\n&lt;/article&gt;</description><guid>https://www.loremipsum.com/posts/hello-world/</guid><link>https://www.loremipsum.com/posts/hello-world/</link><pubDate>Tue, 01 Jan 2019 00:00:00 +0000</pubDate></item></channel></rss>"
  50. );
  51. }
  52. }