aemi-seo-tag 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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: []