locomotivecms_wagon 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +1 -1
  3. data/README.md +1 -1
  4. data/Rakefile +2 -2
  5. data/generators/blank/Gemfile.tt +3 -1
  6. data/generators/blank/config/deploy.yml +4 -1
  7. data/generators/bootstrap/Gemfile.tt +3 -1
  8. data/generators/bootstrap/config/deploy.yml +4 -1
  9. data/generators/cloned/Gemfile.tt +3 -1
  10. data/generators/cloned/config/deploy.yml.tt +5 -1
  11. data/generators/foundation/Gemfile.tt +4 -2
  12. data/generators/foundation/app/views/pages/index.liquid +3 -1
  13. data/generators/foundation/app/views/pages/index.liquid.haml +18 -16
  14. data/generators/foundation/config/deploy.yml +4 -1
  15. data/generators/foundation/public/javascripts/foundation.min.js +32 -14
  16. data/generators/foundation/public/javascripts/foundation/foundation.alerts.js +4 -2
  17. data/generators/foundation/public/javascripts/foundation/foundation.clearing.js +67 -31
  18. data/generators/foundation/public/javascripts/foundation/foundation.cookie.js +1 -1
  19. data/generators/foundation/public/javascripts/foundation/foundation.dropdown.js +73 -25
  20. data/generators/foundation/public/javascripts/foundation/foundation.forms.js +356 -235
  21. data/generators/foundation/public/javascripts/foundation/foundation.interchange.js +271 -0
  22. data/generators/foundation/public/javascripts/foundation/foundation.joyride.js +265 -33
  23. data/generators/foundation/public/javascripts/foundation/foundation.js +130 -55
  24. data/generators/foundation/public/javascripts/foundation/foundation.magellan.js +6 -4
  25. data/generators/foundation/public/javascripts/foundation/foundation.orbit.js +38 -13
  26. data/generators/foundation/public/javascripts/foundation/foundation.placeholder.js +1 -1
  27. data/generators/foundation/public/javascripts/foundation/foundation.reveal.js +74 -14
  28. data/generators/foundation/public/javascripts/foundation/foundation.section.js +210 -66
  29. data/generators/foundation/public/javascripts/foundation/foundation.tooltips.js +25 -12
  30. data/generators/foundation/public/javascripts/foundation/foundation.topbar.js +126 -54
  31. data/generators/foundation/public/javascripts/vendor/custom.modernizr.js +1 -1
  32. data/generators/foundation/public/javascripts/vendor/jquery.js +1 -1
  33. data/generators/foundation/public/javascripts/vendor/zepto.js +1 -1
  34. data/generators/foundation/public/stylesheets/foundation.css +870 -438
  35. data/generators/foundation/public/stylesheets/foundation.min.css +440 -1
  36. data/generators/foundation/public/stylesheets/normalize.css +89 -146
  37. data/generators/page/template.liquid.haml.tt +6 -7
  38. data/generators/page/template.liquid.tt +34 -1
  39. data/lib/locomotive/wagon.rb +15 -1
  40. data/lib/locomotive/wagon/cli.rb +8 -4
  41. data/lib/locomotive/wagon/generators/site/foundation.rb +1 -1
  42. data/lib/locomotive/wagon/liquid.rb +1 -2
  43. data/lib/locomotive/wagon/liquid/drops/content_types.rb +6 -22
  44. data/lib/locomotive/wagon/liquid/drops/page.rb +6 -14
  45. data/lib/locomotive/wagon/liquid/drops/site.rb +4 -1
  46. data/lib/locomotive/wagon/liquid/filters/html.rb +1 -1
  47. data/lib/locomotive/wagon/liquid/filters/translate.rb +10 -6
  48. data/lib/locomotive/wagon/liquid/tags/nav.rb +3 -2
  49. data/lib/locomotive/wagon/misc/dragonfly.rb +1 -1
  50. data/lib/locomotive/wagon/scopeable.rb +28 -0
  51. data/lib/locomotive/wagon/server/page.rb +7 -1
  52. data/lib/locomotive/wagon/version.rb +1 -1
  53. data/locales/de.yml +13 -12
  54. data/locales/en.yml +13 -12
  55. data/locales/es.yml +13 -12
  56. data/locales/et.yml +13 -12
  57. data/locales/fr.yml +14 -12
  58. data/locales/it.yml +13 -12
  59. data/locales/nb.yml +13 -12
  60. data/locales/nl.yml +11 -10
  61. data/locales/pl.yml +13 -12
  62. data/locales/pt-BR.yml +13 -12
  63. data/locales/ru.yml +13 -12
  64. data/locomotivecms_wagon.gemspec +2 -1
  65. data/spec/fixtures/default/app/views/pages/grunge_bands.liquid.haml +8 -0
  66. data/spec/fixtures/default/app/views/pages/index.liquid.haml +3 -0
  67. data/spec/fixtures/default/app/views/pages/music.liquid.haml +1 -1
  68. data/spec/fixtures/default/app/views/pages/songs/template.liquid.haml +4 -0
  69. data/spec/fixtures/default/app/views/pages/tags/nav.liquid.haml +6 -0
  70. data/spec/fixtures/default/app/views/pages/unlisted_pages.liquid.haml +9 -0
  71. data/spec/integration/cassettes/pull.yml +397 -240
  72. data/spec/integration/cassettes/push.yml +468 -438
  73. data/spec/integration/cassettes/staging.yml +846 -0
  74. data/spec/integration/cli_spec.rb +19 -0
  75. data/spec/integration/server/basic_spec.rb +34 -5
  76. data/spec/integration/server/liquid_spec.rb +39 -0
  77. data/spec/integration/sites_spec.rb +28 -4
  78. data/spec/spec_helper.rb +1 -0
  79. data/spec/support/helpers.rb +8 -1
  80. metadata +37 -53
@@ -2,26 +2,25 @@
2
2
  title: <%= config[:slug].humanize -%>
3
3
  <% if config[:translated] %>
4
4
 
5
- # TODO: explain it (used only if the page is not for the defaut locale)
5
+ # unique identifier for urls, the same as a permalink
6
6
  slug: <%= config[:slug] -%>
7
7
  <% end %>
8
8
 
9
- # TODO: explain it
9
+ # true if the page is included in the menu
10
10
  listed: true
11
11
 
12
- # TODO: explain it
12
+ # true if the page is published
13
13
  published: true
14
14
 
15
- # TODO: explain it
15
+ # position among sibling pages
16
16
  # position: 1
17
17
 
18
- # TODO: explain it
18
+ # sets a redirection to the given url (301)
19
19
  # redirect_url: "<url to a page or to a remote url>"
20
20
 
21
- # TODO: explain it
21
+ # content type that this page is templatizing
22
22
  # content_type: "<slug of one of the content types>"
23
23
 
24
- # TODO: explain it
25
24
  # editable_elements:
26
25
  # 'some_block/some_slug': "<text>"
27
26
  # 'some_block/some_slug': "<relative path to the file under the public/samples folder>"
@@ -1 +1,34 @@
1
- TEST LIQUID
1
+ ---
2
+ title: <%= config[:slug].humanize -%>
3
+ <% if config[:translated] %>
4
+
5
+ # unique identifier for urls, the same as a permalink
6
+ slug: <%= config[:slug] -%>
7
+ <% end %>
8
+
9
+ # true if the page is included in the menu
10
+ listed: true
11
+
12
+ # true if the page is published
13
+ published: true
14
+
15
+ # position among sibling pages
16
+ # position: 1
17
+
18
+ # sets a redirection to the given url (301)
19
+ # redirect_url: "<url to a page or to a remote url>"
20
+
21
+ # content type that this page is templatizing
22
+ # content_type: "<slug of one of the content types>"
23
+
24
+ # editable_elements:
25
+ # 'some_block/some_slug': "<text>"
26
+ # 'some_block/some_slug': "<relative path to the file under the public/samples folder>"
27
+ ---
28
+ {% extends parent %}
29
+
30
+ {% block main %}
31
+
32
+ <p>Hello world</p>
33
+
34
+ {% endblock %}
@@ -57,9 +57,14 @@ module Locomotive
57
57
  #
58
58
  def self.push(path, connection_info, options = {})
59
59
  if reader = self.require_mounter(path, true)
60
+
61
+ reader.mounting_point.site.domains = connection_info["domains"] if connection_info["domains"]
62
+ reader.mounting_point.site.subdomain = connection_info["subdomain"] if connection_info["subdomain"]
63
+ require 'bundler'
60
64
  Bundler.require 'misc'
61
65
 
62
66
  writer = Locomotive::Mounter::Writer::Api.instance
67
+ self.validate_resources(options[:resources], writer.writers)
63
68
 
64
69
  connection_info[:uri] = "#{connection_info.delete(:host)}/locomotive/api"
65
70
 
@@ -88,6 +93,7 @@ module Locomotive
88
93
  _options[:only] = _options.delete(:resources)
89
94
 
90
95
  reader = Locomotive::Mounter::Reader::Api.instance
96
+ self.validate_resources(_options[:only], reader.readers)
91
97
  reader.run!(_options.merge(connection_info))
92
98
 
93
99
  writer = Locomotive::Mounter::Writer::FileSystem.instance
@@ -112,7 +118,7 @@ module Locomotive
112
118
  # generate an almost blank site
113
119
  require 'locomotive/wagon/generators/site'
114
120
  generator = Locomotive::Wagon::Generators::Site::Cloned
115
- generator.start [name, path, connection_info]
121
+ generator.start [name, path, connection_info.symbolize_keys]
116
122
 
117
123
  # pull the remote site
118
124
  self.pull(target_path, options.merge(connection_info).with_indifferent_access, { disable_misc: true })
@@ -160,5 +166,13 @@ module Locomotive
160
166
  end
161
167
  end
162
168
 
169
+ protected
170
+ def self.validate_resources(resources, writers_or_readers)
171
+ return if resources.nil?
172
+ valid_resources = writers_or_readers.map { |thing| thing.to_s.demodulize.gsub(/Writer$|Reader$/, '').underscore }
173
+ resources.each do |resource|
174
+ raise ArgumentError, "'#{resource}' resource not recognized. Valid resources are #{valid_resources.join(', ')}." unless valid_resources.include?(resource)
175
+ end
176
+ end
163
177
  end
164
178
  end
@@ -135,11 +135,14 @@ module Locomotive
135
135
  end
136
136
  end
137
137
 
138
- desc 'clone NAME HOST EMAIL PASSWORD [PATH]', 'Clone a remote LocomotiveCMS site'
139
- method_option :verbose, aliases: '-v', type: 'boolean', default: false, desc: 'display the full error stack trace if an error occurs'
140
- def clone(name, host, email, password, path = '.')
138
+ desc 'clone NAME HOST [PATH]', 'Clone a remote LocomotiveCMS site'
139
+ method_option :verbose, aliases: '-v', type: 'boolean', default: false, desc: 'display the full error stack trace if an error occurs'
140
+ method_option :email, aliases: '-e', desc: 'email of an administrator account'
141
+ method_option :password, aliases: '-p', desc: 'password of an administrator account'
142
+ method_option :api_key, aliases: '-a', desc: 'api key of an administrator account'
143
+ def clone(name, host, path = '.')
141
144
  begin
142
- if Locomotive::Wagon.clone(name, path, host: host, email: email, password: password)
145
+ if Locomotive::Wagon.clone(name, path, { host: host }.merge(options))
143
146
  self.print_next_instructions_when_site_created(name, path)
144
147
  end
145
148
  rescue Exception => e
@@ -179,6 +182,7 @@ module Locomotive
179
182
  desc 'push ENV [PATH]', 'Push a site to a remote LocomotiveCMS engine'
180
183
  method_option :resources, aliases: '-r', type: 'array', default: nil, desc: 'Only push the resource(s) passed in argument'
181
184
  method_option :force, aliases: '-f', type: 'boolean', default: false, desc: 'Force the push of a resource'
185
+ method_option :force_translations, type: 'boolean', default: false, desc: 'Force the push of local translations. You must specify it even if already using -f'
182
186
  method_option :data, aliases: '-d', type: 'boolean', default: false, desc: 'Push the content entries and the editable elements (by default, they are not)'
183
187
  method_option :verbose, aliases: '-v', type: 'boolean', default: false, desc: 'display the full error stack trace if an error occurs'
184
188
  def push(env, path = '.')
@@ -27,7 +27,7 @@ module Locomotive
27
27
  end
28
28
 
29
29
  Locomotive::Wagon::Generators::Site.register(:foundation, Foundation, %{
30
- A LocomotiveCMS site powered by Foundation (v4.0.9).
30
+ A LocomotiveCMS site powered by Foundation (v4.2.1).
31
31
  })
32
32
  end
33
33
  end
@@ -1,12 +1,11 @@
1
- require "locomotive/mounter"
2
1
  require 'liquid'
2
+ require 'locomotive/mounter'
3
3
  require 'locomotive/wagon/liquid/drops/base'
4
4
 
5
5
  %w{. drops tags filters}.each do |dir|
6
6
  Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib }
7
7
  end
8
8
 
9
-
10
9
  # add to_liquid methods to main models from the mounter
11
10
  %w{site page content_entry}.each do |name|
12
11
  klass = "Locomotive::Mounter::Models::#{name.classify}".constantize
@@ -1,3 +1,5 @@
1
+ require "locomotive/wagon/scopeable"
2
+
1
3
  module Locomotive
2
4
  module Wagon
3
5
  module Liquid
@@ -12,6 +14,7 @@ module Locomotive
12
14
  end
13
15
 
14
16
  class ProxyCollection < ::Liquid::Drop
17
+ include Scopeable
15
18
 
16
19
  def initialize(content_type)
17
20
  @content_type = content_type
@@ -31,6 +34,7 @@ module Locomotive
31
34
  end
32
35
 
33
36
  alias :length :size
37
+ alias :count :size
34
38
 
35
39
  def each(&block)
36
40
  self.collection.each(&block)
@@ -91,28 +95,8 @@ module Locomotive
91
95
 
92
96
  def collection
93
97
  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
98
+
99
+ @collection = apply_scope(@content_type.entries)
116
100
  end
117
101
  end
118
102
  end
@@ -4,31 +4,23 @@ module Locomotive
4
4
  module Drops
5
5
  class Page < Base
6
6
 
7
- delegate :title, :slug, :fullpath, :parent, :depth, :seo_title, :redirect_url, :meta_description, :meta_keywords, :to => '_source'
7
+ delegate :title, :slug, :fullpath, :parent, :depth, :seo_title, :redirect_url, :meta_description, :meta_keywords,
8
+ :templatized?, :published?, :redirect?, :listed?, to: '_source'
8
9
 
9
10
  def children
10
- _children = @_source.children || []
11
+ _children = _source.children || []
11
12
  _children = _children.sort { |a, b| a.position.to_i <=> b.position.to_i }
12
13
  @children ||= liquify(*_children)
13
14
  end
14
15
 
15
- def published?
16
- @_source.published?
16
+ def content_type
17
+ ProxyCollection.new(_source.content_type) if _source.content_type
17
18
  end
18
-
19
- def redirect?
20
- self._source.redirect?
21
- end
22
-
19
+
23
20
  def breadcrumbs
24
21
  # TODO
25
22
  ''
26
23
  end
27
-
28
- def listed?
29
- @_source.listed?
30
- end
31
-
32
24
  end
33
25
  end
34
26
  end
@@ -1,8 +1,11 @@
1
+ require "locomotive/wagon/scopeable"
2
+
1
3
  module Locomotive
2
4
  module Wagon
3
5
  module Liquid
4
6
  module Drops
5
7
  class Site < Base
8
+ include Scopeable
6
9
 
7
10
  delegate :name, :seo_title, :meta_description, :meta_keywords, :to => '_source'
8
11
 
@@ -11,7 +14,7 @@ module Locomotive
11
14
  end
12
15
 
13
16
  def pages
14
- @pages ||= liquify(*self.mounting_point.pages.values)
17
+ @pages ||= liquify(*apply_scope(self.mounting_point.pages.values))
15
18
  end
16
19
 
17
20
  end
@@ -12,7 +12,7 @@ module Locomotive
12
12
  options = args_to_options(args)
13
13
 
14
14
  rel = options[:rel] || 'alternate'
15
- type = options[:type] || Mime::Type.lookup_by_extension('rss').to_s
15
+ type = options[:type] || MIME::Types.type_for('rss').first
16
16
  title = options[:title] || 'RSS'
17
17
 
18
18
  %{<link rel="#{rel}" type="#{type}" title="#{title}" href="#{input}" />}
@@ -4,16 +4,20 @@ module Locomotive
4
4
  module Filters
5
5
  module Translate
6
6
 
7
- def translate(key, locale = nil)
8
- translation = @context.registers[:mounting_point].translations[key.to_s]
7
+ def translate(key, locale = nil, scope = nil)
8
+ locale ||= I18n.locale.to_s
9
+ if scope.blank?
10
+ translation = @context.registers[:mounting_point].translations[key.to_s]
9
11
 
10
- if translation
11
- translation.get(locale) || translation.get(Locomotive::Mounter.locale.to_s)
12
+ if translation
13
+ translation.get(locale) || translation.get(Locomotive::Mounter.locale.to_s)
14
+ else
15
+ "[unknown translation key: #{key}]"
16
+ end
12
17
  else
13
- "[unknown translation key: #{key}]"
18
+ I18n.t(key, scope: scope.split('.'), locale: locale)
14
19
  end
15
20
  end
16
-
17
21
  end
18
22
 
19
23
  ::Liquid::Template.register_filter(Translate)
@@ -20,7 +20,7 @@ module Locomotive
20
20
  def initialize(tag_name, markup, tokens, context)
21
21
  if markup =~ Syntax
22
22
  @source = ($1 || 'page').gsub(/"|'/, '')
23
- @options = { :id => 'nav', :class => '', :active_class => 'on', :bootstrap => false }
23
+ @options = { id: 'nav', class: '', active_class: 'on', bootstrap: false }
24
24
  markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/"|'/, '') }
25
25
 
26
26
  @options[:exclude] = Regexp.new(@options[:exclude]) if @options[:exclude]
@@ -55,7 +55,8 @@ module Locomotive
55
55
  output = children_output.join("\n")
56
56
 
57
57
  if @options[:no_wrapper] != 'true'
58
- output = %{<ul id="#{@options[:id]}" class="#{@options[:class]}">\n#{output}</ul>}
58
+ list_class = !@options[:class].blank? ? %( class="#{@options[:class]}") : ''
59
+ output = %{<nav id="#{@options[:id]}"#{list_class}><ul>\n#{output}</ul></nav>}
59
60
  end
60
61
 
61
62
  output
@@ -54,7 +54,7 @@ module Locomotive
54
54
 
55
55
  ## configure it ##
56
56
  ::Dragonfly[:images].configure do |c|
57
- convert = `which convert`.strip.presence || '/usr/local/bin/convert'
57
+ convert = `which convert`.strip.presence || '/usr/bin/env convert'
58
58
  c.convert_command = convert
59
59
  c.identify_command = convert
60
60
 
@@ -0,0 +1,28 @@
1
+ module Locomotive
2
+ module Wagon
3
+ module Scopeable
4
+ def apply_scope(entries)
5
+ if @context['with_scope'].blank?
6
+ entries
7
+ else
8
+ collection = []
9
+
10
+ conditions = @context['with_scope'].clone.delete_if { |k, _| %w(order_by per_page page).include?(k) }
11
+
12
+ entries.each do |content|
13
+ accepted = (conditions.map do |key, value|
14
+ case value
15
+ when TrueClass, FalseClass, String then content.send(key) == value
16
+ else
17
+ true
18
+ end
19
+ end).all? # all conditions works ?
20
+
21
+ collection << content if accepted
22
+ end
23
+ collection
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -29,10 +29,16 @@ module Locomotive::Wagon
29
29
  def fetch_page
30
30
  matchers = self.path_combinations(self.path)
31
31
 
32
- self.mounting_point.pages.values.detect do |_page|
32
+ pages = self.mounting_point.pages.values.find_all do |_page|
33
33
  matchers.include?(_page.safe_fullpath) ||
34
34
  matchers.include?(_page.safe_fullpath.try(:underscore))
35
+ end.sort { |a, b| a.position <=> b.position }
36
+
37
+ if pages.size > 1
38
+ self.log "Found multiple pages: #{pages.collect(&:title).join(', ')}"
35
39
  end
40
+
41
+ pages.first
36
42
  end
37
43
 
38
44
  def path_combinations(path)
@@ -1,5 +1,5 @@
1
1
  module Locomotive
2
2
  module Wagon
3
- VERSION = '1.0.2'
3
+ VERSION = '1.1.0'
4
4
  end
5
5
  end
data/locales/de.yml CHANGED
@@ -1,16 +1,17 @@
1
1
  de:
2
- locales:
3
- en: Englisch
4
- de: Deutsch
5
- fr: Französisch
6
- pl: Polnisch
7
- pt-BR: "Bras. Portugiesisch"
8
- it: Italienisch
9
- nl: Niederländisch
10
- nb: Norwegisch
11
- es: Spanisch
12
- ru: Russisch
13
- et: Estnisch
2
+ locomotive:
3
+ locales:
4
+ en: Englisch
5
+ de: Deutsch
6
+ fr: Französisch
7
+ pl: Polnisch
8
+ pt-BR: "Bras. Portugiesisch"
9
+ it: Italienisch
10
+ nl: Niederländisch
11
+ nb: Norwegisch
12
+ es: Spanisch
13
+ ru: Russisch
14
+ et: Estnisch
14
15
 
15
16
  errors:
16
17
  messages:
data/locales/en.yml CHANGED
@@ -1,16 +1,17 @@
1
1
  en:
2
- locales:
3
- en: English
4
- de: German
5
- fr: French
6
- pl: Polish
7
- pt-BR: "Brazilian Portuguese"
8
- it: Italian
9
- nl: Dutch
10
- nb: Norwegian
11
- es: Spanish
12
- ru: Russian
13
- et: Estonian
2
+ locomotive:
3
+ locales:
4
+ en: English
5
+ de: German
6
+ fr: French
7
+ pl: Polish
8
+ pt-BR: "Brazilian Portuguese"
9
+ it: Italian
10
+ nl: Dutch
11
+ nb: Norwegian
12
+ es: Spanish
13
+ ru: Russian
14
+ et: Estonian
14
15
 
15
16
  errors:
16
17
  messages: