@@ -745,26 +745,7 @@ impl Site {
745745 self . render_sitemap ( ) ?;
746746 start = log_time ( start, "Rendered sitemap" ) ;
747747
748- let library = self . library . read ( ) . unwrap ( ) ;
749- if self . config . generate_feeds {
750- let is_multilingual = self . config . is_multilingual ( ) ;
751- let pages: Vec < _ > = if is_multilingual {
752- library. pages . values ( ) . filter ( |p| p. lang == self . config . default_language ) . collect ( )
753- } else {
754- library. pages . values ( ) . collect ( )
755- } ;
756- self . render_feeds ( pages, None , & self . config . default_language , |c| c) ?;
757- start = log_time ( start, "Generated feed in default language" ) ;
758- }
759-
760- for ( code, language) in & self . config . other_languages ( ) {
761- if !language. generate_feeds {
762- continue ;
763- }
764- let pages: Vec < _ > = library. pages . values ( ) . filter ( |p| & p. lang == code) . collect ( ) ;
765- self . render_feeds ( pages, Some ( & PathBuf :: from ( code) ) , code, |c| c) ?;
766- start = log_time ( start, "Generated feed in other language" ) ;
767- }
748+ self . render_all_feeds ( ) ?;
768749 self . render_themes_css ( ) ?;
769750 start = log_time ( start, "Rendered themes css" ) ;
770751 self . render_404 ( ) ?;
@@ -784,6 +765,43 @@ impl Site {
784765 Ok ( ( ) )
785766 }
786767
768+ pub fn render_all_feeds ( & self ) -> Result < ( ) > {
769+ let mut start = Instant :: now ( ) ;
770+ let library = self . library . read ( ) . unwrap ( ) ;
771+
772+ for ( code, language) in & self . config . languages {
773+ let is_default_language = code == & self . config . default_language ;
774+
775+ let skip_default_language_feed_generation = is_default_language && !self . config . generate_feeds && !language. generate_feeds ;
776+ let skip_other_language_feed_generation = !is_default_language && !language. generate_feeds ;
777+ if skip_default_language_feed_generation || skip_other_language_feed_generation {
778+ continue ;
779+ }
780+
781+ let pages: Vec < _ > = if is_default_language && !self . config . is_multilingual ( ) {
782+ library. pages . values ( ) . collect ( )
783+ } else {
784+ library. pages . values ( ) . filter ( |p| & p. lang == code) . collect ( )
785+ } ;
786+
787+ let code_path = PathBuf :: from ( code) ;
788+ let base_path = if is_default_language {
789+ None
790+ } else {
791+ Some ( & code_path)
792+ } ;
793+
794+ self . render_feeds ( pages, base_path, code, |c| c) ?;
795+ let debug_message = if is_default_language {
796+ "Generated feed in default language"
797+ } else {
798+ "Generated feed in other language"
799+ } ;
800+ start = log_time ( start, debug_message) ;
801+ }
802+ Ok ( ( ) )
803+ }
804+
787805 pub fn render_themes_css ( & self ) -> Result < ( ) > {
788806 let themes = & self . config . markdown . highlight_themes_css ;
789807
@@ -1030,8 +1048,8 @@ impl Site {
10301048 Ok ( ( ) )
10311049 }
10321050
1033- /// Renders feeds for the given path and at the given path
1034- /// If both arguments are `None`, it will render only the feeds for the whole
1051+ /// Renders a feed for the given path and at the given path
1052+ /// If both arguments are `None`, it will render only the feed for the whole
10351053 /// site at the root folder.
10361054 pub fn render_feeds (
10371055 & self ,
@@ -1046,7 +1064,13 @@ impl Site {
10461064 None => return Ok ( ( ) ) ,
10471065 } ;
10481066
1049- for ( feed, feed_filename) in feeds. into_iter ( ) . zip ( self . config . feed_filenames . iter ( ) ) {
1067+ let feed_filenames = if let Some ( lang_config) = self . config . languages . get ( lang) {
1068+ & lang_config. feed_filenames
1069+ } else {
1070+ & self . config . feed_filenames
1071+ } ;
1072+
1073+ for ( feed, feed_filename) in feeds. into_iter ( ) . zip ( feed_filenames) {
10501074 if let Some ( base) = base_path {
10511075 let mut components = Vec :: new ( ) ;
10521076 for component in base. components ( ) {
@@ -1209,3 +1233,145 @@ fn log_time(start: Instant, message: &str) -> Instant {
12091233 }
12101234 now
12111235}
1236+
1237+ #[ cfg( test) ]
1238+ mod tests {
1239+ use super :: * ;
1240+ use content:: { FileInfo , Library , Page } ;
1241+ use config:: Config ;
1242+ use tempfile:: { tempdir, TempDir } ;
1243+
1244+ fn create_page ( title : & str , file_path : & str , lang : & str , config : & Config ) -> Page {
1245+ let mut page = Page { lang : lang. to_owned ( ) , ..Page :: default ( ) } ;
1246+ page. file = FileInfo :: new_page (
1247+ Path :: new ( format ! ( "/test/base/path/{}" , file_path) . as_str ( ) ) ,
1248+ & PathBuf :: new ( ) ,
1249+ ) ;
1250+ page. meta . title = Some ( title. to_string ( ) ) ;
1251+ page. meta . date = Some ( "2016-03-01" . to_string ( ) ) ;
1252+ page. meta . weight = Some ( 1 ) ;
1253+ page. lang = lang. to_string ( ) ;
1254+ page. file . find_language (
1255+ & config. default_language ,
1256+ & config. other_languages_codes ( ) ) . unwrap ( ) ;
1257+ page. permalink = config. make_permalink ( file_path) ;
1258+ page
1259+ }
1260+
1261+ fn create_site_from_config_and_pages ( config_raw : & str , pages : & [ ( & str , & str , & str ) ] ) -> ( TempDir , Site ) {
1262+ let config = Config :: parse ( config_raw) . unwrap ( ) ;
1263+ let mut library = Library :: default ( ) ;
1264+ for ( t, f, l) in pages {
1265+ library. insert_page ( create_page ( t, f, l, & config) ) ;
1266+ }
1267+
1268+ let tmp_dir = tempdir ( ) . unwrap ( ) ;
1269+ let path = tmp_dir. path ( ) ;
1270+ let public_dir = path. join ( "public" ) ;
1271+ let site = Site {
1272+ config : config. clone ( ) ,
1273+ library : Arc :: new ( RwLock :: new ( library) ) ,
1274+ base_path : path. into ( ) ,
1275+ tera : load_tera ( path, & config) . unwrap ( ) ,
1276+ imageproc : Arc :: new ( Mutex :: new ( imageproc:: Processor :: new ( path. to_path_buf ( ) , & config) ) ) ,
1277+ live_reload : None ,
1278+ output_path : public_dir. clone ( ) ,
1279+ content_path : path. into ( ) ,
1280+ sass_path : path. into ( ) ,
1281+ static_path : path. into ( ) ,
1282+ templates_path : path. into ( ) ,
1283+ taxonomies : vec ! [ ] ,
1284+ permalinks : HashMap :: new ( ) ,
1285+ include_drafts : false ,
1286+ build_mode : BuildMode :: Disk ,
1287+ shortcode_definitions : HashMap :: new ( ) ,
1288+ } ;
1289+ site. render_all_feeds ( ) . unwrap ( ) ;
1290+ ( tmp_dir, site)
1291+ }
1292+
1293+ #[ test]
1294+ fn can_render_feed_for_single_language_with_global_feed_flag ( ) {
1295+ let config_raw = r#"
1296+ title = "My site"
1297+ base_url = "https://replace-this-with-your-url.com"
1298+ generate_feeds = true
1299+
1300+ "# ;
1301+ let pages = vec ! [
1302+ ( "My En Article" , "content/my-article.md" , "en" ) ,
1303+ ] ;
1304+
1305+ let ( tmp_dir, site) = create_site_from_config_and_pages ( config_raw, & pages) ;
1306+ let public_dir = site. output_path ;
1307+
1308+ assert ! ( tmp_dir. path( ) . exists( ) ) ;
1309+ assert ! ( public_dir. exists( ) ) ;
1310+ assert ! ( public_dir. join( "atom.xml" ) . exists( ) ) ;
1311+ assert ! ( std:: fs:: read_to_string( public_dir. join( "atom.xml" ) ) . unwrap( ) . contains( "My En Article" ) ) ;
1312+ }
1313+
1314+ #[ test]
1315+ fn can_render_feed_for_multi_language_with_language_level_feed_flag ( ) {
1316+ let config_raw = r#"
1317+ base_url = "https://replace-this-with-your-url.com"
1318+ default_language = "en"
1319+
1320+ [languages.en]
1321+ title = "My English site"
1322+ generate_feeds = true
1323+
1324+ [languages.fr]
1325+ title = "My French site"
1326+ generate_feeds = false
1327+
1328+ "# ;
1329+ let pages = vec ! [
1330+ ( "My En Article" , "content/my-article.md" , "en" ) ,
1331+ ( "My Fr Article" , "content/my-article.fr.md" , "fr" ) ,
1332+ ] ;
1333+
1334+ let ( tmp_dir, site) = create_site_from_config_and_pages ( config_raw, & pages) ;
1335+ let public_dir = site. output_path ;
1336+
1337+ assert ! ( tmp_dir. path( ) . exists( ) ) ;
1338+ assert ! ( public_dir. exists( ) ) ;
1339+ assert ! ( public_dir. join( "atom.xml" ) . exists( ) ) ;
1340+ assert ! ( std:: fs:: read_to_string( public_dir. join( "atom.xml" ) ) . unwrap( ) . contains( "My En Article" ) ) ;
1341+ assert ! ( !std:: fs:: read_to_string( public_dir. join( "atom.xml" ) ) . unwrap( ) . contains( "My Fr Article" ) ) ;
1342+ }
1343+
1344+ #[ test]
1345+ fn can_render_feed_for_multi_language_with_language_level_feed_flag_and_feed_files ( ) {
1346+ let config_raw = r#"
1347+ base_url = "https://replace-this-with-your-url.com"
1348+ default_language = "en"
1349+
1350+ [languages.en]
1351+ title = "My English site"
1352+ generate_feeds = true
1353+
1354+ [languages.fr]
1355+ title = "My French site"
1356+ generate_feeds = true
1357+ feed_filenames = ["rss.xml"]
1358+
1359+ "# ;
1360+ let pages = vec ! [
1361+ ( "My En Article" , "content/my-article.md" , "en" ) ,
1362+ ( "My Fr Article" , "content/my-article.fr.md" , "fr" ) ,
1363+ ] ;
1364+
1365+ let ( tmp_dir, site) = create_site_from_config_and_pages ( config_raw, & pages) ;
1366+ let public_dir = site. output_path ;
1367+
1368+ assert ! ( tmp_dir. path( ) . exists( ) ) ;
1369+ assert ! ( public_dir. exists( ) ) ;
1370+ assert ! ( public_dir. join( "atom.xml" ) . exists( ) ) ;
1371+ assert ! ( public_dir. join( "fr" ) . join( "rss.xml" ) . exists( ) ) ;
1372+ assert ! ( std:: fs:: read_to_string( public_dir. join( "atom.xml" ) ) . unwrap( ) . contains( "My En Article" ) ) ;
1373+ assert ! ( !std:: fs:: read_to_string( public_dir. join( "atom.xml" ) ) . unwrap( ) . contains( "My Fr Article" ) ) ;
1374+ assert ! ( !std:: fs:: read_to_string( public_dir. join( "fr" ) . join( "rss.xml" ) ) . unwrap( ) . contains( "My En Article" ) ) ;
1375+ assert ! ( std:: fs:: read_to_string( public_dir. join( "fr" ) . join( "rss.xml" ) ) . unwrap( ) . contains( "My Fr Article" ) ) ;
1376+ }
1377+ }
0 commit comments