bemer 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,8 +18,10 @@ module Bemer
18
18
  def initialize # rubocop:disable Metrics/MethodLength
19
19
  @asset_paths = []
20
20
  @bem = false
21
+ # https://github.com/heartcombo/devise/blob/b52e642c0131f7b0d9f2dd24d8607a186f18223e/lib/devise.rb#L301
21
22
  # Gem::Version.new('0.4.1') > Gem::Version.new('0.10.1')
22
23
  # Здесь вроде также используют https://github.com/rspec/rspec-rails/blob/9b7ab39c027a8cb25e2ebe9e0e985756025b0549/Gemfile#L45
24
+ # https://github.com/JuanitoFatas/fast-ruby/blob/38f49f95fc7574d929de60b71791d09129c2588c/code/string/%3D%3D%3D-vs-%3D~-vs-match.rb#L20
23
25
  @can_use_new_matcher = RUBY_VERSION >= '2.4.0'
24
26
  @default_block_tag = :div
25
27
  @default_element_tag = :div
@@ -59,7 +59,7 @@ module Bemer
59
59
  @bem_cascade = options.delete(:bem_cascade)
60
60
  @css_classes = [options.delete(:class), options.delete(:cls)]
61
61
  @js = options.delete(:js)
62
- @mixins = MixinList.new(options.delete(:mix))
62
+ @mixins = Mixes.new(options.delete(:mix))
63
63
  @modifiers = ModifierList.new(block, element, options.delete(:mods))
64
64
  @tag = build_tag(options.delete(:tag))
65
65
  @html_attrs = options
@@ -4,14 +4,20 @@ require 'active_support/core_ext/object/blank'
4
4
  require 'active_support/core_ext/string/filters'
5
5
 
6
6
  module Bemer
7
- class EntityBuilder < Entity
7
+ class EntityBuilder < Entity # rubocop:disable Metrics/ClassLength
8
+ DATA_BEM_KEY = :'data-bem'
9
+
8
10
  def attrs
9
11
  attributes = Hash[super]
10
12
  attributes[:class] = cls if cls.present?
11
13
 
12
14
  return attributes unless bem?
13
15
 
14
- attributes.merge!(js)
16
+ data_bem = js
17
+
18
+ data_bem[DATA_BEM_KEY] = data_bem[DATA_BEM_KEY].to_json if data_bem.key?(DATA_BEM_KEY)
19
+
20
+ attributes.merge!(data_bem)
15
21
  end
16
22
 
17
23
  def attrs=(new_attrs, save = true)
@@ -39,9 +45,9 @@ module Bemer
39
45
  def cls
40
46
  return super unless bem?
41
47
 
42
- js_class = 'i-bem' if @js.present? && bem_class.present?
48
+ i_bem = 'i-bem' if need_data_bem? || need_mixed_data_bem?
43
49
 
44
- [bem_class, mods, mix, super, js_class].join(' ').squish
50
+ [bem_class, mods, mix, super, i_bem].flatten.reject(&:blank?).uniq.join(' ')
45
51
  end
46
52
 
47
53
  def cls=(new_cls, save = true)
@@ -55,11 +61,18 @@ module Bemer
55
61
  end
56
62
 
57
63
  def js
58
- return {} if @js.blank? || bem_class.blank?
64
+ need_data_bem = need_data_bem?
65
+ need_mixed_data_bem = need_mixed_data_bem?
59
66
 
60
- js_attrs = @js.instance_of?(TrueClass) ? {} : super
67
+ return {} unless need_data_bem || need_mixed_data_bem
61
68
 
62
- { 'data-bem': { name => js_attrs }.to_json }
69
+ if !need_data_bem && need_mixed_data_bem
70
+ mixed_data_bem
71
+ else
72
+ data_bem = @js.instance_of?(TrueClass) ? {} : super
73
+
74
+ { DATA_BEM_KEY => { name => data_bem }.merge!(mixed_data_bem[DATA_BEM_KEY]) }
75
+ end
63
76
  end
64
77
 
65
78
  def js=(new_js, save = true)
@@ -67,9 +80,15 @@ module Bemer
67
80
  end
68
81
 
69
82
  def mix=(new_mix, save = true)
70
- new_mix = MixinList.new(new_mix).to_a
83
+ new_mixes = Mixes.new(new_mix)
84
+ new_mix = new_mixes.to_a
71
85
 
72
- save ? @mix = new_mix : new_mix
86
+ if save
87
+ @mixins = new_mixes
88
+ @mix = new_mix
89
+ else
90
+ new_mix
91
+ end
73
92
  end
74
93
 
75
94
  def mods
@@ -93,8 +112,24 @@ module Bemer
93
112
  save ? @tag = new_tag : new_tag
94
113
  end
95
114
 
115
+ def need_data_bem?
116
+ bem? && @js.present? && bem_class.present?
117
+ end
118
+
119
+ def need_mixed_data_bem?
120
+ bem? && mixins.entities.any?(&:need_data_bem?)
121
+ end
122
+
96
123
  protected
97
124
 
125
+ def mixed_data_bem
126
+ mixins.entities.each_with_object(DATA_BEM_KEY => {}) do |entity, data_bem|
127
+ next unless entity.need_data_bem?
128
+
129
+ data_bem[DATA_BEM_KEY][entity.name] = entity.js[DATA_BEM_KEY][entity.name]
130
+ end
131
+ end
132
+
98
133
  def bem_via_option?
99
134
  !@bem.nil?
100
135
  end
@@ -12,13 +12,16 @@ module Bemer
12
12
 
13
13
  # Использовать mix
14
14
  # Использовать mixs
15
+ # mixes
15
16
  # Использовать bemer_mix
16
17
  def bem_mix(*mix)
17
- Bemer::MixinList.new(mix).to_s
18
+ Bemer::Mixes.new(mix).to_s
18
19
  end
19
20
 
20
21
  # Использовать mods
21
22
  # Использовать mod
23
+ # modifier
24
+ # modifiers
22
25
  # Использовать bemer_mods
23
26
  def bem_mods(*block_and_element, mods)
24
27
  block, element = *block_and_element
@@ -51,5 +54,11 @@ module Bemer
51
54
  def component_partial_path(name)
52
55
  Bemer::PathResolver.new(self).resolve(name, true)
53
56
  end
57
+
58
+ def bem_attrs_for(block = '', element = nil, **options)
59
+ js = options[:js].nil? ? true : options.delete(:js)
60
+
61
+ Bemer::EntityBuilder.new(block, element, options.merge(bem: true, js: js)).attrs
62
+ end
54
63
  end
55
64
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/object/blank'
4
+ require 'active_support/core_ext/array/wrap'
5
+ require 'active_support/core_ext/hash/slice'
6
+
7
+ module Bemer
8
+ class Mixes
9
+ def initialize(*mixes)
10
+ @mixes = Array.wrap(mixes).flatten
11
+ end
12
+
13
+ def to_a
14
+ @to_a ||= entities.map { |e| [e.bem_class, e.mods] }.flatten.reject(&:blank?).uniq
15
+ end
16
+
17
+ def to_s
18
+ @to_s ||= to_a.join(' ')
19
+ end
20
+
21
+ def entities # rubocop:disable Metrics/MethodLength
22
+ @entities ||= mixes.flat_map do |mix|
23
+ if mix.is_a?(Hash)
24
+ options = mix.extract!(:js, :mods)
25
+
26
+ mix.flat_map do |block, elems|
27
+ if elems.nil?
28
+ EntityBuilder.new(block, **options, bem: true)
29
+ else
30
+ Array(elems).map { |elem| EntityBuilder.new(block, elem, **options, bem: true) }
31
+ end
32
+ end
33
+ else
34
+ Array(mix).flat_map { |block| EntityBuilder.new(block) }
35
+ end
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ attr_reader :mixes
42
+ end
43
+ end
@@ -7,7 +7,7 @@ module Bemer
7
7
  @condition = options[:condition].nil? ? true : options[:condition]
8
8
  @element = options[:elem]
9
9
  @mask = build_mask(options[:block], options[:elem])
10
- @mixins = MixinList.new(options[:mix])
10
+ @mixins = Mixes.new(options[:mix])
11
11
  @modifiers = ModifierList.new(:block, :elem, options[:mods])
12
12
  @wildcard = nil
13
13
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bemer
4
- VERSION = '0.3.0'.freeze
4
+ VERSION = '0.4.0'.freeze
5
5
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'bem_attrs_for helper' do
4
+ delegate :bem_attrs_for, to: :view
5
+
6
+ context 'when a block and element have no name' do
7
+ it { expect(bem_attrs_for).to be_empty }
8
+ end
9
+
10
+ context 'when only a block name is specified' do
11
+ it { expect(bem_attrs_for(:block)).to include(class: 'block i-bem', 'data-bem': '{"block":{}}') }
12
+ it { expect(bem_attrs_for(:block, mods: :enabled)).to include(class: 'block block_enabled i-bem', 'data-bem': '{"block":{}}') }
13
+ it { expect(bem_attrs_for(:block, mix: { block1: :elem })).to include(class: 'block block1__elem i-bem', 'data-bem': '{"block":{}}') }
14
+ it { expect(bem_attrs_for(:block, js: { key: :val })).to include(class: 'block i-bem', 'data-bem': '{"block":{"key":"val"}}') }
15
+ it { expect(bem_attrs_for(:block, js: false)).to include(class: 'block') }
16
+
17
+ ['', false].each do |elem|
18
+ it { expect(bem_attrs_for(:block, elem)).to be_empty }
19
+ end
20
+ end
21
+
22
+ context 'when only an element name is specified' do
23
+ ['', nil, false].each do |block|
24
+ it { expect(bem_attrs_for(block, :elem)).to be_empty }
25
+ end
26
+ end
27
+
28
+ context 'when a name is specified for a block and element' do
29
+ it { expect(bem_attrs_for(:block, :elem)).to include(class: 'block__elem i-bem', 'data-bem': '{"block__elem":{}}') }
30
+ it { expect(bem_attrs_for(:block, :elem, mods: :enabled)).to include(class: 'block__elem block__elem_enabled i-bem', 'data-bem': '{"block__elem":{}}') }
31
+ it { expect(bem_attrs_for(:block, :elem, mix: :block_2)).to include(class: 'block__elem block-2 i-bem', 'data-bem': '{"block__elem":{}}') }
32
+ it { expect(bem_attrs_for(:block, :elem, js: { key: :val })).to include(class: 'block__elem i-bem', 'data-bem': '{"block__elem":{"key":"val"}}') }
33
+ it { expect(bem_attrs_for(:block, :elem, js: false)).to include(class: 'block__elem') }
34
+ end
35
+ end
@@ -38,7 +38,7 @@ RSpec.describe 'block_tag helper' do
38
38
  # it_behaves_like 'a BEM entity', '<div></div>'
39
39
  # it_behaves_like 'a block entity builder method', 'Helloo', :yeyeye
40
40
  # it_behaves_like 'an entity builder method', 'html'
41
- it_behaves_like 'an HTML entity tree builder method', :hello, { tag: :strong }, 'html'
41
+ # it_behaves_like 'an HTML entity tree builder method', :hello, { tag: :strong }, 'html'
42
42
  end
43
43
  end
44
44
 
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe 'elem_tag helper' do
4
+ delegate :elem_tag, to: :view
5
+
6
+ context 'when the `default_element_tag` is set to `span`' do
7
+ before do
8
+ Bemer.config.default_element_tag = :span
9
+ end
10
+
11
+ it { expect(elem_tag(:block, :elem)).to have_empty_tag(:span, with: { class: 'block__elem' }, count: 1) }
12
+ end
13
+
14
+ context 'when the `element_name_separator` is set to `___`' do
15
+ before do
16
+ Bemer.config.element_name_separator = '___'
17
+ end
18
+
19
+ it { expect(elem_tag(:block, :elem)).to have_empty_tag(:div, with: { class: 'block___elem' }, count: 1) }
20
+ end
21
+
22
+ context 'when the `modifier_name_separator` is set to `--`' do
23
+ before do
24
+ Bemer.config.modifier_name_separator = '--'
25
+ end
26
+
27
+ it { expect(elem_tag(:block, :elem, mods: :enabled)).to have_empty_tag(:div, with: { class: 'block__elem block__elem--enabled' }, count: 1) }
28
+ end
29
+
30
+ context 'when the `modifier_value_separator` is set to `___`' do
31
+ before do
32
+ Bemer.config.modifier_value_separator = '___'
33
+ end
34
+
35
+ it { expect(elem_tag(:block, :elem, mods: { theme: :gray })).to have_empty_tag(:div, with: { class: 'block__elem block__elem_theme___gray' }, count: 1) }
36
+ end
37
+
38
+ # The bem parameter from the configuration does not affect the operation of elem_tag in any way.
39
+ [true, false].each do |bem|
40
+ context "when the `bem` is globally set to `#{bem}`" do
41
+ before do
42
+ Bemer.config.bem = bem
43
+ end
44
+
45
+ context 'when a block and element have no name' do
46
+ it { expect(elem_tag).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
47
+ it { expect(elem_tag(bem: true)).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
48
+ it { expect(elem_tag(js: true)).to(have_empty_tag(:div, without: { class: 'i-bem' }, count: 1)) { without_tag 'div[data-bem]' } }
49
+
50
+ ['', nil, false].repeated_permutation(2).each do |block, elem|
51
+ it { expect(elem_tag(block, elem, bem: true)).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
52
+ it { expect(elem_tag(block, elem, js: true)).to(have_empty_tag(:div, without: { class: 'i-bem' }, count: 1)) { without_tag 'div[data-bem]' } }
53
+ end
54
+ end
55
+
56
+ context 'when only a block name is specified' do
57
+ it { expect(elem_tag(:block, nil, bem: true)).to have_empty_tag(:div, with: { class: 'block' }, count: 1) }
58
+ it { expect(elem_tag(:block, nil, js: true)).to have_empty_tag(:div, with: { class: 'block i-bem', 'data-bem': '{"block":{}}' }, count: 1) }
59
+
60
+ ['', false].each do |elem|
61
+ it { expect(elem_tag(:block, elem, bem: true)).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
62
+ it { expect(elem_tag(:block, elem, js: true)).to(have_empty_tag(:div, without: { class: 'i-bem' }, count: 1)) { without_tag 'div[data-bem]' } }
63
+ end
64
+ end
65
+
66
+ context 'when only an element name is specified' do
67
+ ['', nil, false].each do |block|
68
+ it { expect(elem_tag(block, :elem)).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
69
+ it { expect(elem_tag(block, :elem, bem: true)).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
70
+ it { expect(elem_tag(block, :elem, js: true)).to(have_empty_tag(:div, without: { class: 'i-bem' }, count: 1)) { without_tag 'div[data-bem]' } }
71
+ end
72
+ end
73
+
74
+ context 'when a name is specified for a block and element' do
75
+ # Entity name
76
+ it { expect(elem_tag(:block_name, :elem_name)).to have_empty_tag(:div, with: { class: 'block-name__elem-name' }, count: 1) }
77
+ it { expect(elem_tag('Block_Name', 'Elem_Name')).to have_empty_tag(:div, with: { class: 'Block_Name__Elem_Name' }, count: 1) }
78
+ it { expect(elem_tag(:Block_Name, :Elem_Name)).to have_empty_tag(:div, with: { class: 'Block-Name__Elem-Name' }, count: 1) }
79
+ it { expect(elem_tag('BlockName', 'ElemName')).to have_empty_tag(:div, with: { class: 'BlockName__ElemName' }, count: 1) }
80
+
81
+ # bem parameter
82
+ it { expect(elem_tag(:block, :elem, mix: :css_mixin, mods: :enabled, js: true, cls: :css_class)).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled css-mixin css-class i-bem', 'data-bem': '{"block__elem":{}}' }, count: 1) }
83
+ it { expect(elem_tag(:block, :elem, bem: true, mix: :css_mixin, mods: :enabled, js: true, cls: :css_class)).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled css-mixin css-class i-bem', 'data-bem': '{"block__elem":{}}' }, count: 1) }
84
+ it { expect(elem_tag(:block, :elem, bem: false, mix: :css_mixin, mods: :enabled, js: true, cls: :css_class)).to(have_empty_tag(:div, with: { class: 'css-class' }, without: { class: 'block__elem block__elem_enabled css-mixin i-bem' }, count: 1)) { without_tag 'div[data-bem]' } }
85
+
86
+ # bem_cascade parameter
87
+ it { expect(elem_tag(:block, :elem, bem_cascade: false)).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
88
+ it { expect(elem_tag(:block, :elem, bem: true, bem_cascade: false)).to have_empty_tag(:div, with: { class: 'block__elem' }, count: 1) }
89
+ it { expect(elem_tag(:block, :elem, bem: false, bem_cascade: true)).to(have_empty_tag(:div, count: 1)) { without_tag 'div[class]' } }
90
+
91
+ # cls and class parameters
92
+ it { expect(elem_tag(:block, :elem, cls: :css_class)).to have_empty_tag(:div, with: { class: 'block__elem css-class' }, count: 1) }
93
+ it { expect(elem_tag(:block, :elem, class: :css_class)).to have_empty_tag(:div, with: { class: 'block__elem css-class' }, count: 1) }
94
+ it { expect(elem_tag(:block, :elem, class: :css_class1, cls: :css_class2)).to have_empty_tag(:div, with: { class: 'block__elem css-class1 css-class2' }, count: 1) }
95
+ it { expect(elem_tag(:block, :elem, class: 'css_class1', cls: 'css_class2')).to have_empty_tag(:div, with: { class: 'block__elem css_class1 css_class2' }, count: 1) }
96
+ it { expect(elem_tag(:block, :elem, class: ['css_class1', :css_class2])).to have_empty_tag(:div, with: { class: 'block__elem css_class1 css-class2' }, count: 1) }
97
+ it { expect(elem_tag(:block, :elem, cls: ['css_class1', :css_class2])).to have_empty_tag(:div, with: { class: 'block__elem css_class1 css-class2' }, count: 1) }
98
+
99
+ # js parameter
100
+ it { expect(elem_tag(:block, :elem, js: true)).to have_empty_tag(:div, with: { class: 'block__elem i-bem', 'data-bem': '{"block__elem":{}}' }, count: 1) }
101
+ it { expect(elem_tag(:block, :elem, js: [1, 2])).to have_empty_tag(:div, with: { class: 'block__elem i-bem', 'data-bem': '{"block__elem":[1,2]}' }, count: 1) }
102
+ it { expect(elem_tag(:block, :elem, js: { key: :val })).to have_empty_tag(:div, with: { class: 'block__elem i-bem', 'data-bem': '{"block__elem":{"key":"val"}}' }, count: 1) }
103
+
104
+ # mix parameter
105
+ it { expect(elem_tag(:block, :elem, mix: :css_mixin)).to have_empty_tag(:div, with: { class: 'block__elem css-mixin' }, count: 1) }
106
+ it { expect(elem_tag(:block, :elem, mix: ['css_mixin', :block_name, block2: :elem])).to have_empty_tag(:div, with: { class: 'block__elem css_mixin block-name block2__elem' }, count: 1) }
107
+ it { expect(elem_tag(:block, :elem, mix: { block_name: :elem })).to have_empty_tag(:div, with: { class: 'block__elem block-name__elem' }, count: 1) }
108
+ it { expect(elem_tag(:block, :elem, mix: { block_name: :elem, js: true })).to have_empty_tag(:div, with: { class: 'block__elem block-name__elem i-bem', 'data-bem': '{"block-name__elem":{}}' }, count: 1) }
109
+ it { expect(elem_tag(:block, :elem, js: true, mix: { block_1: :elem, js: { key: :val } })).to have_empty_tag(:div, with: { class: 'block__elem block-1__elem i-bem', 'data-bem': '{"block__elem":{},"block-1__elem":{"key":"val"}}' }, count: 1) }
110
+ it { expect(elem_tag(:block, :elem, js: true, mix: { block: :elem, js: { key: :val } })).to have_empty_tag(:div, with: { class: 'block__elem i-bem', 'data-bem': '{"block__elem":{"key":"val"}}' }, count: 1) }
111
+ it { expect(elem_tag(:block, :elem, mix: { block_name: :elem, mods: :enabled })).to have_empty_tag(:div, with: { class: 'block__elem block-name__elem block-name__elem_enabled' }, count: 1) }
112
+ it { expect(elem_tag(:block, :elem, mix: [:mix, block_name: :elem, js: true])).to have_empty_tag(:div, with: { class: 'block__elem mix block-name__elem i-bem', 'data-bem': '{"block-name__elem":{}}' }, count: 1) }
113
+ it { expect(elem_tag(:block, :elem, mix: [{ block_1: nil, mods: :enabled, js: { key: :val } }, { block_name: :elem, js: true }])).to have_empty_tag(:div, with: { class: 'block__elem block-1 block-1_enabled block-name__elem i-bem', 'data-bem': '{"block-1":{"key":"val"},"block-name__elem":{}}' }, count: 1) }
114
+ it { expect(elem_tag(:block, :elem, mix: [:block_1, block2: %i[elem1 elem2], js: true])).to have_empty_tag(:div, with: { class: 'block__elem block-1 block2__elem1 block2__elem2 i-bem', 'data-bem': '{"block2__elem1":{},"block2__elem2":{}}' }, count: 1) }
115
+ it { expect(elem_tag(:block, :elem, mix: { block2: %i[elem1 elem2], js: true })).to have_empty_tag(:div, with: { class: 'block__elem block2__elem1 block2__elem2 i-bem', 'data-bem': '{"block2__elem1":{},"block2__elem2":{}}' }, count: 1) }
116
+
117
+ # mods parameter
118
+ it { expect(elem_tag(:block, :elem, mods: :enabled)).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled' }, count: 1) }
119
+ it { expect(elem_tag(:block, :elem, mods: { enabled: true })).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled' }, count: 1) }
120
+ it { expect(elem_tag(:block, :elem, mods: { enabled: 'true' })).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled_true' }, count: 1) }
121
+ it { expect(elem_tag(:block, :elem, mods: { enabled: false })).to have_empty_tag(:div, with: { class: 'block__elem' }, without: { class: 'block__elem_enabled' }, count: 1) }
122
+ it { expect(elem_tag(:block, :elem, mods: { enabled: 'false' })).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled_false' }, count: 1) }
123
+ it { expect(elem_tag(:block, :elem, mods: { enabled: '' })).to have_empty_tag(:div, with: { class: 'block__elem' }, without: { class: 'block__elem_enabled' }, count: 1) }
124
+ it { expect(elem_tag(:block, :elem, mods: { enabled: nil })).to have_empty_tag(:div, with: { class: 'block__elem' }, without: { class: 'block__elem_enabled' }, count: 1) }
125
+ it { expect(elem_tag(:block, :elem, mods: { enabled: 'nil' })).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled_nil' }, count: 1) }
126
+ it { expect(elem_tag(:block, :elem, mods: [:enabled, size: :small])).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled block__elem_size_small' }, count: 1) }
127
+ it { expect(elem_tag(:block, :elem, mods: [:enabled, %i[size small], %i[size large]])).to have_empty_tag(:div, with: { class: 'block__elem block__elem_enabled block__elem_size_large' }, count: 1) }
128
+
129
+ # tag parameter
130
+ it { expect(elem_tag(:block, :elem, tag: :span)).to have_empty_tag(:span, with: { class: 'block__elem' }, count: 1) }
131
+ it { expect(elem_tag(:block, :elem, tag: '', content: 'Content')).to eq 'Content' }
132
+ it { expect(elem_tag(:block, :elem, tag: '', content: '')).to eq '' }
133
+ # got: nil
134
+ # it { expect(elem_tag(:block, :elem, tag: '')).to eq '' }
135
+ it { expect(elem_tag(:block, :elem, tag: false, content: 'Content')).to eq 'Content' }
136
+ it { expect(elem_tag(:block, :elem, tag: false, content: '')).to eq '' }
137
+ # got: nil
138
+ # it { expect(elem_tag(:block, :elem, tag: false)).to eq '' }
139
+ it { expect(elem_tag(:block, :elem, tag: nil, content: 'Content')).to have_tag(:div, with: { class: 'block__elem' }, text: 'Content', count: 1) }
140
+
141
+ # attributes
142
+ it { expect(elem_tag(:block, :elem, data: { key: :val })).to have_empty_tag(:div, with: { class: 'block__elem', 'data-key': 'val' }, count: 1) }
143
+ it { expect(elem_tag(:block, :elem, 'data-key': :val)).to have_empty_tag(:div, with: { class: 'block__elem', 'data-key': 'val' }, count: 1) }
144
+ it { expect(elem_tag(:block, :elem, data: { key: :val }, 'data-key2': :val)).to have_empty_tag(:div, with: { class: 'block__elem', 'data-key': 'val', 'data-key2': 'val' }, count: 1) }
145
+ it { expect(elem_tag(:block, :elem, tag: :a, href: '#')).to have_empty_tag(:a, with: { class: 'block__elem', href: '#' }, count: 1) }
146
+
147
+ # content parameter
148
+ it { expect(elem_tag(:block, :elem, content: 'Content')).to have_tag(:div, with: { class: 'block__elem' }, text: 'Content', count: 1) }
149
+
150
+ it do # rubocop:disable RSpec/ExampleLength
151
+ html = elem_tag :block, :elem do
152
+ elem_tag :block, :elem1, content: 'Content' do
153
+ '<div></div>'.html_safe
154
+ end
155
+ end
156
+
157
+ expect(html).to have_tag(:div, with: { class: 'block__elem' }, count: 1) do
158
+ with_tag :div, with: { class: 'block__elem1' }, count: 1 do
159
+ with_tag :div, without: { class: 'block__elem1' }, blank: true, count: 1
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -7,6 +7,7 @@ require_relative 'dummy/config/environment'
7
7
  require 'rspec/rails'
8
8
  require 'spec_helper'
9
9
  require 'fuubar'
10
+ require 'rspec-html-matchers'
10
11
 
11
12
  RSpec.configure do |config|
12
13
  # RSpec Rails can automatically mix in different behaviours to your tests
@@ -36,4 +37,5 @@ RSpec.configure do |config|
36
37
  end
37
38
 
38
39
  config.include Bemer::Test::ConfigurationHelpers
40
+ config.include RSpecHtmlMatchers
39
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bemer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Grigorev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-01 00:00:00.000000000 Z
11
+ date: 2020-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.2.0
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.16'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.16'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: bundler-audit
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +86,14 @@ dependencies:
100
86
  requirements:
101
87
  - - "~>"
102
88
  - !ruby/object:Gem::Version
103
- version: 12.3.0
89
+ version: 12.3.3
104
90
  type: :development
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
94
  - - "~>"
109
95
  - !ruby/object:Gem::Version
110
- version: 12.3.0
96
+ version: 12.3.3
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rspec
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +108,20 @@ dependencies:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
110
  version: 3.9.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec-html-matchers
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.9.2
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.9.2
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rspec-rails
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -142,28 +142,42 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 0.64.0
145
+ version: 0.68.1
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.68.1
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-performance
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 1.3.0
146
160
  type: :development
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
164
  - - "~>"
151
165
  - !ruby/object:Gem::Version
152
- version: 0.64.0
166
+ version: 1.3.0
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: rubocop-rspec
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
171
  - - "~>"
158
172
  - !ruby/object:Gem::Version
159
- version: 1.32.0
173
+ version: 1.38.1
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
178
  - - "~>"
165
179
  - !ruby/object:Gem::Version
166
- version: 1.32.0
180
+ version: 1.38.1
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: wwtd
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -192,7 +206,8 @@ dependencies:
192
206
  - - ">="
193
207
  - !ruby/object:Gem::Version
194
208
  version: 3.2.22
195
- description: Build reusable UI components for Rails applications using the BEM methodology.
209
+ description: Build reusable UI components for Rails applications with the ability
210
+ to use the BEM methodology.
196
211
  email: vill@rubyinventory.org
197
212
  executables: []
198
213
  extensions: []
@@ -205,6 +220,7 @@ extra_rdoc_files:
205
220
  - docs/Режимы.md
206
221
  - docs/Создание-и-использование-UI-компонент.md
207
222
  - docs/Файловая-структура.md
223
+ - docs/Хелпер-bem_attrs_for.md
208
224
  - docs/Хелпер-bem_mix.md
209
225
  - docs/Хелпер-bem_mods.md
210
226
  - docs/Хелпер-block_tag.md
@@ -228,6 +244,7 @@ files:
228
244
  - docs/Режимы.md
229
245
  - docs/Создание-и-использование-UI-компонент.md
230
246
  - docs/Файловая-структура.md
247
+ - docs/Хелпер-bem_attrs_for.md
231
248
  - docs/Хелпер-bem_mix.md
232
249
  - docs/Хелпер-bem_mods.md
233
250
  - docs/Хелпер-block_tag.md
@@ -260,7 +277,7 @@ files:
260
277
  - lib/bemer/entity.rb
261
278
  - lib/bemer/entity_builder.rb
262
279
  - lib/bemer/helpers.rb
263
- - lib/bemer/mixin_list.rb
280
+ - lib/bemer/mixes.rb
264
281
  - lib/bemer/modifier_list.rb
265
282
  - lib/bemer/path_resolver.rb
266
283
  - lib/bemer/pipeline.rb
@@ -280,10 +297,11 @@ files:
280
297
  - lib/bemer/tree/node.rb
281
298
  - lib/bemer/tree/text_node.rb
282
299
  - lib/bemer/version.rb
300
+ - spec/action_view/helpers/bem_attrs_for_spec.rb
283
301
  - spec/action_view/helpers/block_tag_spec.rb
302
+ - spec/action_view/helpers/elem_tag_spec.rb
284
303
  - spec/bemer/entity_builder_spec.rb
285
304
  - spec/bemer/entity_spec.rb
286
- - spec/bemer/mixin_list_spec.rb
287
305
  - spec/bemer/modifier_list_spec.rb
288
306
  - spec/bemer/railtie_spec.rb
289
307
  - spec/bemer_spec.rb
@@ -301,7 +319,6 @@ files:
301
319
  - spec/rails_helper.rb
302
320
  - spec/spec_helper.rb
303
321
  - spec/support/bemer.rb
304
- - spec/support/shared_examples/an_html_entity_tree_builder_method.rb
305
322
  homepage:
306
323
  licenses:
307
324
  - MIT
@@ -325,16 +342,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
325
342
  - !ruby/object:Gem::Version
326
343
  version: 2.2.0
327
344
  requirements: []
328
- rubyforge_project:
329
- rubygems_version: 2.7.7
345
+ rubygems_version: 3.0.3
330
346
  signing_key:
331
347
  specification_version: 4
332
- summary: Build reusable UI components for Rails applications using the BEM methodology.
348
+ summary: Build reusable UI components for Rails applications with the ability to use
349
+ the BEM methodology.
333
350
  test_files:
351
+ - spec/action_view/helpers/bem_attrs_for_spec.rb
334
352
  - spec/action_view/helpers/block_tag_spec.rb
353
+ - spec/action_view/helpers/elem_tag_spec.rb
335
354
  - spec/bemer/entity_builder_spec.rb
336
355
  - spec/bemer/entity_spec.rb
337
- - spec/bemer/mixin_list_spec.rb
338
356
  - spec/bemer/modifier_list_spec.rb
339
357
  - spec/bemer/railtie_spec.rb
340
358
  - spec/bemer_spec.rb
@@ -352,4 +370,3 @@ test_files:
352
370
  - spec/rails_helper.rb
353
371
  - spec/spec_helper.rb
354
372
  - spec/support/bemer.rb
355
- - spec/support/shared_examples/an_html_entity_tree_builder_method.rb