locomotivecms_steam 1.5.0.rc0 → 1.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/Gemfile +3 -6
  4. data/Gemfile.lock +39 -39
  5. data/README.md +2 -2
  6. data/lib/locomotive/steam/adapters/filesystem/sanitizers/section.rb +62 -16
  7. data/lib/locomotive/steam/adapters/filesystem/sanitizers/site.rb +15 -1
  8. data/lib/locomotive/steam/adapters/filesystem/yaml_loader.rb +30 -9
  9. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb +1 -1
  10. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/page.rb +1 -1
  11. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/section.rb +14 -2
  12. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/site.rb +1 -1
  13. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/translation.rb +1 -1
  14. data/lib/locomotive/steam/adapters/mongodb.rb +1 -1
  15. data/lib/locomotive/steam/entities/content_entry.rb +0 -1
  16. data/lib/locomotive/steam/entities/site.rb +4 -0
  17. data/lib/locomotive/steam/errors.rb +54 -18
  18. data/lib/locomotive/steam/liquid/drops/content_entry.rb +1 -1
  19. data/lib/locomotive/steam/liquid/drops/content_entry_collection.rb +1 -1
  20. data/lib/locomotive/steam/liquid/drops/content_types.rb +1 -1
  21. data/lib/locomotive/steam/liquid/drops/inherited_block.rb +28 -0
  22. data/lib/locomotive/steam/liquid/drops/metafields.rb +2 -2
  23. data/lib/locomotive/steam/liquid/drops/params.rb +1 -1
  24. data/lib/locomotive/steam/liquid/drops/section.rb +10 -2
  25. data/lib/locomotive/steam/liquid/drops/section_content_proxy.rb +13 -2
  26. data/lib/locomotive/steam/liquid/drops/section_editor_setting_data.rb +1 -1
  27. data/lib/locomotive/steam/liquid/drops/session_proxy.rb +1 -1
  28. data/lib/locomotive/steam/liquid/file_system.rb +46 -0
  29. data/lib/locomotive/steam/liquid/filters/array.rb +61 -0
  30. data/lib/locomotive/steam/liquid/filters/misc.rb +12 -2
  31. data/lib/locomotive/steam/liquid/filters/number.rb +13 -12
  32. data/lib/locomotive/steam/liquid/filters/text.rb +4 -0
  33. data/lib/locomotive/steam/liquid/patches.rb +58 -19
  34. data/lib/locomotive/steam/liquid/tags/alt_page_links.rb +9 -5
  35. data/lib/locomotive/steam/liquid/tags/concerns/attributes.rb +47 -0
  36. data/lib/locomotive/steam/liquid/tags/concerns/path.rb +18 -31
  37. data/lib/locomotive/steam/liquid/tags/concerns/section.rb +22 -11
  38. data/lib/locomotive/steam/liquid/tags/consume.rb +26 -33
  39. data/lib/locomotive/steam/liquid/tags/csrf.rb +2 -2
  40. data/lib/locomotive/steam/liquid/tags/editable/base.rb +30 -20
  41. data/lib/locomotive/steam/liquid/tags/editable/control.rb +2 -2
  42. data/lib/locomotive/steam/liquid/tags/editable/file.rb +11 -11
  43. data/lib/locomotive/steam/liquid/tags/editable/text.rb +5 -5
  44. data/lib/locomotive/steam/liquid/tags/extends.rb +56 -8
  45. data/lib/locomotive/steam/liquid/tags/global_section.rb +6 -6
  46. data/lib/locomotive/steam/liquid/tags/google_analytics.rb +16 -6
  47. data/lib/locomotive/steam/liquid/tags/hybrid.rb +8 -4
  48. data/lib/locomotive/steam/liquid/tags/inherited_block.rb +90 -13
  49. data/lib/locomotive/steam/liquid/tags/inline_editor.rb +4 -4
  50. data/lib/locomotive/steam/liquid/tags/link_to.rb +2 -1
  51. data/lib/locomotive/steam/liquid/tags/locale_switcher.rb +25 -21
  52. data/lib/locomotive/steam/liquid/tags/model_form.rb +38 -17
  53. data/lib/locomotive/steam/liquid/tags/nav.rb +4 -4
  54. data/lib/locomotive/steam/liquid/tags/page_not_found.rb +19 -0
  55. data/lib/locomotive/steam/liquid/tags/paginate.rb +13 -7
  56. data/lib/locomotive/steam/liquid/tags/path_to.rb +1 -0
  57. data/lib/locomotive/steam/liquid/tags/redirect_to.rb +34 -0
  58. data/lib/locomotive/steam/liquid/tags/section.rb +34 -33
  59. data/lib/locomotive/steam/liquid/tags/sections_dropzone.rb +1 -1
  60. data/lib/locomotive/steam/liquid/tags/seo.rb +2 -4
  61. data/lib/locomotive/steam/liquid/tags/session_assign.rb +1 -0
  62. data/lib/locomotive/steam/liquid/tags/snippet.rb +21 -29
  63. data/lib/locomotive/steam/liquid/tags/with_scope.rb +61 -27
  64. data/lib/locomotive/steam/liquid.rb +3 -1
  65. data/lib/locomotive/steam/middlewares/cache.rb +117 -0
  66. data/lib/locomotive/steam/middlewares/concerns/helpers.rb +22 -8
  67. data/lib/locomotive/steam/middlewares/concerns/liquid_context.rb +5 -1
  68. data/lib/locomotive/steam/middlewares/concerns/rendering.rb +53 -0
  69. data/lib/locomotive/steam/middlewares/impersonated_entry.rb +4 -0
  70. data/lib/locomotive/steam/middlewares/locale.rb +2 -2
  71. data/lib/locomotive/steam/middlewares/locale_redirection.rb +1 -1
  72. data/lib/locomotive/steam/middlewares/logging.rb +1 -0
  73. data/lib/locomotive/steam/middlewares/page_not_found.rb +37 -0
  74. data/lib/locomotive/steam/middlewares/redirection.rb +1 -1
  75. data/lib/locomotive/steam/middlewares/renderer.rb +4 -26
  76. data/lib/locomotive/steam/middlewares/thread_safe.rb +0 -4
  77. data/lib/locomotive/steam/models/pager.rb +1 -0
  78. data/lib/locomotive/steam/server.rb +3 -1
  79. data/lib/locomotive/steam/services/action_service.rb +5 -0
  80. data/lib/locomotive/steam/services/auth_service.rb +9 -9
  81. data/lib/locomotive/steam/services/cookie_service.rb +1 -0
  82. data/lib/locomotive/steam/services/external_api_service.rb +5 -0
  83. data/lib/locomotive/steam/services/liquid_parser_service.rb +4 -2
  84. data/lib/locomotive/steam/services/page_finder_service.rb +1 -1
  85. data/lib/locomotive/steam/services/recaptcha_service.rb +4 -2
  86. data/lib/locomotive/steam/version.rb +1 -1
  87. data/lib/locomotive/steam.rb +5 -1
  88. data/locomotivecms_steam.gemspec +4 -4
  89. data/spec/fixtures/default/app/views/pages/basic.liquid.haml +1 -0
  90. data/spec/fixtures/default/app/views/pages/music.liquid.haml +6 -0
  91. data/spec/fixtures/default/app/views/sections/carousel.liquid +15 -16
  92. data/spec/fixtures/default/app/views/sections/footer.liquid +37 -3
  93. data/spec/fixtures/default/app/views/sections/header.liquid +47 -10
  94. data/spec/fixtures/default/app/views/sections/misc/hero.liquid +28 -0
  95. data/spec/fixtures/default/config/metafields_schema.yml +3 -0
  96. data/spec/integration/liquid/tags/section_spec.rb +82 -0
  97. data/spec/integration/repositories/content_entry_repository_spec.rb +9 -0
  98. data/spec/integration/server/basic_spec.rb +2 -2
  99. data/spec/integration/server/metafields_spec.rb +1 -0
  100. data/spec/integration/services/content_entry_service_spec.rb +12 -0
  101. data/spec/support/helpers.rb +1 -0
  102. data/spec/support/liquid.rb +32 -2
  103. data/spec/support/mongo.rb +1 -0
  104. data/spec/unit/adapters/filesystem/sanitizers/section_spec.rb +66 -40
  105. data/spec/unit/adapters/filesystem/yaml_loaders/section_spec.rb +25 -0
  106. data/spec/unit/errors_spec.rb +1 -1
  107. data/spec/unit/liquid/drops/content_entry_collection_spec.rb +3 -3
  108. data/spec/unit/liquid/drops/content_entry_spec.rb +4 -4
  109. data/spec/unit/liquid/drops/content_types_spec.rb +2 -2
  110. data/spec/unit/liquid/drops/metafields_spec.rb +8 -8
  111. data/spec/unit/liquid/drops/params_spec.rb +5 -5
  112. data/spec/unit/liquid/drops/section_content_proxy_spec.rb +69 -18
  113. data/spec/unit/liquid/drops/section_spec.rb +1 -1
  114. data/spec/unit/liquid/file_system_spec.rb +25 -0
  115. data/spec/unit/liquid/filters/array_spec.rb +140 -0
  116. data/spec/unit/liquid/filters/misc_spec.rb +21 -3
  117. data/spec/unit/liquid/filters/number_spec.rb +4 -4
  118. data/spec/unit/liquid/filters/text_spec.rb +4 -0
  119. data/spec/unit/liquid/tags/alt_page_links_spec.rb +19 -2
  120. data/spec/unit/liquid/tags/authorize_spec.rb +1 -1
  121. data/spec/unit/liquid/tags/editable/text_spec.rb +32 -4
  122. data/spec/unit/liquid/tags/extends_spec.rb +115 -28
  123. data/spec/unit/liquid/tags/global_section_spec.rb +4 -3
  124. data/spec/unit/liquid/tags/google_analytics_spec.rb +21 -2
  125. data/spec/unit/liquid/tags/inherited_block_spec.rb +18 -4
  126. data/spec/unit/liquid/tags/inline_editor_spec.rb +11 -0
  127. data/spec/unit/liquid/tags/link_to_spec.rb +1 -1
  128. data/spec/unit/liquid/tags/model_form_spec.rb +7 -0
  129. data/spec/unit/liquid/tags/page_not_found_spec.rb +14 -0
  130. data/spec/unit/liquid/tags/redirect_to_spec.rb +171 -0
  131. data/spec/unit/liquid/tags/section_spec.rb +43 -3
  132. data/spec/unit/liquid/tags/sections_dropzone_spec.rb +0 -1
  133. data/spec/unit/liquid/tags/snippet_spec.rb +9 -8
  134. data/spec/unit/liquid/tags/with_scope_spec.rb +80 -60
  135. data/spec/unit/middlewares/cache_spec.rb +186 -0
  136. data/spec/unit/middlewares/impersonated_entry_spec.rb +7 -0
  137. data/spec/unit/middlewares/locale_redirection_spec.rb +7 -0
  138. data/spec/unit/middlewares/locale_spec.rb +8 -1
  139. data/spec/unit/middlewares/page_not_found_spec.rb +46 -0
  140. data/spec/unit/middlewares/redirection_spec.rb +8 -0
  141. data/spec/unit/middlewares/renderer_spec.rb +64 -6
  142. data/spec/unit/middlewares/section_spec.rb +1 -0
  143. data/spec/unit/models/pager_spec.rb +11 -1
  144. data/spec/unit/repositories/section_repository_spec.rb +1 -1
  145. data/spec/unit/services/action_service_spec.rb +23 -3
  146. data/spec/unit/services/page_redirection_service_spec.rb +2 -2
  147. data/spec/unit/services/recaptcha_service_spec.rb +1 -1
  148. metadata +50 -24
@@ -5,29 +5,33 @@ module Locomotive
5
5
  module Concerns
6
6
  module Path
7
7
 
8
- Syntax = /(#{::Liquid::VariableSignature}+)(\s*,.+)?/o
8
+ Syntax = /(#{::Liquid::QuotedFragment}+)(\s*,.+)?/o
9
+
10
+ attr_reader :handle
9
11
 
10
12
  def initialize(tag_name, markup, options)
11
- if markup =~ Syntax
12
- @handle, _options = $1, $2
13
+ super
13
14
 
14
- # FIXME: the with option needs a string with quotes.
15
- # this is a hack for sites which don't follow the new syntax.
16
- make_options_compatible_with_previous_version(_options)
15
+ if markup =~ Syntax
16
+ @handle, _attributes = $1, $2
17
17
 
18
- @raw_path_options = parse_options_from_string(_options)
18
+ parse_attributes(_attributes)
19
19
  else
20
20
  self.wrong_syntax!
21
21
  end
22
-
23
- super
24
22
  end
25
23
 
26
24
  def render_path(context, &block)
25
+ evaluate_attributes(context)
26
+
27
27
  set_vars_from_context(context)
28
28
 
29
- # return a drop or model?
30
- if page = self.retrieve_page_drop_from_handle
29
+ handle = @context[@handle] || @handle
30
+
31
+ # is external url?
32
+ if handle =~ Locomotive::Steam::IsHTTP
33
+ handle
34
+ elsif page = self.retrieve_page_drop_from_handle(handle) # return a drop or model?
31
35
  # make sure we've got the page/content entry (if templatized)
32
36
  # in the right locale
33
37
  change_page_locale(locale, page) do
@@ -50,9 +54,7 @@ module Locomotive
50
54
  services.repositories.page
51
55
  end
52
56
 
53
- def retrieve_page_drop_from_handle
54
- handle = @context[@handle] || @handle
55
-
57
+ def retrieve_page_drop_from_handle(handle)
56
58
  case handle
57
59
  when String
58
60
  _retrieve_page_drop_from(handle)
@@ -84,34 +86,19 @@ module Locomotive
84
86
  end
85
87
 
86
88
  def locale
87
- @path_options[:locale] || @raw_locale || @locale
89
+ attributes[:locale] || raw_attributes[:locale] || @locale
88
90
  end
89
91
 
90
92
  def template_slug
91
- @path_options[:with] || @raw_with
93
+ attributes[:with] || raw_attributes[:with]
92
94
  end
93
95
 
94
96
  def set_vars_from_context(context)
95
97
  @context = context
96
- @path_options = evaluate_path_options(context)
97
98
  @site = context.registers[:site]
98
99
  @locale = context.registers[:locale]
99
100
  end
100
101
 
101
- def evaluate_path_options(context)
102
- interpolate_options(@raw_path_options, context)
103
- end
104
-
105
- def make_options_compatible_with_previous_version(options)
106
- if options
107
- %w(with locale).each do |name|
108
- if options =~ /#{name}: ([\w-]+)/
109
- instance_variable_set(:"@raw_#{name}", $1);
110
- end
111
- end
112
- end
113
- end
114
-
115
102
  end
116
103
  end
117
104
  end
@@ -17,8 +17,8 @@ module Locomotive::Steam::Liquid::Tags::Concerns
17
17
 
18
18
  begin
19
19
  _render(context, template)
20
- rescue Locomotive::Steam::ParsingRenderingError => e
21
- e.file = section.name + ' [Section]'
20
+ rescue Locomotive::Steam::TemplateError => e
21
+ e.template_name = "sections--#{section.name}"
22
22
  raise e
23
23
  end
24
24
  end
@@ -29,14 +29,25 @@ module Locomotive::Steam::Liquid::Tags::Concerns
29
29
  editor_settings_lookup(template.root)
30
30
  end
31
31
 
32
- html = template.render(context)
32
+ html = template.render(context)
33
+
34
+ # by default, Steam will wrap the section HTML to make sure it has all the
35
+ # DOM attributes the live editing editor needs.
36
+ if context['is_section_locomotive_attributes_displayed']
37
+ html
38
+ else
39
+ wrap_html(html, context)
40
+ end
41
+ end
42
+
43
+ def wrap_html(html, context)
33
44
  section = context['section']
34
45
  css_class = context['section_css_class']
35
46
 
36
47
  # we need the section_css_class once
37
- context.scopes.last.delete('section_css_class')
48
+ # context.scopes.last.delete('section_css_class')
38
49
 
39
- anchor_id = %(id="#{section.anchor}-section")
50
+ anchor_id = %(id="#{section.anchor_id}")
40
51
  tag_id = %(id="locomotive-section-#{section.id}")
41
52
  tag_class = %(class="#{['locomotive-section', section.css_class, css_class].compact.join(' ')}")
42
53
  tag_data = %(data-locomotive-section-type="#{section.type}")
@@ -49,13 +60,13 @@ module Locomotive::Steam::Liquid::Tags::Concerns
49
60
  # - once found, get the closest tag
50
61
  # - add custom data attributes to it
51
62
  def editor_settings_lookup(root)
63
+ return if root.nodelist.blank?
64
+
52
65
  previous_node = nil
53
66
  new_nodelist = []
54
67
 
55
- return if root.nodelist.blank?
56
-
57
68
  root.nodelist.each_with_index do |node, index|
58
- if node.is_a?(::Liquid::Variable) && previous_node.is_a?(::Liquid::Token)
69
+ if node.is_a?(::Liquid::Variable) && previous_node.is_a?(String)
59
70
  matches = node.raw.match(Locomotive::Steam::SECTIONS_SETTINGS_VARIABLE_REGEXP)
60
71
 
61
72
  # is a section setting variable?
@@ -66,11 +77,11 @@ module Locomotive::Steam::Liquid::Tags::Concerns
66
77
  # here we go, add a liquid variable!
67
78
  new_nodelist.push(::Liquid::Variable.new(
68
79
  "section.editor_setting_data.#{matches[:id]}",
69
- node.instance_variable_get(:@options))
80
+ node.parse_context)
70
81
  )
71
82
 
72
83
  # close the tag
73
- new_nodelist.push(::Liquid::Token.new('>', previous_node.line_number))
84
+ new_nodelist.push('>') #::Liquid::Tokenizer.new('>', previous_node.line_number))
74
85
  end
75
86
  elsif node.respond_to?(:nodelist)
76
87
  editor_settings_lookup(node)
@@ -90,7 +101,7 @@ module Locomotive::Steam::Liquid::Tags::Concerns
90
101
  previous_node = nodelist[index - 1]
91
102
  next_node = nodelist[index + 1]
92
103
 
93
- return false unless next_node.is_a?(::Liquid::Token)
104
+ return false unless next_node.is_a?(String)
94
105
 
95
106
  (previous_node =~ /\>\s*\z/).present? && (next_node =~ /\A\s*\</).present?
96
107
  end
@@ -15,68 +15,61 @@ module Locomotive
15
15
  #
16
16
  class Consume < ::Liquid::Block
17
17
 
18
- Syntax = /(#{::Liquid::VariableSignature}+)\s*from\s*(#{::Liquid::QuotedString}|#{::Liquid::VariableSignature}+)(.*)?/o
18
+ include Concerns::Attributes
19
+
20
+ Syntax = /(#{::Liquid::VariableSignature}+)\s*from\s*(#{::Liquid::QuotedFragment}+),?(.+)?/o.freeze
21
+
22
+ attr_reader :variable_name, :url, :expires_in
19
23
 
20
24
  def initialize(tag_name, markup, options)
25
+ super
26
+
21
27
  if markup =~ Syntax
22
- @name = $1.to_s
28
+ @variable_name, @url, attributes = $1.to_s, ::Liquid::Expression.parse($2), $3
23
29
 
24
- self.prepare_url($2)
25
- @default_api_options = parse_options_from_string($3)
30
+ parse_attributes(attributes)
26
31
  else
27
32
  raise ::Liquid::SyntaxError.new("Syntax Error in 'consume' - Valid syntax: consume <var> from \"<url>\" [username: value, password: value]")
28
33
  end
29
-
30
- super
31
34
  end
32
35
 
33
36
  def render(context)
34
- self.set_api_options(context)
37
+ evaluate_attributes(context)
35
38
 
36
- if instance_variable_defined?(:@variable_name)
37
- @url = context[@variable_name]
38
- end
39
+ # attributes will become the options which will be passed to the service.
40
+ # we don't want the expires_in option to be part of it.
41
+ @expires_in = attributes.delete(:expires_in)&.to_i
39
42
 
40
- if @url.blank?
43
+ # the URL can come from a variable
44
+ @url = context.evaluate(url)
45
+
46
+ if url.blank?
41
47
  Locomotive::Common::Logger.error "A consume tag can't call an empty URL."
42
48
  ''
43
49
  else
44
- render_all_and_cache_it(context)
50
+ render_all_and_cache_it(context) { |_context| super(_context) }
45
51
  end
46
52
  end
47
53
 
48
54
  protected
49
55
 
50
- def prepare_url(token)
51
- if token.match(::Liquid::QuotedString)
52
- @url = token.gsub(/['"]/, '')
53
- else
54
- @variable_name = token
55
- end
56
- end
57
-
58
- def set_api_options(context)
59
- @api_options = interpolate_options(@default_api_options, context)
60
- @expires_in = @api_options.delete(:expires_in).try(:to_i)
61
- end
62
-
63
- def render_all_and_cache_it(context)
56
+ def render_all_and_cache_it(context, &block)
64
57
  cache_service(context).fetch(page_fragment_cache_key, cache_options) do
65
- self.render_all_without_cache(context)
58
+ self.render_all_without_cache(context, &block)
66
59
  end
67
60
  end
68
61
 
69
62
  def render_all_without_cache(context)
70
63
  context.stack do
71
64
  begin
72
- Locomotive::Common::Logger.info "[consume] #{@url.inspect} / #{@api_options.inspect}"
65
+ Locomotive::Common::Logger.info "[consume] #{url.inspect} / #{attributes.inspect}"
73
66
 
74
- context.scopes.last[@name] = service(context).consume(@url, @api_options)
67
+ context.scopes.last[variable_name] = service(context).consume(url, attributes)
75
68
  rescue Timeout::Error, Errno::ETIMEDOUT
76
- context.scopes.last[@name] = last_response(context)
69
+ context.scopes.last[variable_name] = last_response(context)
77
70
  end
78
71
 
79
- @body.render(context)
72
+ yield(context)
80
73
  end
81
74
  end
82
75
 
@@ -89,7 +82,7 @@ module Locomotive
89
82
  end
90
83
 
91
84
  def cache_options
92
- @expires_in.blank? || @expires_in == 0 ? { force: true } : { expires_in: @expires_in }
85
+ expires_in.blank? || expires_in == 0 ? { force: true } : { expires_in: expires_in }
93
86
  end
94
87
 
95
88
  def last_response(context)
@@ -97,7 +90,7 @@ module Locomotive
97
90
  end
98
91
 
99
92
  def page_fragment_cache_key
100
- "Steam-consume-#{Digest::SHA1.hexdigest(@name + @url)}"
93
+ "Steam-consume-#{Digest::SHA1.hexdigest(variable_name + url)}"
101
94
  end
102
95
 
103
96
  end
@@ -5,12 +5,12 @@ module Locomotive
5
5
  module Csrf
6
6
 
7
7
  class Base < ::Liquid::Tag
8
+
8
9
  def render(context)
9
- service = context.registers[:services].csrf_protection
10
+ service = context.registers[:services].csrf_protection
10
11
 
11
12
  if service.enabled?
12
13
  render_csrf(service)
13
-
14
14
  else
15
15
  ''
16
16
  end
@@ -5,18 +5,20 @@ module Locomotive
5
5
  module Editable
6
6
  class Base < ::Liquid::Block
7
7
 
8
+ include Concerns::Attributes
9
+
8
10
  Syntax = /(#{::Liquid::QuotedFragment})(\s*,\s*#{::Liquid::Expression}+)?/o
9
11
 
10
- attr_accessor :slug
12
+ attr_accessor :label, :slug, :page_fullpath
11
13
 
12
14
  def initialize(tag_name, markup, options)
13
15
  if markup =~ Syntax
14
16
  @page_fullpath = options[:page].fullpath
15
17
  @label_or_slug = $1.gsub(/[\"\']/, '')
16
- @element_options = { fixed: false, inline_editing: true }
17
- markup.scan(::Liquid::TagAttributes) { |key, value| @element_options[key.to_sym] = value.gsub(/^[\"\']/, '').gsub(/[\"\']$/, '') }
18
18
 
19
- self.set_label_and_slug
19
+ parse_attributes(markup, fixed: false, inline_editing: true)
20
+
21
+ set_label_and_slug
20
22
  else
21
23
  raise ::Liquid::SyntaxError.new("Valid syntax: #{tag_name} <slug>(, <options>)")
22
24
  end
@@ -35,14 +37,22 @@ module Locomotive
35
37
  alias :default_render :render
36
38
 
37
39
  def render(context)
40
+ evaluate_attributes(context)
41
+
38
42
  service = context.registers[:services].editable_element
39
43
  page = fetch_page(context)
40
- block = @element_options[:block] || context['block'].try(:name)
44
+ block = attributes[:block] || context['block'].try(:name)
45
+
46
+ # If Steam inside Wagon (test mode), we've to let the developer know
47
+ # that editable_**** tags don't work if the site has declared at least one section
48
+ if context['wagon'] && context.registers[:repositories].section.count > 0
49
+ Locomotive::Common::Logger.error "[#{page.fullpath}] You can't use editable elements whereas you declared section(s)".colorize(:red)
50
+ end
41
51
 
42
- if element = service.find(page, block, @slug)
52
+ if element = service.find(page, block, slug)
43
53
  render_element(context, element)
44
54
  else
45
- Locomotive::Common::Logger.error "[#{page.fullpath}] missing #{@tag_name} \"#{@slug}\" (#{context['block'].try(:name) || 'default'})"
55
+ Locomotive::Common::Logger.error "[#{page.fullpath}] missing #{@tag_name} \"#{slug}\" (#{context['block'].try(:name) || 'default'})".colorize(:yellow)
46
56
  super
47
57
  end
48
58
  end
@@ -74,12 +84,12 @@ module Locomotive
74
84
  def fetch_page(context)
75
85
  page = context.registers[:page]
76
86
 
77
- return page if !@element_options[:fixed] || page.fullpath == @page_fullpath
87
+ return page if !attributes[:fixed] || page.fullpath == page_fullpath
78
88
 
79
89
  pages = context.registers[:pages] ||= {}
80
90
  service = context.registers[:services].page_finder
81
91
 
82
- pages[@page_fullpath] ||= service.find(@page_fullpath)
92
+ pages[page_fullpath] ||= service.find(page_fullpath)
83
93
  end
84
94
 
85
95
  def register_default_content
@@ -93,10 +103,10 @@ module Locomotive
93
103
 
94
104
  def set_label_and_slug
95
105
  @slug = @label_or_slug
96
- @label = @element_options[:label]
106
+ @label = attributes[:label]
97
107
 
98
- if @element_options[:slug].present?
99
- @slug = @element_options[:slug]
108
+ if attributes[:slug].present?
109
+ @slug = attributes[:slug]
100
110
  @label ||= @label_or_slug
101
111
  end
102
112
  end
@@ -104,24 +114,24 @@ module Locomotive
104
114
  def default_element_attributes
105
115
  {
106
116
  block: self.current_inherited_block_name,
107
- label: @label,
108
- slug: @slug,
109
- hint: @element_options[:hint],
110
- priority: @element_options[:priority] || 0,
111
- fixed: [true, 'true'].include?(@element_options[:fixed]),
117
+ label: label,
118
+ slug: slug,
119
+ hint: attributes[:hint],
120
+ priority: attributes[:priority] || 0,
121
+ fixed: [true, 'true'].include?(attributes[:fixed]),
112
122
  disabled: false,
113
- inline_editing: [true, 'true'].include?(@element_options[:inline_editing]),
123
+ inline_editing: [true, 'true'].include?(attributes[:inline_editing]),
114
124
  from_parent: false,
115
125
  type: @tag_name.to_sym
116
126
  }
117
127
  end
118
128
 
119
129
  def current_inherited_block_name
120
- @element_options[:block] || current_inherited_block.try(:name)
130
+ attributes[:block] || current_inherited_block.try(:name)
121
131
  end
122
132
 
123
133
  def current_inherited_block
124
- options[:inherited_blocks].try(:[], :nested).try(:last)
134
+ parse_context[:inherited_blocks].try(:[], :nested).try(:last)
125
135
  end
126
136
 
127
137
  #:nocov:
@@ -10,12 +10,12 @@ module Locomotive
10
10
  def default_element_attributes
11
11
  super.merge({
12
12
  content_from_default: self.render_default_content,
13
- options: @element_options[:options]
13
+ options: attributes[:options]
14
14
  })
15
15
  end
16
16
 
17
17
  def render_element(context, element)
18
- element.content
18
+ element.content.to_s
19
19
  end
20
20
 
21
21
  def render_default_content
@@ -7,7 +7,7 @@ module Locomotive
7
7
 
8
8
  def parse(tokens)
9
9
  super.tap do
10
- @path = [current_inherited_block_name, @slug].compact.join('--').gsub('/', '--')
10
+ @path = [current_inherited_block_name, slug].compact.join('--').gsub('/', '--')
11
11
  end
12
12
  end
13
13
 
@@ -20,7 +20,7 @@ module Locomotive
20
20
  def default_element_attributes
21
21
  super.merge({
22
22
  default_source_url: render_default_content.strip,
23
- resize_format: @element_options[:resize]
23
+ resize_format: attributes[:resize]
24
24
  })
25
25
  end
26
26
 
@@ -54,23 +54,23 @@ module Locomotive
54
54
 
55
55
  def apply_transformation(url, context)
56
56
  # resize image with the image_resizer service?
57
- if (format = @element_options[:resize]).present?
57
+ if (format = attributes[:resize]).present?
58
58
  options = []
59
59
 
60
- @element_options.each do |k, v|
61
- options << case k.to_sym
60
+ attributes.each do |key, value|
61
+ options << case key.to_sym
62
62
  when :quality
63
- "-quality #{v}"
63
+ "-quality #{value}"
64
64
  when :optimize # Shortcut helper to set quality, progressive and strip
65
- "-quality #{v} -strip -interlace Plane"
65
+ "-quality #{value} -strip -interlace Plane"
66
66
  when :auto_orient
67
- "-auto-orient" if v.downcase == "true"
67
+ "-auto-orient" if value
68
68
  when :strip
69
- "-strip" if v.downcase == "true"
69
+ "-strip" if value
70
70
  when :progressive
71
- "-interlace Plane" if v.downcase == "true"
71
+ "-interlace Plane" if value
72
72
  when :filters
73
- v
73
+ value
74
74
  else
75
75
  next
76
76
  end
@@ -42,16 +42,16 @@ module Locomotive
42
42
  def default_element_attributes
43
43
  super.merge(
44
44
  content_from_default: self.render_default_content,
45
- format: @element_options[:format] || 'html',
46
- rows: @element_options[:rows] || 10,
47
- inline: @element_options[:inline],
48
- line_break: @element_options[:line_break].blank? ? true : @element_options[:line_break],
45
+ format: attributes[:format] || 'html',
46
+ rows: attributes[:rows] || 10,
47
+ inline: attributes[:inline],
48
+ line_break: attributes[:line_break].blank? ? true : attributes[:line_break],
49
49
  )
50
50
  end
51
51
 
52
52
  def dom_id(context)
53
53
  block_name = context['block'].try(:name).try(:gsub, '/', '-')
54
- ['locomotive-editable-text', block_name, @slug].compact.join('-')
54
+ ['locomotive-editable-text', block_name, slug].compact.join('-')
55
55
  end
56
56
 
57
57
  def markdown_service(context)
@@ -2,7 +2,45 @@ module Locomotive
2
2
  module Steam
3
3
  module Liquid
4
4
  module Tags
5
- class Extends < ::Liquid::Extends
5
+
6
+ # Extends allows designer to use template inheritance.
7
+ #
8
+ # {% extends home %}
9
+ # {% block content }Hello world{% endblock %}
10
+ #
11
+ class Extends < ::Liquid::Block
12
+ SYNTAX = /(#{::Liquid::QuotedFragment}+)/o
13
+
14
+ def initialize(tag_name, markup, options)
15
+ super
16
+
17
+ if markup =~ SYNTAX
18
+ @template_name = Regexp.last_match(1).gsub(/["']/o, '').strip
19
+ else
20
+ raise ::Liquid::SyntaxError.new("Syntax Error in 'extends' - Valid syntax: extends <page_handle_or_parent_keyword>")
21
+ end
22
+
23
+ # variables needed by the inheritance mechanism during the parsing
24
+ options[:inherited_blocks] ||= {
25
+ nested: [], # used to get the full name of the blocks if nested (stack mechanism)
26
+ all: {}, # keep track of the blocks by their full name
27
+ }
28
+ end
29
+
30
+ def parse(tokens)
31
+ super
32
+
33
+ parent_template = parse_parent_template
34
+
35
+ # replace the nodes of the current template by those from the parent
36
+ # which itself may have have done the same operation if it includes
37
+ # the extends tag.
38
+ nodelist.replace(parent_template.root.nodelist)
39
+ end
40
+
41
+ def blank?
42
+ false
43
+ end
6
44
 
7
45
  def render(context)
8
46
  context.stack do
@@ -11,27 +49,37 @@ module Locomotive
11
49
  end
12
50
  end
13
51
 
14
- private
52
+ protected
53
+
54
+ def parse_body(body, tokens)
55
+ body.parse(tokens, options) do |end_tag_name, _|
56
+ @blank &&= body.blank?
57
+
58
+ # Note: extends does not require the "end tag".
59
+ return false if end_tag_name.nil?
60
+ end
61
+
62
+ true
63
+ end
15
64
 
16
65
  def parse_parent_template
17
- parent = options[:parent_finder].find(options[:page], @template_name)
66
+ parent = parse_context[:parent_finder].find(parse_context[:page], @template_name)
18
67
 
19
68
  # no need to go further if the parent does not exist
20
- raise PageNotFound.new("Extending a missing page. Page/Layout with fullpath '#{@template_name}' was not found") if parent.nil?
69
+ raise Liquid::PageNotFound.new("Extending a missing page. Page/Layout with fullpath '#{@template_name}' was not found") if parent.nil?
21
70
 
22
- ActiveSupport::Notifications.instrument('steam.parse.extends', page: options[:page], parent: parent)
71
+ ActiveSupport::Notifications.instrument('steam.parse.extends', page: parse_context[:page], parent: parent)
23
72
 
24
73
  # define the layout name which is basically the handle of the parent page
25
74
  # if there is no handle, we take the slug which might or might not be localized.
26
75
  @layout_name = parent.handle || parent.slug
27
76
 
28
77
  # the source has already been parsed before
29
- options[:parser]._parse(parent, options.merge(page: parent))
78
+ parse_context[:parser]._parse(parent, parse_context.merge(page: parent))
30
79
  end
31
-
32
80
  end
33
81
 
34
- ::Liquid::Template.register_tag('extends'.freeze, Extends)
82
+ ::Liquid::Template.register_tag('extends', Extends)
35
83
  end
36
84
  end
37
85
  end
@@ -5,22 +5,22 @@ module Locomotive
5
5
  class GlobalSection < Locomotive::Steam::Liquid::Tags::Section
6
6
 
7
7
  def parse(tokens)
8
- notify_on_parsing(evaluate_section_name,
8
+ notify_on_parsing(section_type,
9
9
  source: :site,
10
- id: "site-#{evaluate_section_name}",
11
- key: evaluate_section_name,
12
- placement: @section_options[:placement]&.to_sym
10
+ id: "site-#{section_type}",
11
+ key: section_type,
12
+ placement: attributes[:placement]&.to_sym
13
13
  )
14
14
  end
15
15
 
16
16
  private
17
17
 
18
18
  def find_section_content(context)
19
- context['site']&.sections_content&.fetch(@section_type, nil)
19
+ context['site']&.sections_content&.fetch(section_type, nil)
20
20
  end
21
21
 
22
22
  def set_section_dom_id(context)
23
- context['section_id'] = "site-#{@section_type}"
23
+ context['section_id'] = "site-#{section_type}"
24
24
  end
25
25
 
26
26
  end
@@ -2,18 +2,26 @@ module Locomotive
2
2
  module Steam
3
3
  module Liquid
4
4
  module Tags
5
- class GoogleAnalytics < ::Solid::Tag
5
+ class GoogleAnalytics < ::Liquid::Tag
6
6
 
7
- tag_name :google_analytics
7
+ Syntax = /(#{::Liquid::QuotedFragment}+)/o.freeze
8
8
 
9
- def display(account_id = nil)
10
- if account_id.blank?
11
- raise ::Liquid::SyntaxError.new("Syntax Error in 'google_analytics' - Valid syntax: google_analytics <account_id>")
9
+ attr_reader :account_id
10
+
11
+ def initialize(tag_name, markup, options)
12
+ super
13
+
14
+ if markup =~ Syntax
15
+ @account_id = ::Liquid::Expression.parse($1)
12
16
  else
13
- ga_snippet(account_id)
17
+ raise ::Liquid::SyntaxError.new("Syntax Error in 'google_analytics' - Valid syntax: google_analytics <account_id>")
14
18
  end
15
19
  end
16
20
 
21
+ def render(context)
22
+ ga_snippet(context.evaluate(account_id))
23
+ end
24
+
17
25
  private
18
26
 
19
27
  def ga_snippet(account_id)
@@ -32,6 +40,8 @@ module Locomotive
32
40
 
33
41
  end
34
42
 
43
+ ::Liquid::Template.register_tag('google_analytics'.freeze, GoogleAnalytics)
44
+
35
45
  end
36
46
  end
37
47
  end