Skip to content

Commit

Permalink
Better truncation of title, description, and keywords according to SE…
Browse files Browse the repository at this point in the history
…O best practices (configurable)
  • Loading branch information
kpumuk committed Apr 15, 2014
1 parent ab4fc6e commit 1c4ed21
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 18 deletions.
15 changes: 5 additions & 10 deletions lib/meta_tags/meta_tags_collection.rb
Expand Up @@ -82,17 +82,12 @@ def delete(*names)
# @return [String] page title.
#
def extract_full_title
title = extract_title || []
separator = extract_separator
site_title = extract(:site) || ''
title = extract_title || []
separator = extract_separator
reverse = extract(:reverse) === true

site_title = extract(:site).presence
title.unshift(site_title) if site_title
title = TextNormalizer.normalize_title(title)

title.reverse! if extract(:reverse) === true
title = TextNormalizer.safe_join(title, separator)

title
TextNormalizer.normalize_title(site_title, title, separator, reverse)
end

# Extracts page title as an array of segments without site title and separators.
Expand Down
4 changes: 2 additions & 2 deletions lib/meta_tags/renderer.rb
Expand Up @@ -199,8 +199,8 @@ def process_array(tags, property, content, options = {})
# Recursive method to process a hash with meta tags
#
# @param [Array<Tag>] tags a buffer object to store tag in.
# @param [String, Symbol] property a Hash or a String to render as meta tag.
# @param [String, Symbol] content text content or a symbol reference to
# @param [String, Symbol] name a Hash or a String to render as meta tag.
# @param [String, Symbol] value text content or a symbol reference to
# top-level meta tag.
#
def render_tag(tags, name, value, options = {})
Expand Down
69 changes: 64 additions & 5 deletions lib/meta_tags/text_normalizer.rb
Expand Up @@ -3,11 +3,26 @@ module MetaTags
module TextNormalizer
# Normalize title value.
#
# @param [String] site_title site title.
# @param [String, Array<String>] title title string.
# @param [String] separator a string to join title parts with.
# @param [true,false] reverse whether title should be reversed.
# @return [Array<String>] array of title parts with tags removed.
#
def self.normalize_title(title)
Array(title).flatten.map(&method(:strip_tags))
def self.normalize_title(site_title, title, separator, reverse = false)
title = Array(title).flatten.map(&method(:strip_tags))
title.reject!(&:blank?)
site_title = strip_tags(site_title)
separator = strip_tags(separator)

if MetaTags.config.title_limit
limit = MetaTags.config.title_limit - site_title.length - separator.length
title = truncate_array(title, limit, separator)
end

title.unshift(site_title) if site_title.present?
title.reverse! if reverse
safe_join(title, separator)
end

# Normalize description value.
Expand All @@ -18,7 +33,8 @@ def self.normalize_title(title)
#
def self.normalize_description(description)
return '' if description.blank?
helpers.truncate(cleanup_string(description), :length => 200)
description = cleanup_string(description)
truncate(description, MetaTags.config.description_limit)
end

# Normalize keywords value.
Expand All @@ -28,7 +44,11 @@ def self.normalize_description(description)
#
def self.normalize_keywords(keywords)
return '' if keywords.blank?
cleanup_strings(keywords).join(', ').downcase
keywords = cleanup_strings(keywords).each(&:downcase!)
separator = strip_tags MetaTags.config.keywords_separator

keywords = truncate_array(keywords, MetaTags.config.keywords_limit, separator)
safe_join(keywords, separator)
end

# Easy way to get access to Rails helpers.
Expand All @@ -45,7 +65,7 @@ def self.helpers
# @return [String] string with no HTML tags.
#
def self.strip_tags(string)
helpers.strip_tags(string)
ERB::Util.html_escape helpers.strip_tags(string)
end

# This method returns a html safe string similar to what <tt>Array#join</tt>
Expand Down Expand Up @@ -76,8 +96,47 @@ def self.cleanup_string(string)
# @param [Array<String>] strings input strings.
# @return [Array<String>] clean strings.
# @see cleanup_string
#
def self.cleanup_strings(strings)
Array(strings).flatten.map(&method(:cleanup_string))
end

# Truncates a string to a specific limit.
#
# @param [String] string input strings.
# @param [Integer,nil] limit characters number to truncate to.
# @param [String] natural_separator natural separator to truncate at.
# @return [String] truncated string.
#
def self.truncate(string, limit = nil, natural_separator = ' ')
string = helpers.truncate(string, :length => limit, :separator => natural_separator, :omission => '') if limit
string
end

# Truncates a string to a specific limit.
#
# @param [Array<String>] string_array input strings.
# @param [Integer,nil] limit characters number to truncate to.
# @param [String] separator separator that will be used to join array later.
# @param [String] natural_separator natural separator to truncate at.
# @return [String] truncated string.
#
def self.truncate_array(string_array, limit = nil, separator = '', natural_separator = ' ')
return string_array if limit.nil? || limit == 0
length = 0
result = []
string_array.each do |string|
limit_left = limit - length - separator.length
if string.length > limit_left
result << truncate(string, limit_left, natural_separator)
break
end
length += (result.any? ? separator.length : 0) + string.length
result << string
# No more strings will fit
break if length + separator.length >= limit
end
result
end
end
end
2 changes: 1 addition & 1 deletion spec/view_helper/description_spec.rb
Expand Up @@ -49,7 +49,7 @@

it 'should truncate correctly' do
subject.display_meta_tags(:site => 'someSite', :description => "Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.").tap do |meta|
expect(meta).to include('<meta content="Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dol..." name="description" />')
expect(meta).to include('<meta content="Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At" name="description" />')
end
end
end

0 comments on commit 1c4ed21

Please sign in to comment.