jekyll-feed 0.10.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8f54ea4d5e7e1cca4e3f97822892ebbbbf0e1e14
4
- data.tar.gz: a8f9d0597adee1a4f894dd7721c708099135bdce
2
+ SHA256:
3
+ metadata.gz: c244c9b3dc51c5a96051fe247af215ac0a136bb57fc6fe4f491ffa4acad122e6
4
+ data.tar.gz: a461c52155aa01616e59161c1c44a3eb1e0cfc3ebf58ef5bae70c9e5167272a5
5
5
  SHA512:
6
- metadata.gz: 4886bdd3fc8bf4bc520ddeab68ee7cc8823e3f6021f8633a5173390fc4ac59243edea9d69b651546f33f7d80e8aafba32cb21929bcdfda8c4480a7aeb2ac5212
7
- data.tar.gz: 3b3614f94497c50ce1c091760be4e932b6cd917d40c540434d391e4d15cd5469e17a59f5d9a2bc61e61d807695071e2b945677e9b70391ac81625d1846d8f060
6
+ metadata.gz: 5274b2f62e9fd6184bad9859bcd1ab4d10a0a2bc691393a3ccdae26de936b4a2fc8072db62b0f4cbab39c9efc8b284fb7b023bfac4f575af41efe8de16f609df
7
+ data.tar.gz: 5d0396d7edaa675efcf772cc57c9b7138e523b73a6a452274cca863483740a97d0036e871301dcea951eea1e0b04ce2551b2bc9b9bb4b92fc2d262100d7da45a
@@ -1,3 +1,60 @@
1
+ ## 0.14.0 / 2020-06-24
2
+
3
+ ### Minor Enhancements
4
+
5
+ * add support for categories (#153) (#233)
6
+ * add support for tags (#264)
7
+ * Make posts limit configurable (#314)
8
+ * XML escape the title field of feed_meta (#306)
9
+
10
+ ### Bug Fixes
11
+
12
+ * Fix feed link when post title contains HTML (#305)
13
+
14
+ ### Development Fixes
15
+
16
+ * Use Dir to list source files (#309)
17
+ * Require Ruby >=2.4.0 (#307)
18
+
19
+ ## 0.13.0 / 2019-11-13
20
+
21
+ ### Minor Enhancements
22
+
23
+ * Excerpt only flag (#287)
24
+ * Add media:content tag (#290)
25
+
26
+ ### Development Fixes
27
+
28
+ * test: use categories in post (#249)
29
+
30
+ ## 0.12.1 / 2019-03-23
31
+
32
+ ### Bug Fixes
33
+
34
+ * Re-introduce Ruby 2.3 support and test Jekyll 3.7+ (#272)
35
+
36
+ ## 0.12.0 / 2019-03-21
37
+
38
+ * Allow Jekyll v4 (still alpha)
39
+
40
+ ### Development Fixes
41
+
42
+ * style: fix offenses in specs (#248)
43
+ * dev: update CI and style settings (#258)
44
+ * Enable testing for Windows platform (#265)
45
+
46
+ ## 0.11.0 / 2018-09-09
47
+
48
+ ### Development Fixes
49
+
50
+ * Require Ruby 2.3 (#222)
51
+ * Refactor to remove redundant calls and variables (#240)
52
+
53
+ ### Minor Enhancements
54
+
55
+ * Categories and collections (#228)
56
+ * Remove check for older version of Jekyll (#234)
57
+
1
58
  ## 0.10.0 / 2018-06-04
2
59
 
3
60
  ### Bug Fixes
data/README.md CHANGED
@@ -31,7 +31,7 @@ The plugin will automatically use any of the following configuration variables,
31
31
 
32
32
  * `title` or `name` - The title of the site, e.g., "My awesome site"
33
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., `http://example.com`. If none is provided, the plugin will try to use `site.github.url`.
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
35
  * `author` - Global author information (see below)
36
36
 
37
37
  ### Already have a feed path?
@@ -140,6 +140,110 @@ Want to style what your feed looks like in the browser? Simply add an XSLT at `/
140
140
 
141
141
  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).
142
142
 
143
+ ## Categories
144
+
145
+ Jekyll Feed can generate feeds for each category. Simply define which categories you'd like feeds for in your config:
146
+
147
+ ```yml
148
+ feed:
149
+ categories:
150
+ - news
151
+ - updates
152
+ ```
153
+
154
+ ## Posts limit
155
+
156
+ By default the plugin limits the number of posts in the feed to 10. Simply define a new limit in your config:
157
+
158
+ ```yml
159
+ feed:
160
+ posts_limit: 20
161
+ ```
162
+
163
+ ## Collections
164
+
165
+ 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:
166
+
167
+ ```yml
168
+ feed:
169
+ collections:
170
+ - changes
171
+ ```
172
+
173
+ 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:
174
+
175
+ ```yml
176
+ feed:
177
+ collections:
178
+ changes:
179
+ path: "/changes.xml"
180
+ ```
181
+
182
+ Finally, collections can also have category feeds which are outputted as `/feed/<COLLECTION>/<CATEGORY>.xml`. Specify categories like so:
183
+
184
+ ```yml
185
+ feed:
186
+ collections:
187
+ changes:
188
+ path: "/changes.xml"
189
+ categories:
190
+ - news
191
+ - updates
192
+ ```
193
+
194
+ ## Excerpt Only flag
195
+
196
+ Optional flag `excerpt_only` allows you to exclude post content from the Atom feed. Default value is `false` for backward compatibility.
197
+
198
+ When in `config.yml` is `true` than all posts in feed will be without `<content>` tags.
199
+
200
+ ```yml
201
+ feed:
202
+ excerpt_only: true
203
+ ```
204
+
205
+ The same flag can be used directly in post file. It will be disable `<content>` tag for selected post.
206
+ Settings in post file has higher priority than in config file.
207
+
208
+ ## Tags
209
+
210
+ To automatically generate feeds for each tag you apply to your posts you can add a tags setting to your config:
211
+
212
+ ```yml
213
+ feed:
214
+ tags: true
215
+ ```
216
+
217
+ If there are tags you don't want included in this auto generation you can exclude them
218
+
219
+ ```yml
220
+ feed:
221
+ tags:
222
+ except:
223
+ - tag-to-exclude
224
+ - another-tag
225
+ ```
226
+
227
+ 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.
228
+
229
+ ```yml
230
+ feed:
231
+ tags:
232
+ path: "alternative/path/for/tags/feeds/"
233
+ ```
234
+
235
+ If you only want to generate feeds for a few tags you can also set this.
236
+
237
+ ```yml
238
+ feed:
239
+ tags:
240
+ only:
241
+ - tag-to-include
242
+ - another-tag
243
+ ```
244
+
245
+ Note that if you include a tag that is excluded a feed will not be generated for it.
246
+
143
247
  ## Contributing
144
248
 
145
249
  1. Fork it (https://github.com/jekyll/jekyll-feed/fork)
@@ -7,12 +7,20 @@
7
7
  <link href="{{ page.url | absolute_url }}" rel="self" type="application/atom+xml" />
8
8
  <link href="{{ '/' | absolute_url }}" rel="alternate" type="text/html" {% if site.lang %}hreflang="{{ site.lang }}" {% endif %}/>
9
9
  <updated>{{ site.time | date_to_xmlschema }}</updated>
10
- <id>{{ '/' | absolute_url | xml_escape }}</id>
10
+ <id>{{ page.url | absolute_url | xml_escape }}</id>
11
11
 
12
- {% if site.title %}
13
- <title type="html">{{ site.title | smartify | xml_escape }}</title>
14
- {% elsif site.name %}
15
- <title type="html">{{ site.name | smartify | xml_escape }}</title>
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>
16
24
  {% endif %}
17
25
 
18
26
  {% if site.description %}
@@ -31,15 +39,29 @@
31
39
  </author>
32
40
  {% endif %}
33
41
 
34
- {% assign posts = site.posts | where_exp: "post", "post.draft != true" %}
35
- {% for post in posts limit: 10 %}
42
+ {% if page.tags %}
43
+ {% assign entries = site.tags[page.tags] %}
44
+ {% else %}
45
+ {% assign entries = site[page.collection] %}
46
+ {% endif %}
47
+ {% assign posts = entries | where_exp: "post", "post.draft != true" | sort: "date" | reverse %}
48
+ {% if page.category %}
49
+ {% assign posts = posts | where: "category",page.category %}
50
+ {% endif %}
51
+ {% assign posts_limit = site.feed.posts_limit | default: 10 %}
52
+ {% for post in posts limit: posts_limit %}
36
53
  <entry{% if post.lang %}{{" "}}xml:lang="{{ post.lang }}"{% endif %}>
37
- <title type="html">{{ post.title | smartify | strip_html | normalize_whitespace | xml_escape }}</title>
38
- <link href="{{ post.url | absolute_url }}" rel="alternate" type="text/html" title="{{ post.title | xml_escape }}" />
54
+ {% assign post_title = post.title | smartify | strip_html | normalize_whitespace | xml_escape %}
55
+
56
+ <title type="html">{{ post_title }}</title>
57
+ <link href="{{ post.url | absolute_url }}" rel="alternate" type="text/html" title="{{ post_title }}" />
39
58
  <published>{{ post.date | date_to_xmlschema }}</published>
40
59
  <updated>{{ post.last_modified_at | default: post.date | date_to_xmlschema }}</updated>
41
60
  <id>{{ post.id | absolute_url | xml_escape }}</id>
42
- <content type="html" xml:base="{{ post.url | absolute_url | xml_escape }}">{{ post.content | strip | xml_escape }}</content>
61
+ {% assign excerpt_only = post.feed.excerpt_only | default: site.feed.excerpt_only %}
62
+ {% unless excerpt_only %}
63
+ <content type="html" xml:base="{{ post.url | absolute_url | xml_escape }}">{{ post.content | strip | xml_escape }}</content>
64
+ {% endunless %}
43
65
 
44
66
  {% assign post_author = post.author | default: post.authors[0] | default: site.author %}
45
67
  {% assign post_author = site.data.authors[post_author] | default: post_author %}
@@ -59,6 +81,10 @@
59
81
 
60
82
  {% if post.category %}
61
83
  <category term="{{ post.category | xml_escape }}" />
84
+ {% elsif post.categories %}
85
+ {% for category in post.categories %}
86
+ <category term="{{ category | xml_escape }}" />
87
+ {% endfor %}
62
88
  {% endif %}
63
89
 
64
90
  {% for tag in post.tags %}
@@ -75,6 +101,7 @@
75
101
  {% assign post_image = post_image | absolute_url %}
76
102
  {% endunless %}
77
103
  <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="{{ post_image | xml_escape }}" />
104
+ <media:content medium="image" url="{{ post_image | xml_escape }}" xmlns:media="http://search.yahoo.com/mrss/" />
78
105
  {% endif %}
79
106
  </entry>
80
107
  {% endfor %}
@@ -8,8 +8,16 @@ module JekyllFeed
8
8
  # Main plugin action, called by Jekyll-core
9
9
  def generate(site)
10
10
  @site = site
11
- return if file_exists?(feed_path)
12
- @site.pages << content_for_file(feed_path, feed_source_path)
11
+ collections.each do |name, meta|
12
+ Jekyll.logger.info "Jekyll Feed:", "Generating feed for #{name}"
13
+ (meta["categories"] + [nil]).each do |category|
14
+ path = feed_path(:collection => name, :category => category)
15
+ next if file_exists?(path)
16
+
17
+ @site.pages << make_page(path, :collection => name, :category => category)
18
+ end
19
+ end
20
+ generate_feed_by_tag if config["tags"] && !@site.tags.empty?
13
21
  end
14
22
 
15
23
  private
@@ -18,40 +26,115 @@ module JekyllFeed
18
26
  # 1. A '>', which closes an XML tag or
19
27
  # 2. A '}', which closes a Liquid tag
20
28
  # We will strip all of this whitespace to minify the template
21
- MINIFY_REGEX = %r!(?<=>|})\s+!
22
-
23
- # Path to feed from config, or feed.xml for default
24
- def feed_path
25
- if @site.config["feed"] && @site.config["feed"]["path"]
26
- @site.config["feed"]["path"]
27
- else
28
- "feed.xml"
29
+ MINIFY_REGEX = %r!(?<=>|})\s+!.freeze
30
+
31
+ # Returns the plugin's config or an empty hash if not set
32
+ def config
33
+ @config ||= @site.config["feed"] || {}
34
+ end
35
+
36
+ # Determines the destination path of a given feed
37
+ #
38
+ # collection - the name of a collection, e.g., "posts"
39
+ # category - a category within that collection, e.g., "news"
40
+ #
41
+ # Will return "/feed.xml", or the config-specified default feed for posts
42
+ # Will return `/feed/category.xml` for post categories
43
+ # WIll return `/feed/collection.xml` for other collections
44
+ # Will return `/feed/collection/category.xml` for other collection categories
45
+ def feed_path(collection: "posts", category: nil)
46
+ prefix = collection == "posts" ? "/feed" : "/feed/#{collection}"
47
+ return "#{prefix}/#{category}.xml" if category
48
+
49
+ collections.dig(collection, "path") || "#{prefix}.xml"
50
+ end
51
+
52
+ # Returns a hash representing all collections to be processed and their metadata
53
+ # in the form of { collection_name => { categories = [...], path = "..." } }
54
+ def collections
55
+ return @collections if defined?(@collections)
56
+
57
+ @collections = if config["collections"].is_a?(Array)
58
+ config["collections"].map { |c| [c, {}] }.to_h
59
+ elsif config["collections"].is_a?(Hash)
60
+ config["collections"]
61
+ else
62
+ {}
63
+ end
64
+
65
+ @collections = normalize_posts_meta(@collections)
66
+ @collections.each_value do |meta|
67
+ meta["categories"] = (meta["categories"] || []).to_set
68
+ end
69
+
70
+ @collections
71
+ end
72
+
73
+ def generate_feed_by_tag
74
+ tags_config = config["tags"]
75
+ tags_config = {} unless tags_config.is_a?(Hash)
76
+
77
+ except = tags_config["except"] || []
78
+ only = tags_config["only"] || @site.tags.keys
79
+ tags_pool = only - except
80
+ tags_path = tags_config["path"] || "/feed/by_tag/"
81
+
82
+ generate_tag_feed(tags_pool, tags_path)
83
+ end
84
+
85
+ def generate_tag_feed(tags_pool, tags_path)
86
+ tags_pool.each do |tag|
87
+ # allow only tags with basic alphanumeric characters and underscore to keep
88
+ # feed path simple.
89
+ next if %r![^a-zA-Z0-9_]!.match?(tag)
90
+
91
+ Jekyll.logger.info "Jekyll Feed:", "Generating feed for posts tagged #{tag}"
92
+ path = "#{tags_path}#{tag}.xml"
93
+ next if file_exists?(path)
94
+
95
+ @site.pages << make_page(path, :tags => tag)
29
96
  end
30
97
  end
31
98
 
32
99
  # Path to feed.xml template file
33
100
  def feed_source_path
34
- File.expand_path "feed.xml", __dir__
101
+ @feed_source_path ||= File.expand_path "feed.xml", __dir__
102
+ end
103
+
104
+ def feed_template
105
+ @feed_template ||= File.read(feed_source_path).gsub(MINIFY_REGEX, "")
35
106
  end
36
107
 
37
108
  # Checks if a file already exists in the site source
38
109
  def file_exists?(file_path)
39
- if @site.respond_to?(:in_source_dir)
40
- File.exist? @site.in_source_dir(file_path)
41
- else
42
- File.exist? Jekyll.sanitized_path(@site.source, file_path)
43
- end
110
+ File.exist? @site.in_source_dir(file_path)
44
111
  end
45
112
 
46
113
  # Generates contents for a file
47
- def content_for_file(file_path, file_source_path)
48
- file = PageWithoutAFile.new(@site, __dir__, "", file_path)
49
- file.content = File.read(file_source_path).gsub(MINIFY_REGEX, "")
50
- file.data["layout"] = nil
51
- file.data["sitemap"] = false
52
- file.data["xsl"] = file_exists?("feed.xslt.xml")
53
- file.output
54
- file
114
+
115
+ def make_page(file_path, collection: "posts", category: nil, tags: nil)
116
+ PageWithoutAFile.new(@site, __dir__, "", file_path).tap do |file|
117
+ file.content = feed_template
118
+ file.data.merge!(
119
+ "layout" => nil,
120
+ "sitemap" => false,
121
+ "xsl" => file_exists?("feed.xslt.xml"),
122
+ "collection" => collection,
123
+ "category" => category,
124
+ "tags" => tags
125
+ )
126
+ file.output
127
+ end
128
+ end
129
+
130
+ # Special case the "posts" collection, which, for ease of use and backwards
131
+ # compatability, can be configured via top-level keys or directly as a collection
132
+ def normalize_posts_meta(hash)
133
+ hash["posts"] ||= {}
134
+ hash["posts"]["path"] ||= config["path"]
135
+ hash["posts"]["categories"] ||= config["categories"]
136
+ config["path"] ||= hash["posts"]["path"]
137
+ hash
55
138
  end
56
139
  end
57
140
  end
@@ -7,14 +7,14 @@ module JekyllFeed
7
7
 
8
8
  def render(context)
9
9
  @context = context
10
- attrs = attributes.map { |k, v| %(#{k}="#{v}") }.join(" ")
10
+ attrs = attributes.map { |k, v| %(#{k}=#{v.encode(:xml => :attr)}) }.join(" ")
11
11
  "<link #{attrs} />"
12
12
  end
13
13
 
14
14
  private
15
15
 
16
16
  def config
17
- @context.registers[:site].config
17
+ @config ||= @context.registers[:site].config
18
18
  end
19
19
 
20
20
  def attributes
@@ -27,11 +27,7 @@ module JekyllFeed
27
27
  end
28
28
 
29
29
  def path
30
- if config["feed"] && config["feed"]["path"]
31
- config["feed"]["path"]
32
- else
33
- "feed.xml"
34
- end
30
+ config.dig("feed", "path") || "feed.xml"
35
31
  end
36
32
 
37
33
  def title