storefront 0.3.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. data/Rakefile +4 -4
  2. data/lib/storefront.rb +22 -35
  3. data/lib/storefront/components/base.rb +99 -0
  4. data/lib/storefront/components/breadcrumb.rb +7 -0
  5. data/lib/storefront/components/button.rb +37 -0
  6. data/lib/storefront/components/definition_list.rb +34 -0
  7. data/lib/storefront/components/definition_list_item.rb +63 -0
  8. data/lib/storefront/components/flash.rb +12 -0
  9. data/lib/storefront/components/footer.rb +19 -0
  10. data/lib/storefront/components/form.rb +82 -0
  11. data/lib/storefront/{form → components/form}/base.rb +3 -3
  12. data/lib/storefront/{form → components/form}/builder.rb +3 -3
  13. data/lib/storefront/{form → components/form}/errors.rb +1 -3
  14. data/lib/storefront/{form → components/form}/field.rb +1 -1
  15. data/lib/storefront/{form → components/form}/fieldset.rb +0 -0
  16. data/lib/storefront/{form → components/form}/hint.rb +0 -0
  17. data/lib/storefront/{form → components/form}/input.rb +7 -5
  18. data/lib/storefront/components/form/inputs.rb +7 -0
  19. data/lib/storefront/{form → components/form}/inputs/checkbox.rb +0 -0
  20. data/lib/storefront/{form → components/form}/inputs/date.rb +0 -0
  21. data/lib/storefront/{form → components/form}/inputs/file.rb +0 -0
  22. data/lib/storefront/{form → components/form}/inputs/hidden.rb +0 -0
  23. data/lib/storefront/{form → components/form}/inputs/radio.rb +0 -0
  24. data/lib/storefront/{form → components/form}/inputs/range.rb +0 -0
  25. data/lib/storefront/{form → components/form}/inputs/select.rb +6 -6
  26. data/lib/storefront/{form → components/form}/inputs/string.rb +0 -0
  27. data/lib/storefront/{form → components/form}/inputs/submit.rb +0 -0
  28. data/lib/storefront/{form → components/form}/inputs/textarea.rb +0 -0
  29. data/lib/storefront/{form → components/form}/inputs/value.rb +0 -0
  30. data/lib/storefront/{form → components/form}/label.rb +1 -1
  31. data/lib/storefront/components/header.rb +73 -0
  32. data/lib/storefront/components/image.rb +12 -0
  33. data/lib/storefront/components/javascript_template.rb +21 -0
  34. data/lib/storefront/components/list.rb +27 -0
  35. data/lib/storefront/components/menu.rb +41 -0
  36. data/lib/storefront/components/nav.rb +78 -0
  37. data/lib/storefront/components/sidebar.rb +23 -0
  38. data/lib/storefront/components/table.rb +232 -0
  39. data/lib/storefront/components/text.rb +29 -0
  40. data/lib/storefront/configuration.rb +53 -5
  41. data/lib/storefront/helpers/cache_helper.rb +37 -19
  42. data/lib/storefront/helpers/component_helper.rb +80 -41
  43. data/lib/storefront/helpers/content_helper.rb +211 -0
  44. data/lib/storefront/helpers/dom_helper.rb +136 -0
  45. data/lib/storefront/helpers/head_helper.rb +277 -205
  46. data/lib/storefront/helpers/model_helper.rb +21 -0
  47. data/lib/storefront/helpers/request_helper.rb +301 -53
  48. data/lib/storefront/helpers/tag_helper.rb +29 -0
  49. data/lib/storefront/{proxies/attribute_proxy.rb → models/attribute.rb} +1 -1
  50. data/lib/storefront/{proxies/model_proxy.rb → models/model.rb} +4 -6
  51. data/lib/storefront/railtie.rb +3 -16
  52. metadata +48 -64
  53. data/lib/storefront/dashboard.rb +0 -185
  54. data/lib/storefront/form.rb +0 -82
  55. data/lib/storefront/helpers/attribute_helper.rb +0 -81
  56. data/lib/storefront/helpers/body_helper.rb +0 -18
  57. data/lib/storefront/helpers/browser_helper.rb +0 -54
  58. data/lib/storefront/helpers/collection_helper.rb +0 -14
  59. data/lib/storefront/helpers/dashboard_helper.rb +0 -29
  60. data/lib/storefront/helpers/debug_helper.rb +0 -11
  61. data/lib/storefront/helpers/definition_list_helper.rb +0 -110
  62. data/lib/storefront/helpers/error_helper.rb +0 -11
  63. data/lib/storefront/helpers/flash_helper.rb +0 -14
  64. data/lib/storefront/helpers/form_helper.rb +0 -13
  65. data/lib/storefront/helpers/format_helper.rb +0 -59
  66. data/lib/storefront/helpers/image_helper.rb +0 -30
  67. data/lib/storefront/helpers/list_helper.rb +0 -135
  68. data/lib/storefront/helpers/locale_helper.rb +0 -245
  69. data/lib/storefront/helpers/open_graph_helper.rb +0 -5
  70. data/lib/storefront/helpers/page_helper.rb +0 -91
  71. data/lib/storefront/helpers/presenter_helper.rb +0 -5
  72. data/lib/storefront/helpers/semantic/location_helper.rb +0 -18
  73. data/lib/storefront/helpers/semantic/time_helper.rb +0 -14
  74. data/lib/storefront/helpers/sidebar_helper.rb +0 -27
  75. data/lib/storefront/helpers/system_helper.rb +0 -18
  76. data/lib/storefront/helpers/table_helper.rb +0 -38
  77. data/lib/storefront/helpers/template_helper.rb +0 -11
  78. data/lib/storefront/helpers/time_helper.rb +0 -21
  79. data/lib/storefront/helpers/url_helper.rb +0 -32
  80. data/lib/storefront/helpers/user_helper.rb +0 -15
  81. data/lib/storefront/helpers/widget_helper.rb +0 -142
  82. data/lib/storefront/helpers/workflow_helper.rb +0 -50
  83. data/lib/storefront/model_helper.rb +0 -17
  84. data/lib/storefront/table.rb +0 -198
  85. data/rails/init.rb +0 -1
  86. data/test/form_helper_test.rb +0 -5
  87. data/test/support/mock_controller.rb +0 -15
  88. data/test/support/mock_response.rb +0 -14
  89. data/test/support/models.rb +0 -0
  90. data/test/test_helper.rb +0 -34
@@ -0,0 +1,211 @@
1
+ module Storefront
2
+ module Helpers
3
+ module ContentHelper
4
+ SCOPES_WITH_NAMESPACE_AND_NESTED_MODEL = [
5
+ '%{namespace}.%{model}.%{nested_model}.%{action}.%{attribute}',
6
+ '%{model}.%{nested_model}.%{action}.%{attribute}',
7
+ '%{namespace}.%{model}.%{action}.%{attribute}',
8
+ '%{model}.%{action}.%{attribute}',
9
+ '%{namespace}.%{model}.%{nested_model}.%{attribute}',
10
+ '%{model}.%{nested_model}.%{attribute}',
11
+ '%{namespace}.%{model}.%{attribute}',
12
+ '%{model}.%{attribute}',
13
+ '%{namespace}.%{nested_model}.%{attribute}',
14
+ '%{nested_model}.%{attribute}',
15
+ '%{namespace}.%{attribute}',
16
+ '%{attribute}'
17
+ ]
18
+
19
+ SCOPES_WITH_NESTED_MODEL = [
20
+ '%{model}.%{nested_model}.%{action}.%{attribute}',
21
+ '%{model}.%{action}.%{attribute}',
22
+ '%{model}.%{nested_model}.%{attribute}',
23
+ '%{model}.%{attribute}',
24
+ '%{nested_model}.%{attribute}',
25
+ '%{attribute}'
26
+ ]
27
+
28
+ SCOPES_WITH_NAMESPACE = [
29
+ '%{namespace}.%{model}.%{action}.%{attribute}',
30
+ '%{namespace}.%{model}.%{attribute}',
31
+ '%{model}.%{action}.%{attribute}',
32
+ '%{model}.%{attribute}',
33
+ '%{namespace}.%{attribute}',
34
+ '%{attribute}'
35
+ ]
36
+
37
+ SCOPES = [
38
+ '%{model}.%{action}.%{attribute}',
39
+ '%{model}.%{attribute}',
40
+ '%{attribute}'
41
+ ]
42
+
43
+ # t?(:"what.summary", :scope => :"reports.titles", :model => deal)
44
+ def t?(key, options = {})
45
+ return key if key.is_a?(::String) || key.blank?
46
+
47
+ models = Storefront::Model.model_names(options[:model] || options[:models] || options[:model_names] || storefront_config.current_scope[:resource] || [])
48
+ models << "" if models.blank?
49
+ namespaces = Array(options[:namespaces] || options[:namespace] || storefront_config.current_scope[:namespace])
50
+ namespaces << "" if namespaces.blank? && !!storefront_config.localize_with_namespace
51
+ action_name = options[:action] || storefront_config.current_scope[:action]
52
+ defaults = []
53
+ allow_blank = options[:allow_blank] == true
54
+ count = options[:count]
55
+ # none, one, many, other
56
+ count_key = count != 1 ? :other : :one
57
+
58
+ keys = [key.to_s]
59
+
60
+ if options.has_key?(:present) || options.has_key?(:past) || options.has_key?(:future)
61
+ if options[:future] == true
62
+ tense_key = :future
63
+ else
64
+ tense_key = (options[:present] == true || options[:past] == false) ? :present : :past
65
+ end
66
+ else
67
+ tense_key = nil
68
+ end
69
+
70
+ if options.has_key?(:nested_model)
71
+ with_nested_model = !!options[:nested_model]
72
+ else
73
+ with_nested_model = !!storefront_config.localize_with_nested_model
74
+ end
75
+
76
+ if options.has_key?(:namespace)
77
+ with_namespace = !!options[:namespace]
78
+ else
79
+ with_namespace = !!storefront_config.localize_with_namespace
80
+ end
81
+
82
+ if with_nested_model && with_namespace
83
+ # TODO, need to performance test before we do this many operations
84
+ SCOPES_WITH_NAMESPACE_AND_NESTED_MODEL
85
+ elsif with_nested_model
86
+ # TODO
87
+ SCOPES_WITH_NESTED_MODEL
88
+ elsif with_namespace
89
+ namespaces.each do |namespace|
90
+ keys.each do |_key|
91
+ SCOPES_WITH_NAMESPACE.each do |_path|
92
+ models.each do |model|
93
+ path = _path.dup
94
+ path.gsub!('%{namespace}', namespace)
95
+ path.gsub!('%{model}', model)
96
+ path.gsub!('%{action}', action_name)
97
+ path.gsub!('%{attribute}', _key)
98
+ path.gsub!('..', '.')
99
+ defaults << path
100
+ end
101
+ end
102
+ end
103
+ end
104
+ else
105
+ keys.each do |_key|
106
+ SCOPES.each do |_path|
107
+ models.each do |model|
108
+ path = _path.dup
109
+ path.gsub!('%{model}', model)
110
+ path.gsub!('%{action}', action_name)
111
+ path.gsub!('%{attribute}', _key)
112
+ path.gsub!('..', '.')
113
+ defaults << path
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ # RESERVED KEYS
120
+ [:past, :present, :future, :allow_blank, :model, :models, :model_names, :action, :nested_model, :namespace, :namespaces].each do |key|
121
+ options.delete(key)
122
+ end
123
+
124
+ defaults.map!(&:to_sym)
125
+ defaults << ''
126
+
127
+ value = I18n.t(defaults.shift, options.merge(:default => defaults))
128
+
129
+ if value.is_a?(::Hash)
130
+ if value.has_key?(count_key)
131
+ value = value[count_key]
132
+ elsif value.has_key?(tense_key)
133
+ value = value[tense_key]
134
+ if value.is_a?(::Hash) && value.has_key?(count_key)
135
+ value = value[count_key]
136
+ end
137
+ elsif value.has_key?(count_key)
138
+ value = value[count_key]
139
+ end
140
+ end
141
+
142
+ if value.is_a?(::Hash)
143
+ if value.has_key?(:one)
144
+ value = value[:one]
145
+ end
146
+ end
147
+
148
+ if value.is_a?(::Hash)
149
+ if value.has_key?(:present)
150
+ value = value[:present]
151
+ elsif value.has_key?(:past)
152
+ value = value[:past]
153
+ elsif value.has_key?(:future)
154
+ value = value[:future]
155
+ end
156
+ end
157
+
158
+ # MORE RESERVED KEYS
159
+ [:scope].each do |key|
160
+ options.delete(key)
161
+ end
162
+
163
+ if value.blank? && !allow_blank
164
+ key.to_s.split(".").last.titleize
165
+ elsif options.present?
166
+ I18n.interpolate(value, options)
167
+ else
168
+ value
169
+ end
170
+ end
171
+
172
+ def rendered_text(string)
173
+ string.to_s.
174
+ gsub(/<\/?[^>]*>/, '').
175
+ gsub(/\n/, " ").
176
+ gsub("\r", " ").
177
+ squeeze(" ").
178
+ gsub(/\"/, "&Prime;"). # convert quotes to inches
179
+ gsub(/\'/, "&prime;"). # single quote to feet
180
+ gsub(/\$0?0*\.(\d+)/, "\\1&cent;").html_safe
181
+ end
182
+
183
+ def sanitize(text)
184
+ text.gsub(/<\/?[^>]*>/, '').gsub(/\n/, " ").gsub("\r", " ").squeeze(" ")
185
+ end
186
+
187
+ def read_binary_file(path)
188
+ File.open(path, 'rb') {|f| f.read }
189
+ end
190
+
191
+ def encoded_contents(path)
192
+ Base64.encode64(read_binary_file(path)).gsub(/\n/, '')
193
+ end
194
+
195
+ def font_face_data_uri(path)
196
+ "url(\"data:font/truetype;base64,#{encoded_contents(path)}\")"
197
+ end
198
+
199
+ # http://snippets.dzone.com/posts/show/805
200
+ def read_image_size(path)
201
+ width, height = IO.read("#{Rails.root}/public/images/#{path}")[0x10..0x18].unpack('NN')
202
+ {:width => width, :height => height}
203
+ end
204
+
205
+ def html5_time(date_or_time)
206
+ return nil if date_or_time.blank?
207
+ date_or_time.acts_like?(:time) ? date_or_time.xmlschema : date_or_time.rfc3339
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,136 @@
1
+ module Storefront
2
+ module Helpers
3
+ # HTML Element Attribute Helper
4
+ module DomHelper
5
+ def clone_attributes(hash)
6
+ result = {}
7
+ return result if hash.blank?
8
+ hash.each do |key, value|
9
+ result[key] = value.is_a?(::Hash) ? clone_attributes(value) : value
10
+ end
11
+ result
12
+ end
13
+
14
+ def merge_class!(attributes, *values)
15
+ return {} if attributes.nil?
16
+ hash = merge_class(attributes, *values)
17
+ attributes[:class] = hash[:class] if hash
18
+ attributes
19
+ end
20
+
21
+ def merge_class(attributes, *values)
22
+ if values.present?
23
+ if attributes[:class].present?
24
+ classes = attributes[:class].split(/\s+/)
25
+ else
26
+ classes = []
27
+ end
28
+ classes += values.compact.map(&:to_s)
29
+ classes.uniq!
30
+ else
31
+ classes = nil
32
+ end
33
+
34
+ if classes.present?
35
+ attributes.merge(:class => classes.join(" "))
36
+ else
37
+ attributes
38
+ end
39
+ end
40
+
41
+ def index_class(index, array_or_length)
42
+ length = array_or_length.is_a?(::Array) ? array_or_length.length : array_or_length
43
+ return nil if length.blank? || (length <= 1)
44
+
45
+ if index == 0
46
+ "first"
47
+ elsif index == length - 1
48
+ "last"
49
+ else
50
+ nil
51
+ end
52
+ end
53
+
54
+ # @example Aria role main.
55
+ #
56
+ # aria(:main) #=> {:role => :main}
57
+ def aria(key)
58
+ {:role => key}
59
+ end
60
+
61
+ # @example Customize <tt><body></tt> tag attributes from inside a partial
62
+ #
63
+ # # app/views/posts/_post.haml
64
+ # - dom :body => {:class => "admin", :id => "admin"}
65
+ #
66
+ # # app/views/layouts/application.haml
67
+ # %body{dom[:body]}
68
+ def dom(attributes = {})
69
+ @dom ||= {}
70
+ @dom.deep_merge!(attributes)
71
+ @dom
72
+ end
73
+
74
+ # calls <tt>model.to_title</tt>
75
+ def page(*args)
76
+ options = args.extract_options!
77
+ title = args.shift
78
+ options[:action] ||= storefront_config.current_scope[:action]
79
+
80
+ title = case title
81
+ when ::String
82
+ title
83
+ when ::Symbol
84
+ t?(title, :scope => :"pages.titles")
85
+ else
86
+ if options[:title].present?
87
+ options[:title]
88
+ else
89
+ parent_name = !!options[:parent] ? resource_to_title(storefront_config.current_scope[:parent], options) : nil
90
+ resource_name = resource_to_title(storefront_config.current_scope[:resource], options)
91
+ [parent_name, resource_name].compact.join(storefront_config.breadcrumb)
92
+ end
93
+ end
94
+
95
+ self.title(options[:browser] || title, options)
96
+
97
+ options = header_widget_options(options.merge(:title => title))
98
+
99
+ options[:header_html].reverse_merge!(:id => storefront_config.page_header_id) if storefront_config.page_header_id.present?
100
+ options[:title_html].reverse_merge!(:id => storefront_config.page_title_id) if storefront_config.page_title_id.present?
101
+ options[:subtitle_html].reverse_merge!(:id => storefront_config.page_subtitle_id) if storefront_config.page_subtitle_id.present?
102
+ options[:level] = 1
103
+ options[:skip_format] = true
104
+
105
+ header_widget options.merge(:title => title)
106
+ end
107
+
108
+ def title_widget(*args, &block)
109
+ options = args.extract_options!
110
+ options[:header_html] ||= {}
111
+ merge_class! options[:header_html], *widget_classes("title-widget")
112
+ header_widget(options, &block)
113
+ end
114
+
115
+ def title_widget_options
116
+
117
+ end
118
+
119
+ def resource_to_title(resource, options = {})
120
+ if resource.present?
121
+
122
+ # handle subdomains as well
123
+ t?(options[:action].to_sym,
124
+ :scope => :"pages.titles",
125
+ :model => Storefront::ModelProxy.model_names(resource),
126
+ :namespaces => storefront_config.current_scope[:namespace],
127
+ :allow_blank => true,
128
+ :action => "",
129
+ :name => resource.is_a?(::Class) ? resource.name.titleize.pluralize : resource.to_title,
130
+ :clazz => resource.is_a?(::Class) ? resource.name.titleize : resource.class.name
131
+ )
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -1,229 +1,301 @@
1
1
  module Storefront
2
- module HeadHelper
3
- def meta_for(post)
4
- result = ""
5
- unless post.title.blank?
6
- result << title(post.title)
7
- result << "\n"
8
- end
9
- unless post.tags.blank?
10
- result << keywords(post.tags.join(", "))
11
- result << "\n"
12
- end
13
- unless post.description.blank?
14
- result << description(post.description)
15
- result << "\n"
16
- end
17
- result
18
- end
19
-
20
- def meta(options = {})
21
- title(options[:title]) if options.has_key?(:title)
22
- description(options[:description]) if options.has_key?(:description)
23
- keywords(options[:keywords]) if options.has_key?(:keywords)
24
- copyright(options[:copyright]) if options.has_key?(:copyright)
25
- end
26
-
27
- def meta_tags(*args)
28
- options = args.extract_options!
29
- site = options[:site] || args.first
30
- result = title_tag(site, options[:title])
31
- result << "\n"
32
- result << content_type_tag
33
- result << "\n"
34
- result << description_tag(options[:description])
35
- result << "\n"
36
- result << keywords_tag(options[:keywords])
37
- result << "\n"
38
- result << copyright_tag(options[:copyright])
39
- result
40
- end
41
-
42
- # country
43
- # classification
44
- # author
45
- # apple-mobile-web-app-capable
46
- # apple-touch-fullscreen
47
- # google-analytics
48
- # Revisit-After
49
- # category
50
- def meta_tag(name, content = '')
51
- tag(:meta, :name => name, :content => content)
52
- end
53
-
54
- def title(string)
55
- @content_for_title = string
56
- end
57
-
58
- def title_tag(*args)
59
- options = args.extract_options!
60
-
61
- site = options[:site] || args.first
62
- # Prefix (leading space)
63
- if options[:prefix]
64
- prefix = options[:prefix]
65
- elsif options[:prefix] === false
66
- prefix = ''
67
- else
68
- prefix = ' '
2
+ module Helpers
3
+ module HeadHelper
4
+ def meta_tags(*args)
5
+ options = args.extract_options!
6
+ options[:site] ||= args.shift
7
+ result = []
8
+ storefront_config.meta_tags.each do |meta_tag_name|
9
+ if options[meta_tag_name].present?
10
+ result << meta_tag(meta_tag_name, options[meta_tag_name])
11
+ end
12
+ end
13
+ result.join("\n")
69
14
  end
70
-
71
- # Separator
72
- unless options[:separator].blank?
73
- separator = options[:separator]
74
- else
75
- separator = '|'
15
+ alias_method :meta, :meta_tags
16
+
17
+ def meta_tag(name, content = '')
18
+ capture_haml { haml_tag :meta, :name => name, :content => content }
76
19
  end
77
-
78
- # Suffix (trailing space)
79
- if options[:suffix]
80
- suffix = options[:suffix]
81
- elsif options[:suffix] === false
82
- suffix = ''
83
- else
84
- suffix = ' '
20
+
21
+ def title(*args)
22
+ @content_for_title = *args
85
23
  end
86
-
87
- # Title
88
- title = @content_for_title
89
- if options[:lowercase] === true
90
- title = title.downcase unless title.blank?
24
+
25
+ def title_tag(*args)
26
+ options = args.extract_options!
27
+ # Title
28
+ title = @content_for_title
29
+
30
+ if title.present?
31
+ options.merge!(title.extract_options!)
32
+ title = @content_for_title.shift || options[:title]
33
+ end
34
+
35
+ if options[:lowercase] === true
36
+ title = title.downcase unless title.blank?
37
+ end
38
+
39
+ site = options.has_key?(:site) ? options[:site] : args.first
40
+
41
+ # Prefix (leading space)
42
+ if options[:prefix]
43
+ prefix = options[:prefix]
44
+ elsif options[:prefix] === false
45
+ prefix = ''
46
+ else
47
+ prefix = ' '
48
+ end
49
+
50
+ # Separator
51
+ unless options[:separator].blank?
52
+ separator = options[:separator]
53
+ else
54
+ separator = '|'
55
+ end
56
+
57
+ # Suffix (trailing space)
58
+ if options[:suffix]
59
+ suffix = options[:suffix]
60
+ elsif options[:suffix] === false
61
+ suffix = ''
62
+ else
63
+ suffix = ' '
64
+ end
65
+
66
+ # title
67
+ if title.blank?
68
+ result = content_tag :title, site
69
+ else
70
+ title = normalize_title(title)
71
+ title = [site] + title if site
72
+ title.reverse! unless options[:reverse] === false
73
+ sep = prefix + separator + suffix
74
+ result = content_tag(:title, title.join(sep))
75
+ end
76
+ result
77
+ end
78
+
79
+ def description(string)
80
+ @content_for_description = string
81
+ end
82
+
83
+ def description_tag(default='')
84
+ content = normalize_description(@content_for_description || default)
85
+ meta_tag(:description, content) unless content.blank?
91
86
  end
92
-
93
- # title
94
- if title.blank?
95
- result = content_tag :title, site
96
- else
97
- title = normalize_title(title)
98
- title = [site] + title
99
- title.reverse! unless options[:reverse] === false
100
- sep = prefix + separator + suffix
101
- result = content_tag(:title, title.join(sep))
102
- end
103
- result
104
- end
105
-
106
- def description(string)
107
- @content_for_description = string
108
- end
109
-
110
- def description_tag(default='')
111
- content = normalize_description(@content_for_description || default)
112
- tag(:meta, :name => :description, :content => content) unless content.blank?
113
- end
114
87
 
115
- def keywords(string)
116
- @content_for_keywords = string
117
- end
88
+ def keywords(string)
89
+ @content_for_keywords = string
90
+ end
118
91
 
119
- def keywords_tag(default = '')
120
- content = normalize_keywords(@content_for_keywords || default)
121
- tag(:meta, :name => :keywords, :content => content) unless content.blank?
122
- end
92
+ def keywords_tag(default = '')
93
+ content = normalize_keywords(@content_for_keywords || default)
94
+ meta_tag(:keywords, content) unless content.blank?
95
+ end
123
96
 
124
- def copyright(string)
125
- @content_for_copyright = string
126
- end
97
+ def copyright(string)
98
+ @content_for_copyright = string
99
+ end
127
100
 
128
- def copyright_tag(default='')
129
- content = @content_for_copyright || default
130
- tag(:meta, :name => :copyright, :content => content) unless content.blank?
131
- end
101
+ def copyright_tag(default='')
102
+ content = @content_for_copyright || default
103
+ meta_tag(:copyright, content) unless content.blank?
104
+ end
132
105
 
133
- def robots(*args)
134
- content_for(:robots, args.join(", "))
135
- end
106
+ def robots(*args)
107
+ content_for(:robots, args.join(", "))
108
+ end
136
109
 
137
- def robots_tag(*args)
138
- options = args.extract_options!
110
+ def robots_tag(*args)
111
+ options = args.extract_options!
139
112
 
140
- noindex_name = tags[:noindex].is_a?(String) ? tags[:noindex] : 'robots'
141
- nofollow_name = tags[:nofollow].is_a?(String) ? tags[:nofollow] : 'robots'
142
-
143
- if noindex_name == nofollow_name
144
- content = [(tags[:noindex] ? 'noindex' : nil), (tags[:nofollow] ? 'nofollow' : nil)].compact.join(', ')
145
- unless content.blank?
146
- result << "\n"
147
- result << tag(:meta, :name => noindex_name, :content => content)
148
- end
149
- else
150
- if tags[:noindex]
151
- result << "\n"
152
- result << tag(:meta, :name => noindex_name, :content => 'noindex')
153
- end
154
- if tags[:nofollow]
155
- result << "\n"
156
- result << tag(:meta, :name => nofollow_name, :content => 'nofollow')
113
+ noindex_name = tags[:noindex].is_a?(String) ? tags[:noindex] : 'robots'
114
+ nofollow_name = tags[:nofollow].is_a?(String) ? tags[:nofollow] : 'robots'
115
+
116
+ if noindex_name == nofollow_name
117
+ content = [(tags[:noindex] ? 'noindex' : nil), (tags[:nofollow] ? 'nofollow' : nil)].compact.join(', ')
118
+ unless content.blank?
119
+ result << "\n"
120
+ result << meta_tag(noindex_name, content)
121
+ end
122
+ else
123
+ if tags[:noindex]
124
+ result << "\n"
125
+ result << meta_tag(noindex_name, "noindex")
126
+ end
127
+ if tags[:nofollow]
128
+ result << "\n"
129
+ result << meta_tag(nofollow_name, "nofollow")
130
+ end
157
131
  end
132
+
133
+ return result
158
134
  end
159
- # canonical
160
- unless tags[:canonical].blank?
161
- result << "\n"
162
- result << tag(:link, :rel => :canonical, :href => tags[:canonical])
135
+
136
+ def canonical_link_tag(path)
137
+ link_tag(:rel => :canonical, :href => path)
163
138
  end
164
-
165
- return result
166
- end
167
-
168
- def copyright(from)
169
- now = Time.now.year
170
- now.eql?(from) ? now : "#{from} - #{now}"
171
- end
172
-
173
- # Apple
174
- # http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
175
-
176
- # Facebook (and opengraph)
177
- # http://developers.facebook.com/docs/opengraph#types
178
-
179
- # http://wiki.developers.facebook.com/index.php/Facebook_Share/Specifying_Meta_Tags
180
- def snapshot_tag(href)
181
- tag(:link, :rel => "image_src", :href => href)
182
- end
183
-
184
- # http://wiki.developers.facebook.com/index.php/Facebook_Share/Specifying_Meta_Tags
185
- def medium(type)
186
- tag(:meta, :name => :medium, :content => type)
187
- end
188
-
189
- def classification(type)
190
- tag(:meta, :name => "og:type", :content => type)
191
- end
192
-
193
- def content_type_tag(type = "text/html", charset = "UTF-8")
194
- meta_tag("Content-Type", "#{type}; charset=#{charset}")
195
- end
139
+
140
+ def http_meta_tag(name, content)
141
+ capture_haml { haml_tag :meta, :"http-equiv" => name, :content => content }
142
+ end
143
+
144
+ # @example Redirect to the site home page in 20 seconds.
145
+ #
146
+ # refresh_meta_tag root_url, :in => 20.seconds
147
+ def refresh_meta_tag(path, options = {})
148
+ http_meta_tag("refresh", "#{options[:in].to_i};url=#{path}")
149
+ end
150
+
151
+ def copyright(from)
152
+ now = Time.now.year
153
+ now.eql?(from) ? now : "#{from} - #{now}"
154
+ end
155
+
156
+ # Apple
157
+ # http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
196
158
 
197
- def search_link_tag(href, title)
198
- link_tag({:rel => "search", :type => "application/opensearchdescription+xml", :href => href, :title => title})
199
- end
159
+ # Facebook (and opengraph)
160
+ # http://developers.facebook.com/docs/opengraph#types
200
161
 
201
- def favicon_link_tag(favicon = "/favicon.ico")
202
- link_tag({:rel => "shortcut icon", :href => favicon, :type => "image/x-icon"})
203
- end
162
+ # http://wiki.developers.facebook.com/index.php/Facebook_Share/Specifying_Meta_Tags
163
+ def snapshot_link_tag(href)
164
+ link_tag(:rel => "image_src", :href => href)
165
+ end
204
166
 
205
- def link_tag(options = {})
206
- tag(:link, options)
207
- end
208
-
209
- private
210
-
211
- def normalize_title(title)
212
- if title.is_a? String
213
- title = [title]
167
+ def html4_content_type_tag(charset = "UTF-8", type = "text/html")
168
+ http_meta_tag("Content-Type", "#{type}; charset=#{charset}")
169
+ end
170
+
171
+ def html5_content_type_tag(charset = "UTF-8")
172
+ capture_haml { haml_tag :meta, "charset" => charset }
173
+ end
174
+ alias_method :content_type_tag, :html5_content_type_tag
175
+
176
+ def search_link_tag(href, title)
177
+ link_tag(:rel => "search", :type => "application/opensearchdescription+xml", :href => href, :title => title)
178
+ end
179
+
180
+ def favicon_link_tag(favicon = "/favicon.ico")
181
+ link_tag(:rel => "shortcut icon", :href => favicon, :type => "image/x-icon")
182
+ end
183
+
184
+ def link_tag(options = {})
185
+ capture_haml { haml_tag :link, options }
186
+ end
187
+
188
+ def ie_application_meta_tags(title, options = {})
189
+ result = []
190
+ result << meta_tag("application-name", title)
191
+ result << meta_tag("msapplication-tooltip", options[:tooltip]) if options[:tooltip].present?
192
+ result << meta_tag("msapplication-starturl", options[:url]) if options[:url].present?
193
+ if options[:width].present? && options[:height].present?
194
+ result << meta_tag("msapplication-window", "width=#{options[:width]};height=#{options[:height]}")
214
195
  end
215
- title.map { |t| h(strip_tags(t)) }
196
+ result << meta_tag("msapplication-navbutton-color", options[:color]) if options[:color].present?
197
+ result.join("\n")
216
198
  end
217
-
218
- def normalize_description(description)
219
- return '' unless description
220
- truncate(strip_tags(description).gsub(/\s+/, ' '), :length => 200)
199
+
200
+ def ie_task_meta_tag(name, path, icon = nil)
201
+ content = []
202
+ content << "name=#{name}"
203
+ content << "uri=#{path}"
204
+ content << "icon-uri=#{icon}" if icon
205
+ meta_tag("msapplication-task", content.join(";"))
221
206
  end
222
-
223
- def normalize_keywords(keywords)
224
- return '' unless keywords
225
- keywords = keywords.flatten.join(', ') if keywords.is_a?(Array)
226
- strip_tags(keywords).mb_chars.downcase
207
+
208
+ def apple_meta_tags(options = {})
209
+ result = []
210
+ result << apple_viewport_meta_tag(options)
211
+ result << apple_full_screen_meta_tag(options[:full_screen]) if options.has_key?(:full_screen)
212
+ result << apple_mobile_compatible_meta_tag(options[:mobile]) if options.has_key?(:mobile)
213
+ result.join
214
+ end
215
+
216
+ # http://www.html5rocks.com/en/mobile/mobifying.html
217
+ def apple_viewport_meta_tag(options = {})
218
+ viewport = []
219
+ viewport << "width=#{options[:width]}" if options[:width].present?
220
+ viewport << "height=#{options[:height]}" if options[:height].present?
221
+ viewport << "initial-scale=#{options[:scale] || 1.0}"
222
+ viewport << "minimum-scale=#{options[:min]}" if options[:min].present?
223
+ viewport << "maximum-scale=#{options[:max]}" if options[:max].present?
224
+ viewport << "user-scalable=#{options[:scalable] == true ? "yes" : "no"}" if options.has_key?(:scalable)
225
+
226
+ meta_tag("viewport", viewport.join(", "))
227
+ end
228
+
229
+ def apple_full_screen_meta_tag(value)
230
+ meta_tag("apple-touch-fullscreen", value == true ? "yes" : "no")
231
+ end
232
+
233
+ def apple_mobile_compatible_meta_tag(value)
234
+ meta_tag("apple-mobile-web-app-capable", value == true ? "yes" : "no")
235
+ end
236
+
237
+ def apple_touch_icon_link_tag(path, options = {})
238
+ rel = ["apple-touch-icon"]
239
+ rel << "#{options[:size]}x#{options[:size]}" if options[:size].present?
240
+ rel << "precomposed" if options[:precomposed]
241
+ link_tag(:rel => rel.join("-"), :href => path)
227
242
  end
243
+
244
+ def apple_touch_icon_link_tags(path, *sizes)
245
+ options = sizes.extract_options!
246
+ sizes.map { |size| apple_touch_icon_link_tag(path, options.merge(:size => size)) }.join
247
+ end
248
+
249
+ def open_graph_meta_tags(options = {})
250
+ result = []
251
+
252
+ result << open_graph_meta_tag("og:title", options[:title]) if options[:title]
253
+ result << open_graph_meta_tag("og:type", options[:type]) if options[:type]
254
+ result << open_graph_meta_tag("og:image", options[:image]) if options[:image]
255
+ result << open_graph_meta_tag("og:site_name", options[:site]) if options[:site]
256
+ result << open_graph_meta_tag("og:description", options[:description]) if options[:description]
257
+ result << open_graph_meta_tag("og:email", options[:email]) if options[:email]
258
+ result << open_graph_meta_tag("og:phone_number", options[:phone]) if options[:phone]
259
+ result << open_graph_meta_tag("og:fax_number", options[:fax]) if options[:fax]
260
+ result << open_graph_meta_tag("og:latitude", options[:lat]) if options[:lat]
261
+ result << open_graph_meta_tag("og:longitude", options[:lng]) if options[:lng]
262
+ result << open_graph_meta_tag("og:street-address", options[:street]) if options[:street]
263
+ result << open_graph_meta_tag("og:locality", options[:city]) if options[:city]
264
+ result << open_graph_meta_tag("og:region", options[:state]) if options[:state]
265
+ result << open_graph_meta_tag("og:postal-code", options[:zip]) if options[:zip]
266
+ result << open_graph_meta_tag("og:country-name", options[:country]) if options[:country]
267
+
268
+ result.join("\n")
269
+ end
270
+
271
+ def open_graph_meta_tag(property, content)
272
+ capture_haml { haml_tag :meta, :property => property, :content => content }
273
+ end
274
+
275
+ # first, last, next, prev
276
+ def pagination_meta_tags(options = {})
277
+
278
+ end
279
+
280
+ private
281
+
282
+ def normalize_title(title)
283
+ if title.is_a? String
284
+ title = [title]
285
+ end
286
+ title.map { |t| h(strip_tags(t)) }
287
+ end
288
+
289
+ def normalize_description(description)
290
+ return '' unless description
291
+ truncate(strip_tags(description).gsub(/\s+/, ' '), :length => 200)
292
+ end
293
+
294
+ def normalize_keywords(keywords)
295
+ return '' unless keywords
296
+ keywords = keywords.flatten.join(', ') if keywords.is_a?(Array)
297
+ strip_tags(keywords).mb_chars.downcase
298
+ end
299
+ end
228
300
  end
229
301
  end