bemer 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE-RU.txt +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +268 -27
- data/docs//320/232/320/276/320/275/321/202/320/265/320/272/321/201/321/202-/321/203/320/267/320/273/320/260.md +1 -1
- data/docs//320/245/320/265/320/273/320/277/320/265/321/200-bem_attrs_for.md +58 -0
- data/docs//320/245/320/265/320/273/320/277/320/265/321/200-bem_mix.md +0 -6
- data/docs//320/245/320/265/320/273/320/277/320/265/321/200-block_tag.md +10 -4
- data/docs//320/245/320/265/320/273/320/277/320/265/321/200-elem_tag.md +1 -1
- data/lib/bemer/configuration.rb +3 -0
- data/lib/bemer/entity.rb +1 -1
- data/lib/bemer/entity_builder.rb +44 -9
- data/lib/bemer/helpers.rb +10 -1
- data/lib/bemer/mixes.rb +43 -0
- data/lib/bemer/predicate.rb +1 -1
- data/lib/bemer/railtie.rb +1 -4
- data/lib/bemer/version.rb +1 -1
- data/lib/bemer.rb +4 -3
- data/spec/action_view/helpers/bem_attrs_for_spec.rb +35 -0
- data/spec/action_view/helpers/block_tag_spec.rb +1 -1
- data/spec/action_view/helpers/elem_tag_spec.rb +166 -0
- data/spec/bemer/railtie_spec.rb +1 -1
- data/spec/rails_helper.rb +2 -0
- metadata +14 -179
- data/lib/bemer/mixin_list.rb +0 -74
- data/spec/bemer/mixin_list_spec.rb +0 -99
- data/spec/support/shared_examples/an_html_entity_tree_builder_method.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84098253bdd2d8a9d177fddcf79e6a98af7c76af3e7fab7c717e380a799d12e1
|
4
|
+
data.tar.gz: 673f538a9fe0f1e34c649527cd1d8a3d08940601b18d16223308ebf9ef22dfcf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a3fb72c68982a9d558192541b7de078d6ec98df923ddf048a2074742b62b553852d7f8486e1fd4786f690c6cf0ec392c33d15d82bbded151ccbec14168ed999
|
7
|
+
data.tar.gz: 6a9d7821d738c7a4137438708b8c4b5c9c707aa726cf4619647f2a69fd2c76d33d5c66a82b21a9cf059520f1dcae733b799fc318b96f75216db3379e47e53977
|
data/LICENSE-RU.txt
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,34 +1,273 @@
|
|
1
1
|
# Bemer
|
2
2
|
|
3
|
-
|
3
|
+
1. Build reusable UI components for Ruby on Rails applications.
|
4
|
+
1. Develop Ruby on Rails applications using the `BEM` methodology.
|
4
5
|
|
5
|
-
|
6
|
-
1. Предоставляет функционал для разработки приложений на Ruby on Rails с использованием методологии БЭМ.
|
6
|
+
**IMPORTANT**. *Using the `BEM` methodology is optional.*
|
7
7
|
|
8
|
-
|
8
|
+
Additional resources:
|
9
9
|
|
10
|
-
1.
|
11
|
-
1. [bemer-
|
12
|
-
1. [
|
10
|
+
1. Habr article in Russian - [Переиспользуемые UI компоненты в приложениях на Ruby on Rails](https://habrahabr.ru/post/352938/).
|
11
|
+
1. [`bemer-simple_form`](https://github.com/vill/bemer-simple_form) - Add the `BEM` methodology to your `SimpleForm` forms.
|
12
|
+
1. [`bemer-bootstrap`](https://github.com/vill/bemer-bootstrap) - Reusable UI components of `Bootstrap`.
|
13
|
+
1. [Ruby on Rails application](https://github.com/vill/bemer-example) using `bemer` and [`bemer-bootstrap`](https://github.com/vill/bemer-bootstrap).
|
13
14
|
|
14
|
-
|
15
|
+
*Please refer to the [README.ru.md](README.ru.md) file for instructions in Russian.*
|
15
16
|
|
16
|
-
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add it to your Gemfile:
|
17
21
|
|
18
22
|
```ruby
|
19
|
-
gem 'bemer'
|
23
|
+
gem 'bemer'
|
20
24
|
```
|
21
25
|
|
22
|
-
|
26
|
+
Run the following command to install it:
|
23
27
|
|
24
28
|
$ bundle
|
25
29
|
|
26
|
-
##
|
30
|
+
## Configuration
|
31
|
+
|
32
|
+
See [configuration documentation](docs/%D0%9A%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F.md) for details.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
# config/initializers/bemer.rb
|
36
|
+
|
37
|
+
Bemer.setup do |config|
|
38
|
+
config.bem = true
|
39
|
+
config.modifier_name_separator = '--'
|
40
|
+
config.path = 'app/frontend/components' # or Webpacker.config.source_path
|
41
|
+
# config.default_path_prefix = lambda { |path, view|
|
42
|
+
# view.controller.class.name.split('::')[0].underscore
|
43
|
+
# }
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
## Integrations
|
48
|
+
### Webpacker
|
49
|
+
|
50
|
+
```yml
|
51
|
+
# config/webpacker.yml
|
52
|
+
|
53
|
+
default: &default
|
54
|
+
source_path: app/frontend/components
|
55
|
+
source_entry_path: ../packs
|
56
|
+
public_output_path: frontend/assets
|
57
|
+
# ...
|
58
|
+
|
59
|
+
development:
|
60
|
+
<<: *default
|
61
|
+
# ...
|
62
|
+
|
63
|
+
test:
|
64
|
+
<<: *default
|
65
|
+
# ...
|
66
|
+
|
67
|
+
production:
|
68
|
+
<<: *default
|
69
|
+
# ...
|
70
|
+
```
|
71
|
+
#### File naming and folder structure
|
72
|
+
See [file naming and folder structure documentation](docs/%D0%A4%D0%B0%D0%B8%CC%86%D0%BB%D0%BE%D0%B2%D0%B0%D1%8F-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0.md) for details.
|
73
|
+
|
74
|
+
```
|
75
|
+
app/
|
76
|
+
├── frontend/
|
77
|
+
| ├── components/
|
78
|
+
| | ├── common/
|
79
|
+
| | | ├── carousel/
|
80
|
+
| | | | ├── index.slim
|
81
|
+
| | | | ├── index.bemhtml.slim
|
82
|
+
| | | | ├── index.js
|
83
|
+
| | | | ├── index.scss
|
84
|
+
| | | | └── ...
|
85
|
+
| | | ├── form/
|
86
|
+
| | | | ├── error_messages_elem/
|
87
|
+
| | | | | ├── index.slim
|
88
|
+
| | | | | ├── index.js
|
89
|
+
| | | | | ├── index.scss
|
90
|
+
| | | | | └── ...
|
91
|
+
| | | | ├── locales/
|
92
|
+
| | | | | ├── en.yml
|
93
|
+
| | | | | └── ...
|
94
|
+
| | | | ├── index.slim
|
95
|
+
| | | | ├── base.rb
|
96
|
+
| | | | ├── index.js
|
97
|
+
| | | | ├── index.scss
|
98
|
+
| | | | └── ...
|
99
|
+
| | | └── ...
|
100
|
+
| | ├── admin_panel/
|
101
|
+
| | | └── ...
|
102
|
+
| | ├── landing/
|
103
|
+
| | | └── ...
|
104
|
+
| | ├── user_panel/
|
105
|
+
| | | └── ...
|
106
|
+
| | └── ...
|
107
|
+
| ├── packs/
|
108
|
+
| | ├── admin_panel/
|
109
|
+
| | | ├── application.js
|
110
|
+
| | | └── ...
|
111
|
+
| | ├── landing/
|
112
|
+
| | | ├── application.js
|
113
|
+
| | | └── ...
|
114
|
+
| | ├── user_panel/
|
115
|
+
| | | ├── application.js
|
116
|
+
| | | └── ...
|
117
|
+
| | └── ...
|
118
|
+
| └── ...
|
119
|
+
└── ...
|
120
|
+
```
|
121
|
+
|
122
|
+
### Sprockets
|
123
|
+
|
124
|
+
You do not need to do anything, but add additional assets to the asset load path if necessary:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
# config/initializers/bemer.rb
|
128
|
+
|
129
|
+
Bemer.setup do |config|
|
130
|
+
config.asset_paths << Rails.root.join('some/asset/path')
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
### File naming and folder structure
|
135
|
+
See [file naming and folder structure documentation](docs/%D0%A4%D0%B0%D0%B8%CC%86%D0%BB%D0%BE%D0%B2%D0%B0%D1%8F-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0.md) for details.
|
136
|
+
|
137
|
+
```
|
138
|
+
app/
|
139
|
+
├── assets/
|
140
|
+
| ├── javascripts/
|
141
|
+
| | ├── admin_panel/
|
142
|
+
| | | ├── application.js
|
143
|
+
| | | └── ...
|
144
|
+
| | ├── landing/
|
145
|
+
| | | ├── application.js
|
146
|
+
| | | └── ...
|
147
|
+
| | ├── user_panel/
|
148
|
+
| | | ├── application.js
|
149
|
+
| | | └── ...
|
150
|
+
| | └── ...
|
151
|
+
| ├── stylesheets/
|
152
|
+
| | ├── admin_panel/
|
153
|
+
| | | ├── application.scss
|
154
|
+
| | | └── ...
|
155
|
+
| | ├── landing/
|
156
|
+
| | | ├── application.scss
|
157
|
+
| | | └── ...
|
158
|
+
| | ├── user_panel/
|
159
|
+
| | | ├── application.scss
|
160
|
+
| | | └── ...
|
161
|
+
| | └── ...
|
162
|
+
| └── ...
|
163
|
+
├── frontend/
|
164
|
+
| ├── components/
|
165
|
+
| | ├── common/
|
166
|
+
| | | ├── carousel/
|
167
|
+
| | | | ├── index.slim
|
168
|
+
| | | | ├── index.bemhtml.slim
|
169
|
+
| | | | ├── index.js
|
170
|
+
| | | | ├── index.scss
|
171
|
+
| | | | └── ...
|
172
|
+
| | | ├── form/
|
173
|
+
| | | | ├── error_messages_elem/
|
174
|
+
| | | | | ├── index.slim
|
175
|
+
| | | | | ├── index.js
|
176
|
+
| | | | | ├── index.scss
|
177
|
+
| | | | | └── ...
|
178
|
+
| | | | ├── locales/
|
179
|
+
| | | | | ├── en.yml
|
180
|
+
| | | | | └── ...
|
181
|
+
| | | | ├── index.slim
|
182
|
+
| | | | ├── base.rb
|
183
|
+
| | | | ├── index.js
|
184
|
+
| | | | ├── index.scss
|
185
|
+
| | | | └── ...
|
186
|
+
| | | └── ...
|
187
|
+
| | ├── admin_panel/
|
188
|
+
| | | └── ...
|
189
|
+
| | ├── landing/
|
190
|
+
| | | └── ...
|
191
|
+
| | ├── user_panel/
|
192
|
+
| | | └── ...
|
193
|
+
| | └── ...
|
194
|
+
| └── ...
|
195
|
+
└── ...
|
196
|
+
```
|
197
|
+
|
198
|
+
## Usage
|
199
|
+
|
200
|
+
### Component to which `BEMHTML` templates cannot be applied
|
201
|
+
|
202
|
+
HTML structure of the [Carousel component from Bootstrap](https://getbootstrap.com/docs/4.3/components/carousel/#with-indicators):
|
203
|
+
|
204
|
+
```slim
|
205
|
+
/ app/frontend/components/common/carousel/index.slim
|
206
|
+
|
207
|
+
.carousel.slide data-ride="carousel" class=local_assigns[:cls]
|
208
|
+
ol.carousel-indicators
|
209
|
+
- image_urls.size.times do |i|
|
210
|
+
li data-target=".carousel" class=(:active if i.zero?) data-slide-to=i
|
211
|
+
.carousel-inner
|
212
|
+
- image_urls.each_with_index do |image_url, i|
|
213
|
+
.carousel-item class=(:active if i.zero?)
|
214
|
+
= image_tag image_url, class: 'd-block w-100'
|
215
|
+
a.carousel-control-prev data-slide="prev" data-target='.carousel' role="button"
|
216
|
+
span.carousel-control-prev-icon aria-hidden="true"
|
217
|
+
span.sr-only Previous
|
218
|
+
a.carousel-control-next data-slide="next" data-target='.carousel' role="button"
|
219
|
+
span.carousel-control-next-icon aria-hidden="true"
|
220
|
+
span.sr-only Next
|
221
|
+
```
|
222
|
+
[Rendering](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-render_component.md) the `carousel` component in any view or [other UI components](docs/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B8-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-UI-%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82.md):
|
223
|
+
```slim
|
224
|
+
= render_component :carousel, prefix: :common, image_urls: image_urls, cls: 'carousel-fade'
|
225
|
+
```
|
226
|
+
|
227
|
+
### Component to which `BEMHTML` templates can be applied
|
228
|
+
|
229
|
+
Tree structure of the [Carousel component from Bootstrap](https://getbootstrap.com/docs/4.3/components/carousel/#with-indicators):
|
230
|
+
|
231
|
+
```slim
|
232
|
+
/ app/frontend/components/common/carousel/index.slim
|
233
|
+
|
234
|
+
= define_component do |component|
|
235
|
+
= component.block :carousel, 'data-ride': :carousel, 'data-interval': false, cls: :slide do |carousel|
|
236
|
+
= carousel.elem :indicators, tag: :ol, cls: 'carousel-indicators'
|
237
|
+
- image_urls.size.times do |i|
|
238
|
+
= carousel.elem :indicator, tag: :li, 'data-slide-to': i, mods: (:active if i.zero?), 'data-target': '.carousel'
|
239
|
+
= carousel.elem :inner, cls: 'carousel-inner'
|
240
|
+
- image_urls.each_with_index do |image_url, i|
|
241
|
+
= carousel.elem :item, cls: 'carousel-item', mods: (:active if i.zero?)
|
242
|
+
= carousel.elem :image, tag: :img, cls: 'd-block w-100', src: image_url
|
243
|
+
= carousel.elem :control_prev, tag: :a, cls: 'carousel-control-prev', 'data-slide': :prev, role: :button, 'data-target': '.carousel'
|
244
|
+
span.carousel-control-prev-icon aria-hidden="true"
|
245
|
+
span.sr-only Previous
|
246
|
+
= carousel.elem :control_next, tag: :a, cls: 'carousel-control-next', 'data-slide': :next, role: :button, 'data-target': '.carousel'
|
247
|
+
span.carousel-control-next-icon aria-hidden="true"
|
248
|
+
span.sr-only Next
|
249
|
+
```
|
250
|
+
|
251
|
+
[Default template](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-define_templates.md):
|
252
|
+
```slim
|
253
|
+
/ app/frontend/components/common/carousel/index.bemhtml.slim
|
254
|
+
|
255
|
+
= define_templates do |template|
|
256
|
+
= template.elem(mods: :active).add_cls :active
|
257
|
+
```
|
258
|
+
|
259
|
+
[Rendering](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-render_component.md) the `carousel` component in any view or [other UI components](docs/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B8-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-UI-%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82.md) using [`BEMHTML`](docs/BEMHTML.md) [templates](docs/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B.md):
|
260
|
+
```slim
|
261
|
+
= render_component :carousel, prefix: :common, image_urls: image_urls do |template|
|
262
|
+
= template.block(:carousel).add_mix :carousel_fade
|
263
|
+
```
|
264
|
+
|
265
|
+
## Documentation in Russian
|
27
266
|
|
28
|
-
1. [
|
29
|
-
1. [
|
30
|
-
1. [
|
31
|
-
1.
|
267
|
+
1. [File naming and folder structure](docs/%D0%A4%D0%B0%D0%B8%CC%86%D0%BB%D0%BE%D0%B2%D0%B0%D1%8F-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0.md)
|
268
|
+
1. [Configuration](docs/%D0%9A%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F.md)
|
269
|
+
1. [Creating and using UI components](docs/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B8-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-UI-%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82.md)
|
270
|
+
1. Helpers for UI components
|
32
271
|
1. [`define_component`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-define_component.md)
|
33
272
|
1. [`define_templates`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-define_templates.md)
|
34
273
|
1. [`render_component`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-render_component.md)
|
@@ -36,23 +275,25 @@ gem 'bemer', '~> 0.2.0'
|
|
36
275
|
1. [`component_pack`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-component_pack.md)
|
37
276
|
1. [`component_asset_path`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-component_asset_path.md)
|
38
277
|
1. [`component_partial_path`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-component_partial_path.md)
|
39
|
-
1.
|
278
|
+
1. Additional helpers for the BEM methodology
|
279
|
+
1. [`bem_attrs_for`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-bem_attrs_for.md)
|
40
280
|
1. [`bem_mix`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-bem_mix.md)
|
41
281
|
1. [`bem_mods`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-bem_mods.md)
|
42
282
|
1. [`block_tag`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-block_tag.md)
|
43
283
|
1. [`elem_tag`](docs/%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-elem_tag.md)
|
44
284
|
1. [BEMHTML](docs/BEMHTML.md)
|
45
|
-
1. [
|
46
|
-
1. [
|
47
|
-
1. [
|
48
|
-
1. [
|
285
|
+
1. [Templates](docs/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B.md)
|
286
|
+
1. [Node](docs/%D0%9A%D0%BE%D0%BD%D1%82%D0%B5%D0%BA%D1%81%D1%82-%D1%83%D0%B7%D0%BB%D0%B0.md)
|
287
|
+
1. [Predicates](docs/%D0%9F%D1%80%D0%B5%D0%B4%D0%B8%D0%BA%D0%B0%D1%82%D1%8B.md)
|
288
|
+
1. [Modes](docs/%D0%A0%D0%B5%D0%B6%D0%B8%D0%BC%D1%8B.md)
|
49
289
|
|
50
|
-
##
|
290
|
+
## Links
|
51
291
|
|
52
|
-
1. https://
|
53
|
-
1. https://github.com/bem/bem-
|
54
|
-
1. https://github.com/bem
|
292
|
+
1. BEM methodology - https://bem.info/methodology/
|
293
|
+
1. Minimal stack for coding client-side JavaScript and templating - https://github.com/bem/bem-core
|
294
|
+
1. Declarative template engine for the browser and server with regular JS syntax - https://github.com/bem/bem-xjst
|
295
|
+
1. BEM Forum - https://bem.info/forum/
|
55
296
|
|
56
|
-
##
|
297
|
+
## License
|
57
298
|
|
58
|
-
Copyright (c) 2017
|
299
|
+
Copyright (c) 2017-2023 Alexander Grigorev. See [LICENSE.txt](LICENSE.txt) for further details.
|
@@ -125,7 +125,7 @@ HTML тег изменить на `small` если текущая сущност
|
|
125
125
|
|
126
126
|
### Метод `name`
|
127
127
|
|
128
|
-
**ВАЖНО**. *При
|
128
|
+
**ВАЖНО**. *При формировании названия сущности, действуют [правила преобразования знаков нижнего подчеркивания `_` в тире `-` для `Symbol` и `String`](%D0%A5%D0%B5%D0%BB%D0%BF%D0%B5%D1%80-block_tag.md#%D0%9D%D0%B0%D0%B7%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D0%B8)*
|
129
129
|
|
130
130
|
Возвращает название сущности.
|
131
131
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Хелпер bem_attrs_for
|
2
|
+
|
3
|
+
Хелпер `bem_attrs_for` генерирует `class` и `data-bem` атрибуты для указанной сущности.
|
4
|
+
|
5
|
+
## Допустимые параметры
|
6
|
+
|
7
|
+
`cls` (синоним `class`), `js`, `mix` и `mods`, все остальные переданные параметры с названиями не из этого списка будут считаться атрибутами, за исключением: `bem`, `bem_cascade`, `content` и `tag`.
|
8
|
+
|
9
|
+
|
10
|
+
## Использование
|
11
|
+
|
12
|
+
```slim
|
13
|
+
= bem_attrs_for :block, :element
|
14
|
+
/ => { class: "block__element i-bem", "data-bem": "{\"block__element\":{}}" }
|
15
|
+
```
|
16
|
+
|
17
|
+
```slim
|
18
|
+
= bem_attrs_for :block, :element, js: { some: :value }
|
19
|
+
/ => { class: "block__element i-bem", "data-bem": "{\"block__element\":{\"some\":\"value\"}}" }
|
20
|
+
```
|
21
|
+
|
22
|
+
```slim
|
23
|
+
= simple_form_for :form, url: '#' do |f|
|
24
|
+
= f.input :numbers, collection: (1..5).map { |n| [n, n, bem_attrs_for(:form, :number, js: { value: n })] }
|
25
|
+
= f.button :submit
|
26
|
+
/ =>
|
27
|
+
/ <form novalidate="novalidate" class="form" action="#" accept-charset="UTF-8" method="post">
|
28
|
+
/ <!-- ... -->
|
29
|
+
/ <select class="form__numbers form__numbers--select form__numbers--required" name="form[numbers]" id="form_numbers">
|
30
|
+
/ <option value=""></option>
|
31
|
+
/ <option class="form__number i-bem" data-bem="{"form__number":{"value":1}}" value="1">1</option>
|
32
|
+
/ <option class="form__number i-bem" data-bem="{"form__number":{"value":2}}" value="2">2</option>
|
33
|
+
/ <option class="form__number i-bem" data-bem="{"form__number":{"value":3}}" value="3">3</option>
|
34
|
+
/ <option class="form__number i-bem" data-bem="{"form__number":{"value":4}}" value="4">4</option>
|
35
|
+
/ <option class="form__number i-bem" data-bem="{"form__number":{"value":5}}" value="5">5</option>
|
36
|
+
/ </select>
|
37
|
+
/ <!-- ... -->
|
38
|
+
/ </form>
|
39
|
+
```
|
40
|
+
|
41
|
+
```slim
|
42
|
+
= simple_form_for :form, url: '#' do |f|
|
43
|
+
= f.input :numbers, collection: (1..5).map { |n| [n, n, bem_attrs_for(:form, :number, js: false)] }
|
44
|
+
= f.button :submit
|
45
|
+
/ =>
|
46
|
+
/ <form novalidate="novalidate" class="form" action="#" accept-charset="UTF-8" method="post">
|
47
|
+
/ <!-- ... -->
|
48
|
+
/ <select class="form__numbers form__numbers--select form__numbers--required" name="form[numbers]" id="form_numbers">
|
49
|
+
/ <option value=""></option>
|
50
|
+
/ <option class="form__number" value="1">1</option>
|
51
|
+
/ <option class="form__number" value="2">2</option>
|
52
|
+
/ <option class="form__number" value="3">3</option>
|
53
|
+
/ <option class="form__number" value="4">4</option>
|
54
|
+
/ <option class="form__number" value="5">5</option>
|
55
|
+
/ </select>
|
56
|
+
/ <!-- ... -->
|
57
|
+
/ </form>
|
58
|
+
```
|
@@ -50,12 +50,6 @@ bem_mix 'block_name' => 'elem_name' # => 'block_name__elem_name'
|
|
50
50
|
bem_mix 'block_name', 'block_name__elem' # => 'block_name block_name__elem'
|
51
51
|
```
|
52
52
|
|
53
|
-
эквивалентная запись:
|
54
|
-
|
55
|
-
```ruby
|
56
|
-
bem_mix 'block_name block_name__elem' # => 'block_name block_name__elem'
|
57
|
-
```
|
58
|
-
|
59
53
|
Пустые аргументы возвращают пустую строку
|
60
54
|
```ruby
|
61
55
|
bem_mix nil, '', {} # => ''
|
@@ -16,7 +16,7 @@ block_tag js: true, bem: true # => <div></div>
|
|
16
16
|
## Название сущности
|
17
17
|
|
18
18
|
При вызове `block_tag` первым аргументом передается название блока (указывать не обязательно) допустимые типы:
|
19
|
-
1. `Symbol` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при
|
19
|
+
1. `Symbol` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при формировании css классов по методологии БЭМ
|
20
20
|
1. `String` возвращается без изменений
|
21
21
|
|
22
22
|
```ruby
|
@@ -81,7 +81,7 @@ block_tag :block, cls: ['cls_1', :cls_2], bem: false # => <div class="cls_1 cls-
|
|
81
81
|
Добавляет содержимое для блока.
|
82
82
|
|
83
83
|
```ruby
|
84
|
-
block_tag :block, content: 'Block content' # => <div>Block content</div>
|
84
|
+
block_tag :block, content: 'Block content' # => <div class="block">Block content</div>
|
85
85
|
```
|
86
86
|
Если передан `Ruby &block`, тогда параметр `content` игнорируется:
|
87
87
|
|
@@ -169,6 +169,12 @@ block_tag :block, mix: [:mix_1, block_1: :elem], bem: true
|
|
169
169
|
|
170
170
|
block_tag :block, mix: { block_1: :elem }, bem: true
|
171
171
|
# => <div class="block block-1__elem"></div>
|
172
|
+
|
173
|
+
block_tag :block, mix: { block_1: :elem, mods: :enabled }
|
174
|
+
# => <div class="block block-1__elem block-1__elem--enabled"></div>
|
175
|
+
|
176
|
+
block_tag :block, js: true, mix: { block_1: :elem, js: { key: :value } }
|
177
|
+
# => <div class="block block-1__elem i-bem" data-bem="{"block":{},"block-1__elem":{"key":"value"}}"></div>
|
172
178
|
```
|
173
179
|
|
174
180
|
### Параметр `mods`
|
@@ -192,7 +198,7 @@ block_tag :block, mods: { size: :small }, bem: true
|
|
192
198
|
|
193
199
|
```ruby
|
194
200
|
block_tag :block, tag: :span, content: 'Block content'
|
195
|
-
# => <span>Block content</span>
|
201
|
+
# => <span class="block">Block content</span>
|
196
202
|
|
197
203
|
block_tag :block, tag: '', content: 'Block content'
|
198
204
|
# => 'Block content'
|
@@ -202,7 +208,7 @@ block_tag :block, tag: false, content: 'Block content'
|
|
202
208
|
|
203
209
|
# Будет использован default_block_tag из конфига
|
204
210
|
block_tag :block, tag: nil, content: 'Block content'
|
205
|
-
# => <div>Block content</div>
|
211
|
+
# => <div class="block">Block content</div>
|
206
212
|
```
|
207
213
|
|
208
214
|
### Атрибуты
|
@@ -19,7 +19,7 @@ elem_tag '', :elem, js: true, bem: true # => <div></div>
|
|
19
19
|
## Название сущности
|
20
20
|
|
21
21
|
При вызове `elem_tag` первым аргументом передается название блока (указывать не обязательно), вторым название элемента (указывать не обязательно) допустимые типы:
|
22
|
-
1. `Symbol` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при
|
22
|
+
1. `Symbol` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при формировании css классов по БЭМ методологии
|
23
23
|
1. `String` возвращается без изменений
|
24
24
|
|
25
25
|
```ruby
|
data/lib/bemer/configuration.rb
CHANGED
@@ -18,8 +18,11 @@ module Bemer
|
|
18
18
|
def initialize # rubocop:disable Metrics/MethodLength
|
19
19
|
@asset_paths = []
|
20
20
|
@bem = false
|
21
|
+
# https://github.com/brainspec/enumerize/blob/9dd68ca36d1efed6bc4cec8557a359f34f408d47/lib/enumerize/activerecord.rb#L24
|
22
|
+
# https://github.com/heartcombo/devise/blob/b52e642c0131f7b0d9f2dd24d8607a186f18223e/lib/devise.rb#L301
|
21
23
|
# Gem::Version.new('0.4.1') > Gem::Version.new('0.10.1')
|
22
24
|
# Здесь вроде также используют https://github.com/rspec/rspec-rails/blob/9b7ab39c027a8cb25e2ebe9e0e985756025b0549/Gemfile#L45
|
25
|
+
# https://github.com/JuanitoFatas/fast-ruby/blob/38f49f95fc7574d929de60b71791d09129c2588c/code/string/%3D%3D%3D-vs-%3D~-vs-match.rb#L20
|
23
26
|
@can_use_new_matcher = RUBY_VERSION >= '2.4.0'
|
24
27
|
@default_block_tag = :div
|
25
28
|
@default_element_tag = :div
|
data/lib/bemer/entity.rb
CHANGED
@@ -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 =
|
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
|
data/lib/bemer/entity_builder.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
48
|
+
i_bem = 'i-bem' if need_data_bem? || need_mixed_data_bem?
|
43
49
|
|
44
|
-
[bem_class, mods, mix, super,
|
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
|
-
|
64
|
+
need_data_bem = need_data_bem?
|
65
|
+
need_mixed_data_bem = need_mixed_data_bem?
|
59
66
|
|
60
|
-
|
67
|
+
return {} unless need_data_bem || need_mixed_data_bem
|
61
68
|
|
62
|
-
|
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
|
-
|
83
|
+
new_mixes = Mixes.new(new_mix)
|
84
|
+
new_mix = new_mixes.to_a
|
71
85
|
|
72
|
-
save
|
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
|
data/lib/bemer/helpers.rb
CHANGED
@@ -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::
|
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
|