nested_array 2.3.0 → 3.0.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: 0f9301a9227bde8d348c788d152e3f673629fe658bf5081f7dbf46510b26159b
4
- data.tar.gz: 6bdd98b0b83e52224afa7db078007805ffc19762ae9cb1f042dfe40f0add9248
3
+ metadata.gz: 1cbdc891f87c006049f2995ac7d0337e6b0c36b3fd18eb9e71ff57725c1b3302
4
+ data.tar.gz: 07ab1ff64ded9400e418042fe8159c82e46db8603947f4da77eaa49a50b16752
5
5
  SHA512:
6
- metadata.gz: 106227d9e4b3f3c79fc2cac1ca1c340e18019ea674291d72d4712f5a780209d86913cc9c2f069f9be830bda1235a1f9572cf3a8b73f4dcff0d5c725853a29136
7
- data.tar.gz: 0c2bb221a8a49d0ac5d4deaeb0f6879ccb472a0be79866603a7c56843503a6aedec3a8910c6f396548cd6a986ed07304842076f4d4df2178be7931e5b5f72413
6
+ metadata.gz: f0cd5151f188b7323a42cddbfd114a645b6677df026933c2254e446022d04206c45d9042d3ae3d8fcada6a76efe00b2ec4184c86c8a9a6d6c2d08f2aed98b731
7
+ data.tar.gz: 49b10c6de7ab78ce83ab61e75653a9564dc9359060f3acf4c7bed9512c916302b0b6a4766516a0890144d373b1fac1207ad4bfce2c870f8c35cd21f76d492d95
data/.gitignore CHANGED
@@ -2,7 +2,6 @@
2
2
  /.yardoc
3
3
  /_yardoc/
4
4
  /coverage/
5
- /doc/
6
5
  /pkg/
7
6
  /spec/reports/
8
7
  /tmp/
data/.rspec CHANGED
@@ -1 +1,4 @@
1
- --require spec_helper
1
+ --color # Вывод в цвете
2
+ --require spec_helper # Подключить файл по умолчанию
3
+ --order rand # В случайном порядке
4
+ --format doc # Вывод в формате
data/.rubocop.yml ADDED
@@ -0,0 +1,125 @@
1
+ # Игнорировать отсутствие магического комментария:
2
+ # frozen_string_literal: true
3
+ #
4
+ # Надо понимать что мы теряем производительность если не используем замороженные
5
+ # строки там где это возможно, применяйте!: ` -"неизменяемая строка" `
6
+ Style/FrozenStringLiteralComment:
7
+ Enabled: false
8
+
9
+ # Надо понимать что есть качественное различие между
10
+ #
11
+ # module Foo
12
+ # class Bar
13
+ # end
14
+ # end
15
+ #
16
+ # и
17
+ #
18
+ # class Foo::Bar
19
+ # end
20
+ #
21
+ # Если где то в модуль вынесен код:
22
+ #
23
+ # module Foo
24
+ # X = 42
25
+ # end
26
+ #
27
+ # то следует инициализировать модуль До класса-потомка, иначе ошибка. Как выход,
28
+ # рубокоп предлагает везде использовать первый синтаксис, а это некрасиво)
29
+ Style/ClassAndModuleChildren:
30
+ Enabled: false
31
+
32
+ # Корячить пустые методы с точка-запятой, нет уж извините!
33
+ Style/EmptyMethod:
34
+ Enabled: false
35
+
36
+ # Не даёт сравнимать с нуль (... == 0), заставляет переписывать на `.zero?`, как-то вообще не согласен!
37
+ Style/NumericPredicate:
38
+ Enabled: false
39
+
40
+ Style/SymbolArray:
41
+ # Предпочитаю полный синтаксис вместо %i[foo bar], пстоянно забываю что
42
+ # такое %i, %w, %g, %Ж, %П, %x, %y, %й, %н, %я.
43
+ # EnforcedStyle: brackets
44
+ # Хотя нет, стиль написания может быть любым, учись понимать и так и сяк.
45
+ Enabled: false
46
+
47
+ # fail обычно бросает исключение, raise пребрасывает после отлова при
48
+ # необходимости.
49
+ Style/SignalException:
50
+ Enabled: false
51
+
52
+ # Что может быть более привычным чем простой if
53
+ Style/NegatedIf:
54
+ Enabled: false
55
+
56
+ Style/SymbolProc:
57
+ # Аргументы отдельно блоки отдельно:
58
+ # something.do_something(foo) { |o| o.bar }
59
+ # AllowMethodsWithArguments: true
60
+ # Отключена проверка стиля передачи блоков в метод, и так и сяк должно быть
61
+ # понятным.
62
+ Enabled: false
63
+
64
+ # Короткий синтаксис для слабаков! =) на мой взгляд, когда в одном хэш смешан
65
+ # короткий и полный синтаксис, тогда код читается рывками (читаем один
66
+ # синтаксис, преключаемся на другой, продолжать читать и потом вдруг обратно).
67
+ # Возможно дело привычки.
68
+ Style/HashSyntax:
69
+ EnforcedShorthandSyntax: never
70
+
71
+ # Разбивать метод или блок на подметоды только ради красоты кода не хочу, если
72
+ # всё что нужно сделать в методе задокумментировано и это не дублирующий код а
73
+ # просто большая отдельная задача, то почему бы и не 2000 строк.
74
+ Metrics/MethodLength:
75
+ Max: 100
76
+ Metrics/BlockLength:
77
+ Max: 300
78
+ Metrics/CyclomaticComplexity:
79
+ Max: 30
80
+ Metrics/PerceivedComplexity:
81
+ Max: 30
82
+
83
+ Metrics/ClassLength:
84
+ Max: 300
85
+ Metrics/ModuleLength:
86
+ Max: 300
87
+
88
+ # Assignment - присвоения, в том числе +=...
89
+ # Branch - явное прямое ветвление программы (вызов методов).
90
+ # Condition - логические выражения
91
+ # AbcSize = Math.sqrt(A * A + B * B + C * C)
92
+ Metrics/AbcSize:
93
+ # Enabled: false
94
+ Max: 100
95
+ CountRepeatedAttributes: false
96
+
97
+ # Я так привык — каждый пробел (отступ) должен быть обоснован, а не нафигачен
98
+ # до «красивого» отступа.
99
+ Layout/ArgumentAlignment:
100
+ EnforcedStyle: with_fixed_indentation
101
+
102
+ Layout/HashAlignment:
103
+ EnforcedHashRocketStyle: table
104
+ EnforcedColonStyle: key
105
+
106
+ Layout/FirstHashElementIndentation:
107
+ EnforcedStyle: consistent
108
+
109
+ # Терпеть не могу пробелы ради выравнивания, предпочитаю устанавливать
110
+ # необходимое количество отступов (отступ в ruby − кратен двум пробелам).
111
+ Layout/MultilineOperationIndentation:
112
+ EnforcedStyle: indented
113
+ Layout/MultilineMethodCallIndentation:
114
+ EnforcedStyle: indented
115
+
116
+ # Эммм, это ж короткий синтаксис, нахуй пробелы! array.map{|x| x.id}
117
+ Layout/SpaceBeforeBlockBraces:
118
+ EnforcedStyle: no_space
119
+ Layout/SpaceInsideBlockBraces:
120
+ EnforcedStyle: no_space
121
+ SpaceBeforeBlockParameters: false
122
+
123
+ # На какой вертикали начался блок, на той и должен закрываться.
124
+ Layout/BlockAlignment:
125
+ EnforcedStyleAlignWith: start_of_block
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.3
1
+ 2.7.8
data/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # Changelog
2
+
3
+ ## [2.4.0](https://github.com/Zlatov/nested_array/tree/2.4.0) (2023-01-19)
4
+
5
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/2.3.0...2.4.0)
6
+
7
+ ## [2.3.0](https://github.com/Zlatov/nested_array/tree/2.3.0) (2023-01-18)
8
+
9
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/2.2.1...2.3.0)
10
+
11
+ **Security fixes:**
12
+
13
+ - \[Security\] Bump activesupport from 5.2.4.1 to 6.0.3.2 [\#5](https://github.com/Zlatov/nested_array/pull/5) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
14
+
15
+ ## [2.2.1](https://github.com/Zlatov/nested_array/tree/2.2.1) (2023-01-14)
16
+
17
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/2.2.0...2.2.1)
18
+
19
+ ## [2.2.0](https://github.com/Zlatov/nested_array/tree/2.2.0) (2020-03-10)
20
+
21
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/1.1.0...2.2.0)
22
+
23
+ ## [1.1.0](https://github.com/Zlatov/nested_array/tree/1.1.0) (2020-02-14)
24
+
25
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/2.0.4...1.1.0)
26
+
27
+ ## [2.0.4](https://github.com/Zlatov/nested_array/tree/2.0.4) (2020-01-19)
28
+
29
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/2.0.3...2.0.4)
30
+
31
+ ## [2.0.3](https://github.com/Zlatov/nested_array/tree/2.0.3) (2020-01-19)
32
+
33
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/2.0.2...2.0.3)
34
+
35
+ ## [2.0.2](https://github.com/Zlatov/nested_array/tree/2.0.2) (2020-01-19)
36
+
37
+ [Full Changelog](https://github.com/Zlatov/nested_array/compare/784a121dd18007e7e7d113f03c665eb39aa9b018...2.0.2)
38
+
39
+
40
+
41
+ \* *This Changelog was automatically generated by [github_changelog_generator] (https://github.com/github-changelog-generator/github-changelog-generator)*
data/Gemfile CHANGED
@@ -3,3 +3,10 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  gem 'activesupport', '~> 6.0'
6
+
7
+ group :test do
8
+ gem 'rspec', '~> 3.10'
9
+ end
10
+
11
+ # Следим за кодом
12
+ gem 'rubocop', require: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nested_array (2.2.1)
4
+ nested_array (3.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -12,30 +12,50 @@ GEM
12
12
  minitest (~> 5.1)
13
13
  tzinfo (~> 1.1)
14
14
  zeitwerk (~> 2.2, >= 2.2.2)
15
+ ast (2.4.2)
15
16
  awesome_print (1.8.0)
16
17
  byebug (11.0.1)
17
18
  concurrent-ruby (1.1.6)
18
- diff-lcs (1.3)
19
+ diff-lcs (1.5.0)
19
20
  i18n (1.8.3)
20
21
  concurrent-ruby (~> 1.0)
21
22
  minitest (5.14.1)
23
+ parallel (1.22.1)
24
+ parser (3.2.1.1)
25
+ ast (~> 2.4.1)
26
+ rainbow (3.1.1)
22
27
  rake (10.5.0)
23
- rspec (3.9.0)
24
- rspec-core (~> 3.9.0)
25
- rspec-expectations (~> 3.9.0)
26
- rspec-mocks (~> 3.9.0)
27
- rspec-core (3.9.0)
28
- rspec-support (~> 3.9.0)
29
- rspec-expectations (3.9.0)
28
+ regexp_parser (2.7.0)
29
+ rexml (3.2.5)
30
+ rspec (3.12.0)
31
+ rspec-core (~> 3.12.0)
32
+ rspec-expectations (~> 3.12.0)
33
+ rspec-mocks (~> 3.12.0)
34
+ rspec-core (3.12.1)
35
+ rspec-support (~> 3.12.0)
36
+ rspec-expectations (3.12.2)
30
37
  diff-lcs (>= 1.2.0, < 2.0)
31
- rspec-support (~> 3.9.0)
32
- rspec-mocks (3.9.0)
38
+ rspec-support (~> 3.12.0)
39
+ rspec-mocks (3.12.3)
33
40
  diff-lcs (>= 1.2.0, < 2.0)
34
- rspec-support (~> 3.9.0)
35
- rspec-support (3.9.0)
41
+ rspec-support (~> 3.12.0)
42
+ rspec-support (3.12.0)
43
+ rubocop (1.28.2)
44
+ parallel (~> 1.10)
45
+ parser (>= 3.1.0.0)
46
+ rainbow (>= 2.2.2, < 4.0)
47
+ regexp_parser (>= 1.8, < 3.0)
48
+ rexml
49
+ rubocop-ast (>= 1.17.0, < 2.0)
50
+ ruby-progressbar (~> 1.7)
51
+ unicode-display_width (>= 1.4.0, < 3.0)
52
+ rubocop-ast (1.17.0)
53
+ parser (>= 3.1.1.0)
54
+ ruby-progressbar (1.13.0)
36
55
  thread_safe (0.3.6)
37
56
  tzinfo (1.2.7)
38
57
  thread_safe (~> 0.1)
58
+ unicode-display_width (2.4.2)
39
59
  zeitwerk (2.3.0)
40
60
 
41
61
  PLATFORMS
@@ -48,7 +68,8 @@ DEPENDENCIES
48
68
  byebug (~> 11.0)
49
69
  nested_array!
50
70
  rake (~> 10.0)
51
- rspec (~> 3.9)
71
+ rspec (~> 3.10)
72
+ rubocop
52
73
 
53
74
  BUNDLED WITH
54
75
  2.1.4
data/README-ru-old.md ADDED
@@ -0,0 +1,333 @@
1
+ # NestedArray
2
+
3
+ Предназначен для преобразования в древовидную структуру плоских данных описанных
4
+ по паттерну «Список смежности» (Adjacency List), то есть в нодах указа предок
5
+ `parent_id`. Например:
6
+
7
+ ```ruby
8
+ [
9
+ {id: 1, parent_id: nil, name: 'first', …},
10
+ {id: 2, parent_id: 1, name: 'second', …},
11
+ {id: 3, parent_id: 1, name: 'third', …}
12
+ ]
13
+ # ↓ ↓ ↓
14
+ [
15
+ {id: 1, parent_id: nil, name: 'first', children: [
16
+ {id: 2, parent_id: 1, name: 'second', …},
17
+ {id: 3, parent_id: 1, name: 'third', …}
18
+ ], …}
19
+ ]
20
+ ```
21
+
22
+
23
+
24
+
25
+ ## Установка
26
+
27
+ Добавте строку в _Gemfile_ вашего приложения:
28
+
29
+ ```ruby
30
+ # Работа с древовидными массивами.
31
+ gem "nested_array", "~> 3.0"
32
+ ```
33
+
34
+ И затем выполните `bundle install`.
35
+
36
+ Или установите его как `gem install nested_array`
37
+
38
+ Если вы планируете использовать скромный CSS гема, добавте в
39
+ файл _app/assets/stylesheets/application.scss_:
40
+
41
+ ```css
42
+ /* Отображение древовидных массивов. */
43
+ @import "nested_array";
44
+ ```
45
+
46
+
47
+ ## Использование
48
+
49
+ <a name="methods"></a>
50
+ * Список методов
51
+ * [to_nested](#to_nested) — преобразует плоскую структуру во вложенную;
52
+ * [each_nested](#each_nested) — перебирает вложенную стуктуру;
53
+ * [each_nested!](#each_nested) — перебирает вложенную стуктуру, предоставляя доступ к исходным данным;
54
+ * [nested_to_html](#nested_to_html) — преобразует вложенную структуру в html вёрстку (многоуровневый список `<ul><li>…`);
55
+ * [nested_to_options](#nested_to_options) — преобразует вложенную структуру в массив для формирования опций html-тега `<select>` с псевдографикой;
56
+ * [nested_to_collection_select](#nested_to_collection_select) — преобразует вложенную структуру в плоскую но добавляет псевдографику в тектовое поле для формирования тэга `<select>`;
57
+ * [concat_nested](#concat_nested) — скеивание вложенных структур, ноды склеиваются если путь к ним одинаков.
58
+ * Вывод
59
+ * Вложенный список ul > li
60
+
61
+
62
+ ### Список методов
63
+
64
+ <a name="to_nested"></a>
65
+ #### to_nested [↑](#methods "К методам")
66
+
67
+ Преобразует плоскую структуру во вложенную.
68
+
69
+ ```ruby
70
+ a = [{'id' => 1, 'parent_id' => nil}]
71
+ a = NestedArray::Array.new a
72
+ b = a.to_nested
73
+ ```
74
+
75
+ __Опции__
76
+
77
+ У каждой ноды вложенной структуры есть базовые свойства, такие как
78
+ идентификатор, идентификатор предка и другие. Для доступа к этим данным
79
+ используются ключи, которые можно настроить как в примере ниже. По умолчанию
80
+ используются следующие __строковые__ (_чувствительны к string/symbol_) ключи:
81
+
82
+ ```ruby
83
+ b = a.to_nested({
84
+ id: 'id', # указывает какое свойство ноды является идентификатором;
85
+ parent_id: 'parent_id', # -//- предком;
86
+ children: 'children', # -//- массивом потомков;
87
+ level: 'level' # -//- дополнительным свойством с уровнем вложенности;
88
+ root_id: nil # определяет что является корнем для построения дерева,
89
+ # например, для построения ветви корнем корнем
90
+ # является идентификатор одной из нод.
91
+ })
92
+ ```
93
+
94
+ Дополнительные опции преобразования:
95
+
96
+ ```ruby
97
+ b = a.to_nested({
98
+ hashed: false, # потомки могут храниться не в массиве а в хэше;
99
+ add_level: false, # добавляет в ноду информацию о уровене вложенности ноды;
100
+ })
101
+ ```
102
+
103
+
104
+
105
+
106
+ <a name="each_nested"></a>
107
+ #### each_nested [↑](#methods "К методам")
108
+
109
+ Перебирает вложенную стуктуру.
110
+
111
+ ```ruby
112
+ nested.each_nested do |node, parents, level, is_last_children|
113
+ puts node # > {'id' => ...}
114
+ puts parents # > [{'id' => ...}]
115
+ puts level # > 0
116
+ puts is_last_children # > false
117
+ end
118
+ ```
119
+
120
+
121
+
122
+
123
+ <a name="nested_to_html"></a>
124
+ #### nested_to_html [↑](#methods "К методам")
125
+
126
+ Формирует _html_-код для вывода вложенных структур с использованием вложенных друг в друга списков `<ul>`.
127
+
128
+ __Пример__
129
+
130
+ ```ruby
131
+ [
132
+ {'id' => 1, 'parent_id' => nil, 'name' => 'first'},
133
+ {'id' => 2, 'parent_id' => 1, 'name' => 'second'},
134
+ {'id' => 3, 'parent_id' => 1, 'name' => 'third'}
135
+ ].to_nested.nested_to_html do |node|
136
+ node['name']
137
+ end
138
+ ```
139
+
140
+ Вернёт
141
+
142
+ ```html
143
+ <li>first
144
+ <ul>
145
+ <li>second</li>
146
+ <li>third</li>
147
+ </ul>
148
+ </li>
149
+ ```
150
+
151
+ __Расширенный пример__
152
+
153
+ ```ruby
154
+ .nested_to_html li: '<li class="my">', _ul: '<i></i></ul>' do |node, parents, level|
155
+ block_options = {}
156
+ block_options[:li] = '<li class="my current">' if node['id'] == 2
157
+ [
158
+ "id: #{node['id']}, #{node['name']}, parent name: #{parents[level]&.[]('name')}",
159
+ block_options
160
+ ]
161
+ end
162
+ ```
163
+
164
+ __Опции__
165
+
166
+ Все опции могут быть аргументами метода, и только некоторые опции влияют на результат через блок — на лету (последняя строка блока).
167
+
168
+ ```ruby
169
+ tabulated: true,
170
+ inline: false,
171
+ tab: "\t",
172
+ ul: '<ul>', # может задаваться блоком
173
+ _ul: '</ul>',
174
+ li: '<li>', # может задаваться блоком
175
+ _li: '</li>',
176
+ ```
177
+
178
+
179
+
180
+
181
+ <a name="nested_to_options"></a>
182
+ #### nested_to_options [↑](#methods "К методам")
183
+
184
+ Формирования опций для html-тега &lt;select&gt;
185
+
186
+ Возвращает массив с псевдографикой, позволяющей вывести древовидную структуру.
187
+
188
+ ```ruby
189
+
190
+ [['option_text1', 'option_value1'],['option_text2', 'option_value2'],…]
191
+ ```
192
+
193
+ __Опции__
194
+
195
+ ```ruby
196
+ option_value: 'id', # Что брать в качестве значений при формировании опций селекта.
197
+ option_text: 'name',
198
+ ```
199
+
200
+
201
+
202
+
203
+ <a name="nested_to_collection_select"></a>
204
+ #### nested_to_collection_select [↑](#methods "К методам")
205
+
206
+ Преобразует вложенную структуру данных в плоскую, но добавляет в значение поля
207
+ отвечающего за текстовое представление (:name) псевдографику древовидной
208
+ структуры.
209
+
210
+ Это позволяет вывести тэг select в сносном виде для использования с вложенными
211
+ структурами.
212
+
213
+ Пример с хелпером `collection_select`
214
+
215
+ ```rb
216
+ <%= form.collection_select :catalog_ids,
217
+ Catalog.all.to_a.to_nested.nested_to_collection_select, :id, :name,
218
+ {
219
+ # prompt: true
220
+ # include_blank: true
221
+ },
222
+ {
223
+ multiple: true,
224
+ size: 10
225
+ }
226
+ %>
227
+ ```
228
+
229
+ Пример с хелпером `select` в сочетании с `options_from_collection_for_select`
230
+
231
+ ```erb
232
+ <% catalogs = Catalog.all.to_a %>
233
+ <%= form.select :catalog_ids,
234
+ options_from_collection_for_select(
235
+ catalogs.to_nested.nested_to_collection_select, :id, :name,
236
+ disabled: catalogs.select{|x| x.hidden?}.pluck(:id),
237
+ selected: form.object.catalog_ids
238
+ ),
239
+ {
240
+ # prompt: true
241
+ # include_blank: true
242
+ },
243
+ {
244
+ multiple: true,
245
+ size: 10
246
+ }
247
+ %>
248
+ ```
249
+
250
+
251
+
252
+
253
+ <a name="concat_nested"></a>
254
+ #### concat_nested [↑](#methods "К методам")
255
+
256
+ Скеивание вложенных структур.
257
+
258
+ * Ноды склеиваются если путь к ним одинаков;
259
+ * Путь определяется из сложения Текстов (конфигурируемо через :path_key);
260
+
261
+ __Опции__
262
+
263
+ ```ruby
264
+ path_separator: '-=path_separator=-',
265
+ path_key: 'text',
266
+ ```
267
+
268
+
269
+
270
+ ### Вывод
271
+
272
+ #### Вложенный список ul-li
273
+
274
+ ![Screenshot](doc/images/01.png)
275
+
276
+ ```ruby
277
+ <ul>
278
+ <% @catalogs.to_a.to_nested.each_nested do |node, origin| %>
279
+ <%= node.before -%>
280
+ <%= node.name -%>
281
+ <%= node.after -%>
282
+ <% end %>
283
+ </ul>
284
+ ```
285
+
286
+ ![Screenshot](doc/images/02.png)
287
+
288
+ #### Вложенный расскрывающийся список
289
+
290
+ ```ruby
291
+ <ul class="nested_array-details">
292
+ <% @catalogs.to_a.to_nested.each_nested details: true do |node, origin| %>
293
+ <%= node.before -%>
294
+ <%= node.name -%>
295
+ <%= node.after -%>
296
+ <% end %>
297
+ </ul>
298
+ ```
299
+
300
+ ![Screenshot](doc/images/03.png)
301
+
302
+ Если необходимо открыть некоторые узлы
303
+
304
+ ```ruby
305
+ <ul class="nested_array-details">
306
+ <% @catalogs.to_a.to_nested.each_nested details: true do |node, origin| %>
307
+ <%= node.before -%>
308
+ <%= node.name -%>
309
+ <%= node.after(open: node.is_has_children) -%>
310
+ <% end %>
311
+ </ul>
312
+ ```
313
+
314
+ ![Screenshot](doc/images/04.png)
315
+
316
+
317
+ ## Разработка
318
+
319
+
320
+
321
+
322
+
323
+
324
+ ## Содействие
325
+
326
+
327
+
328
+
329
+
330
+
331
+ ## Лицензия
332
+
333
+ В соответствии с условиями [лицензии MIT](https://opensource.org/licenses/MIT).