Extract some feed logic out of site/lib.rs
This commit is contained in:
parent
5fe1036a1d
commit
d7b53687a5
|
@ -258,8 +258,8 @@ impl Section {
|
|||
None => None,
|
||||
Some(x) => match x {
|
||||
0 => None,
|
||||
_ => Some(x)
|
||||
}
|
||||
_ => Some(x),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ pub fn after_template_change(site: &mut Site, path: &Path) -> Result<()> {
|
|||
site.library.read().unwrap().pages_values(),
|
||||
None,
|
||||
&site.config.default_language,
|
||||
None,
|
||||
|c| c,
|
||||
)
|
||||
}
|
||||
"split_sitemap_index.xml" => site.render_sitemap(),
|
||||
|
|
79
components/site/src/feed.rs
Normal file
79
components/site/src/feed.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use rayon::prelude::*;
|
||||
use serde_derive::Serialize;
|
||||
use tera::Context;
|
||||
|
||||
use crate::Site;
|
||||
use errors::Result;
|
||||
use library::{sort_actual_pages_by_date, Page, TaxonomyItem};
|
||||
use utils::templates::render_template;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
pub struct SerializedFeedTaxonomyItem<'a> {
|
||||
name: &'a str,
|
||||
slug: &'a str,
|
||||
permalink: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> SerializedFeedTaxonomyItem<'a> {
|
||||
pub fn from_item(item: &'a TaxonomyItem) -> Self {
|
||||
SerializedFeedTaxonomyItem {
|
||||
name: &item.name,
|
||||
slug: &item.slug,
|
||||
permalink: &item.permalink,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_feed(
|
||||
site: &Site,
|
||||
all_pages: Vec<&Page>,
|
||||
lang: &str,
|
||||
base_path: Option<&PathBuf>,
|
||||
additional_context_fn: impl Fn(Context) -> Context,
|
||||
) -> Result<Option<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
|
||||
if pages.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
pages.par_sort_unstable_by(sort_actual_pages_by_date);
|
||||
|
||||
let mut context = Context::new();
|
||||
context.insert(
|
||||
"last_updated",
|
||||
pages
|
||||
.iter()
|
||||
.filter_map(|page| page.meta.updated.as_ref())
|
||||
.chain(pages[0].meta.date.as_ref())
|
||||
.max() // I love lexicographically sorted date strings
|
||||
.unwrap(), // Guaranteed because of pages[0].meta.date
|
||||
);
|
||||
let library = site.library.read().unwrap();
|
||||
// limit to the last n elements if the limit is set; otherwise use all.
|
||||
let num_entries = site.config.feed_limit.unwrap_or_else(|| pages.len());
|
||||
let p =
|
||||
pages.iter().take(num_entries).map(|x| x.to_serialized_basic(&library)).collect::<Vec<_>>();
|
||||
|
||||
context.insert("pages", &p);
|
||||
context.insert("config", &site.config);
|
||||
context.insert("lang", lang);
|
||||
|
||||
let feed_filename = &site.config.feed_filename;
|
||||
let feed_url = if let Some(ref base) = base_path {
|
||||
site.config.make_permalink(&base.join(feed_filename).to_string_lossy().replace('\\', "/"))
|
||||
} else {
|
||||
site.config.make_permalink(feed_filename)
|
||||
};
|
||||
|
||||
context.insert("feed_url", &feed_url);
|
||||
|
||||
context = additional_context_fn(context);
|
||||
|
||||
let feed = render_template(feed_filename, &site.tera, context, &site.config.theme)?;
|
||||
|
||||
Ok(Some(feed))
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
pub mod feed;
|
||||
pub mod link_checking;
|
||||
pub mod sass;
|
||||
pub mod sitemap;
|
||||
|
@ -10,18 +11,15 @@ use std::sync::{Arc, Mutex, RwLock};
|
|||
|
||||
use glob::glob;
|
||||
use rayon::prelude::*;
|
||||
use serde_derive::Serialize;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
use crate::feed::render_feed;
|
||||
use crate::link_checking::{check_external_links, check_internal_links_with_anchors};
|
||||
use crate::tpls::{load_tera, register_early_global_fns, register_tera_global_fns};
|
||||
use config::{get_config, Config, Taxonomy as TaxonomyConfig};
|
||||
use config::{get_config, Config};
|
||||
use errors::{bail, Error, Result};
|
||||
use front_matter::InsertAnchor;
|
||||
use library::{
|
||||
find_taxonomies, sort_actual_pages_by_date, Library, Page, Paginator, Section, Taxonomy,
|
||||
TaxonomyItem,
|
||||
};
|
||||
use library::{find_taxonomies, Library, Page, Paginator, Section, Taxonomy};
|
||||
use templates::render_redirect_template;
|
||||
use utils::fs::{copy_directory, create_directory, create_file, ensure_directory_exists};
|
||||
use utils::net::get_available_port;
|
||||
|
@ -50,23 +48,6 @@ pub struct Site {
|
|||
include_drafts: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||
struct SerializedFeedTaxonomyItem<'a> {
|
||||
name: &'a str,
|
||||
slug: &'a str,
|
||||
permalink: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> SerializedFeedTaxonomyItem<'a> {
|
||||
pub fn from_item(item: &'a TaxonomyItem) -> Self {
|
||||
SerializedFeedTaxonomyItem {
|
||||
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
|
||||
|
@ -533,7 +514,7 @@ impl Site {
|
|||
} else {
|
||||
library.pages_values()
|
||||
};
|
||||
self.render_feed(pages, None, &self.config.default_language, None)?;
|
||||
self.render_feed(pages, None, &self.config.default_language, |c| c)?;
|
||||
}
|
||||
|
||||
for lang in &self.config.languages {
|
||||
|
@ -542,7 +523,7 @@ 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())), &lang.code, None)?;
|
||||
self.render_feed(pages, Some(&PathBuf::from(lang.code.clone())), &lang.code, |c| c)?;
|
||||
}
|
||||
|
||||
self.render_404()?;
|
||||
|
@ -714,7 +695,12 @@ impl Site {
|
|||
} else {
|
||||
&self.config.default_language
|
||||
},
|
||||
Some((&taxonomy.kind, &item)),
|
||||
|mut context: Context| {
|
||||
context.insert("taxonomy", &taxonomy.kind);
|
||||
context
|
||||
.insert("term", &feed::SerializedFeedTaxonomyItem::from_item(item));
|
||||
context
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Ok(())
|
||||
|
@ -782,58 +768,15 @@ impl Site {
|
|||
all_pages: Vec<&Page>,
|
||||
base_path: Option<&PathBuf>,
|
||||
lang: &str,
|
||||
taxonomy_and_item: Option<(&TaxonomyConfig, &TaxonomyItem)>,
|
||||
additional_context_fn: impl Fn(Context) -> Context,
|
||||
) -> Result<()> {
|
||||
ensure_directory_exists(&self.output_path)?;
|
||||
|
||||
let mut context = Context::new();
|
||||
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
|
||||
if pages.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pages.par_sort_unstable_by(sort_actual_pages_by_date);
|
||||
|
||||
context.insert(
|
||||
"last_updated",
|
||||
pages
|
||||
.iter()
|
||||
.filter_map(|page| page.meta.updated.as_ref())
|
||||
.chain(pages[0].meta.date.as_ref())
|
||||
.max() // I love lexicographically sorted date strings
|
||||
.unwrap(), // Guaranteed because of pages[0].meta.date
|
||||
);
|
||||
let library = self.library.read().unwrap();
|
||||
// limit to the last n elements if the limit is set; otherwise use all.
|
||||
let num_entries = self.config.feed_limit.unwrap_or_else(|| pages.len());
|
||||
let p = pages
|
||||
.iter()
|
||||
.take(num_entries)
|
||||
.map(|x| x.to_serialized_basic(&library))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
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 {
|
||||
self.config
|
||||
.make_permalink(&base.join(feed_filename).to_string_lossy().replace('\\', "/"))
|
||||
} else {
|
||||
self.config.make_permalink(feed_filename)
|
||||
let feed = match render_feed(self, all_pages, lang, base_path, additional_context_fn)? {
|
||||
Some(v) => v,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
context.insert("feed_url", &feed_url);
|
||||
|
||||
if let Some((taxonomy, item)) = taxonomy_and_item {
|
||||
context.insert("taxonomy", taxonomy);
|
||||
context.insert("term", &SerializedFeedTaxonomyItem::from_item(item));
|
||||
}
|
||||
|
||||
let feed = &render_template(feed_filename, &self.tera, context, &self.config.theme)?;
|
||||
let feed_filename = &self.config.feed_filename;
|
||||
|
||||
if let Some(ref base) = base_path {
|
||||
let mut output_path = self.output_path.clone();
|
||||
|
@ -843,9 +786,9 @@ impl Site {
|
|||
create_directory(&output_path)?;
|
||||
}
|
||||
}
|
||||
create_file(&output_path.join(feed_filename), feed)?;
|
||||
create_file(&output_path.join(feed_filename), &feed)?;
|
||||
} else {
|
||||
create_file(&self.output_path.join(feed_filename), feed)?;
|
||||
create_file(&self.output_path.join(feed_filename), &feed)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -89,7 +89,8 @@ pub fn find_entries<'a>(
|
|||
if let Some(paginate_by) = section.paginate_by() {
|
||||
let number_pagers = (section.pages.len() as f64 / paginate_by as f64).ceil() as isize;
|
||||
for i in 1..=number_pagers {
|
||||
let permalink = format!("{}{}/{}/", section.permalink, section.meta.paginate_path, i);
|
||||
let permalink =
|
||||
format!("{}{}/{}/", section.permalink, section.meta.paginate_path, i);
|
||||
sections.push(SitemapEntry::new(Cow::Owned(permalink), None))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue