seo_cache 0.2.0 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 555ef8fa31e4a10781d79a8366b6b2d72b366c9a7c9760a4be215e937bc5ad47
4
- data.tar.gz: 17849429c79a3d5aff80ee63f2d85697ba8cef0b90fdd763dc3fa5c7d63aaabe
3
+ metadata.gz: 4a029127389aa4942e27c5fbca325e56c020dfe4d35ec743034649e45700b71f
4
+ data.tar.gz: cb8f7123d7ef7a959e86f53d65c127b4195cfc2b3c21938bf0fb31c6fdcbf507
5
5
  SHA512:
6
- metadata.gz: 159fcc02649cfafdc96046d64681164e48114907de82802d6ff94207ae3861b94bb4b99410b39291267cd31ca1763d8072480d7096a921bf66327d75ad9f9b39
7
- data.tar.gz: de661dfc3d73e00a04834de214b9dc11070899a2ba2647e898a80f0876d92e77d7c2a6442c31483ba263bdb2979a5c10b395d4ce7b1128bc6c2ff498dc8ee3fd
6
+ metadata.gz: bd0f5a06df0b92a34304fad8893e3b708ef5142bd62509664dba5689fab503ffa1ae7a50901c3ee14f626c92a4d0b3994a017989e3024c8b2e6dd0083cbe47e5
7
+ data.tar.gz: 7d1e4891181adb3b9deb3cb9c7773b9328befcebfc237f4c76ce3857b6c673751a14c72403126852782726c3b2998fb3253bf7a346d3f4f4f385542b538547bf
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.3.0
2
+
3
+ - Add more examples in README
4
+ - Switch chromedriver to webdrivers
5
+ - Add tests
6
+ - Set correct URL for Github
7
+
1
8
  ## 0.2.0
2
9
 
3
10
  - Improve README
data/README.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  Cache dedicated for SEO with Javascript rendering :fire:
4
4
 
5
+ ## Purpose
6
+
7
+ Google credo is: Don't waste my bot time!
8
+
9
+ So to reduce Googlebot crawling time, let's provide HTML files in a specific cache.
10
+
11
+ This cache is suitable for static (generated or not) pages but not for connected pages.
5
12
 
6
13
  ## Installation
7
14
 
@@ -19,42 +26,98 @@ Or install it yourself as:
19
26
 
20
27
  $ gem install seo_cache
21
28
 
22
- Install chrome driver on your device
29
+ Install chromium or chrome driver on your device (the chromedriver will be automatically downloaded).
23
30
 
24
- ## How it works
31
+ Declare the middleware. For instance in `config/initializers/seo_cache.rb`:
25
32
 
26
- Specific cache for bots to optimize time to first byte and render Javascript on server side.
33
+ ```ruby
34
+ require 'seo_cache'
35
+
36
+ # See options below
27
37
 
28
- Options:
38
+ Rails.application.config.middleware.use SeoCache::Middleware
39
+ ```
29
40
 
30
- Choose a cache mode (`disk` or `memory`):
41
+ ## Options
42
+
43
+ Chrome path (**required**) (`disk` or `memory`):
44
+
45
+ SeoCache.chrome_path = Rails.env.development? ? '/usr/bin/chromium-browser' : '/usr/bin/chromium'
46
+
47
+ Choose a cache mode (`memory` (default) or `disk`):
31
48
 
32
49
  SeoCache.cache_mode = 'memory'
33
50
 
34
- If cache on disk, specify the cache path (e.g. `Rails.root.join('public', 'seo_cache')`):
51
+ Disk cache path (required if disk cache):
52
+
53
+ SeoCache.disk_cache_path = Rails.root.join('public', 'seo_cache')
54
+
55
+ Redis URL (required if memory cache):
35
56
 
36
- SeoCache.disk_cache_path = nil
57
+ SeoCache.redis_url = "redis://localhost:6379/"
58
+
59
+ Redis prefix:
60
+
61
+ SeoCache.redis_namespace = '_my_project:seo_cache'
62
+
63
+ Specific log file (if you want to log missed cache urls):
64
+
65
+ SeoCache.logger_path = Rails.root.join('log', 'seo_cache.log')
66
+
67
+ Activate missed cache urls:
68
+
69
+ SeoCache.log_missed_cache = true
37
70
 
38
71
  URLs to blacklist:
39
72
 
40
- SeoCache.blacklist_urls = []
73
+ SeoCache.blacklist_params = %w[^/assets/.* ^/admin.*]
74
+
75
+ Params to blacklist:
76
+
77
+ SeoCache.blacklist_urls = %w[page]
41
78
 
42
79
  URLs to whitelist:
43
80
 
44
81
  SeoCache.whitelist_urls = []
45
82
 
46
- Query params un URl to blacklist:
83
+ Parameter to add manually to the URl to force page caching, if you want to cache a specific URL (e.g. `https://<my_website>/?_seo_cache_=true`):
84
+
85
+ SeoCache.force_cache_url_param = '_seo_cache_'
86
+
87
+ URL extension to ignore when caching (already defined):
88
+
89
+ SeoCache.extensions_to_ignore = [<your_list>]
90
+
91
+ List of bot agents (already defined):
92
+
93
+ SeoCache.crawler_user_agents = [<your_list>]
94
+
95
+ Parameter added to URL when generating the page, avoid infinite rendering (override only if already used):
47
96
 
48
- SeoCache.blacklist_params = []
97
+ SeoCache.prerender_url_param = '_prerender_'
98
+
99
+ Be aware, JS will be render twice: once by server rendering and once by client. For React, this not a problem but with jQuery plugins, it can duplicate elements in the page (you have to check the redundancy).
49
100
 
50
101
  ## Automatic caching
51
102
 
52
- To automate cache, create a cron rake task which called:
103
+ To automate caching, create a cron rake task (e.g. in `lib/tasks/populate_seo_cache.rake`):
53
104
 
54
105
  ```ruby
55
- SeoCache::PopulateCache.new('https://<your-domain-name>', paths_to_cache).new.perform
106
+ namespace :MyProject do
107
+
108
+ desc 'Populate cache for SEO'
109
+ task populate_seo_cache: :environment do |_task, _args|
110
+ require 'seo_cache/populate_cache'
111
+
112
+ paths_to_cache = public_paths_like_sitemap
113
+
114
+ SeoCache::PopulateCache.new('https://<your-domain-name>', paths_to_cache).new.perform
115
+ end
116
+ end
56
117
  ```
57
118
 
119
+ You can add the `force_cache: true` option to `SeoCache::PopulateCache` for overwrite cache data.
120
+
58
121
  ## Server
59
122
 
60
123
  If you use disk caching, add to your Nginx configuration:
@@ -89,6 +152,78 @@ location / {
89
152
  }
90
153
  ```
91
154
 
155
+ ## Heroku case
156
+
157
+ If you use Heroku server, you can't store file on dynos. But you have two alternatives :
158
+
159
+ - Use the memory mode
160
+
161
+ - Use a second server (a dedicated one) to store HTML files and combine with Nginx.
162
+
163
+ To intercept the request, use the following middleware in Rails:
164
+
165
+ In `config/initializers`, create a new file:
166
+
167
+ ```ruby
168
+ require 'bot_detector'
169
+
170
+ if Rails.env.production?
171
+ Rails.application.config.middleware.insert_before ActionDispatch::Static, BotDetector
172
+ end
173
+ ```
174
+
175
+ Then in `lib` directory, for instance, manage the request:
176
+
177
+ ```ruby
178
+ class BotRedirector
179
+ CRAWLER_USER_AGENTS = ['googlebot', 'yahoo', 'bingbot', 'baiduspider', 'facebookexternalhit', 'twitterbot', 'rogerbot', 'linkedinbot', 'embedly', 'bufferbot', 'quora link preview', 'showyoubot', 'outbrain', 'pinterest/0.', 'developers.google.com/+/web/snippet', 'www.google.com/webmasters/tools/richsnippets', 'slackbot', 'vkShare', 'W3C_Validator', 'redditbot', 'Applebot', 'WhatsApp', 'flipboard', 'tumblr', 'bitlybot', 'SkypeUriPreview', 'nuzzel', 'Discordbot', 'Google Page Speed', 'Qwantify'].freeze
180
+
181
+ IGNORE_URLS = [
182
+ '/robots.txt'
183
+ ].freeze
184
+
185
+ def initialize(app)
186
+ @app = app
187
+ end
188
+
189
+ def call(env)
190
+ if env['HTTP_USER_AGENT'].present? && CRAWLER_USER_AGENTS.any? { |crawler_user_agent| env['HTTP_USER_AGENT'].downcase.include?(crawler_user_agent.downcase) }
191
+ begin
192
+ request = Rack::Request.new(env)
193
+
194
+ return @app.call(env) if IGNORE_URLS.any? { |ignore_url| request.fullpath.downcase =~ /^#{ignore_url.downcase}/ }
195
+
196
+ url = URI.parse(ENV['SEO_SERVER'] + request.fullpath)
197
+ headers = {
198
+ 'User-Agent' => env['HTTP_USER_AGENT'],
199
+ 'Accept-Encoding' => 'gzip'
200
+ }
201
+ req = Net::HTTP::Get.new(url.request_uri, headers)
202
+ # req.basic_auth(ENV['SEO_USER_ID'], ENV['SEO_PASSWD']) # if authentication mechanism
203
+ http = Net::HTTP.new(url.host, url.port)
204
+ http.use_ssl = true if url.scheme == 'https'
205
+ response = http.request(req)
206
+ if response['Content-Encoding'] == 'gzip'
207
+ response.body = ActiveSupport::Gzip.decompress(response.body)
208
+ response['Content-Length'] = response.body.length
209
+ response.delete('Content-Encoding')
210
+ end
211
+
212
+ return [response.code.to_i, { 'Content-Type' => response.header['Content-Type'] }, [response.body]]
213
+ rescue => error
214
+ Rails.logger.error("[bot_redirection] #{error.message}")
215
+
216
+ @app.call(env)
217
+ end
218
+ else
219
+ @app.call(env)
220
+ end
221
+ end
222
+ end
223
+ ```
224
+
225
+ If you use a second server, all links must be relatives in your HTML files, to avoid multi-domains links.
226
+
92
227
  ## Inspiration
93
228
 
94
229
  Inspired by [prerender gem](https://github.com/prerender/prerender_rails).
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'logger'
5
+
6
+ module SeoCache
7
+ #
8
+ # @example Enable full logging
9
+ # SeoCache.logger.level = :debug
10
+ #
11
+ # @example Log to file
12
+ # SeoCache.logger.output = 'seo_cache.log'
13
+ #
14
+ # @example Use logger manually
15
+ # SeoCache.logger.info('This is info message')
16
+ # SeoCache.logger.warn('This is warning message')
17
+ #
18
+ class Logger
19
+ extend Forwardable
20
+ include ::Logger::Severity
21
+
22
+ def_delegators :@logger, :debug, :debug?,
23
+ :info, :info?,
24
+ :warn, :warn?,
25
+ :error, :error?,
26
+ :fatal, :fatal?,
27
+ :level
28
+
29
+ def initialize(logger_path = nil)
30
+ @logger = create_logger(logger_path || $stdout)
31
+ end
32
+
33
+ def output=(io)
34
+ # `Logger#reopen` was added in Ruby 2.3
35
+ if @logger.respond_to?(:reopen)
36
+ @logger.reopen(io)
37
+ else
38
+ @logger = create_logger(io)
39
+ end
40
+ end
41
+
42
+ #
43
+ # For Ruby < 2.3 compatibility
44
+ # Based on https://github.com/ruby/ruby/blob/ruby_2_3/lib/logger.rb#L250
45
+ #
46
+
47
+ def level=(severity)
48
+ if severity.is_a?(Integer)
49
+ @logger.level = severity
50
+ else
51
+ case severity.to_s.downcase
52
+ when 'debug'.freeze
53
+ @logger.level = DEBUG
54
+ when 'info'.freeze
55
+ @logger.level = INFO
56
+ when 'warn'.freeze
57
+ @logger.level = WARN
58
+ when 'error'.freeze
59
+ @logger.level = ERROR
60
+ when 'fatal'.freeze
61
+ @logger.level = FATAL
62
+ when 'unknown'.freeze
63
+ @logger.level = UNKNOWN
64
+ else
65
+ raise ArgumentError, "invalid log level: #{severity}"
66
+ end
67
+ end
68
+ end
69
+
70
+ #
71
+ # Returns IO object used by logger internally.
72
+ #
73
+ # Normally, we would have never needed it, but we want to
74
+ # use it as IO object for all child processes to ensure their
75
+ # output is redirected there.
76
+ #
77
+ # It is only used in debug level, in other cases output is suppressed.
78
+ #
79
+ # @api private
80
+ #
81
+ def io
82
+ @logger.instance_variable_get(:@logdev).instance_variable_get(:@dev)
83
+ end
84
+
85
+ #
86
+ # Marks code as deprecated with replacement.
87
+ #
88
+ # @param [String] old
89
+ # @param [String] new
90
+ #
91
+ def deprecate(old, new)
92
+ warn "[DEPRECATION] #{old} is deprecated. Use #{new} instead."
93
+ end
94
+
95
+ private
96
+
97
+ def create_logger(output)
98
+ logger = ::Logger.new(output)
99
+ logger.progname = 'SeoCache'
100
+ logger.level = ($DEBUG ? DEBUG : INFO)
101
+ logger.formatter = proc do |severity, time, progname, msg|
102
+ "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
103
+ end
104
+
105
+ logger
106
+ end
107
+ end
108
+ end
@@ -35,7 +35,7 @@ module SeoCache
35
35
 
36
36
  def cache_exists?(path)
37
37
  if SeoCache.memory_cache? && @redis
38
- @redis.exists?(cache_path(path))
38
+ @redis.exists(cache_path(path))
39
39
  else
40
40
  File.exist?(cache_path(path))
41
41
  end
@@ -33,6 +33,8 @@ module SeoCache
33
33
  def init_driver
34
34
  # Selenium::WebDriver.logger.level = :info
35
35
 
36
+ Selenium::WebDriver::Chrome.path = SeoCache.chrome_path if SeoCache.chrome_path
37
+
36
38
  client = ::Selenium::WebDriver::Remote::Http::Persistent.new
37
39
  browser_options = ::Selenium::WebDriver::Chrome::Options.new
38
40
  browser_options.args << '--headless'
@@ -1,3 +1,3 @@
1
1
  module SeoCache
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
data/lib/seo_cache.rb CHANGED
@@ -1,23 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/http'
4
3
  require 'active_support'
5
- require 'selenium/webdriver'
6
- require 'chromedriver-helper'
7
- require 'selenium/webdriver/remote/http/persistent'
4
+ require 'net/http'
8
5
  require 'redis'
9
6
  require 'redis-namespace'
7
+ require 'selenium/webdriver'
8
+ require 'selenium/webdriver/remote/http/persistent'
9
+ require 'webdrivers'
10
10
 
11
+ require 'seo_cache/logger'
11
12
  require 'seo_cache/version'
12
13
  require 'seo_cache/middleware'
13
14
 
14
15
  module SeoCache
15
16
 
17
+ mattr_accessor :chrome_path
18
+ self.chrome_path = nil
19
+
16
20
  mattr_accessor :cache_mode # disk or memory
17
21
  self.cache_mode = 'memory'
18
22
 
19
23
  mattr_accessor :disk_cache_path
20
- self.disk_cache_path = nil
24
+ self.disk_cache_path = ''
21
25
 
22
26
  mattr_accessor :disk_cache_extension
23
27
  self.disk_cache_extension = '.html'
@@ -89,6 +93,15 @@ module SeoCache
89
93
  'Qwantify'
90
94
  ]
91
95
 
96
+ mattr_accessor :logger_path
97
+ self.logger_path = nil
98
+
99
+ mattr_accessor :logger_level
100
+ self.logger_level = :INFO
101
+
102
+ mattr_accessor :logger
103
+ # self.logger = SeoCache::Logger.new(SeoCache.logger_path)
104
+
92
105
  def self.memory_cache?
93
106
  SeoCache.cache_mode == 'memory'
94
107
  end
@@ -97,11 +110,17 @@ module SeoCache
97
110
  SeoCache.cache_mode == 'disk'
98
111
  end
99
112
 
113
+ def self.logger
114
+ @logger ||= SeoCache::Logger.new(SeoCache.logger_path)
115
+ end
116
+
100
117
  def self.log(message)
101
- Rails.logger.info { "[seo_cache] #{message}" }
118
+ SeoCache.logger.info(message)
119
+ # Rails.logger.info { "[seo_cache] #{message}" }
102
120
  end
103
121
 
104
122
  def self.log_error(message)
105
- Rails.logger.error { "[seo_cache] #{message}" }
123
+ SeoCache.logger.error(message)
124
+ # Rails.logger.error { "[seo_cache] #{message}" }
106
125
  end
107
126
  end
data/seo_cache.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = 'Cache dedicated for SEO with Javascript rendering'
12
12
  spec.description = 'Specific cache for bots to optimize time to first byte and render Javascript on server side.'
13
- spec.homepage = 'https://github.com/floXcoder/SeoCache'
13
+ spec.homepage = 'https://github.com/floXcoder/seo_cache'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -20,16 +20,18 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ['lib']
22
22
 
23
+ spec.add_dependency 'activesupport', '~> 5'
24
+ spec.add_dependency 'net-http-persistent', '~> 3'
23
25
  spec.add_dependency 'rack', '~> 2'
24
26
  spec.add_dependency 'railties', '~> 5'
25
- spec.add_dependency 'net-http-persistent', '~> 3'
26
- spec.add_dependency 'activesupport', '~> 5'
27
- spec.add_dependency 'selenium-webdriver', '~> 3'
28
- spec.add_dependency 'chromedriver-helper', '~> 2'
29
27
  spec.add_dependency 'redis', '~> 4'
30
28
  spec.add_dependency 'redis-namespace', '~> 1'
29
+ spec.add_dependency 'selenium-webdriver', '~> 3'
30
+ spec.add_dependency 'webdrivers', '~> 3'
31
31
 
32
32
  spec.add_development_dependency 'bundler', '~> 1'
33
33
  spec.add_development_dependency 'rake', '~> 12'
34
34
  spec.add_development_dependency 'rspec', '~> 3'
35
+ spec.add_development_dependency 'simplecov', '~> 0.16'
36
+ spec.add_development_dependency 'webmock', '~> 3'
35
37
  end
metadata CHANGED
@@ -1,59 +1,59 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seo_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - FloXcoder
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-26 00:00:00.000000000 Z
11
+ date: 2019-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rack
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2'
19
+ version: '5'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2'
26
+ version: '5'
27
27
  - !ruby/object:Gem::Dependency
28
- name: railties
28
+ name: net-http-persistent
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5'
33
+ version: '3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '5'
40
+ version: '3'
41
41
  - !ruby/object:Gem::Dependency
42
- name: net-http-persistent
42
+ name: rack
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3'
47
+ version: '2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3'
54
+ version: '2'
55
55
  - !ruby/object:Gem::Dependency
56
- name: activesupport
56
+ name: railties
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
@@ -67,61 +67,61 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '5'
69
69
  - !ruby/object:Gem::Dependency
70
- name: selenium-webdriver
70
+ name: redis
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3'
75
+ version: '4'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3'
82
+ version: '4'
83
83
  - !ruby/object:Gem::Dependency
84
- name: chromedriver-helper
84
+ name: redis-namespace
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '2'
89
+ version: '1'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '2'
96
+ version: '1'
97
97
  - !ruby/object:Gem::Dependency
98
- name: redis
98
+ name: selenium-webdriver
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '4'
103
+ version: '3'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '4'
110
+ version: '3'
111
111
  - !ruby/object:Gem::Dependency
112
- name: redis-namespace
112
+ name: webdrivers
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '1'
117
+ version: '3'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '1'
124
+ version: '3'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: bundler
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,34 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: '3'
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '0.16'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '0.16'
181
+ - !ruby/object:Gem::Dependency
182
+ name: webmock
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '3'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '3'
167
195
  description: Specific cache for bots to optimize time to first byte and render Javascript
168
196
  on server side.
169
197
  email:
@@ -186,13 +214,14 @@ files:
186
214
  - bin/console
187
215
  - bin/setup
188
216
  - lib/seo_cache.rb
217
+ - lib/seo_cache/logger.rb
189
218
  - lib/seo_cache/middleware.rb
190
219
  - lib/seo_cache/page_caching.rb
191
220
  - lib/seo_cache/page_render.rb
192
221
  - lib/seo_cache/populate_cache.rb
193
222
  - lib/seo_cache/version.rb
194
223
  - seo_cache.gemspec
195
- homepage: https://github.com/floXcoder/SeoCache
224
+ homepage: https://github.com/floXcoder/seo_cache
196
225
  licenses:
197
226
  - MIT
198
227
  metadata: {}