blocks 3.0.4 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +61 -17
  4. data/CHANGELOG.rdoc +27 -0
  5. data/Gemfile +11 -10
  6. data/Guardfile +1 -0
  7. data/README.md +2 -0
  8. data/bin/deploy_docs +1 -1
  9. data/blocks.gemspec +3 -1
  10. data/docs/_includes/configuration.md +3 -6
  11. data/docs/_includes/defining.md +7 -7
  12. data/docs/_includes/{introduction.md → features.md} +2 -2
  13. data/docs/_includes/helper-blocks.md +5 -0
  14. data/docs/_includes/helper-blocks/content_tag.md +44 -0
  15. data/docs/_includes/installation.md +16 -2
  16. data/docs/_includes/overview.md +21 -0
  17. data/docs/_includes/templating.md +1 -1
  18. data/docs/_includes/templating/bootstrap_4_cards.md +9 -9
  19. data/docs/_layouts/slate.html +11 -9
  20. data/docs/index.md +3 -1
  21. data/gemfiles/Gemfile.rails-3-0-stable +1 -0
  22. data/gemfiles/Gemfile.rails-3-1-stable +1 -0
  23. data/gemfiles/Gemfile.rails-3-2-stable +1 -0
  24. data/gemfiles/Gemfile.rails-4-0-stable +2 -1
  25. data/gemfiles/Gemfile.rails-4-1-stable +2 -1
  26. data/gemfiles/Gemfile.rails-4-2-stable +2 -1
  27. data/gemfiles/Gemfile.rails-5-0-stable +4 -3
  28. data/gemfiles/Gemfile.rails-5-1-stable +4 -3
  29. data/gemfiles/Gemfile.rails-5-2-stable +13 -0
  30. data/lib/blocks.rb +37 -29
  31. data/lib/blocks/builders/block_definition.rb +45 -43
  32. data/lib/blocks/builders/builder.rb +96 -60
  33. data/lib/blocks/builders/hook_definition.rb +19 -4
  34. data/lib/blocks/engine.rb +14 -0
  35. data/lib/blocks/helpers/controller_extensions.rb +13 -0
  36. data/lib/blocks/helpers/haml_capture.rb +44 -0
  37. data/lib/blocks/{action_view_extensions → helpers}/view_extensions.rb +10 -4
  38. data/lib/blocks/renderers/adjacent_blocks_renderer.rb +9 -7
  39. data/lib/blocks/renderers/block_placeholder.rb +2 -0
  40. data/lib/blocks/renderers/block_renderer.rb +26 -5
  41. data/lib/blocks/renderers/block_with_hooks_renderer.rb +29 -19
  42. data/lib/blocks/renderers/collection_renderer.rb +19 -6
  43. data/lib/blocks/renderers/nesting_blocks_renderer.rb +9 -11
  44. data/lib/blocks/renderers/partial_renderer.rb +16 -14
  45. data/lib/blocks/renderers/renderer.rb +9 -24
  46. data/lib/blocks/renderers/runtime_context.rb +174 -152
  47. data/lib/blocks/renderers/wrapper_renderer.rb +21 -10
  48. data/lib/blocks/utilities/configurator.rb +30 -6
  49. data/lib/blocks/utilities/hash_with_caller.rb +36 -32
  50. data/lib/blocks/utilities/hash_with_render_strategy.rb +67 -19
  51. data/lib/blocks/utilities/options_set.rb +38 -63
  52. data/lib/blocks/version.rb +3 -1
  53. metadata +22 -21
  54. data/docs/_includes/wip.md +0 -34
  55. data/lib/blocks/experimental/builder_permissions.rb +0 -52
  56. data/lib/blocks/experimental/invalid_permissions_handler.rb +0 -27
  57. data/lib/blocks/renderers/abstract_renderer.rb +0 -69
  58. data/lib/blocks/utilities/dynamic_configuration.rb +0 -71
@@ -23,15 +23,13 @@ under the License.
23
23
  {% assign images_url = '/' | prepend: site.images_dir | prepend: '/' | prepend: site_url %}
24
24
  <html>
25
25
  <head>
26
- <!-- Global Site Tag (gtag.js) - Google Analytics -->
27
- <script async src="https://www.googletagmanager.com/gtag/js?id=UA-104699666-1"></script>
28
- <script>
29
- window.dataLayer = window.dataLayer || [];
30
- function gtag(){dataLayer.push(arguments)};
31
- gtag('js', new Date());
32
-
33
- gtag('config', 'UA-104699666-1');
34
- </script>
26
+ <!-- Google Tag Manager -->
27
+ <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
28
+ new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
29
+ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
30
+ 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
31
+ })(window,document,'script','dataLayer','GTM-KG9MQ69');</script>
32
+ <!-- End Google Tag Manager -->
35
33
 
36
34
  <meta charset="utf-8">
37
35
  <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
@@ -42,6 +40,10 @@ under the License.
42
40
  </head>
43
41
 
44
42
  <body class="{{ page_classes }}" data-languages='{{ language_tabs | jsonify }}'>
43
+ <!-- Google Tag Manager (noscript) -->
44
+ <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KG9MQ69"
45
+ height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
46
+ <!-- End Google Tag Manager (noscript) -->
45
47
  <a href="#" id="nav-button">
46
48
  <span>
47
49
  NAV
data/docs/index.md CHANGED
@@ -10,14 +10,16 @@ toc_footers:
10
10
  - <a href='https://github.com/tripit/slate'>Documentation Powered by Slate</a>
11
11
 
12
12
  includes:
13
- - introduction
13
+ - features
14
14
  - installation
15
+ - overview
15
16
  - defining
16
17
  - rendering
17
18
  - hooks
18
19
  - wrappers
19
20
  - skipping
20
21
  - reserved-keywords
22
+ - helper-blocks
21
23
  - templating
22
24
  - configuration
23
25
  - custom-builders
@@ -9,6 +9,7 @@ gem "public_suffix", "~> 1.4.6"
9
9
  gem "mime-types", "< 3.0"
10
10
  gem "rack", "< 2.0"
11
11
  gem "rspec", "~> 3.0.0"
12
+ gem "rspec-its", "~> 1.2.0"
12
13
  gem "rails", github: "rails/rails", branch: "3-0-stable"
13
14
  gem "shoulda-matchers", "~> 2.0"
14
15
  gem 'test-unit', '~> 3.0'
@@ -9,6 +9,7 @@ gem "public_suffix", "~> 1.4.6"
9
9
  gem "mime-types", "< 3.0"
10
10
  gem "rack", "< 2.0"
11
11
  gem "rspec", "~> 3.0.0"
12
+ gem "rspec-its", "~> 1.2.0"
12
13
  gem "rails", github: "rails/rails", branch: "3-1-stable"
13
14
  gem "shoulda-matchers", "~> 2.0"
14
15
  gem 'test-unit', '~> 3.0'
@@ -9,6 +9,7 @@ gem "public_suffix", "~> 1.4.6"
9
9
  gem "mime-types", "< 3.0"
10
10
  gem "rack", "< 2.0"
11
11
  gem "rspec", "~> 3.0.0"
12
+ gem "rspec-its", "~> 1.2.0"
12
13
  gem "rails", github: "rails/rails", branch: "3-2-stable"
13
14
  gem "shoulda-matchers", "~> 2.0"
14
15
  gem 'test-unit', '~> 3.0'
@@ -9,6 +9,7 @@ gem "public_suffix", "~> 1.4.6"
9
9
  gem "mime-types", "< 3.0"
10
10
  gem "rack", "< 2.0"
11
11
  gem "rspec", "~> 3.0.0"
12
+ gem "rspec-its", "~> 1.2.0"
12
13
  gem "rails", github: "rails/rails", branch: "4-0-stable"
13
- gem "shoulda-matchers", "~> 2.0"
14
+ gem "shoulda-matchers", "3.1.3"
14
15
  gem "haml", "4.0.4"
@@ -9,6 +9,7 @@ gem "public_suffix", "~> 1.4.6"
9
9
  gem "mime-types", "< 3.0"
10
10
  gem "rack", "< 2.0"
11
11
  gem "rspec", "~> 3.0.0"
12
+ gem "rspec-its", "~> 1.2.0"
12
13
  gem "rails", github: "rails/rails", branch: "4-1-stable"
13
- gem "shoulda-matchers", "~> 2.0"
14
+ gem "shoulda-matchers", "3.1.3"
14
15
  gem "haml", "4.0.4"
@@ -9,6 +9,7 @@ gem "public_suffix", "~> 1.4.6"
9
9
  gem "mime-types", "< 3.0"
10
10
  gem "rack", "< 2.0"
11
11
  gem "rspec", "~> 3.0.0"
12
+ gem "rspec-its", "~> 1.2.0"
12
13
  gem "rails", github: "rails/rails", branch: "4-2-stable"
13
- gem "shoulda-matchers", "~> 2.0"
14
+ gem "shoulda-matchers", "3.1.3"
14
15
  gem "haml", "4.0.4"
@@ -2,11 +2,12 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec path: ".."
4
4
 
5
- # Requires min Ruby version 2.2.2
5
+ # Requires min Ruby version 2.3
6
6
 
7
- gem "nokogiri", "1.6.8.1"
7
+ gem "nokogiri", "1.10.7"
8
8
  gem "capybara"
9
9
  gem "rspec", "~> 3.6.0"
10
+ gem "rspec-its", "~> 1.2.0"
10
11
  gem "rails", github: "rails/rails", branch: "5-0-stable"
11
- gem "shoulda-matchers", "~> 2.0"
12
+ gem "shoulda-matchers", "3.1.3"
12
13
  gem "haml", "~> 5.0.0"
@@ -2,11 +2,12 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec path: ".."
4
4
 
5
- # Requires min Ruby version 2.2.2
5
+ # Requires min Ruby version 2.3
6
6
 
7
- gem "nokogiri", "1.6.8.1"
7
+ gem "nokogiri", "1.10.7"
8
8
  gem "capybara"
9
9
  gem "rspec", "~> 3.6.0"
10
+ gem "rspec-its", "~> 1.2.0"
10
11
  gem "rails", github: "rails/rails", branch: "5-1-stable"
11
- gem "shoulda-matchers", "~> 2.0"
12
+ gem "shoulda-matchers", "3.1.3"
12
13
  gem "haml", "~> 5.0.0"
@@ -0,0 +1,13 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec path: ".."
4
+
5
+ # Requires min Ruby version 2.3
6
+
7
+ gem "nokogiri", "1.10.7"
8
+ gem "capybara"
9
+ gem "rspec", "~> 3.6.0"
10
+ gem "rspec-its", "~> 1.2.0"
11
+ gem "rails", github: "rails/rails", branch: "5-2-stable"
12
+ gem "shoulda-matchers", "3.1.3"
13
+ gem "haml", "~> 5.0.0"
data/lib/blocks.rb CHANGED
@@ -1,47 +1,55 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/core_ext/hash'
2
- require 'active_support/hash_with_indifferent_access'
3
- require 'blocks/action_view_extensions/view_extensions'
4
+ require 'blocks/helpers/view_extensions'
5
+ require 'blocks/helpers/controller_extensions'
4
6
 
5
7
  module Blocks
6
8
  extend ActiveSupport::Autoload
7
9
 
10
+ # The following classes have no direct references when loading the rest
11
+ # of the Blocks classes so they must be eager loaded to prevent them
12
+ # from having to be loaded during the request
13
+ # (http://blog.plataformatec.com.br/2012/08/eager-loading-for-greater-good/)
8
14
  eager_autoload do
15
+ autoload_under 'builders' do
16
+ autoload :BlockDefinition
17
+ end
18
+
9
19
  autoload_under 'renderers' do
10
- autoload :Renderer
11
20
  autoload :RuntimeContext
12
- autoload :AbstractRenderer
13
- autoload :PartialRenderer
14
- autoload :BlockWithHooksRenderer
15
- autoload :AdjacentBlocksRenderer
16
- autoload :NestingBlocksRenderer
17
- autoload :CollectionRenderer
18
- autoload :WrapperRenderer
19
- autoload :BlockRenderer
20
21
  autoload :BlockPlaceholder
21
22
  end
23
+ end
22
24
 
23
- autoload_under 'builders' do
24
- autoload :HookDefinition
25
- autoload :BlockDefinition
26
- autoload :Builder
27
- end
25
+ autoload_under 'renderers' do
26
+ autoload :Renderer
27
+ autoload :PartialRenderer
28
+ autoload :BlockWithHooksRenderer
29
+ autoload :AdjacentBlocksRenderer
30
+ autoload :NestingBlocksRenderer
31
+ autoload :CollectionRenderer
32
+ autoload :WrapperRenderer
33
+ autoload :BlockRenderer
34
+ end
28
35
 
29
- autoload_under 'utilities' do
30
- autoload :DynamicConfiguration
31
- autoload :Configurator
32
- autoload :OptionsSet
33
- autoload :HashWithRenderStrategy
34
- autoload :HashWithCaller
35
- end
36
+ autoload_under 'builders' do
37
+ autoload :Builder
38
+ autoload :HookDefinition
36
39
  end
37
40
 
38
- # WIP
39
- # autoload_under 'experimental' do
40
- # autoload :BuilderPermissions
41
- # autoload :InvalidPermissionsHandler
42
- # end
41
+ autoload_under 'utilities' do
42
+ autoload :Configurator
43
+ autoload :OptionsSet
44
+ autoload :HashWithRenderStrategy
45
+ autoload :HashWithCaller
46
+ end
43
47
 
44
- autoload :Version
48
+ autoload_under 'helpers' do
49
+ autoload :HamlCapture
50
+ end
45
51
 
46
52
  include Configurator
47
53
  end
54
+
55
+ require 'blocks/engine'
@@ -1,12 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Blocks
2
4
  class BlockDefinition < OptionsSet
3
- attr_accessor :options_set,
4
- :skip_content,
5
- :skip_completely,
6
- :anonymous,
7
- *HookDefinition::HOOKS.map {|hook| "#{hook}_hooks" }
8
-
5
+ attr_accessor :skip_content,
6
+ :skip_completely,
7
+ :anonymous,
8
+ :hooks
9
9
 
10
+ def initialize(*)
11
+ self.hooks = Hash.new {|hash, key| hash[key] = [] }
12
+ super
13
+ end
14
+
10
15
  def skip(completely=false)
11
16
  self.skip_content = true
12
17
  self.skip_completely = completely
@@ -20,49 +25,46 @@ module Blocks
20
25
  !!skip_completely
21
26
  end
22
27
 
23
- def hooks_for(hook_name)
24
- self.send("#{hook_name}_hooks")
28
+ def hooks_for(hook_type, initialize_when_missing: false)
29
+ hooks[hook_type] if initialize_when_missing || hooks.key?(hook_type)
25
30
  end
26
31
 
27
- HookDefinition::HOOKS.each do |hook|
28
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
29
- def #{hook}_hooks
30
- @#{hook}_hooks ||= []
31
- end
32
- RUBY
32
+ def hooks_present?
33
+ hooks.present?
34
+ end
33
35
 
34
- define_method(hook) do |*args, &block|
35
- HookDefinition.new(self, hook, *args, &block).tap do |definition|
36
- hooks_for(hook) << definition
36
+ HookDefinition::HOOKS.each do |hook|
37
+ define_method(hook) do |*args, &hook_definition|
38
+ HookDefinition.new(self, hook, *args, &hook_definition).tap do |definition|
39
+ hooks_for(hook, initialize_when_missing: true) << definition
37
40
  end
38
41
  end
39
42
  end
40
43
 
41
- def to_s
42
- description = []
43
- description << super
44
- options = [
45
- runtime_options,
46
- standard_options,
47
- default_options
48
- ].detect(&:render_strategy)
49
-
50
- strategy = options.try(:render_strategy)
51
- render_strategy_name = if strategy == HashWithRenderStrategy::RENDER_WITH_PROXY
52
- caller_id = options.callers[HashWithRenderStrategy::RENDER_WITH_PROXY]
53
- "proxy block \"#{options[strategy]}\""
54
- elsif strategy == HashWithRenderStrategy::RENDER_WITH_BLOCK
55
- caller_id = options.callers[HashWithRenderStrategy::RENDER_WITH_BLOCK]
56
- "block defined at #{options[strategy].source_location}"
57
- elsif strategy == HashWithRenderStrategy::RENDER_WITH_PARTIAL
58
- caller_id = options.callers[HashWithRenderStrategy::RENDER_WITH_PARTIAL]
59
- "partial \"#{options[strategy]}\""
60
- end
61
- if render_strategy_name
62
- description << "Renders with #{render_strategy_name} [#{caller_id}]"
63
- end
64
-
65
- description.join("\n")
66
- end
44
+ # def to_s
45
+ # description = []
46
+ # description << super
47
+ # options = [
48
+ # standard_options,
49
+ # default_options
50
+ # ].detect(&:render_strategy)
51
+ #
52
+ # strategy = options.try(:render_strategy)
53
+ # render_strategy_name = if strategy == HashWithRenderStrategy::RENDER_WITH_PROXY
54
+ # # caller_id = options.callers[HashWithRenderStrategy::RENDER_WITH_PROXY]
55
+ # "proxy block \"#{options[strategy]}\""
56
+ # elsif strategy == HashWithRenderStrategy::RENDER_WITH_BLOCK
57
+ # # caller_id = options.callers[HashWithRenderStrategy::RENDER_WITH_BLOCK]
58
+ # "block defined at #{options[strategy].source_location}"
59
+ # elsif strategy == HashWithRenderStrategy::RENDER_WITH_PARTIAL
60
+ # # caller_id = options.callers[HashWithRenderStrategy::RENDER_WITH_PARTIAL]
61
+ # "partial \"#{options[strategy]}\""
62
+ # end
63
+ # if render_strategy_name
64
+ # # description << "Renders with #{render_strategy_name} [#{caller_id}]"
65
+ # end
66
+ #
67
+ # description.join("\n")
68
+ # end
67
69
  end
68
70
  end
@@ -1,8 +1,10 @@
1
- require 'call_with_params'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Blocks
4
4
  class Builder
5
- include CallWithParams
5
+ if defined?(Haml)
6
+ prepend HamlCapture
7
+ end
6
8
 
7
9
  # A pointer to the view context
8
10
  attr_accessor :view
@@ -11,58 +13,55 @@ module Blocks
11
13
  attr_accessor :block_definitions
12
14
 
13
15
  # Options provided during initialization of builder
14
- attr_accessor :options_set
16
+ attr_accessor :options
15
17
 
16
18
  attr_accessor :anonymous_block_number
17
19
 
18
- delegate :content_tag, to: :view
19
-
20
- delegate :render,
21
- :render_with_overrides,
22
- :deferred_render,
23
- to: :renderer
24
-
25
- delegate :runtime_options,
26
- :standard_options,
27
- :default_options,
28
- to: :options_set
20
+ delegate :with_output_buffer, :output_buffer, to: :view
29
21
 
30
- CONTENT_TAG_WRAPPER_BLOCK = :content_tag_wrapper
31
-
32
- def initialize(view, options={})
33
- if defined?(::Haml) && !view.instance_variables.include?(:@haml_buffer)
34
- class << view
35
- include Haml::Helpers
36
- end
37
- view.init_haml_helpers
38
- end
22
+ def initialize(view, options=nil)
39
23
  self.view = view
40
24
  self.block_definitions = HashWithIndifferentAccess.new do |hash, key|
41
25
  hash[key] = BlockDefinition.new(key); hash[key]
42
26
  end
43
27
  self.anonymous_block_number = 0
44
- self.options_set = OptionsSet.new("Builder Options", options)
45
- define_helper_blocks
28
+ self.options = options
29
+ end
30
+
31
+ def render(*args, &block)
32
+ renderer_class.render(self, *args, &block)
33
+ end
34
+
35
+ def render_with_overrides(*args, &block)
36
+ warn "[DEPRECATION] `render_with_overrides` is deprecated. Please use `render` instead."
37
+ render(*args, &block)
46
38
  end
47
39
 
48
- def renderer
49
- @renderer ||= Blocks.renderer_class.new(self)
40
+ def deferred_render(*args, &block)
41
+ renderer_class.deferred_render(self, *args, &block)
50
42
  end
51
43
 
52
44
  def block_for(block_name)
53
45
  block_definitions[block_name] if block_defined?(block_name)
54
46
  end
55
47
 
56
- def block_defined?(block_name)
57
- block_definitions.key?(block_name)
48
+ def hooks_for(block_name, hook_name)
49
+ block_for(block_name).try(:hooks_for, hook_name) || []
58
50
  end
59
51
 
60
- def define_each(collection, block_name_proc, *args, &block)
61
- collection.map do |object|
62
- define(call_with_params(block_name_proc, object, *args), object, *args, &block)
52
+ def capture(*args, &block)
53
+ if block.arity >= 0
54
+ args = args[0, block.arity]
55
+ end
56
+ with_output_buffer do
57
+ output_buffer << view.capture(*args, &block)
63
58
  end
64
59
  end
65
60
 
61
+ def block_defined?(block_name)
62
+ block_definitions.key?(block_name)
63
+ end
64
+
66
65
  # Define a block, unless a block by the same name is already defined.
67
66
  # <%= blocks.define :some_block_name, :parameter1 => "1", :parameter2 => "2" do |options| %>
68
67
  # <%= options[:parameter1] %> and <%= options[:parameter2] %>
@@ -79,16 +78,17 @@ module Blocks
79
78
  def define(*args, &block)
80
79
  options = args.extract_options!
81
80
 
82
- name, anonymous = if args.first
83
- [args.shift, false]
81
+ name = if args.first
82
+ args.shift
84
83
  else
84
+ anonymous = true
85
85
  self.anonymous_block_number += 1
86
- ["anonymous_block_#{anonymous_block_number}", true]
86
+ "anonymous_block_#{anonymous_block_number}"
87
87
  end
88
88
 
89
89
  block_definitions[name].tap do |block_definition|
90
- block_definition.add_options options, &block
91
- block_definition.anonymous = anonymous
90
+ block_definition.reverse_merge! options, &block
91
+ block_definition.anonymous = !!anonymous
92
92
  end
93
93
  end
94
94
 
@@ -132,8 +132,7 @@ module Blocks
132
132
  options = call_each_hash_value_with_params(options, *args) || {}
133
133
  options2 = call_each_hash_value_with_params(options2, *args) || {}
134
134
 
135
-
136
- options.symbolize_keys.merge(options2.symbolize_keys) do |key, v1, v2|
135
+ options.merge(options2) do |key, v1, v2|
137
136
  if v1.is_a?(String) && v2.is_a?(String)
138
137
  "#{v1} #{v2}"
139
138
  else
@@ -142,29 +141,66 @@ module Blocks
142
141
  end
143
142
  end
144
143
 
145
- protected
144
+ # Blocks::Builder#content_tag extends ActionView's content_tag method
145
+ # by allowing itself to be used as a wrapper, hook, or called directly,
146
+ # while also not requiring the content tag name (defaults to :div).
147
+ def content_tag(*args, &block)
148
+ options = args.extract_options!
149
+ escape = options.key?(:escape) ? options.delete(:escape) : true
150
+ if wrapper_type = options.delete(:wrapper_type)
151
+
152
+ html_option = options["#{wrapper_type}_html_option".to_sym] || options[:html_option]
153
+ wrapper_html = if html_option.is_a?(Array)
154
+ html_option.map { |html_attribute| options[html_attribute] }.compact.first
155
+ elsif html_option.present?
156
+ options[html_option]
157
+ end
146
158
 
147
- # TODO: move this logic elsewhere
148
- def define_helper_blocks
149
- define CONTENT_TAG_WRAPPER_BLOCK, defaults: { wrapper_tag: :div } do |content_block, *args|
150
- options = args.extract_options!
151
- wrapper_options = if options[:wrapper_html_option]
152
- if options[:wrapper_html_option].is_a?(Array)
153
- wrapper_attribute = nil
154
- options[:wrapper_html_option].each do |attribute|
155
- if options[attribute].present?
156
- wrapper_attribute = attribute
157
- break
158
- end
159
- end
160
- options[wrapper_attribute]
161
- else
162
- options[options[:wrapper_html_option]]
163
- end
159
+ wrapper_html = concatenating_merge(options["#{wrapper_type}_html".to_sym] || options[:html], wrapper_html, *args, options)
160
+
161
+ wrapper_tag = options["#{wrapper_type}_tag".to_sym]
162
+ end
163
+ wrapper_html ||= call_each_hash_value_with_params(options[:html], options).presence || options
164
+ wrapper_tag ||= options.delete(:tag)
165
+
166
+ if !wrapper_tag
167
+ first_arg = args.first
168
+ wrapper_tag = if first_arg.is_a?(String) || first_arg.is_a?(Symbol)
169
+ args.shift
170
+ else
171
+ :div
164
172
  end
165
- content_tag options[:wrapper_tag],
166
- concatenating_merge(options[:wrapper_html], wrapper_options, *args, options),
167
- &content_block
173
+ end
174
+
175
+ content_tag_args = [wrapper_tag]
176
+ if !block_given?
177
+ content_tag_args << (wrapper_html.delete(:content) || options[:content] || args.shift)
178
+ end
179
+ content_tag_args << wrapper_html
180
+ content_tag_args << escape
181
+
182
+ view.content_tag *content_tag_args, &block
183
+ end
184
+
185
+ protected
186
+ def renderer_class
187
+ @renderer_class ||= Blocks.renderer_class
188
+ end
189
+
190
+ def call_with_params(*args)
191
+ return nil if args.empty?
192
+ v = args.shift
193
+ v.is_a?(Proc) ? v.call(*(args[0, v.arity.abs])) : v
194
+ end
195
+
196
+ def call_each_hash_value_with_params(*args)
197
+ return {} if args.empty?
198
+
199
+ options = args.shift || {}
200
+ if options.is_a?(Proc)
201
+ call_with_params(options, *args)
202
+ else
203
+ options.inject(Hash.new) { |hash, (k, v)| hash[k] = call_with_params(v, *args); hash}
168
204
  end
169
205
  end
170
206
  end