mirror of
https://github.com/zyllian/webdog.git
synced 2025-05-10 02:26:42 -07:00
make rss feeds optional for resources
This commit is contained in:
parent
95a0765b1e
commit
ddeb079d52
7 changed files with 101 additions and 65 deletions
|
@ -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
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -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,
|
||||||
|
|
106
src/resource.rs
106
src/resource.rs
|
@ -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,49 +417,51 @@ impl ResourceBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build RSS feed
|
// Build RSS feed
|
||||||
let mut items = Vec::with_capacity(data.len());
|
if let Some(rss) = &self.config.rss {
|
||||||
for resource in data {
|
let mut items = Vec::with_capacity(data.len());
|
||||||
items.push(
|
for resource in data {
|
||||||
ItemBuilder::default()
|
items.push(
|
||||||
.title(Some(resource.resource.data().title.to_owned()))
|
ItemBuilder::default()
|
||||||
.link(Some(
|
.title(Some(resource.resource.data().title.to_owned()))
|
||||||
builder
|
.link(Some(
|
||||||
.site
|
builder
|
||||||
.config
|
.site
|
||||||
.base_url
|
.config
|
||||||
.join(&format!(
|
.base_url
|
||||||
"{}/{}",
|
.join(&format!(
|
||||||
self.config.output_path_resources, resource.id
|
"{}/{}",
|
||||||
))?
|
self.config.output_path_resources, resource.id
|
||||||
.to_string(),
|
))?
|
||||||
))
|
.to_string(),
|
||||||
.description(resource.resource.data().desc.clone())
|
))
|
||||||
.pub_date(Some(resource.timestamp.format(&Rfc2822)?))
|
.description(resource.resource.data().desc.clone())
|
||||||
.content(Some(builder.tera.render(
|
.pub_date(Some(resource.timestamp.format(&Rfc2822)?))
|
||||||
&self.config.rss_template,
|
.content(Some(builder.tera.render(
|
||||||
&tera::Context::from_serialize(resource)?,
|
&rss.template,
|
||||||
)?))
|
&tera::Context::from_serialize(resource)?,
|
||||||
.build(),
|
)?))
|
||||||
)
|
.build(),
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let channel = ChannelBuilder::default()
|
let channel = ChannelBuilder::default()
|
||||||
.title(self.config.rss_title.clone())
|
.title(rss.title.clone())
|
||||||
.link(
|
.link(
|
||||||
builder
|
builder
|
||||||
.site
|
.site
|
||||||
.config
|
.config
|
||||||
.base_url
|
.base_url
|
||||||
.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(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue