Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let collections have custom titles and descriptions #261

Closed
wants to merge 11 commits into from
14 changes: 13 additions & 1 deletion README.md
Expand Up @@ -34,6 +34,8 @@ The plugin will automatically use any of the following configuration variables,
* `url` - The URL to your site, e.g., `https://example.com`. If none is provided, the plugin will try to use `site.github.url`.
* `author` - Global author information (see below)

If you configure additional collection feeds, this plugin can consume collection `title` and `description` variables, as well. See [Collections](#collections) for more information.

### Already have a feed path?

Do you already have an existing feed someplace other than `/feed.xml`, but are on a host like GitHub Pages that doesn't support machine-friendly redirects? If you simply swap out `jekyll-feed` for your existing template, your existing subscribers won't continue to get updates. Instead, you can specify a non-default path via your site's config.
Expand All @@ -59,7 +61,6 @@ The plugin will use the following post metadata, automatically generated by Jeky
Additionally, the plugin will use the following values, if present in a post's YAML front matter:

* `image` - URL of an image that is representative of the post (can also be passed as `image.path`)

* `author` - The author of the post, e.g., "Dr. Jekyll". If none is given, feed readers will look to the feed author as defined in `_config.yml`. Like the feed author, this can also be an object or a reference to an author in `_data/authors.yml` (see below).

### Author information
Expand Down Expand Up @@ -191,6 +192,17 @@ feed:
- updates
```

If your collections have `title` and `description` configuration variables set under the top-level `collections:` key, this plugin can consume those as well:

```yml
collections:
changes:
title: "Important News and Updates"
description: "Subscribe to this feed for exciting new changelogs."
```
benjaminwil marked this conversation as resolved.
Show resolved Hide resolved

This allows you to use your custom collection title and description globally – letting your RSS feed fields match your website frontend.

## Excerpt Only flag

Optional flag `excerpt_only` allows you to exclude post content from the Atom feed. Default value is `false` for backward compatibility.
Expand Down
18 changes: 9 additions & 9 deletions lib/jekyll-feed/feed.xml
Expand Up @@ -9,22 +9,22 @@
<updated>{{ site.time | date_to_xmlschema }}</updated>
<id>{{ page.url | absolute_url | xml_escape }}</id>

{% assign title = site.title | default: site.name %}
{% if page.collection != "posts" %}
{% assign collection = page.collection | capitalize %}
{% assign title = title | append: " | " | append: collection %}
{% if page.collection == "posts" %}
{% assign title = site.title | default: site.name %}
{% else %}
{% assign title = page.title | default: site.name %}
benjaminwil marked this conversation as resolved.
Show resolved Hide resolved
{% endif %}

{% if page.category %}
{% assign category = page.category | capitalize %}
{% assign title = title | append: " | " | append: category %}
{% endif %}

{% if title %}
<title type="html">{{ title | smartify | xml_escape }}</title>
{% endif %}
<title type="html">{{ title | smartify | xml_escape }}</title>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code here assumes that title variable is never falsey.
What about the situation where all of site.title, site.name and page.title are undefined or nil?


{% if site.description %}
<subtitle>{{ site.description | xml_escape }}</subtitle>
{% assign description = page.description | default: site.description %}
{% if description %}
<subtitle>{{ description | xml_escape }}</subtitle>
{% endif %}

{% if site.author %}
Expand Down
38 changes: 32 additions & 6 deletions lib/jekyll-feed/generator.rb
Expand Up @@ -33,6 +33,30 @@ def config
@config ||= @site.config["feed"] || {}
end

# Returns the metadata for the collection in the argument
def data_for_collection(name)
@site.collections[name].metadata
end
benjaminwil marked this conversation as resolved.
Show resolved Hide resolved

# Returns the configured title for the collection if defined. Otherwise, it
# returns a fallback value of "Site Name | Collection_name"
def title(collection_name)
return if collection_name == "posts"

data_for_collection(collection_name)["title"] || default_title(collection_name)
end

# Returns a default title of "Site Name | Collection_name"
def default_title(collection_name)
site_title = @site.config["title"] || @site.config["name"]
[site_title, collection_name.capitalize].join(" | ")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if @site.config["title"] and @site.config["name"] are both undefined / nil, then
[nil, "Posts"].join(" | ") is going to result in " | Posts"...
similarly, if one of them is an empty string ""..

end

# Returns the description YAML for a collection if defined.
def description(collection_name)
data_for_collection(collection_name)["description"]
end

# Determines the destination path of a given feed
#
# collection - the name of a collection, e.g., "posts"
Expand Down Expand Up @@ -116,12 +140,14 @@ def make_page(file_path, collection: "posts", category: nil, tags: nil)
PageWithoutAFile.new(@site, __dir__, "", file_path).tap do |file|
file.content = feed_template
file.data.merge!(
"layout" => nil,
"sitemap" => false,
"xsl" => file_exists?("feed.xslt.xml"),
"collection" => collection,
"category" => category,
"tags" => tags
"layout" => nil,
"sitemap" => false,
"xsl" => file_exists?("feed.xslt.xml"),
"title" => title(collection),
"description" => description(collection),
"collection" => collection,
"category" => category,
"tags" => tags
)
file.output
end
Expand Down
105 changes: 105 additions & 0 deletions spec/jekyll-feed_spec.rb
Expand Up @@ -231,6 +231,86 @@ def to_s
expect(feed.title.content).to eql(site_title.encode(xml: :text))
end
end

context "with collections.collection.title set" do
let(:page_title) { "A custom feed title" }
let(:overrides) do
{
"collections" => {
"collection" => {
"title" => page_title,
"output" => true,
},
},
"feed" => { "collections" => ["collection"] },
}
end
let(:collection_feed) { File.read(dest_dir("feed/collection.xml")) }

it "uses collections.collection.title for the feed title" do
expect(collection_feed).to match '<title type="html">A custom feed title</title>'
end
end

context "with collections.collection.title not set" do
let(:site_name) { "My Site Title" }
let(:collection_name) { "collection" }
let(:overrides) do
{
"title" => site_name,
"collections" => {
collection_name => {
"output" => true,
},
},
"feed" => { "collections" => ["collection"] },
}
end
let(:collection_feed) { File.read(dest_dir("feed/collection.xml")) }

it "uses default title for the feed title" do
default_title = [site_name, collection_name.capitalize ].join(" | ")
expect(collection_feed).to match "<title type=\"html\">#{default_title}</title>"
end
end

context "with 'posts' collection" do
let(:site_name) { "My Site Title" }
let(:overrides) do
{
"title" => site_name,
"collections" => {
"posts" => {
"output" => true
}
}
}
end

it "uses the site name as the feed title" do
expect(contents).to match '<title type="html">My Site Title</title>'
end
end

context "with collection.collection.description set" do
let(:page_description) { "A custom description of the collection feed." }
let(:overrides) do
{
"collections" => {
"collection" => {
"description" => page_description,
"output" => true,
},
},
"feed" => { "collections" => ["collection"] },
}
end
let(:collection_feed) { File.read(dest_dir("feed/collection.xml")) }

it "users collections.collection.description for the feed description" do
expect(collection_feed).to match "<subtitle>#{page_description}</subtitle>"
end
end
end

context "smartify" do
Expand Down Expand Up @@ -523,6 +603,31 @@ def to_s
expect(Pathname.new(dest_dir("feed/collection/news.xml"))).to exist
end
end

context "with collections.collection.title set" do
let(:overrides) do
{
"collections" => {
"collection" => {
"title" => "A custom feed title",
"output" => true,
},
},
"feed" => {
"collections" => {
"collection" => {
"categories" => ["news"],
},
},
},
}
end
let(:news_feed) { File.read(dest_dir("feed/collection/news.xml")) }

it "should use the title from the collection metadata and append the categories" do
expect(news_feed).to match '<title type="html">My custom feed title | News</title>'
end
end
end

context "tags" do
Expand Down