govuk-components 3.3.0 → 4.0.0a1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1df60620e63644cfc2a2007fb73966c65701a0034787a34a504e309f8c2666f9
4
- data.tar.gz: f0c1980dde2b151960efc9a56bf6b1e443459a47f36137346e8e6336cd31ef52
3
+ metadata.gz: e5498c871090fc7b01a2bf8b6caf80a29a00d713917173e6c7350d47e99b3f56
4
+ data.tar.gz: 86369759dd515ef9fd7a9826be8c95ce3dacbcd987c59cdcc253cdb1e32648b5
5
5
  SHA512:
6
- metadata.gz: cdf8542481bbae72b25a5a16775c2bbad8d1ed51fce15f03997e5b6f24f2e18b1c03312d04a176b8cb90ba857909bd06f464a302502d1cf316b3947b81f5c4a2
7
- data.tar.gz: ae8afa05dc72db60956893985d0c0b2cab9d81573f24bf513ec0276b1d38a0472e1ae26f36bc9fd923a43a6512c7af06225de1b67cf09bb3e1cc4c828424ee61
6
+ metadata.gz: ec79d90aeab7f907b61a3105ac2a05595846d05d5af481489160aa3da47020459044c77dec97e9734a742faf1cbc86eedc46ec486899ed8f60b8fdbf85b491dc
7
+ data.tar.gz: f8b7225906230461f099835e91799117f6f6528a93e1311b01109b4210a0003e532201877377166d3cadf4ba841306e886ca41164aaeb7497b53340da530ff62
data/README.md CHANGED
@@ -6,9 +6,9 @@
6
6
  [![Gem](https://img.shields.io/gem/dt/govuk-components?logo=rubygems)](https://rubygems.org/gems/govuk-components)
7
7
  [![Test Coverage](https://api.codeclimate.com/v1/badges/cbcbc140f300b920d833/test_coverage)](https://codeclimate.com/github/DFE-Digital/govuk-components/test_coverage)
8
8
  [![GitHub license](https://img.shields.io/github/license/DFE-Digital/govuk-components)](https://github.com/DFE-Digital/govuk-components/blob/main/LICENSE)
9
- [![GOV.UK Design System Version](https://img.shields.io/badge/GOV.UK%20Design%20System-4.4.0-brightgreen)](https://design-system.service.gov.uk)
10
- [![Rails](https://img.shields.io/badge/Rails-6.1.5%20%E2%95%B1%207.0.3-E16D6D)](https://weblog.rubyonrails.org/releases/)
11
- [![Ruby](https://img.shields.io/badge/Ruby-2.7.6%20%20%E2%95%B1%203.0.3%20%20%E2%95%B1%203.1.2-E16D6D)](https://www.ruby-lang.org/en/downloads/)
9
+ [![GOV.UK Design System Version](https://img.shields.io/badge/GOV.UK%20Design%20System-4.4.1-brightgreen)](https://design-system.service.gov.uk)
10
+ [![Rails](https://img.shields.io/badge/Rails-6.1.7%20%E2%95%B1%207.0.3-E16D6D)](https://weblog.rubyonrails.org/releases/)
11
+ [![Ruby](https://img.shields.io/badge/Ruby-3.0.5%20%20%E2%95%B1%203.1.3%20%20%E2%95%B1%203.2.0-E16D6D)](https://www.ruby-lang.org/en/downloads/)
12
12
 
13
13
  This gem provides a suite of reusable components for the [GOV.UK Design System](https://design-system.service.gov.uk/). It is intended to provide a lightweight alternative to the [GOV.UK Publishing Components](https://github.com/alphagov/govuk_publishing_components) library and is built with GitHub’s [ViewComponent](https://github.com/github/view_component) framework.
14
14
 
@@ -1,5 +1,13 @@
1
1
  class GovukComponent::TableComponent::BodyComponent < GovukComponent::Base
2
- renders_many :rows, "GovukComponent::TableComponent::RowComponent"
2
+ renders_many :rows, ->(cell_data: nil, first_cell_is_header: false, classes: [], html_attributes: {}, &block) do
3
+ GovukComponent::TableComponent::RowComponent.from_body(
4
+ cell_data: cell_data,
5
+ first_cell_is_header: first_cell_is_header,
6
+ classes: classes,
7
+ html_attributes: html_attributes,
8
+ &block
9
+ )
10
+ end
3
11
 
4
12
  def initialize(rows: nil, first_cell_is_header: false, classes: [], html_attributes: {})
5
13
  super(classes: classes, html_attributes: html_attributes)
@@ -7,6 +15,10 @@ class GovukComponent::TableComponent::BodyComponent < GovukComponent::Base
7
15
  build_rows_from_row_data(rows, first_cell_is_header)
8
16
  end
9
17
 
18
+ def call
19
+ tag.tbody(**html_attributes) { safe_join(rows) }
20
+ end
21
+
10
22
  private
11
23
 
12
24
  def build_rows_from_row_data(data, first_cell_is_header)
@@ -1,7 +1,8 @@
1
1
  class GovukComponent::TableComponent::CellComponent < GovukComponent::Base
2
- attr_reader :text, :header, :numeric, :width
2
+ attr_reader :text, :header, :numeric, :width, :scope, :parent
3
3
 
4
4
  alias_method :numeric?, :numeric
5
+ alias_method :header?, :header
5
6
 
6
7
  WIDTHS = {
7
8
  "full" => "govuk-!-width-full",
@@ -12,11 +13,13 @@ class GovukComponent::TableComponent::CellComponent < GovukComponent::Base
12
13
  "one-quarter" => "govuk-!-width-one-quarter",
13
14
  }.freeze
14
15
 
15
- def initialize(header: false, text: nil, numeric: false, width: nil, classes: [], html_attributes: {})
16
- @header = header
16
+ def initialize(scope: nil, header: nil, numeric: false, text: nil, width: nil, parent: nil, classes: [], html_attributes: {})
17
17
  @text = text
18
18
  @numeric = numeric
19
19
  @width = width
20
+ @scope = scope
21
+ @parent = parent
22
+ @header = (header.nil?) ? in_thead? : header
20
23
 
21
24
  super(classes: classes, html_attributes: html_attributes)
22
25
  end
@@ -36,22 +39,45 @@ private
36
39
  end
37
40
 
38
41
  def cell_element
39
- header ? :th : :td
42
+ header ? 'th' : 'td'
40
43
  end
41
44
 
42
45
  def default_attributes
43
- { class: default_classes }
46
+ { class: default_classes, scope: determine_scope }
47
+ end
48
+
49
+ def determine_scope
50
+ conditions = { scope: scope, parent: parent, header: header, auto_table_scopes: config.enable_auto_table_scopes }
51
+
52
+ case conditions
53
+ in { scope: String }
54
+ scope
55
+ in { scope: false } | { header: false } | { auto_table_scopes: false }
56
+ nil
57
+ in { auto_table_scopes: true, parent: 'thead' }
58
+ 'col'
59
+ in { auto_table_scopes: true, parent: 'tbody' }
60
+ 'row'
61
+ else
62
+ Rails.logger.warn("No scope pattern matched")
63
+
64
+ nil
65
+ end
44
66
  end
45
67
 
46
68
  def default_classes
47
69
  if header
48
- class_names("govuk-table__header", "govuk-table__header--numeric" => numeric?, width_class => width?).split
70
+ class_names("govuk-table__header", "govuk-table__header--numeric" => numeric?, width_class => width?)
49
71
  else
50
- class_names("govuk-table__cell", "govuk-table__cell--numeric" => numeric?, width_class => width?).split
72
+ class_names("govuk-table__cell", "govuk-table__cell--numeric" => numeric?, width_class => width?)
51
73
  end
52
74
  end
53
75
 
54
76
  def width_class
55
77
  WIDTHS.fetch(width, nil)
56
78
  end
79
+
80
+ def in_thead?
81
+ parent == "thead"
82
+ end
57
83
  end
@@ -1,5 +1,12 @@
1
1
  class GovukComponent::TableComponent::HeadComponent < GovukComponent::Base
2
- renders_many :rows, "GovukComponent::TableComponent::RowComponent"
2
+ renders_many :rows, ->(cell_data: nil, classes: [], html_attributes: {}, &block) do
3
+ GovukComponent::TableComponent::RowComponent.from_head(
4
+ cell_data: cell_data,
5
+ classes: classes,
6
+ html_attributes: html_attributes,
7
+ &block
8
+ )
9
+ end
3
10
 
4
11
  attr_reader :row_data
5
12
 
@@ -9,12 +16,16 @@ class GovukComponent::TableComponent::HeadComponent < GovukComponent::Base
9
16
  build_rows_from_row_data(rows)
10
17
  end
11
18
 
19
+ def call
20
+ tag.thead(**html_attributes) { safe_join(rows) }
21
+ end
22
+
12
23
  private
13
24
 
14
25
  def build_rows_from_row_data(data)
15
26
  return if data.blank?
16
27
 
17
- data.each { |d| row(cell_data: d, header: true) }
28
+ data.each { |d| row(cell_data: d) }
18
29
  end
19
30
 
20
31
  def default_attributes
@@ -1,30 +1,64 @@
1
1
  class GovukComponent::TableComponent::RowComponent < GovukComponent::Base
2
- renders_many :cells, "GovukComponent::TableComponent::CellComponent"
2
+ renders_many :cells, ->(scope: nil, header: nil, text: nil, numeric: false, width: nil, classes: [], html_attributes: {}, &block) do
3
+ GovukComponent::TableComponent::CellComponent.new(
4
+ scope: scope,
5
+ header: header,
6
+ text: text,
7
+ numeric: numeric,
8
+ width: width,
9
+ parent: parent,
10
+ classes: classes,
11
+ html_attributes: html_attributes,
12
+ &block
13
+ )
14
+ end
3
15
 
4
- attr_reader :header, :first_cell_is_header
16
+ attr_reader :first_cell_is_header, :parent
5
17
 
6
- def initialize(cell_data: nil, first_cell_is_header: false, header: false, classes: [], html_attributes: {})
7
- @header = header
18
+ def initialize(cell_data: nil, first_cell_is_header: false, parent: nil, classes: [], html_attributes: {})
8
19
  @first_cell_is_header = first_cell_is_header
20
+ @parent = parent
9
21
 
10
22
  super(classes: classes, html_attributes: html_attributes)
11
23
 
12
24
  build_cells_from_cell_data(cell_data)
13
25
  end
14
26
 
27
+ def self.from_head(*args, **kwargs, &block)
28
+ new(*args, parent: 'thead', **kwargs, &block)
29
+ end
30
+
31
+ def self.from_body(*args, **kwargs, &block)
32
+ new(*args, parent: 'tbody', **kwargs, &block)
33
+ end
34
+
35
+ def call
36
+ tag.tr(**html_attributes) { safe_join(cells) }
37
+ end
38
+
15
39
  private
16
40
 
17
41
  def build_cells_from_cell_data(cell_data)
18
42
  return if cell_data.blank?
19
43
 
20
- cell_data.map.with_index { |cd, i| cell(header: cell_is_header?(i), text: cd) }
44
+ cell_data.each.with_index { |data, i| cell(text: data, **cell_attributes(i)) }
45
+ end
46
+
47
+ def cell_attributes(count)
48
+ cell_is_header?(count).then do |cell_is_header|
49
+ { header: cell_is_header }
50
+ end
21
51
  end
22
52
 
23
53
  def cell_is_header?(count)
24
- header || (first_cell_is_header && count.zero?)
54
+ in_thead? || (first_cell_is_header && count.zero?)
25
55
  end
26
56
 
27
57
  def default_attributes
28
58
  { class: %w(govuk-table__row) }
29
59
  end
60
+
61
+ def in_thead?
62
+ parent == "thead"
63
+ end
30
64
  end
@@ -20,6 +20,10 @@ module GovukComponent
20
20
  build(*(head ? [head, rows] : [rows[0], rows[1..]]), caption_text)
21
21
  end
22
22
 
23
+ def call
24
+ tag.table(**html_attributes) { safe_join([caption, head, bodies]) }
25
+ end
26
+
23
27
  private
24
28
 
25
29
  def build(head_data, body_data, caption_text)
@@ -1,4 +1,8 @@
1
+ require "html_attributes_utils"
2
+
1
3
  module GovukLinkHelper
4
+ using HTMLAttributesUtils
5
+
2
6
  LINK_STYLES = {
3
7
  inverse: "govuk-link--inverse",
4
8
  muted: "govuk-link--muted",
@@ -13,6 +17,11 @@ module GovukLinkHelper
13
17
  warning: "govuk-button--warning",
14
18
  }.freeze
15
19
 
20
+ NEW_TAB_ATTRIBUTES = {
21
+ target: "_blank",
22
+ rel: "noreferrer noopener"
23
+ }.freeze
24
+
16
25
  def govuk_link_classes(*styles, default_class: 'govuk-link')
17
26
  if (invalid_styles = (styles - LINK_STYLES.keys)) && invalid_styles.any?
18
27
  fail(ArgumentError, "invalid styles #{invalid_styles.to_sentence}. Valid styles are #{LINK_STYLES.keys.to_sentence}")
@@ -29,14 +38,14 @@ module GovukLinkHelper
29
38
  [default_class] + BUTTON_STYLES.values_at(*styles).compact
30
39
  end
31
40
 
32
- def govuk_link_to(name = nil, options = nil, extra_options = {}, &block)
41
+ def govuk_link_to(name = nil, options = nil, extra_options = {}, new_tab: false, &block)
33
42
  extra_options = options if block_given?
34
- html_options = build_html_options(extra_options)
43
+ html_options = build_html_options(extra_options, new_tab: new_tab)
35
44
 
36
45
  if block_given?
37
46
  link_to(name, html_options, &block)
38
47
  else
39
- link_to(name, options, html_options)
48
+ link_to(prepare_link_text(name, new_tab), options, html_options)
40
49
  end
41
50
  end
42
51
 
@@ -62,15 +71,15 @@ module GovukLinkHelper
62
71
  end
63
72
  end
64
73
 
65
- def govuk_button_link_to(name = nil, options = nil, extra_options = {}, &block)
74
+ def govuk_button_link_to(name = nil, options = nil, extra_options = {}, new_tab: false, &block)
66
75
  extra_options = options if block_given?
67
76
  html_options = GovukComponent::StartButtonComponent::LINK_ATTRIBUTES
68
- .merge build_html_options(extra_options, style: :button)
77
+ .merge build_html_options(extra_options, style: :button, new_tab: new_tab)
69
78
 
70
79
  if block_given?
71
80
  link_to(name, html_options, &block)
72
81
  else
73
- link_to(name, options, html_options)
82
+ link_to(prepare_link_text(name, new_tab), options, html_options)
74
83
  end
75
84
  end
76
85
 
@@ -87,18 +96,22 @@ module GovukLinkHelper
87
96
 
88
97
  private
89
98
 
90
- def build_html_options(provided_options, style: :link)
91
- styles = case style
92
- when :link then LINK_STYLES
93
- when :button then BUTTON_STYLES
94
- else {}
95
- end
99
+ def build_html_options(provided_options, style: :link, new_tab: false)
100
+ element_styles = { link: LINK_STYLES, button: BUTTON_STYLES }.fetch(style, {})
101
+
102
+ # we need to take a couple of extra steps here because we don't want the style
103
+ # params (inverse, muted, etc) to end up as extra attributes on the link.
96
104
 
97
- remaining_options = provided_options&.slice!(*styles.keys)
105
+ remaining_options = new_tab_options(new_tab)
106
+ .deep_merge_html_attributes(remove_styles_from_provided_options(element_styles, provided_options))
98
107
 
99
- return {} unless (style_classes = build_style_classes(style, provided_options))
108
+ style_classes = build_style_classes(style, extract_styles_from_provided_options(element_styles, provided_options))
100
109
 
101
- inject_class(remaining_options, class_name: style_classes)
110
+ combine_attributes(remaining_options, class_name: style_classes)
111
+ end
112
+
113
+ def new_tab_options(new_tab)
114
+ new_tab ? NEW_TAB_ATTRIBUTES : {}
102
115
  end
103
116
 
104
117
  def build_style_classes(style, provided_options)
@@ -111,13 +124,35 @@ private
111
124
  end
112
125
  end
113
126
 
114
- def inject_class(attributes, class_name:)
127
+ def combine_attributes(attributes, class_name:)
115
128
  attributes ||= {}
116
129
 
117
130
  attributes.with_indifferent_access.tap do |attrs|
118
131
  attrs[:class] = Array.wrap(attrs[:class]).prepend(class_name).flatten.join(" ")
119
132
  end
120
133
  end
134
+
135
+ def extract_styles_from_provided_options(styles, provided_options)
136
+ return {} if provided_options.blank?
137
+
138
+ provided_options.slice(*styles.keys)
139
+ end
140
+
141
+ def remove_styles_from_provided_options(styles, provided_options)
142
+ return {} if provided_options.blank?
143
+
144
+ provided_options&.except(*styles.keys)
145
+ end
146
+
147
+ def prepare_link_text(text, new_tab)
148
+ return text unless new_tab
149
+
150
+ new_tab_text = new_tab.is_a?(String) ? new_tab : Govuk::Components.config.default_link_new_tab_text
151
+
152
+ return text if new_tab_text.blank?
153
+
154
+ %(#{text} #{new_tab_text})
155
+ end
121
156
  end
122
157
 
123
158
  ActiveSupport.on_load(:action_view) { include GovukLinkHelper }
@@ -64,6 +64,7 @@ module Govuk
64
64
  # +:default_warning_text_icon+ "!"
65
65
  #
66
66
  # +:require_summary_list_action_visually_hidden_text+ when true forces visually hidden text to be set for every action. It can still be explicitly skipped by passing in +nil+. Defaults to +false+
67
+ # +:enable_auto_table_scopes+ automatically adds a scope of 'col' to th elements in thead and 'row' to th elements in tbody.
67
68
  DEFAULTS = {
68
69
  default_back_link_text: 'Back',
69
70
  default_breadcrumbs_collapse_on_mobile: false,
@@ -96,7 +97,10 @@ module Govuk
96
97
  default_warning_text_icon_fallback_text: "Warning",
97
98
  default_warning_text_icon: "!",
98
99
 
100
+ default_link_new_tab_text: "(opens in new tab)",
101
+
99
102
  require_summary_list_action_visually_hidden_text: false,
103
+ enable_auto_table_scopes: true,
100
104
  }.freeze
101
105
 
102
106
  DEFAULTS.each_key { |k| config_accessor(k) { DEFAULTS[k] } }
@@ -1,5 +1,5 @@
1
1
  module Govuk
2
2
  module Components
3
- VERSION = '3.3.0'.freeze
3
+ VERSION = '4.0.0a1'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk-components
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 4.0.0a1
5
5
  platform: ruby
6
6
  authors:
7
7
  - DfE developers
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-16 00:00:00.000000000 Z
11
+ date: 2023-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: html-attributes-utils
@@ -16,48 +16,48 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.9'
19
+ version: 1.0.0
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 0.9.2
22
+ version: 1.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '0.9'
29
+ version: 1.0.0
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 0.9.2
32
+ version: 1.0.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: pagy
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 5.10.1
39
+ version: '6.0'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 5.10.1
46
+ version: '6.0'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: view_component
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: 2.74.1
53
+ version: '2'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: 2.74.1
60
+ version: '2'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: deep_merge
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -120,14 +120,14 @@ dependencies:
120
120
  requirements:
121
121
  - - '='
122
122
  - !ruby/object:Gem::Version
123
- version: 4.0.0
123
+ version: 4.9.0
124
124
  type: :development
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - '='
129
129
  - !ruby/object:Gem::Version
130
- version: 4.0.0
130
+ version: 4.9.0
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: sassc-rails
133
133
  requirement: !ruby/object:Gem::Requirement
@@ -357,15 +357,11 @@ files:
357
357
  - app/components/govuk_component/summary_list_component/value_component.rb
358
358
  - app/components/govuk_component/tab_component.html.erb
359
359
  - app/components/govuk_component/tab_component.rb
360
- - app/components/govuk_component/table_component.html.erb
361
360
  - app/components/govuk_component/table_component.rb
362
- - app/components/govuk_component/table_component/body_component.html.erb
363
361
  - app/components/govuk_component/table_component/body_component.rb
364
362
  - app/components/govuk_component/table_component/caption_component.rb
365
363
  - app/components/govuk_component/table_component/cell_component.rb
366
- - app/components/govuk_component/table_component/head_component.html.erb
367
364
  - app/components/govuk_component/table_component/head_component.rb
368
- - app/components/govuk_component/table_component/row_component.html.erb
369
365
  - app/components/govuk_component/table_component/row_component.rb
370
366
  - app/components/govuk_component/tag_component.rb
371
367
  - app/components/govuk_component/traits.rb
@@ -385,7 +381,7 @@ homepage: https://github.com/DFE-Digital/govuk-components
385
381
  licenses:
386
382
  - MIT
387
383
  metadata: {}
388
- post_install_message:
384
+ post_install_message:
389
385
  rdoc_options: []
390
386
  require_paths:
391
387
  - lib
@@ -396,12 +392,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
396
392
  version: '0'
397
393
  required_rubygems_version: !ruby/object:Gem::Requirement
398
394
  requirements:
399
- - - ">="
395
+ - - ">"
400
396
  - !ruby/object:Gem::Version
401
- version: '0'
397
+ version: 1.3.1
402
398
  requirements: []
403
- rubygems_version: 3.1.6
404
- signing_key:
399
+ rubygems_version: 3.2.33
400
+ signing_key:
405
401
  specification_version: 4
406
402
  summary: Lightweight set of reusable GOV.UK Design System components
407
403
  test_files: []
@@ -1,5 +0,0 @@
1
- <%= tag.tbody(**html_attributes) do %>
2
- <% rows.each do |row| %>
3
- <%= row %>
4
- <% end %>
5
- <% end %>
@@ -1,5 +0,0 @@
1
- <%= tag.thead(**html_attributes) do %>
2
- <% rows.each do |row| %>
3
- <%= row %>
4
- <% end %>
5
- <% end %>
@@ -1,5 +0,0 @@
1
- <%= tag.tr(**html_attributes) do %>
2
- <% cells.each do |cell| %>
3
- <%= cell %>
4
- <% end %>
5
- <% end %>
@@ -1,7 +0,0 @@
1
- <%= tag.table(**html_attributes) do %>
2
- <%= caption %>
3
- <%= head %>
4
- <% bodies.each do |body| %>
5
- <%= body %>
6
- <% end %>
7
- <% end %>