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.
- checksums.yaml +5 -5
- data/.ruby-version +1 -1
- data/.travis.yml +61 -17
- data/CHANGELOG.rdoc +27 -0
- data/Gemfile +11 -10
- data/Guardfile +1 -0
- data/README.md +2 -0
- data/bin/deploy_docs +1 -1
- data/blocks.gemspec +3 -1
- data/docs/_includes/configuration.md +3 -6
- data/docs/_includes/defining.md +7 -7
- data/docs/_includes/{introduction.md → features.md} +2 -2
- data/docs/_includes/helper-blocks.md +5 -0
- data/docs/_includes/helper-blocks/content_tag.md +44 -0
- data/docs/_includes/installation.md +16 -2
- data/docs/_includes/overview.md +21 -0
- data/docs/_includes/templating.md +1 -1
- data/docs/_includes/templating/bootstrap_4_cards.md +9 -9
- data/docs/_layouts/slate.html +11 -9
- data/docs/index.md +3 -1
- data/gemfiles/Gemfile.rails-3-0-stable +1 -0
- data/gemfiles/Gemfile.rails-3-1-stable +1 -0
- data/gemfiles/Gemfile.rails-3-2-stable +1 -0
- data/gemfiles/Gemfile.rails-4-0-stable +2 -1
- data/gemfiles/Gemfile.rails-4-1-stable +2 -1
- data/gemfiles/Gemfile.rails-4-2-stable +2 -1
- data/gemfiles/Gemfile.rails-5-0-stable +4 -3
- data/gemfiles/Gemfile.rails-5-1-stable +4 -3
- data/gemfiles/Gemfile.rails-5-2-stable +13 -0
- data/lib/blocks.rb +37 -29
- data/lib/blocks/builders/block_definition.rb +45 -43
- data/lib/blocks/builders/builder.rb +96 -60
- data/lib/blocks/builders/hook_definition.rb +19 -4
- data/lib/blocks/engine.rb +14 -0
- data/lib/blocks/helpers/controller_extensions.rb +13 -0
- data/lib/blocks/helpers/haml_capture.rb +44 -0
- data/lib/blocks/{action_view_extensions → helpers}/view_extensions.rb +10 -4
- data/lib/blocks/renderers/adjacent_blocks_renderer.rb +9 -7
- data/lib/blocks/renderers/block_placeholder.rb +2 -0
- data/lib/blocks/renderers/block_renderer.rb +26 -5
- data/lib/blocks/renderers/block_with_hooks_renderer.rb +29 -19
- data/lib/blocks/renderers/collection_renderer.rb +19 -6
- data/lib/blocks/renderers/nesting_blocks_renderer.rb +9 -11
- data/lib/blocks/renderers/partial_renderer.rb +16 -14
- data/lib/blocks/renderers/renderer.rb +9 -24
- data/lib/blocks/renderers/runtime_context.rb +174 -152
- data/lib/blocks/renderers/wrapper_renderer.rb +21 -10
- data/lib/blocks/utilities/configurator.rb +30 -6
- data/lib/blocks/utilities/hash_with_caller.rb +36 -32
- data/lib/blocks/utilities/hash_with_render_strategy.rb +67 -19
- data/lib/blocks/utilities/options_set.rb +38 -63
- data/lib/blocks/version.rb +3 -1
- metadata +22 -21
- data/docs/_includes/wip.md +0 -34
- data/lib/blocks/experimental/builder_permissions.rb +0 -52
- data/lib/blocks/experimental/invalid_permissions_handler.rb +0 -27
- data/lib/blocks/renderers/abstract_renderer.rb +0 -69
- data/lib/blocks/utilities/dynamic_configuration.rb +0 -71
data/docs/_layouts/slate.html
CHANGED
@@ -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
|
-
<!--
|
27
|
-
<script
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
-
|
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", "
|
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", "
|
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", "
|
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.
|
5
|
+
# Requires min Ruby version 2.3
|
6
6
|
|
7
|
-
gem "nokogiri", "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", "
|
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.
|
5
|
+
# Requires min Ruby version 2.3
|
6
6
|
|
7
|
-
gem "nokogiri", "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", "
|
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 '
|
3
|
-
require 'blocks/
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
autoload_under 'utilities' do
|
42
|
+
autoload :Configurator
|
43
|
+
autoload :OptionsSet
|
44
|
+
autoload :HashWithRenderStrategy
|
45
|
+
autoload :HashWithCaller
|
46
|
+
end
|
43
47
|
|
44
|
-
|
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 :
|
4
|
-
|
5
|
-
|
6
|
-
|
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(
|
24
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
@#{hook}_hooks ||= []
|
31
|
-
end
|
32
|
-
RUBY
|
32
|
+
def hooks_present?
|
33
|
+
hooks.present?
|
34
|
+
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Blocks
|
4
4
|
class Builder
|
5
|
-
|
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 :
|
16
|
+
attr_accessor :options
|
15
17
|
|
16
18
|
attr_accessor :anonymous_block_number
|
17
19
|
|
18
|
-
delegate :
|
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
|
-
|
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.
|
45
|
-
|
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
|
49
|
-
|
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
|
57
|
-
|
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
|
61
|
-
|
62
|
-
|
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
|
83
|
-
|
81
|
+
name = if args.first
|
82
|
+
args.shift
|
84
83
|
else
|
84
|
+
anonymous = true
|
85
85
|
self.anonymous_block_number += 1
|
86
|
-
|
86
|
+
"anonymous_block_#{anonymous_block_number}"
|
87
87
|
end
|
88
88
|
|
89
89
|
block_definitions[name].tap do |block_definition|
|
90
|
-
block_definition.
|
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
|
-
|
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
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
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
|
-
|
166
|
-
|
167
|
-
|
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
|