From 5de6cd7f2c15b2d6ac8a6835080ae9bc6565bd22 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Wed, 23 Aug 2017 16:11:55 -0400 Subject: [PATCH] convert JSON LD to a drop --- lib/jekyll-seo-tag.rb | 11 ++-- lib/jekyll-seo-tag/drop.rb | 20 ++++--- lib/jekyll-seo-tag/jason_ld_drop.rb | 79 +++++++++++++++++++++++++ lib/jekyll-seo-tag/json_ld.rb | 59 +----------------- spec/jekyll_seo_tag_integration_spec.rb | 2 +- spec/spec_helper.rb | 9 +++ 6 files changed, 108 insertions(+), 72 deletions(-) create mode 100644 lib/jekyll-seo-tag/jason_ld_drop.rb diff --git a/lib/jekyll-seo-tag.rb b/lib/jekyll-seo-tag.rb index 1a50302..6d84dfb 100644 --- a/lib/jekyll-seo-tag.rb +++ b/lib/jekyll-seo-tag.rb @@ -3,12 +3,13 @@ require "jekyll-seo-tag/version" module Jekyll class SeoTag < Liquid::Tag - autoload :JSONLD, "jekyll-seo-tag/json_ld" + autoload :JSONLD, "jekyll-seo-tag/json_ld" autoload :AuthorDrop, "jekyll-seo-tag/author_drop" - autoload :ImageDrop, "jekyll-seo-tag/image_drop" - autoload :UrlHelper, "jekyll-seo-tag/url_helper" - autoload :Drop, "jekyll-seo-tag/drop" - autoload :Filters, "jekyll-seo-tag/filters" + autoload :ImageDrop, "jekyll-seo-tag/image_drop" + autoload :JSONLDDrop, "jekyll-seo-tag/jason_ld_drop" + autoload :UrlHelper, "jekyll-seo-tag/url_helper" + autoload :Drop, "jekyll-seo-tag/drop" + autoload :Filters, "jekyll-seo-tag/filters" attr_accessor :context diff --git a/lib/jekyll-seo-tag/drop.rb b/lib/jekyll-seo-tag/drop.rb index 2561664..a554201 100644 --- a/lib/jekyll-seo-tag/drop.rb +++ b/lib/jekyll-seo-tag/drop.rb @@ -1,7 +1,6 @@ module Jekyll class SeoTag class Drop < Jekyll::Drops::Drop - include Jekyll::SeoTag::JSONLD include Jekyll::SeoTag::UrlHelper TITLE_SEPARATOR = " | ".freeze @@ -78,6 +77,18 @@ module Jekyll @author ||= AuthorDrop.new(:page => page, :site => site) end + # A drop representing the JSON-LD output + def json_ld + @json_ld ||= JSONLDDrop.new(self) + end + + # Returns a Drop representing the page's image + # Returns nil if the image has no path, to preserve backwards compatability + def image + @image ||= ImageDrop.new(:page => page, :context => @context) + @image if @image.path + end + def date_modified @date_modified ||= begin date = if page_seo["date_modified"] @@ -130,13 +141,6 @@ module Jekyll end end - # Returns a Drop representing the page's image - # Returns nil if the image has no path, to preserve backwards compatability - def image - @image ||= ImageDrop.new(:page => page, :context => @context) - @image if @image.path - end - def page_lang @page_lang ||= page["lang"] || site["lang"] || "en_US" end diff --git a/lib/jekyll-seo-tag/jason_ld_drop.rb b/lib/jekyll-seo-tag/jason_ld_drop.rb new file mode 100644 index 0000000..22c2e8b --- /dev/null +++ b/lib/jekyll-seo-tag/jason_ld_drop.rb @@ -0,0 +1,79 @@ +module Jekyll + class SeoTag + class JSONLDDrop < Jekyll::Drops::Drop + extend Forwardable + + def_delegator :page_drop, :name, :name + def_delegator :page_drop, :description, :description + def_delegator :page_drop, :canonical_url, :url + def_delegator :page_drop, :page_title, :headline + def_delegator :page_drop, :date_modified, :dateModified + def_delegator :page_drop, :date_published, :datePublished + def_delegator :page_drop, :links, :sameAs + def_delegator :page_drop, :logo, :logo + + # Expose #type and #logo and private methods and #@type as a public method + def_delegator :page_drop, :type, :type + alias_method :"@type", :type + private :type + private :logo + + # page_drop should be an instance of Jekyll::SeoTag::Drop + def initialize(page_drop) + @mutations = {} + @page_drop = page_drop + end + + def fallback_data + { + "@context" => "http://schema.org", + } + end + + def author + return unless page_drop.author["name"] + { + "@type" => "Person", + "name" => page_drop.author["name"], + } + end + + def image + return unless page_drop.image + return page_drop.image.path if page_drop.image.keys.length == 1 + + hash = page_drop.image.to_h + hash["url"] = hash.delete("path") + hash["@type"] = "imageObject" + hash + end + + def publisher + return unless logo + output = { + "@type" => "Organization", + "logo" => { + "@type" => "ImageObject", + "url" => logo, + }, + } + output["name"] = page_drop.author.name if page_drop.author.name + output + end + + def main_entity + return unless %w(BlogPosting CreativeWork).include?(type) + { + "@type" => "WebPage", + "@id" => page_drop.canonical_url, + } + end + alias_method :mainEntityOfPage, :main_entity + private :main_entity + + private + + attr_reader :page_drop + end + end +end diff --git a/lib/jekyll-seo-tag/json_ld.rb b/lib/jekyll-seo-tag/json_ld.rb index c097770..7ac993e 100644 --- a/lib/jekyll-seo-tag/json_ld.rb +++ b/lib/jekyll-seo-tag/json_ld.rb @@ -1,8 +1,7 @@ module Jekyll class SeoTag module JSONLD - - # A hash of instance methods => key in resulting JSON-LD hash + # Unused, but here to preserve backwards compatability METHODS_KEYS = { :json_context => "@context", :type => "@type", @@ -18,62 +17,6 @@ module Jekyll :links => "sameAs", :canonical_url => "url", }.freeze - - def json_ld - @json_ld ||= begin - output = {} - METHODS_KEYS.each do |method, key| - value = send(method) - output[key] = value unless value.nil? - end - output - end - end - - private - - def json_context - "http://schema.org" - end - - def json_author - return unless author - { - "@type" => "Person", - "name" => author["name"], - } - end - - def json_image - return unless image - return image["path"] if image.keys.length == 1 - - hash = image.to_h - hash["url"] = hash.delete("path") - hash["@type"] = "imageObject" - hash - end - - def publisher - return unless logo - output = { - "@type" => "Organization", - "logo" => { - "@type" => "ImageObject", - "url" => logo, - }, - } - output["name"] = author["name"] if author - output - end - - def main_entity - return unless %w(BlogPosting CreativeWork).include?(type) - { - "@type" => "WebPage", - "@id" => canonical_url, - } - end end end end diff --git a/spec/jekyll_seo_tag_integration_spec.rb b/spec/jekyll_seo_tag_integration_spec.rb index a0f3ca8..81278b8 100755 --- a/spec/jekyll_seo_tag_integration_spec.rb +++ b/spec/jekyll_seo_tag_integration_spec.rb @@ -330,7 +330,7 @@ EOS it "minifies JSON-LD" do expected = <<-EOS.strip -{"@context":"http://schema.org","@type":"BlogPosting","headline":"post", +{"name":null,"description":"description","author":null,"@type":"BlogPosting" EOS expect(output).to match(expected) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bbb2756..81ab4ab 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,15 @@ require "jekyll" require "jekyll-seo-tag" require "html-proofer" +# Monkey patch Jekyll::Drops::Drop so Rspec's `have_key` works as expected +module Jekyll + module Drops + class Drop + alias_method :has_key?, :key? + end + end +end + ENV["JEKYLL_LOG_LEVEL"] = "error" def dest_dir