aemi-seo-tag 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4e9bd5aa03e132d5ac70d4d1467ab6ae2954e720cb567d3b4e24f9b8b0f22bee
4
+ data.tar.gz: 48746be5b30ccef44f1ee6137867c2dd7ab1f447b40bb0883087cc81e65f2d0e
5
+ SHA512:
6
+ metadata.gz: bc1b664eb653217feb33fed4687210770202d441e535181344ca35736d536c80b5c430d63151771f7e07e726d83c9748ddbfed75b0328bc679bbe42e3f75d62d
7
+ data.tar.gz: ba1053115e4cc817473ecf48a75ebfde754eb29bc77eada43897a63288923072496412ee5829f4617355ede0d291f5bb18b8a42cb95f7438685a2ddbe0e91cbe
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/aemi-seo-tag/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "aemi-seo-tag"
7
+ spec.version = Jekyll::AemiSeoTag::VERSION
8
+ spec.authors = ["Guillaume COQUARD"]
9
+ spec.email = ["public@gcqd.fr"]
10
+ spec.summary = "A Jekyll plugin to add metadata tags for search engines and social networks to better index and display your site's content. Almost the same as aemi-seo-tag. But adapted to aemi-jekyll-theme's needs."
11
+ spec.homepage = "https://github.com/aemi-dev/aemi-seo-tag"
12
+ spec.license = "MIT"
13
+
14
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
15
+ # delete this section to allow pushing this gem to any host.
16
+ if spec.respond_to?(:metadata)
17
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
+ else
19
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
20
+ end
21
+
22
+ spec.required_ruby_version = ">= 2.5.0"
23
+
24
+ spec.files = Dir["lib/*.rb"]
25
+ spec.files += Dir["lib/*.html"]
26
+ spec.files += Dir["lib/**/*.rb"]
27
+ spec.files += Dir["aemi-seo-tag.gemspec"]
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r!^exe/!) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_dependency "jekyll", ">= 3.8", "< 5.0"
33
+ spec.add_development_dependency "bundler", ">= 1.15"
34
+ spec.add_development_dependency "html-proofer", "~> 3.7"
35
+ spec.add_development_dependency "webrick"
36
+ spec.add_development_dependency "aemi"
37
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class AemiSeoTag
5
+ # A drop representing the current page's author
6
+ #
7
+ # Author name will be pulled from:
8
+ #
9
+ # 1. The page's `author` key
10
+ # 2. The first author in the page's `authors` key
11
+ # 3. The `author` key in the site config
12
+ #
13
+ # If the result from the name search is a string, we'll also check
14
+ # for additional author metadata in `site.data.authors`
15
+ class AuthorDrop < Jekyll::Drops::Drop
16
+ # Initialize a new AuthorDrop
17
+ #
18
+ # page - The page hash (e.g., Page#to_liquid)
19
+ # site - The Jekyll::Drops::SiteDrop
20
+ def initialize(page: nil, site: nil)
21
+ raise ArgumentError unless page && site
22
+
23
+ @mutations = {}
24
+ @page = page
25
+ @site = site
26
+ end
27
+
28
+ # AuthorDrop#to_s should return name, allowing the author drop to safely
29
+ # replace `page.author`, if necessary, and remain backwards compatible
30
+ def name
31
+ author_hash["name"]
32
+ end
33
+ alias_method :to_s, :name
34
+
35
+ def twitter
36
+ return @twitter if defined? @twitter
37
+
38
+ twitter = author_hash["twitter"] || author_hash["name"]
39
+ @twitter = twitter.is_a?(String) ? twitter.sub(%r!^@!, "") : nil
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :site, :page
45
+
46
+ # Finds the page author in the page.author, page.authors, or site.author
47
+ #
48
+ # Returns a string or hash representing the author
49
+ def resolved_author
50
+ return @resolved_author if defined? @resolved_author
51
+
52
+ sources = [page["author"]]
53
+ sources << page["authors"].first if page["authors"].is_a?(Array)
54
+ sources << site["author"]
55
+ @resolved_author = sources.find { |s| !s.to_s.empty? }
56
+ end
57
+
58
+ # If resolved_author is a string, attempts to find coresponding author
59
+ # metadata in `site.data.authors`
60
+ #
61
+ # Returns a hash representing additional metadata or an empty hash
62
+ def site_data_hash
63
+ @site_data_hash ||= begin
64
+ return {} unless resolved_author.is_a?(String)
65
+ return {} unless site.data["authors"].is_a?(Hash)
66
+
67
+ author_hash = site.data["authors"][resolved_author]
68
+ author_hash.is_a?(Hash) ? author_hash : {}
69
+ end
70
+ end
71
+
72
+ # Returns the normalized author hash representing the page author,
73
+ # including site-wide metadata if the author is provided as a string,
74
+ # or an empty hash, if the author cannot be resolved
75
+ def author_hash
76
+ @author_hash ||= begin
77
+ case resolved_author
78
+ when Hash
79
+ resolved_author
80
+ when String
81
+ { "name" => resolved_author }.merge!(site_data_hash)
82
+ else
83
+ {}
84
+ end
85
+ end
86
+ end
87
+
88
+ # Since author_hash is aliased to fallback_data, any values in the hash
89
+ # will be exposed via the drop, allowing support for arbitrary metadata
90
+ alias_method :fallback_data, :author_hash
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,262 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class AemiSeoTag
5
+ class Drop < Jekyll::Drops::Drop
6
+ include Jekyll::AemiSeoTag::UrlHelper
7
+
8
+ TITLE_SEPARATOR = " | "
9
+ FORMAT_STRING_METHODS = [
10
+ :markdownify, :strip_html, :normalize_whitespace, :escape_once,
11
+ ].freeze
12
+ HOMEPAGE_OR_ABOUT_REGEX = %r!^/(about/)?(index.html?)?$!.freeze
13
+
14
+ EMPTY_READ_ONLY_HASH = {}.freeze
15
+ private_constant :EMPTY_READ_ONLY_HASH
16
+
17
+ def initialize(text, context)
18
+ @obj = EMPTY_READ_ONLY_HASH
19
+ @mutations = {}
20
+ @text = text
21
+ @context = context
22
+ end
23
+
24
+ def version
25
+ Jekyll::AemiSeoTag::VERSION
26
+ end
27
+
28
+ def generator
29
+ return false unless generator
30
+ return true if generator
31
+ end
32
+
33
+ def comments
34
+ return false unless comments
35
+ return true if comments
36
+ end
37
+
38
+ # Should the `<title>` tag be generated for this page?
39
+ def title?
40
+ return false unless title
41
+ return @display_title if defined?(@display_title)
42
+
43
+ @display_title = (@text !~ %r!title=false!i)
44
+ end
45
+
46
+ def site_title
47
+ @site_title ||= format_string(site["title"] || site["name"])
48
+ end
49
+
50
+ def site_tagline
51
+ @site_tagline ||= format_string site["tagline"]
52
+ end
53
+
54
+ def site_description
55
+ @site_description ||= format_string site["description"]
56
+ end
57
+
58
+ # Page title without site title or description appended
59
+ def page_title
60
+ @page_title ||= format_string(page["title"]) || site_title
61
+ end
62
+
63
+ def site_tagline_or_description
64
+ site_tagline || site_description
65
+ end
66
+
67
+ # Page title with site title or description appended
68
+ # rubocop:disable Metrics/CyclomaticComplexity
69
+ def title
70
+ @title ||= begin
71
+ if site_title && page_title != site_title
72
+ page_title + TITLE_SEPARATOR + site_title
73
+ elsif site_description && site_title
74
+ site_title + TITLE_SEPARATOR + site_tagline_or_description
75
+ else
76
+ page_title || site_title
77
+ end
78
+ end
79
+
80
+ return page_number + @title if page_number
81
+
82
+ @title
83
+ end
84
+ # rubocop:enable Metrics/CyclomaticComplexity
85
+
86
+ def name
87
+ return @name if defined?(@name)
88
+
89
+ @name = if seo_name
90
+ seo_name
91
+ elsif !homepage_or_about?
92
+ nil
93
+ elsif site_social["name"]
94
+ format_string site_social["name"]
95
+ elsif site_title
96
+ site_title
97
+ end
98
+ end
99
+
100
+ def description
101
+ @description ||= begin
102
+ format_string(page["description"] || page["excerpt"]) || site_description
103
+ end
104
+ end
105
+
106
+ # A drop representing the page author
107
+ def author
108
+ @author ||= AuthorDrop.new(:page => page, :site => site)
109
+ end
110
+
111
+ def jsonld
112
+ return true unless generator
113
+ return false if generator == false
114
+ end
115
+
116
+ # A drop representing the JSON-LD output
117
+ def json_ld
118
+ @json_ld ||= JSONLDDrop.new(self)
119
+ end
120
+
121
+ # Returns a Drop representing the page's image
122
+ # Returns nil if the image has no path, to preserve backwards compatability
123
+ def image
124
+ @image ||= ImageDrop.new(:page => page, :context => @context)
125
+ @image if @image.path
126
+ end
127
+
128
+ def date_modified
129
+ @date_modified ||= begin
130
+ date = page_seo["date_modified"] || page["last_modified_at"].to_liquid || page["date"]
131
+ filters.date_to_xmlschema(date) if date
132
+ end
133
+ end
134
+
135
+ def date_published
136
+ @date_published ||= filters.date_to_xmlschema(page["date"]) if page["date"]
137
+ end
138
+
139
+ def type
140
+ @type ||= begin
141
+ if page_seo["type"]
142
+ page_seo["type"]
143
+ elsif homepage_or_about?
144
+ "WebSite"
145
+ elsif page["date"]
146
+ "BlogPosting"
147
+ else
148
+ "WebPage"
149
+ end
150
+ end
151
+ end
152
+
153
+ def links
154
+ @links ||= begin
155
+ if page_seo["links"]
156
+ page_seo["links"]
157
+ elsif homepage_or_about? && site_social["links"]
158
+ site_social["links"]
159
+ end
160
+ end
161
+ end
162
+
163
+ def logo
164
+ @logo ||= begin
165
+ return unless site["logo"]
166
+
167
+ if absolute_url? site["logo"]
168
+ filters.uri_escape site["logo"]
169
+ else
170
+ filters.uri_escape filters.absolute_url site["logo"]
171
+ end
172
+ end
173
+ end
174
+
175
+ def page_lang
176
+ @page_lang ||= page["lang"] || site["lang"] || "en_US"
177
+ end
178
+
179
+ def page_locale
180
+ @page_locale ||= (page["locale"] || site["locale"] || page_lang).tr("-", "_")
181
+ end
182
+
183
+ def canonical_url
184
+ @canonical_url ||= begin
185
+ if page["canonical_url"].to_s.empty?
186
+ filters.absolute_url(page["url"]).to_s.gsub(%r!/index\.html$!, "/")
187
+ else
188
+ page["canonical_url"]
189
+ end
190
+ end
191
+ end
192
+
193
+ private
194
+
195
+ def filters
196
+ @filters ||= Jekyll::AemiSeoTag::Filters.new(@context)
197
+ end
198
+
199
+ def page
200
+ @page ||= @context.registers[:page].to_liquid
201
+ end
202
+
203
+ def site
204
+ @site ||= @context.registers[:site].site_payload["site"].to_liquid
205
+ end
206
+
207
+ def homepage_or_about?
208
+ page["url"] =~ HOMEPAGE_OR_ABOUT_REGEX
209
+ end
210
+
211
+ def page_number
212
+ return unless @context["paginator"] && @context["paginator"]["page"]
213
+
214
+ current = @context["paginator"]["page"]
215
+ total = @context["paginator"]["total_pages"]
216
+ paginator_message = site["seo_paginator_message"] || "Page %<current>s of %<total>s for "
217
+
218
+ format(paginator_message, :current => current, :total => total) if current > 1
219
+ end
220
+
221
+ attr_reader :context
222
+
223
+ def fallback_data
224
+ @fallback_data ||= {}
225
+ end
226
+
227
+ def format_string(string)
228
+ string = FORMAT_STRING_METHODS.reduce(string) do |memo, method|
229
+ filters.public_send(method, memo)
230
+ end
231
+
232
+ string unless string.empty?
233
+ end
234
+
235
+ def seo_name
236
+ @seo_name ||= format_string(page_seo["name"]) if page_seo["name"]
237
+ end
238
+
239
+ def page_seo
240
+ @page_seo ||= sub_hash(page, "seo")
241
+ end
242
+
243
+ def site_social
244
+ @site_social ||= sub_hash(site, "social")
245
+ end
246
+
247
+ # Safely returns a sub hash
248
+ #
249
+ # hash - the parent hash
250
+ # key - the key in the parent hash
251
+ #
252
+ # Returns the sub hash or an empty hash, if it does not exist
253
+ def sub_hash(hash, key)
254
+ if hash[key].is_a?(Hash)
255
+ hash[key]
256
+ else
257
+ EMPTY_READ_ONLY_HASH
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class AemiSeoTag
5
+ class Filters
6
+ include Jekyll::Filters
7
+ include Liquid::StandardFilters
8
+
9
+ def initialize(context)
10
+ @context = context
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class AemiSeoTag
5
+ # A drop representing the page image
6
+ # The image path will be pulled from:
7
+ #
8
+ # 1. The `image` key if it's a string
9
+ # 2. The `image.path` key if it's a hash
10
+ # 3. The `image.facebook` key
11
+ # 4. The `image.twitter` key
12
+ class ImageDrop < Jekyll::Drops::Drop
13
+ include Jekyll::AemiSeoTag::UrlHelper
14
+
15
+ # Initialize a new ImageDrop
16
+ #
17
+ # page - The page hash (e.g., Page#to_liquid)
18
+ # context - the Liquid::Context
19
+ def initialize(page: nil, context: nil)
20
+ raise ArgumentError unless page && context
21
+
22
+ @mutations = {}
23
+ @page = page
24
+ @context = context
25
+ end
26
+
27
+ # Called path for backwards compatability, this is really
28
+ # the escaped, absolute URL representing the page's image
29
+ # Returns nil if no image path can be determined
30
+ def path
31
+ @path ||= filters.uri_escape(absolute_url) if absolute_url
32
+ end
33
+ alias_method :to_s, :path
34
+
35
+ private
36
+
37
+ attr_accessor :page, :context
38
+
39
+ # The normalized image hash with a `path` key (which may be nil)
40
+ def image_hash
41
+ @image_hash ||= begin
42
+ image_meta = page["image"]
43
+
44
+ case image_meta
45
+ when Hash
46
+ { "path" => nil }.merge!(image_meta)
47
+ when String
48
+ { "path" => image_meta }
49
+ else
50
+ { "path" => nil }
51
+ end
52
+ end
53
+ end
54
+ alias_method :fallback_data, :image_hash
55
+
56
+ def raw_path
57
+ @raw_path ||= begin
58
+ image_hash["path"] || image_hash["facebook"] || image_hash["twitter"]
59
+ end
60
+ end
61
+
62
+ def absolute_url
63
+ return unless raw_path
64
+ return @absolute_url if defined? @absolute_url
65
+
66
+ @absolute_url = if raw_path.is_a?(String) && absolute_url?(raw_path) == false
67
+ filters.absolute_url raw_path
68
+ else
69
+ raw_path
70
+ end
71
+ end
72
+
73
+ def filters
74
+ @filters ||= Jekyll::AemiSeoTag::Filters.new(context)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class AemiSeoTag
5
+ # This module is deprecated, but is included in the Gem to avoid a breaking
6
+ # change and should be removed at the next major version bump
7
+ module JSONLD
8
+ METHODS_KEYS = {
9
+ :json_context => "@context",
10
+ :type => "@type",
11
+ :name => "name",
12
+ :page_title => "headline",
13
+ :json_author => "author",
14
+ :json_image => "image",
15
+ :date_published => "datePublished",
16
+ :date_modified => "dateModified",
17
+ :description => "description",
18
+ :publisher => "publisher",
19
+ :main_entity => "mainEntityOfPage",
20
+ :links => "sameAs",
21
+ :canonical_url => "url",
22
+ }.freeze
23
+
24
+ # Self should be a Jekyll::AemiSeoTag::Drop instance (when extending the module)
25
+ def json_ld
26
+ Jekyll.logger.warn "Jekyll::AemiSeoTag::JSONLD is deprecated"
27
+ @json_ld ||= JSONLDDrop.new(self)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class AemiSeoTag
5
+ class JSONLDDrop < Jekyll::Drops::Drop
6
+ extend Forwardable
7
+
8
+ def_delegator :page_drop, :name, :name
9
+ def_delegator :page_drop, :description, :description
10
+ def_delegator :page_drop, :canonical_url, :url
11
+ def_delegator :page_drop, :page_title, :headline
12
+ def_delegator :page_drop, :date_modified, :dateModified
13
+ def_delegator :page_drop, :date_published, :datePublished
14
+ def_delegator :page_drop, :links, :sameAs
15
+ def_delegator :page_drop, :logo, :logo
16
+ def_delegator :page_drop, :type, :type
17
+
18
+ # Expose #type and #logo as private methods and #@type as a public method
19
+ alias_method :@type, :type
20
+ private :type, :logo
21
+
22
+ VALID_ENTITY_TYPES = %w(BlogPosting CreativeWork).freeze
23
+ VALID_AUTHOR_TYPES = %w(Organization Person).freeze
24
+ private_constant :VALID_ENTITY_TYPES, :VALID_AUTHOR_TYPES
25
+
26
+ # page_drop should be an instance of Jekyll::AemiSeoTag::Drop
27
+ def initialize(page_drop)
28
+ @mutations = {}
29
+ @page_drop = page_drop
30
+ end
31
+
32
+ def fallback_data
33
+ @fallback_data ||= {
34
+ "@context" => "https://schema.org",
35
+ }
36
+ end
37
+
38
+ def author
39
+ return unless page_drop.author["name"]
40
+
41
+ author_type = page_drop.author["type"]
42
+ return if author_type && !VALID_AUTHOR_TYPES.include?(author_type)
43
+
44
+ hash = {
45
+ "@type" => author_type || "Person",
46
+ "name" => page_drop.author["name"],
47
+ }
48
+
49
+ author_url = page_drop.author["url"]
50
+ hash["url"] = author_url if author_url
51
+
52
+ hash
53
+ end
54
+
55
+ def image
56
+ return unless page_drop.image
57
+ return page_drop.image.path if page_drop.image.keys.length == 1
58
+
59
+ hash = page_drop.image.to_h
60
+ hash["url"] = hash.delete("path")
61
+ hash["@type"] = "imageObject"
62
+ hash
63
+ end
64
+
65
+ def publisher
66
+ return unless logo
67
+
68
+ output = {
69
+ "@type" => "Organization",
70
+ "logo" => {
71
+ "@type" => "ImageObject",
72
+ "url" => logo,
73
+ },
74
+ }
75
+ output["name"] = page_drop.author.name if page_drop.author.name
76
+ output
77
+ end
78
+
79
+ def main_entity
80
+ return unless VALID_ENTITY_TYPES.include?(type)
81
+
82
+ {
83
+ "@type" => "WebPage",
84
+ "@id" => page_drop.canonical_url,
85
+ }
86
+ end
87
+ alias_method :mainEntityOfPage, :main_entity
88
+ private :main_entity
89
+
90
+ # Returns a JSON-encoded object containing the JSON-LD data.
91
+ # Keys are sorted.
92
+ def to_json(state = nil)
93
+ keys.sort.each_with_object({}) do |(key, _), result|
94
+ v = self[key]
95
+ result[key] = v unless v.nil?
96
+ end.to_json(state)
97
+ end
98
+
99
+ private
100
+
101
+ attr_reader :page_drop
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class AemiSeoTag
5
+ # Mixin to share common URL-related methods between class
6
+ module UrlHelper
7
+ private
8
+
9
+ # Determines if the given string is an absolute URL
10
+ #
11
+ # Returns true if an absolute URL
12
+ # Returns false if it's a relative URL
13
+ # Returns nil if it is not a string or can't be parsed as a URL
14
+ def absolute_url?(string)
15
+ return unless string
16
+
17
+ Addressable::URI.parse(string).absolute?
18
+ rescue Addressable::URI::InvalidURIError
19
+ nil
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Prevent bundler errors
4
+ module Liquid; class Tag; end; end
5
+
6
+ module Jekyll
7
+ class AemiSeoTag < Liquid::Tag
8
+ VERSION = "0.0.5"
9
+ end
10
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jekyll"
4
+ require "aemi-seo-tag/version"
5
+
6
+ module Jekyll
7
+ class AemiSeoTag < Liquid::Tag
8
+ autoload :JSONLD, "aemi-seo-tag/json_ld"
9
+ autoload :AuthorDrop, "aemi-seo-tag/author_drop"
10
+ autoload :ImageDrop, "aemi-seo-tag/image_drop"
11
+ autoload :JSONLDDrop, "aemi-seo-tag/json_ld_drop"
12
+ autoload :UrlHelper, "aemi-seo-tag/url_helper"
13
+ autoload :Drop, "aemi-seo-tag/drop"
14
+ autoload :Filters, "aemi-seo-tag/filters"
15
+
16
+ attr_accessor :context
17
+
18
+ # Matches all whitespace that follows either
19
+ # 1. A '}', which closes a Liquid tag
20
+ # 2. A '{', which opens a JSON block
21
+ # 3. A '>' followed by a newline, which closes an XML tag or
22
+ # 4. A ',' followed by a newline, which ends a JSON line
23
+ # We will strip all of this whitespace to minify the template
24
+ # We will not strip any whitespace if the next character is a '-'
25
+ # so that we do not interfere with the HTML comment at the
26
+ # very begining
27
+ MINIFY_REGEX = %r!(?<=[{}]|[>,]\n)\s+(?\!-)!.freeze
28
+
29
+ def initialize(_tag_name, text, _tokens)
30
+ super
31
+ @text = text
32
+ end
33
+
34
+ def render(context)
35
+ @context = context
36
+ AemiSeoTag.template.render!(payload, info)
37
+ end
38
+
39
+ private
40
+
41
+ def options
42
+ {
43
+ "version" => Jekyll::AemiSeoTag::VERSION,
44
+ "title" => title?,
45
+ }
46
+ end
47
+
48
+ def payload
49
+ # site_payload is an instance of UnifiedPayloadDrop. See https://github.com/jekyll/jekyll/blob/22f2724a1f117a94cc16d18c499a93d5915ede4f/lib/jekyll/site.rb#L261-L276
50
+ context.registers[:site].site_payload.tap do |site_payload|
51
+ site_payload["page"] = context.registers[:page]
52
+ site_payload["paginator"] = context["paginator"]
53
+ site_payload["seo_tag"] = drop
54
+ end
55
+ end
56
+
57
+ def drop
58
+ if context.registers[:site].liquid_renderer.respond_to?(:cache)
59
+ Jekyll::AemiSeoTag::Drop.new(@text, @context)
60
+ else
61
+ @drop ||= Jekyll::AemiSeoTag::Drop.new(@text, @context)
62
+ end
63
+ end
64
+
65
+ def info
66
+ {
67
+ :registers => context.registers,
68
+ :filters => [Jekyll::Filters],
69
+ }
70
+ end
71
+
72
+ class << self
73
+ def template
74
+ @template ||= Liquid::Template.parse template_contents
75
+ end
76
+
77
+ private
78
+
79
+ def template_contents
80
+ @template_contents ||= begin
81
+ File.read(template_path).gsub(MINIFY_REGEX, "")
82
+ end
83
+ end
84
+
85
+ def template_path
86
+ @template_path ||= begin
87
+ File.expand_path "./template.html", File.dirname(__FILE__)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ Liquid::Template.register_tag("seo", Jekyll::AemiSeoTag)
data/lib/template.html ADDED
@@ -0,0 +1,138 @@
1
+
2
+ {% if seo_tag.comments? %}
3
+ <!-- Begin Jekyll SEO tag v{{ seo_tag.version }} -->
4
+ {% endif %}
5
+
6
+ {% if seo_tag.title? %}
7
+ <title>{{ seo_tag.title }}</title>
8
+ {% endif %}
9
+
10
+ {% if seo_tag.generator? %}
11
+ <meta name="generator" content="Jekyll v{{ jekyll.version }}" />
12
+ {% endif %}
13
+
14
+ {% if seo_tag.page_title %}
15
+ <meta property="og:title" content="{{ seo_tag.page_title }}" />
16
+ {% endif %}
17
+
18
+ {% if seo_tag.author.name %}
19
+ <meta name="author" content="{{ seo_tag.author.name }}" />
20
+ {% endif %}
21
+
22
+ <meta property="og:locale" content="{{ seo_tag.page_locale }}" />
23
+
24
+ {% if seo_tag.description %}
25
+ <meta name="description" content="{{ seo_tag.description }}" />
26
+ <meta property="og:description" content="{{ seo_tag.description }}" />
27
+ {% endif %}
28
+
29
+ {% if site.url %}
30
+ <link rel="canonical" href="{{ seo_tag.canonical_url }}" />
31
+ <meta property="og:url" content="{{ seo_tag.canonical_url }}" />
32
+ {% endif %}
33
+
34
+ {% if seo_tag.site_title %}
35
+ <meta property="og:site_name" content="{{ seo_tag.site_title }}" />
36
+ {% endif %}
37
+
38
+ {% if seo_tag.image %}
39
+ <meta property="og:image" content="{{ seo_tag.image.path }}" />
40
+ {% if seo_tag.image.height %}
41
+ <meta property="og:image:height" content="{{ seo_tag.image.height }}" />
42
+ {% endif %}
43
+ {% if seo_tag.image.width %}
44
+ <meta property="og:image:width" content="{{ seo_tag.image.width }}" />
45
+ {% endif %}
46
+ {% if seo_tag.image.alt %}
47
+ <meta property="og:image:alt" content="{{ seo_tag.image.alt }}" />
48
+ {% endif %}
49
+ {% endif %}
50
+
51
+ {% if page.date %}
52
+ <meta property="og:type" content="article" />
53
+ <meta property="article:published_time" content="{{ page.date | date_to_xmlschema }}" />
54
+ {% else %}
55
+ <meta property="og:type" content="website" />
56
+ {% endif %}
57
+
58
+ {% if paginator.previous_page %}
59
+ <link rel="prev" href="{{ paginator.previous_page_path | absolute_url }}" />
60
+ {% endif %}
61
+ {% if paginator.next_page %}
62
+ <link rel="next" href="{{ paginator.next_page_path | absolute_url }}" />
63
+ {% endif %}
64
+
65
+ {% if seo_tag.image %}
66
+ <meta name="twitter:card" content="{{ page.twitter.card | default: site.twitter.card | default: "summary_large_image" }}" />
67
+ <meta property="twitter:image" content="{{ seo_tag.image.path }}" />
68
+ {% else %}
69
+ <meta name="twitter:card" content="summary" />
70
+ {% endif %}
71
+
72
+ {% if seo_tag.image.alt %}
73
+ <meta name="twitter:image:alt" content="{{ seo_tag.image.alt }}" />
74
+ {% endif %}
75
+
76
+ {% if seo_tag.page_title %}
77
+ <meta property="twitter:title" content="{{ seo_tag.page_title }}" />
78
+ {% endif %}
79
+
80
+ {% if site.twitter %}
81
+ <meta name="twitter:site" content="@{{ site.twitter.username | remove:'@' }}" />
82
+
83
+ {% if seo_tag.author.twitter %}
84
+ <meta name="twitter:creator" content="@{{ seo_tag.author.twitter | remove:'@' }}" />
85
+ {% endif %}
86
+ {% endif %}
87
+
88
+ {% if site.facebook %}
89
+ {% if site.facebook.admins %}
90
+ <meta property="fb:admins" content="{{ site.facebook.admins }}" />
91
+ {% endif %}
92
+
93
+ {% if site.facebook.publisher %}
94
+ <meta property="article:publisher" content="{{ site.facebook.publisher }}" />
95
+ {% endif %}
96
+
97
+ {% if site.facebook.app_id %}
98
+ <meta property="fb:app_id" content="{{ site.facebook.app_id }}" />
99
+ {% endif %}
100
+ {% endif %}
101
+
102
+ {% if site.webmaster_verifications %}
103
+ {% if site.webmaster_verifications.google %}
104
+ <meta name="google-site-verification" content="{{ site.webmaster_verifications.google }}" />
105
+ {% endif %}
106
+
107
+ {% if site.webmaster_verifications.bing %}
108
+ <meta name="msvalidate.01" content="{{ site.webmaster_verifications.bing }}" />
109
+ {% endif %}
110
+
111
+ {% if site.webmaster_verifications.alexa %}
112
+ <meta name="alexaVerifyID" content="{{ site.webmaster_verifications.alexa }}" />
113
+ {% endif %}
114
+
115
+ {% if site.webmaster_verifications.yandex %}
116
+ <meta name="yandex-verification" content="{{ site.webmaster_verifications.yandex }}" />
117
+ {% endif %}
118
+
119
+ {% if site.webmaster_verifications.baidu %}
120
+ <meta name="baidu-site-verification" content="{{ site.webmaster_verifications.baidu }}" />
121
+ {% endif %}
122
+
123
+ {% if site.webmaster_verifications.facebook %}
124
+ <meta name="facebook-domain-verification" content="{{ site.webmaster_verifications.facebook }}" />
125
+ {% endif %}
126
+ {% elsif site.google_site_verification %}
127
+ <meta name="google-site-verification" content="{{ site.google_site_verification }}" />
128
+ {% endif %}
129
+
130
+ {% if seo_tag.jsonld? != false %}
131
+ <script type="application/ld+json">
132
+ {{ seo_tag.json_ld | jsonify }}
133
+ </script>
134
+ {% endif %}
135
+
136
+ {% if seo_tag.comments? %}
137
+ <!-- End Jekyll SEO tag -->
138
+ {% endif %}
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aemi-seo-tag
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Guillaume COQUARD
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-06-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.8'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.8'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '1.15'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '1.15'
47
+ - !ruby/object:Gem::Dependency
48
+ name: html-proofer
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.7'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.7'
61
+ - !ruby/object:Gem::Dependency
62
+ name: webrick
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: aemi
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ description:
90
+ email:
91
+ - public@gcqd.fr
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - aemi-seo-tag.gemspec
97
+ - lib/aemi-seo-tag.rb
98
+ - lib/aemi-seo-tag/author_drop.rb
99
+ - lib/aemi-seo-tag/drop.rb
100
+ - lib/aemi-seo-tag/filters.rb
101
+ - lib/aemi-seo-tag/image_drop.rb
102
+ - lib/aemi-seo-tag/json_ld.rb
103
+ - lib/aemi-seo-tag/json_ld_drop.rb
104
+ - lib/aemi-seo-tag/url_helper.rb
105
+ - lib/aemi-seo-tag/version.rb
106
+ - lib/template.html
107
+ homepage: https://github.com/aemi-dev/aemi-seo-tag
108
+ licenses:
109
+ - MIT
110
+ metadata:
111
+ allowed_push_host: https://rubygems.org
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: 2.5.0
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.3.11
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: A Jekyll plugin to add metadata tags for search engines and social networks
131
+ to better index and display your site's content. Almost the same as aemi-seo-tag.
132
+ But adapted to aemi-jekyll-theme's needs.
133
+ test_files: []