hanami-helpers 1.1.2 → 1.2.0.beta1

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: 2240795ff1bddb8305850e8473c60580701e7175528edcc25f83bad073a49fc9
4
- data.tar.gz: 704af3c5d22e74509806c87c17bb368b0935dafe6ff276d2532bbc010c59eba2
3
+ metadata.gz: e45f7f598ca31c583c6c23bc8c5462caba3c2ef912ec92d28902681fcade042f
4
+ data.tar.gz: 1471aee67afbf749bc146f0127de2c40bb08f8973bf133832251b939142a5d33
5
5
  SHA512:
6
- metadata.gz: 94778d91a095e8e7e41d58c0fa9477de162960fab463f2c8eb593b03f27ba2ac3dc7041d6fdab42b7f46783838510f0532191d678c4d5cd2225b454251b0c499
7
- data.tar.gz: 6a5c35fd9efdc2c5db4d763398e10bc51de1cf2b429e28bfcfc5b2694e2dc3a68d24d6b22658965e85e5b85202a3c1f206d920badc5bf6e70ae75335dd4d8410
6
+ metadata.gz: f894fd9f04c7e0e9ab8829f14caac0c3589345224c88bf02cda2aca4c48817c8bdf0773ab0de489a45eada4f4892eb5a494d730a1a0e616180f7f7b9347c0221
7
+ data.tar.gz: 8fbcfe52c12a78b6b7e26b2e8d7a35533b7558bbd2742466c5d79d87472306751db6f93b0eda4300b48cffb8bbda29f56a042bdc42426ffa3117604445bdd3a2
data/CHANGELOG.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # Hanami::Helpers
2
2
  View helpers for Ruby web applications
3
3
 
4
- ## v1.1.2 - 2018-04-05
5
- ### Fixed
6
- - [Luca Guidi] Ensure correct arity of `#form_for`, to be used in conjuction with `Hanami::Helpers::FormHelper::Form` (eg. `<%= form_for(form) { ... } %>`)
4
+ ## v1.2.0.beta1 - 2018-02-28
5
+ ## Added
6
+ - [Luca Guidi] Introduced `csrf_meta_tags` helper to print meta tags for CSRF protection
7
+ - [Luca Guidi] Added support for `form_for(..., remote: true)` which translates to `<form ... data-remote="true">`
8
+ - [Sean Collins] Allow HTML attributes to be specified as an array of strings or symbols (eg `<%= html.span("foo", class: %w(ui form)) %>`)
7
9
 
8
10
  ## v1.1.1 - 2018-02-27
9
11
  ### Fixed
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ['lib']
21
21
  spec.required_ruby_version = '>= 2.3.0'
22
22
 
23
- spec.add_dependency 'hanami-utils', '~> 1.1'
23
+ spec.add_dependency 'hanami-utils', '1.2.0.beta1'
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.6'
26
26
  spec.add_development_dependency 'dry-struct', '~> 0.3'
@@ -1,4 +1,5 @@
1
1
  require 'hanami/helpers/form_helper/form_builder'
2
+ require 'hanami/helpers/html_helper'
2
3
 
3
4
  module Hanami
4
5
  module Helpers
@@ -97,6 +98,8 @@ module Hanami
97
98
  # @api private
98
99
  CSRF_TOKEN = :_csrf_token
99
100
 
101
+ include HtmlHelper
102
+
100
103
  # Form object
101
104
  #
102
105
  # @since 0.2.0
@@ -229,7 +232,7 @@ module Hanami
229
232
  # @option options [Hash] :values An optional payload of objects to pass
230
233
  # @param blk [Proc] A block that describes the contents of the form
231
234
  #
232
- # @overload form_for(form, attributes = {}, &blk)
235
+ # @overload form_for(form, attributes, &blk)
233
236
  # Use Form
234
237
  # @param form [Hanami::Helpers::FormHelper::Form] a form object
235
238
  # @param attributes [Hash] HTML attributes to pass to the form tag and form values
@@ -406,15 +409,18 @@ module Hanami
406
409
  #
407
410
  # <button type="submit">Create</button>
408
411
  # </form>
409
- def form_for(name, url = nil, options = {}, &blk)
412
+ def form_for(name, url, options = {}, &blk)
410
413
  form = if name.is_a?(Form)
411
- options = url || {}
414
+ options = url
412
415
  name
413
416
  else
414
417
  Form.new(name, url, options.delete(:values))
415
418
  end
416
419
 
417
- attributes = { action: form.url, method: form.verb, 'accept-charset': DEFAULT_CHARSET, id: "#{form.name}-form" }.merge(options)
420
+ opts = options.dup
421
+ opts[:"data-remote"] = opts.delete(:remote) if opts.key?(:remote)
422
+ attributes = { action: form.url, method: form.verb, 'accept-charset': DEFAULT_CHARSET, id: "#{form.name}-form" }.merge(opts)
423
+
418
424
  FormBuilder.new(form, attributes, self, &blk)
419
425
  end
420
426
 
@@ -432,6 +438,36 @@ module Hanami
432
438
  locals[:session][CSRF_TOKEN]
433
439
  end
434
440
  end
441
+
442
+ # Prints CSRF meta tags for Unobtrusive JavaScript (UJS) purposes.
443
+ #
444
+ # @return [Hanami::Helpers::HtmlHelper::HtmlBuilder,NilClass] the tags if `csrf_token` is not `nil`
445
+ #
446
+ # @since 1.2.0
447
+ #
448
+ # @example
449
+ # <html>
450
+ # <head>
451
+ # <!-- ... -->
452
+ # <%= csrf_meta_tags %>
453
+ # </head>
454
+ # <!-- ... -->
455
+ # </html>
456
+ #
457
+ # <html>
458
+ # <head>
459
+ # <!-- ... -->
460
+ # <meta name="csrf-param" value="_csrf_token">
461
+ # <meta name="csrf-token" value="4a038be85b7603c406dcbfad4b9cdf91ec6ca138ed6441163a07bb0fdfbe25b5">
462
+ # </head>
463
+ # <!-- ... -->
464
+ # </html>
465
+ def csrf_meta_tags
466
+ return if csrf_token.nil?
467
+
468
+ html.meta(name: "csrf-param", value: CSRF_TOKEN) +
469
+ html.meta(name: "csrf-token", value: csrf_token)
470
+ end
435
471
  end
436
472
  end
437
473
  end
@@ -81,11 +81,11 @@ module Hanami
81
81
 
82
82
  # Instantiate a form builder
83
83
  #
84
- # @overload initialize(form, attributes, context, &blk)
84
+ # @overload initialize(form, attributes, params, &blk)
85
85
  # Top level form
86
86
  # @param form [Hanami::Helpers:FormHelper::Form] the form
87
87
  # @param attributes [::Hash] a set of HTML attributes
88
- # @param context [Hanami::Helpers::FormHelper]
88
+ # @param params [Hanami::Action::Params] request params
89
89
  # @param blk [Proc] a block that describes the contents of the form
90
90
  #
91
91
  # @overload initialize(form, attributes, params, &blk)
@@ -1225,19 +1225,17 @@ module Hanami
1225
1225
  # <option value="zw">Zimbabwe</option>
1226
1226
  # </select>
1227
1227
  def select(name, values, attributes = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
1228
- options = attributes.delete(:options) { {} }
1229
- multiple = attributes[:multiple]
1230
- attributes = { name: _select_input_name(name, multiple), id: _input_id(name) }.merge(attributes)
1231
- prompt = options.delete(:prompt)
1232
- selected = options.delete(:selected)
1233
- input_value = _value(name)
1228
+ options = attributes.delete(:options) { {} }
1229
+ attributes = { name: _select_input_name(name, attributes[:multiple]), id: _input_id(name) }.merge(attributes)
1230
+ prompt = options.delete(:prompt)
1231
+ selected = options.delete(:selected)
1234
1232
 
1235
1233
  super(attributes) do
1236
1234
  option(prompt) unless prompt.nil?
1237
1235
 
1238
1236
  already_selected = nil
1239
1237
  values.each do |content, value|
1240
- if (multiple || !already_selected) && (already_selected = _select_option_selected?(value, selected, input_value, multiple))
1238
+ if (attributes[:multiple] || !already_selected) && (already_selected = _select_option_selected?(value, selected, _value(name), attributes[:multiple]))
1241
1239
  option(content, { value: value, selected: SELECTED }.merge(options))
1242
1240
  else
1243
1241
  option(content, { value: value }.merge(options))
@@ -1570,35 +1568,20 @@ module Hanami
1570
1568
  select_name
1571
1569
  end
1572
1570
 
1571
+ # TODO: this has to be refactored
1572
+ #
1573
1573
  # @api private
1574
+ #
1575
+ # rubocop:disable Metrics/CyclomaticComplexity
1576
+ # rubocop:disable Metrics/PerceivedComplexity
1574
1577
  def _select_option_selected?(value, selected, input_value, multiple)
1575
- if input_value && selected.nil?
1576
- value.to_s == input_value
1577
- else
1578
- (value == selected) ||
1579
- _is_in_selected_values?(multiple, selected, value) ||
1580
- _is_current_value?(input_value, value) ||
1581
- _is_in_input_values?(multiple, input_value, value)
1582
- end
1583
- end
1584
-
1585
- # @api private
1586
- def _is_current_value?(input_value, value)
1587
- return unless input_value
1588
- value.to_s == input_value.to_s
1589
- end
1590
-
1591
- # @api private
1592
- def _is_in_selected_values?(multiple, selected, value)
1593
- return unless multiple && selected.is_a?(Array)
1594
- selected.include?(value)
1595
- end
1596
-
1597
- # @api private
1598
- def _is_in_input_values?(multiple, input_value, value)
1599
- return unless multiple && input_value.is_a?(Array)
1600
- input_value.include?(value)
1578
+ value == selected ||
1579
+ (multiple && (selected.is_a?(Array) && selected.include?(value))) ||
1580
+ (!input_value.nil? && (value.to_s == input_value.to_s)) ||
1581
+ (multiple && (input_value.is_a?(Array) && input_value.include?(value)))
1601
1582
  end
1583
+ # rubocop:enable Metrics/PerceivedComplexity
1584
+ # rubocop:enable Metrics/CyclomaticComplexity
1602
1585
 
1603
1586
  # @api private
1604
1587
  def _check_box_checked?(value, input_value)
@@ -78,7 +78,7 @@ module Hanami
78
78
  # @api private
79
79
  def initialize(name, attributes)
80
80
  @name = name
81
- @attributes = attributes
81
+ @attributes = prepare_html_attributes(attributes)
82
82
  end
83
83
 
84
84
  # Resolve and return the output
@@ -129,6 +129,21 @@ module Hanami
129
129
  def attribute(attribute_name, value)
130
130
  %(#{ATTRIBUTES_SEPARATOR}#{attribute_name}="#{value}")
131
131
  end
132
+
133
+ # Changes any attributes values that are arrays into a string joined by
134
+ # a space, as HTML expects it.
135
+ #
136
+ # @param attributes [Hash] the attributes with values to be HTMLified
137
+ #
138
+ # @return [Hash] the attributes transformed into HTML friendly values, i.e space separated strings
139
+ #
140
+ # @since 1.2.0
141
+ def prepare_html_attributes(attributes)
142
+ attributes&.inject({}) do |attrs, (key, value)|
143
+ attrs[key] = value.is_a?(Array) ? value.join(ATTRIBUTES_SEPARATOR) : value
144
+ attrs
145
+ end
146
+ end
132
147
  end
133
148
  end
134
149
  end
@@ -22,12 +22,12 @@ module Hanami
22
22
  def initialize(name, content, attributes, _options = {})
23
23
  @builder = HtmlBuilder.new
24
24
  @name = name
25
- @content = case content
26
- when Hash
25
+ @content = if content.is_a?(Hash)
27
26
  @attributes = content
28
27
  nil
29
28
  else
30
- @attributes = attributes.to_h if attributes.respond_to?(:to_h)
29
+ attributes_hash = attributes.to_h if attributes.respond_to?(:to_h)
30
+ @attributes = prepare_html_attributes(attributes_hash)
31
31
  content
32
32
  end
33
33
  end
@@ -3,6 +3,6 @@ module Hanami
3
3
  # Define version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '1.1.2'.freeze
6
+ VERSION = '1.2.0.beta1'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-05 00:00:00.000000000 Z
11
+ date: 2018-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hanami-utils
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: '1.1'
19
+ version: 1.2.0.beta1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: '1.1'
26
+ version: 1.2.0.beta1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -123,9 +123,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
123
123
  version: 2.3.0
124
124
  required_rubygems_version: !ruby/object:Gem::Requirement
125
125
  requirements:
126
- - - ">="
126
+ - - ">"
127
127
  - !ruby/object:Gem::Version
128
- version: '0'
128
+ version: 1.3.1
129
129
  requirements: []
130
130
  rubyforge_project:
131
131
  rubygems_version: 2.7.5