jekyll-atom-feed 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2856d0204ad301147c97c8d41ebf461083782c7157fa64ee060cbf1e037d2133
4
+ data.tar.gz: 8a891b3f82b36ce614360fb44fa2cb0080474fc3c80a78016c76e80026428c00
5
+ SHA512:
6
+ metadata.gz: c1d64a6aef3d8e06fecd61f056bc33084a198de42d71ad6dae88f70416cb091e19aedbb0db09c8bacbc865d61e25157d4181f12c01f49a4e48fa32ec35e2496e
7
+ data.tar.gz: 68fc9c2df214ad48c11eef52c2b55ba513d19a3eae913862e3cbb6c0a8b87bb99a4d0315445a41e3747a2ee6080b01ff0d5ad5a875652c4fd96b8971faf97964
data/History.markdown ADDED
@@ -0,0 +1,244 @@
1
+ ## HEAD
2
+
3
+ ## 0.18.0 / 2023-09-17
4
+
5
+ * Integrate Webfeeds for better Feedly integration
6
+ * Provide a template configuration option to overwrite feed.xml template
7
+
8
+ ### Development Fixes
9
+
10
+ * Upgrade to Rake 13 to fix master (#381)
11
+
12
+ ### Documentation
13
+
14
+ * Fix typos in Readme (#384)
15
+
16
+ ## 0.17.0 / 2022-10-14
17
+
18
+ ### Documentation
19
+
20
+ * Update CI status badge (#363)
21
+
22
+ ### Development Fixes
23
+
24
+ * Add Ruby 3.1 to the CI matrix (#365)
25
+
26
+ ### Minor Enhancements
27
+
28
+ * Allow disabling of jekyll-feed while in development (#370)
29
+
30
+ ## 0.16.0 / 2022-01-03
31
+
32
+ ### Minor Enhancements
33
+
34
+ * Add support for `page.description` in front matter to become entry `<summary>` (#297)
35
+
36
+ ### Bug Fixes
37
+
38
+ * Fold private methods into the `:render` method as local variables (#327)
39
+ * Check `post.categories` instead of `post.category` (#357)
40
+ * Switched xml_escape for `<![CDATA[]]>` for post content (#332)
41
+
42
+ ### Development Fixes
43
+
44
+ * Add Ruby 3.0 to CI (#337)
45
+ * Lock RuboCop to v1.18.x (#348)
46
+ * Add workflow to release gem via GH Action (#355)
47
+
48
+ ### Documentation
49
+
50
+ * Use `.atom` extension in documented examples since we write an Atom feed (#359)
51
+
52
+ ## 0.15.1 / 2020-10-04
53
+
54
+ ### Bug Fixes
55
+
56
+ * MetaTag: when encoding for XML special characters, handle non-string objects (#326)
57
+
58
+ ## 0.15.0 / 2020-07-10
59
+
60
+ ### Minor Enhancements
61
+
62
+ * Add support for drafts (#316)
63
+
64
+ ## 0.14.0 / 2020-06-24
65
+
66
+ ### Minor Enhancements
67
+
68
+ * add support for categories (#153) (#233)
69
+ * add support for tags (#264)
70
+ * Make posts limit configurable (#314)
71
+ * XML escape the title field of feed_meta (#306)
72
+
73
+ ### Bug Fixes
74
+
75
+ * Fix feed link when post title contains HTML (#305)
76
+
77
+ ### Development Fixes
78
+
79
+ * Use Dir to list source files (#309)
80
+ * Require Ruby &gt;=2.4.0 (#307)
81
+
82
+ ## 0.13.0 / 2019-11-13
83
+
84
+ ### Minor Enhancements
85
+
86
+ * Excerpt only flag (#287)
87
+ * Add media:content tag (#290)
88
+
89
+ ### Development Fixes
90
+
91
+ * test: use categories in post (#249)
92
+
93
+ ## 0.12.1 / 2019-03-23
94
+
95
+ ### Bug Fixes
96
+
97
+ * Re-introduce Ruby 2.3 support and test Jekyll 3.7+ (#272)
98
+
99
+ ## 0.12.0 / 2019-03-21
100
+
101
+ * Allow Jekyll v4 (still alpha)
102
+
103
+ ### Development Fixes
104
+
105
+ * style: fix offenses in specs (#248)
106
+ * dev: update CI and style settings (#258)
107
+ * Enable testing for Windows platform (#265)
108
+
109
+ ## 0.11.0 / 2018-09-09
110
+
111
+ ### Development Fixes
112
+
113
+ * Require Ruby 2.3 (#222)
114
+ * Refactor to remove redundant calls and variables (#240)
115
+
116
+ ### Minor Enhancements
117
+
118
+ * Categories and collections (#228)
119
+ * Remove check for older version of Jekyll (#234)
120
+
121
+ ## 0.10.0 / 2018-06-04
122
+
123
+ ### Bug Fixes
124
+
125
+ * Escape image URL (#209)
126
+
127
+ ### Development Fixes
128
+
129
+ * Rubocop 0.55 (#223)
130
+ * Bump Rubocop (#230)
131
+
132
+ ### Minor Enhancements
133
+
134
+ * Support Typhoeus 1.0 (#232)
135
+
136
+ ## 0.9.3 / 2018-02-04
137
+
138
+ * Define path with __dir (#187)
139
+ * Bump Ruby for Travis (#188)
140
+
141
+ ### Documentation
142
+
143
+ * Fix: Add note about using plugins instead of gems key (#197)
144
+ * Add documentation for disabling smartify filter (#205)
145
+ * Use `https` in more places. (#165)
146
+
147
+ ### Development Fixes
148
+
149
+ * Rubocop: Target Ruby 2.2 (#195)
150
+ * Test feeds that have a `site.lang` (#164)
151
+ * Test against Ruby 2.5 (#201)
152
+
153
+ ### Minor Enhancements
154
+
155
+ * fix <entry> template for posts with post.lang defined (#168)
156
+
157
+ ## 0.9.1 / 2017-02-17
158
+
159
+ ### Minor Enhancements
160
+
161
+ * Update feed.xml (#162)
162
+
163
+ ## 0.9.0 / 2017-02-16
164
+
165
+ ### Minor Enhancements
166
+
167
+ * Use absolute_url to generate the feed_meta url (#150)
168
+ * Make feed stylesheet optional (#149)
169
+ * Use new `normalize_whitespace` filter (#143)
170
+ * Feed entries must contain <author> (#152)
171
+ * Remove trailing slash from feed ID (#159)
172
+
173
+ ### Development Fixes
174
+
175
+ * Simplify minify regular expression (#141)
176
+ * Namespace as JekyllFeed (#151)
177
+ * rubocop -a (#160)
178
+
179
+ ### Bug Fixes
180
+
181
+ * Filter out drafts before limit (#154)
182
+
183
+ ## 0.8.0 / 2016-10-06
184
+
185
+ * Use filters to clean up Liquid template (#134)
186
+
187
+ ### Minor Enhancements
188
+
189
+ * Don't set @site.config["time"] on feed generation (#138)
190
+
191
+ ### pedantry
192
+
193
+ * Appease Rubocop (#139)
194
+
195
+ ## 0.7.2 / 2016-10-06
196
+
197
+ * Support `image.path` when `post.image` is an object (#137)
198
+
199
+ ## 0.7.1 / 2016-09-26
200
+
201
+ * Assign `url_base` before first usage (#133)
202
+
203
+ ## 0.7.0 / 2016-09-06
204
+
205
+ * Use type="html" to skirt around double escaping problem (#127)
206
+
207
+ ## 0.6.0 / 2016-07-08
208
+
209
+ * Cleanup `post_author` logic (#113)
210
+ * Add XML stylesheet example with XSLT (#119)
211
+ * DRY up and add more doc (#120)
212
+ * Use smartify filter (#117)
213
+
214
+ ## 0.5.1 / 2016-04-18
215
+
216
+ * Fix mangling of whitespace when `site.lang` is set (#110)
217
+
218
+ ## 0.5.0 / 2016-04-13
219
+
220
+ * Consolidate regexps for stripping whitespace (#82)
221
+ * Only test against Jekyll 3 (#99)
222
+ * Think about how i18n might work (#75)
223
+ * Find author by reference (#106)
224
+ * Drop support for Jekyll 2 (#105)
225
+ * Add support for post image (#104)
226
+
227
+ ### Minor Enhancements
228
+
229
+ * Use Module#method_defined? (#83)
230
+ * Use site.title for meta tag if available (#100)
231
+
232
+ ### Development Fixes
233
+
234
+ * Do not require [**jekyll-last-modified-at**](https://github.com/gjtorikian/jekyll-last-modified-at) in tests (#87)
235
+ * Add Rubocop (#81)
236
+ * Correct typo in tests (#102)
237
+ * Simplify testing feed_meta tag (#101)
238
+ * Quiet known warnings in tests (#103)
239
+
240
+ ## 0.4.0 / 2015-12-30
241
+
242
+ * Feed uses `site.title`, or `site.name` if `title` doesn't exist (#72)
243
+ * Replace newlines with spaces in `title` and `summary` elements (#67)
244
+ * Properly render post content with Jekyll (#73)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015-present Ben Balter and jekyll-feed and jekyll-atom-feed contributors
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,285 @@
1
+ # Jekyll Feed plugin
2
+
3
+ A Jekyll plugin to generate an Atom (RSS-like) feed of your Jekyll posts
4
+
5
+ [![Continuous Integration](https://github.com/bautisflow/jekyll-atom-feed/actions/workflows/ruby.yml/badge.svg)](https://github.com/bautisflow/jekyll-atom-feed/actions/workflows/ruby.yml) [![Gem Version](https://badge.fury.io/rb/jekyll-atom-feed.svg)](https://badge.fury.io/rb/jekyll-atom-feed)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your site's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'jekyll-atom-feed'
13
+ ```
14
+
15
+ And then add this line to your site's `_config.yml`:
16
+
17
+ ```yml
18
+ plugins:
19
+ - jekyll-atom-feed
20
+ ```
21
+
22
+ :warning: If you are using Jekyll < 3.5.0 use the `gems` key instead of `plugins`.
23
+
24
+ ## Usage
25
+
26
+ The plugin will automatically generate an Atom feed at `/feed.xml`.
27
+
28
+ ### Optional configuration options
29
+
30
+ The plugin will automatically use any of the following configuration variables, if they are present in your site's `_config.yml` file.
31
+
32
+ * `title` or `name` - The title of the site, e.g., "My awesome site"
33
+ * `description` - A longer description of what your site is about, e.g., "Where I blog about Jekyll and other awesome things"
34
+ * `url` - The URL to your site, e.g., `https://example.com`. If none is provided, the plugin will try to use `site.github.url`.
35
+ * `author` - Global author information (see below)
36
+
37
+ If you want to enrich your feed for [Feedly](https://feedly.com), create the following object with any of these optional values:
38
+ ```yml
39
+ webfeeds:
40
+ icon: # path to a 96x96 favicon
41
+ logo: # path to a 30px height svg
42
+ cover: # path to a large 16:9 banner image
43
+ accent_color: # hex colour without the hash
44
+ related: # true = show other stories from your feed under yours
45
+ analytics: # Google Analytics UA-x tracking ID
46
+ ```
47
+
48
+ ### Already have a feed path?
49
+
50
+ 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-atom-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.
51
+
52
+ ```yml
53
+ feed:
54
+ path: /blog/feed.atom
55
+ ```
56
+
57
+ 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.
58
+
59
+ ### Optional front matter
60
+
61
+ The plugin will use the following post metadata, automatically generated by Jekyll, which you can override via a post's YAML front matter:
62
+
63
+ * `date`
64
+ * `title`
65
+ * `excerpt`
66
+ * `id`
67
+ * `category`
68
+ * `tags`
69
+
70
+ Additionally, the plugin will use the following values, if present in a post's YAML front matter:
71
+
72
+ * `image` - URL of an image that is representative of the post (can also be passed as `image.path`)
73
+
74
+ * `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).
75
+
76
+ * `description` - A short description of the post.
77
+
78
+ ### Author information
79
+
80
+ *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.*
81
+
82
+ There are several ways to convey author-specific information. Author information is found in the following order of priority:
83
+
84
+ 1. An `author` object, in the document's front matter, e.g.:
85
+
86
+ ```yml
87
+ author:
88
+ twitter: benbalter
89
+ ```
90
+
91
+ 2. An `author` object, in the site's `_config.yml`, e.g.:
92
+
93
+ ```yml
94
+ author:
95
+ twitter: benbalter
96
+ ```
97
+
98
+ 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:
99
+
100
+ ```yml
101
+ author: benbalter
102
+ ```
103
+
104
+ And you have the following in `_data/authors.yml`:
105
+
106
+ ```yml
107
+ benbalter:
108
+ picture: /img/benbalter.png
109
+ twitter: jekyllrb
110
+
111
+ potus:
112
+ picture: /img/potus.png
113
+ twitter: whitehouse
114
+ ```
115
+
116
+ 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.
117
+
118
+ *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.*
119
+
120
+ 4. An author in the document's front matter (the simplest way), e.g.:
121
+
122
+ ```yml
123
+ author: benbalter
124
+ ```
125
+
126
+ 5. An author in the site's `_config.yml`, e.g.:
127
+
128
+ ```yml
129
+ author: benbalter
130
+ ```
131
+
132
+ ### Meta tags
133
+
134
+ 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 `<head>` section, to output the necessary metadata.
135
+
136
+ ### SmartyPants
137
+
138
+ 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.
139
+
140
+ 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:
141
+
142
+ ```yml
143
+ kramdown:
144
+ smart_quotes: apos,apos,quot,quot
145
+ typographic_symbols: {hellip: ...}
146
+ ```
147
+
148
+ ### Custom styling
149
+
150
+ Want to style what your feed looks like in the browser? When a XSLT Styleheet file named `feed.xslt.xml` exists at the root of your repository, a link to this stylesheet is added to the generated feed.
151
+
152
+ ### Custom source template
153
+
154
+ You can specify your own source `feed.xml` if you like to modify the content of the generated feed. Simply define a template path to your xml source file:
155
+
156
+ ```yaml
157
+ feed:
158
+ template: _layouts/feed.xml
159
+ ```
160
+
161
+ ## Why Atom, and not RSS?
162
+
163
+ 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).
164
+
165
+ ## Categories
166
+
167
+ Jekyll Feed can generate feeds for each category. Simply define which categories you'd like feeds for in your config:
168
+
169
+ ```yml
170
+ feed:
171
+ categories:
172
+ - news
173
+ - updates
174
+ ```
175
+
176
+ ## Posts limit
177
+
178
+ By default the plugin limits the number of posts in the feed to 10. Simply define a new limit in your config:
179
+
180
+ ```yml
181
+ feed:
182
+ posts_limit: 20
183
+ ```
184
+
185
+ ## Collections
186
+
187
+ 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:
188
+
189
+ ```yml
190
+ feed:
191
+ collections:
192
+ - changes
193
+ ```
194
+
195
+ By default, collection feeds will be outputted to `/feed/<COLLECTION>.xml`. If you'd like to customize the output path, specify a collection's custom path as follows:
196
+
197
+ ```yml
198
+ feed:
199
+ collections:
200
+ changes:
201
+ path: "/changes.atom"
202
+ ```
203
+
204
+ Finally, collections can also have category feeds that are outputted as `/feed/<COLLECTION>/<CATEGORY>.xml`. Specify categories like so:
205
+
206
+ ```yml
207
+ feed:
208
+ collections:
209
+ changes:
210
+ path: "/changes.atom"
211
+ categories:
212
+ - news
213
+ - updates
214
+ ```
215
+
216
+ ## Excerpt Only flag
217
+
218
+ Optional flag `excerpt_only` allows you to exclude post content from the Atom feed. Default value is `false` for backward compatibility.
219
+
220
+ When in `config.yml` is `true` then all posts in feed will be without `<content>` tags.
221
+
222
+ ```yml
223
+ feed:
224
+ excerpt_only: true
225
+ ```
226
+
227
+ The same flag can be used directly in post file. It will disable `<content>` tag for selected post.
228
+ Settings in post file have higher priority than in config file.
229
+
230
+ ## Tags
231
+
232
+ To automatically generate feeds for each tag you apply to your posts you can add a tags setting to your config:
233
+
234
+ ```yml
235
+ feed:
236
+ tags: true
237
+ ```
238
+
239
+ If there are tags you don't want included in this auto generation you can exclude them
240
+
241
+ ```yml
242
+ feed:
243
+ tags:
244
+ except:
245
+ - tag-to-exclude
246
+ - another-tag
247
+ ```
248
+
249
+ If you wish to change the location of these auto generated feeds (`/feed/by_tag/<TAG>.xml` by default) you can provide an alternative folder for them to live in.
250
+
251
+ ```yml
252
+ feed:
253
+ tags:
254
+ path: "alternative/path/for/tags/feeds/"
255
+ ```
256
+
257
+ If you only want to generate feeds for a few tags you can also set this.
258
+
259
+ ```yml
260
+ feed:
261
+ tags:
262
+ only:
263
+ - tag-to-include
264
+ - another-tag
265
+ ```
266
+
267
+ Note that if you include a tag that is excluded a feed will not be generated for it.
268
+
269
+ ## Skip development
270
+
271
+ Use `disable_in_development: true` if you want to turn off feed generation when `jekyll.environment == "development"`,
272
+ but don't want to remove the plugin (so you don't accidentally commit the removal). Default value is `false`.
273
+
274
+ ```yml
275
+ feed:
276
+ disable_in_development: true
277
+ ```
278
+
279
+ ## Contributing
280
+
281
+ 1. Fork it (https://github.com/bautisflow/jekyll-atom-feed/fork)
282
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
283
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
284
+ 4. Push to the branch (`git push origin my-new-feature`)
285
+ 5. Create a new Pull Request
@@ -0,0 +1,121 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ {% if page.xsl %}
3
+ <?xml-stylesheet type="text/xml" href="{{ '/feed.xslt.xml' | absolute_url }}"?>
4
+ {% endif %}
5
+ <feed xmlns="http://www.w3.org/2005/Atom" {% if site.webfeeds %} xmlns:webfeeds="http://webfeeds.org/rss/1.0"{% endif %} {% if site.lang %}xml:lang="{{ site.lang }}"{% endif %}>
6
+ <generator uri="https://jekyllrb.com/" version="{{ jekyll.version }}">Jekyll</generator>
7
+ <link href="{{ page.url | absolute_url }}" rel="self" type="application/atom+xml" />
8
+ <link href="{{ '/' | absolute_url }}" rel="alternate" type="text/html" {% if site.lang %}hreflang="{{ site.lang }}" {% endif %}/>
9
+ <updated>{{ site.time | date_to_xmlschema }}</updated>
10
+ <id>{{ page.url | absolute_url | xml_escape }}</id>
11
+
12
+ {% assign title = site.title | default: site.name %}
13
+ {% if page.collection != "posts" %}
14
+ {% assign collection = page.collection | capitalize %}
15
+ {% assign title = title | append: " | " | append: collection %}
16
+ {% endif %}
17
+ {% if page.category %}
18
+ {% assign category = page.category | capitalize %}
19
+ {% assign title = title | append: " | " | append: category %}
20
+ {% endif %}
21
+
22
+ {% if title %}
23
+ <title type="html">{{ title | smartify | xml_escape }}</title>
24
+ {% endif %}
25
+
26
+ {% if site.description %}
27
+ <subtitle>{{ site.description | xml_escape }}</subtitle>
28
+ {% endif %}
29
+
30
+ {% if site.author %}
31
+ <author>
32
+ <name>{{ site.author.name | default: site.author | xml_escape }}</name>
33
+ {% if site.author.email %}
34
+ <email>{{ site.author.email | xml_escape }}</email>
35
+ {% endif %}
36
+ {% if site.author.uri %}
37
+ <uri>{{ site.author.uri | xml_escape }}</uri>
38
+ {% endif %}
39
+ </author>
40
+ {% endif %}
41
+
42
+ {% if site.webfeeds %}
43
+ {% if site.webfeeds.icon %}<webfeeds:icon>{{ site.webfeeds.icon }}</webfeeds:icon>{% endif %}
44
+ {% if site.webfeeds.logo %}<webfeeds:logo>{{ site.webfeeds.logo }}</webfeeds:logo>{% endif %}
45
+ {% if site.webfeeds.cover %}<webfeeds:cover>{{ site.webfeeds.cover }}</webfeeds:cover>{% endif %}
46
+ {% if site.webfeeds.accent_color %}<webfeeds:accentColor>{{ site.webfeeds.accent_color }}</webfeeds:accentColor>{% endif %}
47
+ {% if site.webfeeds.related %}<webfeeds:related layout="card" target="browser"/>{% endif %}
48
+ {% if site.webfeeds.analytics %}<webfeeds:analytics id="{{ site.webfeeds.analytics }}" engine="GoogleAnalytics" />{% endif %}
49
+ {% endif %}
50
+
51
+ {% if page.tags %}
52
+ {% assign posts = site.tags[page.tags] %}
53
+ {% else %}
54
+ {% assign posts = site[page.collection] %}
55
+ {% endif %}
56
+ {% if page.category %}
57
+ {% assign posts = posts | where: "categories", page.category %}
58
+ {% endif %}
59
+ {% unless site.show_drafts %}
60
+ {% assign posts = posts | where_exp: "post", "post.draft != true" %}
61
+ {% endunless %}
62
+ {% assign posts = posts | sort: "date" | reverse %}
63
+ {% assign posts_limit = site.feed.posts_limit | default: 10 %}
64
+ {% for post in posts limit: posts_limit %}
65
+ <entry{% if post.lang %}{{" "}}xml:lang="{{ post.lang }}"{% endif %}>
66
+ {% assign post_title = post.title | smartify | strip_html | normalize_whitespace | xml_escape %}
67
+
68
+ <title type="html">{{ post_title }}</title>
69
+ <link href="{{ post.url | absolute_url }}" rel="alternate" type="text/html" title="{{ post_title }}" />
70
+ <published>{{ post.date | date_to_xmlschema }}</published>
71
+ <updated>{{ post.last_modified_at | default: post.date | date_to_xmlschema }}</updated>
72
+ <id>{{ post.id | absolute_url | xml_escape }}</id>
73
+ {% assign excerpt_only = post.feed.excerpt_only | default: site.feed.excerpt_only %}
74
+ {% unless excerpt_only %}
75
+ <content type="html" xml:base="{{ post.url | absolute_url | xml_escape }}"><![CDATA[{{ post.content | strip }}]]></content>
76
+ {% endunless %}
77
+
78
+ {% assign post_author = post.author | default: post.authors[0] | default: site.author %}
79
+ {% assign post_author = site.data.authors[post_author] | default: post_author %}
80
+ {% assign post_author_email = post_author.email | default: nil %}
81
+ {% assign post_author_uri = post_author.uri | default: nil %}
82
+ {% assign post_author_name = post_author.name | default: post_author %}
83
+
84
+ <author>
85
+ <name>{{ post_author_name | default: "" | xml_escape }}</name>
86
+ {% if post_author_email %}
87
+ <email>{{ post_author_email | xml_escape }}</email>
88
+ {% endif %}
89
+ {% if post_author_uri %}
90
+ <uri>{{ post_author_uri | xml_escape }}</uri>
91
+ {% endif %}
92
+ </author>
93
+
94
+ {% if post.category %}
95
+ <category term="{{ post.category | xml_escape }}" />
96
+ {% elsif post.categories %}
97
+ {% for category in post.categories %}
98
+ <category term="{{ category | xml_escape }}" />
99
+ {% endfor %}
100
+ {% endif %}
101
+
102
+ {% for tag in post.tags %}
103
+ <category term="{{ tag | xml_escape }}" />
104
+ {% endfor %}
105
+
106
+ {% assign post_summary = post.description | default: post.excerpt %}
107
+ {% if post_summary and post_summary != empty %}
108
+ <summary type="html"><![CDATA[{{ post_summary | strip_html | normalize_whitespace }}]]></summary>
109
+ {% endif %}
110
+
111
+ {% assign post_image = post.image.path | default: post.image %}
112
+ {% if post_image %}
113
+ {% unless post_image contains "://" %}
114
+ {% assign post_image = post_image | absolute_url %}
115
+ {% endunless %}
116
+ <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="{{ post_image | xml_escape }}" />
117
+ <media:content medium="image" url="{{ post_image | xml_escape }}" xmlns:media="http://search.yahoo.com/mrss/" />
118
+ {% endif %}
119
+ </entry>
120
+ {% endfor %}
121
+ </feed>
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllFeed
4
+ class Generator < Jekyll::Generator
5
+ safe true
6
+ priority :lowest
7
+
8
+ # Main plugin action, called by Jekyll-core
9
+ def generate(site)
10
+ @site = site
11
+ if disabled_in_development?
12
+ Jekyll.logger.info "Jekyll Feed:", "Skipping feed generation in development"
13
+ return
14
+ end
15
+ collections.each do |name, meta|
16
+ Jekyll.logger.info "Jekyll Feed:", "Generating feed for #{name}"
17
+ (meta["categories"] + [nil]).each do |category|
18
+ path = feed_path(:collection => name, :category => category)
19
+ next if file_exists?(path)
20
+
21
+ @site.pages << make_page(path, :collection => name, :category => category)
22
+ end
23
+ end
24
+ generate_feed_by_tag if config["tags"] && !@site.tags.empty?
25
+ end
26
+
27
+ private
28
+
29
+ # Matches all whitespace that follows
30
+ # 1. A '>', which closes an XML tag or
31
+ # 2. A '}', which closes a Liquid tag
32
+ # We will strip all of this whitespace to minify the template
33
+ MINIFY_REGEX = %r!(?<=>|})\s+!.freeze
34
+
35
+ # Returns the plugin's config or an empty hash if not set
36
+ def config
37
+ @config ||= @site.config["feed"] || {}
38
+ end
39
+
40
+ # Determines the destination path of a given feed
41
+ #
42
+ # collection - the name of a collection, e.g., "posts"
43
+ # category - a category within that collection, e.g., "news"
44
+ #
45
+ # Will return "/feed.xml", or the config-specified default feed for posts
46
+ # Will return `/feed/category.xml` for post categories
47
+ # WIll return `/feed/collection.xml` for other collections
48
+ # Will return `/feed/collection/category.xml` for other collection categories
49
+ def feed_path(collection: "posts", category: nil)
50
+ prefix = collection == "posts" ? "/feed" : "/feed/#{collection}"
51
+ return "#{prefix}/#{category}.xml" if category
52
+
53
+ collections.dig(collection, "path") || "#{prefix}.xml"
54
+ end
55
+
56
+ # Returns a hash representing all collections to be processed and their metadata
57
+ # in the form of { collection_name => { categories = [...], path = "..." } }
58
+ def collections
59
+ return @collections if defined?(@collections)
60
+
61
+ @collections = case config["collections"]
62
+ when Array
63
+ config["collections"].map { |c| [c, {}] }.to_h
64
+ when Hash
65
+ config["collections"]
66
+ else
67
+ {}
68
+ end
69
+
70
+ @collections = normalize_posts_meta(@collections)
71
+ @collections.each_value do |meta|
72
+ meta["categories"] = (meta["categories"] || []).to_set
73
+ end
74
+
75
+ @collections
76
+ end
77
+
78
+ def generate_feed_by_tag
79
+ tags_config = config["tags"]
80
+ tags_config = {} unless tags_config.is_a?(Hash)
81
+
82
+ except = tags_config["except"] || []
83
+ only = tags_config["only"] || @site.tags.keys
84
+ tags_pool = only - except
85
+ tags_path = tags_config["path"] || "/feed/by_tag/"
86
+
87
+ generate_tag_feed(tags_pool, tags_path)
88
+ end
89
+
90
+ def generate_tag_feed(tags_pool, tags_path)
91
+ tags_pool.each do |tag|
92
+ # allow only tags with basic alphanumeric characters and underscore to keep
93
+ # feed path simple.
94
+ next if %r![^a-zA-Z0-9_]!.match?(tag)
95
+
96
+ Jekyll.logger.info "Jekyll Feed:", "Generating feed for posts tagged #{tag}"
97
+ path = "#{tags_path}#{tag}.xml"
98
+ next if file_exists?(path)
99
+
100
+ @site.pages << make_page(path, :tags => tag)
101
+ end
102
+ end
103
+
104
+ # Path to feed.xml template file
105
+ def feed_source_path
106
+ @feed_source_path = config["template"] if config["template"]
107
+ @feed_source_path ||= File.expand_path "feed.xml", __dir__
108
+ end
109
+
110
+ def feed_template
111
+ @feed_template ||= File.read(feed_source_path).gsub(MINIFY_REGEX, "")
112
+ end
113
+
114
+ # Checks if a file already exists in the site source
115
+ def file_exists?(file_path)
116
+ File.exist? @site.in_source_dir(file_path)
117
+ end
118
+
119
+ # Generates contents for a file
120
+
121
+ def make_page(file_path, collection: "posts", category: nil, tags: nil)
122
+ PageWithoutAFile.new(@site, __dir__, "", file_path).tap do |file|
123
+ file.content = feed_template
124
+ file.data.merge!(
125
+ "layout" => nil,
126
+ "sitemap" => false,
127
+ "xsl" => file_exists?("feed.xslt.xml"),
128
+ "collection" => collection,
129
+ "category" => category,
130
+ "tags" => tags
131
+ )
132
+ file.output
133
+ end
134
+ end
135
+
136
+ # Special case the "posts" collection, which, for ease of use and backwards
137
+ # compatability, can be configured via top-level keys or directly as a collection
138
+ def normalize_posts_meta(hash)
139
+ hash["posts"] ||= {}
140
+ hash["posts"]["path"] ||= config["path"]
141
+ hash["posts"]["categories"] ||= config["categories"]
142
+ config["path"] ||= hash["posts"]["path"]
143
+ hash
144
+ end
145
+
146
+ def disabled_in_development?
147
+ config && config["disable_in_development"] && Jekyll.env == "development"
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllFeed
4
+ class MetaTag < Liquid::Tag
5
+ # Use Jekyll's native relative_url filter
6
+ include Jekyll::Filters::URLFilters
7
+
8
+ def render(context)
9
+ # Jekyll::Filters::URLFilters requires `@context` to be set in the environment.
10
+ @context = context
11
+
12
+ config = context.registers[:site].config
13
+ path = config.dig("feed", "path") || "feed.xml"
14
+ title = config["title"] || config["name"]
15
+
16
+ attributes = {
17
+ :type => "application/atom+xml",
18
+ :rel => "alternate",
19
+ :href => absolute_url(path),
20
+ }
21
+ attributes[:title] = title if title
22
+
23
+ attrs = attributes.map { |k, v| "#{k}=#{v.to_s.encode(:xml => :attr)}" }.join(" ")
24
+ "<link #{attrs} />"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllFeed
4
+ class PageWithoutAFile < Jekyll::Page
5
+ def read_yaml(*)
6
+ @data ||= {}
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Feed
5
+ VERSION = "0.18.0"
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jekyll"
4
+ require "fileutils"
5
+ require "jekyll-atom-feed/generator"
6
+
7
+ module JekyllFeed
8
+ autoload :MetaTag, "jekyll-atom-feed/meta-tag"
9
+ autoload :PageWithoutAFile, "jekyll-atom-feed/page-without-a-file.rb"
10
+ end
11
+
12
+ Liquid::Template.register_tag "feed_meta", JekyllFeed::MetaTag
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-atom-feed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.18.0
5
+ platform: ruby
6
+ authors:
7
+ - Jaime Bautista
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-09-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.7'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.7'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: nokogiri
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.6'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.6'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '13.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '13.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop-jekyll
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 0.12.0
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 0.12.0
103
+ - !ruby/object:Gem::Dependency
104
+ name: typhoeus
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0.7'
110
+ - - "<"
111
+ - !ruby/object:Gem::Version
112
+ version: '2.0'
113
+ type: :development
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0.7'
120
+ - - "<"
121
+ - !ruby/object:Gem::Version
122
+ version: '2.0'
123
+ description:
124
+ email:
125
+ - bautisflow@github.com
126
+ executables: []
127
+ extensions: []
128
+ extra_rdoc_files:
129
+ - README.md
130
+ - History.markdown
131
+ - LICENSE.txt
132
+ files:
133
+ - History.markdown
134
+ - LICENSE.txt
135
+ - README.md
136
+ - lib/jekyll-atom-feed.rb
137
+ - lib/jekyll-atom-feed/feed.xml
138
+ - lib/jekyll-atom-feed/generator.rb
139
+ - lib/jekyll-atom-feed/meta-tag.rb
140
+ - lib/jekyll-atom-feed/page-without-a-file.rb
141
+ - lib/jekyll-atom-feed/version.rb
142
+ homepage: https://github.com/bautisflow/jekyll-atom-feed
143
+ licenses:
144
+ - MIT
145
+ metadata: {}
146
+ post_install_message:
147
+ rdoc_options: []
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 2.5.0
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ requirements: []
161
+ rubygems_version: 3.0.3.1
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: A Jekyll plugin to generate an Atom feed of your Jekyll posts
165
+ test_files: []