represent 0.0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Lance Pollard (lancejpollard@gmail.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,36 @@
1
+ # Represent
2
+
3
+ <q>DRY, SEO-friendly Rails Views</q>
4
+
5
+ ## Usage
6
+
7
+ ### Install
8
+
9
+ sudo gem install represent
10
+
11
+ ### Helpers
12
+
13
+ #### Metadata Helpers
14
+
15
+ Adding metadata to your views is easy (`app/views/pages/index.html.erb`):
16
+
17
+ <% title @post.title %>
18
+ <% description @post.description %>
19
+ <% keywords @post.tag_list %>
20
+ <% body_class "post post-template" %>
21
+
22
+ <div id="content">...</div>
23
+
24
+ Default metadata is just as easy (`app/views/layouts/application.html.erb`):
25
+
26
+ <%= meta_tags "My Site",
27
+ :keywords => "Rails 3, jQuery",
28
+ :description => "This is what Facebook displays" %>
29
+
30
+ #### System Helpers
31
+
32
+ Need to check what browser it is? No problem.
33
+
34
+ #### Layout Helpers
35
+
36
+ Would you like to create a nested menu, or a grid? No problem.
data/Rakefile ADDED
@@ -0,0 +1,78 @@
1
+ require 'rake'
2
+ require "rake/rdoctask"
3
+ require 'rake/gempackagetask'
4
+
5
+ spec = Gem::Specification.new do |s|
6
+ s.name = "represent"
7
+ s.authors = ["Lance Pollard"]
8
+ s.version = "0.0.1.5"
9
+ s.summary = "Represent: DRY, SEO-friendly Rails Views"
10
+ s.homepage = "http://github.com/viatropos/represent"
11
+ s.email = "lancejpollard@gmail.com"
12
+ s.description = "DRY, SEO-friendly Rails Views"
13
+ s.has_rdoc = false
14
+ s.rubyforge_project = "represent"
15
+ s.platform = Gem::Platform::RUBY
16
+ s.files = %w(README.markdown Rakefile init.rb MIT-LICENSE) + Dir["{lib,rails,test}/**/*"] - Dir["test/tmp"]
17
+ s.require_path = "lib"
18
+ end
19
+
20
+ Rake::GemPackageTask.new(spec) do |pkg|
21
+ pkg.gem_spec = spec
22
+ pkg.package_dir = "pkg"
23
+ end
24
+
25
+ desc 'run unit tests'
26
+ task :test do
27
+ Dir["test/**/*"].each do |file|
28
+ next unless File.basename(file) =~ /test_/
29
+ next unless File.extname(file) == ".rb"
30
+ system "ruby #{file}"
31
+ end
32
+ end
33
+
34
+ desc "Create .gemspec file (useful for github)"
35
+ task :gemspec do
36
+ File.open("pkg/#{spec.name}.gemspec", "w") do |f|
37
+ f.puts spec.to_ruby
38
+ end
39
+ end
40
+
41
+ desc "Build the gem into the current directory"
42
+ task :gem => :gemspec do
43
+ `gem build pkg/#{spec.name}.gemspec`
44
+ end
45
+
46
+ desc "Publish gem to rubygems"
47
+ task :publish => [:package] do
48
+ %x[gem push pkg/#{spec.name}-#{spec.version}.gem]
49
+ end
50
+
51
+ desc "Print a list of the files to be put into the gem"
52
+ task :manifest do
53
+ File.open("Manifest", "w") do |f|
54
+ spec.files.each do |file|
55
+ f.puts file
56
+ end
57
+ end
58
+ end
59
+
60
+ desc "Install the gem locally"
61
+ task :install => [:package] do
62
+ File.mkdir("pkg") unless File.exists?("pkg")
63
+ command = "gem install pkg/#{spec.name}-#{spec.version} --no-ri --no-rdoc"
64
+ command = "sudo #{command}" if ENV["SUDO"] == true
65
+ sh %{#{command}}
66
+ end
67
+
68
+ desc "Generate the rdoc"
69
+ Rake::RDocTask.new do |rdoc|
70
+ files = ["README.markdown", "lib/**/*.rb"]
71
+ rdoc.rdoc_files.add(files)
72
+ rdoc.main = "README.markdown"
73
+ rdoc.title = spec.summary
74
+ end
75
+
76
+ task :yank do
77
+ `gem yank #{spec.name} -v #{spec.version}`
78
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ File.dirname(__FILE__) + "/rails/init.rb"
@@ -0,0 +1,14 @@
1
+ # since I love the haml pretty-printed output so much,
2
+ # this makes it so I can use that instead of the built in
3
+ # rails ugly printing
4
+ module Represent
5
+ module Adapter
6
+ def render_tag(name, *args, &block)
7
+ if self.respond_to?("is_haml?".to_sym) and is_haml?
8
+ haml_tag(name.to_sym, options)
9
+ else
10
+ tag(name.to_sym)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Represent
2
+ module BodyHelper
3
+ def body_id(string)
4
+ @body_id = string
5
+ end
6
+
7
+ def body_class(string)
8
+ @body_class = string
9
+ end
10
+
11
+ def body_attributes(options = {})
12
+ options[:class] = @body_class if @body_class
13
+ options[:id] = @body_id if @body_id
14
+
15
+ options
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module Represent
2
+ module GridHelper
3
+ def grid_for(array, options = {}, &block)
4
+ return "" if array.empty?
5
+ columns = options[:columns] || 3
6
+ (array / columns).each do |row|
7
+ yield row
8
+ end
9
+ end
10
+
11
+ def row_for(array, options = {}, &block)
12
+ return "" if array.empty?
13
+ array.each_with_index do |node, i|
14
+ attributes = options.has_key?(:li_attributes) ? options[:li_attributes] : {}
15
+ attributes[:class] ||= ""
16
+ if i == 0 and options.has_key?(:first)
17
+ attributes[:class] << "#{options[:first]}"
18
+ elsif i == array.length - 1 and options.has_key?(:last)
19
+ attributes[:class] << "#{options[:last]}"
20
+ end
21
+ haml_tag :li, attributes do
22
+ if block_given?
23
+ yield node, i
24
+ else
25
+ haml_concat node.title
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,213 @@
1
+ module Represent
2
+ module HeadHelper
3
+
4
+ def meta(options = {})
5
+ title(options[:title]) if options.has_key?(:title)
6
+ description(options[:description]) if options.has_key?(:description)
7
+ keywords(options[:keywords]) if options.has_key?(:keywords)
8
+ copyright(options[:copyright]) if options.has_key?(:copyright)
9
+ end
10
+
11
+ def meta_tags(*args)
12
+ options = args.extract_options!
13
+ site = options[:site] || args.first
14
+ result = title_tag(site, options[:title])
15
+ result << "\n"
16
+ result << content_type_tag
17
+ result << "\n"
18
+ result << description_tag(options[:description])
19
+ result << "\n"
20
+ result << keywords_tag(options[:keywords])
21
+ result << "\n"
22
+ result << copyright_tag(options[:copyright])
23
+ result
24
+ end
25
+
26
+ # country
27
+ # classification
28
+ # author
29
+ # apple-mobile-web-app-capable
30
+ # apple-touch-fullscreen
31
+ # google-analytics
32
+ # Revisit-After
33
+ # category
34
+ def meta_tag(name, content = '')
35
+ tag(:meta, :name => name, :content => content)
36
+ end
37
+
38
+ def title(string)
39
+ @content_for_title = string
40
+ end
41
+
42
+ def title_tag(*args)
43
+ options = args.extract_options!
44
+
45
+ site = options[:site] || args.first
46
+ # Prefix (leading space)
47
+ if options[:prefix]
48
+ prefix = options[:prefix]
49
+ elsif options[:prefix] === false
50
+ prefix = ''
51
+ else
52
+ prefix = ' '
53
+ end
54
+
55
+ # Separator
56
+ unless options[:separator].blank?
57
+ separator = options[:separator]
58
+ else
59
+ separator = '|'
60
+ end
61
+
62
+ # Suffix (trailing space)
63
+ if options[:suffix]
64
+ suffix = options[:suffix]
65
+ elsif options[:suffix] === false
66
+ suffix = ''
67
+ else
68
+ suffix = ' '
69
+ end
70
+
71
+ # Title
72
+ title = @content_for_title
73
+ if options[:lowercase] === true
74
+ title = title.downcase unless title.blank?
75
+ end
76
+
77
+ # title
78
+ if title.blank?
79
+ result = content_tag :title, site
80
+ else
81
+ title = normalize_title(title)
82
+ title = [site] + title
83
+ title.reverse! if options[:reverse] === true
84
+ sep = prefix + separator + suffix
85
+ result = content_tag(:title, title.join(sep))
86
+ end
87
+ result
88
+ end
89
+
90
+ def description(string)
91
+ @content_for_description = string
92
+ end
93
+
94
+ def description_tag(default='')
95
+ content = normalize_description(@content_for_description || default)
96
+ tag(:meta, :name => :description, :content => content) unless content.blank?
97
+ end
98
+
99
+ def keywords(string)
100
+ @content_for_keywords = string
101
+ end
102
+
103
+ def keywords_tag(default = '')
104
+ content = normalize_keywords(@content_for_keywords || default)
105
+ tag(:meta, :name => :keywords, :content => content) unless content.blank?
106
+ end
107
+
108
+ def copyright(string)
109
+ @content_for_copyright = string
110
+ end
111
+
112
+ def copyright_tag(default='')
113
+ content = @content_for_copyright || default
114
+ tag(:meta, :name => :copyright, :content => content) unless content.blank?
115
+ end
116
+
117
+ def robots(*args)
118
+ content_for(:robots, args.join(", "))
119
+ end
120
+
121
+ def robots_tag(*args)
122
+ options = args.extract_options!
123
+
124
+ noindex_name = tags[:noindex].is_a?(String) ? tags[:noindex] : 'robots'
125
+ nofollow_name = tags[:nofollow].is_a?(String) ? tags[:nofollow] : 'robots'
126
+
127
+ if noindex_name == nofollow_name
128
+ content = [(tags[:noindex] ? 'noindex' : nil), (tags[:nofollow] ? 'nofollow' : nil)].compact.join(', ')
129
+ unless content.blank?
130
+ result << "\n"
131
+ result << tag(:meta, :name => noindex_name, :content => content)
132
+ end
133
+ else
134
+ if tags[:noindex]
135
+ result << "\n"
136
+ result << tag(:meta, :name => noindex_name, :content => 'noindex')
137
+ end
138
+ if tags[:nofollow]
139
+ result << "\n"
140
+ result << tag(:meta, :name => nofollow_name, :content => 'nofollow')
141
+ end
142
+ end
143
+ # canonical
144
+ unless tags[:canonical].blank?
145
+ result << "\n"
146
+ result << tag(:link, :rel => :canonical, :href => tags[:canonical])
147
+ end
148
+
149
+ return result
150
+ end
151
+
152
+ def copyright(from)
153
+ now = Time.now.year
154
+ now.eql?(from) ? now : "#{from} - #{now}"
155
+ end
156
+
157
+ # Apple
158
+ # http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
159
+
160
+ # Facebook (and opengraph)
161
+ # http://developers.facebook.com/docs/opengraph#types
162
+
163
+ # http://wiki.developers.facebook.com/index.php/Facebook_Share/Specifying_Meta_Tags
164
+ def snapshot_tag(href)
165
+ tag(:link, :rel => "image_src", :href => href)
166
+ end
167
+
168
+ # http://wiki.developers.facebook.com/index.php/Facebook_Share/Specifying_Meta_Tags
169
+ def medium(type)
170
+ tag(:meta, :name => :medium, :content => type)
171
+ end
172
+
173
+ def classification(type)
174
+ tag(:meta, :name => "og:type", :content => type)
175
+ end
176
+
177
+ def content_type_tag(type = "text/html", charset = "UTF-8")
178
+ meta_tag("Content-Type", "#{type}; charset=#{charset}")
179
+ end
180
+
181
+ def search_link_tag(href, title)
182
+ link_tag({:rel => "search", :type => "application/opensearchdescription+xml", :href => href, :title => title})
183
+ end
184
+
185
+ def favicon_link_tag(favicon = "/favicon.ico")
186
+ link_tag({:rel => "shortcut icon", :href => favicon, :type => "image/x-icon"})
187
+ end
188
+
189
+ def link_tag(options = {})
190
+ tag(:link, options)
191
+ end
192
+
193
+ private
194
+
195
+ def normalize_title(title)
196
+ if title.is_a? String
197
+ title = [title]
198
+ end
199
+ title.map { |t| h(strip_tags(t)) }
200
+ end
201
+
202
+ def normalize_description(description)
203
+ return '' unless description
204
+ truncate(strip_tags(description).gsub(/\s+/, ' '), :length => 200)
205
+ end
206
+
207
+ def normalize_keywords(keywords)
208
+ return '' unless keywords
209
+ keywords = keywords.flatten.join(', ') if keywords.is_a?(Array)
210
+ strip_tags(keywords).mb_chars.downcase
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,67 @@
1
+ module Represent
2
+ module NavigationHelper
3
+
4
+ def menu_for(item, options = {}, &block)
5
+ if item.respond_to?(:children) && !item.children.blank?
6
+ menu_tag(item.children, options, &block)
7
+ else
8
+ menu_tag(item, options, &block)
9
+ end
10
+ end
11
+
12
+ # - menu_tag(c(:menu)) do |attributes, node|
13
+ # - attributes[:class] = "one two"
14
+ # - node[:title]
15
+ def menu_tag(array, options = {}, &block)
16
+ return "" if array.empty?
17
+ menu_attributes = nil
18
+ if options.has_key?(:menu_attributes)
19
+ menu_attributes = options[:menu_attributes]
20
+ options.delete(:menu_attributes)
21
+ end
22
+ haml_tag :ul, menu_attributes do
23
+ array.each_with_index do |node, i|
24
+ attributes = options.has_key?(:li_attributes) ? options[:li_attributes] : {}
25
+ attributes[:class] ||= ""
26
+ if i == 0 and options.has_key?(:first)
27
+ attributes[:class] << " #{options[:first]}"
28
+ elsif i == array.length - 1 and options.has_key?(:last)
29
+ attributes[:class] << " #{options[:last]}"
30
+ end
31
+ haml_tag :li, attributes do
32
+ if block_given?
33
+ yield node
34
+ else
35
+ haml_concat node.title
36
+ end
37
+ next unless (node.respond_to?(:children))
38
+ menu_tag(node.children, options, &block)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def breadcrumb_for(item, options = {}, &block)
45
+ options[:from] ||= "/" + item.url.gsub(/^\//, "").split("/").first
46
+ options[:to] ||= item.url
47
+ breadcrumb(options[:from], options, &block)
48
+ end
49
+
50
+ def breadcrumb(current_url, options, &block)
51
+ item = site.find_by_url(current_url)
52
+ return "" unless item
53
+ haml_tag :a, options.merge(:href => current_url) do
54
+ if block_given?
55
+ yield item
56
+ else
57
+ haml_concat item.title
58
+ end
59
+ end
60
+ if options[:to] != current_url
61
+ haml_concat options[:delimiter] || " » "
62
+ next_node = options[:to].gsub(/#{current_url}\/?/, "").split("/").first
63
+ breadcrumb("#{current_url}/#{next_node}", options, &block)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,61 @@
1
+ module Represent
2
+ module SystemHelper
3
+ # check the current browser (via user agent) for the following:
4
+ # :mozilla / :firefox
5
+ # :ie6
6
+ # :ie7
7
+ # :ie
8
+ # :iphone
9
+ # :safari
10
+ def browser_is? name
11
+ name = name.to_s.strip
12
+
13
+ return true if browser_name == name
14
+ return true if (name == 'mozilla' or name == "firefox") && browser_name == 'gecko'
15
+ return true if name == 'ie6' && browser_name.index('ie6')
16
+ return true if name == 'ie7' && browser_name.index('ie7')
17
+ return true if name == 'ie' && browser_name.index('ie')
18
+ return true if name == 'iphone' && browser_name == 'iphone'
19
+ return true if name == 'webkit' && browser_name == 'safari'
20
+ end
21
+
22
+ # find the current browser name
23
+ def browser_name
24
+ @browser_name ||= begin
25
+ ua = request.user_agent.to_s.downcase
26
+ if ua.index('msie') && !ua.index('opera') && !ua.index('webtv')
27
+ 'ie'+ua[ua.index('msie')+5].chr
28
+ elsif ua.index('gecko/')
29
+ 'gecko'
30
+ elsif ua.index('opera')
31
+ 'opera'
32
+ elsif ua.index('konqueror')
33
+ 'konqueror'
34
+ elsif ua.index('iphone')
35
+ 'iphone'
36
+ elsif ua.index('applewebkit/')
37
+ 'safari'
38
+ elsif ua.index('mozilla/')
39
+ 'gecko'
40
+ else
41
+ ""
42
+ end
43
+ end
44
+ end
45
+
46
+ def windows?
47
+ # Can't match for just 'win' cause it will match darwin as well.
48
+ (/win32|mswin|mingw/).match(RUBY_PLATFORM) ? true : false
49
+ end
50
+
51
+ # Works on Debian and Ubuntu, don't have anything else to test on.
52
+ def linux?
53
+ (/linux/).match(RUBY_PLATFORM) ? true : false
54
+ end
55
+
56
+ # Works on my MacBook Pro, don't have anything else to test on,
57
+ def mac?
58
+ (/darwin/).match(RUBY_PLATFORM) ? true : false
59
+ end
60
+ end
61
+ end
data/lib/represent.rb ADDED
@@ -0,0 +1,22 @@
1
+
2
+ # This takes care of the rest of functionality you need
3
+ # for an SEO and easy to build page.
4
+ # It includes: metadata helpers, grid helpers (e.g. for photo gallerys),
5
+ # navigation helpers (menus and breadcrumbs),
6
+ # better render method so you can pass a block to partials
7
+ # http://github.com/rpheath/navigation_helper.git
8
+ # http://github.com/justinfrench/lovely-layouts.git
9
+ # http://github.com/ianwhite/truncate_html
10
+ # http://github.com/dekart/breadcrumbs.git
11
+ # http://github.com/html/once/blob/master/lib/once.rb
12
+ # http://github.com/fnando/breadcrumbs.git
13
+ # http://github.com/semanticart/smart-meta
14
+
15
+ Dir["acts-as-webpage/*"] {|file| require file}
16
+
17
+ Represent.send(:include, Represent::HeadHelper)
18
+ Represent.send(:include, Represent::BodyHelper)
19
+ Represent.send(:include, Represent::NavigationHelper)
20
+
21
+ ActionView::Base.send(:include, Represent) if defined?(ActionView)
22
+ ActionController::Base.helper(Represent) if defined?(ActionController)
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'represent'
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: represent
3
+ version: !ruby/object:Gem::Version
4
+ hash: 65
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ - 5
11
+ version: 0.0.1.5
12
+ platform: ruby
13
+ authors:
14
+ - Lance Pollard
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-06-19 00:00:00 -07:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: DRY, SEO-friendly Rails Views
24
+ email: lancejpollard@gmail.com
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - README.markdown
33
+ - Rakefile
34
+ - init.rb
35
+ - MIT-LICENSE
36
+ - lib/represent/adapter.rb
37
+ - lib/represent/body_helper.rb
38
+ - lib/represent/grid_helper.rb
39
+ - lib/represent/head_helper.rb
40
+ - lib/represent/navigation_helper.rb
41
+ - lib/represent/system_helper.rb
42
+ - lib/represent.rb
43
+ - rails/init.rb
44
+ has_rdoc: true
45
+ homepage: http://github.com/viatropos/represent
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ requirements: []
72
+
73
+ rubyforge_project: represent
74
+ rubygems_version: 1.3.7
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: "Represent: DRY, SEO-friendly Rails Views"
78
+ test_files: []
79
+