bemer 0.3.0 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f081d85127046ac29d85d4dcffc832af6fc5c1e4ad49a2248b0502f3d0c17b26
4
- data.tar.gz: f0be9ccbdaf778a2ec2c4f01d533d12da6a687d3f152f007e3659c689bfc3985
3
+ metadata.gz: 84098253bdd2d8a9d177fddcf79e6a98af7c76af3e7fab7c717e380a799d12e1
4
+ data.tar.gz: 673f538a9fe0f1e34c649527cd1d8a3d08940601b18d16223308ebf9ef22dfcf
5
5
  SHA512:
6
- metadata.gz: c0155b1372465945e5090b8a205e155a26fe6af51291b8a47591dc2a36e697ff73e1943ec3acd1c183a0f320760f159b99e51f524acda1e1920d08e213eb0ebe
7
- data.tar.gz: a5ee0ef203901272ef8df243f9dfd1246451cf742ac98bc05ab73369ec42460de0fbd58dbf33e49ddb7eb255edf398c6885fb8044d5fb71765f61985921549ea
6
+ metadata.gz: 9a3fb72c68982a9d558192541b7de078d6ec98df923ddf048a2074742b62b553852d7f8486e1fd4786f690c6cf0ec392c33d15d82bbded151ccbec14168ed999
7
+ data.tar.gz: 6a9d7821d738c7a4137438708b8c4b5c9c707aa726cf4619647f2a69fd2c76d33d5c66a82b21a9cf059520f1dcae733b799fc318b96f75216db3379e47e53977
data/LICENSE-RU.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  Лицензия MIT
2
2
 
3
- Copyright (c) 2017-2020 Александр Григорьев
3
+ Copyright (c) 2017-2023 Александр Григорьев
4
4
 
5
5
  Данная лицензия разрешает лицам, получившим копию данного программного
6
6
  обеспечения и сопутствующей документации (в дальнейшем именуемыми
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017-2020 Alexander Grigorev
3
+ Copyright (c) 2017-2023 Alexander Grigorev
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,34 +1,273 @@
1
1
  # Bemer
2
2
 
3
- **ВАЖНО**. *Для работы с UI компонентами не обязательно использовать методологию БЭМ.*
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
- 1. Позволяет создавать переиспользуемые UI компоненты для приложений на Ruby on Rails.
6
- 1. Предоставляет функционал для разработки приложений на Ruby on Rails с использованием методологии БЭМ.
6
+ **IMPORTANT**. *Using the `BEM` methodology is optional.*
7
7
 
8
- ## Дополнительно
8
+ Additional resources:
9
9
 
10
- 1. Статья на Хабре - [Переиспользуемые UI компоненты в приложениях на Ruby on Rails](https://habrahabr.ru/post/352938/).
11
- 1. [bemer-bootstrap](https://github.com/vill/bemer-bootstrap) - переиспользуемые компоненты Bootstrap v3.
12
- 1. [Пример приложения](https://github.com/vill/bemer-example) с использованием `bemer` и [bemer-bootstrap](https://github.com/vill/bemer-bootstrap).
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
- Добавить в `Gemfile`:
17
+
18
+ ## Installation
19
+
20
+ Add it to your Gemfile:
17
21
 
18
22
  ```ruby
19
- gem 'bemer', '~> 0.2.0'
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. [Файловая структура](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)
29
- 1. [Конфигурация](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)
30
- 1. [Создание и использование UI компонент](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)
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. [Шаблоны](docs/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B.md)
46
- 1. [Контекст узла](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)
47
- 1. [Предикаты](docs/%D0%9F%D1%80%D0%B5%D0%B4%D0%B8%D0%BA%D0%B0%D1%82%D1%8B.md)
48
- 1. [Режимы](docs/%D0%A0%D0%B5%D0%B6%D0%B8%D0%BC%D1%8B.md)
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://ru.bem.info/methodology/
53
- 1. https://github.com/bem/bem-xjst
54
- 1. https://github.com/bem-site/bem-forum-content-ru/issues
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 - 2020 Александр Григорьев. Более подробную информацию о лицензии можно получить в файле [LICENSE.txt](LICENSE.txt).
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
- **ВАЖНО**. *При формирование названия сущности, действуют [правила преобразования знаков нижнего подчеркивания `_` в тире `-` для `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)*
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="{&quot;form__number&quot;:{&quot;value&quot;:1}}" value="1">1</option>
32
+ / <option class="form__number i-bem" data-bem="{&quot;form__number&quot;:{&quot;value&quot;:2}}" value="2">2</option>
33
+ / <option class="form__number i-bem" data-bem="{&quot;form__number&quot;:{&quot;value&quot;:3}}" value="3">3</option>
34
+ / <option class="form__number i-bem" data-bem="{&quot;form__number&quot;:{&quot;value&quot;:4}}" value="4">4</option>
35
+ / <option class="form__number i-bem" data-bem="{&quot;form__number&quot;:{&quot;value&quot;: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` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при формирование css классов по методологии БЭМ
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` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при формирование css классов по БЭМ методологии
22
+ 1. `Symbol` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при формировании css классов по БЭМ методологии
23
23
  1. `String` возвращается без изменений
24
24
 
25
25
  ```ruby
@@ -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 = 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
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::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