bemer 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +5 -5
  2. data/{LICENSE-RU → LICENSE-RU.txt} +0 -0
  3. data/{LICENSE → LICENSE.txt} +5 -5
  4. data/README.md +47 -16
  5. data/docs/BEMHTML.md +5 -0
  6. 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 +275 -0
  7. data/docs//320/232/320/276/320/275/321/204/320/270/320/263/321/203/321/200/320/260/321/206/320/270/321/217.md +158 -0
  8. data/docs//320/237/321/200/320/265/320/264/320/270/320/272/320/260/321/202/321/213.md +205 -0
  9. data/docs//320/240/320/265/320/266/320/270/320/274/321/213.md +274 -0
  10. data/docs//320/241/320/276/320/267/320/264/320/260/320/275/320/270/320/265-/320/270-/320/270/321/201/320/277/320/276/320/273/321/214/320/267/320/276/320/262/320/260/320/275/320/270/320/265-UI-/320/272/320/276/320/274/320/277/320/276/320/275/320/265/320/275/321/202.md +173 -0
  11. data/docs//320/244/320/260/320/270/314/206/320/273/320/276/320/262/320/260/321/217-/321/201/321/202/321/200/321/203/320/272/321/202/321/203/321/200/320/260.md +167 -0
  12. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-bem_mix.md +62 -0
  13. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-bem_mods.md +63 -0
  14. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-block_tag.md +215 -0
  15. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-component_asset_path.md +71 -0
  16. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-component_pack.md +101 -0
  17. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-component_partial_path.md +28 -0
  18. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-define_component.md +154 -0
  19. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-define_templates.md +96 -0
  20. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-elem_tag.md +38 -0
  21. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-refine_component.md +114 -0
  22. data/docs//320/245/320/265/320/273/320/277/320/265/321/200-render_component.md +108 -0
  23. data/docs//320/250/320/260/320/261/320/273/320/276/320/275/321/213.md +44 -0
  24. data/lib/bemer.rb +3 -1
  25. data/lib/bemer/builders.rb +8 -0
  26. data/lib/bemer/builders/tree.rb +0 -8
  27. data/lib/bemer/configuration.rb +3 -1
  28. data/lib/bemer/context_extentions/structure.rb +2 -3
  29. data/lib/bemer/entity.rb +2 -2
  30. data/lib/bemer/entity_builder.rb +5 -9
  31. data/lib/bemer/helpers.rb +10 -0
  32. data/lib/bemer/mixin_list.rb +1 -1
  33. data/lib/bemer/modifier_list.rb +2 -2
  34. data/lib/bemer/path_resolver.rb +23 -0
  35. data/lib/bemer/pipeline/handler.rb +4 -6
  36. data/lib/bemer/railtie.rb +22 -9
  37. data/lib/bemer/renderer.rb +1 -1
  38. data/lib/bemer/template_list.rb +2 -4
  39. data/lib/bemer/tree.rb +3 -3
  40. data/lib/bemer/tree/node.rb +5 -7
  41. data/lib/bemer/version.rb +1 -1
  42. data/spec/bemer/railtie_spec.rb +95 -0
  43. data/spec/dummy/config/application.rb +30 -12
  44. data/spec/dummy/config/initializers/backtrace_silencers.rb +1 -5
  45. data/spec/dummy/config/initializers/bemer.rb +1 -3
  46. data/spec/rails_helper.rb +5 -9
  47. metadata +87 -129
  48. data/.gitignore +0 -17
  49. data/.overcommit.yml +0 -59
  50. data/.rspec +0 -4
  51. data/.rubocop.yml +0 -21
  52. data/.rubocop_todo.yml +0 -11
  53. data/Gemfile +0 -12
  54. data/Rakefile +0 -12
  55. data/bemer.gemspec +0 -43
  56. data/spec/dummy/Rakefile +0 -8
  57. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  58. data/spec/dummy/app/helpers/application_helper.rb +0 -4
  59. data/spec/dummy/app/jobs/application_job.rb +0 -4
  60. data/spec/dummy/app/mailers/application_mailer.rb +0 -6
  61. data/spec/dummy/app/models/application_record.rb +0 -5
  62. data/spec/dummy/app/models/concerns/.keep +0 -0
  63. data/spec/dummy/app/views/layouts/mailer.html.erb +0 -13
  64. data/spec/dummy/app/views/layouts/mailer.text.erb +0 -1
  65. data/spec/dummy/bin/bundle +0 -5
  66. data/spec/dummy/bin/rails +0 -6
  67. data/spec/dummy/bin/rake +0 -6
  68. data/spec/dummy/bin/setup +0 -39
  69. data/spec/dummy/bin/update +0 -31
  70. data/spec/dummy/bin/yarn +0 -13
  71. data/spec/dummy/config/cable.yml +0 -10
  72. data/spec/dummy/config/database.yml +0 -25
  73. data/spec/dummy/config/environments/development.rb +0 -51
  74. data/spec/dummy/config/environments/production.rb +0 -84
  75. data/spec/dummy/config/environments/test.rb +0 -44
  76. data/spec/dummy/config/initializers/application_controller_renderer.rb +0 -7
  77. data/spec/dummy/config/initializers/cookies_serializer.rb +0 -7
  78. data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -6
  79. data/spec/dummy/config/initializers/inflections.rb +0 -17
  80. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  81. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  82. data/spec/dummy/config/locales/en.yml +0 -33
  83. data/spec/dummy/config/puma.rb +0 -58
  84. data/spec/dummy/config/routes.rb +0 -5
  85. data/spec/dummy/config/secrets.yml +0 -32
  86. data/spec/dummy/config/spring.rb +0 -8
  87. data/spec/dummy/lib/assets/.keep +0 -0
  88. data/spec/dummy/log/.keep +0 -0
  89. data/spec/dummy/package.json +0 -5
  90. data/spec/dummy/public/404.html +0 -67
  91. data/spec/dummy/public/422.html +0 -67
  92. data/spec/dummy/public/500.html +0 -66
  93. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  94. data/spec/dummy/public/apple-touch-icon.png +0 -0
  95. data/spec/dummy/public/favicon.ico +0 -0
@@ -0,0 +1,215 @@
1
+ # Хелпер block_tag
2
+
3
+ **ВАЖНО**. *Только для компонент, [структура (дерево) которых была создана](Создание-и-использование-UI-компонент.md) с помощью [хелпера `define_component`](Хелпер-define_component.md) доступно использование [BEMHTML шаблонов](Шаблоны.md).*
4
+
5
+ **ВАЖНО**. *Для сущностей у которых не указано название, не будут созданы css классы и js атрибуты из методологии БЭМ*:
6
+ ```ruby
7
+ block_tag js: true, bem: true # => <div></div>
8
+ ```
9
+
10
+ **ВАЖНО**. *[Параметр `bem` из конфигурации](Конфигурация.md#%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80-bem) никак не влияет на работу `block_tag`.*
11
+
12
+ **ВАЖНО**. *Использование строковых (`String`) ключей при передаче параметров не допустимо, ключами могут быть только сиволы (`Symbol`).*
13
+
14
+ Позволяет создавать блок по методологии БЭМ.
15
+
16
+ ## Название сущности
17
+
18
+ При вызове `block_tag` первым аргументом передается название блока (указывать не обязательно) допустимые типы:
19
+ 1. `Symbol` ВСЕ символы нижнего подчеркивания будут преобразованы в тире, при формирование css классов по методологии БЭМ
20
+ 1. `String` возвращается без изменений
21
+
22
+ ```ruby
23
+ # Вызов без каких-либо параметров
24
+ block_tag # => <div></div>
25
+ ```
26
+ ```ruby
27
+ block_tag :block_name # => <div class="block-name"></div>
28
+ ```
29
+
30
+ **ВАЖНО**. *Будьте ВНИМАТЕЛЬНЫ при использовании названий с типом `String`, если в них содержатся знаки нижнего подчеркивания `_`, это может привести к неправильному результату согласно методологии БЭМ*:
31
+ ```ruby
32
+ block_tag 'block_name' # => <div class="block_name"></div>
33
+ ```
34
+
35
+ ## Допустимые параметры
36
+
37
+ `bem`, `bem_cascade`, `cls` (синоним `class`), `content`, `js`, `mix`, `mods` и `tag`, все остальные переданные параметры с названиями не из этого списка будут считаться атрибутами.
38
+
39
+ ### Параметр `bem`
40
+
41
+ Разрешает или запрещает использовать методологию БЭМ при создании текущего блока.
42
+
43
+ ```ruby
44
+ block_tag :block, bem: true # => <div class="block"></div>
45
+ block_tag :block, bem: false # => <div></div>
46
+ block_tag :block, bem: nil # => <div class="block"></div>
47
+ ```
48
+
49
+ ### Параметр `bem_cascade`
50
+
51
+ Разрешает или запрещает использовать методологию БЭМ для текущего блока и ТОЛЬКО всех его элементов (в [хелпере `define_component` используется для ВСЕХ ДОЧЕРНИХ ЭЛЕМЕНТОВ см. описание параметра `content`](#%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80-content))
52
+
53
+ ```ruby
54
+ block_tag :block, bem_cascade: true # => <div class="block"></div>
55
+ block_tag :block, bem_cascade: false # => <div></div>
56
+ ```
57
+
58
+ Имеет меньший приоритет чем параметр `bem`:
59
+
60
+ ```ruby
61
+ block_tag :block, bem_cascade: true, bem: false # => <div></div>
62
+ block_tag :block, bem_cascade: false, bem: true # => <div class="block"></div>
63
+ ```
64
+
65
+ ### Параметр `cls` синоним `class`
66
+
67
+ Добавляет css классы.
68
+
69
+ ```ruby
70
+ block_tag :block, cls: 'class-1', bem: false # => <div class="class-1"></div>
71
+ block_tag :block, class: 'class-1', bem: true # => <div class="block class-1"></div>
72
+ ```
73
+ ВСЕ символы нижнего подчеркивания будут преобразованы в тире, если класс передан как `Symbol`:
74
+
75
+ ```ruby
76
+ block_tag :block, cls: ['cls_1', :cls_2], bem: false # => <div class="cls_1 cls-2"></div>
77
+ ```
78
+
79
+ ### Параметр `content`
80
+
81
+ Добавляет содержимое для блока.
82
+
83
+ ```ruby
84
+ block_tag :block, content: 'Block content' # => <div>Block content</div>
85
+ ```
86
+ Если передан `Ruby &block`, тогда параметр `content` игнорируется:
87
+
88
+ ```slim
89
+ / Шаблонизатор Slim
90
+ = block_tag :block, content: 'Block content', bem: false do
91
+ h1 Content from Ruby &block
92
+
93
+ / => <div><h1>Content from Ruby &block</h1></div>
94
+ ```
95
+ Для блоков доступно альтернативное создание элементов:
96
+
97
+ ```slim
98
+ / Шаблонизатор Slim
99
+ = block_tag :block, bem_cascade: true do |block|
100
+ = block.elem :elem_1 do
101
+ = block.elem :elem_2 do
102
+ span Elem 2 content
103
+
104
+ / =>
105
+ /<div class="block">
106
+ / <div class="block__elem-1">
107
+ / <div class="block__elem-2">
108
+ / <span>Elem 2 content</span>
109
+ / </div>
110
+ / </div>
111
+ / </div>
112
+
113
+ = block_tag :block, bem_cascade: false, bem: true do |block|
114
+ = block.elem :elem_1 do
115
+ = block.elem :elem_2 do
116
+ span Elem 2 content
117
+
118
+ / =>
119
+ / <div class="block">
120
+ / <div>
121
+ / <div>
122
+ / <span>Elem 2 content</span>
123
+ / </div>
124
+ / </div>
125
+ / </div>
126
+
127
+ = block_tag :block, bem_cascade: false, bem: true do |block|
128
+ = block.elem :elem_1, bem: true do
129
+ = block.elem :elem_2 do
130
+ span Elem 2 content
131
+ / =>
132
+ / <div class="block">
133
+ / <div class="block__elem-1">
134
+ / <div>
135
+ / <span>Elem 2 content</span>
136
+ / </div>
137
+ / </div>
138
+ / </div>
139
+ ```
140
+
141
+
142
+ ### Параметр `js`
143
+
144
+ Создает атрибут `data-bem` и css класс `i-bem`.
145
+
146
+ ```ruby
147
+ block_tag :block, js: true, bem: true
148
+ # => <div class="block i-bem" data-bem="{"block":{}}"></div>
149
+
150
+ block_tag :block, js: [1, 2], bem: true
151
+ # => <div class="block i-bem" data-bem="{"block":[1,2]}"></div>
152
+
153
+ block_tag :block, js: { key: :val }, bem: true
154
+ # => <div class="block i-bem" data-bem="{"block":{"key":"val"}}"></div>
155
+
156
+ block_tag :block, js: true, bem: false # => <div></div>
157
+ ```
158
+ Для блока без имени js атрибуты не создаются:
159
+ ```ruby
160
+ block_tag js: true, bem: true # => <div></div>
161
+ ```
162
+ ### Параметр `mix`
163
+
164
+ Добавляет миксы подробнее см. [хелпер `bem_mix`](Хелпер-bem_mix.md).
165
+
166
+ ```ruby
167
+ block_tag :block, mix: [:mix_1, block_1: :elem], bem: true
168
+ # => <div class="block mix-1 block-1__elem"></div>
169
+
170
+ block_tag :block, mix: { block_1: :elem }, bem: true
171
+ # => <div class="block block-1__elem"></div>
172
+ ```
173
+
174
+ ### Параметр `mods`
175
+
176
+ Добавляет модификаторы подробнее см. [хелпер `bem_mods`](Хелпер-bem_mods.md).
177
+
178
+ ```ruby
179
+ block_tag :block, mods: :enabled, bem: true
180
+ # => <div class="block block_enabled"></div>
181
+
182
+ block_tag :block, mods: [:enabled, size: :small], bem: true
183
+ # => <div class="block block_enabled block_size_small"></div>
184
+
185
+ block_tag :block, mods: { size: :small }, bem: true
186
+ # => <div class="block block_size_small"></div>
187
+ ```
188
+
189
+ ### Параметр `tag`
190
+
191
+ Добавляет или удаляет html тег, допустимые значения: `Symbol`, `String`, `false` и `nil`.
192
+
193
+ ```ruby
194
+ block_tag :block, tag: :span, content: 'Block content'
195
+ # => <span>Block content</span>
196
+
197
+ block_tag :block, tag: '', content: 'Block content'
198
+ # => 'Block content'
199
+
200
+ block_tag :block, tag: false, content: 'Block content'
201
+ # => 'Block content'
202
+
203
+ # Будет использован default_block_tag из конфига
204
+ block_tag :block, tag: nil, content: 'Block content'
205
+ # => <div>Block content</div>
206
+ ```
207
+
208
+ ### Атрибуты
209
+
210
+ Любой параметр с названием не из [списка допустимых параметров](#%D0%94%D0%BE%D0%BF%D1%83%D1%81%D1%82%D0%B8%D0%BC%D1%8B%D0%B5-%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D1%8B) считается атрибутом:
211
+
212
+ ```ruby
213
+ block_tag :block, data: { key: :val } # => <div data-key="val"></div>
214
+ block_tag :block, key: :val # => <div key="val"></div>
215
+ ```
@@ -0,0 +1,71 @@
1
+ # Хелпер component_asset_path
2
+
3
+ **ВАЖНО**. *Необходимо делать прекомпиляцию ресурсов, с помощью `sprockets` или `webpacker`.*
4
+
5
+ Хелпер `component_asset_path` возвращает путь до ресурса (asset) компонента: изображения, файла и т.д. При вызове, хелперу необходимо передать название ресурса (asset).
6
+
7
+ Для примеров используется следующая файловая структура:
8
+
9
+ ```
10
+ app/
11
+ ├── bemer_components/
12
+ | ├── image_gallery/
13
+ | | ├── images/
14
+ | | | ├── placeholder.jpg
15
+ | | | └── ...
16
+ | | ├── _image.html.slim
17
+ | | ├── index.html.slim
18
+ | | ├── index.js
19
+ | | ├── index.scss
20
+ | | └── ...
21
+ | ├── user_profile/
22
+ | | ├── images/
23
+ | | | ├── placeholder.jpg
24
+ | | | └── ...
25
+ | | ├── index.html.slim
26
+ | | ├── index.js
27
+ | | ├── index.scss
28
+ | | └── ...
29
+ | └── ...
30
+ ├── views/
31
+ | ├── users/
32
+ | | ├── show.html.slim
33
+ | | └── ...
34
+ | ├── images/
35
+ | | ├── index.html.slim
36
+ | | └── ...
37
+ | └── ...
38
+ └── ...
39
+ ```
40
+
41
+ ## Использование
42
+
43
+ ```slim
44
+ / app/bemer_components/user_profile/index.html.slim
45
+
46
+ = component_asset_path('images/placeholder.jpg') / => 'user_profile/images/placeholder.jpg'
47
+ = component_asset_path('image_gallery/images/placeholder.jpg') / => 'image_gallery/images/placeholder.jpg'
48
+
49
+ ```
50
+
51
+ ```slim
52
+ / app/bemer_components/image_gallery/_image.html.slim
53
+
54
+ = component_asset_path('images/placeholder.jpg') / => 'image_gallery/images/placeholder.jpg'
55
+ = component_asset_path('user_profile/images/placeholder.jpg') / => 'user_profile/images/placeholder.jpg'
56
+
57
+ ```
58
+
59
+ ```slim
60
+ / app/views/users/show.html.slim
61
+
62
+ = component_asset_path('user_profile/images/placeholder.jpg') / => 'user_profile/images/placeholder.jpg'
63
+
64
+ ```
65
+
66
+ ```slim
67
+ / app/views/images/index.html.slim
68
+
69
+ = component_asset_path('image_gallery/images/placeholder.jpg') / => 'image_gallery/images/placeholder.jpg'
70
+
71
+ ```
@@ -0,0 +1,101 @@
1
+ # Хелпер component_pack
2
+
3
+ **ВАЖНО**. *`component_pack` и параметр `cached: true` позволяют лишь в некоторых случаях пропускать перекомпиляцию одних и тех же шаблонов для технологии BEMHTML, дополнительно к этому обязательно используйте кэширование которое [доступно в Rails](http://rusrails.ru/caching-with-rails-an-overview)*.
4
+
5
+ Использование `component_pack` и `cached: true` может пригодиться только в том случае, когда один и тот же компонент(ы) нужно вывести в одном месте несколько раз (используя цикл), при этом шаблоны этого компонента или используемые внутри его вызовы других компонент не зависят от итераций, для всех итераций шаблоны у них будут одни и те же (нет динамических данных в шаблонах BEMHTML).
6
+
7
+ Для всех примеров используется файловая структура:
8
+ ```
9
+ app/
10
+ ├── assets/
11
+ | ├── javascripts/
12
+ | | └── application.js
13
+ | └── stylesheets/
14
+ | └── application.css
15
+ ├── bemer_components/
16
+ | ├── common/
17
+ | | ├── alert/
18
+ | | | ├── index.html.slim
19
+ | | | ├── index.js
20
+ | | | └── index.css
21
+ | | └── ...
22
+ | └── ...
23
+ └── ...
24
+ ```
25
+ Подключение технологий JavaScript и CSS компонента `alert` при использование Sprockets:
26
+
27
+ ```js
28
+ // Файл app/assets/javascripts/application.js
29
+ //= require common/alert
30
+ ```
31
+
32
+ ```scss
33
+ // Файл app/assets/stylesheets/application.css
34
+ //= require common/alert
35
+ ```
36
+
37
+ В качестве структуры компонента `alert` будет взят [компонент `alert` из библиотеки Twitter Bootstrap](https://getbootstrap.com/docs/3.3/components/#alerts):
38
+
39
+ ```html
40
+ <!-- Исходная HTML структура компонента alert из библиотеки Twitter Bootstrap -->
41
+ <div class="alert alert-info alert-dismissible" role="alert">
42
+ <button type="button" class="close" data-dismiss="alert">
43
+ <span aria-hidden="true">&times;</span>
44
+ </button>
45
+ <strong>Warning!</strong> Better check yourself, you're not looking too good.
46
+ </div>
47
+ ```
48
+ Возможный вариант разметки компонента `alert` по БЭМ методологии:
49
+ ```slim
50
+ / Содержимое файла index.html.slim компонента alert
51
+ = define_component bem_cascade: false do |component|
52
+ = component.block :alert, tag: :div, cls: 'alert alert-dismissible', role: :alert do |alert|
53
+ = alert.elem :close, type: :button, tag: :button, cls: :close, data: { dismiss: :alert }
54
+ span aria-hidden='true' &times;
55
+ = alert.elem :message, tag: false
56
+ strong> Warning!
57
+ | Better check yourself, you're not looking too good.
58
+ ```
59
+ ## Примеры
60
+
61
+ ### Без использования `component_pack` с параметром `cached: true`
62
+
63
+ После каждой итерации, скомпилированные шаблоны компонента `alert` и шаблоны других компонент (в примере их нет), которые были созданы при вызове `render_component :alert` будут удалены, поэтому `cached: true` при вызове компонента `alert` не влияет на результат:
64
+ ```slim
65
+ - %i[success info warning danger].each do |alert_type|
66
+ = render_component :alert, cached: true do |template|
67
+ = template.block(:alert).add_cls "alert-#{alert_type}"
68
+ = template.elem(:message).content
69
+ strong = "Alert type: #{alert_type}"
70
+ ```
71
+ ![alert-cached-false](images/alert-cached-false.jpg)
72
+
73
+ ### С использованием `component_pack` без параметра `cached` (`cached: false`)
74
+
75
+ Если у компонента есть в шаблонах вызов других компонент с параметром `cached: true` или присутствуют [шаблоны по умолчанию (у `define_templates` по умолчанию параметр `cached` равен `true`)](Хелпер-define_templates.md) тогда для каждой итерации будут использоваться шаблоны из кэша (скомпилированные при первой итерации).
76
+
77
+ Шаблоны для компонента `alert` не кэшируются потому что не был передан параметр `cached: true`
78
+
79
+ ```slim
80
+ = component_pack do
81
+ - %i[success info warning danger].each do |alert_type|
82
+ = render_component :alert do |template|
83
+ = template.block(:alert).add_cls "alert-#{alert_type}"
84
+ = template.elem(:message).content
85
+ strong = "Alert type: #{alert_type}"
86
+ ```
87
+ ![alert-cached-false](images/alert-cached-false.jpg)
88
+
89
+ ### С использованием `component_pack` и параметром `cached: true`
90
+
91
+ Для всех итераций используются шаблоны которые были получены при первой итерации:
92
+ ```slim
93
+ = component_pack do
94
+ - %i[success info warning danger].each do |alert_type|
95
+ = render_component :alert, cached: true do |template|
96
+ = template.block(:alert).add_cls "alert-#{alert_type}"
97
+ = template.elem(:message).content
98
+ strong = "Alert type: #{alert_type}"
99
+ ```
100
+
101
+ ![alert-cached-true](images/alert-cached-true.jpg)
@@ -0,0 +1,28 @@
1
+ # Хелпер component_partial_path
2
+
3
+ Хелпер `component_partial_path` возвращает путь до партиала (partial) в каталоге компонента. При вызове хелпера необходимо передать название партиала (partial).
4
+
5
+ Для примеров используется следующая файловая структура:
6
+
7
+ ```
8
+ app/
9
+ ├── bemer_components/
10
+ | ├── image_gallery/
11
+ | | ├── _image.html.slim
12
+ | | ├── index.html.slim
13
+ | | ├── index.js
14
+ | | ├── index.scss
15
+ | | └── ...
16
+ └── ...
17
+ ```
18
+
19
+ ## Использование
20
+
21
+ ```slim
22
+ / app/bemer_components/image_gallery/index.html.slim
23
+
24
+ = component_partial_path(:image) / => 'image_gallery/image'
25
+
26
+ = render component_partial_path(:image)
27
+
28
+ ```
@@ -0,0 +1,154 @@
1
+ # Хелпер define_component
2
+
3
+ **ВАЖНО**. *Необходимо только описывать структуру (дерево) компонента в терминах (блок и элемент) методологии БЭМ*, **создание `css` классов и `js` атрибутов из методологии БЭМ НЕ ОБЯЗАТЕЛЬНО**.
4
+
5
+ **ВАЖНО**. *В отличие от хелперов `block_tag` и `elem_tag`, генерация данных из методологии БЭМ зависит от параметра [`bem` в конфигурации](Конфигурация.md#%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80-bem).*
6
+
7
+ **ВАЖНО**. *Доступно использование [BEMHTML шаблонов](Шаблоны.md).*
8
+
9
+ **ВАЖНО**. *Для сущностей у которых не указано название, не будут созданы css классы и js атрибуты из методологии БЭМ*.
10
+
11
+ Хелпер `define_component` позволяет описывать структуру (дерево) компонента с помощью сущностей (блок и элемент) методологии БЭМ, благодаря этому, используя BEMHTML шаблоны можно более продвинутыми способами взаимодействовать с такими типами компонент.
12
+
13
+ При вызове `define_component` обязательно нужно использовать `&block` в который будет передан билдер (builder) для построения структуры (дерева) компонента.
14
+
15
+ ## Метод `block`
16
+
17
+ Принимает такие же параметры как и [хелпер `block_tag`](Хелпер-block_tag.md).
18
+
19
+ **ВАЖНО**. *В отличие от `block_tag` и `elem_tag`, переданный в текущий узел параметр `bem_cascade` распространяется на сам узел и все его дочерние узлы (блоки и элементы), даже если текущий узел является элементом.*
20
+
21
+ Позволяет создавать блок из методологии БЭМ:
22
+ ```slim
23
+ = define_component do |component|
24
+ = component.block content: 'Plain text'
25
+
26
+ = define_component do |component|
27
+ = component.block :block_name, content: 'Plain text'
28
+
29
+ = define_component do |component|
30
+ = component.block
31
+ span Content
32
+
33
+ / bem_cascade: false применится к узлу и ко всем его дочерним узлам
34
+ = define_component do |component|
35
+ = component.block bem_cascade: false do |block|
36
+ = component.block :block2 do |block2|
37
+ = block2.elem :elem
38
+ = block.elem content: 'Plain text'
39
+ ```
40
+
41
+ ## Метод `elem`
42
+
43
+ Принимает такие же параметры как и [хелпер `elem_tag`](Хелпер-elem_tag.md).
44
+
45
+ **ВАЖНО**. *В отличие от `block_tag` и `elem_tag`, переданный в текущий узел параметр `bem_cascade` распространяется на сам узел и все его дочерние узлы (блоки и элементы), даже если текущий узел является элементом.*
46
+
47
+ Позволяет создавать элемент из методологии БЭМ:
48
+ ```slim
49
+ = define_component do |component|
50
+ = component.elem content: 'Plain text'
51
+
52
+ = define_component do |component|
53
+ = component.elem :block_name, :elem_name, content: 'Plain text'
54
+
55
+ = define_component do |component|
56
+ = component.elem
57
+ span Content
58
+
59
+ / bem_cascade: true применится к узлу и ко всем его дочерним узлам
60
+ = define_component do |component|
61
+ = component.elem bem_cascade: true
62
+ = component.block do |block|
63
+ = block.elem content: 'Plain text'
64
+ ```
65
+
66
+ ## Метод `text`
67
+
68
+ **ВАЖНО**. *Переданные параметры через методы `apply`, `apply_next`, `content` и `ctx` не будут использоваться в узлах внутри метода `text`*.
69
+
70
+ Создает текстовый узел(`TextNode`) в структуре(дереве) компонента, к узлам такого типа **не применяются шаблоны BEMHTML** и значение параметра `tag` указано как `false`, не принимает никаких дополнительных параметров.
71
+
72
+ Узлы с типом `TextNode` предназначены ТОЛЬКО для расположения текста на определенном уровне в структуре(дереве), чтобы при рендеринге компонента не происходило выталкивание вверх текстовых вставок:
73
+
74
+ ```slim
75
+ / При такой структуре 'span Content' всплывет на верх
76
+ = define_component bem_cascade: true do |component|
77
+ = component.block :block_name
78
+ span Content
79
+
80
+ / =>
81
+ / <span>Content</span>
82
+ / <div class="block-name"></div>
83
+
84
+ = define_component bem_cascade: true do |component|
85
+ = component.block :block_name
86
+ = component.text
87
+ span Content
88
+
89
+ / =>
90
+ / <div class="block-name"></div>
91
+ / <span>Content</span>
92
+
93
+ = define_component bem_cascade: true do |component|
94
+ = component.block :block_name
95
+ = component.text 'Content'
96
+
97
+ / =>
98
+ / <div class="block-name"></div>
99
+ / Content
100
+ ```
101
+
102
+ В данном случае, результат будет одинаковым, но лучше избегать использование методов `block` и `elem` внутри метода `text`:
103
+ ```slim
104
+ = define_component bem_cascade: true do |component|
105
+ = component.block :block1
106
+ = component.text
107
+ = component.block :block2 do |block2|
108
+ = block2.elem :elem
109
+
110
+ = define_component bem_cascade: true do |component|
111
+ = component.block :block1
112
+ = component.block :block2 do |block2|
113
+ = block2.elem :elem
114
+
115
+ / =>
116
+ / <div class="block1"></div>
117
+ / <div class="block2">
118
+ / <div class="block2__elem"></div>
119
+ / </div>
120
+ ```
121
+
122
+ ## Параметры по умолчанию
123
+
124
+ В `define_component` можно передать такие же параметры как и в методы `block` и `elem`, которые будут значениями по умолчанию для узлов дерева (структуры) компонента:
125
+ ```slim
126
+ / Эквивалентные записи
127
+ = define_component do |component|
128
+ = component.block :block1, tag: :div, js: true, bem: true
129
+ = component.block :block2, tag: :div, js: true, bem: true do |block2|
130
+ = block2.elem :elem, tag: :div, js: true, bem: true
131
+
132
+ = define_component tag: :div, js: true, bem: true do |component|
133
+ = component.block :block1
134
+ = component.block :block2 do |block2|
135
+ = block2.elem :elem
136
+
137
+ / =>
138
+ / <div data-bem="{"block1":{}}" class="block1 i-bem"></div>
139
+ / <div data-bem="{"block2":{}}" class="block2 i-bem">
140
+ / <div data-bem="{"block2__elem":{}}" class="block2__elem i-bem"></div>
141
+ / </div>
142
+
143
+ / Переопределение дефолтных значений
144
+ = define_component tag: :div, js: true, bem: true do |component|
145
+ = component.block :block1, js: false
146
+ = component.block :block2, js: false do |block2|
147
+ = block2.elem :elem
148
+
149
+ / =>
150
+ / <div class="block1"></div>
151
+ / <div class="block2">
152
+ / <div data-bem="{"block2__elem":{}}" class="block2__elem i-bem"></div>
153
+ / </div>
154
+ ```