From c054ed1b10163085f82805ba630d54ffbc3b8d03 Mon Sep 17 00:00:00 2001 From: LunarEclipse363 Date: Wed, 19 Jun 2024 14:57:18 +0200 Subject: [PATCH] Added support for multiple feeds (i.e. generating both Atom and RSS) (#2477) * Added support for multiple feeds * Implemented backwards-compatibility for feed config * Added a test for feed config backwards-compat, fixed bugs - Fixed language config merge bug found by a test - Adjusted two existing tests to fully check stuff related to multiple feeds - Added a new test for backwards-compatibility of the changes - Fixed bugs found by the newly added test * Renamed MightBeSingle to SingleOrVec * Made the multiple feeds config changes "loudly" backwards-incompatible * added #[serde(deny_unknown_fields)] to front-matter, fixed problems this found in tests --- CHANGELOG.md | 4 ++ components/config/src/config/languages.rs | 41 ++++++------ components/config/src/config/mod.rs | 60 ++++++++++------- .../content/src/front_matter/section.rs | 6 +- components/content/src/section.rs | 2 +- components/content/src/ser.rs | 4 +- components/site/benches/site.rs | 2 +- components/site/src/{feed.rs => feeds.rs} | 29 +++++---- components/site/src/lib.rs | 64 ++++++++++--------- components/templates/src/global_fns/files.rs | 27 +++++--- .../documentation/content/multilingual.md | 2 +- docs/content/documentation/content/section.md | 4 +- .../getting-started/configuration.md | 12 ++-- .../documentation/templates/feeds/index.md | 10 +-- .../documentation/templates/pages-sections.md | 4 +- docs/content/themes/zolarwind/index.md | 4 +- test_site/config.toml | 2 +- test_site/content/posts/_index.md | 2 +- .../posts/tutorials/programming/_index.md | 2 +- test_site_i18n/config.toml | 4 +- test_site_i18n/content/blog/_index.fr.md | 2 +- test_site_i18n/content/blog/_index.it.md | 2 +- test_site_i18n/content/blog/_index.md | 2 +- 23 files changed, 163 insertions(+), 128 deletions(-) rename components/site/src/{feed.rs => feeds.rs} (76%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75950a3d..4b786ff3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ - Add `render = false` capability to pages - Handle string dates in YAML front-matter - Add support for fuse.js search format +- Added support for generating multiple kinds of feeds at once +- Changed config options named `generate_feed` to `generate_feeds` (both in config.toml and in section front-matter) +- Changed config option `feed_filename: String` to `feed_filenames: Vec` +- The config file no longer allows arbitrary fields outside the `[extra]` section ## 0.18.0 (2023-12-18) diff --git a/components/config/src/config/languages.rs b/components/config/src/config/languages.rs index 3c863799..eca7bc95 100644 --- a/components/config/src/config/languages.rs +++ b/components/config/src/config/languages.rs @@ -8,17 +8,17 @@ use crate::config::search; use crate::config::taxonomies; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(default)] +#[serde(default, deny_unknown_fields)] pub struct LanguageOptions { /// Title of the site. Defaults to None pub title: Option, /// Description of the site. Defaults to None pub description: Option, - /// Whether to generate a feed for that language, defaults to `false` - pub generate_feed: bool, - /// The filename to use for feeds. Used to find the template, too. - /// Defaults to "atom.xml", with "rss.xml" also having a template provided out of the box. - pub feed_filename: String, + /// Whether to generate feeds for that language, defaults to `false` + pub generate_feeds: bool, + /// The filenames to use for feeds. Used to find the templates, too. + /// Defaults to ["atom.xml"], with "rss.xml" also having a template provided out of the box. + pub feed_filenames: Vec, pub taxonomies: Vec, /// Whether to generate search index for that language, defaults to `false` pub build_search_index: bool, @@ -66,9 +66,10 @@ impl LanguageOptions { merge_field!(self.title, other.title, "title"); merge_field!(self.description, other.description, "description"); merge_field!( - self.feed_filename == "atom.xml", - self.feed_filename, - other.feed_filename, + self.feed_filenames.is_empty() + || self.feed_filenames == LanguageOptions::default().feed_filenames, + self.feed_filenames, + other.feed_filenames, "feed_filename" ); merge_field!(self.taxonomies.is_empty(), self.taxonomies, other.taxonomies, "taxonomies"); @@ -79,7 +80,7 @@ impl LanguageOptions { "translations" ); - self.generate_feed = self.generate_feed || other.generate_feed; + self.generate_feeds = self.generate_feeds || other.generate_feeds; self.build_search_index = self.build_search_index || other.build_search_index; if self.search == search::Search::default() { @@ -101,8 +102,8 @@ impl Default for LanguageOptions { LanguageOptions { title: None, description: None, - generate_feed: false, - feed_filename: "atom.xml".to_string(), + generate_feeds: false, + feed_filenames: vec!["atom.xml".to_string()], taxonomies: vec![], build_search_index: false, search: search::Search::default(), @@ -129,8 +130,8 @@ mod tests { let mut base_default_language_options = LanguageOptions { title: Some("Site's title".to_string()), description: None, - generate_feed: true, - feed_filename: "atom.xml".to_string(), + generate_feeds: true, + feed_filenames: vec!["atom.xml".to_string()], taxonomies: vec![], build_search_index: true, search: search::Search::default(), @@ -140,8 +141,8 @@ mod tests { let section_default_language_options = LanguageOptions { title: None, description: Some("Site's description".to_string()), - generate_feed: false, - feed_filename: "rss.xml".to_string(), + generate_feeds: false, + feed_filenames: vec!["rss.xml".to_string()], taxonomies: vec![], build_search_index: true, search: search::Search::default(), @@ -156,8 +157,8 @@ mod tests { let mut base_default_language_options = LanguageOptions { title: Some("Site's title".to_string()), description: Some("Duplicate site description".to_string()), - generate_feed: true, - feed_filename: "".to_string(), + generate_feeds: true, + feed_filenames: vec![], taxonomies: vec![], build_search_index: true, search: search::Search::default(), @@ -167,8 +168,8 @@ mod tests { let section_default_language_options = LanguageOptions { title: None, description: Some("Site's description".to_string()), - generate_feed: false, - feed_filename: "Some feed_filename".to_string(), + generate_feeds: false, + feed_filenames: vec!["Some feed_filename".to_string()], taxonomies: vec![], build_search_index: true, search: search::Search::default(), diff --git a/components/config/src/config/mod.rs b/components/config/src/config/mod.rs index f2a40675..186d884b 100644 --- a/components/config/src/config/mod.rs +++ b/components/config/src/config/mod.rs @@ -30,7 +30,7 @@ pub enum Mode { } #[derive(Clone, Debug, Deserialize)] -#[serde(default)] +#[serde(default, deny_unknown_fields)] pub struct Config { /// Base URL of the site, the only required config argument pub base_url: String, @@ -49,13 +49,13 @@ pub struct Config { /// The translations strings for the default language translations: HashMap, - /// Whether to generate a feed. Defaults to false. - pub generate_feed: bool, + /// Whether to generate feeds. Defaults to false. + pub generate_feeds: bool, /// The number of articles to include in the feed. Defaults to including all items. pub feed_limit: Option, - /// The filename to use for feeds. Used to find the template, too. - /// Defaults to "atom.xml", with "rss.xml" also having a template provided out of the box. - pub feed_filename: String, + /// The filenames to use for feeds. Used to find the templates, too. + /// Defaults to ["atom.xml"], with "rss.xml" also having a template provided out of the box. + pub feed_filenames: Vec, /// If set, files from static/ will be hardlinked instead of copied to the output dir. pub hard_link_static: bool, pub taxonomies: Vec, @@ -109,7 +109,7 @@ pub struct SerializedConfig<'a> { languages: HashMap<&'a String, &'a languages::LanguageOptions>, default_language: &'a str, generate_feed: bool, - feed_filename: &'a str, + feed_filenames: &'a [String], taxonomies: &'a [taxonomies::TaxonomyConfig], author: &'a Option, build_search_index: bool, @@ -183,12 +183,14 @@ impl Config { /// Makes a url, taking into account that the base url might have a trailing slash pub fn make_permalink(&self, path: &str) -> String { - let trailing_bit = - if path.ends_with('/') || path.ends_with(&self.feed_filename) || path.is_empty() { - "" - } else { - "/" - }; + let trailing_bit = if path.ends_with('/') + || self.feed_filenames.iter().any(|feed_filename| path.ends_with(feed_filename)) + || path.is_empty() + { + "" + } else { + "/" + }; // Index section with a base url that has a trailing slash if self.base_url.ends_with('/') && path == "/" { @@ -212,8 +214,8 @@ impl Config { let mut base_language_options = languages::LanguageOptions { title: self.title.clone(), description: self.description.clone(), - generate_feed: self.generate_feed, - feed_filename: self.feed_filename.clone(), + generate_feeds: self.generate_feeds, + feed_filenames: self.feed_filenames.clone(), build_search_index: self.build_search_index, taxonomies: self.taxonomies.clone(), search: self.search.clone(), @@ -320,8 +322,8 @@ impl Config { description: &options.description, languages: self.languages.iter().filter(|(k, _)| k.as_str() != lang).collect(), default_language: &self.default_language, - generate_feed: options.generate_feed, - feed_filename: &options.feed_filename, + generate_feed: options.generate_feeds, + feed_filenames: &options.feed_filenames, taxonomies: &options.taxonomies, author: &self.author, build_search_index: options.build_search_index, @@ -369,9 +371,9 @@ impl Default for Config { theme: None, default_language: "en".to_string(), languages: HashMap::new(), - generate_feed: false, + generate_feeds: false, feed_limit: None, - feed_filename: "atom.xml".to_string(), + feed_filenames: vec!["atom.xml".to_string()], hard_link_static: false, taxonomies: Vec::new(), author: None, @@ -428,8 +430,8 @@ mod tests { languages::LanguageOptions { title: None, description: description_lang_section.clone(), - generate_feed: true, - feed_filename: config.feed_filename.clone(), + generate_feeds: true, + feed_filenames: config.feed_filenames.clone(), taxonomies: config.taxonomies.clone(), build_search_index: false, search: search::Search::default(), @@ -456,8 +458,8 @@ mod tests { languages::LanguageOptions { title: title_lang_section.clone(), description: None, - generate_feed: true, - feed_filename: config.feed_filename.clone(), + generate_feeds: true, + feed_filenames: config.feed_filenames.clone(), taxonomies: config.taxonomies.clone(), build_search_index: false, search: search::Search::default(), @@ -976,4 +978,16 @@ author = "person@example.com (Some Person)" let config = Config::parse(config).unwrap(); assert_eq!(config.author, Some("person@example.com (Some Person)".to_owned())) } + + #[test] + #[should_panic] + fn test_backwards_incompatibility_for_feeds() { + let config = r#" +base_url = "example.com" +generate_feed = true +feed_filename = "test.xml" + "#; + + Config::parse(config).unwrap(); + } } diff --git a/components/content/src/front_matter/section.rs b/components/content/src/front_matter/section.rs index ee077799..76c51461 100644 --- a/components/content/src/front_matter/section.rs +++ b/components/content/src/front_matter/section.rs @@ -12,7 +12,7 @@ static DEFAULT_PAGINATE_PATH: &str = "page"; /// The front matter of every section #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(default)] +#[serde(default, deny_unknown_fields)] pub struct SectionFrontMatter { /// of the page pub title: Option<String>, @@ -69,7 +69,7 @@ pub struct SectionFrontMatter { pub aliases: Vec<String>, /// Whether to generate a feed for the current section #[serde(skip_serializing)] - pub generate_feed: bool, + pub generate_feeds: bool, /// Any extra parameter present in the front matter pub extra: Map<String, Value>, } @@ -113,7 +113,7 @@ impl Default for SectionFrontMatter { transparent: false, page_template: None, aliases: Vec::new(), - generate_feed: false, + generate_feeds: false, extra: Map::new(), draft: false, } diff --git a/components/content/src/section.rs b/components/content/src/section.rs index 920f863e..d4c84a9b 100644 --- a/components/content/src/section.rs +++ b/components/content/src/section.rs @@ -283,7 +283,7 @@ mod tests { create_dir_all(path.join(&article_path).join("foo/baz/quux")) .expect("create nested temp dir"); let mut f = File::create(article_path.join("_index.md")).unwrap(); - f.write_all(b"+++\nslug=\"hey\"\n+++\n").unwrap(); + f.write_all(b"+++\n+++\n").unwrap(); File::create(article_path.join("example.js")).unwrap(); File::create(article_path.join("graph.jpg")).unwrap(); File::create(article_path.join("fail.png")).unwrap(); diff --git a/components/content/src/ser.rs b/components/content/src/ser.rs index 607d361d..919d0d1b 100644 --- a/components/content/src/ser.rs +++ b/components/content/src/ser.rs @@ -160,7 +160,7 @@ pub struct SerializingSection<'a> { subsections: Vec<&'a str>, translations: Vec<TranslatedContent<'a>>, backlinks: Vec<BackLink<'a>>, - generate_feed: bool, + generate_feeds: bool, transparent: bool, } @@ -220,7 +220,7 @@ impl<'a> SerializingSection<'a> { reading_time: section.reading_time, assets: §ion.serialized_assets, lang: §ion.lang, - generate_feed: section.meta.generate_feed, + generate_feeds: section.meta.generate_feeds, transparent: section.meta.transparent, pages, subsections, diff --git a/components/site/benches/site.rs b/components/site/benches/site.rs index 0ec69d9e..d7fa13b3 100644 --- a/components/site/benches/site.rs +++ b/components/site/benches/site.rs @@ -42,7 +42,7 @@ fn bench_render_feed(b: &mut test::Bencher) { let public = &tmp_dir.path().join("public"); site.set_output_path(&public); b.iter(|| { - site.render_feed( + site.render_feeds( site.library.read().unwrap().pages.values().collect(), None, &site.config.default_language, diff --git a/components/site/src/feed.rs b/components/site/src/feeds.rs similarity index 76% rename from components/site/src/feed.rs rename to components/site/src/feeds.rs index 5ae58368..653b0f9a 100644 --- a/components/site/src/feed.rs +++ b/components/site/src/feeds.rs @@ -27,13 +27,13 @@ impl<'a> SerializedFeedTaxonomyItem<'a> { } } -pub fn render_feed( +pub fn render_feeds( site: &Site, all_pages: Vec<&Page>, lang: &str, base_path: Option<&PathBuf>, additional_context_fn: impl Fn(Context) -> Context, -) -> Result<Option<String>> { +) -> Result<Option<Vec<String>>> { let mut pages = all_pages.into_iter().filter(|p| p.meta.date.is_some()).collect::<Vec<_>>(); // Don't generate a feed if none of the pages has a date @@ -73,18 +73,23 @@ pub fn render_feed( context.insert("config", &site.config.serialize(lang)); context.insert("lang", lang); - let feed_filename = &site.config.feed_filename; - let feed_url = if let Some(base) = base_path { - site.config.make_permalink(&base.join(feed_filename).to_string_lossy().replace('\\', "/")) - } else { - site.config.make_permalink(feed_filename) - }; + let mut feeds = Vec::new(); + for feed_filename in &site.config.feed_filenames { + let mut context = context.clone(); - context.insert("feed_url", &feed_url); + let feed_url = if let Some(base) = base_path { + site.config + .make_permalink(&base.join(feed_filename).to_string_lossy().replace('\\', "/")) + } else { + site.config.make_permalink(feed_filename) + }; - context = additional_context_fn(context); + context.insert("feed_url", &feed_url); - let feed = render_template(feed_filename, &site.tera, context, &site.config.theme)?; + context = additional_context_fn(context); - Ok(Some(feed)) + feeds.push(render_template(feed_filename, &site.tera, context, &site.config.theme)?); + } + + Ok(Some(feeds)) } diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index 10729437..96c9c150 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -1,4 +1,4 @@ -pub mod feed; +pub mod feeds; pub mod link_checking; mod minify; pub mod sass; @@ -746,23 +746,23 @@ impl Site { start = log_time(start, "Rendered sitemap"); let library = self.library.read().unwrap(); - if self.config.generate_feed { + if self.config.generate_feeds { let is_multilingual = self.config.is_multilingual(); let pages: Vec<_> = if is_multilingual { library.pages.values().filter(|p| p.lang == self.config.default_language).collect() } else { library.pages.values().collect() }; - self.render_feed(pages, None, &self.config.default_language, |c| c)?; + self.render_feeds(pages, None, &self.config.default_language, |c| c)?; start = log_time(start, "Generated feed in default language"); } for (code, language) in &self.config.other_languages() { - if !language.generate_feed { + if !language.generate_feeds { continue; } let pages: Vec<_> = library.pages.values().filter(|p| &p.lang == code).collect(); - self.render_feed(pages, Some(&PathBuf::from(code)), code, |c| c)?; + self.render_feeds(pages, Some(&PathBuf::from(code)), code, |c| c)?; start = log_time(start, "Generated feed in other language"); } self.render_themes_css()?; @@ -965,14 +965,16 @@ impl Site { } else { PathBuf::from(format!("{}/{}/{}", taxonomy.lang, taxonomy.slug, item.slug)) }; - self.render_feed( + self.render_feeds( item.pages.iter().map(|p| library.pages.get(p).unwrap()).collect(), Some(&tax_path), &taxonomy.lang, |mut context: Context| { context.insert("taxonomy", &taxonomy.kind); - context - .insert("term", &feed::SerializedFeedTaxonomyItem::from_item(item)); + context.insert( + "term", + &feeds::SerializedFeedTaxonomyItem::from_item(item), + ); context }, ) @@ -1028,36 +1030,38 @@ impl Site { Ok(()) } - /// Renders a feed for the given path and at the given path - /// If both arguments are `None`, it will render only the feed for the whole + /// Renders feeds for the given path and at the given path + /// If both arguments are `None`, it will render only the feeds for the whole /// site at the root folder. - pub fn render_feed( + pub fn render_feeds( &self, all_pages: Vec<&Page>, base_path: Option<&PathBuf>, lang: &str, additional_context_fn: impl Fn(Context) -> Context, ) -> Result<()> { - let feed = match feed::render_feed(self, all_pages, lang, base_path, additional_context_fn)? - { - Some(v) => v, - None => return Ok(()), - }; - let feed_filename = &self.config.feed_filename; + let feeds = + match feeds::render_feeds(self, all_pages, lang, base_path, additional_context_fn)? { + Some(v) => v, + None => return Ok(()), + }; - if let Some(base) = base_path { - let mut components = Vec::new(); - for component in base.components() { - components.push(component.as_os_str().to_string_lossy()); + for (feed, feed_filename) in feeds.into_iter().zip(self.config.feed_filenames.iter()) { + if let Some(base) = base_path { + let mut components = Vec::new(); + for component in base.components() { + components.push(component.as_os_str().to_string_lossy()); + } + self.write_content( + &components.iter().map(|x| x.as_ref()).collect::<Vec<_>>(), + feed_filename, + feed, + )?; + } else { + self.write_content(&[], feed_filename, feed)?; } - self.write_content( - &components.iter().map(|x| x.as_ref()).collect::<Vec<_>>(), - feed_filename, - feed, - )?; - } else { - self.write_content(&[], feed_filename, feed)?; } + Ok(()) } @@ -1076,10 +1080,10 @@ impl Site { output_path.push(component); } - if section.meta.generate_feed { + if section.meta.generate_feeds { let library = &self.library.read().unwrap(); let pages = section.pages.iter().map(|k| library.pages.get(k).unwrap()).collect(); - self.render_feed( + self.render_feeds( pages, Some(&PathBuf::from(§ion.path[1..])), §ion.lang, diff --git a/components/templates/src/global_fns/files.rs b/components/templates/src/global_fns/files.rs index 2fd9678a..eaad1231 100644 --- a/components/templates/src/global_fns/files.rs +++ b/components/templates/src/global_fns/files.rs @@ -461,27 +461,34 @@ title = "A title" } #[test] - fn can_get_feed_url_with_default_language() { + fn can_get_feed_urls_with_default_language() { let config = Config::parse(CONFIG_DATA).unwrap(); let dir = create_temp_dir(); let static_fn = GetUrl::new(dir.path().to_path_buf(), config.clone(), HashMap::new(), PathBuf::new()); - let mut args = HashMap::new(); - args.insert("path".to_string(), to_value(config.feed_filename).unwrap()); - args.insert("lang".to_string(), to_value("fr").unwrap()); - assert_eq!(static_fn.call(&args).unwrap(), "https://remplace-par-ton-url.fr/atom.xml"); + for feed_filename in &config.feed_filenames { + let mut args = HashMap::new(); + args.insert("path".to_string(), to_value(feed_filename).unwrap()); + args.insert("lang".to_string(), to_value("fr").unwrap()); + assert_eq!(static_fn.call(&args).unwrap(), "https://remplace-par-ton-url.fr/atom.xml"); + } } #[test] - fn can_get_feed_url_with_other_language() { + fn can_get_feed_urls_with_other_language() { let config = Config::parse(CONFIG_DATA).unwrap(); let dir = create_temp_dir(); let static_fn = GetUrl::new(dir.path().to_path_buf(), config.clone(), HashMap::new(), PathBuf::new()); - let mut args = HashMap::new(); - args.insert("path".to_string(), to_value(config.feed_filename).unwrap()); - args.insert("lang".to_string(), to_value("en").unwrap()); - assert_eq!(static_fn.call(&args).unwrap(), "https://remplace-par-ton-url.fr/en/atom.xml"); + for feed_filename in &config.feed_filenames { + let mut args = HashMap::new(); + args.insert("path".to_string(), to_value(feed_filename).unwrap()); + args.insert("lang".to_string(), to_value("en").unwrap()); + assert_eq!( + static_fn.call(&args).unwrap(), + "https://remplace-par-ton-url.fr/en/atom.xml" + ); + } } #[test] diff --git a/docs/content/documentation/content/multilingual.md b/docs/content/documentation/content/multilingual.md index 45f893ae..ab200e49 100644 --- a/docs/content/documentation/content/multilingual.md +++ b/docs/content/documentation/content/multilingual.md @@ -11,7 +11,7 @@ to your `config.toml`. For example: ```toml [languages.fr] -generate_feed = true # there will be a feed for French content +generate_feeds = true # there will be a feed for French content build_search_index = true taxonomies = [ {name = "auteurs"}, diff --git a/docs/content/documentation/content/section.md b/docs/content/documentation/content/section.md index 9a726e7b..73ec1e50 100644 --- a/docs/content/documentation/content/section.md +++ b/docs/content/documentation/content/section.md @@ -106,11 +106,11 @@ transparent = false # current one. This takes an array of paths, not URLs. aliases = [] -# If set to "true", a feed file will be generated for this section at the +# If set to "true", feed files will be generated for this section at the # section's root path. This is independent of the site-wide variable of the same # name. The section feed will only include posts from that respective feed, and # not from any other sections, including sub-sections under that section. -generate_feed = false +generate_feeds = false # Your own data. [extra] diff --git a/docs/content/documentation/getting-started/configuration.md b/docs/content/documentation/getting-started/configuration.md index 1130cecb..103ae073 100644 --- a/docs/content/documentation/getting-started/configuration.md +++ b/docs/content/documentation/getting-started/configuration.md @@ -65,12 +65,12 @@ ignored_content = [] ignored_static = [] # When set to "true", a feed is automatically generated. -generate_feed = false +generate_feeds = false -# The filename to use for the feed. Used as the template filename, too. -# Defaults to "atom.xml", which has a built-in template that renders an Atom 1.0 feed. +# The filenames to use for the feeds. Used as the template filenames, too. +# Defaults to ["atom.xml"], which has a built-in template that renders an Atom 1.0 feed. # There is also a built-in template "rss.xml" that renders an RSS 2.0 feed. -feed_filename = "atom.xml" +feed_filenames = ["atom.xml"] # The number of articles to include in the feed. All items are included if # this limit is not set (the default). @@ -199,13 +199,13 @@ index_format = "elasticlunr_javascript" # Additional languages definition # You can define language specific config values and translations: -# title, description, generate_feed, feed_filename, taxonomies, build_search_index +# title, description, generate_feeds, feed_filenames, taxonomies, build_search_index # as well as its own search configuration and translations (see above for details on those) [languages] # For example # [languages.fr] # title = "Mon blog" -# generate_feed = true +# generate_feeds = true # taxonomies = [ # {name = "auteurs"}, # {name = "tags"}, diff --git a/docs/content/documentation/templates/feeds/index.md b/docs/content/documentation/templates/feeds/index.md index 806f9995..7a8d593f 100644 --- a/docs/content/documentation/templates/feeds/index.md +++ b/docs/content/documentation/templates/feeds/index.md @@ -4,13 +4,13 @@ weight = 50 aliases = ["/documentation/templates/rss/"] +++ -If the site `config.toml` file sets `generate_feed = true`, then Zola will -generate a feed file for the site, named according to the `feed_filename` +If the site `config.toml` file sets `generate_feeds = true`, then Zola will +generate feed files for the site, named according to the `feed_filenames` setting in `config.toml`, which defaults to `atom.xml`. Given the feed filename `atom.xml`, the generated file will live at `base_url/atom.xml`, based upon the `atom.xml` file in the `templates` directory, or the built-in Atom template. -`feed_filename` can be set to any value, but built-in templates are provided +`feed_filenames` can be set to any value, but built-in templates are provided for `atom.xml` (in the preferred Atom 1.0 format), and `rss.xml` (in the RSS 2.0 format). If you choose a different filename (e.g. `feed.xml`), you will need to provide a template yourself. @@ -54,7 +54,7 @@ Feeds for taxonomy terms get two more variables, using types from the - `term`: of type `TaxonomyTerm`, but without `term.pages` (use `pages` instead) You can also enable separate feeds for each section by setting the -`generate_feed` variable to true in the respective section's front matter. +`generate_feeds` variable to true in the respective section's front matter. Section feeds will use the same template as indicated in the `config.toml` file. Section feeds, in addition to the five feed template variables, get the `section` variable from the [section @@ -85,4 +85,4 @@ In order to enable the tag feeds as well, you can overload the `block rss` using Each tag page will refer to it's dedicated feed. [atom_rfc]: https://www.rfc-editor.org/rfc/rfc4287 -[rss_spec]: https://www.rssboard.org/rss-specification#ltauthorgtSubelementOfLtitemgt \ No newline at end of file +[rss_spec]: https://www.rssboard.org/rss-specification#ltauthorgtSubelementOfLtitemgt diff --git a/docs/content/documentation/templates/pages-sections.md b/docs/content/documentation/templates/pages-sections.md index 99a06760..97f95596 100644 --- a/docs/content/documentation/templates/pages-sections.md +++ b/docs/content/documentation/templates/pages-sections.md @@ -108,8 +108,8 @@ lang: String; translations: Array<TranslatedContent>; // All the pages/sections linking this page: their permalink and a title if there is one backlinks: Array<{permalink: String, title: String?}>; -// Whether this section generates a feed or not. Taken from the front-matter if set -generate_feed: bool; +// Whether this section generates feeds or not. Taken from the front-matter if set +generate_feeds: bool; // Whether this section is transparent. Taken from the front-matter if set transparent: bool; ``` diff --git a/docs/content/themes/zolarwind/index.md b/docs/content/themes/zolarwind/index.md index 57360be2..201eb53e 100644 --- a/docs/content/themes/zolarwind/index.md +++ b/docs/content/themes/zolarwind/index.md @@ -120,7 +120,7 @@ Here's a breakdown of the configuration settings tailored for this theme: - **build_search_index**: If set to `true`, a search index will be built from the pages and section content for the `default_language`. In this configuration and for this theme, it's disabled (`false`). -- **generate_feed**: Determines if an Atom feed (file `atom.xml`) is automatically generated. +- **generate_feeds**: Determines if an Atom feed (file `atom.xml`) is automatically generated. It's set to `true`, meaning a feed will be generated. - **taxonomies**: An array of taxonomies (classification systems) used for the site. @@ -408,4 +408,4 @@ Just use the file `en.toml` as a template for your own translations. This theme is under the MIT License. For details, please refer to the LICENSE file. - \ No newline at end of file + diff --git a/test_site/config.toml b/test_site/config.toml index e3fcbfd6..05e0db0e 100644 --- a/test_site/config.toml +++ b/test_site/config.toml @@ -1,7 +1,7 @@ title = "My Integration Testing site" base_url = "https://replace-this-with-your-url.com" compile_sass = true -generate_feed = true +generate_feeds = true theme = "sample" taxonomies = [ diff --git a/test_site/content/posts/_index.md b/test_site/content/posts/_index.md index 2be1b38c..2abaaf94 100644 --- a/test_site/content/posts/_index.md +++ b/test_site/content/posts/_index.md @@ -5,5 +5,5 @@ template = "section_paginated.html" insert_anchor_links = "left" sort_by = "date" aliases = ["another-old-url/index.html"] -generate_feed = true +generate_feeds = true +++ diff --git a/test_site/content/posts/tutorials/programming/_index.md b/test_site/content/posts/tutorials/programming/_index.md index 6ab12564..50891f33 100644 --- a/test_site/content/posts/tutorials/programming/_index.md +++ b/test_site/content/posts/tutorials/programming/_index.md @@ -2,7 +2,7 @@ title = "Programming" sort_by = "weight" weight = 1 -generate_feed = true +generate_feeds = true [extra] we_have_extra = "variables" diff --git a/test_site_i18n/config.toml b/test_site_i18n/config.toml index d7f03a3e..846e1037 100644 --- a/test_site_i18n/config.toml +++ b/test_site_i18n/config.toml @@ -9,7 +9,7 @@ build_search_index = true default_language = "en" -generate_feed = true +generate_feeds = true taxonomies = [ {name = "authors", feed = true}, @@ -17,7 +17,7 @@ taxonomies = [ ] [languages.fr] -generate_feed = true +generate_feeds = true taxonomies = [ {name = "auteurs", feed = true}, {name = "tags"}, diff --git a/test_site_i18n/content/blog/_index.fr.md b/test_site_i18n/content/blog/_index.fr.md index 8e1497c0..80e98f72 100644 --- a/test_site_i18n/content/blog/_index.fr.md +++ b/test_site_i18n/content/blog/_index.fr.md @@ -1,7 +1,7 @@ +++ title = "Mon blog" sort_by = "date" -insert_anchors = "right" +insert_anchor_links = "right" +++ [Dernières nouvelles](#news) diff --git a/test_site_i18n/content/blog/_index.it.md b/test_site_i18n/content/blog/_index.it.md index 5e008825..6a2f1512 100644 --- a/test_site_i18n/content/blog/_index.it.md +++ b/test_site_i18n/content/blog/_index.it.md @@ -1,5 +1,5 @@ +++ title = "Il mio blog" sort_by = "date" -insert_anchors = "right" +insert_anchor_links = "right" +++ diff --git a/test_site_i18n/content/blog/_index.md b/test_site_i18n/content/blog/_index.md index a0b42407..bab311ae 100644 --- a/test_site_i18n/content/blog/_index.md +++ b/test_site_i18n/content/blog/_index.md @@ -1,5 +1,5 @@ +++ title = "My blog" sort_by = "date" -insert_anchors = "left" +insert_anchor_links = "left" +++