seo_optimizer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +39 -0
- data/LICENSE.txt +21 -0
- data/README.md +166 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/generators/seo_optimizer/errors_pages/errors_pages_generator.rb +23 -0
- data/lib/generators/seo_optimizer/errors_pages/templates/404.erb +231 -0
- data/lib/generators/seo_optimizer/errors_pages/templates/500.erb +231 -0
- data/lib/generators/seo_optimizer/errors_pages/templates/errors_controller_template.erb +11 -0
- data/lib/generators/seo_optimizer/models/models_generator.rb +72 -0
- data/lib/generators/seo_optimizer/models/templates/model_template.erb +19 -0
- data/lib/generators/seo_optimizer/robots_files/robots_files_generator.rb +51 -0
- data/lib/generators/seo_optimizer/robots_files/templates/robots_controller_template.erb +11 -0
- data/lib/generators/seo_optimizer/robots_files/templates/robots_show_template.erb +3 -0
- data/lib/generators/seo_optimizer/robots_files/templates/sitemaps_controller_template.erb +8 -0
- data/lib/generators/seo_optimizer/robots_files/templates/sitemaps_task_template.erb +39 -0
- data/lib/generators/seo_optimizer/setups/setups_generator.rb +19 -0
- data/lib/seo_optimizer.rb +6 -0
- data/lib/seo_optimizer/version.rb +3 -0
- data/seo_optimizer.gemspec +36 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 415bd41bed30c7e261ee469383cc1384e07fe41bcd1ac7e0da7b08811e3875ac
|
4
|
+
data.tar.gz: d45bd5f93a75a9ba0758372c3d5cb26c1fd01be470097d494f614efe2e654163
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e3ffb4b684021306c18991d6c35d6f024001f84f6f0b4225bf60b5fe91fcc6047c0ed168ae72ef229664ebf6c96bf9f5cb1bcd7a23eb2243ef93daf20e7fc986
|
7
|
+
data.tar.gz: bea7e285cdf9c260b748867a27ee1c104107543fe7892f9ff34ebe6b74fd38c78aa29f8302d198e26f54b9c9f3ba6c1d758f92c23a7cd1ee3d49e33f89c74dcd
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7.1
|
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at ronan33720@hotmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [https://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: https://contributor-covenant.org
|
74
|
+
[version]: https://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
seo_optimizer (0.1.0)
|
5
|
+
sitemap_generator
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
builder (3.2.4)
|
11
|
+
diff-lcs (1.4.4)
|
12
|
+
rake (12.3.3)
|
13
|
+
rspec (3.10.0)
|
14
|
+
rspec-core (~> 3.10.0)
|
15
|
+
rspec-expectations (~> 3.10.0)
|
16
|
+
rspec-mocks (~> 3.10.0)
|
17
|
+
rspec-core (3.10.0)
|
18
|
+
rspec-support (~> 3.10.0)
|
19
|
+
rspec-expectations (3.10.0)
|
20
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
21
|
+
rspec-support (~> 3.10.0)
|
22
|
+
rspec-mocks (3.10.0)
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
+
rspec-support (~> 3.10.0)
|
25
|
+
rspec-support (3.10.0)
|
26
|
+
sitemap_generator (6.1.2)
|
27
|
+
builder (~> 3.0)
|
28
|
+
|
29
|
+
PLATFORMS
|
30
|
+
ruby
|
31
|
+
|
32
|
+
DEPENDENCIES
|
33
|
+
rake (~> 12.0)
|
34
|
+
rspec (~> 3.0)
|
35
|
+
seo_optimizer!
|
36
|
+
sitemap_generator
|
37
|
+
|
38
|
+
BUNDLED WITH
|
39
|
+
2.1.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Ronan Louarn
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
# Seo Optimizer
|
2
|
+
|
3
|
+
Seo Optimizer provides a set of helpers which guide you in SEO improvements.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'seo_optimizer'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install seo_optimizer
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
#### Sitemap.yml, robots.txt
|
24
|
+
|
25
|
+
There is a generator and a task to create needed files that will be read by search engines robots.
|
26
|
+
|
27
|
+
**1** - Setup (it add a new config variable in `application.rb`)
|
28
|
+
|
29
|
+
```bash
|
30
|
+
$ rails g seo_optimizer:setups
|
31
|
+
```
|
32
|
+
**2** - Replace the default value of product_url in `application.rb`
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
config.sitemap_config_variable = {}
|
36
|
+
config.sitemap_config_variable[:production_url] = 'https://YOUR-PRODUCTION-URL.com'
|
37
|
+
```
|
38
|
+
|
39
|
+
**3** - Generate robots files (this will create sitemap.yml, robots.txt routes/actions/views)
|
40
|
+
|
41
|
+
```bash
|
42
|
+
$ rails g seo_optimizer:robots_files
|
43
|
+
```
|
44
|
+
|
45
|
+
**4** - Edit sitemap generate task `lib/tasks/sitemap/generate.rake` to add your customs routes like resources CRUD
|
46
|
+
routes etc, check the section below for more informations or check sitemap_generator
|
47
|
+
doc (https://github.com/kjvarga/sitemap_generator).
|
48
|
+
|
49
|
+
**5** - Generate the sitemap.xml
|
50
|
+
```bash
|
51
|
+
$ rails sitemap:generate
|
52
|
+
```
|
53
|
+
**Existing routes will be generated in sitemap by default.**
|
54
|
+
|
55
|
+
Then you can check these urls:
|
56
|
+
|
57
|
+
robots.txt file: http://localhost:3000/robots.txt
|
58
|
+
sitemap.xml file: http://localhost:3000/sitemap.xml
|
59
|
+
|
60
|
+
_________________
|
61
|
+
|
62
|
+
#### Model routes with slug:
|
63
|
+
|
64
|
+
To add seo_slug field to a model, you can use the generator as shown below.
|
65
|
+
|
66
|
+
**1** - Syntax:
|
67
|
+
`rails g seo_optimizer:my_model field_1 field_2 3 4 5...`
|
68
|
+
|
69
|
+
$ rails generate seo_optimizer:user first_name last_name other_field
|
70
|
+
|
71
|
+
**2** - Migrate
|
72
|
+
|
73
|
+
$ rails db:migrate
|
74
|
+
|
75
|
+
**3** - Override `to_param` method in your model to change your models links pattern
|
76
|
+
|
77
|
+
````ruby
|
78
|
+
class User < ApplicationRecord
|
79
|
+
...
|
80
|
+
|
81
|
+
def to_param
|
82
|
+
seo_slug
|
83
|
+
end
|
84
|
+
end
|
85
|
+
````
|
86
|
+
|
87
|
+
And then `<%= link_to 'Show', User.first %>` will generate a link that follow the new seo pattern
|
88
|
+
|
89
|
+
`/users/USERID-FIELD-FIELD-FIELD`
|
90
|
+
|
91
|
+
|
92
|
+
`/users/1-field_one-field_two-other_field`
|
93
|
+
|
94
|
+
|
95
|
+
**4** - So, in your `UsersController`:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
class UsersController < ApplicationController
|
99
|
+
before_action :set_user, only: :show
|
100
|
+
|
101
|
+
def show; end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def set_user
|
106
|
+
# we find users by seo_slug field
|
107
|
+
@user = User.find_by(seo_slug: params[:id])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
**5** - You can update the sitemap task to add every routes with slugs in it.
|
113
|
+
|
114
|
+
- In `SitemapGenerator::Sitemap.create` block
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
SitemapGenerator::Sitemap.create do
|
118
|
+
...
|
119
|
+
User.select(:seo_slug, :updated_at).each do |slug|
|
120
|
+
add user_path(slug), lastmod: slug.updated_at, priority: 0.8
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
- Then don't forget to `$ rails sitemap:generate`.
|
126
|
+
|
127
|
+
______________
|
128
|
+
|
129
|
+
#### Error pages (404, 500):
|
130
|
+
|
131
|
+
**1** - Generate error pages view, actions and routes.
|
132
|
+
```bash
|
133
|
+
$ rails g seo_optimizer:errors_pages
|
134
|
+
```
|
135
|
+
|
136
|
+
**2** - You can customize pages in `app/views/errors/`
|
137
|
+
|
138
|
+
**3** - Edit `config/environment/develoment.rb` if you want to test it in dev environment.
|
139
|
+
|
140
|
+
⛔️ DO NOT COMMIT ⛔️
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
config.consider_all_requests_local = true
|
144
|
+
# to
|
145
|
+
config.consider_all_requests_local = false
|
146
|
+
```
|
147
|
+
_________________
|
148
|
+
|
149
|
+
## Development
|
150
|
+
|
151
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
152
|
+
|
153
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
154
|
+
|
155
|
+
## Contributing
|
156
|
+
|
157
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/seo_optimizer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/seo_optimizer/blob/master/CODE_OF_CONDUCT.md).
|
158
|
+
|
159
|
+
|
160
|
+
## License
|
161
|
+
|
162
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
163
|
+
|
164
|
+
## Code of Conduct
|
165
|
+
|
166
|
+
Everyone interacting in the SeoOptimizer project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/seo_optimizer/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "seo_optimizer"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
module SeoOptimizer
|
6
|
+
class ErrorsPagesGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path('templates', __dir__)
|
8
|
+
desc 'Generates errors pages'
|
9
|
+
|
10
|
+
def create_controller_files
|
11
|
+
route %(get '/500' => 'errors#internal_server_error'\nget '/404' => 'errors#not_found'\n)
|
12
|
+
|
13
|
+
inject_into_file 'config/application.rb', :before => " end" do
|
14
|
+
"\n config.exceptions_app = self.routes\n"
|
15
|
+
end
|
16
|
+
%x(rm -f public/404.html)
|
17
|
+
%x(rm -f public/500.html)
|
18
|
+
template 'errors_controller_template.erb', File.join('app/controllers', 'errors_controller.rb')
|
19
|
+
template '404.erb', File.join('app/views/errors', 'not_found.html.erb')
|
20
|
+
template '500.erb', File.join('app/views/errors', 'internal_server_error.html.erb')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
<div class="background">
|
2
|
+
<div class="ground"></div>
|
3
|
+
</div>
|
4
|
+
<div class="container">
|
5
|
+
<div class="left-section">
|
6
|
+
<div class="inner-content">
|
7
|
+
<h1 class="heading">404</h1>
|
8
|
+
<p class="subheading">Looks like the page you were looking for is no longer here.</p>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
<div class="right-section">
|
12
|
+
<svg class="svgimg" xmlns="http://www.w3.org/2000/svg" viewBox="51.5 -15.288 385 505.565">
|
13
|
+
<g class="bench-legs">
|
14
|
+
<path d="M202.778,391.666h11.111v98.611h-11.111V391.666z M370.833,390.277h11.111v100h-11.111V390.277z M183.333,456.944h11.111
|
15
|
+
v33.333h-11.111V456.944z M393.056,456.944h11.111v33.333h-11.111V456.944z" />
|
16
|
+
</g>
|
17
|
+
<g class="top-bench">
|
18
|
+
<path d="M396.527,397.917c0,1.534-1.243,2.777-2.777,2.777H190.972c-1.534,0-2.778-1.243-2.778-2.777v-8.333
|
19
|
+
c0-1.535,1.244-2.778,2.778-2.778H393.75c1.534,0,2.777,1.243,2.777,2.778V397.917z M400.694,414.583
|
20
|
+
c0,1.534-1.243,2.778-2.777,2.778H188.194c-1.534,0-2.778-1.244-2.778-2.778v-8.333c0-1.534,1.244-2.777,2.778-2.777h209.723
|
21
|
+
c1.534,0,2.777,1.243,2.777,2.777V414.583z M403.473,431.25c0,1.534-1.244,2.777-2.778,2.777H184.028
|
22
|
+
c-1.534,0-2.778-1.243-2.778-2.777v-8.333c0-1.534,1.244-2.778,2.778-2.778h216.667c1.534,0,2.778,1.244,2.778,2.778V431.25z"
|
23
|
+
/>
|
24
|
+
</g>
|
25
|
+
<g class="bottom-bench">
|
26
|
+
<path d="M417.361,459.027c0,0.769-1.244,1.39-2.778,1.39H170.139c-1.533,0-2.777-0.621-2.777-1.39v-4.86
|
27
|
+
c0-0.769,1.244-0.694,2.777-0.694h244.444c1.534,0,2.778-0.074,2.778,0.694V459.027z" />
|
28
|
+
<path d="M185.417,443.75H400c0,0,18.143,9.721,17.361,10.417l-250-0.696C167.303,451.65,185.417,443.75,185.417,443.75z" />
|
29
|
+
</g>
|
30
|
+
<g id="lamp">
|
31
|
+
<path class="lamp-details" d="M125.694,421.997c0,1.257-0.73,3.697-1.633,3.697H113.44c-0.903,0-1.633-2.44-1.633-3.697V84.917
|
32
|
+
c0-1.257,0.73-2.278,1.633-2.278h10.621c0.903,0,1.633,1.02,1.633,2.278V421.997z"
|
33
|
+
/>
|
34
|
+
<path class="lamp-accent" d="M128.472,93.75c0,1.534-1.244,2.778-2.778,2.778h-13.889c-1.534,0-2.778-1.244-2.778-2.778V79.861
|
35
|
+
c0-1.534,1.244-2.778,2.778-2.778h13.889c1.534,0,2.778,1.244,2.778,2.778V93.75z" />
|
36
|
+
|
37
|
+
<circle class="lamp-light" cx="119.676" cy="44.22" r="40.51" />
|
38
|
+
<path class="lamp-details" d="M149.306,71.528c0,3.242-13.37,13.889-29.861,13.889S89.583,75.232,89.583,71.528c0-4.166,13.369-13.889,29.861-13.889
|
39
|
+
S149.306,67.362,149.306,71.528z"/>
|
40
|
+
<radialGradient class="light-gradient" id="SVGID_1_" cx="119.676" cy="44.22" r="65" gradientUnits="userSpaceOnUse">
|
41
|
+
<stop offset="0%" style="stop-color:#FFFFFF; stop-opacity: 1"/>
|
42
|
+
<stop offset="50%" style="stop-color:#EDEDED; stop-opacity: 0.5">
|
43
|
+
<animate attributeName="stop-opacity" values="0.0; 0.5; 0.0" dur="5000ms" repeatCount="indefinite"></animate>
|
44
|
+
</stop>
|
45
|
+
<stop offset="100%" style="stop-color:#EDEDED; stop-opacity: 0"/>
|
46
|
+
</radialGradient>
|
47
|
+
<circle class="lamp-light__glow" fill="url(#SVGID_1_)" cx="119.676" cy="44.22" r="65"/>
|
48
|
+
<path class="lamp-bottom" d="M135.417,487.781c0,1.378-1.244,2.496-2.778,2.496H106.25c-1.534,0-2.778-1.118-2.778-2.496v-74.869
|
49
|
+
c0-1.378,1.244-2.495,2.778-2.495h26.389c1.534,0,2.778,1.117,2.778,2.495V487.781z" />
|
50
|
+
</g>
|
51
|
+
</svg>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
|
55
|
+
<style>
|
56
|
+
@import url("https://fonts.googleapis.com/css?family=Fira+Sans");
|
57
|
+
/*Variables */
|
58
|
+
.left-section .inner-content {
|
59
|
+
position: absolute;
|
60
|
+
top: 50%;
|
61
|
+
transform: translateY(-50%);
|
62
|
+
}
|
63
|
+
|
64
|
+
* {
|
65
|
+
box-sizing: border-box;
|
66
|
+
}
|
67
|
+
|
68
|
+
html, body {
|
69
|
+
margin: 0;
|
70
|
+
padding: 0;
|
71
|
+
}
|
72
|
+
|
73
|
+
body {
|
74
|
+
font-family: "Fira Sans", sans-serif;
|
75
|
+
color: #f5f6fa;
|
76
|
+
}
|
77
|
+
|
78
|
+
.background {
|
79
|
+
position: absolute;
|
80
|
+
top: 0;
|
81
|
+
left: 0;
|
82
|
+
width: 100%;
|
83
|
+
height: 100%;
|
84
|
+
background: linear-gradient(#0C0E10, #446182);
|
85
|
+
}
|
86
|
+
.background .ground {
|
87
|
+
position: absolute;
|
88
|
+
bottom: 0;
|
89
|
+
width: 100%;
|
90
|
+
height: 25vh;
|
91
|
+
background: #0C0E10;
|
92
|
+
}
|
93
|
+
@media (max-width: 770px) {
|
94
|
+
.background .ground {
|
95
|
+
height: 0vh;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
.container {
|
100
|
+
position: relative;
|
101
|
+
margin: 0 auto;
|
102
|
+
width: 85%;
|
103
|
+
height: 100vh;
|
104
|
+
padding-bottom: 25vh;
|
105
|
+
display: flex;
|
106
|
+
flex-direction: row;
|
107
|
+
justify-content: space-around;
|
108
|
+
}
|
109
|
+
@media (max-width: 770px) {
|
110
|
+
.container {
|
111
|
+
flex-direction: column;
|
112
|
+
padding-bottom: 0vh;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
.left-section, .right-section {
|
117
|
+
position: relative;
|
118
|
+
}
|
119
|
+
|
120
|
+
.left-section {
|
121
|
+
width: 40%;
|
122
|
+
}
|
123
|
+
@media (max-width: 770px) {
|
124
|
+
.left-section {
|
125
|
+
width: 100%;
|
126
|
+
height: 40%;
|
127
|
+
position: absolute;
|
128
|
+
top: 0;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
@media (max-width: 770px) {
|
132
|
+
.left-section .inner-content {
|
133
|
+
position: relative;
|
134
|
+
padding: 1rem 0;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
.heading {
|
139
|
+
text-align: center;
|
140
|
+
font-size: 9em;
|
141
|
+
line-height: 1.3em;
|
142
|
+
margin: 2rem 0 0.5rem 0;
|
143
|
+
padding: 0;
|
144
|
+
text-shadow: 0 0 1rem #fefefe;
|
145
|
+
}
|
146
|
+
@media (max-width: 770px) {
|
147
|
+
.heading {
|
148
|
+
font-size: 7em;
|
149
|
+
line-height: 1.15;
|
150
|
+
margin: 0;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
.subheading {
|
155
|
+
text-align: center;
|
156
|
+
max-width: 480px;
|
157
|
+
font-size: 1.5em;
|
158
|
+
line-height: 1.15em;
|
159
|
+
padding: 0 1rem;
|
160
|
+
margin: 0 auto;
|
161
|
+
}
|
162
|
+
@media (max-width: 770px) {
|
163
|
+
.subheading {
|
164
|
+
font-size: 1.3em;
|
165
|
+
line-height: 1.15;
|
166
|
+
max-width: 100%;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
.right-section {
|
171
|
+
width: 50%;
|
172
|
+
}
|
173
|
+
@media (max-width: 770px) {
|
174
|
+
.right-section {
|
175
|
+
width: 100%;
|
176
|
+
height: 60%;
|
177
|
+
position: absolute;
|
178
|
+
bottom: 0;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
.svgimg {
|
183
|
+
position: absolute;
|
184
|
+
bottom: 0;
|
185
|
+
padding-top: 10vh;
|
186
|
+
padding-left: 1vh;
|
187
|
+
max-width: 100%;
|
188
|
+
max-height: 100%;
|
189
|
+
}
|
190
|
+
@media (max-width: 770px) {
|
191
|
+
.svgimg {
|
192
|
+
padding: 0;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
.svgimg .bench-legs {
|
196
|
+
fill: #0C0E10;
|
197
|
+
}
|
198
|
+
.svgimg .top-bench, .svgimg .bottom-bench {
|
199
|
+
stroke: #0C0E10;
|
200
|
+
stroke-width: 1px;
|
201
|
+
fill: #5B3E2B;
|
202
|
+
}
|
203
|
+
.svgimg .bottom-bench path:nth-child(1) {
|
204
|
+
fill: #432d20;
|
205
|
+
}
|
206
|
+
.svgimg .lamp-details {
|
207
|
+
fill: #202425;
|
208
|
+
}
|
209
|
+
.svgimg .lamp-accent {
|
210
|
+
fill: #2c3133;
|
211
|
+
}
|
212
|
+
.svgimg .lamp-bottom {
|
213
|
+
fill: linear-gradient(#202425, #0C0E10);
|
214
|
+
}
|
215
|
+
.svgimg .lamp-light {
|
216
|
+
fill: #EFEFEF;
|
217
|
+
}
|
218
|
+
|
219
|
+
@keyframes glow {
|
220
|
+
0% {
|
221
|
+
text-shadow: 0 0 1rem #fefefe;
|
222
|
+
}
|
223
|
+
50% {
|
224
|
+
text-shadow: 0 0 1.85rem #ededed;
|
225
|
+
}
|
226
|
+
100% {
|
227
|
+
text-shadow: 0 0 1rem #fefefe;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
</style>
|
@@ -0,0 +1,231 @@
|
|
1
|
+
<div class="background">
|
2
|
+
<div class="ground"></div>
|
3
|
+
</div>
|
4
|
+
<div class="container">
|
5
|
+
<div class="left-section">
|
6
|
+
<div class="inner-content">
|
7
|
+
<h1 class="heading">500</h1>
|
8
|
+
<p class="subheading">Looks like the page you were looking for is no longer here.</p>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
<div class="right-section">
|
12
|
+
<svg class="svgimg" xmlns="http://www.w3.org/2000/svg" viewBox="51.5 -15.288 385 505.565">
|
13
|
+
<g class="bench-legs">
|
14
|
+
<path d="M202.778,391.666h11.111v98.611h-11.111V391.666z M370.833,390.277h11.111v100h-11.111V390.277z M183.333,456.944h11.111
|
15
|
+
v33.333h-11.111V456.944z M393.056,456.944h11.111v33.333h-11.111V456.944z" />
|
16
|
+
</g>
|
17
|
+
<g class="top-bench">
|
18
|
+
<path d="M396.527,397.917c0,1.534-1.243,2.777-2.777,2.777H190.972c-1.534,0-2.778-1.243-2.778-2.777v-8.333
|
19
|
+
c0-1.535,1.244-2.778,2.778-2.778H393.75c1.534,0,2.777,1.243,2.777,2.778V397.917z M400.694,414.583
|
20
|
+
c0,1.534-1.243,2.778-2.777,2.778H188.194c-1.534,0-2.778-1.244-2.778-2.778v-8.333c0-1.534,1.244-2.777,2.778-2.777h209.723
|
21
|
+
c1.534,0,2.777,1.243,2.777,2.777V414.583z M403.473,431.25c0,1.534-1.244,2.777-2.778,2.777H184.028
|
22
|
+
c-1.534,0-2.778-1.243-2.778-2.777v-8.333c0-1.534,1.244-2.778,2.778-2.778h216.667c1.534,0,2.778,1.244,2.778,2.778V431.25z"
|
23
|
+
/>
|
24
|
+
</g>
|
25
|
+
<g class="bottom-bench">
|
26
|
+
<path d="M417.361,459.027c0,0.769-1.244,1.39-2.778,1.39H170.139c-1.533,0-2.777-0.621-2.777-1.39v-4.86
|
27
|
+
c0-0.769,1.244-0.694,2.777-0.694h244.444c1.534,0,2.778-0.074,2.778,0.694V459.027z" />
|
28
|
+
<path d="M185.417,443.75H400c0,0,18.143,9.721,17.361,10.417l-250-0.696C167.303,451.65,185.417,443.75,185.417,443.75z" />
|
29
|
+
</g>
|
30
|
+
<g id="lamp">
|
31
|
+
<path class="lamp-details" d="M125.694,421.997c0,1.257-0.73,3.697-1.633,3.697H113.44c-0.903,0-1.633-2.44-1.633-3.697V84.917
|
32
|
+
c0-1.257,0.73-2.278,1.633-2.278h10.621c0.903,0,1.633,1.02,1.633,2.278V421.997z"
|
33
|
+
/>
|
34
|
+
<path class="lamp-accent" d="M128.472,93.75c0,1.534-1.244,2.778-2.778,2.778h-13.889c-1.534,0-2.778-1.244-2.778-2.778V79.861
|
35
|
+
c0-1.534,1.244-2.778,2.778-2.778h13.889c1.534,0,2.778,1.244,2.778,2.778V93.75z" />
|
36
|
+
|
37
|
+
<circle class="lamp-light" cx="119.676" cy="44.22" r="40.51" />
|
38
|
+
<path class="lamp-details" d="M149.306,71.528c0,3.242-13.37,13.889-29.861,13.889S89.583,75.232,89.583,71.528c0-4.166,13.369-13.889,29.861-13.889
|
39
|
+
S149.306,67.362,149.306,71.528z"/>
|
40
|
+
<radialGradient class="light-gradient" id="SVGID_1_" cx="119.676" cy="44.22" r="65" gradientUnits="userSpaceOnUse">
|
41
|
+
<stop offset="0%" style="stop-color:#FFFFFF; stop-opacity: 1"/>
|
42
|
+
<stop offset="50%" style="stop-color:#EDEDED; stop-opacity: 0.5">
|
43
|
+
<animate attributeName="stop-opacity" values="0.0; 0.5; 0.0" dur="5000ms" repeatCount="indefinite"></animate>
|
44
|
+
</stop>
|
45
|
+
<stop offset="100%" style="stop-color:#EDEDED; stop-opacity: 0"/>
|
46
|
+
</radialGradient>
|
47
|
+
<circle class="lamp-light__glow" fill="url(#SVGID_1_)" cx="119.676" cy="44.22" r="65"/>
|
48
|
+
<path class="lamp-bottom" d="M135.417,487.781c0,1.378-1.244,2.496-2.778,2.496H106.25c-1.534,0-2.778-1.118-2.778-2.496v-74.869
|
49
|
+
c0-1.378,1.244-2.495,2.778-2.495h26.389c1.534,0,2.778,1.117,2.778,2.495V487.781z" />
|
50
|
+
</g>
|
51
|
+
</svg>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
|
55
|
+
<style>
|
56
|
+
@import url("https://fonts.googleapis.com/css?family=Fira+Sans");
|
57
|
+
/*Variables */
|
58
|
+
.left-section .inner-content {
|
59
|
+
position: absolute;
|
60
|
+
top: 50%;
|
61
|
+
transform: translateY(-50%);
|
62
|
+
}
|
63
|
+
|
64
|
+
* {
|
65
|
+
box-sizing: border-box;
|
66
|
+
}
|
67
|
+
|
68
|
+
html, body {
|
69
|
+
margin: 0;
|
70
|
+
padding: 0;
|
71
|
+
}
|
72
|
+
|
73
|
+
body {
|
74
|
+
font-family: "Fira Sans", sans-serif;
|
75
|
+
color: #f5f6fa;
|
76
|
+
}
|
77
|
+
|
78
|
+
.background {
|
79
|
+
position: absolute;
|
80
|
+
top: 0;
|
81
|
+
left: 0;
|
82
|
+
width: 100%;
|
83
|
+
height: 100%;
|
84
|
+
background: linear-gradient(#0C0E10, #446182);
|
85
|
+
}
|
86
|
+
.background .ground {
|
87
|
+
position: absolute;
|
88
|
+
bottom: 0;
|
89
|
+
width: 100%;
|
90
|
+
height: 25vh;
|
91
|
+
background: #0C0E10;
|
92
|
+
}
|
93
|
+
@media (max-width: 770px) {
|
94
|
+
.background .ground {
|
95
|
+
height: 0vh;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
.container {
|
100
|
+
position: relative;
|
101
|
+
margin: 0 auto;
|
102
|
+
width: 85%;
|
103
|
+
height: 100vh;
|
104
|
+
padding-bottom: 25vh;
|
105
|
+
display: flex;
|
106
|
+
flex-direction: row;
|
107
|
+
justify-content: space-around;
|
108
|
+
}
|
109
|
+
@media (max-width: 770px) {
|
110
|
+
.container {
|
111
|
+
flex-direction: column;
|
112
|
+
padding-bottom: 0vh;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
.left-section, .right-section {
|
117
|
+
position: relative;
|
118
|
+
}
|
119
|
+
|
120
|
+
.left-section {
|
121
|
+
width: 40%;
|
122
|
+
}
|
123
|
+
@media (max-width: 770px) {
|
124
|
+
.left-section {
|
125
|
+
width: 100%;
|
126
|
+
height: 40%;
|
127
|
+
position: absolute;
|
128
|
+
top: 0;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
@media (max-width: 770px) {
|
132
|
+
.left-section .inner-content {
|
133
|
+
position: relative;
|
134
|
+
padding: 1rem 0;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
.heading {
|
139
|
+
text-align: center;
|
140
|
+
font-size: 9em;
|
141
|
+
line-height: 1.3em;
|
142
|
+
margin: 2rem 0 0.5rem 0;
|
143
|
+
padding: 0;
|
144
|
+
text-shadow: 0 0 1rem #fefefe;
|
145
|
+
}
|
146
|
+
@media (max-width: 770px) {
|
147
|
+
.heading {
|
148
|
+
font-size: 7em;
|
149
|
+
line-height: 1.15;
|
150
|
+
margin: 0;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
.subheading {
|
155
|
+
text-align: center;
|
156
|
+
max-width: 480px;
|
157
|
+
font-size: 1.5em;
|
158
|
+
line-height: 1.15em;
|
159
|
+
padding: 0 1rem;
|
160
|
+
margin: 0 auto;
|
161
|
+
}
|
162
|
+
@media (max-width: 770px) {
|
163
|
+
.subheading {
|
164
|
+
font-size: 1.3em;
|
165
|
+
line-height: 1.15;
|
166
|
+
max-width: 100%;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
.right-section {
|
171
|
+
width: 50%;
|
172
|
+
}
|
173
|
+
@media (max-width: 770px) {
|
174
|
+
.right-section {
|
175
|
+
width: 100%;
|
176
|
+
height: 60%;
|
177
|
+
position: absolute;
|
178
|
+
bottom: 0;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
.svgimg {
|
183
|
+
position: absolute;
|
184
|
+
bottom: 0;
|
185
|
+
padding-top: 10vh;
|
186
|
+
padding-left: 1vh;
|
187
|
+
max-width: 100%;
|
188
|
+
max-height: 100%;
|
189
|
+
}
|
190
|
+
@media (max-width: 770px) {
|
191
|
+
.svgimg {
|
192
|
+
padding: 0;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
.svgimg .bench-legs {
|
196
|
+
fill: #0C0E10;
|
197
|
+
}
|
198
|
+
.svgimg .top-bench, .svgimg .bottom-bench {
|
199
|
+
stroke: #0C0E10;
|
200
|
+
stroke-width: 1px;
|
201
|
+
fill: #5B3E2B;
|
202
|
+
}
|
203
|
+
.svgimg .bottom-bench path:nth-child(1) {
|
204
|
+
fill: #432d20;
|
205
|
+
}
|
206
|
+
.svgimg .lamp-details {
|
207
|
+
fill: #202425;
|
208
|
+
}
|
209
|
+
.svgimg .lamp-accent {
|
210
|
+
fill: #2c3133;
|
211
|
+
}
|
212
|
+
.svgimg .lamp-bottom {
|
213
|
+
fill: linear-gradient(#202425, #0C0E10);
|
214
|
+
}
|
215
|
+
.svgimg .lamp-light {
|
216
|
+
fill: #EFEFEF;
|
217
|
+
}
|
218
|
+
|
219
|
+
@keyframes glow {
|
220
|
+
0% {
|
221
|
+
text-shadow: 0 0 1rem #fefefe;
|
222
|
+
}
|
223
|
+
50% {
|
224
|
+
text-shadow: 0 0 1.85rem #ededed;
|
225
|
+
}
|
226
|
+
100% {
|
227
|
+
text-shadow: 0 0 1rem #fefefe;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
</style>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
module SeoOptimizer
|
6
|
+
class ModelsGenerator < Rails::Generators::NamedBase
|
7
|
+
source_root File.expand_path('templates', __dir__)
|
8
|
+
include Rails::Generators::Migration
|
9
|
+
desc 'Generates migration for models'
|
10
|
+
|
11
|
+
argument :desired_fields, type: :array, default: [], banner: "field field"
|
12
|
+
|
13
|
+
def self.orm
|
14
|
+
Rails::Generators.options[:rails][:orm]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.orm_has_migration?
|
18
|
+
[:active_record].include? orm
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.next_migration_number(_path)
|
22
|
+
Time.now.utc.strftime('%Y%m%d%H%M%S')
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_migration_file
|
26
|
+
return unless self.class.orm_has_migration?
|
27
|
+
|
28
|
+
migration_template 'model_template.erb',
|
29
|
+
"db/migrate/add_#{model_name}_seo_slug_migration.rb",
|
30
|
+
migration_version: migration_version,
|
31
|
+
model_name: model_name,
|
32
|
+
model_table: model_table,
|
33
|
+
desired_fields_reference: desired_fields_reference
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def model
|
40
|
+
name
|
41
|
+
end
|
42
|
+
|
43
|
+
def model_name
|
44
|
+
model.downcase
|
45
|
+
end
|
46
|
+
|
47
|
+
def model_table
|
48
|
+
model_name.pluralize(2)
|
49
|
+
end
|
50
|
+
|
51
|
+
def desired_fields_reference
|
52
|
+
desired_fields.delete('seo_slug')
|
53
|
+
desired_fields.join(', ')
|
54
|
+
end
|
55
|
+
|
56
|
+
def migration_version
|
57
|
+
if rails5?
|
58
|
+
'[4.2]'
|
59
|
+
elsif rails6?
|
60
|
+
'[6.0]'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def rails5?
|
65
|
+
Rails.version.start_with? '5'
|
66
|
+
end
|
67
|
+
|
68
|
+
def rails6?
|
69
|
+
Rails.version.start_with? '6'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Add<%= model_name.capitalize %>SeoSlugMigration < ActiveRecord::Migration<%= migration_version %>
|
2
|
+
def up
|
3
|
+
add_column(:<%= model_table %>, :seo_slug, :string) unless column_exists?(:<%= model_table %>, :seo_slug)
|
4
|
+
ActiveRecord::Base.connection.execute(query)
|
5
|
+
end
|
6
|
+
|
7
|
+
def down
|
8
|
+
remove_column :<%= model_table %>, :seo_slug
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def query
|
14
|
+
<<-SQL
|
15
|
+
UPDATE <%= model_table %>
|
16
|
+
SET seo_slug = concat_ws('-', id, <%= desired_fields_reference %>)
|
17
|
+
SQL
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
module SeoOptimizer
|
6
|
+
class RobotsFilesGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path('templates', __dir__)
|
8
|
+
desc 'Generates robots files'
|
9
|
+
|
10
|
+
def create_controller_files
|
11
|
+
prod_variable = Rails.configuration.sitemap_config_variable rescue raise(SeoOptimizer::Error, setup_error_message)
|
12
|
+
url = prod_variable[:production_url]
|
13
|
+
raise SeoOptimizer::Error, replace_url_error if !url || url == 'https://YOUR-PRODUCTION-URL.com'
|
14
|
+
|
15
|
+
site_map_xml
|
16
|
+
robots_text
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def robots_text
|
22
|
+
routing_code = %(get 'robots.:format', to: 'robots#show')
|
23
|
+
route routing_code
|
24
|
+
%x(rm -f public/robots.txt)
|
25
|
+
template 'robots_controller_template.erb', File.join('app/controllers', 'robots_controller.rb')
|
26
|
+
%x(mkdir -p app/views/robots)
|
27
|
+
template 'robots_show_template.erb', File.join('app/views/robots', 'show.txt.erb')
|
28
|
+
end
|
29
|
+
|
30
|
+
def site_map_xml
|
31
|
+
routing_code = %(get 'sitemap.xml', to: 'sitemaps#show', as: :sitemap, defaults: { format: :xml })
|
32
|
+
route routing_code
|
33
|
+
template 'sitemaps_controller_template.erb', File.join('app/controllers', 'sitemaps_controller.rb')
|
34
|
+
template 'sitemaps_task_template.erb', File.join('lib/tasks/sitemap', 'generate.rake')
|
35
|
+
end
|
36
|
+
|
37
|
+
def replace_url_error
|
38
|
+
'
|
39
|
+
Please replace https://YOUR-PRODUCTION-URL.com by your production url in application.rb,
|
40
|
+
check the doc https://github.com/RonanLOUARN/seo_optimizer for more infos.
|
41
|
+
'
|
42
|
+
end
|
43
|
+
|
44
|
+
def setup_error_message
|
45
|
+
'
|
46
|
+
Please type "rails generate seo_optimizer:setups" in terminal,
|
47
|
+
check the doc https://github.com/RonanLOUARN/seo_optimizer for more infos.
|
48
|
+
'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :sitemap do
|
4
|
+
task generate: :environment do
|
5
|
+
SitemapGenerator::Sitemap.default_host = '<%= Rails.configuration.sitemap_config_variable[:production_url] %>'
|
6
|
+
SitemapGenerator::Sitemap.create_index = false
|
7
|
+
SitemapGenerator::Sitemap.create do
|
8
|
+
routes = Rails.application.routes.routes.map do |route|
|
9
|
+
{
|
10
|
+
alias: route.name,
|
11
|
+
path: route.path.spec.to_s,
|
12
|
+
controller: route.defaults[:controller],
|
13
|
+
action: route.defaults[:action],
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Set a list of controllers you don't want to generate routes for.
|
18
|
+
# /rails/info in particular maps to something inaccessible.
|
19
|
+
# redirects have a nil controller. This prevents duplicate content penalties.
|
20
|
+
banned_controllers = ["rails/info", nil]
|
21
|
+
routes.reject! { |route| banned_controllers.include?(route[:controller]) }
|
22
|
+
|
23
|
+
# sitemap_generator includes root by default; prevent duplication
|
24
|
+
routes.reject! { |route| route[:path] == '/' }
|
25
|
+
|
26
|
+
routes.each { |route| add route[:path][0..-11] } # Strips off '(.:format)
|
27
|
+
|
28
|
+
# Notice the below if you're hosting Jekyll/Octopress in a subdirectory
|
29
|
+
# or otherwise want to index content outside of Rails' routes.
|
30
|
+
# add_to_index '/sitemaps/show.xml'
|
31
|
+
|
32
|
+
# example for user resources
|
33
|
+
# User.select(:seo_slug, :updated_at).each do |slug|
|
34
|
+
# add user_path(slug), lastmod: slug.updated_at
|
35
|
+
# end
|
36
|
+
end
|
37
|
+
SitemapGenerator::Sitemap.ping_search_engines('<%= Rails.configuration.sitemap_config_variable[:production_url] %>/sitemap.xml')
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
module SeoOptimizer
|
6
|
+
class SetupsGenerator < Rails::Generators::Base
|
7
|
+
source_root File.expand_path('templates', __dir__)
|
8
|
+
desc 'Generates setup lines'
|
9
|
+
|
10
|
+
def create_controller_files
|
11
|
+
Rails.configuration.sitemap_config_variable
|
12
|
+
rescue
|
13
|
+
inject_into_file 'config/application.rb', :before => " end" do
|
14
|
+
"\n config.sitemap_config_variable = {}" +
|
15
|
+
"\n config.sitemap_config_variable[:production_url] = 'https://YOUR-PRODUCTION-URL.com'\n\n"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require_relative 'lib/seo_optimizer/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = "seo_optimizer"
|
10
|
+
spec.version = SeoOptimizer::VERSION
|
11
|
+
spec.authors = ["Ronan Louarn"]
|
12
|
+
spec.email = ["ronan33720@hotmail.com"]
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
15
|
+
spec.summary = %q{Simple gem to improve SEO to your rails app.}
|
16
|
+
spec.description = %q{Simple gem to improve SEO to your rails app.}
|
17
|
+
spec.homepage = "https://www.lr-dev.fr"
|
18
|
+
spec.license = "MIT"
|
19
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
20
|
+
|
21
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
22
|
+
|
23
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
24
|
+
spec.metadata["source_code_uri"] = "https://github.com/RonanLOUARN/seo_optimizer"
|
25
|
+
spec.metadata["changelog_uri"] = "https://github.com/RonanLOUARN/seo_optimizer/commits/master"
|
26
|
+
|
27
|
+
# Specify which files should be added to the gem when it is released.
|
28
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
29
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
30
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
31
|
+
end
|
32
|
+
spec.bindir = "exe"
|
33
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
34
|
+
spec.require_paths = ["lib"]
|
35
|
+
spec.add_dependency 'sitemap_generator'
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: seo_optimizer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ronan Louarn
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-11-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sitemap_generator
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Simple gem to improve SEO to your rails app.
|
28
|
+
email:
|
29
|
+
- ronan33720@hotmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- ".rspec"
|
36
|
+
- ".ruby-version"
|
37
|
+
- ".travis.yml"
|
38
|
+
- CODE_OF_CONDUCT.md
|
39
|
+
- Gemfile
|
40
|
+
- Gemfile.lock
|
41
|
+
- LICENSE.txt
|
42
|
+
- README.md
|
43
|
+
- Rakefile
|
44
|
+
- bin/console
|
45
|
+
- bin/setup
|
46
|
+
- lib/generators/seo_optimizer/errors_pages/errors_pages_generator.rb
|
47
|
+
- lib/generators/seo_optimizer/errors_pages/templates/404.erb
|
48
|
+
- lib/generators/seo_optimizer/errors_pages/templates/500.erb
|
49
|
+
- lib/generators/seo_optimizer/errors_pages/templates/errors_controller_template.erb
|
50
|
+
- lib/generators/seo_optimizer/models/models_generator.rb
|
51
|
+
- lib/generators/seo_optimizer/models/templates/model_template.erb
|
52
|
+
- lib/generators/seo_optimizer/robots_files/robots_files_generator.rb
|
53
|
+
- lib/generators/seo_optimizer/robots_files/templates/robots_controller_template.erb
|
54
|
+
- lib/generators/seo_optimizer/robots_files/templates/robots_show_template.erb
|
55
|
+
- lib/generators/seo_optimizer/robots_files/templates/sitemaps_controller_template.erb
|
56
|
+
- lib/generators/seo_optimizer/robots_files/templates/sitemaps_task_template.erb
|
57
|
+
- lib/generators/seo_optimizer/setups/setups_generator.rb
|
58
|
+
- lib/seo_optimizer.rb
|
59
|
+
- lib/seo_optimizer/version.rb
|
60
|
+
- seo_optimizer.gemspec
|
61
|
+
homepage: https://www.lr-dev.fr
|
62
|
+
licenses:
|
63
|
+
- MIT
|
64
|
+
metadata:
|
65
|
+
allowed_push_host: https://rubygems.org
|
66
|
+
homepage_uri: https://www.lr-dev.fr
|
67
|
+
source_code_uri: https://github.com/RonanLOUARN/seo_optimizer
|
68
|
+
changelog_uri: https://github.com/RonanLOUARN/seo_optimizer/commits/master
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.3.0
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubygems_version: 3.1.2
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: Simple gem to improve SEO to your rails app.
|
88
|
+
test_files: []
|