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 +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
|