comfortable_mexican_sofa 2.0.12 → 2.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +5 -2
  4. data/Gemfile +5 -0
  5. data/Rakefile +2 -0
  6. data/app/assets/javascripts/comfy/admin/cms/application.js +40 -0
  7. data/app/assets/javascripts/comfy/admin/cms/base.js +46 -0
  8. data/app/assets/javascripts/comfy/admin/cms/categories.js +17 -0
  9. data/app/assets/javascripts/comfy/admin/cms/codemirror.js +31 -0
  10. data/app/assets/javascripts/comfy/admin/cms/custom.js +1 -0
  11. data/app/assets/javascripts/comfy/admin/cms/diff.js +10 -0
  12. data/app/assets/javascripts/comfy/admin/cms/file_link.js +67 -0
  13. data/app/assets/javascripts/comfy/admin/cms/file_upload.js +194 -0
  14. data/app/assets/javascripts/comfy/admin/cms/files_modal.js +40 -0
  15. data/app/assets/javascripts/comfy/admin/cms/page_fragments.js +22 -0
  16. data/app/assets/javascripts/comfy/admin/cms/slugify.js +34 -0
  17. data/app/assets/javascripts/comfy/admin/cms/sortable_list.js +40 -0
  18. data/app/assets/javascripts/comfy/admin/cms/timepicker.js +30 -0
  19. data/app/assets/javascripts/comfy/admin/cms/wysiwyg.js +65 -0
  20. data/app/assets/javascripts/comfy/vendor/redactor.js +12 -6
  21. data/app/assets/stylesheets/comfy/admin/cms/base.sass +32 -35
  22. data/app/controllers/application_controller.rb +2 -0
  23. data/app/controllers/comfy/admin/base_controller.rb +3 -1
  24. data/app/controllers/comfy/admin/cms/base_controller.rb +9 -1
  25. data/app/controllers/comfy/admin/cms/categories_controller.rb +2 -0
  26. data/app/controllers/comfy/admin/cms/files_controller.rb +3 -1
  27. data/app/controllers/comfy/admin/cms/layouts_controller.rb +2 -0
  28. data/app/controllers/comfy/admin/cms/pages_controller.rb +4 -1
  29. data/app/controllers/comfy/admin/cms/revisions/base_controller.rb +2 -0
  30. data/app/controllers/comfy/admin/cms/revisions/layout_controller.rb +2 -0
  31. data/app/controllers/comfy/admin/cms/revisions/page_controller.rb +2 -0
  32. data/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb +2 -0
  33. data/app/controllers/comfy/admin/cms/revisions/translation_controller.rb +2 -0
  34. data/app/controllers/comfy/admin/cms/sites_controller.rb +2 -0
  35. data/app/controllers/comfy/admin/cms/snippets_controller.rb +2 -0
  36. data/app/controllers/comfy/admin/cms/translations_controller.rb +8 -0
  37. data/app/controllers/comfy/cms/assets_controller.rb +2 -0
  38. data/app/controllers/comfy/cms/base_controller.rb +4 -2
  39. data/app/controllers/comfy/cms/content_controller.rb +3 -1
  40. data/app/controllers/concerns/comfy/paginate.rb +2 -0
  41. data/app/controllers/concerns/comfy/reorder_action.rb +2 -0
  42. data/app/helpers/comfy/admin/cms_helper.rb +19 -0
  43. data/app/helpers/comfy/cms_helper.rb +4 -2
  44. data/app/models/comfy/cms/categorization.rb +2 -0
  45. data/app/models/comfy/cms/category.rb +2 -0
  46. data/app/models/comfy/cms/file.rb +2 -0
  47. data/app/models/comfy/cms/fragment.rb +3 -1
  48. data/app/models/comfy/cms/layout.rb +3 -1
  49. data/app/models/comfy/cms/page.rb +3 -1
  50. data/app/models/comfy/cms/revision.rb +2 -0
  51. data/app/models/comfy/cms/site.rb +5 -1
  52. data/app/models/comfy/cms/snippet.rb +2 -0
  53. data/app/models/comfy/cms/translation.rb +2 -0
  54. data/app/models/concerns/comfy/cms/with_categories.rb +2 -0
  55. data/app/models/concerns/comfy/cms/with_fragments.rb +2 -0
  56. data/app/views/comfy/admin/cms/categories/_index.html.haml +3 -3
  57. data/app/views/comfy/admin/cms/categories/create.js.erb +1 -1
  58. data/app/views/comfy/admin/cms/categories/destroy.js.erb +8 -3
  59. data/app/views/comfy/admin/cms/files/_file.html.haml +9 -10
  60. data/app/views/comfy/admin/cms/files/_modal.html.haml +1 -2
  61. data/app/views/comfy/admin/cms/files/destroy.js.erb +4 -0
  62. data/app/views/comfy/admin/cms/files/index.html.haml +10 -10
  63. data/app/views/comfy/admin/cms/fragments/_form_fragment_attachments.html.haml +15 -6
  64. data/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml +17 -21
  65. data/app/views/comfy/admin/cms/pages/_form.html.haml +3 -2
  66. data/app/views/comfy/admin/cms/pages/toggle_branch.js.erb +3 -1
  67. data/app/views/comfy/admin/cms/translations/_form.html.haml +3 -2
  68. data/app/views/layouts/comfy/admin/cms.html.haml +0 -1
  69. data/app/views/layouts/comfy/admin/cms/_body.html.haml +1 -0
  70. data/app/views/layouts/comfy/admin/cms/_left.html.haml +1 -1
  71. data/comfortable_mexican_sofa.gemspec +3 -2
  72. data/config.ru +2 -0
  73. data/config/application.rb +2 -0
  74. data/config/boot.rb +2 -0
  75. data/config/cms_routes.rb +2 -0
  76. data/config/environment.rb +2 -0
  77. data/config/environments/development.rb +2 -0
  78. data/config/environments/test.rb +2 -0
  79. data/config/initializers/comfortable_mexican_sofa.rb +2 -0
  80. data/lib/comfortable_mexican_sofa.rb +2 -0
  81. data/lib/comfortable_mexican_sofa/access_control/admin_authentication.rb +2 -0
  82. data/lib/comfortable_mexican_sofa/access_control/admin_authorization.rb +2 -0
  83. data/lib/comfortable_mexican_sofa/access_control/public_authentication.rb +2 -0
  84. data/lib/comfortable_mexican_sofa/access_control/public_authorization.rb +2 -0
  85. data/lib/comfortable_mexican_sofa/configuration.rb +3 -0
  86. data/lib/comfortable_mexican_sofa/content.rb +3 -0
  87. data/lib/comfortable_mexican_sofa/content/block.rb +2 -0
  88. data/lib/comfortable_mexican_sofa/content/params_parser.rb +59 -41
  89. data/lib/comfortable_mexican_sofa/content/renderer.rb +18 -4
  90. data/lib/comfortable_mexican_sofa/content/tag.rb +20 -5
  91. data/lib/comfortable_mexican_sofa/content/tags/asset.rb +2 -0
  92. data/lib/comfortable_mexican_sofa/content/tags/checkbox.rb +10 -3
  93. data/lib/comfortable_mexican_sofa/content/tags/date.rb +3 -1
  94. data/lib/comfortable_mexican_sofa/content/tags/datetime.rb +3 -1
  95. data/lib/comfortable_mexican_sofa/content/tags/file.rb +21 -27
  96. data/lib/comfortable_mexican_sofa/content/tags/file_link.rb +23 -24
  97. data/lib/comfortable_mexican_sofa/content/tags/files.rb +11 -9
  98. data/lib/comfortable_mexican_sofa/content/tags/fragment.rb +11 -1
  99. data/lib/comfortable_mexican_sofa/content/tags/helper.rb +3 -1
  100. data/lib/comfortable_mexican_sofa/content/tags/markdown.rb +3 -1
  101. data/lib/comfortable_mexican_sofa/content/tags/mixins/file_content.rb +38 -0
  102. data/lib/comfortable_mexican_sofa/content/tags/number.rb +3 -1
  103. data/lib/comfortable_mexican_sofa/content/tags/page_file_link.rb +82 -0
  104. data/lib/comfortable_mexican_sofa/content/tags/partial.rb +3 -1
  105. data/lib/comfortable_mexican_sofa/content/tags/snippet.rb +2 -0
  106. data/lib/comfortable_mexican_sofa/content/tags/template.rb +3 -1
  107. data/lib/comfortable_mexican_sofa/content/tags/text.rb +3 -1
  108. data/lib/comfortable_mexican_sofa/content/tags/textarea.rb +3 -1
  109. data/lib/comfortable_mexican_sofa/content/tags/wysiwyg.rb +3 -1
  110. data/lib/comfortable_mexican_sofa/engine.rb +2 -1
  111. data/lib/comfortable_mexican_sofa/error.rb +2 -0
  112. data/lib/comfortable_mexican_sofa/extensions/acts_as_tree.rb +2 -0
  113. data/lib/comfortable_mexican_sofa/extensions/has_revisions.rb +2 -0
  114. data/lib/comfortable_mexican_sofa/form_builder.rb +24 -17
  115. data/lib/comfortable_mexican_sofa/render_methods.rb +2 -0
  116. data/lib/comfortable_mexican_sofa/routes/cms.rb +2 -0
  117. data/lib/comfortable_mexican_sofa/routes/cms_admin.rb +2 -0
  118. data/lib/comfortable_mexican_sofa/routing.rb +2 -0
  119. data/lib/comfortable_mexican_sofa/seeds.rb +3 -1
  120. data/lib/comfortable_mexican_sofa/seeds/file/exporter.rb +2 -0
  121. data/lib/comfortable_mexican_sofa/seeds/file/importer.rb +2 -0
  122. data/lib/comfortable_mexican_sofa/seeds/layout/exporter.rb +2 -0
  123. data/lib/comfortable_mexican_sofa/seeds/layout/importer.rb +2 -0
  124. data/lib/comfortable_mexican_sofa/seeds/page/exporter.rb +2 -0
  125. data/lib/comfortable_mexican_sofa/seeds/page/importer.rb +2 -0
  126. data/lib/comfortable_mexican_sofa/seeds/snippet/exporter.rb +2 -0
  127. data/lib/comfortable_mexican_sofa/seeds/snippet/importer.rb +2 -0
  128. data/lib/comfortable_mexican_sofa/version.rb +3 -1
  129. data/lib/comfortable_mexican_sofa/view_hooks.rb +2 -0
  130. data/lib/generators/comfy/cms/assets_generator.rb +2 -0
  131. data/lib/generators/comfy/cms/cms_generator.rb +6 -4
  132. data/lib/generators/comfy/cms/controllers_generator.rb +2 -0
  133. data/lib/generators/comfy/cms/models_generator.rb +2 -0
  134. data/lib/generators/comfy/cms/views_generator.rb +2 -0
  135. data/lib/generators/comfy/scaffold/scaffold_generator.rb +6 -2
  136. data/lib/tasks/cms_seeds.rake +2 -0
  137. metadata +20 -26
  138. data/app/assets/javascripts/comfy/admin/cms/application.js.coffee +0 -30
  139. data/app/assets/javascripts/comfy/admin/cms/base.js.coffee +0 -224
  140. data/app/assets/javascripts/comfy/admin/cms/custom.js.coffee +0 -1
  141. data/app/assets/javascripts/comfy/admin/cms/files.js.coffee +0 -29
  142. data/app/assets/javascripts/comfy/admin/cms/uploader.js.coffee +0 -140
  143. data/app/views/comfy/admin/cms/files/create.js.erb +0 -1
  144. data/app/views/comfy/admin/cms/files/destroy.js.coffee +0 -2
  145. data/app/views/comfy/admin/cms/pages/form_fragments.js.erb +0 -1
  146. data/app/views/comfy/admin/cms/translations/form_fragments.js.erb +0 -1
@@ -1,10 +1,6 @@
1
1
  - begin
2
2
  - nodes = record.fragment_nodes
3
-
4
- // Grouping nodes by their namespace
5
- - namespace = nodes.each_with_object({}) do |n, h|
6
- - h[n.namespace] ||= []
7
- - h[n.namespace] << n
3
+ - namespace = nodes.group_by(&:namespace)
8
4
 
9
5
  #form-fragments
10
6
  - if nodes.empty?
@@ -14,29 +10,29 @@
14
10
  = t(".no_tags").html_safe
15
11
 
16
12
  - else
17
- = fields scope: :fragments, builder: ComfortableMexicanSofa::FormBuilder, bootstrap: { layout: :horizontal } do |fragments|
13
+ .tabbable
14
+ - if namespace.size > 1
15
+ .row
16
+ .col-sm-2
17
+ .col-sm-10
18
+ %ul.nav.nav-tabs
19
+ - namespace.each_with_index do |(name, tags), index|
20
+ %li.nav-item
21
+ - active = index == 0 ? "active" : nil
22
+ - label = t("comfy.cms.content.namespace.#{name}", default: name.humanize)
23
+ = link_to label, "#ns-#{name}", class: "nav-link #{active}", data: {toggle: "tab"}
18
24
 
19
- .tabbable
20
- - if namespace.size > 1
21
- .row
22
- .col-sm-2
23
- .col-sm-10
24
- %ul.nav.nav-tabs
25
- - namespace.each_with_index do |(name, tags), index|
26
- %li.nav-item
27
- - active = index == 0 ? "active" : nil
28
- - label = t("comfy.cms.content.namespace.#{name}", default: name.humanize)
29
- = link_to label, "#ns-#{name}", class: "nav-link #{active}", data: {toggle: "tab"}
25
+ .tab-content
26
+ - frag_index = 0
30
27
 
31
- .tab-content
32
- - frag_index = 0
28
+ - builder_opts = { builder: ComfortableMexicanSofa::FormBuilder, bootstrap: { layout: :horizontal }}
29
+ = fields scope, model: record, **builder_opts do |form|
33
30
  - namespace.each_with_index do |(name, tags), index|
34
31
  .tab-pane{id: "ns-#{name}", class: index == 0 ? "active" : nil}
35
32
  - tags.each do |tag|
36
- = fragments.field(record, tag, frag_index)
33
+ = form.fragment_field(tag, frag_index)
37
34
  - frag_index += 1
38
35
 
39
-
40
36
  - rescue ComfortableMexicanSofa::Content::Renderer::SyntaxError, ComfortableMexicanSofa::Content::Tag::Error => e
41
37
  .alert.alert-danger
42
38
  = e
@@ -13,7 +13,8 @@
13
13
 
14
14
  = comfy_admin_partial "comfy/admin/cms/partials/page_form_inner", form: form
15
15
 
16
- = render "comfy/admin/cms/fragments/form_fragments", form: form, record: @page
16
+ #form-fragments-container
17
+ = render "comfy/admin/cms/fragments/form_fragments", record: @page, scope: :page
17
18
 
18
19
  = render "comfy/admin/cms/categories/form", form: form
19
20
 
@@ -25,6 +26,6 @@
25
26
  = comfy_admin_partial "comfy/admin/cms/partials/page_form_after", form: form
26
27
 
27
28
  = form.form_actions do
28
- = submit_tag t(".preview"), name: "preview", id: nil, class: "btn btn-secondary", data: {disable_with: false}
29
+ = submit_tag t(".preview"), name: "preview", formtarget: "comfy-cms-preview", id: nil, class: "btn btn-secondary", data: {disable_with: false}
29
30
  = submit_tag t(@page.new_record?? ".create" : ".update"), class: "btn btn-primary ml-sm-1", data: {disable_with: false}
30
31
  = link_to t(".cancel"), comfy_admin_cms_site_pages_path, class: "btn btn-link"
@@ -1,10 +1,12 @@
1
+ // TODO: Extract this so the server only renders the HTML.
1
2
  var li = $('li#comfy_cms_page_<%=@page.id%>');
2
3
  li.find('.item .toggle').first().toggleClass('open');
3
4
 
4
5
  <% if session[:cms_page_tree].member?(@page.id.to_s) %>
5
6
  if(!li.find('ul.children')[0]) {
6
7
  li.append('<ul class="children sortable pl-md-3"><%= escape_javascript(render partial: "index_branch", collection: @page.children) %></ul>');
7
- CMS.sortable_list();
8
+ CMS.sortableList.destroy();
9
+ CMS.sortableList.init();
8
10
  }
9
11
  <% else %>
10
12
  li.find('ul.children').remove();
@@ -7,13 +7,14 @@
7
7
  - if (options = ::Comfy::Cms::Layout.options_for_select(@site)).present?
8
8
  = form.select :layout_id, options, {}, {data: {url: form_fragments_comfy_admin_cms_site_page_translation_path(@site, @page, @translation.id.to_i)}, id: "fragments-toggle"}
9
9
 
10
- = render "comfy/admin/cms/fragments/form_fragments", record: @translation
10
+ #form-fragments-container
11
+ = render "comfy/admin/cms/fragments/form_fragments", record: @translation, scope: :translation
11
12
 
12
13
  = form.check_box :is_published
13
14
 
14
15
  = comfy_admin_partial "comfy/admin/cms/partials/translation_form_after", form: form
15
16
 
16
17
  = form.form_actions do
17
- = submit_tag t(".preview"), name: "preview", id: nil, class: "btn btn-secondary", data: {disable_with: false}
18
+ = submit_tag t(".preview"), name: "preview", formtarget: "comfy-cms-preview", id: nil, class: "btn btn-secondary", data: {disable_with: false}
18
19
  = submit_tag t(@translation.new_record? ? ".create" : ".update"), class: "btn btn-primary", data: {disable_with: false}
19
20
  = link_to t(".cancel"), edit_comfy_admin_cms_site_page_path(@site, @page), class: "btn btn-link"
@@ -2,4 +2,3 @@
2
2
  %html{lang: I18n.locale}
3
3
  = render 'layouts/comfy/admin/cms/head'
4
4
  = render 'layouts/comfy/admin/cms/body'
5
- = render 'comfy/admin/cms/files/modal' if @site && !@site.new_record?
@@ -7,6 +7,7 @@
7
7
  #cms-main.col-lg-8.m-auto
8
8
  = render "layouts/comfy/admin/cms/flash"
9
9
  = yield
10
+ = render 'comfy/admin/cms/files/modal' if @site && !@site.new_record?
10
11
  #cms-right.col-lg-2
11
12
  = render 'layouts/comfy/admin/cms/right'
12
13
 
@@ -23,7 +23,7 @@
23
23
  = t('comfy.admin.cms.base.snippets')
24
24
  %li.nav-item
25
25
  - unless is_active_link?(comfy_admin_cms_site_files_path(@site))
26
- %a.cms-files-open-modal{href: '#', title: "Open library"}
26
+ %a.cms-files-open-modal{href: comfy_admin_cms_site_files_path(@site), title: "Open library"}
27
27
  %i.fas.fa-bars
28
28
  = active_link_to comfy_admin_cms_site_files_path(@site), class: "nav-link" do
29
29
  = t('comfy.admin.cms.base.files')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
4
  require "comfortable_mexican_sofa/version"
3
5
 
@@ -15,10 +17,9 @@ Gem::Specification.new do |s|
15
17
  f.match(%r{^(test|doc)/})
16
18
  end
17
19
 
18
- s.required_ruby_version = ">= 2.2.2"
20
+ s.required_ruby_version = ">= 2.3.0"
19
21
 
20
22
  s.add_dependency "active_link_to", ">= 1.0.0"
21
- s.add_dependency "coffee-rails", ">= 4.2.0"
22
23
  s.add_dependency "comfy_bootstrap_form", ">= 4.0.0"
23
24
  s.add_dependency "haml-rails", ">= 1.0.0"
24
25
  s.add_dependency "jquery-rails", ">= 4.3.1"
data/config.ru CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is used by Rack-based servers to start the application.
2
4
 
3
5
  require ::File.expand_path("../config/environment", __FILE__)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "boot"
2
4
 
3
5
  require "rails/all"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Set up gems listed in the Gemfile.
2
4
  ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # We can't have this in config/routes.rb as they will get pulled in into parent
2
4
  # application automatically. We want user to manually place them.
3
5
  ComfortableMexicanSofa::Application.routes.draw do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Load the rails application
2
4
  require File.expand_path("../application", __FILE__)
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  defined?(ComfortableMexicanSofa::Application) && ComfortableMexicanSofa::Application.configure do
2
4
  # Settings specified here will take precedence over those in config/application.rb.
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  defined?(ComfortableMexicanSofa::Application) && ComfortableMexicanSofa::Application.configure do
2
4
  # Settings specified here will take precedence over those in config/application.rb.
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ComfortableMexicanSofa.configure do |config|
2
4
  # Title of the admin area
3
5
  # config.cms_title = 'ComfortableMexicanSofa CMS Engine'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Loading engine only if this is not a standalone installation
2
4
  unless defined? ComfortableMexicanSofa::Application
3
5
  require_relative "comfortable_mexican_sofa/engine"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ComfortableMexicanSofa::AccessControl
2
4
  module AdminAuthentication
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ComfortableMexicanSofa::AccessControl
2
4
  module AdminAuthorization
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ComfortableMexicanSofa::AccessControl
2
4
  module PublicAuthentication
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ComfortableMexicanSofa::AccessControl
2
4
  module PublicAuthorization
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ComfortableMexicanSofa::Configuration
2
4
 
3
5
  # Don't like ComfortableMexicanSofa? Set it to whatever you like. :(
@@ -45,6 +47,7 @@ class ComfortableMexicanSofa::Configuration
45
47
  attr_accessor :admin_cache_sweeper
46
48
 
47
49
  # Not allowing erb code to be run inside page content. False by default.
50
+ # @return [Boolean]
48
51
  attr_accessor :allow_erb
49
52
 
50
53
  # Whitelist of all helper methods that can be used via {{cms:helper}} tag. By default
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ComfortableMexicanSofa::Content
2
4
  # ...
3
5
  end
@@ -23,6 +25,7 @@ require_relative "content/tags/files"
23
25
  require_relative "content/tags/snippet"
24
26
  require_relative "content/tags/asset"
25
27
  require_relative "content/tags/file_link"
28
+ require_relative "content/tags/page_file_link"
26
29
  require_relative "content/tags/helper"
27
30
  require_relative "content/tags/partial"
28
31
  require_relative "content/tags/template"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # wtf does this mean
2
4
  # it means that all nodes between this must be moved into here
3
5
  # {{cms:block}} some content {{cms:end_block}}
@@ -1,54 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "strscan"
4
+
1
5
  module ComfortableMexicanSofa::Content::ParamsParser
2
6
 
3
7
  class Error < StandardError; end
4
8
 
5
- SINGLE_STRING_LITERAL = %r{'[^']*'}
6
- DOUBLE_STRING_LITERAL = %r{"[^"]*"}
7
- IDENTIFIER = %r{[a-z0-9][\w\-/.]*}i
8
- COLUMN = %r{:}
9
- COMMA = %r{,}
9
+ STRING_LITERAL = %r{'[^']*'|"[^"]*"}
10
+ IDENTIFIER = %r{[a-z0-9][\w\-/.]*}i
11
+ COLON = %r{:}
12
+ COMMA = %r{,}
10
13
 
14
+ # @param [String] text
15
+ # @return [Array<String, {String => String}>]
16
+ # @raise [Error] if the given `text` is malformed.
17
+ #
18
+ # @example
19
+ # parse("happy greeting name:Joe show:true")
20
+ # #=> ['happy', 'greeting', {'name' => 'Joe', 'show' => 'true'}]
11
21
  def self.parse(text)
12
- parameterize(slice(tokenize(text.to_s)))
22
+ parse_token_groups(split_on_commas(tokenize(text.to_s)))
13
23
  end
14
24
 
15
- def self.parameterize(token_groups)
16
- params = []
17
- token_groups.each do |tokens|
18
- if tokens.count == 1
19
- collect_param_for_string!(params, tokens[0])
20
- elsif tokens.count == 3
21
- collect_param_for_hash!(params, tokens)
25
+ # @param [Enumerable<Array<(Symbol, String)>>] token_groups
26
+ # @return [Array<String, {String => String}>]
27
+ def self.parse_token_groups(token_groups)
28
+ token_groups.each_with_object([]) do |tokens, params|
29
+ case tokens.count
30
+ when 1
31
+ params << parse_string_param(tokens[0])
32
+ when 3
33
+ param = parse_key_value_param(tokens)
34
+ if params.last.is_a?(Hash)
35
+ params.last.update(param)
36
+ else
37
+ params << param
38
+ end
22
39
  else
23
40
  raise Error, "Unexpected tokens found: #{tokens}"
24
41
  end
25
42
  end
26
- params
27
43
  end
28
44
 
29
- def self.collect_param_for_string!(params, token)
45
+ # @param [(:string, String)] token
46
+ # @return [String]
47
+ # @raise [Error] if `token[0] != :string`.
48
+ def self.parse_string_param(token)
30
49
  type, value = token
31
50
  raise Error, "Unexpected token: #{token}" unless type == :string
32
- params << value
51
+ value
33
52
  end
34
53
 
35
- def self.collect_param_for_hash!(params, tokens)
36
- key, col, val = tokens
37
- key_type, key_value = key
38
- col_type, = col
39
- val_type, val_value = val
40
-
41
- unless key_type == :string && col_type == :column && val_type == :string
54
+ # @param [((:string, String), (:colon, String), (:string, String))] tokens
55
+ # @return [{String => String}]
56
+ # @raise [Error] if `tokens[0][0] != :string`, or `tokens[1][0] != :colon`,
57
+ # or `tokens[2][0] != :string`.
58
+ def self.parse_key_value_param(tokens)
59
+ (key_type, key_value), (col_type, _col_value), (val_type, val_value) = tokens
60
+ unless key_type == :string && col_type == :colon && val_type == :string
42
61
  raise Error, "Unexpected tokens: #{tokens}"
43
62
  end
44
-
45
- hash = params.last.is_a?(Hash) ? params.pop : {}
46
- hash[key_value] = val_value
47
- params << hash
63
+ { key_value => val_value }
48
64
  end
49
65
 
50
- # grouping tokens based on the comma and also removing comma tokens
51
- def self.slice(tokens)
66
+ # Splits tokens on commas. The result contains no `:comma` tokens.
67
+ #
68
+ # @param [Enumerable<(Symbol, String)>] tokens
69
+ # @return [Enumerable<Array<(Symbol, String)>>] Token groups.
70
+ def self.split_on_commas(tokens)
52
71
  slices = tokens.slice_after do |token|
53
72
  token[0] == :comma
54
73
  end
@@ -59,25 +78,24 @@ module ComfortableMexicanSofa::Content::ParamsParser
59
78
 
60
79
  # Tokenizing input string into a list of touples
61
80
  # Also args_string is stripped of "smart" quotes coming from wysiwyg
81
+ #
82
+ # @param [String] args_string
83
+ # @return [Array<String>] tokens
62
84
  def self.tokenize(args_string)
63
- args_string.gsub!(%r{[“”]}, '"')
64
- args_string.gsub!(%r{[‘’]}, "'")
65
-
66
- tokens = []
85
+ args_string = args_string.tr("“”‘’", %q(""''))
67
86
  ss = StringScanner.new(args_string)
68
- until ss.eos?
87
+ tokens = []
88
+ loop do
69
89
  ss.skip(%r{\s*})
70
90
  break if ss.eos?
71
- token =
72
- if (t = ss.scan(SINGLE_STRING_LITERAL)) then [:string, t[1...t.size - 1]]
73
- elsif (t = ss.scan(DOUBLE_STRING_LITERAL)) then [:string, t[1...t.size - 1]]
74
- elsif (t = ss.scan(IDENTIFIER)) then [:string, t]
75
- elsif (t = ss.scan(COLUMN)) then [:column, t]
76
- elsif (t = ss.scan(COMMA)) then [:comma, t]
91
+ tokens <<
92
+ if (t = ss.scan(STRING_LITERAL)) then [:string, t[1...-1]]
93
+ elsif (t = ss.scan(IDENTIFIER)) then [:string, t]
94
+ elsif (t = ss.scan(COLON)) then [:colon, t]
95
+ elsif (t = ss.scan(COMMA)) then [:comma, t]
77
96
  else
78
97
  raise Error, "Unexpected char: #{ss.getch}"
79
98
  end
80
- tokens << token
81
99
  end
82
100
  tokens
83
101
  end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "strscan"
4
+
1
5
  # Processing content follows these stages:
2
6
  #
3
7
  # string - Text with tags. like this: "some {{cms:fragment content}} text"
@@ -22,16 +26,20 @@ class ComfortableMexicanSofa::Content::Renderer
22
26
 
23
27
  class << self
24
28
 
29
+ # @return [Hash<String, Class<ComfortableMexicanSofa::Content::Tag>>]
25
30
  def tags
26
31
  @tags ||= {}
27
32
  end
28
33
 
34
+ # @param [String] name
35
+ # @param [Class<ComfortableMexicanSofa::Content::Tag>] klass
29
36
  def register_tag(name, klass)
30
37
  tags[name.to_s] = klass
31
38
  end
32
39
 
33
40
  end
34
41
 
42
+ # @param [Comfy::Cms::WithFragments, nil] context
35
43
  def initialize(context)
36
44
  @context = context
37
45
  @depth = 0
@@ -39,6 +47,8 @@ class ComfortableMexicanSofa::Content::Renderer
39
47
 
40
48
  # This is how we render content out. Takes context (cms page) and content
41
49
  # nodes
50
+ # @param [Array<String, ComfortableMexicanSofa::Content::Tag>]
51
+ # @param [Boolean] allow_erb
42
52
  def render(nodes, allow_erb = ComfortableMexicanSofa.config.allow_erb)
43
53
  if (@depth += 1) > MAX_DEPTH
44
54
  raise Error, "Deep tag nesting or recursive nesting detected"
@@ -51,7 +61,7 @@ class ComfortableMexicanSofa::Content::Renderer
51
61
  else
52
62
  tokens = tokenize(node.render)
53
63
  nodes = nodes(tokens)
54
- render(nodes, allow_erb || node.allow_erb)
64
+ render(nodes, allow_erb || node.allow_erb?)
55
65
  end
56
66
  end.flatten.join
57
67
  end
@@ -65,6 +75,7 @@ class ComfortableMexicanSofa::Content::Renderer
65
75
  end
66
76
 
67
77
  # Splitting text with tags into tokens we can process down the line
78
+ # @return [Array<String, {Symbol => String}>]
68
79
  def tokenize(string)
69
80
  tokens = []
70
81
  ss = StringScanner.new(string.to_s)
@@ -85,6 +96,8 @@ class ComfortableMexicanSofa::Content::Renderer
85
96
  # Constructing node tree for content. It's a list of strings and tags with
86
97
  # their own `nodes` method that has array of strings and tags with their own
87
98
  # `nodes` method that... you get the idea.
99
+ # @param [Array<String, {Symbol => String}>] tokens
100
+ # @return [Array<String, ComfortableMexicanSofa::Content::Tag>]
88
101
  def nodes(tokens)
89
102
  nodes = [[]]
90
103
  tokens.each do |token|
@@ -102,10 +115,11 @@ class ComfortableMexicanSofa::Content::Renderer
102
115
  nodes.pop
103
116
 
104
117
  else
105
- unless (klass = self.class.tags[tag_class])
106
- raise SyntaxError, "Unrecognized tag: #{token[:source]}"
107
- end
118
+ # @type [Class<ComfortableMexicanSofa::Content::Tag>]
119
+ klass = self.class.tags[tag_class] ||
120
+ raise(SyntaxError, "Unrecognized tag: #{token[:source]}")
108
121
 
122
+ # @type [ComfortableMexicanSofa::Content::Tag]
109
123
  tag = klass.new(
110
124
  context: @context,
111
125
  params: ComfortableMexicanSofa::Content::ParamsParser.parse(token[:tag_params]),