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
@@ -18,19 +18,23 @@ module Locomotive
18
18
  end
19
19
  end
20
20
 
21
- def find_block_delimiter?(tokens)
22
- tokens.each do |token|
21
+ def find_block_delimiter?(tokenizer)
22
+ tokenizer.instance_variable_get(:@tokens).each do |token|
23
23
  next if token.empty?
24
24
  if token.start_with?(::Liquid::BlockBody::TAGSTART)
25
25
  if token =~ ::Liquid::BlockBody::FullToken
26
- return false if $1 == @tag_name
27
- return true if $1 == block_delimiter
26
+ return false if Regexp.last_match(1) == @tag_name
27
+ return true if Regexp.last_match(1) == block_delimiter
28
28
  end
29
29
  end
30
30
  end
31
31
  false
32
32
  end
33
33
 
34
+ def nodelist
35
+ @body&.nodelist || []
36
+ end
37
+
34
38
  end
35
39
 
36
40
  end
@@ -13,33 +13,111 @@ module Locomotive
13
13
  # - short_name (Boolean): use just the name and skip the name of the nested blocks.
14
14
  # - priority (Integer): allow blocks to be displayed before others
15
15
  #
16
- class InheritedBlock < ::Liquid::InheritedBlock
16
+ class InheritedBlock < ::Liquid::Block
17
+
18
+ include Concerns::Attributes
19
+
20
+ SYNTAX = /(#{::Liquid::QuotedFragment}+)/o
21
+
22
+ attr_reader :name
23
+
24
+ # linked chain of inherited blocks included
25
+ # in different templates if multiple extends
26
+ attr_accessor :parent, :descendant
17
27
 
18
28
  def initialize(tag_name, markup, options)
19
29
  super
20
30
 
21
- @attributes = { short_name: false, priority: 0, anchor: true }
22
- markup.scan(::Liquid::TagAttributes) do |key, value|
23
- @attributes[key.to_sym] = ::Liquid::Expression.parse(value)
31
+ if markup =~ SYNTAX
32
+ @name = Regexp.last_match(1).gsub(/["']/o, '').strip
33
+ else
34
+ raise ::Liquid::SyntaxError.new("Syntax Error in 'block' - Valid syntax: block <name>")
35
+ end
36
+
37
+ prepare_for_inheritance
38
+
39
+ parse_attributes(markup, short_name: false, priority: 0, anchor: true)
40
+ end
41
+
42
+ def prepare_for_inheritance
43
+ # give a different name if this is a nested block
44
+ if (block = inherited_blocks[:nested].last)
45
+ @name = "#{block.name}/#{@name}"
46
+ end
47
+
48
+ # append this block to the stack in order to
49
+ # get a name for the other nested inherited blocks
50
+ inherited_blocks[:nested].push(self)
51
+
52
+ # build the linked chain of inherited blocks
53
+ # make a link with the descendant and the parent (chained list)
54
+ if (descendant = inherited_blocks[:all][@name])
55
+ self.descendant = descendant
56
+ descendant.parent = self
57
+
58
+ # get the value of the blank property from the descendant
59
+ @blank = descendant.blank?
24
60
  end
61
+
62
+ # become the descendant of the inherited block from the parent template
63
+ inherited_blocks[:all][@name] = self
25
64
  end
26
65
 
27
66
  def parse(tokens)
28
- super.tap do
67
+ super
68
+
69
+ # when the parsing of the block is done, we can then remove it from the stack
70
+ inherited_blocks[:nested].pop.tap do
29
71
  ActiveSupport::Notifications.instrument('steam.parse.inherited_block', {
30
- page: options[:page],
31
- name: @name,
72
+ page: parse_context[:page],
73
+ name: name,
32
74
  found_super: self.contains_super?(nodelist)
33
- }.merge(@attributes))
75
+ }.merge(attributes))
34
76
  end
35
77
  end
36
78
 
79
+ alias_method :render_without_inheritance, :render
80
+
37
81
  def render(context)
38
- (if live_editing?(context) && (@attributes[:anchor] || @attributes[:anchor].nil?)
39
- %{<span class="locomotive-block-anchor" data-element-id="#{@name}" style="visibility: hidden"></span>}
82
+ context.stack do
83
+ # look for the very first descendant
84
+ block = self_or_first_descendant
85
+
86
+ # the block drop is in charge of rendering "{{ block.super }}"
87
+ context['block'] = Drops::InheritedBlock.new(block)
88
+
89
+ anchor_html = if live_editing?(context) && (attributes[:anchor] || attributes[:anchor].nil?)
90
+ %{<span class="locomotive-block-anchor" data-element-id="#{name}" style="visibility: hidden"></span>}
91
+ else
92
+ ''
93
+ end
94
+
95
+ anchor_html + block.render_without_inheritance(context)
96
+ end
97
+ end
98
+
99
+ # when we render an inherited block, we need the version of the
100
+ # very first descendant.
101
+ def self_or_first_descendant
102
+ block = self
103
+ while block.descendant; block = block.descendant; end
104
+ block
105
+ end
106
+
107
+ def call_super(context)
108
+ if parent
109
+ # remove the block from the linked chain
110
+ parent.descendant = nil
111
+
112
+ parent.render(context)
40
113
  else
41
114
  ''
42
- end) + super
115
+ end
116
+ end
117
+
118
+ def inherited_blocks
119
+ # initialize it in the case the template does not include an extend tag
120
+ options[:inherited_blocks] ||= { all: {}, nested: [] }
43
121
  end
44
122
 
45
123
  protected
@@ -71,10 +149,9 @@ module Locomotive
71
149
  def live_editing?(context)
72
150
  !!context.registers[:live_editing]
73
151
  end
74
-
75
152
  end
76
153
 
77
- ::Liquid::Template.register_tag('block'.freeze, InheritedBlock)
154
+ ::Liquid::Template.register_tag('block', InheritedBlock)
78
155
  end
79
156
  end
80
157
  end
@@ -8,17 +8,17 @@ module Locomotive
8
8
  #
9
9
  # @deprecated
10
10
  #
11
- class InlineEditor < Solid::Tag
11
+ class InlineEditor < ::Liquid::Tag
12
12
 
13
- tag_name :inline_editor
14
-
15
- def display
13
+ def render(context)
16
14
  Locomotive::Common::Logger.warn %(The inline_editor liquid tag is no more used.).yellow
17
15
  ''
18
16
  end
19
17
 
20
18
  end
21
19
 
20
+ ::Liquid::Template.register_tag('inline_editor'.freeze, InlineEditor)
21
+
22
22
  end
23
23
  end
24
24
  end
@@ -4,6 +4,7 @@ module Locomotive
4
4
  module Tags
5
5
  class LinkTo < Hybrid
6
6
 
7
+ include Concerns::Attributes
7
8
  include Concerns::I18nPage
8
9
  include Concerns::Path
9
10
 
@@ -40,7 +41,7 @@ module Locomotive
40
41
  end
41
42
 
42
43
  def css
43
- @path_options[:class]
44
+ attributes[:class]
44
45
  end
45
46
 
46
47
  end
@@ -20,14 +20,24 @@ module Locomotive
20
20
  # - " | " is the default separating code
21
21
  #
22
22
 
23
- class LocaleSwitcher < Solid::Tag
23
+ class LocaleSwitcher < ::Liquid::Tag
24
24
 
25
+ include Concerns::Attributes
25
26
  include Concerns::I18nPage
26
27
 
27
- tag_name :locale_switcher
28
+ attr_reader :attributes, :site, :page, :current_locale, :url_builder
29
+
30
+ def initialize(tag_name, markup, options)
31
+ super
32
+
33
+ parse_attributes(markup, label: 'iso', sep: ' | ')
34
+ end
35
+
36
+ def render(context)
37
+ evaluate_attributes(context)
38
+
39
+ set_vars_from_context(context)
28
40
 
29
- def display(*values)
30
- @options = { label: 'iso', sep: ' | ' }.merge(values.first || {})
31
41
  %{<div id="locale-switcher">#{build_site_locales}</div>}
32
42
  end
33
43
 
@@ -41,12 +51,12 @@ module Locomotive
41
51
 
42
52
  %(<a href="#{path}" class="#{css}">#{link_label(locale)}</a>)
43
53
  end
44
- end.join(@options[:sep])
54
+ end.join(attributes[:sep])
45
55
  end
46
56
 
47
57
  def link_class(locale)
48
58
  css = [locale]
49
- css << 'current' if locale.to_sym == current_locale.to_sym
59
+ css << 'current' if locale.to_sym == current_locale
50
60
  css.join(' ')
51
61
  end
52
62
 
@@ -55,7 +65,7 @@ module Locomotive
55
65
  end
56
66
 
57
67
  def link_label(locale)
58
- case @options[:label]
68
+ case attributes[:label]
59
69
  when 'locale' then I18n.t("locomotive.locales.#{locale}")
60
70
  when 'title' then page_title
61
71
  else
@@ -71,24 +81,18 @@ module Locomotive
71
81
  end
72
82
  end
73
83
 
74
- def site
75
- @site ||= current_context.registers[:site]
76
- end
77
-
78
- def page
79
- @page ||= current_context['page']
80
- end
81
-
82
- def url_builder
83
- current_context.registers[:services].url_builder
84
- end
85
-
86
- def current_locale
87
- @current_locale ||= current_context.registers[:locale]
84
+ def set_vars_from_context(context)
85
+ @context = context
86
+ @site = context.registers[:site]
87
+ @page = context['page']
88
+ @current_locale = context.registers[:locale].to_sym
89
+ @url_builder = context.registers[:services].url_builder
88
90
  end
89
91
 
90
92
  end
91
93
 
94
+ ::Liquid::Template.register_tag('locale_switcher'.freeze, LocaleSwitcher)
95
+
92
96
  end
93
97
  end
94
98
  end
@@ -16,27 +16,46 @@ module Locomotive
16
16
  #
17
17
  # {% model_form 'newsletter_addresses', class: 'a-css-class', success: 'http://www.google.fr', error: '/error' %}...{% endform_form %}
18
18
  #
19
- class ModelForm < Solid::Block
19
+ class ModelForm < ::Liquid::Block
20
20
 
21
- tag_name :model_form
21
+ include Concerns::Attributes
22
22
 
23
- def display(*options, &block)
24
- name = options.shift
25
- options = options.shift || {}
23
+ Syntax = /(#{::Liquid::QuotedFragment})\s*,*(.*)?/o.freeze
26
24
 
27
- form_attributes = prepare_form_attributes(options)
25
+ attr_reader :name
28
26
 
29
- html_content_tag :form,
30
- content_type_html(name) + csrf_html + callbacks_html(options) + recaptcha_html(options) + yield,
27
+ def initialize(tag_name, markup, options)
28
+ super
29
+
30
+ if markup =~ Syntax
31
+ @name, _attributes = $1, $2
32
+
33
+ parse_attributes(_attributes)
34
+ else
35
+ raise ::Liquid::SyntaxError.new("Syntax Error in 'model_form' - Valid syntax: model_form <content_type_slug>(, <attributes>)")
36
+ end
37
+ end
38
+
39
+ def render(context)
40
+ @name = context[name]
41
+
42
+ evaluate_attributes(context)
43
+
44
+ form_attributes = prepare_form_attributes(context, attributes)
45
+
46
+ html_content_tag(
47
+ :form,
48
+ content_type_html(name) + csrf_html(context) + callbacks_html(attributes) + recaptcha_html(attributes) + super,
31
49
  form_attributes
50
+ )
32
51
  end
33
52
 
34
53
  def content_type_html(name)
35
54
  html_tag :input, type: 'hidden', name: 'content_type_slug', value: name
36
55
  end
37
56
 
38
- def csrf_html
39
- service = current_context.registers[:services].csrf_protection
57
+ def csrf_html(context)
58
+ service = context.registers[:services].csrf_protection
40
59
 
41
60
  html_tag :input, type: 'hidden', name: service.field, value: service.token
42
61
  end
@@ -70,8 +89,8 @@ module Locomotive
70
89
  (options.stringify_keys.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ')
71
90
  end
72
91
 
73
- def prepare_form_attributes(options)
74
- url = action_url(options)
92
+ def prepare_form_attributes(context, options)
93
+ url = action_url(context, options)
75
94
  attributes = options.slice(:id, :class, :name, :novalidate)
76
95
 
77
96
  { method: 'POST', enctype: 'multipart/form-data' }.merge(attributes).tap do |_attributes|
@@ -79,28 +98,30 @@ module Locomotive
79
98
  end
80
99
  end
81
100
 
82
- def action_url(options)
101
+ def action_url(context, options)
83
102
  url = options[:action]
84
103
 
85
104
  if url.blank?
86
105
  if options[:json]
87
- url = current_context['path'].blank? ? '/' : current_context['path']
106
+ url = context['path'].blank? ? '/' : context['path']
88
107
  url + (url.ends_with?('/') ? 'index.json' : '.json')
89
108
  else
90
109
  nil
91
110
  end
92
111
  else
93
112
  url = '/' + url unless url.starts_with?('/')
94
- url_builder.prefix(url)
113
+ url_builder(context).prefix(url)
95
114
  end
96
115
  end
97
116
 
98
- def url_builder
99
- current_context.registers[:services].url_builder
117
+ def url_builder(context)
118
+ context.registers[:services].url_builder
100
119
  end
101
120
 
102
121
  end
103
122
 
123
+ ::Liquid::Template.register_tag('model_form'.freeze, ModelForm)
124
+
104
125
  end
105
126
  end
106
127
  end
@@ -34,14 +34,14 @@ module Locomotive
34
34
  set_template_if_asked
35
35
 
36
36
  # get all the children of a source: site (index page), parent or page.
37
- pages = children_of(fetch_starting_page)
38
- output = self.build_entries_output(pages, context)
37
+ pages = children_of(fetch_starting_page)
38
+ _output = self.build_entries_output(pages, context)
39
39
 
40
40
  if self.no_wrapper?
41
- output
41
+ _output
42
42
  else
43
43
  self.render_tag(:nav, id: @_options[:id], css: @_options[:class]) do
44
- self.render_tag(:ul) { output }
44
+ self.render_tag(:ul) { _output }
45
45
  end
46
46
  end
47
47
  end
@@ -0,0 +1,19 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Liquid
4
+ module Tags
5
+
6
+ class PageNotFound < ::Liquid::Tag
7
+
8
+ def render(context)
9
+ raise Locomotive::Steam::PageNotFoundException.new
10
+ end
11
+
12
+ end
13
+
14
+ ::Liquid::Template.register_tag('render_page_not_found'.freeze, PageNotFound)
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -15,14 +15,18 @@ module Locomotive
15
15
  #
16
16
  class Paginate < ::Liquid::Block
17
17
 
18
+ include Concerns::Attributes
19
+
18
20
  Syntax = /(#{::Liquid::QuotedFragment}+)\s+by\s+(#{::Liquid::QuotedFragment}+)/o
19
21
 
22
+ attr_reader :collection_name, :per_page
23
+
20
24
  def initialize(tag_name, markup, options)
21
25
  if markup =~ Syntax
22
26
  @collection_name = $1
23
27
  @per_page = $2
24
- @paginate_options = {}
25
- markup.scan(::Liquid::TagAttributes) { |key, value| @paginate_options[key.to_sym] = value.gsub(/^'/, '').gsub(/'$/, '') }
28
+
29
+ parse_attributes(markup)
26
30
  else
27
31
  raise ::Liquid::SyntaxError.new('Valid syntax: paginate <collection> by <number>')
28
32
  end
@@ -31,6 +35,8 @@ module Locomotive
31
35
  end
32
36
 
33
37
  def render(context)
38
+ evaluate_attributes(context)
39
+
34
40
  context.stack do
35
41
  pagination = context['paginate'] = paginate_collection(context)
36
42
 
@@ -53,11 +59,11 @@ module Locomotive
53
59
  # collection.
54
60
  #
55
61
  def paginate_collection(context)
56
- collection = context[@collection_name]
57
- per_page = context[@per_page].to_i
62
+ collection = context[collection_name]
63
+ per_page = context[self.per_page].to_i
58
64
  current_page = context['current_page'].try(:to_i)
59
65
 
60
- raise ::Liquid::ArgumentError.new("Cannot paginate '#{@collection_name}'. Not found.") if collection.nil?
66
+ raise ::Liquid::ArgumentError.new("Cannot paginate '#{collection_name}'. Not found.") if collection.nil?
61
67
 
62
68
  pager = Locomotive::Steam::Models::Pager.new(collection, current_page, per_page)
63
69
 
@@ -117,7 +123,7 @@ module Locomotive
117
123
  end
118
124
 
119
125
  def window_size
120
- @window_size ||= @paginate_options[:window_size] ? @paginate_options[:window_size].to_i : 3
126
+ @window_size ||= attributes[:window_size] ? attributes[:window_size].to_i : 3
121
127
  end
122
128
 
123
129
  def no_link(title)
@@ -126,7 +132,7 @@ module Locomotive
126
132
 
127
133
  def link(title, page, path)
128
134
  _path = %(#{path}#{path.include?('?') ? '&' : '?'}page=#{page})
129
- { 'title' => title, 'url' => _path, 'is_link' => true }
135
+ { 'title' => title, 'url' => _path, 'is_link' => true, 'page' => page }
130
136
  end
131
137
  end
132
138
 
@@ -4,6 +4,7 @@ module Locomotive
4
4
  module Tags
5
5
  class PathTo < ::Liquid::Tag
6
6
 
7
+ include Concerns::Attributes
7
8
  include Concerns::I18nPage
8
9
  include Concerns::Path
9
10
 
@@ -0,0 +1,34 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Liquid
4
+ module Tags
5
+
6
+ class RedirectTo < ::Liquid::Tag
7
+
8
+ include Concerns::Attributes
9
+ include Concerns::I18nPage
10
+ include Concerns::Path
11
+
12
+ def render(context)
13
+ if (path = render_path(context)).present?
14
+ # 301 or 302 redirection
15
+ is_permanent = attributes[:permanent].nil? ? true : attributes[:permanent]
16
+
17
+ # break the rendering process
18
+ raise Locomotive::Steam::RedirectionException.new(path, permanent: is_permanent)
19
+ end
20
+ ''
21
+ end
22
+
23
+ def wrong_syntax!
24
+ raise SyntaxError.new("Valid syntax: redirect_to <page|page_handle|content_entry|external_url>(, locale: [fr|de|...], with: <page_handle>, permanent: [true|false]")
25
+ end
26
+
27
+ end
28
+
29
+ ::Liquid::Template.register_tag('redirect_to'.freeze, RedirectTo)
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -5,38 +5,43 @@ module Locomotive
5
5
  class Section < ::Liquid::Include
6
6
 
7
7
  include Concerns::Section
8
+ include Concerns::Attributes
9
+
10
+ Syntax = /(#{::Liquid::QuotedString}|#{::Liquid::VariableSignature}+)\s*,*(.*)?/o.freeze
11
+
12
+ attr_reader :section_type
8
13
 
9
14
  def initialize(tag_name, markup, options)
10
- if markup =~ /(#{::Liquid::QuotedString}|#{::Liquid::VariableSignature}+)\s*,*(.*)?/o
11
- @section_type, _options = $1, $2
12
- raw_options = parse_options_from_string(_options)
13
- @section_options = interpolate_options(raw_options, {})
14
- super
15
- else
16
- raise ::Liquid::SyntaxError.new("Syntax Error in 'section' - Valid syntax: section section_type, id: '<string>', placement: 'top|bottom' (id and placement are optional)")
15
+ super
16
+
17
+ if markup =~ Syntax
18
+ @section_type, _attributes = $1, $2
19
+ @template_name_expr = @section_type.gsub!(/['"]/, '')
20
+
21
+ parse_attributes(_attributes)
17
22
  end
18
23
  end
19
24
 
20
25
  def parse(tokens)
21
- notify_on_parsing(evaluate_section_name,
22
- id: "page-#{@section_options[:id] || evaluate_section_name}",
23
- key: (@section_options[:id] || evaluate_section_name).to_s,
24
- label: @section_options[:label],
25
- placement: @section_options[:placement]&.to_sym
26
+ notify_on_parsing(section_type,
27
+ id: "page-#{attributes[:id] || section_type}",
28
+ key: (attributes[:id] || section_type).to_s,
29
+ label: attributes[:label],
30
+ placement: attributes[:placement]&.to_sym
26
31
  )
27
32
  end
28
33
 
29
34
  def render(context)
30
- # @options doesn't include the page key if cache is on
31
- @options[:page] = context.registers[:page]
35
+ evaluate_attributes(context)
36
+
37
+ # the context (parsing) doesn't include the page key if cache is on
38
+ parse_context[:page] = context.registers[:page]
32
39
 
33
- # get the type/slug of the section
34
- # @section_options = interpolate_options(@raw_section_options, context)
35
- @section_type = evaluate_section_name(context)
36
- @template_name = "sections-#{@section_type}"
40
+ # use the Liquid filesystem to get the template of the section
41
+ template = parse_template(section_type, context)
37
42
 
38
- section = find_section(context)
39
- template = load_cached_partial(context)
43
+ # fetch the section definition
44
+ section = find_section(context)
40
45
 
41
46
  # if the tag is called by the Section middleware, use the content
42
47
  # from the request.
@@ -54,28 +59,24 @@ module Locomotive
54
59
  private
55
60
 
56
61
  def set_section_dom_id(context)
57
- context['section_id'] = "page-#{@section_options[:id] || @section_type}"
58
- end
59
-
60
- def read_template_from_file_system(context)
61
- section = find_section(context)
62
- raise SectionNotFound.new("Section with slug '#{@section_type}' was not found") if section.nil?
63
- section.liquid_source
62
+ context['section_id'] = "page-#{attributes[:id] || section_type}"
64
63
  end
65
64
 
66
65
  def find_section(context)
67
- context.registers[:services].section_finder.find(@section_type)
66
+ context.registers[:services].section_finder.find(section_type)
68
67
  end
69
68
 
70
69
  def find_section_content(context)
71
- section_id = @section_options[:id].presence || @section_type
70
+ section_id = attributes[:id].presence || section_type
72
71
  context['page']&.sections_content&.fetch(section_id, nil)
73
72
  end
74
73
 
75
- def evaluate_section_name(context = nil)
76
- context.try(:evaluate, @template_name) ||
77
- (!@template_name.is_a?(String) && @template_name.send(:state).first) ||
78
- @template_name
74
+ def parse_template(section_type, context)
75
+ ::Liquid::PartialCache.load(
76
+ "sections--#{section_type}",
77
+ context: context,
78
+ parse_context: parse_context
79
+ )
79
80
  end
80
81
 
81
82
  end
@@ -42,7 +42,7 @@ module Locomotive
42
42
 
43
43
  def build_template(section)
44
44
  # TODO: add some cache here (useful if there are sections with the same type)
45
- ::Liquid::Template.parse(section.liquid_source, @options)
45
+ ::Liquid::Template.parse(section.liquid_source, parse_context)
46
46
  end
47
47
 
48
48
  end
@@ -7,10 +7,8 @@ module Locomotive
7
7
  class Base < ::Liquid::Tag
8
8
 
9
9
  def render(context)
10
- %{
11
- #{self.render_title(context)}
12
- #{self.render_metadata(context)}
13
- }
10
+ self.render_title(context) +
11
+ self.render_metadata(context)
14
12
  end
15
13
 
16
14
  protected
@@ -12,6 +12,7 @@ module Locomotive
12
12
  # {{ session.foo }}
13
13
  #
14
14
  class SessionAssign < ::Liquid::Tag
15
+
15
16
  Syntax = /(#{::Liquid::VariableSignature}+)\s*=\s*(#{::Liquid::QuotedFragment}+)/o
16
17
 
17
18
  def initialize(tag_name, markup, options)