From 77288c6480826059f1ebbe0f9d4aac3cffbe21be Mon Sep 17 00:00:00 2001 From: Goulven Champenois Date: Wed, 14 Nov 2018 15:35:40 +0100 Subject: [PATCH 1/7] Output feed links for collections --- lib/jekyll-feed/generator.rb | 28 ++++++++++++++-------------- lib/jekyll-feed/meta-tag.rb | 24 ++++++++++++++++-------- spec/jekyll-feed_spec.rb | 26 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/lib/jekyll-feed/generator.rb b/lib/jekyll-feed/generator.rb index 13684056..3fd11c6a 100644 --- a/lib/jekyll-feed/generator.rb +++ b/lib/jekyll-feed/generator.rb @@ -19,19 +19,6 @@ def generate(site) 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" @@ -45,7 +32,7 @@ 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" + @collections.dig(collection, "path") || "#{prefix}.xml" end # Returns a hash representing all collections to be processed and their metadata @@ -69,6 +56,19 @@ def collections @collections 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 + # Path to feed.xml template file def feed_source_path @feed_source_path ||= File.expand_path "feed.xml", __dir__ diff --git a/lib/jekyll-feed/meta-tag.rb b/lib/jekyll-feed/meta-tag.rb index 76da23f0..8cb357da 100644 --- a/lib/jekyll-feed/meta-tag.rb +++ b/lib/jekyll-feed/meta-tag.rb @@ -7,8 +7,15 @@ class MetaTag < Liquid::Tag def render(context) @context = context - attrs = attributes.map { |k, v| %(#{k}="#{v}") }.join(" ") - "" + @generator = generator + links = [] + generator.collections.each do |collection, meta| + (meta["categories"] + [nil]).each do |category| + attrs = attributes(collection, category).map { |k, v| %(#{k}="#{v}") }.join(" ") + links << "" + end + end + links.reverse.join "\n" end private @@ -17,19 +24,20 @@ def config @config ||= @context.registers[:site].config end - def attributes + def generator + @generator ||= @context.registers[:site].generators.select { |it| it.is_a? JekyllFeed::Generator }.first # rubocop:disable Metrics/LineLength + end + + def attributes(collection, category) + href = absolute_url(generator.feed_path(:collection => collection, :category => category)) { :type => "application/atom+xml", :rel => "alternate", - :href => absolute_url(path), + :href => href, :title => title, }.keep_if { |_, v| v } end - def path - config.dig("feed", "path") || "feed.xml" - end - def title config["title"] || config["name"] end diff --git a/spec/jekyll-feed_spec.rb b/spec/jekyll-feed_spec.rb index 1a8cc5c7..94272816 100644 --- a/spec/jekyll-feed_spec.rb +++ b/spec/jekyll-feed_spec.rb @@ -269,6 +269,32 @@ expect(feed_meta).not_to include("title=") end end + context "with a collection" do + let(:overrides) do + { + "collections" => { + "collection" => { + "output" => true, + }, + }, + "feed" => { + "collections" => { + "collection" => { + "categories" => ["news"], + }, + }, + }, + } + end + it "renders a feed meta for each collection" do + default_feed = '' + collection_feed = '' + category_feed = '' + expect(feed_meta).to include(default_feed) + expect(feed_meta).to include(collection_feed) + expect(feed_meta).to include(category_feed) + end + end end context "changing the feed path" do From 4d580454808d7294376601c7a02fb3b01ef12ffe Mon Sep 17 00:00:00 2001 From: Goulven Champenois Date: Sat, 17 Nov 2018 19:14:43 +0100 Subject: [PATCH 2/7] Make feed_meta helper collection- and category-aware --- README.md | 4 ++ lib/jekyll-feed/meta-tag.rb | 51 +++++++++++++++++++--- spec/jekyll-feed_spec.rb | 86 ++++++++++++++++++++++++++----------- 3 files changed, 108 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 84d68634..882227d3 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,10 @@ There are several ways to convey author-specific information. Author information 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. +The helper can also generate the link for a given collection: `{% feed_meta my_collection %}` or a given category: `{% feed_meta my_collection my_category %}`. + +To generate links for every collections and categories, call the helper using this syntax: `{% feed_meta include: all %}`. + ### 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. diff --git a/lib/jekyll-feed/meta-tag.rb b/lib/jekyll-feed/meta-tag.rb index 8cb357da..d520127e 100644 --- a/lib/jekyll-feed/meta-tag.rb +++ b/lib/jekyll-feed/meta-tag.rb @@ -5,17 +5,26 @@ class MetaTag < Liquid::Tag # Use Jekyll's native relative_url filter include Jekyll::Filters::URLFilters + def initialize(tag_name, args, tokens) + super + @args = args + end + def render(context) @context = context - @generator = generator - links = [] - generator.collections.each do |collection, meta| - (meta["categories"] + [nil]).each do |category| - attrs = attributes(collection, category).map { |k, v| %(#{k}="#{v}") }.join(" ") - links << "" + if @args.strip == "include: all" + links = [] + generator.collections.each do |collection, meta| + (meta["categories"] + [nil]).each do |category| + links << link(collection, category) + end end + links.reverse.join "\n" + else + @collection, @category = @args.split(" ") + @collection ||= "posts" + link(@collection, @category) if valid_collection && valid_category end - links.reverse.join "\n" end private @@ -28,6 +37,11 @@ def generator @generator ||= @context.registers[:site].generators.select { |it| it.is_a? JekyllFeed::Generator }.first # rubocop:disable Metrics/LineLength end + def link(collection, category) + attrs = attributes(collection, category).map { |k, v| %(#{k}="#{v}") }.join(" ") + "" + end + def attributes(collection, category) href = absolute_url(generator.feed_path(:collection => collection, :category => category)) { @@ -41,5 +55,28 @@ def attributes(collection, category) def title config["title"] || config["name"] end + + def valid_collection + return true if generator.collections.key? @collection + + Jekyll.logger.warn( + "Jekyll Feed:", + "Invalid collection name. Please review `{% feed_meta #{@args} %}`" + ) + false + end + + def valid_category + return true if @collection == "posts" || @category.nil? + + collection = generator.collections[@collection] + return true if collection.key?("categories") && collection["categories"].include?(@category) + + Jekyll.logger.warn( + "Jekyll Feed:", + "Invalid category name. Please review `{% feed_meta #{@args} %}`" + ) + false + end end end diff --git a/spec/jekyll-feed_spec.rb b/spec/jekyll-feed_spec.rb index 94272816..68d3672d 100644 --- a/spec/jekyll-feed_spec.rb +++ b/spec/jekyll-feed_spec.rb @@ -269,32 +269,6 @@ expect(feed_meta).not_to include("title=") end end - context "with a collection" do - let(:overrides) do - { - "collections" => { - "collection" => { - "output" => true, - }, - }, - "feed" => { - "collections" => { - "collection" => { - "categories" => ["news"], - }, - }, - }, - } - end - it "renders a feed meta for each collection" do - default_feed = '' - collection_feed = '' - category_feed = '' - expect(feed_meta).to include(default_feed) - expect(feed_meta).to include(collection_feed) - expect(feed_meta).to include(category_feed) - end - end end context "changing the feed path" do @@ -339,6 +313,66 @@ end end + context "selecting a particular collection" do + let(:overrides) do + { + "collections" => { + "collection" => { + "output" => true, + }, + }, + "feed" => { + "collections" => { + "collection" => { + "categories" => ["news"], + }, + }, + }, + } + end + let(:default_feed) { Liquid::Template.parse("{% feed_meta posts %}").render!(context, {}) } + let(:collection_feed) { Liquid::Template.parse("{% feed_meta collection %}").render!(context, {}) } + let(:category_feed) { Liquid::Template.parse("{% feed_meta collection news %}").render!(context, {}) } + + it "renders the feed meta for the selected collection" do + default_feed_link = '' + collection_feed_link = '' + category_feed_link = '' + expect(default_feed).to eql(default_feed_link) + expect(collection_feed).to eql(collection_feed_link) + expect(category_feed).to eql(category_feed_link) + end + end + + context "requesting all feed links" do + let(:overrides) do + { + "collections" => { + "collection" => { + "output" => true, + }, + }, + "feed" => { + "collections" => { + "collection" => { + "categories" => ["news"], + }, + }, + }, + } + end + let(:full_feed_meta) { Liquid::Template.parse("{% feed_meta include: all %}").render!(context, {}) } + + it "renders the feed meta for all collections and categories" do + default_feed_link = '' + collection_feed_link = '' + category_feed_link = '' + expect(full_feed_meta).to include(default_feed_link) + expect(full_feed_meta).to include(collection_feed_link) + expect(full_feed_meta).to include(category_feed_link) + end + end + context "feed stylesheet" do it "includes the stylesheet" do expect(contents).to include('') From 416c2c20b3a8bafe694d0d4e1dde5f228f8c790a Mon Sep 17 00:00:00 2001 From: Ashwin Maroli Date: Wed, 6 Feb 2019 10:01:53 +0100 Subject: [PATCH 3/7] Improve memory by stripping `args` when they are stored As recommended by @ashmaroli Co-Authored-By: goulvench --- lib/jekyll-feed/meta-tag.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jekyll-feed/meta-tag.rb b/lib/jekyll-feed/meta-tag.rb index d520127e..2747e50b 100644 --- a/lib/jekyll-feed/meta-tag.rb +++ b/lib/jekyll-feed/meta-tag.rb @@ -7,7 +7,7 @@ class MetaTag < Liquid::Tag def initialize(tag_name, args, tokens) super - @args = args + @args = args.strip end def render(context) From bb8d50e0af93a048e37c18281fe010820452ac61 Mon Sep 17 00:00:00 2001 From: Goulven Champenois Date: Wed, 6 Feb 2019 10:31:35 +0100 Subject: [PATCH 4/7] Initialize variables outside conditional for more robust code Recommended by @ashmaroli --- lib/jekyll-feed/meta-tag.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/jekyll-feed/meta-tag.rb b/lib/jekyll-feed/meta-tag.rb index 2747e50b..f3f0eee6 100644 --- a/lib/jekyll-feed/meta-tag.rb +++ b/lib/jekyll-feed/meta-tag.rb @@ -12,6 +12,9 @@ def initialize(tag_name, args, tokens) def render(context) @context = context + @collection = nil + @category = nil + if @args.strip == "include: all" links = [] generator.collections.each do |collection, meta| From 298dcdb14edd540012b595816d9703f482a789cf Mon Sep 17 00:00:00 2001 From: Goulven Champenois Date: Wed, 6 Feb 2019 10:32:04 +0100 Subject: [PATCH 5/7] Refactor `#generator` for readability and speed Recommended by @ashmaroli --- lib/jekyll-feed/meta-tag.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/jekyll-feed/meta-tag.rb b/lib/jekyll-feed/meta-tag.rb index f3f0eee6..fe0ad7b6 100644 --- a/lib/jekyll-feed/meta-tag.rb +++ b/lib/jekyll-feed/meta-tag.rb @@ -37,7 +37,9 @@ def config end def generator - @generator ||= @context.registers[:site].generators.select { |it| it.is_a? JekyllFeed::Generator }.first # rubocop:disable Metrics/LineLength + @generator ||= @context.registers[:site].generators.find do |generator| + generator.is_a? JekyllFeed::Generator + end end def link(collection, category) From 05fed0e55e0f55192a7beec75c45582d0ec13889 Mon Sep 17 00:00:00 2001 From: Ashwin Maroli Date: Wed, 6 Feb 2019 13:56:02 +0100 Subject: [PATCH 6/7] Remove unneeded strip Thanks @ashmaroli for spotting that one! Co-Authored-By: goulvench --- lib/jekyll-feed/meta-tag.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jekyll-feed/meta-tag.rb b/lib/jekyll-feed/meta-tag.rb index fe0ad7b6..c16213d6 100644 --- a/lib/jekyll-feed/meta-tag.rb +++ b/lib/jekyll-feed/meta-tag.rb @@ -15,7 +15,7 @@ def render(context) @collection = nil @category = nil - if @args.strip == "include: all" + if @args == "include: all" links = [] generator.collections.each do |collection, meta| (meta["categories"] + [nil]).each do |category| From dcf82486050eef7ae477f5bce672242048e38e06 Mon Sep 17 00:00:00 2001 From: Ashwin Maroli Date: Wed, 6 Feb 2019 21:11:27 +0530 Subject: [PATCH 7/7] DRY repeated code with a private helper method --- lib/jekyll-feed/meta-tag.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/jekyll-feed/meta-tag.rb b/lib/jekyll-feed/meta-tag.rb index c16213d6..5456225b 100644 --- a/lib/jekyll-feed/meta-tag.rb +++ b/lib/jekyll-feed/meta-tag.rb @@ -64,11 +64,7 @@ def title def valid_collection return true if generator.collections.key? @collection - Jekyll.logger.warn( - "Jekyll Feed:", - "Invalid collection name. Please review `{% feed_meta #{@args} %}`" - ) - false + invalidate_with_warning("collection") end def valid_category @@ -77,9 +73,13 @@ def valid_category collection = generator.collections[@collection] return true if collection.key?("categories") && collection["categories"].include?(@category) + invalidate_with_warning("category") + end + + def invalidate_with_warning(type) Jekyll.logger.warn( "Jekyll Feed:", - "Invalid category name. Please review `{% feed_meta #{@args} %}`" + "Invalid #{type} name. Please review `{% feed_meta #{@args} %}`" ) false end