move author logic to its own drop
This commit is contained in:
parent
f5dbc6c36f
commit
891d621899
2
Gemfile
2
Gemfile
|
@ -1,6 +1,4 @@
|
|||
source "https://rubygems.org"
|
||||
require "json"
|
||||
require "open-uri"
|
||||
|
||||
gemspec
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ 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 :Drop, "jekyll-seo-tag/drop"
|
||||
autoload :Filters, "jekyll-seo-tag/filters"
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
module Jekyll
|
||||
class SeoTag
|
||||
class AuthorDrop < Jekyll::Drops::Drop
|
||||
# A drop representing the current page's author
|
||||
#
|
||||
# Author name will be pulled from:
|
||||
#
|
||||
# 1. The page's `author` key
|
||||
# 2. The first author in the page's `authors` key
|
||||
# 3. The `author` key in the site config
|
||||
#
|
||||
# If the result from the name search is a string, we'll also check
|
||||
# for additional author metadata in `site.data.authors`
|
||||
def initialize(page: nil, site: nil)
|
||||
raise ArugementError unless page && site
|
||||
@mutations = {}
|
||||
@page = page
|
||||
@site = site
|
||||
end
|
||||
|
||||
# Public methods to delegate to keys of the author hash
|
||||
# Ensures keys will be present when `to_h` is called, even with nil values
|
||||
DELEGATED_METHODS = %i[name picture].freeze
|
||||
|
||||
DELEGATED_METHODS.each do |meth|
|
||||
define_method meth do
|
||||
author_hash[meth.to_s]
|
||||
end
|
||||
end
|
||||
|
||||
# AuthorDrop#to_s should return name, allowing the author drop to safely
|
||||
# replace `page.author`, if necessary, and remain backwards compatible
|
||||
alias_method :to_s, :name
|
||||
|
||||
def twitter
|
||||
return @twitter if defined? @twitter
|
||||
twitter = author_hash["twitter"] || author_hash["name"]
|
||||
@twitter = twitter.is_a?(String) ? twitter.sub(%r!^@!, "") : nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :page
|
||||
attr_reader :site
|
||||
|
||||
# Finds the page author in the page.author, page.authors, or site.author
|
||||
#
|
||||
# Returns a string or hash representing the author
|
||||
def resolved_author
|
||||
return @resolved_author if defined? @resolved_author
|
||||
sources = [page["author"]]
|
||||
sources << page["authors"].first if page["authors"].is_a?(Array)
|
||||
sources << site["author"]
|
||||
@resolved_author = sources.find { |s| !s.to_s.empty? }
|
||||
end
|
||||
|
||||
# If resolved_author is a string, attempts to find coresponding author
|
||||
# metadata in `site.data.authors`
|
||||
#
|
||||
# Returns a hash representing additional metadata or an empty hash
|
||||
def site_data_hash
|
||||
@site_data_hash ||= begin
|
||||
return {} unless resolved_author.is_a?(String)
|
||||
return {} unless site.data["authors"].is_a?(Hash)
|
||||
author_hash = site.data["authors"][resolved_author]
|
||||
author_hash.is_a?(Hash) ? author_hash : {}
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the normalized author hash representing the page author,
|
||||
# including site-wide metadata if the author is provided as a string,
|
||||
# or an empty hash, if the author cannot be resolved
|
||||
def author_hash
|
||||
if resolved_author.is_a? Hash
|
||||
resolved_author
|
||||
elsif resolved_author.is_a? String
|
||||
{ "name" => resolved_author }.merge(site_data_hash)
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
# Since author_hash is aliased to fallback_data, any values in the hash
|
||||
# will be exposed via the drop, allowing support for arbitrary metadata
|
||||
alias_method :fallback_data, :author_hash
|
||||
end
|
||||
end
|
||||
end
|
|
@ -72,29 +72,9 @@ module Jekyll
|
|||
end
|
||||
end
|
||||
|
||||
# Returns a nil or a hash representing the author
|
||||
# Author name will be pulled from:
|
||||
#
|
||||
# 1. The `author` key, if the key is a string
|
||||
# 2. The first author in the `authors` key
|
||||
# 3. The `author` key in the site config
|
||||
#
|
||||
# If the result from the name search is a string, we'll also check
|
||||
# to see if the author exists in `site.data.authors`
|
||||
# A drop representing the page author
|
||||
def author
|
||||
@author ||= begin
|
||||
return if author_string_or_hash.to_s.empty?
|
||||
|
||||
author = if author_string_or_hash.is_a?(String)
|
||||
author_hash(author_string_or_hash)
|
||||
else
|
||||
author_string_or_hash
|
||||
end
|
||||
|
||||
author["twitter"] ||= author["name"]
|
||||
author["twitter"].delete! "@" if author["twitter"]
|
||||
author.to_liquid
|
||||
end
|
||||
@author ||= AuthorDrop.new(:page => page, :site => site)
|
||||
end
|
||||
|
||||
def date_modified
|
||||
|
@ -231,35 +211,6 @@ module Jekyll
|
|||
string unless string.empty?
|
||||
end
|
||||
|
||||
def author_string_or_hash
|
||||
@author_string_or_hash ||= begin
|
||||
author = page["author"]
|
||||
author = page["authors"][0] if author.to_s.empty? && page["authors"]
|
||||
author = site["author"] if author.to_s.empty?
|
||||
author
|
||||
end
|
||||
end
|
||||
|
||||
# Given a string representing the current document's author, return
|
||||
# a normalized hash representing that author. Will try to pull from
|
||||
# site.authors if present and in the proper format.
|
||||
def author_hash(author_string)
|
||||
site_author_hash(author_string) || { "name" => author_string }
|
||||
end
|
||||
|
||||
# Given a string representing the current document's author, attempt
|
||||
# to retrieve additional metadata from site.data.authors, if present
|
||||
#
|
||||
# Returns the author hash
|
||||
def site_author_hash(author_string)
|
||||
return unless site.data["authors"] && site.data["authors"].is_a?(Hash)
|
||||
author_hash = site.data["authors"][author_string]
|
||||
return unless author_hash.is_a?(Hash)
|
||||
author_hash["name"] ||= author_string
|
||||
author_hash["twitter"] ||= author_string
|
||||
author_hash
|
||||
end
|
||||
|
||||
def seo_name
|
||||
@seo_name ||= format_string(page_seo["name"]) if page_seo["name"]
|
||||
end
|
||||
|
|
|
@ -223,6 +223,16 @@ RSpec.describe Jekyll::SeoTag::Drop do
|
|||
end
|
||||
|
||||
context "author" do
|
||||
let(:name) { "foo" }
|
||||
let(:twitter) { "foo" }
|
||||
let(:picture) { nil }
|
||||
let(:expected_hash) do
|
||||
{
|
||||
"name" => name,
|
||||
"twitter" => twitter,
|
||||
"picture" => picture,
|
||||
}
|
||||
end
|
||||
let(:data) { {} }
|
||||
let(:config) { { "author" => "site_author" } }
|
||||
let(:site) do
|
||||
|
@ -236,7 +246,7 @@ RSpec.describe Jekyll::SeoTag::Drop do
|
|||
let(:page_meta) { { "author" => "foo" } }
|
||||
|
||||
it "doesn't error" do
|
||||
expect(subject.author).to eql({ "name" => "foo", "twitter" => "foo" })
|
||||
expect(subject.author.to_h).to eql(expected_hash)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -245,7 +255,7 @@ RSpec.describe Jekyll::SeoTag::Drop do
|
|||
let(:page_meta) { { "author" => "foo" } }
|
||||
|
||||
it "doesn't error" do
|
||||
expect(subject.author).to eql({ "name" => "foo", "twitter" => "foo" })
|
||||
expect(subject.author.to_h).to eql(expected_hash)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -279,8 +289,8 @@ RSpec.describe Jekyll::SeoTag::Drop do
|
|||
"#{author_type}_author".sub("nil_", "site_").sub("empty_string_", "site_")
|
||||
end
|
||||
|
||||
it "returns a hash" do
|
||||
expect(subject.author).to be_a(Hash)
|
||||
it "returns a Drop" do
|
||||
expect(subject.author).to be_a(Jekyll::SeoTag::AuthorDrop)
|
||||
end
|
||||
|
||||
it "returns the name" do
|
||||
|
|
Loading…
Reference in New Issue