diff --git a/CHANGELOG.md b/CHANGELOG.md index 90fa1dfe..96329fea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ ### Other - Add `updated` front-matter field for pages, which sitemap templates will use for the `SitemapEntry.date` field instead of the `date` front-matter field, and which the default Atom feed template will use +- Add `lang` to the feed template context +- Add `taxonomy` and `term` to the feed template context for taxonomy feeds ## 0.10.2 (unreleased) diff --git a/components/rebuild/src/lib.rs b/components/rebuild/src/lib.rs index 3123cd86..c0918954 100644 --- a/components/rebuild/src/lib.rs +++ b/components/rebuild/src/lib.rs @@ -396,7 +396,15 @@ pub fn after_template_change(site: &mut Site, path: &Path) -> Result<()> { match filename { "sitemap.xml" => site.render_sitemap(), filename if filename == site.config.feed_filename => { - site.render_feed(site.library.read().unwrap().pages_values(), None) + // FIXME: this is insufficient; for multilingual sites, it’s rendering the wrong + // content into the root feed, and it’s not regenerating any of the other feeds (other + // languages or taxonomies with feed enabled). + site.render_feed( + site.library.read().unwrap().pages_values(), + None, + &site.config.default_language, + None, + ) } "split_sitemap_index.xml" => site.render_sitemap(), "robots.txt" => site.render_robots(), diff --git a/components/site/benches/site.rs b/components/site/benches/site.rs index 4cd08058..f5eb7ccf 100644 --- a/components/site/benches/site.rs +++ b/components/site/benches/site.rs @@ -40,7 +40,14 @@ fn bench_render_feed(b: &mut test::Bencher) { let tmp_dir = tempdir().expect("create temp dir"); let public = &tmp_dir.path().join("public"); site.set_output_path(&public); - b.iter(|| site.render_feed(site.library.read().unwrap().pages_values(), None).unwrap()); + b.iter(|| { + site.render_feed( + site.library.read().unwrap().pages_values(), + None, + &site.config.default_language, + None, + ).unwrap(); + }); } #[bench] diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index 562ea387..bf39a970 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -8,13 +8,15 @@ use std::sync::{Arc, Mutex, RwLock}; use glob::glob; use rayon::prelude::*; use sass_rs::{compile_file, Options as SassOptions, OutputStyle}; +use serde_derive::Serialize; use tera::{Context, Tera}; -use config::{get_config, Config}; +use config::{get_config, Config, Taxonomy as TaxonomyConfig}; use errors::{bail, Error, ErrorKind, Result}; use front_matter::InsertAnchor; use library::{ find_taxonomies, sort_actual_pages_by_date, Library, Page, Paginator, Section, Taxonomy, + TaxonomyItem, }; use link_checker::check_url; use templates::{global_fns, render_redirect_template, ZOLA_TERA}; @@ -45,6 +47,23 @@ pub struct Site { include_drafts: bool, } +#[derive(Debug, Clone, PartialEq, Serialize)] +struct SerializedTaxonomyItem<'a> { + name: &'a str, + slug: &'a str, + permalink: &'a str, +} + +impl<'a> SerializedTaxonomyItem<'a> { + pub fn from_item(item: &'a TaxonomyItem) -> Self { + SerializedTaxonomyItem { + name: &item.name, + slug: &item.slug, + permalink: &item.permalink, + } + } +} + impl Site { /// Parse a site at the given path. Defaults to the current dir /// Passing in a path is used in tests and when --root argument is passed @@ -746,7 +765,8 @@ impl Site { let library = self.library.read().unwrap(); if self.config.generate_feed { - let pages = if self.config.is_multilingual() { + let is_multilingual = self.config.is_multilingual(); + let pages = if is_multilingual { library .pages_values() .iter() @@ -756,7 +776,12 @@ impl Site { } else { library.pages_values() }; - self.render_feed(pages, None)?; + self.render_feed( + pages, + None, + &self.config.default_language, + None, + )?; } for lang in &self.config.languages { @@ -765,7 +790,12 @@ impl Site { } let pages = library.pages_values().iter().filter(|p| p.lang == lang.code).cloned().collect(); - self.render_feed(pages, Some(&PathBuf::from(lang.code.clone())))?; + self.render_feed( + pages, + Some(&PathBuf::from(lang.code.clone())), + &lang.code, + None, + )?; } self.render_404()?; @@ -987,6 +1017,12 @@ impl Site { self.render_feed( item.pages.iter().map(|p| library.get_page_by_key(*p)).collect(), Some(&PathBuf::from(format!("{}/{}", taxonomy.kind.name, item.slug))), + if self.config.is_multilingual() && !taxonomy.kind.lang.is_empty() { + &taxonomy.kind.lang + } else { + &self.config.default_language + }, + Some((&taxonomy.kind, &item)), ) } else { Ok(()) @@ -1052,6 +1088,8 @@ impl Site { &self, all_pages: Vec<&Page>, base_path: Option<&PathBuf>, + lang: &str, + taxonomy_and_item: Option<(&TaxonomyConfig, &TaxonomyItem)>, ) -> Result<()> { ensure_directory_exists(&self.output_path)?; @@ -1084,6 +1122,7 @@ impl Site { context.insert("pages", &p); context.insert("config", &self.config); + context.insert("lang", lang); let feed_filename = &self.config.feed_filename; let feed_url = if let Some(ref base) = base_path { @@ -1099,6 +1138,11 @@ impl Site { context.insert("feed_url", &feed_url); + if let Some((taxonomy, item)) = taxonomy_and_item { + context.insert("taxonomy", taxonomy); + context.insert("term", &SerializedTaxonomyItem::from_item(item)); + } + let feed = &render_template(feed_filename, &self.tera, context, &self.config.theme)?; if let Some(ref base) = base_path { diff --git a/components/site/tests/site_i18n.rs b/components/site/tests/site_i18n.rs index acd4b97d..be666776 100644 --- a/components/site/tests/site_i18n.rs +++ b/components/site/tests/site_i18n.rs @@ -119,9 +119,11 @@ fn can_build_multilingual_site() { assert!(file_exists!(public, "atom.xml")); assert!(file_contains!(public, "atom.xml", "https://example.com/blog/something-else/")); assert!(!file_contains!(public, "atom.xml", "https://example.com/fr/blog/something-else/")); + assert!(file_contains!(public, "atom.xml", r#""#)); assert!(file_exists!(public, "fr/atom.xml")); assert!(!file_contains!(public, "fr/atom.xml", "https://example.com/blog/something-else/")); assert!(file_contains!(public, "fr/atom.xml", "https://example.com/fr/blog/something-else/")); + assert!(file_contains!(public, "fr/atom.xml", r#""#)); // Italian doesn't have feed enabled assert!(!file_exists!(public, "it/atom.xml")); @@ -132,6 +134,8 @@ fn can_build_multilingual_site() { assert!(!file_contains!(public, "authors/index.html", "Vincent")); assert!(!file_exists!(public, "auteurs/index.html")); assert!(file_exists!(public, "authors/queen-elizabeth/atom.xml")); + assert!(file_contains!(public, "authors/queen-elizabeth/atom.xml", r#""#)); + assert!(file_contains!(public, "authors/queen-elizabeth/atom.xml", r#" - Queen Elizabeth"#)); assert!(file_exists!(public, "tags/index.html")); assert!(file_contains!(public, "tags/index.html", "hello")); diff --git a/components/templates/src/builtins/atom.xml b/components/templates/src/builtins/atom.xml index 279b2339..e4e191cc 100644 --- a/components/templates/src/builtins/atom.xml +++ b/components/templates/src/builtins/atom.xml @@ -1,6 +1,9 @@ - - {{ config.title }} + + {{ config.title }} + {%- if term %} - {{ term.name }} + {%- endif -%} + {%- if config.description %} {{ config.description }} {%- endif %} @@ -11,7 +14,7 @@ {{ feed_url | safe }} {%- for page in pages %} {{ page.title }} {{ page.date | date(format="%+") }} diff --git a/docs/content/documentation/templates/feeds.md b/docs/content/documentation/templates/feeds.md index 7ab92ff7..fb0dec5e 100644 --- a/docs/content/documentation/templates/feeds.md +++ b/docs/content/documentation/templates/feeds.md @@ -17,9 +17,18 @@ need to provide a template yourself. **Only pages with a date will be available.** -The feed template gets three variables in addition to `config`: +The feed template gets five variables: +- `config`: the site config - `feed_url`: the full url to that specific feed - `last_updated`: the most recent `updated` or `date` field of any post -- `pages`: see [page variables](@/documentation/templates/pages-sections.md#page-variables) for -a detailed description of what this contains +- `pages`: see [page variables](@/documentation/templates/pages-sections.md#page-variables) + for a detailed description of what this contains +- `lang`: the language code that applies to all of the pages in the feed, + if the site is multilingual, or `config.default_language` if it is not + +Feeds for taxonomy terms get two more variables, using types from the +[taxonomies templates](@/documentation/templates/taxonomies.md): + +- `taxonomy`: of type `TaxonomyConfig` +- `term`: of type `TaxonomyTerm`, but without `term.pages` (use `pages` instead)