diff --git a/lib/jekyll-seo-tag.rb b/lib/jekyll-seo-tag.rb index 7d3a736..4707faa 100644 --- a/lib/jekyll-seo-tag.rb +++ b/lib/jekyll-seo-tag.rb @@ -1,4 +1,6 @@ +require "jekyll" require "jekyll-seo-tag/version" +require "jekyll-seo-tag/drop" module Jekyll class SeoTag < Liquid::Tag @@ -36,15 +38,15 @@ module Jekyll def payload { - "page" => context.registers[:page], - "site" => context.registers[:site].site_payload["site"], + "page" => @context.registers[:page], + "site" => @context.registers[:site].site_payload["site"], "paginator" => context["paginator"], - "seo_tag" => options, + "seo_tag" => drop, } end - def title? - @text !~ %r!title=false!i + def drop + Jekyll::SeoTag::Drop.new(@text, @context) end def info diff --git a/lib/jekyll-seo-tag/context.rb b/lib/jekyll-seo-tag/context.rb new file mode 100644 index 0000000..cb1bf1f --- /dev/null +++ b/lib/jekyll-seo-tag/context.rb @@ -0,0 +1,16 @@ +module Jekyll + class SeoTag + # Stubbed LiquidContext to support relative_url and absolute_url helpers + class Context + attr_reader :site + + def initialize(site) + @site = site + end + + def registers + { :site => site } + end + end + end +end diff --git a/lib/jekyll-seo-tag/drop.rb b/lib/jekyll-seo-tag/drop.rb new file mode 100644 index 0000000..097c6c7 --- /dev/null +++ b/lib/jekyll-seo-tag/drop.rb @@ -0,0 +1,184 @@ +module Jekyll + class SeoTag + class Drop < Jekyll::Drops::Drop + TITLE_SEPARATOR = " | " + include Jekyll::Filters + include Liquid::StandardFilters + + def initialize(text, context) + @obj = {} + @mutations = {} + @text = text + @context = context + end + + def version + Jekyll::SeoTag::VERSION + end + + # Should the `` tag be generated for this page? + def title? + @text !~ %r!title=false!i && title + end + + def site_title + format_string(site["title"] || site["name"]) + end + + # Page title without site title or description appended + def page_title + format_string(page["title"] || site_title) + end + + # Page title with site title or description appended + def title + if page["title"] && site_title + format_string(page["title"]) + TITLE_SEPARATOR + site_title + elsif site["description"] && site_title + site_title + TITLE_SEPARATOR + format_string(site["description"]) + else + format_string(page["title"]) || site_title + end + end + + def name + if page["seo"] && page["seo"]["name"] + format_string page["seo"]["name"] + elsif homepage_or_about? && site["social"] && site["social"]["name"] + format_string site["social"]["name"] + elsif homepage_or_about? && site_title + format_string site_title + end + end + + def description + format_string(page["description"] || page["excerpt"] || site["description"]) + 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` + def author + author = page["author"] + author = page["authors"][0] if author.to_s.empty? && page["authors"] + author = site["author"] if author.to_s.empty? + return if author.to_s.empty? + + if author.is_a?(String) + if site.data["authors"] && site.data["authors"][author] + author = site.data["authors"][author] + else + author = { "name" => author } + end + end + + author["twitter"] ||= author["name"] + author["twitter"].gsub! "@", "" + author.to_liquid + end + + def date_modified + return page["seo"].date_modified if page["seo"] && page["seo"]["date_modified"] + page["last_modified_at"] || page["date"] + end + + def type + if page["seo"] && page["seo"]["type"] + page["seo"]["type"] + elsif homepage_or_about? + "WebSite" + elsif page["date"] + "BlogPosting" + else + "WebPage" + end + end + + def links + if page["seo"] && page["seo"]["links"] + page["seo"]["links"] + elsif homepage_or_about? && site["social"] && site["social"]["links"] + site["social"]["links"] + end + end + + # TODO escape + def logo + return unless site["logo"] + if absolute_url? site["logo"] + site["logo"] + else + absolute_url site["logo"] + end + end + + # Returns nil or a hash representing the page image + # The image hash will always contain a path, pulled from: + # + # 1. The `image` key if it's a string + # 2. The `image.path` key if it's a hash + # 3. The `image.facebook` key + # 4. The `image.twitter` key + # + # The resulting path is always an absolute URL + # TODO escape + def image + return unless image = page["image"] + + image = { "path" => image } if image.is_a?(String) + image["path"] ||= image["facebook"] || image["twitter"] + + unless absolute_url? image["path"] + image["path"] = absolute_url image["path"] + end + + image.to_liquid + end + + def page_lang + page["lang"] || site["lang"] || "en_US" + end + + private + + def page + @page ||= @context.registers[:page].to_liquid + end + + def site + @site ||= @context.registers[:site].site_payload["site"].to_liquid + end + + def homepage_or_about? + ["/", "/index.html", "/about/"].include? page["url"] + end + + def context + @context + end + + def fallback_data + {} + end + + def absolute_url?(string) + string.include? "://" + end + + def format_string(string) + methods = %i(markdownify strip_html normalize_whitespace escape_once) + methods.each do |method| + string = public_send(method, string) + end + + string unless string.empty? + end + end + end +end diff --git a/lib/template.html b/lib/template.html index e3375c2..b28fd7b 100755 --- a/lib/template.html +++ b/lib/template.html @@ -1,143 +1,39 @@ <!-- Begin Jekyll SEO tag v{{ seo_tag.version }} --> - -{% if page.url == "/" or page.url == "/about/" %} - {% assign seo_homepage_or_about = true %} +{% if seo_tag.title? %} + <title>{{ seo_tag.title }} {% endif %} -{% assign seo_site_title = site.title | default: site.name %} -{% assign seo_page_title = page.title | default: seo_site_title %} -{% assign seo_title = page.title | default: seo_site_title %} - -{% if page.title and seo_site_title %} - {% assign seo_title = page.title | append:" | " | append: seo_site_title %} -{% elsif site.description and seo_site_title %} - {% assign seo_title = seo_site_title | append:" | " | append: site.description %} +{% if seo_tag.page_title %} + {% endif %} -{% if page.seo and page.seo.name %} - {% assign seo_name = page.seo.name %} -{% elsif seo_homepage_or_about and site.social and site.social.name %} - {% assign seo_name = site.social.name %} -{% elsif seo_homepage_or_about and seo_site_title %} - {% assign seo_name = seo_site_title %} -{% endif %} -{% if seo_name %} - {% assign seo_name = seo_name | smartify | strip_html | normalize_whitespace | escape_once %} +{% if seo_tag.author.name %} + {% endif %} -{% if seo_title %} - {% assign seo_title = seo_title | smartify | strip_html | normalize_whitespace | escape_once %} + + +{% if seo_tag.description %} + + {% endif %} -{% if seo_site_title %} - {% assign seo_site_title = seo_site_title | smartify | strip_html | normalize_whitespace | escape_once %} -{% endif %} - -{% if seo_page_title %} - {% assign seo_page_title = seo_page_title | smartify | strip_html | normalize_whitespace | escape_once %} -{% endif %} - -{% assign seo_description = page.description | default: page.excerpt | default: site.description %} -{% if seo_description %} - {% assign seo_description = seo_description | markdownify | strip_html | normalize_whitespace | escape_once %} -{% endif %} - -{% assign seo_author = page.author | default: page.authors[0] | default: site.author %} -{% if seo_author %} - {% if seo_author.name %} - {% assign seo_author_name = seo_author.name %} - {% else %} - {% if site.data.authors and site.data.authors[seo_author] %} - {% assign seo_author_name = site.data.authors[seo_author].name %} - {% else %} - {% assign seo_author_name = seo_author %} - {% endif %} - {% endif %} - {% if seo_author.twitter %} - {% assign seo_author_twitter = seo_author.twitter %} - {% else %} - {% if site.data.authors and site.data.authors[seo_author] %} - {% assign seo_author_twitter = site.data.authors[seo_author].twitter %} - {% else %} - {% assign seo_author_twitter = seo_author %} - {% endif %} - {% endif %} - {% assign seo_author_twitter = seo_author_twitter | replace:"@","" %} -{% endif %} - -{% if page.date_modified or page.last_modified_at or page.date %} - {% assign seo_date_modified = page.seo.date_modified | default: page.last_modified_at %} -{% endif %} - -{% if page.seo and page.seo.type %} - {% assign seo_type = page.seo.type %} -{% elsif seo_homepage_or_about %} - {% assign seo_type = "WebSite" %} -{% elsif page.date %} - {% assign seo_type = "BlogPosting" %} -{% else %} - {% assign seo_type = "WebPage" %} -{% endif %} - -{% if page.seo and page.seo.links %} - {% assign seo_links = page.seo.links %} -{% elsif seo_homepage_or_about and site.social and site.social.links %} - {% assign seo_links = site.social.links %} -{% endif %} - -{% if site.logo %} - {% assign seo_site_logo = site.logo %} - {% unless seo_site_logo contains "://" %} - {% assign seo_site_logo = seo_site_logo | absolute_url %} - {% endunless %} - {% assign seo_site_logo = seo_site_logo | escape %} -{% endif %} - -{% if page.image %} - {% assign seo_page_image = page.image.path | default: page.image.facebook | default: page.image.twitter | default: page.image %} - {% unless seo_page_image contains "://" %} - {% assign seo_page_image = seo_page_image | absolute_url %} - {% endunless %} - {% assign seo_page_image = seo_page_image | escape %} -{% endif %} - -{% assign seo_page_lang = page.lang | default: site.lang | default: "en_US" %} - -{% if seo_tag.title and seo_title %} - {{ seo_title }} -{% endif %} - -{% if seo_page_title %} - -{% endif %} - -{% if seo_author_name %} - -{% endif %} - - - -{% if seo_description %} - - -{% endif %} - -{% if page.url %} +{% if site.url %} {% endif %} -{% if seo_site_title %} - +{% if seo_tag.site_title %} + {% endif %} -{% if seo_page_image %} - - {% if page.image.height %} - +{% if seo_tag.image %} + + {% if seo_tag.image.height %} + {% endif %} - {% if page.image.width %} - + {% if seo_tag.image.width %} + {% endif %} {% endif %} @@ -153,8 +49,9 @@ {% endif %} +{{ seo_tag.author | jsonify }} {% if site.twitter %} - {% if seo_page_image or page.image.twitter %} + {% if seo_tag.image %} {% else %} @@ -162,8 +59,8 @@ - {% if seo_author_twitter %} - + {% if seo_tag.author.twitter %} + {% endif %} {% endif %} @@ -185,12 +82,15 @@ {% if site.webmaster_verifications.google %} {% endif %} + {% if site.webmaster_verifications.bing %} {% endif %} + {% if site.webmaster_verifications.alexa %} {% endif %} + {% if site.webmaster_verifications.yandex %} {% endif %} @@ -203,63 +103,63 @@ { "@context": "http://schema.org", -{% if seo_type %} - "@type": {{ seo_type | jsonify }}, +{% if seo_tag.type %} + "@type": {{ seo_tag.type | jsonify }}, {% endif %} -{% if seo_name %} - "name": {{ seo_name | jsonify }}, +{% if seo_tag.name %} + "name": {{ seo_tag.name | jsonify }}, {% endif %} -{% if seo_page_title %} - "headline": {{ seo_page_title | jsonify }}, +{% if seo_tag.page_title %} + "headline": {{ seo_tag.page_title | jsonify }}, {% endif %} -{% if seo_author %} +{% if seo_tag.author %} "author": { "@type": "Person", - "name": {{ seo_author | jsonify }} + "name": {{ seo_tag.author.name | jsonify }} }, {% endif %} -{% if seo_page_image %} - "image": {{ seo_page_image | jsonify }}, +{% if seo_tag.image %} + "image": {{ seo_tag.image.path | jsonify }}, {% endif %} {% if page.date %} "datePublished": {{ page.date | date_to_xmlschema | jsonify }}, {% endif %} -{% if seo_date_modified %} - "dateModified": {{ seo_date_modified | date_to_xmlschema | jsonify }}, +{% if seo_tag.date_modified %} + "dateModified": {{ seo_tag.date_modified | date_to_xmlschema | jsonify }}, {% endif %} -{% if seo_description %} - "description": {{ seo_description | jsonify }}, +{% if seo_tag.description %} + "description": {{ seo_tag.description | jsonify }}, {% endif %} -{% if seo_site_logo %} +{% if seo_tag.logo %} "publisher": { "@type": "Organization", - {% if seo_author %} - "name": {{ seo_author | jsonify }}, + {% if seo_tag.author %} + "name": {{ seo_tag.author.name | jsonify }}, {% endif %} "logo": { "@type": "ImageObject", - "url": {{ seo_site_logo | jsonify }} + "url": {{ seo_tag.logo | jsonify }} } }, {% endif %} -{% if seo_type == "BlogPosting" or seo_type == "CreativeWork"%} +{% if seo_tag.type == "BlogPosting" or seo_tag.type == "CreativeWork"%} "mainEntityOfPage": { "@type": "WebPage", "@id": {{ page.url | replace:'/index.html','/' | absolute_url | jsonify }} }, {% endif %} -{% if seo_links %} - "sameAs": {{ seo_links | jsonify }}, +{% if seo_tag.links %} + "sameAs": {{ seo_tag.links | jsonify }}, {% endif %} "url": {{ page.url | replace:'/index.html','/' | absolute_url | jsonify }}