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_list_template: blog/list.tera
tag_list_template: basic-link-list.tera
rss_template: blog/rss.tera
rss_title: webdog blog
rss_description: feed of recent webdog blog posts.
rss:
template: blog/rss.tera
title: webdog blog
description: feed of recent webdog blog posts.
list_title: blog
tag_list_title: blog tags
resource_name_plural: blog posts

View file

@ -66,6 +66,9 @@ Arguments:
<ID> The resource type's ID
<NAME> The name of the resource type to create
<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`

View file

@ -73,17 +73,23 @@ the link to actually use for the link.
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.
this template is provided a single resource's properties as its properties.
### `rss_title`
#### `title`
the title for the resource type's rss feed.
### `rss_description`
#### `description`
the description for the resource type's rss feed.

View file

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

View file

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

View file

@ -6,7 +6,7 @@ use time::{format_description::well_known::Rfc3339, OffsetDateTime};
use url::Url;
use webdog::{
frontmatter::FrontMatter,
resource::{ResourceBuilderConfig, ResourceMetadata},
resource::{ResourceBuilderConfig, ResourceMetadata, ResourceRSSBuilderConfig},
PageMetadata, Site, SiteConfig,
};
@ -93,6 +93,9 @@ enum ResourceCommands {
name: String,
/// The name of the resource type, but plural.
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(())
}
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 mut config = SiteConfig::read(&cli.site)?;
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 {
source_path: id.clone(),
output_path_resources: id.clone(),
@ -203,9 +217,7 @@ fn main() -> eyre::Result<()> {
resource_template: format!("{id}/resource.tera"),
resource_list_template: format!("{id}/list.tera"),
tag_list_template: "basic-link-list.tera".to_string(),
rss_template: format!("{id}/rss.tera"),
rss_title: id.clone(),
rss_description: Default::default(),
rss,
list_title: name.clone(),
tag_list_title: format!("{name} tags"),
resource_name_plural: plural,

View file

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