make rss feeds optional for resources

This commit is contained in:
zyl 2024-11-13 13:11:37 -08:00
parent 95a0765b1e
commit ddeb079d52
Signed by: zyl
SSH key fingerprint: SHA256:uxxbSXbdroP/OnKBGnEDk5q7EKB2razvstC/KmzdXXs
7 changed files with 101 additions and 65 deletions

View file

@ -14,9 +14,10 @@ resources:
resource_template: blog/blog.tera resource_template: blog/blog.tera
resource_list_template: blog/list.tera resource_list_template: blog/list.tera
tag_list_template: basic-link-list.tera tag_list_template: basic-link-list.tera
rss_template: blog/rss.tera rss:
rss_title: webdog blog template: blog/rss.tera
rss_description: feed of recent webdog blog posts. title: webdog blog
description: feed of recent webdog blog posts.
list_title: blog list_title: blog
tag_list_title: blog tags tag_list_title: blog tags
resource_name_plural: blog posts resource_name_plural: blog posts

View file

@ -66,6 +66,9 @@ Arguments:
<ID> The resource type's ID <ID> The resource type's ID
<NAME> The name of the resource type to create <NAME> The name of the resource type to create
<PLURAL> The name of the resource type, but plural <PLURAL> The name of the resource type, but plural
Options:
--no-rss Whether to skip enabling RSS for this resource or not
``` ```
## `webdog page new` ## `webdog page new`

View file

@ -73,17 +73,23 @@ the link to actually use for the link.
the link's title. the link's title.
### `rss_template` ### `rss`
the resource type's rss info. if not present, no rss feed will be built.
consists of the following properties:
#### `template`
the template used to render the resource type's rss feed's html content. the template used to render the resource type's rss feed's html content.
this template is provided a single resource's properties as its properties. this template is provided a single resource's properties as its properties.
### `rss_title` #### `title`
the title for the resource type's rss feed. the title for the resource type's rss feed.
### `rss_description` #### `description`
the description for the resource type's rss feed. the description for the resource type's rss feed.

View file

@ -6,8 +6,10 @@
{% else %} {% else %}
<h1>blog Posts</h1> <h1>blog Posts</h1>
<p><a href="tags">view blog tags</a></p> <p><a href="tags">view blog tags</a></p>
{% if data.rss_enabled %}
<p><a href="rss.xml">rss feed</a></p> <p><a href="rss.xml">rss feed</a></p>
{% endif %} {% endif %}
{% endif %}
<h1>Page {{data.page}}/{{data.page_max}}</h1> <h1>Page {{data.page}}/{{data.page_max}}</h1>
{% if data.previous %} {% if data.previous %}
<a href="./{{data.previous}}">previous page</a> <a href="./{{data.previous}}">previous page</a>

View file

@ -1,22 +1,24 @@
{% extends "base.tera" %} {% extends "base.tera" %}
{% block content %} {% block content %}
{% if tag %} {% if data.tag %}
<h1>!!RESOURCE_NAME_PLURAL!! tagged {{ tag }}</h1> <h1>!!RESOURCE_NAME_PLURAL!! tagged {{ data.tag }}</h1>
<p><a href="/!!RESOURCE_TYPE!!/">View all !!RESOURCE_NAME_PLURAL_LOWERCASE!!</a></p> <p><a href="/!!RESOURCE_TYPE!!/">View all !!RESOURCE_NAME_PLURAL_LOWERCASE!!</a></p>
{% else %} {% else %}
<h1>!!RESOURCE_NAME_PLURAL!!</h1> <h1>!!RESOURCE_NAME_PLURAL!!</h1>
<p><a href="tags">view !!RESOURCE_NAME!! tags</a></p> <p><a href="tags">view !!RESOURCE_NAME!! tags</a></p>
{% if data.rss_enabled %}
<p><a href="rss.xml">rss feed</a></p> <p><a href="rss.xml">rss feed</a></p>
{% endif %} {% endif %}
<h1>Page {{ page }}/{{ page_max }}</h1> {% endif %}
<h1>Page {{ data.page }}/{{ data.page_max }}</h1>
{% if previous %} {% if previous %}
<a href="./{{previous}}">previous page</a> <a href="./{{data.previous}}">previous page</a>
{% endif %} {% endif %}
{% if next %} {% if next %}
<a href="./{{next}}">next page</a> <a href="./{{data.next}}">next page</a>
{% endif %} {% endif %}
<div> <div>
{% for resource in resources %} {% for resource in data.resources %}
<p><a href="/!!RESOURCE_TYPE!!/{{resource.id}}">{{ resource.title }}</a></p> <p><a href="/!!RESOURCE_TYPE!!/{{resource.id}}">{{ resource.title }}</a></p>
{% endfor %} {% endfor %}
</div> </div>

View file

@ -6,7 +6,7 @@ use time::{format_description::well_known::Rfc3339, OffsetDateTime};
use url::Url; use url::Url;
use webdog::{ use webdog::{
frontmatter::FrontMatter, frontmatter::FrontMatter,
resource::{ResourceBuilderConfig, ResourceMetadata}, resource::{ResourceBuilderConfig, ResourceMetadata, ResourceRSSBuilderConfig},
PageMetadata, Site, SiteConfig, PageMetadata, Site, SiteConfig,
}; };
@ -93,6 +93,9 @@ enum ResourceCommands {
name: String, name: String,
/// The name of the resource type, but plural. /// The name of the resource type, but plural.
plural: String, plural: String,
/// Whether to skip enabling RSS for this resource or not.
#[arg(long, default_value = "false")]
no_rss: bool,
}, },
} }
@ -163,7 +166,12 @@ fn main() -> eyre::Result<()> {
Ok(()) Ok(())
} }
Commands::Resource { command } => match command { Commands::Resource { command } => match command {
ResourceCommands::Create { id, name, plural } => { ResourceCommands::Create {
id,
name,
plural,
no_rss,
} => {
let config_path = cli.site.join(SiteConfig::FILENAME); let config_path = cli.site.join(SiteConfig::FILENAME);
let mut config = SiteConfig::read(&cli.site)?; let mut config = SiteConfig::read(&cli.site)?;
if config.resources.contains_key(&id) { if config.resources.contains_key(&id) {
@ -196,6 +204,12 @@ fn main() -> eyre::Result<()> {
} }
} }
let rss = (!no_rss).then(|| ResourceRSSBuilderConfig {
template: format!("{id}/rss.tera"),
title: id.clone(),
description: Default::default(),
});
let resource_config = ResourceBuilderConfig { let resource_config = ResourceBuilderConfig {
source_path: id.clone(), source_path: id.clone(),
output_path_resources: id.clone(), output_path_resources: id.clone(),
@ -203,9 +217,7 @@ fn main() -> eyre::Result<()> {
resource_template: format!("{id}/resource.tera"), resource_template: format!("{id}/resource.tera"),
resource_list_template: format!("{id}/list.tera"), resource_list_template: format!("{id}/list.tera"),
tag_list_template: "basic-link-list.tera".to_string(), tag_list_template: "basic-link-list.tera".to_string(),
rss_template: format!("{id}/rss.tera"), rss,
rss_title: id.clone(),
rss_description: Default::default(),
list_title: name.clone(), list_title: name.clone(),
tag_list_title: format!("{name} tags"), tag_list_title: format!("{name} tags"),
resource_name_plural: plural, resource_name_plural: plural,

View file

@ -113,6 +113,7 @@ impl EmbedMetadata {
struct ResourceListTemplateData<'r> { struct ResourceListTemplateData<'r> {
resources: Vec<&'r ResourceTemplateData<'r>>, resources: Vec<&'r ResourceTemplateData<'r>>,
tag: Option<&'r str>, tag: Option<&'r str>,
rss_enabled: bool,
page: usize, page: usize,
page_max: usize, page_max: usize,
previous: Option<usize>, previous: Option<usize>,
@ -134,12 +135,8 @@ pub struct ResourceBuilderConfig {
pub resource_list_template: String, pub resource_list_template: String,
/// The template used to render the resource's tag pages. /// The template used to render the resource's tag pages.
pub tag_list_template: String, pub tag_list_template: String,
/// Template used when rendering the RSS feed. /// The resource type's RSS info, if enabled.
pub rss_template: String, pub rss: Option<ResourceRSSBuilderConfig>,
/// The RSS feed's title.
pub rss_title: String,
/// The description for the RSS feed.
pub rss_description: String,
/// Title for the main list of resources. /// Title for the main list of resources.
pub list_title: String, pub list_title: String,
/// Title for the page containing a list of tags. /// Title for the page containing a list of tags.
@ -150,6 +147,16 @@ pub struct ResourceBuilderConfig {
pub resources_per_page: usize, pub resources_per_page: usize,
} }
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ResourceRSSBuilderConfig {
/// Template used when rendering the RSS feed.
pub template: String,
/// The RSS feed's title.
pub title: String,
/// The description for the RSS feed.
pub description: String,
}
/// Helper to genericize resource building. /// Helper to genericize resource building.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ResourceBuilder { pub struct ResourceBuilder {
@ -332,6 +339,7 @@ impl ResourceBuilder {
ResourceListTemplateData { ResourceListTemplateData {
resources: iter.copied().collect(), resources: iter.copied().collect(),
tag, tag,
rss_enabled: config.rss.is_some(),
page: page + 1, page: page + 1,
page_max, page_max,
previous, previous,
@ -409,6 +417,7 @@ impl ResourceBuilder {
} }
// Build RSS feed // Build RSS feed
if let Some(rss) = &self.config.rss {
let mut items = Vec::with_capacity(data.len()); let mut items = Vec::with_capacity(data.len());
for resource in data { for resource in data {
items.push( items.push(
@ -428,7 +437,7 @@ impl ResourceBuilder {
.description(resource.resource.data().desc.clone()) .description(resource.resource.data().desc.clone())
.pub_date(Some(resource.timestamp.format(&Rfc2822)?)) .pub_date(Some(resource.timestamp.format(&Rfc2822)?))
.content(Some(builder.tera.render( .content(Some(builder.tera.render(
&self.config.rss_template, &rss.template,
&tera::Context::from_serialize(resource)?, &tera::Context::from_serialize(resource)?,
)?)) )?))
.build(), .build(),
@ -436,7 +445,7 @@ impl ResourceBuilder {
} }
let channel = ChannelBuilder::default() let channel = ChannelBuilder::default()
.title(self.config.rss_title.clone()) .title(rss.title.clone())
.link( .link(
builder builder
.site .site
@ -445,13 +454,14 @@ impl ResourceBuilder {
.join(&format!("{}/", self.config.output_path_lists)) .join(&format!("{}/", self.config.output_path_lists))
.expect("Should never fail"), .expect("Should never fail"),
) )
.description(self.config.rss_description.clone()) .description(rss.description.clone())
.last_build_date(Some(OffsetDateTime::now_utc().format(&Rfc2822)?)) .last_build_date(Some(OffsetDateTime::now_utc().format(&Rfc2822)?))
.items(items) .items(items)
.build(); .build();
channel.validate().wrap_err("Failed to validate RSS feed")?; channel.validate().wrap_err("Failed to validate RSS feed")?;
let out = channel.to_string(); let out = channel.to_string();
std::fs::write(out_long.join("rss.xml"), out)?; std::fs::write(out_long.join("rss.xml"), out)?;
}
Ok(()) Ok(())
} }