jekyll-feed-0.13.0/ 0000755 0000041 0000041 00000000000 13565064320 014022 5 ustar www-data www-data jekyll-feed-0.13.0/.travis.yml 0000644 0000041 0000041 00000002364 13565064320 016140 0 ustar www-data www-data language: ruby
cache: bundler
rvm:
- &latest_ruby 2.6
- 2.4
- 2.3
env:
global:
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
matrix:
- JEKYLL_VERSION="~> 3.8"
matrix:
include:
- rvm: *latest_ruby
env: JEKYLL_VERSION="~> 3.7.4"
- rvm: *latest_ruby
env: JEKYLL_VERSION=">= 4.0.0.pre.alpha1"
before_install:
- gem update --system
- gem install bundler
before_script: bundle update
script: script/cibuild
notifications:
email: false
deploy:
provider: rubygems
api_key:
secure: qz0q6ur0kGo03jjLdoAak6WcEAwxX2r9LG3DVrhOrcfoFipkuW+uwR0et4tpK8uFrz0P9y7eTIKOb0XCXeIsIXWj6R5benpRGr2U8m9A+tE/jxviBFUaxaokte0lqWiX1fEyhRmW3zvcdLQ47Vd2EwTNaq6ZmPulmEe9gS0rBQghyclakGlZ17LI7oGgiNL9SQ335Yqa1qJklTHYHbodWQ3Z07v7VN2jxqi3WH6NacT5gUGp5iCNCLLa8+jpKr4uONNIoy6/geAWdqtvgGUE8oTjIWDoJarrknJpqfx9Rd0KLDzkyneAigHDYPW60QtrE6GGpK/+TF1pF4DzdK2EgTWqGFnZf8ehfnxmtHVl2Xq/DPr6hS8Q/f+ut4ioMzBQxPD0hfh8/EOMYKsO8mOuOlYTiZXC7iuGyvFUOl2hnBgWA99t+I0NNB06qFp3ZxIjolEc3zjzc9f1a5HUXlEut5V8nqvCwbctNiTVpT8ZEWlsQlyRUnr9cIMUTEfLgQ+v6DnvAJBMO1EILq6liB5qfutjNhzhlREt7P/ZdppGsAzWpgt0q2PafqVoPe62WR3+/8Lj2ErMr034xSSqZVNcBS0mbdvW6k3jaABo1VJ4XuHm6/yDuemWzWb7kdG9/14+IIJMW1VuaWcmnCnB6gxjkCW3Dm2ftYiN7Rfn3AUz/nU=
gem: jekyll-feed
on:
tags: true
repo: jekyll/jekyll-feed
jekyll-feed-0.13.0/.rspec 0000644 0000041 0000041 00000000032 13565064320 015132 0 ustar www-data www-data --color
--format progress
jekyll-feed-0.13.0/README.md 0000644 0000041 0000041 00000015663 13565064320 015314 0 ustar www-data www-data # Jekyll Feed plugin
A Jekyll plugin to generate an Atom (RSS-like) feed of your Jekyll posts
[](https://travis-ci.org/jekyll/jekyll-feed) [](https://badge.fury.io/rb/jekyll-feed)
## Installation
Add this line to your site's Gemfile:
```ruby
gem 'jekyll-feed'
```
And then add this line to your site's `_config.yml`:
```yml
plugins:
- jekyll-feed
```
:warning: If you are using Jekyll < 3.5.0 use the `gems` key instead of `plugins`.
## Usage
The plugin will automatically generate an Atom feed at `/feed.xml`.
### Optional configuration options
The plugin will automatically use any of the following configuration variables, if they are present in your site's `_config.yml` file.
* `title` or `name` - The title of the site, e.g., "My awesome site"
* `description` - A longer description of what your site is about, e.g., "Where I blog about Jekyll and other awesome things"
* `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)
### 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.
```yml
feed:
path: atom.xml
```
To note, you shouldn't have to do this unless you already have a feed you're using, and you can't or wish not to redirect existing subscribers.
### Optional front matter
The plugin will use the following post metadata, automatically generated by Jekyll, which you can override via a post's YAML front matter:
* `date`
* `title`
* `excerpt`
* `id`
* `category`
* `tags`
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
*TL;DR: In most cases, put `author: [your name]` in the document's front matter, for sites with multiple authors. If you need something more complicated, read on.*
There are several ways to convey author-specific information. Author information is found in the following order of priority:
1. An `author` object, in the documents's front matter, e.g.:
```yml
author:
twitter: benbalter
```
2. An `author` object, in the site's `_config.yml`, e.g.:
```yml
author:
twitter: benbalter
```
3. `site.data.authors[author]`, if an author is specified in the document's front matter, and a corresponding key exists in `site.data.authors`. E.g., you have the following in the document's front matter:
```yml
author: benbalter
```
And you have the following in `_data/authors.yml`:
```yml
benbalter:
picture: /img/benbalter.png
twitter: jekyllrb
potus:
picture: /img/potus.png
twitter: whitehouse
```
In the above example, the author `benbalter`'s Twitter handle will be resolved to `@jekyllrb`. This allows you to centralize author information in a single `_data/authors` file for site with many authors that require more than just the author's username.
*Pro-tip: If `authors` is present in the document's front matter as an array (and `author` is not), the plugin will use the first author listed.*
4. An author in the document's front matter (the simplest way), e.g.:
```yml
author: benbalter
```
5. An author in the site's `_config.yml`, e.g.:
```yml
author: benbalter
```
### Meta tags
The plugin exposes a helper tag to expose the appropriate meta tags to support automated discovery of your feed. Simply place `{% feed_meta %}` someplace in your template's `
` section, to output the necessary metadata.
### SmartyPants
The plugin uses [Jekyll's `smartify` filter](https://jekyllrb.com/docs/templates/) for processing the site title and post titles. This will translate plain ASCII punctuation into "smart" typographic punctuation. This will not render or strip any Markdown you may be using in a title.
Jekyll's `smartify` filter uses [kramdown](https://kramdown.gettalong.org/options.html) as a processor. Accordingly, if you do not want "smart" typographic punctuation, disabling them in kramdown in your `_config.yml` will disable them in your feed. For example:
```yml
kramdown:
smart_quotes: apos,apos,quot,quot
typographic_symbols: {hellip: ...}
```
### Custom styling
Want to style what your feed looks like in the browser? Simply add an XSLT at `/feed.xslt.xml` and Jekyll Feed will link to the stylesheet.
## Why Atom, and not RSS?
Great question. In short, Atom is a better format. Think of it like RSS 3.0. For more information, see [this discussion on why we chose Atom over RSS 2.0](https://github.com/jekyll/jekyll-rss-feed/issues/2).
## Categories
Jekyll Feed can generate feeds for each category. Simply define which categories you'd like feeds for in your config:
```yml
feed:
categories:
- news
- updates
```
## Collections
Jekyll Feed can generate feeds for collections other than the Posts collection. This works best for chronological collections (e.g., collections with dates in the filenames). Simply define which collections you'd like feeds for in your config:
```yml
feed:
collections:
- changes
```
By default, collection feeds will be outputted to `/feed/.xml`. If you'd like to customize the output path, specify a collection's custom path as follows:
```yml
feed:
collections:
changes:
path: "/changes.xml"
```
Finally, collections can also have category feeds which are outputted as `/feed//.xml`. Specify categories like so:
```yml
feed:
collections:
changes:
path: "/changes.xml"
categories:
- news
- updates
```
## Excerpt Only flag
Optional flag `excerpt_only` allows you to exclude post content from the Atom feed. Default value is `false` for backward compatibility.
When in `config.yml` is `true` than all posts in feed will be without `` tags.
```yml
feed:
excerpt_only: true
```
The same flag can be used directly in post file. It will be disable `` tag for selected post.
Settings in post file has higher priority than in config file.
## Contributing
1. Fork it (https://github.com/jekyll/jekyll-feed/fork)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
jekyll-feed-0.13.0/spec/ 0000755 0000041 0000041 00000000000 13565064320 014754 5 ustar www-data www-data jekyll-feed-0.13.0/spec/jekyll-feed_spec.rb 0000644 0000041 0000041 00000043404 13565064320 020513 0 ustar www-data www-data # frozen_string_literal: true
require "spec_helper"
describe(JekyllFeed) do
let(:overrides) { {} }
let(:config) do
Jekyll.configuration(Jekyll::Utils.deep_merge_hashes({
"full_rebuild" => true,
"source" => source_dir,
"destination" => dest_dir,
"show_drafts" => true,
"url" => "http://example.org",
"name" => "My awesome site",
"author" => {
"name" => "Dr. Jekyll",
},
"collections" => {
"my_collection" => { "output" => true },
"other_things" => { "output" => false },
},
}, overrides))
end
let(:site) { Jekyll::Site.new(config) }
let(:contents) { File.read(dest_dir("feed.xml")) }
let(:context) { make_context(:site => site) }
let(:feed_meta) { Liquid::Template.parse("{% feed_meta %}").render!(context, {}) }
before(:each) do
site.process
end
it "has no layout" do
expect(contents).not_to match(%r!\ATHIS IS MY LAYOUT!)
end
it "creates a feed.xml file" do
expect(Pathname.new(dest_dir("feed.xml"))).to exist
end
it "doesn't have multiple new lines or trailing whitespace" do
expect(contents).to_not match %r!\s+\n!
expect(contents).to_not match %r!\n{2,}!
end
it "puts all the posts in the feed.xml file" do
expect(contents).to match "http://example.org/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(contents).to match "http://example.org/news/2014/03/02/march-the-second.html"
expect(contents).to match "http://example.org/news/2013/12/12/dec-the-second.html"
expect(contents).to match "http://example.org/2015/08/08/stuck-in-the-middle.html"
expect(contents).to_not match "http://example.org/2016/02/09/a-draft.html"
end
it "does not include assets or any static files that aren't .html" do
expect(contents).not_to match "http://example.org/images/hubot.png"
expect(contents).not_to match "http://example.org/feeds/atom.xml"
end
it "preserves linebreaks in preformatted text in posts" do
expect(contents).to match "Line 1\nLine 2\nLine 3"
end
it "supports post author name as an object" do
expect(contents).to match %r!\s*Ben\s*ben@example\.com\s*http://ben\.balter\.com\s*!
end
it "supports post author name as a string" do
expect(contents).to match %r!\s*Pat\s*!
end
it "does not output author tag no author is provided" do
expect(contents).not_to match %r!\s*\s*!
end
it "does use author reference with data from _data/authors.yml" do
expect(contents).to match %r!\s*Garth\s*example@mail\.com\s*http://garthdb\.com\s*!
end
it "converts markdown posts to HTML" do
expect(contents).to match %r!<p>March the second\!</p>!
end
it "uses last_modified_at where available" do
expect(contents).to match %r!2015-05-12T13:27:59\+00:00!
end
it "replaces newlines in posts to spaces" do
expect(contents).to match 'The plugin will properly strip newlines.'
end
it "renders Liquid inside posts" do
expect(contents).to match "Liquid is rendered."
expect(contents).not_to match "Liquid is not rendered."
end
context "images" do
let(:image1) { 'http://example.org/image.png' }
let(:image2) { 'https://cdn.example.org/absolute.png?h=188&w=250' }
let(:image3) { 'http://example.org/object-image.png' }
it "includes the item image" do
expect(contents).to include(%())
expect(contents).to include(%())
expect(contents).to include(%())
end
it "included media content for mail templates (Mailchimp)" do
expect(contents).to include(%())
expect(contents).to include(%())
expect(contents).to include(%())
end
end
context "parsing" do
let(:feed) { RSS::Parser.parse(contents) }
it "outputs an RSS feed" do
expect(feed.feed_type).to eql("atom")
expect(feed.feed_version).to eql("1.0")
expect(feed.encoding).to eql("UTF-8")
expect(feed.lang).to be_nil
expect(feed.valid?).to eql(true)
end
it "outputs the link" do
expect(feed.link.href).to eql("http://example.org/feed.xml")
end
it "outputs the generator" do
expect(feed.generator.content).to eql("Jekyll")
expect(feed.generator.version).to eql(Jekyll::VERSION)
end
it "includes the items" do
expect(feed.items.count).to eql(10)
end
it "includes item contents" do
post = feed.items.last
expect(post.title.content).to eql("Dec The Second")
expect(post.link.href).to eql("http://example.org/news/2013/12/12/dec-the-second.html")
expect(post.published.content).to eql(Time.parse("2013-12-12"))
end
it "includes the item's excerpt" do
post = feed.items.last
expect(post.summary.content).to eql("Foo")
end
it "doesn't include the item's excerpt if blank" do
post = feed.items.first
expect(post.summary).to be_nil
end
context "with site.lang set" do
lang = "en_US"
let(:overrides) { { "lang" => lang } }
it "outputs a valid feed" do
expect(feed.feed_type).to eql("atom")
expect(feed.feed_version).to eql("1.0")
expect(feed.encoding).to eql("UTF-8")
expect(feed.valid?).to eql(true)
end
it "outputs the correct language" do
expect(feed.lang).to eql(lang)
end
it "sets the language of entries" do
post = feed.items.first
expect(post.lang).to eql(lang)
end
it "renders the feed meta" do
expected = %r!!
expect(contents).to match(expected)
end
end
context "with site.title set" do
let(:site_title) { "My Site Title" }
let(:overrides) { { "title" => site_title } }
it "uses site.title for the title" do
expect(feed.title.content).to eql(site_title)
end
end
context "with site.name set" do
let(:site_name) { "My Site Name" }
let(:overrides) { { "name" => site_name } }
it "uses site.name for the title" do
expect(feed.title.content).to eql(site_name)
end
end
context "with site.name and site.title set" do
let(:site_title) { "My Site Title" }
let(:site_name) { "My Site Name" }
let(:overrides) { { "title" => site_title, "name" => site_name } }
it "uses site.title for the title, dropping site.name" do
expect(feed.title.content).to eql(site_title)
end
end
end
context "smartify" do
let(:site_title) { "Pat's Site" }
let(:overrides) { { "title" => site_title } }
let(:feed) { RSS::Parser.parse(contents) }
it "processes site title with SmartyPants" do
expect(feed.title.content).to eql("Pat’s Site")
end
end
context "validation" do
it "validates" do
skip "Typhoeus couldn't find the 'libcurl' module on Windows" if Gem.win_platform?
# See https://validator.w3.org/docs/api.html
url = "https://validator.w3.org/feed/check.cgi?output=soap12"
response = Typhoeus.post(url, :body => { :rawdata => contents }, :accept_encoding => "gzip")
pending "Something went wrong with the W3 validator" unless response.success?
result = Nokogiri::XML(response.body)
result.remove_namespaces!
result.css("warning").each do |warning|
# Quiet a warning that results from us passing the feed as a string
next if warning.css("text").text =~ %r!Self reference doesn't match document location!
# Quiet expected warning that results from blank summary test case
next if warning.css("text").text =~ %r!(content|summary) should not be blank!
# Quiet expected warning about multiple posts with same updated time
next if warning.css("text").text =~ %r!Two entries with the same value for atom:updated!
warn "Validation warning: #{warning.css("text").text} on line #{warning.css("line").text} column #{warning.css("column").text}"
end
errors = result.css("error").map do |error|
"Validation error: #{error.css("text").text} on line #{error.css("line").text} column #{error.css("column").text}"
end
expect(result.css("validity").text).to eql("true"), errors.join("\n")
end
end
context "with a baseurl" do
let(:overrides) do
{ "baseurl" => "/bass" }
end
it "correctly adds the baseurl to the posts" do
expect(contents).to match "http://example.org/bass/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(contents).to match "http://example.org/bass/news/2014/03/02/march-the-second.html"
expect(contents).to match "http://example.org/bass/news/2013/12/12/dec-the-second.html"
end
it "renders the feed meta" do
expected = 'href="http://example.org/bass/feed.xml"'
expect(feed_meta).to include(expected)
end
end
context "feed meta" do
it "renders the feed meta" do
expected = ''
expect(feed_meta).to eql(expected)
end
context "with a blank site name" do
let(:config) do
Jekyll.configuration(
"source" => source_dir,
"destination" => dest_dir,
"url" => "http://example.org"
)
end
it "does not output blank title" do
expect(feed_meta).not_to include("title=")
end
end
end
context "changing the feed path" do
let(:overrides) do
{
"feed" => {
"path" => "atom.xml",
},
}
end
it "should write to atom.xml" do
expect(Pathname.new(dest_dir("atom.xml"))).to exist
end
it "renders the feed meta with custom feed path" do
expected = 'href="http://example.org/atom.xml"'
expect(feed_meta).to include(expected)
end
end
context "changing the file path via collection meta" do
let(:overrides) do
{
"feed" => {
"collections" => {
"posts" => {
"path" => "atom.xml",
},
},
},
}
end
it "should write to atom.xml" do
expect(Pathname.new(dest_dir("atom.xml"))).to exist
end
it "renders the feed meta with custom feed path" do
expected = 'href="http://example.org/atom.xml"'
expect(feed_meta).to include(expected)
end
end
context "feed stylesheet" do
it "includes the stylesheet" do
expect(contents).to include('')
end
end
context "with site.lang set" do
let(:overrides) { { "lang" => "en-US" } }
it "should set the language" do
expect(contents).to match 'type="text/html" hreflang="en-US" />'
end
end
context "with post.lang set" do
it "should set the language for that entry" do
expect(contents).to match ''
expect(contents).to match ''
end
end
context "categories" do
context "with top-level post categories" do
let(:overrides) do
{
"feed" => { "categories" => ["news"] },
}
end
let(:news_feed) { File.read(dest_dir("feed/news.xml")) }
it "outputs the primary feed" do
expect(contents).to match "http://example.org/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(contents).to match "http://example.org/news/2014/03/02/march-the-second.html"
expect(contents).to match "http://example.org/news/2013/12/12/dec-the-second.html"
expect(contents).to match "http://example.org/2015/08/08/stuck-in-the-middle.html"
expect(contents).to_not match "http://example.org/2016/02/09/a-draft.html"
end
it "outputs the category feed" do
expect(news_feed).to match 'My awesome site | News'
expect(news_feed).to match "http://example.org/news/2014/03/02/march-the-second.html"
expect(news_feed).to match "http://example.org/news/2013/12/12/dec-the-second.html"
expect(news_feed).to_not match "http://example.org/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(news_feed).to_not match "http://example.org/2015/08/08/stuck-in-the-middle.html"
end
end
context "with collection-level post categories" do
let(:overrides) do
{
"feed" => {
"collections" => {
"posts" => {
"categories" => ["news"],
},
},
},
}
end
let(:news_feed) { File.read(dest_dir("feed/news.xml")) }
it "outputs the primary feed" do
expect(contents).to match "http://example.org/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(contents).to match "http://example.org/news/2014/03/02/march-the-second.html"
expect(contents).to match "http://example.org/news/2013/12/12/dec-the-second.html"
expect(contents).to match "http://example.org/2015/08/08/stuck-in-the-middle.html"
expect(contents).to_not match "http://example.org/2016/02/09/a-draft.html"
end
it "outputs the category feed" do
expect(news_feed).to match 'My awesome site | News'
expect(news_feed).to match "http://example.org/news/2014/03/02/march-the-second.html"
expect(news_feed).to match "http://example.org/news/2013/12/12/dec-the-second.html"
expect(news_feed).to_not match "http://example.org/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(news_feed).to_not match "http://example.org/2015/08/08/stuck-in-the-middle.html"
end
end
end
context "collections" do
let(:collection_feed) { File.read(dest_dir("feed/collection.xml")) }
context "when initialized as an array" do
let(:overrides) do
{
"collections" => {
"collection" => {
"output" => true,
},
},
"feed" => { "collections" => ["collection"] },
}
end
it "outputs the collection feed" do
expect(collection_feed).to match 'My awesome site | Collection'
expect(collection_feed).to match "http://example.org/collection/2018-01-01-collection-doc.html"
expect(collection_feed).to match "http://example.org/collection/2018-01-02-collection-category-doc.html"
expect(collection_feed).to_not match "http://example.org/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(collection_feed).to_not match "http://example.org/2015/08/08/stuck-in-the-middle.html"
end
end
context "with categories" do
let(:overrides) do
{
"collections" => {
"collection" => {
"output" => true,
},
},
"feed" => {
"collections" => {
"collection" => {
"categories" => ["news"],
},
},
},
}
end
let(:news_feed) { File.read(dest_dir("feed/collection/news.xml")) }
it "outputs the collection category feed" do
expect(news_feed).to match 'My awesome site | Collection | News'
expect(news_feed).to match "http://example.org/collection/2018-01-02-collection-category-doc.html"
expect(news_feed).to_not match "http://example.org/collection/2018-01-01-collection-doc.html"
expect(news_feed).to_not match "http://example.org/updates/jekyll/2014/03/04/march-the-fourth.html"
expect(news_feed).to_not match "http://example.org/2015/08/08/stuck-in-the-middle.html"
end
end
context "with a custom path" do
let(:overrides) do
{
"collections" => {
"collection" => {
"output" => true,
},
},
"feed" => {
"collections" => {
"collection" => {
"categories" => ["news"],
"path" => "custom.xml",
},
},
},
}
end
it "should write to the custom path" do
expect(Pathname.new(dest_dir("custom.xml"))).to exist
expect(Pathname.new(dest_dir("feed/collection.xml"))).to_not exist
expect(Pathname.new(dest_dir("feed/collection/news.xml"))).to exist
end
end
end
context "excerpt_only flag" do
context "backward compatibility for no excerpt_only flag" do
it "should be in contents" do
expect(contents).to match ' { "excerpt_only" => true } }
end
it "should not set any contents" do
expect(contents).to_not match ' { "excerpt_only" => false } }
end
it "should be in contents" do
expect(contents).to match ' { "excerpt_only" => false } }
end
it "should not be in contents" do
expect(contents).to_not match "This content should not be in feed."
end
end
end
end
jekyll-feed-0.13.0/spec/fixtures/ 0000755 0000041 0000041 00000000000 13565064320 016625 5 ustar www-data www-data jekyll-feed-0.13.0/spec/fixtures/_layouts/ 0000755 0000041 0000041 00000000000 13565064320 020464 5 ustar www-data www-data jekyll-feed-0.13.0/spec/fixtures/_layouts/some_default.html 0000644 0000041 0000041 00000000161 13565064320 024017 0 ustar www-data www-data ---
---
{% feed_meta %}
THIS IS MY LAYOUT
{{ content }}
jekyll-feed-0.13.0/spec/fixtures/_config.yml 0000644 0000041 0000041 00000000160 13565064320 020751 0 ustar www-data www-data timezone: UTC
defaults:
-
scope:
path: ""
type: pages
values:
layout: some_default
jekyll-feed-0.13.0/spec/fixtures/_drafts/ 0000755 0000041 0000041 00000000000 13565064320 020247 5 ustar www-data www-data jekyll-feed-0.13.0/spec/fixtures/_drafts/2015-01-12-a-draft.md 0000644 0000041 0000041 00000000032 13565064320 023125 0 ustar www-data www-data ---
---
This is a draft.
jekyll-feed-0.13.0/spec/fixtures/_data/ 0000755 0000041 0000041 00000000000 13565064320 017675 5 ustar www-data www-data jekyll-feed-0.13.0/spec/fixtures/_data/authors.yml 0000644 0000041 0000041 00000000140 13565064320 022100 0 ustar www-data www-data garthdb:
name: Garth
twitter: garthdb
uri: "http://garthdb.com"
email: example@mail.com
jekyll-feed-0.13.0/spec/fixtures/_collection/ 0000755 0000041 0000041 00000000000 13565064320 021117 5 ustar www-data www-data jekyll-feed-0.13.0/spec/fixtures/_collection/2018-01-02-collection-category-doc.md 0000644 0000041 0000041 00000000110 13565064320 027167 0 ustar www-data www-data ---
category: news
---
Look at me! I'm a collection doc in a category!
jekyll-feed-0.13.0/spec/fixtures/_collection/2018-01-01-collection-doc.md 0000644 0000041 0000041 00000000047 13565064320 025364 0 ustar www-data www-data ---
---
Look at me! I'm a collection!
jekyll-feed-0.13.0/spec/fixtures/feed.xslt.xml 0000644 0000041 0000041 00000000000 13565064320 021231 0 ustar www-data www-data jekyll-feed-0.13.0/spec/fixtures/_posts/ 0000755 0000041 0000041 00000000000 13565064320 020134 5 ustar www-data www-data jekyll-feed-0.13.0/spec/fixtures/_posts/2015-05-12-liquid.md 0000644 0000041 0000041 00000000164 13565064320 022775 0 ustar www-data www-data ---
---
{% capture liquidstring %}
Liquid is not rendered.
{% endcapture %}
{{ liquidstring | replace:'not ','' }}
jekyll-feed-0.13.0/spec/fixtures/_posts/2015-02-12-strip-newlines.md 0000644 0000041 0000041 00000000104 13565064320 024460 0 ustar www-data www-data ---
title:
The plugin
will properly
strip newlines.
---
jekyll-feed-0.13.0/spec/fixtures/_posts/2015-05-12-pre.html 0000644 0000041 0000041 00000000076 13565064320 022642 0 ustar www-data www-data ---
author: Pat
lang: en
---
Line 1
Line 2
Line 3
jekyll-feed-0.13.0/spec/fixtures/_posts/2015-05-18-author-detail.md 0000644 0000041 0000041 00000000203 13565064320 024250 0 ustar www-data www-data ---
excerpt: ""
author:
name: Ben
uri: "http://ben.balter.com"
email: ben@example.com
---
# December the twelfth, actually.
jekyll-feed-0.13.0/spec/fixtures/_posts/2013-12-12-dec-the-second.md 0000644 0000041 0000041 00000000135 13565064320 024262 0 ustar www-data www-data ---
excerpt: "Foo"
image: "/image.png"
category: news
---
# December the twelfth, actually.
jekyll-feed-0.13.0/spec/fixtures/_posts/2014-03-04-march-the-fourth.md 0000644 0000041 0000041 00000000157 13565064320 024663 0 ustar www-data www-data ---
tags:
- '"/>'
image:
path: "/object-image.png"
categories: updates jekyll
---
March the fourth!
jekyll-feed-0.13.0/spec/fixtures/_posts/2015-01-18-jekyll-last-modified-at.md 0000644 0000041 0000041 00000000165 13565064320 026124 0 ustar www-data www-data ---
last_modified_at: 2015-05-12T13:27:59+00:00
---
Please don't modify this file. It's modified time is important.
jekyll-feed-0.13.0/spec/fixtures/_posts/2015-08-08-stuck-in-the-middle.html 0000644 0000041 0000041 00000000110 13565064320 025620 0 ustar www-data www-data ---
feed:
excerpt_only: true
---
This content should not be in feed.
jekyll-feed-0.13.0/spec/fixtures/_posts/2016-04-25-author-reference.md 0000644 0000041 0000041 00000000077 13565064320 024753 0 ustar www-data www-data ---
excerpt: ""
author: garthdb
---
# April the twenty-fifth?
jekyll-feed-0.13.0/spec/fixtures/_posts/2014-03-02-march-the-second.md 0000644 0000041 0000041 00000000142 13565064320 024617 0 ustar www-data www-data ---
image: https://cdn.example.org/absolute.png?h=188&w=250
category: news
---
March the second!
jekyll-feed-0.13.0/spec/spec_helper.rb 0000644 0000041 0000041 00000001267 13565064320 017600 0 ustar www-data www-data # frozen_string_literal: true
require "jekyll"
require "typhoeus" unless Gem.win_platform?
require "nokogiri"
require "rss"
require File.expand_path("../lib/jekyll-feed", __dir__)
Jekyll.logger.log_level = :error
RSpec.configure do |config|
config.run_all_when_everything_filtered = true
config.filter_run :focus
config.order = "random"
SOURCE_DIR = File.expand_path("fixtures", __dir__)
DEST_DIR = File.expand_path("dest", __dir__)
def source_dir(*files)
File.join(SOURCE_DIR, *files)
end
def dest_dir(*files)
File.join(DEST_DIR, *files)
end
def make_context(registers = {})
Liquid::Context.new({}, {}, { :site => site }.merge(registers))
end
end
jekyll-feed-0.13.0/.rubocop.yml 0000644 0000041 0000041 00000000644 13565064320 016300 0 ustar www-data www-data require: rubocop-jekyll
inherit_gem:
rubocop-jekyll: .rubocop.yml
AllCops:
TargetRubyVersion: 2.3
Include:
- lib/**/*.rb
Exclude:
- .gitignore
- .rspec
- .rubocop.yml
- .travis.yml
- Gemfile.lock
- History.markdown
- LICENSE.txt
- README.md
- script/**/*
- vendor/**/*
Naming/MemoizedInstanceVariableName:
Exclude:
- lib/jekyll-feed/page-without-a-file.rb
jekyll-feed-0.13.0/jekyll-feed.gemspec 0000644 0000041 0000041 00000002116 13565064320 017562 0 ustar www-data www-data # frozen_string_literal: true
lib = File.expand_path("lib", __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "jekyll-feed/version"
Gem::Specification.new do |spec|
spec.name = "jekyll-feed"
spec.version = Jekyll::Feed::VERSION
spec.authors = ["Ben Balter"]
spec.email = ["ben.balter@github.com"]
spec.summary = "A Jekyll plugin to generate an Atom feed of your Jekyll posts"
spec.homepage = "https://github.com/jekyll/jekyll-feed"
spec.license = "MIT"
spec.files = `git ls-files -z`.split("\x0")
spec.test_files = spec.files.grep(%r!^spec/!)
spec.require_paths = ["lib"]
spec.required_ruby_version = ">= 2.3.0"
spec.add_dependency "jekyll", ">= 3.7", "< 5.0"
spec.add_development_dependency "bundler"
spec.add_development_dependency "nokogiri", "~> 1.6"
spec.add_development_dependency "rake", "~> 12.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency "rubocop-jekyll", "~> 0.5"
spec.add_development_dependency "typhoeus", ">= 0.7", "< 2.0"
end
jekyll-feed-0.13.0/.gitignore 0000644 0000041 0000041 00000000336 13565064320 016014 0 ustar www-data www-data /vendor
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
*.bundle
*.so
*.o
*.a
mkmf.log
*.gem
Gemfile.lock
spec/dest
.bundle
spec/fixtures/.jekyll-metadata
spec/fixtures/.jekyll-cache
jekyll-feed-0.13.0/script/ 0000755 0000041 0000041 00000000000 13565064320 015326 5 ustar www-data www-data jekyll-feed-0.13.0/script/test 0000755 0000041 0000041 00000000054 13565064320 016232 0 ustar www-data www-data #!/bin/bash
set -ex
bundle exec rspec "$@"
jekyll-feed-0.13.0/script/release 0000755 0000041 0000041 00000000125 13565064320 016672 0 ustar www-data www-data #!/bin/sh
# Tag and push a release.
set -e
script/cibuild
bundle exec rake release
jekyll-feed-0.13.0/script/cibuild 0000755 0000041 0000041 00000000104 13565064320 016662 0 ustar www-data www-data #! /bin/bash
set -e
script/test
script/fmt
bundle exec rake build
jekyll-feed-0.13.0/script/bootstrap 0000755 0000041 0000041 00000000035 13565064320 017267 0 ustar www-data www-data #! /bin/bash
bundle install
jekyll-feed-0.13.0/script/fmt 0000755 0000041 0000041 00000000340 13565064320 016037 0 ustar www-data www-data #!/bin/bash
set -e
echo "Rubocop $(bundle exec rubocop --version)"
bundle exec rubocop -D -E $@
success=$?
if ((success != 0)); then
echo -e "\nTry running \`script/fmt -a\` to automatically fix errors"
fi
exit $success
jekyll-feed-0.13.0/Rakefile 0000644 0000041 0000041 00000000224 13565064320 015465 0 ustar www-data www-data # frozen_string_literal: true
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
task :default => :spec
jekyll-feed-0.13.0/lib/ 0000755 0000041 0000041 00000000000 13565064320 014570 5 ustar www-data www-data jekyll-feed-0.13.0/lib/jekyll-feed/ 0000755 0000041 0000041 00000000000 13565064320 016763 5 ustar www-data www-data jekyll-feed-0.13.0/lib/jekyll-feed/version.rb 0000644 0000041 0000041 00000000134 13565064320 020773 0 ustar www-data www-data # frozen_string_literal: true
module Jekyll
module Feed
VERSION = "0.13.0"
end
end
jekyll-feed-0.13.0/lib/jekyll-feed/feed.xml 0000644 0000041 0000041 00000010340 13565064320 020406 0 ustar www-data www-data
{% if page.xsl %}
{% endif %}
Jekyll{{ site.time | date_to_xmlschema }}{{ page.url | absolute_url | xml_escape }}
{% assign title = site.title | default: site.name %}
{% if page.collection != "posts" %}
{% assign collection = page.collection | capitalize %}
{% assign title = title | append: " | " | append: collection %}
{% endif %}
{% if page.category %}
{% assign category = page.category | capitalize %}
{% assign title = title | append: " | " | append: category %}
{% endif %}
{% if title %}
{{ title | smartify | xml_escape }}
{% endif %}
{% if site.description %}
{{ site.description | xml_escape }}
{% endif %}
{% if site.author %}
{{ site.author.name | default: site.author | xml_escape }}
{% if site.author.email %}
{{ site.author.email | xml_escape }}
{% endif %}
{% if site.author.uri %}
{{ site.author.uri | xml_escape }}
{% endif %}
{% endif %}
{% assign posts = site[page.collection] | where_exp: "post", "post.draft != true" | sort: "date" | reverse %}
{% if page.category %}
{% assign posts = posts | where: "category",page.category %}
{% endif %}
{% for post in posts limit: 10 %}
{{ post.title | smartify | strip_html | normalize_whitespace | xml_escape }}{{ post.date | date_to_xmlschema }}{{ post.last_modified_at | default: post.date | date_to_xmlschema }}{{ post.id | absolute_url | xml_escape }}
{% assign excerpt_only = post.feed.excerpt_only | default: site.feed.excerpt_only %}
{% unless excerpt_only %}
{{ post.content | strip | xml_escape }}
{% endunless %}
{% assign post_author = post.author | default: post.authors[0] | default: site.author %}
{% assign post_author = site.data.authors[post_author] | default: post_author %}
{% assign post_author_email = post_author.email | default: nil %}
{% assign post_author_uri = post_author.uri | default: nil %}
{% assign post_author_name = post_author.name | default: post_author %}
{{ post_author_name | default: "" | xml_escape }}
{% if post_author_email %}
{{ post_author_email | xml_escape }}
{% endif %}
{% if post_author_uri %}
{{ post_author_uri | xml_escape }}
{% endif %}
{% if post.category %}
{% endif %}
{% for tag in post.tags %}
{% endfor %}
{% if post.excerpt and post.excerpt != empty %}
{{ post.excerpt | strip_html | normalize_whitespace | xml_escape }}
{% endif %}
{% assign post_image = post.image.path | default: post.image %}
{% if post_image %}
{% unless post_image contains "://" %}
{% assign post_image = post_image | absolute_url %}
{% endunless %}
{% endif %}
{% endfor %}
jekyll-feed-0.13.0/lib/jekyll-feed/meta-tag.rb 0000644 0000041 0000041 00000001354 13565064320 021012 0 ustar www-data www-data # frozen_string_literal: true
module JekyllFeed
class MetaTag < Liquid::Tag
# Use Jekyll's native relative_url filter
include Jekyll::Filters::URLFilters
def render(context)
@context = context
attrs = attributes.map { |k, v| %(#{k}="#{v}") }.join(" ")
""
end
private
def config
@config ||= @context.registers[:site].config
end
def attributes
{
:type => "application/atom+xml",
:rel => "alternate",
:href => absolute_url(path),
:title => title,
}.keep_if { |_, v| v }
end
def path
config.dig("feed", "path") || "feed.xml"
end
def title
config["title"] || config["name"]
end
end
end
jekyll-feed-0.13.0/lib/jekyll-feed/page-without-a-file.rb 0000644 0000041 0000041 00000000223 13565064320 023055 0 ustar www-data www-data # frozen_string_literal: true
module JekyllFeed
class PageWithoutAFile < Jekyll::Page
def read_yaml(*)
@data ||= {}
end
end
end
jekyll-feed-0.13.0/lib/jekyll-feed/generator.rb 0000644 0000041 0000041 00000007235 13565064320 021305 0 ustar www-data www-data # frozen_string_literal: true
module JekyllFeed
class Generator < Jekyll::Generator
safe true
priority :lowest
# Main plugin action, called by Jekyll-core
def generate(site)
@site = site
collections.each do |name, meta|
Jekyll.logger.info "Jekyll Feed:", "Generating feed for #{name}"
(meta["categories"] + [nil]).each do |category|
path = feed_path(:collection => name, :category => category)
next if file_exists?(path)
@site.pages << make_page(path, :collection => name, :category => category)
end
end
end
private
# Matches all whitespace that follows
# 1. A '>', which closes an XML tag or
# 2. A '}', which closes a Liquid tag
# We will strip all of this whitespace to minify the template
MINIFY_REGEX = %r!(?<=>|})\s+!.freeze
# Returns the plugin's config or an empty hash if not set
def config
@config ||= @site.config["feed"] || {}
end
# Determines the destination path of a given feed
#
# collection - the name of a collection, e.g., "posts"
# category - a category within that collection, e.g., "news"
#
# Will return "/feed.xml", or the config-specified default feed for posts
# Will return `/feed/category.xml` for post categories
# WIll return `/feed/collection.xml` for other collections
# Will return `/feed/collection/category.xml` for other collection categories
def feed_path(collection: "posts", category: nil)
prefix = collection == "posts" ? "/feed" : "/feed/#{collection}"
return "#{prefix}/#{category}.xml" if category
collections.dig(collection, "path") || "#{prefix}.xml"
end
# Returns a hash representing all collections to be processed and their metadata
# in the form of { collection_name => { categories = [...], path = "..." } }
def collections
return @collections if defined?(@collections)
@collections = if config["collections"].is_a?(Array)
config["collections"].map { |c| [c, {}] }.to_h
elsif config["collections"].is_a?(Hash)
config["collections"]
else
{}
end
@collections = normalize_posts_meta(@collections)
@collections.each_value do |meta|
meta["categories"] = (meta["categories"] || []).to_set
end
@collections
end
# Path to feed.xml template file
def feed_source_path
@feed_source_path ||= File.expand_path "feed.xml", __dir__
end
def feed_template
@feed_template ||= File.read(feed_source_path).gsub(MINIFY_REGEX, "")
end
# Checks if a file already exists in the site source
def file_exists?(file_path)
File.exist? @site.in_source_dir(file_path)
end
# Generates contents for a file
def make_page(file_path, collection: "posts", category: 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
)
file.output
end
end
# Special case the "posts" collection, which, for ease of use and backwards
# compatability, can be configured via top-level keys or directly as a collection
def normalize_posts_meta(hash)
hash["posts"] ||= {}
hash["posts"]["path"] ||= config["path"]
hash["posts"]["categories"] ||= config["categories"]
config["path"] ||= hash["posts"]["path"]
hash
end
end
end
jekyll-feed-0.13.0/lib/jekyll-feed.rb 0000644 0000041 0000041 00000000463 13565064320 017313 0 ustar www-data www-data # frozen_string_literal: true
require "jekyll"
require "fileutils"
require "jekyll-feed/generator"
module JekyllFeed
autoload :MetaTag, "jekyll-feed/meta-tag"
autoload :PageWithoutAFile, "jekyll-feed/page-without-a-file.rb"
end
Liquid::Template.register_tag "feed_meta", JekyllFeed::MetaTag
jekyll-feed-0.13.0/History.markdown 0000644 0000041 0000041 00000007036 13565064320 017235 0 ustar www-data www-data ## 0.13.0 / 2019-11-13
### Minor Enhancements
* Excerpt only flag (#287)
* Add media:content tag (#290)
### Development Fixes
* test: use categories in post (#249)
## 0.12.1 / 2019-03-23
### Bug Fixes
* Re-introduce Ruby 2.3 support and test Jekyll 3.7+ (#272)
## 0.12.0 / 2019-03-21
* Allow Jekyll v4 (still alpha)
### Development Fixes
* style: fix offenses in specs (#248)
* dev: update CI and style settings (#258)
* Enable testing for Windows platform (#265)
## 0.11.0 / 2018-09-09
### Development Fixes
* Require Ruby 2.3 (#222)
* Refactor to remove redundant calls and variables (#240)
### Minor Enhancements
* Categories and collections (#228)
* Remove check for older version of Jekyll (#234)
## 0.10.0 / 2018-06-04
### Bug Fixes
* Escape image URL (#209)
### Development Fixes
* Rubocop 0.55 (#223)
* Bump Rubocop (#230)
### Minor Enhancements
* Support Typhoeus 1.0 (#232)
## 0.9.3 / 2018-02-04
* Define path with __dir (#187)
* Bump Ruby for Travis (#188)
### Documentation
* Fix: Add note about using plugins instead of gems key (#197)
* Add documentation for disabling smartify filter (#205)
* Use `https` in more places. (#165)
### Development Fixes
* Rubocop: Target Ruby 2.2 (#195)
* Test feeds that have a `site.lang` (#164)
* Test against Ruby 2.5 (#201)
### Minor Enhancements
* fix template for posts with post.lang defined (#168)
## 0.9.3 / 2017-03-28
## 0.9.1 / 2017-02-17
### Minor Enhancements
* Update feed.xml (#162)
## 0.9.0 / 2017-02-16
### Minor Enhancements
* Use absolute_url to generate the feed_meta url (#150)
* Make feed stylesheet optional (#149)
* Use new `normalize_whitespace` filter (#143)
* Feed entries must contain (#152)
* Remove trailing slash from feed ID (#159)
### Development Fixes
* Simplify minify regular expression (#141)
* Namespace as JekyllFeed (#151)
* rubocop -a (#160)
### Bug Fixes
* Filter out drafts before limit (#154)
## 0.8.0 / 2016-10-06
* Use filters to clean up Liquid template (#134)
### Minor Enhancements
* Don't set @site.config["time"] on feed generation (#138)
### pedantry
* Appease Rubocop (#139)
## 0.7.2 / 2016-10-06
* Support `image.path` when `post.image` is an object (#137)
## 0.7.1 / 2016-09-26
* Assign `url_base` before first usage (#133)
## 0.7.0 / 2016-09-06
* Use type="html" to skirt around double escaping problem (#127)
## 0.6.0 / 2016-07-08
* Cleanup `post_author` logic (#113)
* Add XML stylesheet example with XSLT (#119)
* DRY up and add more doc (#120)
* Use smartify filter (#117)
## 0.5.1 / 2016-04-18
* Fix mangling of whitespace when `site.lang` is set (#110)
## 0.5.0 / 2016-04-13
* Consolidate regexps for stripping whitespace (#82)
* Only test against Jekyll 3 (#99)
* Think about how i18n might work (#75)
* Find author by reference (#106)
* Drop support for Jekyll 2 (#105)
* Add support for post image (#104)
### Minor Enhancements
* Use Module#method_defined? (#83)
* Use site.title for meta tag if available (#100)
### Development Fixes
* Do not require [**jekyll-last-modified-at**](https://github.com/gjtorikian/jekyll-last-modified-at) in tests (#87)
* Add Rubocop (#81)
* Correct typo in tests (#102)
* Simplify testing feed_meta tag (#101)
* Quiet known warnings in tests (#103)
## 0.4.0 / 2015-12-30
* Feed uses `site.title`, or `site.name` if `title` doesn't exist (#72)
* Replace newlines with spaces in `title` and `summary` elements (#67)
* Properly render post content with Jekyll (#73)
jekyll-feed-0.13.0/Gemfile 0000644 0000041 0000041 00000000334 13565064320 015315 0 ustar www-data www-data # frozen_string_literal: true
source "https://rubygems.org"
gemspec
gem "jekyll", ENV["JEKYLL_VERSION"] if ENV["JEKYLL_VERSION"]
install_if -> { Gem.win_platform? } do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
jekyll-feed-0.13.0/appveyor.yml 0000644 0000041 0000041 00000001363 13565064320 016415 0 ustar www-data www-data version: "{build}"
clone_depth: 5
build: off
environment:
NOKOGIRI_USE_SYSTEM_LIBRARIES: true
JEKYLL_VERSION: "~> 3.8"
matrix:
- RUBY_FOLDER_VER: "26"
JEKYLL_VERSION : "~> 3.7.4"
- RUBY_FOLDER_VER: "26"
JEKYLL_VERSION : ">= 4.0.0.pre.alpha1"
- RUBY_FOLDER_VER: "26"
- RUBY_FOLDER_VER: "24"
- RUBY_FOLDER_VER: "23"
install:
- SET PATH=C:\Ruby%RUBY_FOLDER_VER%-x64\bin;%PATH%
- bundle install --retry 5 --jobs=%NUMBER_OF_PROCESSORS% --clean --path vendor\bundle
test_script:
- ruby --version
- gem --version
- bundler --version
- bash ./script/test
cache:
# If one of the files after the right arrow changes, cache will be invalidated
- 'vendor\bundle -> appveyor.yml, Gemfile, jekyll-feed.gemspec'
jekyll-feed-0.13.0/LICENSE.txt 0000644 0000041 0000041 00000002120 13565064320 015640 0 ustar www-data www-data Copyright (c) 2015-present Ben Balter and jekyll-feed contributors
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.