locomotivecms_wagon 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data/.gitignore +27 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +68 -0
  6. data/Rakefile +57 -0
  7. data/TODO +57 -0
  8. data/bin/wagon +9 -0
  9. data/generators/blank/Gemfile.tt +20 -0
  10. data/generators/blank/app/content_types/.empty_directory +1 -0
  11. data/generators/blank/app/views/pages/404.liquid +11 -0
  12. data/generators/blank/app/views/pages/index.liquid +19 -0
  13. data/generators/blank/app/views/snippets/.empty_directory +1 -0
  14. data/generators/blank/config/deploy.yml +12 -0
  15. data/generators/blank/config/site.yml.tt +16 -0
  16. data/generators/blank/config/translations.yml +8 -0
  17. data/generators/blank/config.ru +3 -0
  18. data/generators/blank/data/.empty_directory +1 -0
  19. data/generators/blank/public/fonts/.empty_directory +1 -0
  20. data/generators/blank/public/images/.empty_directory +1 -0
  21. data/generators/blank/public/javascripts/.empty_directory +1 -0
  22. data/generators/blank/public/samples/.empty_directory +1 -0
  23. data/generators/blank/public/stylesheets/.empty_directory +1 -0
  24. data/generators/bootstrap/Gemfile.tt +20 -0
  25. data/generators/bootstrap/app/content_types/.empty_directory +1 -0
  26. data/generators/bootstrap/app/views/pages/404.liquid +13 -0
  27. data/generators/bootstrap/app/views/pages/404.liquid.haml +10 -0
  28. data/generators/bootstrap/app/views/pages/index.liquid +89 -0
  29. data/generators/bootstrap/app/views/pages/index.liquid.haml +72 -0
  30. data/generators/bootstrap/app/views/snippets/footer.liquid +3 -0
  31. data/generators/bootstrap/app/views/snippets/footer.liquid.haml +2 -0
  32. data/generators/bootstrap/config/deploy.yml +12 -0
  33. data/generators/bootstrap/config/site.yml.tt +16 -0
  34. data/generators/bootstrap/config/translations.yml +8 -0
  35. data/generators/bootstrap/config.ru +3 -0
  36. data/generators/bootstrap/data/.empty_directory +1 -0
  37. data/generators/bootstrap/public/fonts/FontAwesome.otf +0 -0
  38. data/generators/bootstrap/public/fonts/font-awesome-ie7.min.css +23 -0
  39. data/generators/bootstrap/public/fonts/font-awesome.css +469 -0
  40. data/generators/bootstrap/public/fonts/font-awesome.min.css +34 -0
  41. data/generators/bootstrap/public/fonts/fontawesome-webfont.eot +0 -0
  42. data/generators/bootstrap/public/fonts/fontawesome-webfont.ttf +0 -0
  43. data/generators/bootstrap/public/fonts/fontawesome-webfont.woff +0 -0
  44. data/generators/bootstrap/public/javascripts/bootstrap.js +2159 -0
  45. data/generators/bootstrap/public/javascripts/bootstrap.min.js +6 -0
  46. data/generators/bootstrap/public/samples/.empty_directory +1 -0
  47. data/generators/bootstrap/public/stylesheets/application.css.scss +39 -0
  48. data/generators/bootstrap/public/stylesheets/bootstrap-responsive.css +1092 -0
  49. data/generators/bootstrap/public/stylesheets/bootstrap-responsive.min.css +9 -0
  50. data/generators/bootstrap/public/stylesheets/bootstrap.css +5652 -0
  51. data/generators/bootstrap/public/stylesheets/bootstrap.min.css +726 -0
  52. data/generators/content_type/app/content_types/%name%.yml.tt +58 -0
  53. data/generators/content_type/data/%name%.yml.tt +24 -0
  54. data/generators/foundation/Gemfile.tt +20 -0
  55. data/generators/foundation/app/content_types/.empty_directory +1 -0
  56. data/generators/foundation/app/views/pages/404.liquid +13 -0
  57. data/generators/foundation/app/views/pages/404.liquid.haml +10 -0
  58. data/generators/foundation/app/views/pages/index.liquid +152 -0
  59. data/generators/foundation/app/views/pages/index.liquid.haml +130 -0
  60. data/generators/foundation/app/views/snippets/footer.liquid +16 -0
  61. data/generators/foundation/app/views/snippets/footer.liquid.haml +23 -0
  62. data/generators/foundation/config/deploy.yml +12 -0
  63. data/generators/foundation/config/site.yml.tt +16 -0
  64. data/generators/foundation/config/translations.yml +8 -0
  65. data/generators/foundation/config.ru +3 -0
  66. data/generators/foundation/data/.empty_directory +1 -0
  67. data/generators/foundation/public/fonts/.empty_directory +1 -0
  68. data/generators/foundation/public/javascripts/foundation/foundation.alerts.js +50 -0
  69. data/generators/foundation/public/javascripts/foundation/foundation.clearing.js +480 -0
  70. data/generators/foundation/public/javascripts/foundation/foundation.cookie.js +74 -0
  71. data/generators/foundation/public/javascripts/foundation/foundation.dropdown.js +130 -0
  72. data/generators/foundation/public/javascripts/foundation/foundation.forms.js +395 -0
  73. data/generators/foundation/public/javascripts/foundation/foundation.joyride.js +612 -0
  74. data/generators/foundation/public/javascripts/foundation/foundation.js +372 -0
  75. data/generators/foundation/public/javascripts/foundation/foundation.magellan.js +130 -0
  76. data/generators/foundation/public/javascripts/foundation/foundation.orbit.js +365 -0
  77. data/generators/foundation/public/javascripts/foundation/foundation.placeholder.js +159 -0
  78. data/generators/foundation/public/javascripts/foundation/foundation.reveal.js +270 -0
  79. data/generators/foundation/public/javascripts/foundation/foundation.section.js +272 -0
  80. data/generators/foundation/public/javascripts/foundation/foundation.tooltips.js +195 -0
  81. data/generators/foundation/public/javascripts/foundation/foundation.topbar.js +225 -0
  82. data/generators/foundation/public/javascripts/foundation.min.js +14 -0
  83. data/generators/foundation/public/javascripts/vendor/custom.modernizr.js +4 -0
  84. data/generators/foundation/public/javascripts/vendor/jquery.js +9597 -0
  85. data/generators/foundation/public/javascripts/vendor/zepto.js +1884 -0
  86. data/generators/foundation/public/samples/.empty_directory +1 -0
  87. data/generators/foundation/public/stylesheets/foundation.css +3818 -0
  88. data/generators/foundation/public/stylesheets/foundation.min.css +1 -0
  89. data/generators/foundation/public/stylesheets/normalize.css +396 -0
  90. data/generators/page/template.liquid.haml.tt +35 -0
  91. data/generators/page/template.liquid.tt +1 -0
  92. data/generators/snippet/template.liquid.haml.tt +4 -0
  93. data/generators/snippet/template.liquid.tt +4 -0
  94. data/lib/locomotive/wagon/cli.rb +238 -0
  95. data/lib/locomotive/wagon/exceptions.rb +35 -0
  96. data/lib/locomotive/wagon/generators/content_type.rb +47 -0
  97. data/lib/locomotive/wagon/generators/page.rb +63 -0
  98. data/lib/locomotive/wagon/generators/site/base.rb +30 -0
  99. data/lib/locomotive/wagon/generators/site/blank.rb +23 -0
  100. data/lib/locomotive/wagon/generators/site/bootstrap.rb +35 -0
  101. data/lib/locomotive/wagon/generators/site/foundation.rb +35 -0
  102. data/lib/locomotive/wagon/generators/site/unzip.rb +81 -0
  103. data/lib/locomotive/wagon/generators/site.rb +99 -0
  104. data/lib/locomotive/wagon/generators/snippet.rb +60 -0
  105. data/lib/locomotive/wagon/liquid/drops/base.rb +44 -0
  106. data/lib/locomotive/wagon/liquid/drops/content_entry.rb +48 -0
  107. data/lib/locomotive/wagon/liquid/drops/content_types.rb +121 -0
  108. data/lib/locomotive/wagon/liquid/drops/page.rb +36 -0
  109. data/lib/locomotive/wagon/liquid/drops/site.rb +21 -0
  110. data/lib/locomotive/wagon/liquid/errors.rb +7 -0
  111. data/lib/locomotive/wagon/liquid/filters/date.rb +98 -0
  112. data/lib/locomotive/wagon/liquid/filters/html.rb +154 -0
  113. data/lib/locomotive/wagon/liquid/filters/misc.rb +28 -0
  114. data/lib/locomotive/wagon/liquid/filters/resize.rb +18 -0
  115. data/lib/locomotive/wagon/liquid/filters/text.rb +50 -0
  116. data/lib/locomotive/wagon/liquid/filters/translate.rb +24 -0
  117. data/lib/locomotive/wagon/liquid/patches.rb +47 -0
  118. data/lib/locomotive/wagon/liquid/tags/consume.rb +58 -0
  119. data/lib/locomotive/wagon/liquid/tags/csrf.rb +34 -0
  120. data/lib/locomotive/wagon/liquid/tags/editable/base.rb +46 -0
  121. data/lib/locomotive/wagon/liquid/tags/editable/control.rb +19 -0
  122. data/lib/locomotive/wagon/liquid/tags/editable/file.rb +15 -0
  123. data/lib/locomotive/wagon/liquid/tags/editable/long_text.rb +15 -0
  124. data/lib/locomotive/wagon/liquid/tags/editable/short_text.rb +15 -0
  125. data/lib/locomotive/wagon/liquid/tags/editable.rb +5 -0
  126. data/lib/locomotive/wagon/liquid/tags/extends.rb +25 -0
  127. data/lib/locomotive/wagon/liquid/tags/google_analytics.rb +28 -0
  128. data/lib/locomotive/wagon/liquid/tags/inline_editor.rb +16 -0
  129. data/lib/locomotive/wagon/liquid/tags/locale_switcher.rb +106 -0
  130. data/lib/locomotive/wagon/liquid/tags/nav.rb +167 -0
  131. data/lib/locomotive/wagon/liquid/tags/paginate.rb +105 -0
  132. data/lib/locomotive/wagon/liquid/tags/seo.rb +74 -0
  133. data/lib/locomotive/wagon/liquid/tags/snippet.rb +44 -0
  134. data/lib/locomotive/wagon/liquid/tags/with_scope.rb +43 -0
  135. data/lib/locomotive/wagon/liquid.rb +19 -0
  136. data/lib/locomotive/wagon/listen.rb +57 -0
  137. data/lib/locomotive/wagon/logger.rb +54 -0
  138. data/lib/locomotive/wagon/misc/core_ext.rb +29 -0
  139. data/lib/locomotive/wagon/misc/dragonfly.rb +79 -0
  140. data/lib/locomotive/wagon/misc/httparty.rb +46 -0
  141. data/lib/locomotive/wagon/misc/i18n.rb +2 -0
  142. data/lib/locomotive/wagon/misc/will_paginate.rb +16 -0
  143. data/lib/locomotive/wagon/misc.rb +5 -0
  144. data/lib/locomotive/wagon/server/dynamic_assets.rb +31 -0
  145. data/lib/locomotive/wagon/server/entry_submission.rb +116 -0
  146. data/lib/locomotive/wagon/server/favicon.rb +17 -0
  147. data/lib/locomotive/wagon/server/locale.rb +42 -0
  148. data/lib/locomotive/wagon/server/logging.rb +32 -0
  149. data/lib/locomotive/wagon/server/middleware.rb +59 -0
  150. data/lib/locomotive/wagon/server/not_found.rb +19 -0
  151. data/lib/locomotive/wagon/server/page.rb +61 -0
  152. data/lib/locomotive/wagon/server/path.rb +34 -0
  153. data/lib/locomotive/wagon/server/renderer.rb +105 -0
  154. data/lib/locomotive/wagon/server/templatized_page.rb +32 -0
  155. data/lib/locomotive/wagon/server.rb +81 -0
  156. data/lib/locomotive/wagon/standalone_server.rb +28 -0
  157. data/lib/locomotive/wagon/version.rb +5 -0
  158. data/lib/locomotive/wagon.rb +163 -0
  159. data/locales/de.yml +156 -0
  160. data/locales/en.yml +177 -0
  161. data/locales/es.yml +132 -0
  162. data/locales/et.yml +153 -0
  163. data/locales/fr.yml +146 -0
  164. data/locales/it.yml +154 -0
  165. data/locales/nb.yml +190 -0
  166. data/locales/nl.yml +159 -0
  167. data/locales/pl.yml +202 -0
  168. data/locales/pt-BR.yml +138 -0
  169. data/locales/ru.yml +223 -0
  170. data/locomotivecms_wagon.gemspec +44 -0
  171. data/spec/integration/cassettes/pull.yml +590 -0
  172. data/spec/integration/cassettes/push.yml +810 -0
  173. data/spec/integration/integration_helper.rb +14 -0
  174. data/spec/integration/server_spec.rb +38 -0
  175. data/spec/integration/sites_spec.rb +29 -0
  176. data/spec/spec_helper.rb +12 -0
  177. data/spec/support/helpers.rb +13 -0
  178. metadata +544 -0
@@ -0,0 +1,60 @@
1
+ require 'thor/group'
2
+ require 'active_support'
3
+ require 'active_support/core_ext'
4
+
5
+ module Locomotive
6
+ module Wagon
7
+ module Generators
8
+ class Snippet < Thor::Group
9
+
10
+ include Thor::Actions
11
+
12
+ argument :slug
13
+ argument :target_path # path to the site
14
+ argument :locales
15
+
16
+ attr_accessor :haml
17
+
18
+ def ask_for_haml
19
+ self.haml = yes?('Do you prefer a HAML template ?')
20
+ end
21
+
22
+ def apply_locales?
23
+ self.locales.shift # remove the default locale
24
+
25
+ unless self.locales.empty?
26
+ unless yes?('Do you want to generate files for each locale ?')
27
+ self.locales = []
28
+ end
29
+ end
30
+ end
31
+
32
+ def create_snippet
33
+ extension = self.haml ? 'liquid.haml' : 'liquid'
34
+
35
+ options = { slug: slug, translated: false }
36
+ file_path = File.join(pages_path, slug)
37
+
38
+ template "template.#{extension}.tt", "#{file_path}.#{extension}", options
39
+
40
+ self.locales.each do |locale|
41
+ options[:translated] = true
42
+ template "template.#{extension}.tt", "#{file_path}.#{locale}.#{extension}", options
43
+ end
44
+ end
45
+
46
+ def self.source_root
47
+ File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'generators', 'snippet')
48
+ end
49
+
50
+ protected
51
+
52
+ def pages_path
53
+ File.join(target_path, 'app', 'views', 'snippets')
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,44 @@
1
+ # Code taken from Mephisto sources (http://mephistoblog.com/)
2
+ module Locomotive
3
+ module Wagon
4
+ module Liquid
5
+ module Drops
6
+ class Base < ::Liquid::Drop
7
+
8
+ @@forbidden_attributes = %w{_id _version _index}
9
+
10
+ attr_reader :_source
11
+
12
+ def initialize(source)
13
+ @_source = source
14
+ end
15
+
16
+ def id
17
+ (@_source.respond_to?(:id) ? @_source.id : nil) || 'new'
18
+ end
19
+
20
+ # converts an array of records to an array of liquid drops
21
+ def self.liquify(*records, &block)
22
+ i = -1
23
+ records =
24
+ records.inject [] do |all, r|
25
+ i+=1
26
+ attrs = (block && block.arity == 1) ? [r] : [r, i]
27
+ all << (block ? block.call(*attrs) : r.to_liquid)
28
+ all
29
+ end
30
+ records.compact!
31
+ records
32
+ end
33
+
34
+ protected
35
+
36
+ def liquify(*records, &block)
37
+ self.class.liquify(*records, &block)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Drops
5
+ class ContentEntry < Base
6
+
7
+ delegate :seo_title, :meta_keywords, :meta_description, :to => '_source'
8
+
9
+ def _label
10
+ @_label ||= self._source._label
11
+ end
12
+
13
+ def _permalink
14
+ @_source._permalink.try(:parameterize)
15
+ end
16
+
17
+ alias :_slug :_permalink
18
+
19
+ def next
20
+ self
21
+ end
22
+
23
+ def previous
24
+ self
25
+ end
26
+
27
+ def errors
28
+ (@_source.errors || []).inject({}) do |memo, name|
29
+ memo[name] = ::I18n.t('errors.messages.blank')
30
+ memo
31
+ end
32
+ end
33
+
34
+ def before_method(meth)
35
+ return '' if self._source.nil?
36
+
37
+ if not @@forbidden_attributes.include?(meth.to_s)
38
+ self._source.send(meth)
39
+ else
40
+ nil
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,121 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Drops
5
+ class ContentTypes < ::Liquid::Drop
6
+
7
+ def before_method(meth)
8
+ type = self.mounting_point.content_types[meth.to_s]
9
+ ProxyCollection.new(type)
10
+ end
11
+
12
+ end
13
+
14
+ class ProxyCollection < ::Liquid::Drop
15
+
16
+ def initialize(content_type)
17
+ @content_type = content_type
18
+ @collection = nil
19
+ end
20
+
21
+ def first
22
+ self.collection.first
23
+ end
24
+
25
+ def last
26
+ self.collection.last
27
+ end
28
+
29
+ def size
30
+ self.collection.size
31
+ end
32
+
33
+ alias :length :size
34
+
35
+ def each(&block)
36
+ self.collection.each(&block)
37
+ end
38
+
39
+ def public_submission_url
40
+ "/entry_submissions/#{@content_type.slug}"
41
+ end
42
+
43
+ def api
44
+ { 'create' => "/entry_submissions/#{@content_type.slug}" }
45
+ end
46
+
47
+ def before_method(meth)
48
+ if (meth.to_s =~ /^group_by_(.+)$/) == 0
49
+ self.group_entries_by(@content_type, $1)
50
+ elsif (meth.to_s =~ /^(.+)_options$/) == 0
51
+ self.select_options_for(@content_type, $1)
52
+ else
53
+ @content_type.send(meth)
54
+ end
55
+ end
56
+
57
+ protected
58
+
59
+ def group_entries_by(content_type, name)
60
+ field = @content_type.find_field(name)
61
+
62
+ return {} if field.nil? || !%w(belongs_to select).include?(field.type.to_s)
63
+
64
+ (@content_type.entries || []).group_by do |entry|
65
+ entry.send(name.to_sym)
66
+ end.to_a.collect do |group|
67
+ { name: group.first, entries: group.last }.with_indifferent_access
68
+ end
69
+ end
70
+
71
+ def select_options_for(content_type, name)
72
+ field = @content_type.find_field(name)
73
+
74
+ return {} if field.nil? || field.type.to_s != 'select'
75
+
76
+ field.select_options.map(&:name)
77
+ end
78
+
79
+ def paginate(options = {})
80
+ @collection ||= self.collection.paginate(options)
81
+ {
82
+ collection: @collection,
83
+ current_page: @collection.current_page,
84
+ previous_page: @collection.previous_page,
85
+ next_page: @collection.next_page,
86
+ total_entries: @collection.total_entries,
87
+ total_pages: @collection.total_pages,
88
+ per_page: @collection.per_page
89
+ }
90
+ end
91
+
92
+ def collection
93
+ return unless @collection.blank?
94
+
95
+ if @context['with_scope'].blank?
96
+ @collection = @content_type.entries
97
+ else
98
+ @collection = []
99
+
100
+ conditions = @context['with_scope'].clone.delete_if { |k, _| %w(order_by per_page page).include?(k) }
101
+
102
+ @content_type.entries.each do |content|
103
+ accepted = (conditions.map do |key, value|
104
+ case value
105
+ when TrueClass, FalseClass, String then content.send(key) == value
106
+ else
107
+ true
108
+ end
109
+ end).all? # all conditions works ?
110
+
111
+ @collection << content if accepted
112
+ end
113
+ end
114
+
115
+ @collection
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,36 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Drops
5
+ class Page < Base
6
+
7
+ delegate :title, :slug, :fullpath, :parent, :depth, :seo_title, :redirect_url, :meta_description, :meta_keywords, :to => '_source'
8
+
9
+ def children
10
+ _children = @_source.children || []
11
+ _children = _children.sort { |a, b| a.position.to_i <=> b.position.to_i }
12
+ @children ||= liquify(*_children)
13
+ end
14
+
15
+ def published?
16
+ @_source.published?
17
+ end
18
+
19
+ def redirect?
20
+ self._source.redirect?
21
+ end
22
+
23
+ def breadcrumbs
24
+ # TODO
25
+ ''
26
+ end
27
+
28
+ def listed?
29
+ @_source.listed?
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Drops
5
+ class Site < Base
6
+
7
+ delegate :name, :seo_title, :meta_description, :meta_keywords, :to => '_source'
8
+
9
+ def index
10
+ @index ||= self.mounting_point.pages['index']
11
+ end
12
+
13
+ def pages
14
+ @pages ||= liquify(*self._source.pages)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ class PageNotFound < ::Liquid::Error; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,98 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Filters
5
+ module Date
6
+
7
+ def localized_date(input, *args)
8
+ return '' if input.blank?
9
+
10
+ format, locale = args
11
+
12
+ locale ||= I18n.locale
13
+ format ||= I18n.t('date.formats.default', :locale => locale)
14
+
15
+ if input.is_a?(String)
16
+ begin
17
+ fragments = ::Date._strptime(input, format)
18
+ input = ::Date.new(fragments[:year], fragments[:mon], fragments[:mday])
19
+ rescue
20
+ input = Time.parse(input)
21
+ end
22
+ end
23
+
24
+ return input.to_s unless input.respond_to?(:strftime)
25
+
26
+ I18n.l input, :format => format, :locale => locale
27
+ end
28
+
29
+ alias :format_date :localized_date
30
+
31
+ def distance_of_time_in_words(input, *args)
32
+ return '' if input.blank?
33
+
34
+ from_time = input
35
+ to_time = args[0] || Time.now
36
+
37
+ from_time = from_time.to_time if from_time.respond_to?(:to_time)
38
+ to_time = to_time.to_time if to_time.respond_to?(:to_time)
39
+ distance_in_minutes = (((to_time - from_time).abs)/60).round
40
+ distance_in_seconds = ((to_time - from_time).abs).round
41
+
42
+ ::I18n.with_options({ :scope => :'datetime.distance_in_words' }) do |locale|
43
+
44
+ case distance_in_minutes
45
+ when 0..1
46
+ return distance_in_minutes == 0 ?
47
+ locale.t(:less_than_x_minutes, :count => 1) :
48
+ locale.t(:x_minutes, :count => distance_in_minutes) unless include_seconds
49
+
50
+ case distance_in_seconds
51
+ when 0..4 then locale.t :less_than_x_seconds, :count => 5
52
+ when 5..9 then locale.t :less_than_x_seconds, :count => 10
53
+ when 10..19 then locale.t :less_than_x_seconds, :count => 20
54
+ when 20..39 then locale.t :half_a_minute
55
+ when 40..59 then locale.t :less_than_x_minutes, :count => 1
56
+ else locale.t :x_minutes, :count => 1
57
+ end
58
+
59
+ when 2..44 then locale.t :x_minutes, :count => distance_in_minutes
60
+ when 45..89 then locale.t :about_x_hours, :count => 1
61
+ when 90..1439 then locale.t :about_x_hours, :count => (distance_in_minutes.to_f / 60.0).round
62
+ when 1440..2519 then locale.t :x_days, :count => 1
63
+ when 2520..43199 then locale.t :x_days, :count => (distance_in_minutes.to_f / 1440.0).round
64
+ when 43200..86399 then locale.t :about_x_months, :count => 1
65
+ when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes.to_f / 43200.0).round
66
+ else
67
+ fyear = from_time.year
68
+ fyear += 1 if from_time.month >= 3
69
+ tyear = to_time.year
70
+ tyear -= 1 if to_time.month < 3
71
+ leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count{|x| ::Date.leap?(x)}
72
+ minute_offset_for_leap_year = leap_years * 1440
73
+ # Discount the leap year days when calculating year distance.
74
+ # e.g. if there are 20 leap year days between 2 dates having the same day
75
+ # and month then the based on 365 days calculation
76
+ # the distance in years will come out to over 80 years when in written
77
+ # english it would read better as about 80 years.
78
+ minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
79
+ remainder = (minutes_with_offset % 525600)
80
+ distance_in_years = (minutes_with_offset / 525600)
81
+ if remainder < 131400
82
+ locale.t(:about_x_years, :count => distance_in_years)
83
+ elsif remainder < 394200
84
+ locale.t(:over_x_years, :count => distance_in_years)
85
+ else
86
+ locale.t(:almost_x_years, :count => distance_in_years + 1)
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ ::Liquid::Template.register_filter(Date)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,154 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Filters
5
+ module Html
6
+
7
+ # Write the link to a stylesheet resource
8
+ # input: url of the css file
9
+ def stylesheet_tag(input, media = 'screen')
10
+ return '' if input.nil?
11
+
12
+ input = "/stylesheets/#{input}" unless input =~ /^(\/|http:)/
13
+
14
+ input = "#{input}.css" unless input.ends_with?('.css')
15
+
16
+ %{<link href="#{input}" media="#{media}" rel="stylesheet" type="text/css" />}
17
+ end
18
+
19
+ # Write the link to javascript resource
20
+ # input: url of the javascript file
21
+ def javascript_tag(input)
22
+ return '' if input.nil?
23
+
24
+ input = "/javascripts/#{input}" unless input =~ /^(\/|http:)/
25
+
26
+ input = "#{input}.js" unless input.ends_with?('.js')
27
+
28
+ %{<script src="#{input}" type="text/javascript"></script>}
29
+ end
30
+
31
+ # Write an image tag
32
+ # input: url of the image OR asset drop
33
+ def image_tag(input, *args)
34
+ image_options = inline_options(args_to_options(args))
35
+
36
+ input = "/images/#{input}" unless input =~ /^(\/|http:)/
37
+
38
+ "<img src=\"#{File.join('/', get_url_from_asset(input))}\" #{image_options}/>"
39
+ end
40
+
41
+ # Write a theme image tag
42
+ # input: name of file including folder
43
+ # example: 'about/myphoto.jpg' | theme_image # <img src="images/about/myphoto.jpg" />
44
+ def theme_image_tag(input, *args)
45
+ image_options = inline_options(args_to_options(args))
46
+ "<img src=\"#{theme_image_url(input)}\" #{image_options}/>"
47
+ end
48
+
49
+ def theme_image_url(input)
50
+ return '' if input.nil?
51
+
52
+ input = "images/#{input}" unless input.starts_with?('/')
53
+
54
+ File.join('/', input)
55
+ end
56
+
57
+ def image_format(input, *args)
58
+ format = args_to_options(args).first
59
+ "#{input}.#{format}"
60
+ end
61
+
62
+ # Embed a flash movie into a page
63
+ # input: url of the flash movie OR asset drop
64
+ # width: width (in pixel or in %) of the embedded movie
65
+ # height: height (in pixel or in %) of the embedded movie
66
+ def flash_tag(input, *args)
67
+ path = get_url_from_asset(input)
68
+ embed_options = inline_options(args_to_options(args))
69
+ %{
70
+ <object #{embed_options}>
71
+ <param name="movie" value="#{path}" />
72
+ <embed src="#{path}" #{embed_options}/>
73
+ </embed>
74
+ </object>
75
+ }.gsub(/ >/, '>').strip
76
+ end
77
+
78
+ # Render the navigation for a paginated collection
79
+ def default_pagination(paginate, *args)
80
+ return '' if paginate['parts'].empty?
81
+
82
+ options = args_to_options(args)
83
+
84
+ previous_label = options[:previous_label] || I18n.t('pagination.previous')
85
+ next_label = options[:next_label] || I18n.t('pagination.next')
86
+
87
+ previous_link = (if paginate['previous'].blank?
88
+ "<span class=\"disabled prev_page\">#{previous_label}</span>"
89
+ else
90
+ "<a href=\"#{absolute_url(paginate['previous']['url'])}\" class=\"prev_page\">#{previous_label}</a>"
91
+ end)
92
+
93
+ links = ""
94
+ paginate['parts'].each do |part|
95
+ links << (if part['is_link']
96
+ "<a href=\"#{absolute_url(part['url'])}\">#{part['title']}</a>"
97
+ elsif part['hellip_break']
98
+ "<span class=\"gap\">#{part['title']}</span>"
99
+ else
100
+ "<span class=\"current\">#{part['title']}</span>"
101
+ end)
102
+ end
103
+
104
+ next_link = (if paginate['next'].blank?
105
+ "<span class=\"disabled next_page\">#{next_label}</span>"
106
+ else
107
+ "<a href=\"#{absolute_url(paginate['next']['url'])}\" class=\"next_page\">#{next_label}</a>"
108
+ end)
109
+
110
+ %{<div class="pagination #{options[:css]}">
111
+ #{previous_link}
112
+ #{links}
113
+ #{next_link}
114
+ </div>}
115
+ end
116
+
117
+ protected
118
+
119
+ # Convert an array of properties ('key:value') into a hash
120
+ # Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' }
121
+ def args_to_options(*args)
122
+ options = {}
123
+ args.flatten.each do |a|
124
+ if (a =~ /^(.*):(.*)$/)
125
+ options[$1.to_sym] = $2
126
+ end
127
+ end
128
+ options
129
+ end
130
+
131
+ # Write options (Hash) into a string according to the following pattern:
132
+ # <key1>="<value1>", <key2>="<value2", ...etc
133
+ def inline_options(options = {})
134
+ return '' if options.empty?
135
+ (options.stringify_keys.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' '
136
+ end
137
+
138
+ # Get the path to be used in html tags such as image_tag, flash_tag, ...etc
139
+ # input: url (String) OR asset drop
140
+ def get_url_from_asset(input)
141
+ input.respond_to?(:url) ? input.url : input
142
+ end
143
+
144
+ def absolute_url(url)
145
+ url =~ /^\// ? url : "/#{url}"
146
+ end
147
+ end
148
+
149
+ ::Liquid::Template.register_filter(Html)
150
+
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,28 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Filters
5
+ module Misc
6
+
7
+ # was called modulo at first
8
+ def str_modulo(word, index, modulo)
9
+ (index.to_i + 1) % modulo == 0 ? word : ''
10
+ end
11
+
12
+ # Get the nth element of the passed in array
13
+ def index(array, position)
14
+ array.at(position) if array.respond_to?(:at)
15
+ end
16
+
17
+ def default(input, value)
18
+ input.blank? ? value : input
19
+ end
20
+
21
+ end
22
+
23
+ ::Liquid::Template.register_filter(Misc)
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Liquid
4
+ module Filters
5
+ module Resize
6
+
7
+ def resize(input, resize_string)
8
+ Locomotive::Wagon::Dragonfly.instance.resize_url(input, resize_string)
9
+ end
10
+
11
+ end
12
+
13
+ ::Liquid::Template.register_filter(Resize)
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ require 'RedCloth'
2
+
3
+ module Locomotive
4
+ module Wagon
5
+ module Liquid
6
+ module Filters
7
+ module Text
8
+
9
+ # right justify and padd a string
10
+ def rjust(input, integer, padstr = '')
11
+ input.to_s.rjust(integer, padstr)
12
+ end
13
+
14
+ # left justify and padd a string
15
+ def ljust(input, integer, padstr = '')
16
+ input.to_s.ljust(integer, padstr)
17
+ end
18
+
19
+ def underscore(input)
20
+ input.to_s.gsub(' ', '_').gsub('/', '_').underscore
21
+ end
22
+
23
+ def dasherize(input)
24
+ input.to_s.gsub(' ', '-').gsub('/', '-').dasherize
25
+ end
26
+
27
+ # alias newline_to_br
28
+ def multi_line(input)
29
+ input.to_s.gsub("\n", '<br/>')
30
+ end
31
+
32
+ def concat(input, *args)
33
+ result = input.to_s
34
+ args.flatten.each { |a| result << a.to_s }
35
+ result
36
+ end
37
+
38
+
39
+ def textile(input)
40
+ ::RedCloth.new(input).to_html
41
+ end
42
+
43
+ end
44
+
45
+ ::Liquid::Template.register_filter(Text)
46
+
47
+ end
48
+ end
49
+ end
50
+ end