locomotivecms_builder 1.0.0.alpha1
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.
- data/.gitignore +31 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/Rakefile +47 -0
- data/TODO +57 -0
- data/bin/builder +9 -0
- data/generators/blank/Gemfile.tt +20 -0
- data/generators/blank/app/content_types/.empty_directory +1 -0
- data/generators/blank/app/views/pages/404.liquid +11 -0
- data/generators/blank/app/views/pages/index.liquid +19 -0
- data/generators/blank/app/views/snippets/.empty_directory +1 -0
- data/generators/blank/config/deploy.yml +12 -0
- data/generators/blank/config/site.yml.tt +16 -0
- data/generators/blank/config/translations.yml +8 -0
- data/generators/blank/config.ru +3 -0
- data/generators/blank/data/.empty_directory +1 -0
- data/generators/blank/public/fonts/.empty_directory +1 -0
- data/generators/blank/public/images/.empty_directory +1 -0
- data/generators/blank/public/javascripts/.empty_directory +1 -0
- data/generators/blank/public/samples/.empty_directory +1 -0
- data/generators/blank/public/stylesheets/.empty_directory +1 -0
- data/generators/bootstrap/Gemfile.tt +20 -0
- data/generators/bootstrap/app/content_types/.empty_directory +1 -0
- data/generators/bootstrap/app/views/pages/404.liquid +13 -0
- data/generators/bootstrap/app/views/pages/404.liquid.haml +10 -0
- data/generators/bootstrap/app/views/pages/index.liquid +85 -0
- data/generators/bootstrap/app/views/pages/index.liquid.haml +72 -0
- data/generators/bootstrap/app/views/snippets/footer.liquid +3 -0
- data/generators/bootstrap/app/views/snippets/footer.liquid.haml +2 -0
- data/generators/bootstrap/config/deploy.yml +12 -0
- data/generators/bootstrap/config/site.yml.tt +16 -0
- data/generators/bootstrap/config/translations.yml +8 -0
- data/generators/bootstrap/config.ru +3 -0
- data/generators/bootstrap/data/.empty_directory +1 -0
- data/generators/bootstrap/public/fonts/FontAwesome.otf +0 -0
- data/generators/bootstrap/public/fonts/font-awesome-ie7.min.css +23 -0
- data/generators/bootstrap/public/fonts/font-awesome.css +469 -0
- data/generators/bootstrap/public/fonts/font-awesome.min.css +34 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.eot +0 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.ttf +0 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.woff +0 -0
- data/generators/bootstrap/public/javascripts/bootstrap.js +2159 -0
- data/generators/bootstrap/public/javascripts/bootstrap.min.js +6 -0
- data/generators/bootstrap/public/samples/.empty_directory +1 -0
- data/generators/bootstrap/public/stylesheets/application.css.scss +39 -0
- data/generators/bootstrap/public/stylesheets/bootstrap-responsive.css +1092 -0
- data/generators/bootstrap/public/stylesheets/bootstrap-responsive.min.css +9 -0
- data/generators/bootstrap/public/stylesheets/bootstrap.css +5652 -0
- data/generators/bootstrap/public/stylesheets/bootstrap.min.css +726 -0
- data/generators/content_type/app/content_types/%name%.yml.tt +58 -0
- data/generators/content_type/data/%name%.yml.tt +24 -0
- data/generators/page/template.liquid.haml.tt +35 -0
- data/generators/page/template.liquid.tt +1 -0
- data/generators/snippet/template.liquid.haml.tt +4 -0
- data/generators/snippet/template.liquid.tt +4 -0
- data/lib/locomotive/builder/cli.rb +225 -0
- data/lib/locomotive/builder/exceptions.rb +17 -0
- data/lib/locomotive/builder/generators/content_type.rb +47 -0
- data/lib/locomotive/builder/generators/page.rb +57 -0
- data/lib/locomotive/builder/generators/site/base.rb +30 -0
- data/lib/locomotive/builder/generators/site/blank.rb +23 -0
- data/lib/locomotive/builder/generators/site/bootstrap.rb +35 -0
- data/lib/locomotive/builder/generators/site.rb +97 -0
- data/lib/locomotive/builder/generators/snippet.rb +54 -0
- data/lib/locomotive/builder/liquid/drops/base.rb +44 -0
- data/lib/locomotive/builder/liquid/drops/content_entry.rb +48 -0
- data/lib/locomotive/builder/liquid/drops/content_types.rb +121 -0
- data/lib/locomotive/builder/liquid/drops/page.rb +36 -0
- data/lib/locomotive/builder/liquid/drops/site.rb +21 -0
- data/lib/locomotive/builder/liquid/errors.rb +7 -0
- data/lib/locomotive/builder/liquid/filters/date.rb +98 -0
- data/lib/locomotive/builder/liquid/filters/html.rb +154 -0
- data/lib/locomotive/builder/liquid/filters/misc.rb +28 -0
- data/lib/locomotive/builder/liquid/filters/resize.rb +18 -0
- data/lib/locomotive/builder/liquid/filters/text.rb +50 -0
- data/lib/locomotive/builder/liquid/filters/translate.rb +24 -0
- data/lib/locomotive/builder/liquid/patches.rb +47 -0
- data/lib/locomotive/builder/liquid/tags/consume.rb +58 -0
- data/lib/locomotive/builder/liquid/tags/csrf.rb +34 -0
- data/lib/locomotive/builder/liquid/tags/editable/base.rb +46 -0
- data/lib/locomotive/builder/liquid/tags/editable/control.rb +19 -0
- data/lib/locomotive/builder/liquid/tags/editable/file.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable/long_text.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable/short_text.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable.rb +5 -0
- data/lib/locomotive/builder/liquid/tags/extends.rb +25 -0
- data/lib/locomotive/builder/liquid/tags/google_analytics.rb +28 -0
- data/lib/locomotive/builder/liquid/tags/inline_editor.rb +16 -0
- data/lib/locomotive/builder/liquid/tags/locale_switcher.rb +180 -0
- data/lib/locomotive/builder/liquid/tags/nav.rb +167 -0
- data/lib/locomotive/builder/liquid/tags/paginate.rb +105 -0
- data/lib/locomotive/builder/liquid/tags/seo.rb +74 -0
- data/lib/locomotive/builder/liquid/tags/snippet.rb +42 -0
- data/lib/locomotive/builder/liquid/tags/with_scope.rb +43 -0
- data/lib/locomotive/builder/liquid.rb +19 -0
- data/lib/locomotive/builder/listen.rb +48 -0
- data/lib/locomotive/builder/misc/core_ext.rb +29 -0
- data/lib/locomotive/builder/misc/dragonfly.rb +82 -0
- data/lib/locomotive/builder/misc/httparty.rb +47 -0
- data/lib/locomotive/builder/misc/i18n.rb +2 -0
- data/lib/locomotive/builder/misc/will_paginate.rb +16 -0
- data/lib/locomotive/builder/misc.rb +5 -0
- data/lib/locomotive/builder/server/dynamic_assets.rb +31 -0
- data/lib/locomotive/builder/server/entry_submission.rb +116 -0
- data/lib/locomotive/builder/server/favicon.rb +17 -0
- data/lib/locomotive/builder/server/locale.rb +42 -0
- data/lib/locomotive/builder/server/middleware.rb +54 -0
- data/lib/locomotive/builder/server/not_found.rb +18 -0
- data/lib/locomotive/builder/server/page.rb +59 -0
- data/lib/locomotive/builder/server/path.rb +34 -0
- data/lib/locomotive/builder/server/renderer.rb +105 -0
- data/lib/locomotive/builder/server/templatized_page.rb +32 -0
- data/lib/locomotive/builder/server.rb +78 -0
- data/lib/locomotive/builder/standalone_server.rb +33 -0
- data/lib/locomotive/builder/version.rb +5 -0
- data/lib/locomotive/builder.rb +167 -0
- data/locales/de.yml +143 -0
- data/locales/en.yml +164 -0
- data/locales/es.yml +119 -0
- data/locales/et.yml +140 -0
- data/locales/fr.yml +133 -0
- data/locales/it.yml +141 -0
- data/locales/nb.yml +177 -0
- data/locales/nl.yml +148 -0
- data/locales/pl.yml +189 -0
- data/locales/pt-BR.yml +125 -0
- data/locales/ru.yml +210 -0
- data/locomotivecms_builder.gemspec +42 -0
- data/spec/integration/cassettes/pull.yml +590 -0
- data/spec/integration/cassettes/push.yml +775 -0
- data/spec/integration/integration_helper.rb +15 -0
- data/spec/integration/server_spec.rb +37 -0
- data/spec/integration/sites_spec.rb +27 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/helpers.rb +13 -0
- metadata +468 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'thor/group'
|
|
2
|
+
require 'active_support'
|
|
3
|
+
require 'active_support/core_ext'
|
|
4
|
+
|
|
5
|
+
module Locomotive
|
|
6
|
+
module Builder
|
|
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
|
+
|
|
15
|
+
attr_accessor :haml, :locales
|
|
16
|
+
|
|
17
|
+
def ask_for_haml_and_locales
|
|
18
|
+
self.locales = []
|
|
19
|
+
self.haml = yes?('Do you prefer a HAML template ?')
|
|
20
|
+
|
|
21
|
+
if yes?('Is your snippet localized ?')
|
|
22
|
+
self.locales = ask('What are the locales other than the default one (comma separated) ?').split(',').map(&:strip)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create_snippet
|
|
27
|
+
extension = self.haml ? 'liquid.haml' : 'liquid'
|
|
28
|
+
|
|
29
|
+
options = { slug: slug, translated: false }
|
|
30
|
+
file_path = File.join(pages_path, slug)
|
|
31
|
+
|
|
32
|
+
template "template.#{extension}.tt", "#{file_path}.#{extension}", options
|
|
33
|
+
|
|
34
|
+
self.locales.each do |locale|
|
|
35
|
+
options[:translated] = true
|
|
36
|
+
template "template.#{extension}.tt", "#{file_path}.#{locale}.#{extension}", options
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.source_root
|
|
41
|
+
File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'generators', 'snippet')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
protected
|
|
45
|
+
|
|
46
|
+
def pages_path
|
|
47
|
+
File.join(target_path, 'app', 'views', 'snippets')
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Code taken from Mephisto sources (http://mephistoblog.com/)
|
|
2
|
+
module Locomotive
|
|
3
|
+
module Builder
|
|
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 Builder
|
|
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 Builder
|
|
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 Builder
|
|
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 Builder
|
|
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,98 @@
|
|
|
1
|
+
module Locomotive
|
|
2
|
+
module Builder
|
|
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 Builder
|
|
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 Builder
|
|
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 Builder
|
|
3
|
+
module Liquid
|
|
4
|
+
module Filters
|
|
5
|
+
module Resize
|
|
6
|
+
|
|
7
|
+
def resize(input, resize_string)
|
|
8
|
+
Locomotive::Builder::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 Builder
|
|
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
|