From d43d738a4faf7fa146532b1a31830a07803a7e87 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Tue, 7 Mar 2017 16:43:27 +0900 Subject: [PATCH] RSS feed generation --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 4 ++-- src/page.rs | 19 +++++++++++++++++-- src/site.rs | 41 ++++++++++++++++++++++++++++++++++++++--- src/templates/rss.xml | 20 ++++++++++++++++++++ 5 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 src/templates/rss.xml diff --git a/Cargo.lock b/Cargo.lock index eb9a42a5..15104770 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ dependencies = [ "slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tera 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tera 0.8.0 (git+https://github.com/Keats/tera)", "toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -388,7 +388,7 @@ dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -405,7 +405,7 @@ dependencies = [ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -416,7 +416,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -427,7 +427,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -448,7 +448,7 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -672,7 +672,7 @@ name = "serde_codegen_internals" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -682,7 +682,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -737,7 +737,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "tera" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/Keats/tera#2eb55de231e08da50ca32a443499fbce8d9003e0" dependencies = [ "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1055,7 +1055,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum miow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a78d2605eb97302c10cf944b8d96b0a2a890c52957caf92fcd1f24f69049579" "checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" "checksum mount 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32245731923cd096899502fc4c4317cfd09f121e80e73f7f576cf3777a824256" -"checksum net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "5edf9cb6be97212423aed9413dd4729d62b370b5e1c571750e882cebbbc1e3e2" +"checksum net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)" = "18b9642ad6222faf5ce46f6966f59b71b9775ad5758c9e09fcf0a6c8061972b4" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" "checksum notify 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c628262cc8a99209596ec610dcf199d6876a10cfa22e355acc5936d6f1fa63" "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" @@ -1092,10 +1092,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f5ff4b43cb07b86c5f9236c92714a22cdf9e5a27a7d85e398e2c9403328cb8" "checksum staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31493480e073d52522a94cdf56269dd8eb05f99549effd1826b0271690608878" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)" = "37c279fb816210c9bb28b2c292664581e7b87b4561e86b94df462664d8620bb8" +"checksum syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)" = "480c834701caba3548aa991e54677281be3a5414a9d09ddbdf4ed74a569a9d19" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f79be04af68d5fa09e71b3274159a955a25f25a5cbfba9a6ff64139b71d848a" -"checksum tera 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb775e4a7318e080e9c3000b150f720caf5825b66504f56f358df35b74fd0c14" +"checksum tera 0.8.0 (git+https://github.com/Keats/tera)" = "" "checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a" "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" diff --git a/Cargo.toml b/Cargo.toml index 8ebd7137..f381c61e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,8 +20,8 @@ glob = "0.2" serde = "0.9" serde_json = "0.9" serde_derive = "0.9" -# tera = { git = "https://github.com/Keats/tera", branch = "next" } -tera = "0.8" +tera = { git = "https://github.com/Keats/tera", branch = "master" } +# tera = "0.8" slug = "0.1" syntect = "1" chrono = "0.3" diff --git a/src/page.rs b/src/page.rs index 52da0a72..a4c4d9c1 100644 --- a/src/page.rs +++ b/src/page.rs @@ -134,7 +134,7 @@ impl Page { page.filename = path.file_stem().expect("Couldn't get filename").to_string_lossy().to_string(); page.slug = { if let Some(ref slug) = page.meta.slug { - slug.to_string() + slug.trim().to_string() } else { slugify(page.filename.clone()) } @@ -144,7 +144,7 @@ impl Page { // 4. Find sections // Pages with custom urls exists outside of sections if let Some(ref u) = page.meta.url { - page.url = u.to_string(); + page.url = u.trim().to_string(); } else { // find out if we have sections for section in path.parent().unwrap().components() { @@ -381,6 +381,21 @@ Hello world"#; assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "file-with-space")); } + #[test] + fn test_trim_slug_if_needed() { + let content = r#" ++++ +title = "Hello" +description = "hey there" ++++ +Hello world"#; + let res = Page::parse(" file with space.md", content, &Config::default()); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.slug, "file-with-space"); + assert_eq!(page.permalink, format!("{}{}", Config::default().base_url, "file-with-space")); + } + #[test] fn test_reading_analytics_short() { let content = r#" diff --git a/src/site.rs b/src/site.rs index b562b883..499ae54d 100644 --- a/src/site.rs +++ b/src/site.rs @@ -153,6 +153,9 @@ impl Site { self.render_categories_and_tags(RenderList::Categories, &category_pages)?; self.render_categories_and_tags(RenderList::Tags, &tag_pages)?; + self.render_sitemap()?; + self.render_rss_feed()?; + // And finally the index page let mut context = Context::new(); pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); @@ -161,8 +164,6 @@ impl Site { let index = self.templates.render("index.html", &context)?; create_file(public.join("index.html"), &self.inject_livereload(index))?; - self.render_sitemap()?; - // TODO: render rss feed Ok(()) } @@ -218,7 +219,7 @@ impl Site { Ok(()) } - pub fn render_sitemap(&self) -> Result<()> { + fn render_sitemap(&self) -> Result<()> { let tpl = String::from_utf8(include_bytes!("templates/sitemap.xml").to_vec()).unwrap(); let mut context = Context::new(); context.add("pages", &self.pages.values().collect::>()); @@ -229,4 +230,38 @@ impl Site { Ok(()) } + + fn get_rss_feed_url(&self) -> String { + if self.config.base_url.ends_with("/") { + format!("{}{}", self.config.base_url, "feed.xml") + } else { + format!("{}/{}", self.config.base_url, "feed.xml") + } + } + + fn render_rss_feed(&self) -> Result<()> { + let tpl = String::from_utf8(include_bytes!("templates/rss.xml").to_vec()).unwrap(); + let mut context = Context::new(); + let mut pages = self.pages.values() + .filter(|p| p.meta.date.is_some()) + .take(15) // limit to the last 15 elements + .collect::>(); + + // Don't generate a RSS feed if none of the pages has a date + if pages.is_empty() { + return Ok(()); + } + pages.sort_by(|a, b| a.partial_cmp(b).unwrap()); + context.add("pages", &pages); + context.add("last_build_date", &pages[0].meta.date); + context.add("config", &self.config); + context.add("feed_url", &self.get_rss_feed_url()); + + let sitemap = Tera::one_off(&tpl, &context, false)?; + + let public = Path::new("public"); + create_file(public.join("rss.xml"), &sitemap)?; + + Ok(()) + } } diff --git a/src/templates/rss.xml b/src/templates/rss.xml new file mode 100644 index 00000000..53aae2f5 --- /dev/null +++ b/src/templates/rss.xml @@ -0,0 +1,20 @@ + + + {{ config.title }} + {{ config.base_url }} + {{ config.description }} + Gutenberg + {{ config.language_code }} + + {{ last_build_date | date(format="%a, %d %b %Y %H:%M:%S %z") }} + {% for page in pages %} + + {{ page.title }} + {{ page.date | date(format="%a, %d %b %Y %H:%M:%S %z") }} + {{ page.permalink }} + {{ page.permalink }} + "{{ page.content | escape }}" + + {% endfor %} + +