hancock_cms_seo 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +4 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +86 -0
  9. data/Rakefile +1 -0
  10. data/app/assets/javascripts/hancock/rails_admin/plugins/seo.coffee +4 -0
  11. data/app/assets/javascripts/hancock/rails_admin/plugins/seo/custom/ui.coffee +0 -0
  12. data/app/assets/stylesheets/hancock/rails_admin/plugins/seo.sass +3 -0
  13. data/app/assets/stylesheets/hancock/rails_admin/plugins/seo/custom/theming.sass +0 -0
  14. data/app/assets/stylesheets/hancock/rails_admin/plugins/seo/footer_nav_links.sass +16 -0
  15. data/app/controllers/concerns/hancock/seo/x_frame_options.rb +42 -0
  16. data/app/helpers/hancock/seo/seo_helper.rb +60 -0
  17. data/app/models/concerns/hancock/seo/decorators/seo.rb +60 -0
  18. data/app/models/concerns/hancock/seo/decorators/sitemap_data.rb +35 -0
  19. data/app/models/concerns/hancock/seo/seoable.rb +71 -0
  20. data/app/models/concerns/hancock/seo/sitemap_data_field.rb +37 -0
  21. data/app/models/concerns/hancock/seo/sitemapable.rb +7 -0
  22. data/app/models/hancock/seo/seo.rb +16 -0
  23. data/app/models/hancock/seo/sitemap_data.rb +16 -0
  24. data/app/views/blocks/_seo_block.html.slim +25 -0
  25. data/app/views/blocks/_seo_block_with_obj.html.slim +18 -0
  26. data/app/views/hancock/seo/blocks/_ga.html.slim +8 -0
  27. data/app/views/hancock/seo/blocks/_ym.html.slim +31 -0
  28. data/app/views/shared/_meta.html.slim +28 -0
  29. data/app/views/shared/_obj_with_seo.html.slim +38 -0
  30. data/app/views/shared/_og.html.slim +4 -0
  31. data/bin/console +14 -0
  32. data/bin/setup +7 -0
  33. data/config/initializers/hancock_seo.rb +7 -0
  34. data/config/locales/ru.hancock.seo.yml +37 -0
  35. data/hancock_cms_seo.gemspec +40 -0
  36. data/lib/generators/hancock/seo/config/config_generator.rb +13 -0
  37. data/lib/generators/hancock/seo/config/templates/hancock_seo.erb +10 -0
  38. data/lib/generators/hancock/seo/migrations/migrations_generator.rb +18 -0
  39. data/lib/generators/hancock/seo/migrations/templates/migration_seos.rb +48 -0
  40. data/lib/generators/hancock/seo/models/decorators_generator.rb +24 -0
  41. data/lib/generators/hancock/seo/models/seo_generator.rb +39 -0
  42. data/lib/generators/hancock/seo/models/sitemap_data_generator.rb +39 -0
  43. data/lib/generators/hancock/seo/models/templates/seo.erb +57 -0
  44. data/lib/generators/hancock/seo/models/templates/sitemap_data.erb +31 -0
  45. data/lib/generators/hancock/seo/sitemap/sitemap_generator.rb +27 -0
  46. data/lib/generators/hancock/seo/sitemap/templates/sitemap.erb +31 -0
  47. data/lib/hancock/seo/admin.rb +24 -0
  48. data/lib/hancock/seo/admin/seo.rb +69 -0
  49. data/lib/hancock/seo/admin/sitemap_data.rb +47 -0
  50. data/lib/hancock/seo/configuration.rb +29 -0
  51. data/lib/hancock/seo/engine.rb +44 -0
  52. data/lib/hancock/seo/models/active_record/seo.rb +14 -0
  53. data/lib/hancock/seo/models/active_record/sitemap_data.rb +11 -0
  54. data/lib/hancock/seo/models/mongoid/seo.rb +25 -0
  55. data/lib/hancock/seo/models/mongoid/sitemap_data.rb +24 -0
  56. data/lib/hancock/seo/models/seo.rb +114 -0
  57. data/lib/hancock/seo/models/sitemap_data.rb +79 -0
  58. data/lib/hancock/seo/version.rb +5 -0
  59. data/lib/hancock_cms_seo.rb +43 -0
  60. data/release.sh +6 -0
  61. metadata +193 -0
@@ -0,0 +1,37 @@
1
+ module Hancock::Seo::SitemapDataField
2
+ extend ActiveSupport::Concern
3
+ FIELDS = [:sitemap_show, :sitemap_lastmod, :sitemap_changefreq, :sitemap_priority]
4
+
5
+ included do
6
+ has_one :sitemap_data, as: :sitemap_data_field, autosave: true, class_name: "Hancock::Seo::SitemapData"
7
+ accepts_nested_attributes_for :sitemap_data
8
+
9
+ delegate *FIELDS, to: :sitemap_data
10
+ delegate *(FIELDS.map {|f| "#{f}=".to_sym }), to: :sitemap_data
11
+
12
+ alias sitemap_data_without_build sitemap_data
13
+ def sitemap_data
14
+ sitemap_data_without_build || build_sitemap_data
15
+ end
16
+
17
+ def default_sitemap_changefreq
18
+ 'weekly'
19
+ end
20
+ def default_sitemap_priority
21
+ 0.8
22
+ end
23
+
24
+ def to_sitemap(sitemap)
25
+ _sitemap_data = self.sitemap_data
26
+ _lastmod = _sitemap_data.sitemap_lastmod.to_date unless _sitemap_data.sitemap_lastmod.nil?
27
+ _lastmod = self.updated_at.to_date unless self.updated_at.nil? if _lastmod.nil?
28
+ _lastmod = self.created_at.to_date unless self.created_at.nil? if _lastmod.nil?
29
+
30
+ sitemap.add sitemap.url_for(i),
31
+ :lastmod => _lastmod,
32
+ :changefreq => "#{_sitemap_data.sitemap_changefreq.blank? ? self.default_sitemap_changefreq : _sitemap_data.sitemap_changefreq}",
33
+ :priority => (_sitemap_data.sitemap_priority.nil? ? self.default_sitemap_priority : _sitemap_data.sitemap_priority)
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,7 @@
1
+ module Hancock::Seo::Sitemapable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ include Hancock::Seo::SitemapDataField
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ module Hancock::Seo
2
+ if Hancock.active_record?
3
+ class Seo < ActiveRecord::Base
4
+ end
5
+ end
6
+
7
+ class Seo
8
+ include Hancock::Seo::Models::Seo
9
+
10
+ include Hancock::Seo::Decorators::Seo
11
+
12
+ rails_admin(&Hancock::Seo::Admin::Seo.config(rails_admin_add_fields) { |config|
13
+ rails_admin_add_config(config)
14
+ })
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Hancock::Seo
2
+ if Hancock.active_record?
3
+ class SitemapData < ActiveRecord::Base
4
+ end
5
+ end
6
+
7
+ class SitemapData
8
+ include Hancock::Seo::Models::SitemapData
9
+
10
+ include Hancock::Seo::Decorators::SitemapData
11
+
12
+ rails_admin(&Hancock::Seo::Admin::SitemapData.config(rails_admin_add_fields) { |config|
13
+ rails_admin_add_config(config)
14
+ })
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ - if @seo_page
2
+ - content_for :meta do
3
+ - _cache_helper = (Hancock::Seo.config.cache_support ? :hancock_cache : :cache)
4
+ - send _cache_helper, [@seo_page, @seo_parent_page, 'meta'].compact.uniq do
5
+ = render 'shared/meta', obj: @seo_page, alt_obj: @seo_parent_page
6
+
7
+ - og_title = (@seo_page.get_og_title.blank? and @seo_parent_page ? @seo_parent_page.get_og_title : @seo_page.get_og_title)
8
+ - og_image = (@seo_page.og_image.blank? and @seo_parent_page ? @seo_parent_page.og_image : @seo_page.og_image)
9
+ = render 'shared/og', title: og_title, image: og_image
10
+
11
+ - unless @seo_page.title.blank?
12
+ - content_for :title do
13
+ = @seo_page.title
14
+
15
+
16
+ - elsif @seo_parent_page
17
+ - content_for :meta do
18
+ - _cache_helper = (Hancock::Seo.config.cache_support ? :hancock_cache : :cache)
19
+ - send _cache_helper, [@seo_parent_page, 'meta'] do
20
+ = render 'shared/meta', obj: @seo_parent_page
21
+ = render 'shared/og', title: @seo_parent_page.get_og_title, image: @seo_parent_page.og_image
22
+
23
+ - unless @seo_parent_page.title.blank?
24
+ - content_for :title do
25
+ = @seo_parent_page.title
@@ -0,0 +1,18 @@
1
+ - obj ||= nil
2
+ - if obj
3
+ - seo_page = @seo_page || @seo_parent_page
4
+ - content_for :meta do
5
+ - _cache_helper = (Hancock::Seo.config.cache_support ? :hancock_cache : :cache)
6
+ - send _cache_helper, [obj, seo_page, 'meta'].uniq.compact do
7
+ = render 'shared/meta', obj: obj
8
+
9
+ - og_title = (obj.get_og_title.blank? and seo_page ? seo_page.get_og_title : obj.get_og_title)
10
+ - og_image = (obj.og_image.blank? and seo_page ? seo_page.og_image : obj.og_image)
11
+ = render 'shared/og', title: og_title, image: og_image
12
+
13
+ - unless obj.title.blank?
14
+ - content_for :title do
15
+ = obj.title
16
+
17
+ - else
18
+ = render 'blocks/seo_block'
@@ -0,0 +1,8 @@
1
+ javascript:
2
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
3
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
4
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
5
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
6
+
7
+ ga('create', '#{counter_id}', 'auto');
8
+ ga('send', 'pageview');
@@ -0,0 +1,31 @@
1
+ /! Yandex.Metrika counter
2
+ javascript:
3
+ (function (d, w, c) {
4
+ (w[c] = w[c] || []).push(function() {
5
+ try {
6
+ w.yaCounter#{counter_id} = new Ya.Metrika({
7
+ id:#{counter_id},
8
+ clickmap:true,
9
+ trackLinks:true,
10
+ accurateTrackBounce:true,
11
+ webvisor:true,
12
+ trackHash:true
13
+ });
14
+ } catch(e) { }
15
+ });
16
+
17
+ var n = d.getElementsByTagName("script")[0],
18
+ s = d.createElement("script"),
19
+ f = function () { n.parentNode.insertBefore(s, n); };
20
+ s.type = "text/javascript";
21
+ s.async = true;
22
+ s.src = "https://mc.yandex.ru/metrika/watch.js";
23
+
24
+ if (w.opera == "[object Opera]") {
25
+ d.addEventListener("DOMContentLoaded", f, false);
26
+ } else { f(); }
27
+ })(document, window, "yandex_metrika_callbacks");
28
+
29
+ noscript
30
+ div= image_tag "https://mc.yandex.ru/watch/#{counter_id}", style: "position:absolute; left:-9999px;", alt: ""
31
+ /! Yandex.Metrika counter
@@ -0,0 +1,28 @@
1
+ - alt_obj ||= nil
2
+
3
+ - if obj.respond_to?(:keywords) and !obj.keywords.blank?
4
+ meta{name="keywords" content=obj.keywords}/
5
+ - else
6
+ - if alt_obj and alt_obj.respond_to?(:keywords) and !alt_obj.keywords.blank?
7
+ meta{name="keywords" content=alt_obj.keywords}/
8
+
9
+
10
+ - if obj.respond_to?(:description) and !obj.description.blank?
11
+ meta{name="description" content=obj.description}/
12
+ - else
13
+ - if alt_obj and alt_obj.respond_to?(:description) and !alt_obj.description.blank?
14
+ meta{name="description" content=alt_obj.description}/
15
+
16
+
17
+ - if obj.respond_to?(:author) and !obj.author.blank?
18
+ meta{name="author" content=obj.author}/
19
+ - else
20
+ - if alt_obj and alt_obj.respond_to?(:author) and !alt_obj.author.blank?
21
+ meta{name="author" content=alt_obj.author}/
22
+
23
+
24
+ - if obj.respond_to?(:robots) and !obj.robots.blank?
25
+ meta{name="robots" content=obj.robots}/
26
+ - else
27
+ - if alt_obj and alt_obj.respond_to?(:robots) and !alt_obj.robots.blank?
28
+ meta{name="robots" content=alt_obj.robots}/
@@ -0,0 +1,38 @@
1
+ - obj ||= nil
2
+ - unless obj.nil?
3
+
4
+ - _cache_helper = (Hancock::Seo.config.cache_support ? :hancock_cache : :cache)
5
+ - send _cache_helper, [obj, @seo_page].uniq do
6
+ .text_content
7
+ - seo = obj.seo
8
+ - if (!defined?(h1) || h1) && seo and !seo.h1.blank?
9
+ h1= seo.h1
10
+
11
+ - if obj.content.blank?
12
+ - unless @seo_page.nil?
13
+ == @seo_page.page_content(self) rescue @seo_page.page_content
14
+ - else
15
+ - if defined?(Hancock::Pages::Page) and obj.is_a?(Hancock::Pages::Page)
16
+ == obj.page_content(self) rescue obj.page_content
17
+ - else
18
+ - if obj.respond_to?(:page_content)
19
+ == obj.page_content rescue obj.content
20
+ - else
21
+ == obj.content
22
+
23
+ = render 'blocks/seo_block_with_obj', obj: obj
24
+
25
+ / = render 'shared/admin_link', obj: obj
26
+ / - if !@seo_page.nil? && (@seo_page.id != obj.id || @seo_page.class.name != obj.class.name)
27
+ / = render 'shared/admin_link', obj: @seo_page
28
+
29
+ / - content_for :meta do
30
+ / - send _cache_helper, [obj, 'meta'] do
31
+ / = render 'shared/meta', obj: obj, alt_obj: @seo_page
32
+ / - og_title = (obj.get_og_title.blank? and @seo_page ? @seo_page.get_og_title : obj.get_og_title)
33
+ / - og_image = (obj.og_image.blank? and @seo_page ? @seo_page.og_image : obj.og_image)
34
+ / = render 'shared/og', title: _og_title, image: _og_image
35
+ /
36
+ / - content_for :title do
37
+ / - if obj.title
38
+ / = obj.title
@@ -0,0 +1,4 @@
1
+ - if defined?(title) && !title.blank?
2
+ meta{property='og:title' content=title}
3
+ - if defined?(image) && !image.blank?
4
+ meta{property='og:image' content="http://#{request.host_with_port}#{image}"}
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "hancock_cms_seo"
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
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ Hancock.rails_admin_configure do |config|
2
+ config.action_visible_for :sitemap, Proc.new { false }
3
+ config.action_visible_for :sitemap_for_model, 'Hancock::Seo::SitemapData'
4
+
5
+ config.action_visible_for :robots_txt, Proc.new { false }
6
+ config.action_visible_for :robots_txt_for_model, 'Hancock::Seo::Seo'
7
+ end
@@ -0,0 +1,37 @@
1
+ ru:
2
+ hancock:
3
+ seo_n_sitemap: SEO и карта сайта
4
+ seo:
5
+ seo: SEO
6
+ sitemap_data: Карта сайта
7
+
8
+
9
+ mongoid: &mongoid
10
+ models:
11
+ hancock/seo/seo: SEO
12
+ hancock/seo/sitemap_data: Карта сайта
13
+ activerecord:
14
+ <<: *mongoid
15
+
16
+ attributes:
17
+ hancock/seo/seo:
18
+ seoable: Родительский элемент/страница
19
+ title: Title
20
+ description: SEO Description
21
+ keywords: SEO Keywords
22
+ og_title: Og title
23
+ og_image: Og image
24
+ robots: Robots
25
+ hancock/seo/sitemap_data:
26
+ sitemap_data_field: Родительский элемент/страница
27
+ sitemap_show: Отображать в карте сайта
28
+ sitemap_lastmod: lastmod
29
+ sitemap_changefreq: changefreq
30
+ sitemap_priority: priority
31
+
32
+ admin:
33
+ actions:
34
+ hancock_sitemap_generate:
35
+ menu: "Сгенирить карту сайта"
36
+ breadcrumb: "Сгенирить карту сайта"
37
+ title: "Сгенирить карту сайта"
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hancock/seo/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hancock_cms_seo"
8
+ spec.version = Hancock::Seo::VERSION
9
+ spec.authors = ["Alexander Kiseliev"]
10
+ spec.email = ["dev@redrocks.pro"]
11
+
12
+ spec.description = %q{hancock_cms_seo }
13
+ spec.summary = %q{hancock_cms_seo}
14
+ spec.homepage = 'https://github.com/red-rocks/hancock_cms_seo'
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ # end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.10"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+
33
+ spec.add_dependency 'hancock_cms', [">=1.0.2", "<2.1.x"]
34
+ # spec.add_dependency 'hancock_cms', ["~> 1.0.2", "~> 2.0"]
35
+
36
+ spec.add_dependency "sitemap_generator", '~> 5.3.1' #5.2.0
37
+ spec.add_dependency "rails_admin_sitemap", '~> 0.3.0'
38
+
39
+ spec.add_dependency "rails_admin_robots_txt", '~> 0.1.0'
40
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators'
2
+
3
+ module Hancock::Seo
4
+ class ConfigGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../templates', __FILE__)
6
+
7
+ desc 'Hancock::Seo Config generator'
8
+ def config
9
+ template 'hancock_seo.erb', "config/initializers/hancock_seo.rb"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ Hancock::Seo.configure do |config|
2
+ ##### defaults #####
3
+ # config.localize = Hancock.config.localize
4
+ #
5
+ # config.gallery_support = !!defined?(Hancock::Gallery)
6
+
7
+ # config.model_settings_support = !!defined?(RailsAdminModelSettings)
8
+ # config.user_abilities_support = !!defined?(RailsAdminUserAbilities)
9
+ # config.ra_comments_support = !!defined?(RailsAdminComments)
10
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/active_record'
3
+
4
+ module Hancock::Seo
5
+ class MigrationsGenerator < Rails::Generators::Base
6
+ include ActiveRecord::Generators::Migration
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ desc 'Hancock SEO migration generator'
10
+ def migrations
11
+ if Hancock.active_record?
12
+ %w(seos).each do |table_name|
13
+ migration_template "migration_#{table_name}.rb", "db/migrate/hancock_create_#{table_name}.rb"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ class HancockCreateSeos < ActiveRecord::Migration
2
+ def change
3
+ ############## SEO ###################33
4
+ create_table :hancock_seo_seos do |t|
5
+ t.boolean :enabled, default: true, null: false
6
+ t.integer :seoable_id
7
+ t.string :seoable_type
8
+
9
+ if Hancock::Seo.config.localize
10
+ t.column :h1_translations, 'hstore', default: {}
11
+ t.column :title_translations, 'hstore', default: {}
12
+ t.column :keywords_translations, 'hstore', default: {}
13
+ t.column :description_translations, 'hstore', default: {}
14
+ t.column :og_title_translations, 'hstore', default: {}
15
+ else
16
+ t.string :h1
17
+ t.string :title
18
+ t.text :keywords
19
+ t.text :description
20
+ t.string :og_title
21
+ end
22
+ t.string :robots
23
+ t.attachment :og_image
24
+
25
+ t.timestamps
26
+ end
27
+
28
+ add_index :hancock_seo_seos, [:seoable_id, :seoable_type], unique: true
29
+
30
+
31
+
32
+ ################# SITEMAP #####################
33
+ create_table :hancock_seo_sitemap_data do |t|
34
+ t.boolean :enabled, default: true, null: false
35
+ t.integer :sitemap_data_field_id
36
+ t.string :sitemap_data_field_type
37
+
38
+ t.boolean :sitemap_show, default: true, null: false
39
+ t.timestamps :sitemap_lastmod
40
+ t.string :sitemap_changefreq
41
+ t.float :sitemap_priority
42
+
43
+ t.timestamps
44
+ end
45
+
46
+ add_index :hancock_seo_sitemap_data, [:sitemap_data_field_id, :sitemap_data_field_type], unique: true
47
+ end
48
+ end