bemer 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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