implement feature #57
This commit is contained in:
parent
d4b7734003
commit
fa7e4c24d8
@ -4,10 +4,11 @@ module Extensions
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
field :seo_title, :type => String
|
||||
field :meta_keywords, :type => String
|
||||
field :meta_description, :type => String
|
||||
end
|
||||
|
||||
|
||||
end # Seo
|
||||
end # Shared
|
||||
end # Extensions
|
||||
|
@ -5,11 +5,11 @@ class Site
|
||||
## Extensions ##
|
||||
extend Extensions::Site::SubdomainDomains
|
||||
extend Extensions::Site::FirstInstallation
|
||||
extend Extensions::Site::FirstInstallation
|
||||
include Extensions::Shared::Seo
|
||||
|
||||
## fields ##
|
||||
field :name
|
||||
field :meta_keywords
|
||||
field :meta_description
|
||||
|
||||
## associations ##
|
||||
references_many :pages, :validate => false
|
||||
|
@ -7,5 +7,6 @@
|
||||
= f.foldable_inputs :name => :advanced_options do
|
||||
|
||||
= f.input :_slug
|
||||
= f.input :seo_title
|
||||
= f.input :meta_keywords
|
||||
= f.input :meta_description
|
||||
|
@ -11,8 +11,9 @@
|
||||
|
||||
= f.input :slug, :required => false, :hint => @page.slug.blank? ? ' ' : page_url(@page), :input_html => { :data_url => get_path_admin_pages_url, :disabled => @page.index? || @page.not_found? }, :wrapper_html => { :style => "#{'display: none' if @page.templatized?}; height: 50px" }
|
||||
|
||||
= f.foldable_inputs :name => :meta do
|
||||
= f.foldable_inputs :name => :seo do
|
||||
|
||||
= f.input :seo_title
|
||||
= f.input :meta_keywords
|
||||
= f.input :meta_description
|
||||
|
||||
|
@ -63,6 +63,7 @@ fr:
|
||||
redirect: Redirection
|
||||
redirect_url: Url de redirection
|
||||
cache_strategy: Cache
|
||||
seo_title: Titre SEO
|
||||
content_type:
|
||||
name: Nom
|
||||
description: Description
|
||||
|
@ -4,6 +4,7 @@ en:
|
||||
information: General information
|
||||
advanced_options: Advanced options
|
||||
meta: SEO Metadata
|
||||
seo: SEO settings
|
||||
code: Code
|
||||
raw_template: Template
|
||||
credentials: Credentials
|
||||
@ -46,6 +47,8 @@ en:
|
||||
edit:
|
||||
password: New password
|
||||
password_confirmation: New password confirmation
|
||||
page:
|
||||
seo_title: Title
|
||||
|
||||
hints:
|
||||
page:
|
||||
@ -54,6 +57,7 @@ en:
|
||||
templatized: "Use the page as a template for a model you defined."
|
||||
listed: "Control whether to show the page from generated menus."
|
||||
content_type_id: "The type of content this page will be a template for."
|
||||
seo_title: "Define a page title which should be used as the value for the title tag in the head section."
|
||||
meta_keywords: "Overrides the site's meta keywords used within the head tag of the page. They are separated by a comma."
|
||||
meta_description: "Overrides the site's meta description used within the head tag of the page."
|
||||
snippet:
|
||||
@ -78,6 +82,9 @@ en:
|
||||
hint: "Text displayed in the model form just below the field"
|
||||
content_instance:
|
||||
_slug: "Property used to generate the url of a page working as a template for this content type (ex: \"template_page/{{ your_object._permalink }})\"."
|
||||
seo_title: "The value you fill in will replace the SEO title of the templatized page related to your model."
|
||||
meta_keywords: "Overrides the site's meta keywords used within the head tag of the page. They are separated by a comma."
|
||||
meta_description: "Overrides the site's meta description used within the head tag of the page."
|
||||
import:
|
||||
source: "A zipfile containing a database.yml along with assets and templates"
|
||||
samples: "If enabled, the import process will also copy contents and assets"
|
||||
|
@ -4,6 +4,7 @@ fr:
|
||||
information: Informations générales
|
||||
advanced_options: Options avancées
|
||||
meta: SEO Metadata
|
||||
seo: Paramètres SEO
|
||||
code: Code
|
||||
raw_template: Gabarit
|
||||
credentials: Informations de connexion
|
||||
@ -48,6 +49,8 @@ fr:
|
||||
edit:
|
||||
password: Nouveau mot de passe
|
||||
password_confirmation: Confirmation nouveau mot de passe
|
||||
page:
|
||||
seo_title: Titre
|
||||
|
||||
hints:
|
||||
page:
|
||||
@ -56,6 +59,7 @@ fr:
|
||||
templatized: "Utilise la page comme un template pour un modèle défini."
|
||||
listed: "Controle si la page doit être visible depuis les menus automatiquement générés."
|
||||
content_type_id: "Le type du contenu pour lequel cette page est un template."
|
||||
seo_title: "Définit un titre de page à mettre dans la balise TITLE de la page."
|
||||
meta_keywords: "Redéfinit les mots-clés du site. Utilisés à l'intérieur de la balise HEAD. Ils sont séparés par une virgule."
|
||||
meta_description: "Redéfinit la description du site. Utilisée à l'intérieur de la balise HEAD."
|
||||
snippet:
|
||||
@ -80,6 +84,9 @@ fr:
|
||||
hint: "Texte affiché dans le formulaire de l'élément juste en dessous du champ."
|
||||
content_instance:
|
||||
_slug: "Propriété utilisée pour générer l'url d'une page faisant office de template pour ce modèle (ex: \"template_de_la_page/{{ votre_object._permalink }})\"."
|
||||
seo_title: "La valeur que vous rentrez sera utilisée comme titre SEO pour la page faisant office de template pour ce modèle."
|
||||
meta_keywords: "Redéfinit les mots-clés du site. Utilisés à l'intérieur de la balise HEAD. Ils sont séparés par une virgule."
|
||||
meta_description: "Redéfinit la description du site. Utilisée à l'intérieur de la balise HEAD."
|
||||
import:
|
||||
source: "Un fichier zip contenant database.yml, les fichiers du thème et les templates de page"
|
||||
samples: "Si activé, les contenus et les média seront aussi copiés lors de l'import"
|
||||
|
1
doc/TODO
1
doc/TODO
@ -24,6 +24,7 @@ x bushido changes in the master
|
||||
x SEO: support and support/ should be 2 different pages. Remove trailing slash
|
||||
x issue #91: httparty
|
||||
x issue #90: seo metadata
|
||||
- issue #57: seo page title
|
||||
- Has_one => group by in the select
|
||||
- convert existing templates (the 2 of the themes section)
|
||||
- better hints:
|
||||
|
@ -2,7 +2,7 @@ module Locomotive
|
||||
module Liquid
|
||||
module Drops
|
||||
class Content < Base
|
||||
delegate :meta_keywords, :meta_description, :to => '_source'
|
||||
delegate :seo_title, :meta_keywords, :meta_description, :to => '_source'
|
||||
|
||||
def _id
|
||||
self._source._id.to_s
|
||||
|
@ -2,7 +2,7 @@ module Locomotive
|
||||
module Liquid
|
||||
module Drops
|
||||
class Page < Base
|
||||
delegate :meta_keywords, :meta_description, :to => "_source"
|
||||
delegate :seo_title, :meta_keywords, :meta_description, :to => "_source"
|
||||
|
||||
def title
|
||||
self._source.templatized? ? @context['content_instance'].highlighted_field_value : self._source.title
|
||||
|
@ -3,7 +3,7 @@ module Locomotive
|
||||
module Drops
|
||||
class Site < Base
|
||||
|
||||
liquid_attributes << :name << :meta_keywords << :meta_description
|
||||
liquid_attributes << :name << :seo_title << :meta_keywords << :meta_description
|
||||
|
||||
def index
|
||||
@index ||= self._source.pages.root.first
|
||||
|
72
lib/locomotive/liquid/tags/seo.rb
Normal file
72
lib/locomotive/liquid/tags/seo.rb
Normal file
@ -0,0 +1,72 @@
|
||||
module Locomotive
|
||||
module Liquid
|
||||
module Tags
|
||||
module SEO
|
||||
|
||||
class Base < ::Liquid::Tag
|
||||
|
||||
def render(context)
|
||||
%{
|
||||
#{self.render_title(context)}
|
||||
#{self.render_metadata(context)}
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def render_title(context)
|
||||
title = self.value_for(:seo_title, context)
|
||||
title = context.registers[:site].name if title.blank?
|
||||
|
||||
%{
|
||||
<title>#{title}</title>
|
||||
}
|
||||
end
|
||||
|
||||
def render_metadata(context)
|
||||
%{
|
||||
<meta name="description" content="#{self.value_for(:meta_description, context)}" />
|
||||
<meta name="keywords" content="#{self.value_for(:meta_keywords, context)}" />
|
||||
}
|
||||
end
|
||||
|
||||
# Removes whitespace and quote charactets from the input
|
||||
def sanitized_string(string)
|
||||
string ? string.strip.gsub(/"/, '') : ''
|
||||
end
|
||||
|
||||
def value_for(attribute, context)
|
||||
object = self.metadata_object(context)
|
||||
value = object.try(attribute.to_sym).blank? ? context.registers[:site].send(attribute.to_sym) : object.send(attribute.to_sym)
|
||||
self.sanitized_string(value)
|
||||
end
|
||||
|
||||
def metadata_object(context)
|
||||
context['content_instance'] || context['page']
|
||||
end
|
||||
end
|
||||
|
||||
class Title < Base
|
||||
|
||||
def render(context)
|
||||
self.render_title(context)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Metadata < Base
|
||||
|
||||
def render(context)
|
||||
self.render_metadata(context)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
::Liquid::Template.register_tag('seo', SEO::Base)
|
||||
::Liquid::Template.register_tag('seo_title', SEO::Title)
|
||||
::Liquid::Template.register_tag('seo_metadata', SEO::Metadata)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,38 +0,0 @@
|
||||
module Locomotive
|
||||
module Liquid
|
||||
module Tags
|
||||
class SEOMetadata < ::Liquid::Tag
|
||||
|
||||
def render(context)
|
||||
%{
|
||||
<meta name="description" content="#{sanitized_string(meta_description(context))}" />
|
||||
<meta name="keywords" content="#{sanitized_string(meta_keywords(context))}" />
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Removes whitespace and quote charactets from the input
|
||||
def sanitized_string(string)
|
||||
string ? string.strip.gsub(/"/, '') : ''
|
||||
end
|
||||
|
||||
def meta_description(context)
|
||||
object = metadata_object(context)
|
||||
object.try(:meta_description).blank? ? context.registers[:site].meta_description : object.meta_description
|
||||
end
|
||||
|
||||
def meta_keywords(context)
|
||||
object = metadata_object(context)
|
||||
object.try(:meta_keywords).blank? ? context.registers[:site].meta_keywords : object.meta_keywords
|
||||
end
|
||||
|
||||
def metadata_object(context)
|
||||
context['content_instance'] || context['page']
|
||||
end
|
||||
end
|
||||
|
||||
::Liquid::Template.register_tag('seo_metadata', SEOMetadata)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,14 +1,30 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Locomotive::Liquid::Tags::SEOMetadata do
|
||||
describe Locomotive::Liquid::Tags::SEO do
|
||||
|
||||
let(:site) do
|
||||
Factory.build(:site, :meta_description => 'A short site description', :meta_keywords => 'test only cat dog')
|
||||
Factory.build(:site, :seo_title => 'Site title (SEO)', :meta_description => 'A short site description', :meta_keywords => 'test only cat dog')
|
||||
end
|
||||
|
||||
describe 'rendering' do
|
||||
|
||||
it 'renders a a meta description tag' do
|
||||
it 'renders everything' do
|
||||
html = render_seo
|
||||
html.should include '<title>Site title (SEO)</title>'
|
||||
html.should include '<meta name="description" content="A short site description" />'
|
||||
html.should include '<meta name="keywords" content="test only cat dog" />'
|
||||
end
|
||||
|
||||
it 'renders a seo title' do
|
||||
render_seo_title.should include '<title>Site title (SEO)</title>'
|
||||
end
|
||||
|
||||
it 'renders the site title if no seo title is provided' do
|
||||
site.seo_title = nil
|
||||
render_seo_title.should include '<title>Acme Website</title>'
|
||||
end
|
||||
|
||||
it 'renders a meta description tag' do
|
||||
render_seo_metadata.should include '<meta name="description" content="A short site description" />'
|
||||
end
|
||||
|
||||
@ -33,6 +49,18 @@ describe Locomotive::Liquid::Tags::SEOMetadata do
|
||||
|
||||
context "when page" do
|
||||
|
||||
context "has seo title" do
|
||||
let(:page) { site.pages.build(:seo_title => 'Page title (SEO)', :meta_keywords => 'hulk,gamma', :meta_description => "Bruce Banner") }
|
||||
subject { render_seo_title('page' => page) }
|
||||
it { should include(%Q[<title>Page title (SEO)</title>]) }
|
||||
end
|
||||
|
||||
context "does not have seo title" do
|
||||
let(:page) { site.pages.build }
|
||||
subject { render_seo_title('page' => page) }
|
||||
it { should include(%Q[<title>Site title (SEO)</title>]) }
|
||||
end
|
||||
|
||||
context "has metadata" do
|
||||
let(:page) { site.pages.build(:meta_keywords => 'hulk,gamma', :meta_description => "Bruce Banner") }
|
||||
subject { render_seo_metadata('page' => page) }
|
||||
@ -46,6 +74,7 @@ describe Locomotive::Liquid::Tags::SEOMetadata do
|
||||
it { should include(%Q[<meta name="keywords" content="#{site.meta_keywords}" />]) }
|
||||
it { should include(%Q[<meta name="description" content="#{site.meta_description}" />]) }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "when content instance" do
|
||||
@ -56,6 +85,18 @@ describe Locomotive::Liquid::Tags::SEOMetadata do
|
||||
end
|
||||
end
|
||||
|
||||
context "has seo title" do
|
||||
let(:content) { content_type.contents.build(:seo_title => 'Content title (SEO)', :meta_keywords => 'Libidinous, Angsty', :meta_description => "Quite the combination.") }
|
||||
subject { render_seo_title('content_instance' => content) }
|
||||
it { should include(%Q[<title>Content title (SEO)</title>]) }
|
||||
end
|
||||
|
||||
context "does not have seo title" do
|
||||
let(:content) { content_type.contents.build }
|
||||
subject { render_seo_title('content_instance' => content) }
|
||||
it { should include(%Q[<title>Site title (SEO)</title>]) }
|
||||
end
|
||||
|
||||
context "has metadata" do
|
||||
let(:content) { content_type.contents.build(:meta_keywords => 'Libidinous, Angsty', :meta_description => "Quite the combination.") }
|
||||
subject { render_seo_metadata('content_instance' => content) }
|
||||
@ -69,13 +110,26 @@ describe Locomotive::Liquid::Tags::SEOMetadata do
|
||||
it { should include(%Q[<meta name="keywords" content="#{site.meta_keywords}" />]) }
|
||||
it { should include(%Q[<meta name="description" content="#{site.meta_description}" />]) }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def render_seo(assigns = {})
|
||||
render_seo_tag('seo', assigns)
|
||||
end
|
||||
|
||||
def render_seo_title(assigns = {})
|
||||
render_seo_tag('seo_title', assigns)
|
||||
end
|
||||
|
||||
def render_seo_metadata(assigns = {})
|
||||
render_seo_tag('seo_metadata', assigns)
|
||||
end
|
||||
|
||||
def render_seo_tag(tag_name, assigns = {})
|
||||
registers = { :site => site }
|
||||
liquid_context = ::Liquid::Context.new({}, assigns, registers)
|
||||
output = Liquid::Template.parse("{% seo_metadata %}").render(liquid_context)
|
||||
output = Liquid::Template.parse("{% #{tag_name} %}").render(liquid_context)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user