hanami-helpers 0.3.0 → 0.4.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
  SHA1:
3
- metadata.gz: 00c50648c23a0d34befe080287206beb9e46aa34
4
- data.tar.gz: 2be73f77dead23bc48142b567b0a2595d9ba6a00
3
+ metadata.gz: e90f277e6ff4d461bd7ebcc45e48de6c03f91e70
4
+ data.tar.gz: 8d97b52cf45b16454acf597a6fe198b3a549148a
5
5
  SHA512:
6
- metadata.gz: ce6e712b2a0e0aaf38e79a682112a51929ec62fb77cc2f2af17c0645fddc28d56654e0c0b8dd4acf4c707c502ea7cc6dc19870e1ed7ca027304755d90dde9826
7
- data.tar.gz: 75c87873818c331507ce01574fbd5652a9be6f8e782805e4f731377f37e81429578384cc9dde5b7a1f521d6c0473ab4e6f4057ff9593fcee49bf68bdd9f6d419
6
+ metadata.gz: 21d4b2160f0d6af94d099ec8f765bbcce309b22623aff0ce3190f50b7fb2fec228fde3b6f330a47242455ab7989144e8c04b5a146170399d74f914ba0facc79f
7
+ data.tar.gz: f898b3a411eb8d77e776a398ef2873bc6b6e8ef39fffd59602f8d0b7cd53a5662ea767665a95e7da228271bb3f16cf635f3df12d28feceed507177b2e621134c
@@ -1,6 +1,20 @@
1
1
  # Hanami::Helpers
2
2
  View helpers for Ruby web applications
3
3
 
4
+ ## v0.4.0 - 2016-07-22
5
+ ### Added
6
+ - [Luca Guidi] Allow `link_to` to be concat with other helpers. Eg `link_to(...) + link_to(...)`, `span(...) + link_to(...)`.
7
+ - [Anton Davydov] Support blank `<option>` tag for `select` form helper. Eg. `select :store, [...], options: { prompt: '' }`
8
+ - [Sebastjan Hribar] Support selected `<option>` for `select` form helper. Eg. `select :store, [...], options: { selected: 'it' }`
9
+ - [Cang Ta] Added `datalist` form helper
10
+
11
+ ### Changed
12
+ – [Luca Guidi] Drop support for Ruby 2.0 and 2.1. Official support for JRuby 9.0.5.0+.
13
+ - [Luca Guidi] Inverted options (label, value) for `select` form helper. Now the syntax is `select :store, { 'Italy' => 'it', 'United States' => 'us' }`
14
+
15
+ ### Fixed
16
+ – [Nikolay Shebanov] Explicitly require some `hanami-utils` dependencies
17
+
4
18
  ## v0.3.0 - 2016-01-22
5
19
  ### Changed
6
20
  - [Luca Guidi] Renamed the project
@@ -8,20 +8,21 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Hanami::Helpers::VERSION
9
9
  spec.authors = ['Luca Guidi', 'Trung Lê', 'Alfonso Uceda']
10
10
  spec.email = ['me@lucaguidi.com', 'trung.le@ruby-journal.com', 'uceda73@gmail.com']
11
- spec.summary = %q{Hanami helpers}
12
- spec.description = %q{View helpers for Ruby applications}
11
+ spec.summary = 'Hanami helpers'
12
+ spec.description = 'View helpers for Ruby applications'
13
13
  spec.homepage = 'http://hanamirb.org'
14
14
  spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-helpers.gemspec`.split($/)
16
+ spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-helpers.gemspec`.split($/) # rubocop:disable Style/SpecialGlobalVars
17
+
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
20
  spec.require_paths = ['lib']
20
- spec.required_ruby_version = '>= 2.0.0'
21
+ spec.required_ruby_version = '>= 2.2.0'
21
22
 
22
- spec.add_dependency 'hanami-utils', '~> 0.7'
23
+ spec.add_dependency 'hanami-utils', '~> 0.8'
23
24
 
24
25
  spec.add_development_dependency 'bundler', '~> 1.6'
25
- spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rake', '~> 11'
26
27
  spec.add_development_dependency 'minitest', '~> 5.5'
27
28
  end
@@ -1 +1 @@
1
- require 'hanami/helpers'
1
+ require 'hanami/helpers' # rubocop:disable Style/FileName
@@ -4,7 +4,7 @@ module Hanami
4
4
  module Helpers
5
5
  # Escape helpers
6
6
  #
7
- # You can include this module inside your view and
7
+ # You can include this module inside your view and
8
8
  # the view will have access all methods.
9
9
  #
10
10
  # By including <tt>Hanami::Helpers::EscapeHelper</tt> it will inject private
@@ -13,6 +13,7 @@ module Hanami
13
13
  # @since 0.1.0
14
14
  module EscapeHelper
15
15
  private
16
+
16
17
  # Escape the given HTML tag content.
17
18
  #
18
19
  # This should be used only for untrusted contents: user input.
@@ -75,7 +76,7 @@ module Hanami
75
76
  end
76
77
 
77
78
  # @since 0.1.0
78
- alias_method :h, :escape_html
79
+ alias h escape_html
79
80
 
80
81
  # Escape the given HTML tag attribute.
81
82
  #
@@ -147,7 +148,7 @@ module Hanami
147
148
  end
148
149
 
149
150
  # @since 0.1.0
150
- alias_method :ha, :escape_html_attribute
151
+ alias ha escape_html_attribute
151
152
 
152
153
  # Escape an URL to be used in HTML attributes
153
154
  #
@@ -225,7 +226,7 @@ module Hanami
225
226
  end
226
227
 
227
228
  # @since 0.1.0
228
- alias_method :hu, :escape_url
229
+ alias hu escape_url
229
230
 
230
231
  # Bypass escape.
231
232
  #
@@ -28,22 +28,24 @@ module Hanami
28
28
  #
29
29
  # Supported tags and inputs:
30
30
  #
31
+ # * <tt>check_box</tt>
31
32
  # * <tt>color_field</tt>
32
33
  # * <tt>date_field</tt>
33
34
  # * <tt>datetime_field</tt>
34
35
  # * <tt>datetime_local_field</tt>
35
36
  # * <tt>email_field</tt>
36
- # * <tt>hidden_field</tt>
37
- # * <tt>file_field</tt>
38
37
  # * <tt>fields_for</tt>
38
+ # * <tt>file_field</tt>
39
39
  # * <tt>form_for</tt>
40
+ # * <tt>hidden_field</tt>
40
41
  # * <tt>label</tt>
41
- # * <tt>text_area</tt>
42
- # * <tt>text_field</tt>
42
+ # * <tt>number_field</tt>
43
43
  # * <tt>password_field</tt>
44
44
  # * <tt>radio_button</tt>
45
45
  # * <tt>select</tt>
46
46
  # * <tt>submit</tt>
47
+ # * <tt>text_area</tt>
48
+ # * <tt>text_field</tt>
47
49
  #
48
50
  # @since 0.2.0
49
51
  #
@@ -395,13 +397,13 @@ module Hanami
395
397
  # # </form>
396
398
  def form_for(name, url, options = {}, &blk)
397
399
  form = if name.is_a?(Form)
398
- options = url
399
- name
400
- else
401
- Form.new(name, url, options.delete(:values))
402
- end
400
+ options = url
401
+ name
402
+ else
403
+ Form.new(name, url, options.delete(:values))
404
+ end
403
405
 
404
- attributes = { action: form.url, method: form.verb, :'accept-charset' => DEFAULT_CHARSET, id: "#{ form.name }-form" }.merge(options)
406
+ attributes = { action: form.url, method: form.verb, :'accept-charset' => DEFAULT_CHARSET, id: "#{form.name}-form" }.merge(options)
405
407
  FormBuilder.new(form, attributes, self, &blk)
406
408
  end
407
409
 
@@ -11,18 +11,18 @@ module Hanami
11
11
  # @since 0.2.0
12
12
  #
13
13
  # @see Hanami::Helpers::HtmlHelper::HtmlBuilder
14
- class FormBuilder < ::Hanami::Helpers::HtmlHelper::HtmlBuilder
14
+ class FormBuilder < ::Hanami::Helpers::HtmlHelper::HtmlBuilder # rubocop:disable Metrics/ClassLength
15
15
  # Set of HTTP methods that are understood by web browsers
16
16
  #
17
17
  # @since 0.2.0
18
18
  # @api private
19
- BROWSER_METHODS = ['GET', 'POST'].freeze
19
+ BROWSER_METHODS = %w(GET POST).freeze
20
20
 
21
21
  # Set of HTTP methods that should NOT generate CSRF token
22
22
  #
23
23
  # @since 0.2.0
24
24
  # @api private
25
- EXCLUDED_CSRF_METHODS = ['GET'].freeze
25
+ EXCLUDED_CSRF_METHODS = %w(GET).freeze
26
26
 
27
27
  # Checked attribute value
28
28
  #
@@ -104,11 +104,13 @@ module Hanami
104
104
  #
105
105
  # @since 0.2.0
106
106
  # @api private
107
- def initialize(form, attributes, context = nil, &blk)
107
+ def initialize(form, attributes, context = nil, &blk) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
108
108
  super()
109
109
 
110
- @context = context
111
- @blk = blk
110
+ @context = context
111
+ @blk = blk
112
+ @verb = nil
113
+ @csrf_token = nil
112
114
 
113
115
  # Nested form
114
116
  if @context.nil? && attributes.is_a?(Values)
@@ -361,7 +363,7 @@ module Hanami
361
363
  # # <input type="checkbox" name="book[languages][]" value="italian" checked="checked">
362
364
  # # <input type="checkbox" name="book[languages][]" value="english">
363
365
  def check_box(name, attributes = {})
364
- _hidden_field_for_check_box( name, attributes)
366
+ _hidden_field_for_check_box(name, attributes)
365
367
  input _attributes_for_check_box(name, attributes)
366
368
  end
367
369
 
@@ -486,6 +488,7 @@ module Hanami
486
488
  # @param name [Symbol] the input name
487
489
  # @param attributes [Hash] HTML attributes to pass to the input tag
488
490
  # @option attributes [String,Array] :accept Optional set of accepted MIME Types
491
+ # @option attributes [TrueClass,FalseClass] :multiple Optional, allow multiple file upload
489
492
  #
490
493
  # @since 0.2.0
491
494
  #
@@ -515,6 +518,15 @@ module Hanami
515
518
  #
516
519
  # # Output:
517
520
  # # <input type="file" name="user[resume]" id="user-resume" accept="application/pdf,application/ms-word">
521
+ #
522
+ # @example Accepted multiple file upload (as array)
523
+ # <%=
524
+ # # ...
525
+ # file_field :resume, multiple: true
526
+ # %>
527
+ #
528
+ # # Output:
529
+ # # <input type="file" name="user[resume]" id="user-resume" multiple="multiple">
518
530
  def file_field(name, attributes = {})
519
531
  attributes[:accept] = Array(attributes[:accept]).join(ACCEPT_SEPARATOR) if attributes.key?(:accept)
520
532
  attributes = { type: :file, name: _input_name(name), id: _input_id(name) }.merge(attributes)
@@ -609,7 +621,7 @@ module Hanami
609
621
  content = nil
610
622
  end
611
623
 
612
- attributes = {name: _input_name(name), id: _input_id(name)}.merge(attributes)
624
+ attributes = { name: _input_name(name), id: _input_id(name) }.merge(attributes)
613
625
  textarea(content || _value(name), attributes)
614
626
  end
615
627
 
@@ -631,7 +643,7 @@ module Hanami
631
643
  def text_field(name, attributes = {})
632
644
  input _attributes(:text, name, attributes)
633
645
  end
634
- alias_method :input_text, :text_field
646
+ alias input_text text_field
635
647
 
636
648
  # Radio input
637
649
  #
@@ -701,7 +713,7 @@ module Hanami
701
713
  #
702
714
  # @param name [Symbol] the input name
703
715
  # @param values [Hash] a Hash to generate <tt><option></tt> tags.
704
- # Keys correspond to <tt>value</tt> and values correspond to the content.
716
+ # Values correspond to <tt>value</tt> and keys correspond to the content.
705
717
  # @param attributes [Hash] HTML attributes to pass to the input tag
706
718
  #
707
719
  # If request params have a value that corresponds to one of the given values,
@@ -713,7 +725,7 @@ module Hanami
713
725
  # @example Basic usage
714
726
  # <%=
715
727
  # # ...
716
- # values = Hash['it' => 'Italy', 'us' => 'United States']
728
+ # values = Hash['Italy' => 'it', 'United States' => 'us']
717
729
  # select :stores, values
718
730
  # %>
719
731
  #
@@ -741,21 +753,132 @@ module Hanami
741
753
  # # <option value="it" selected="selected">Italy</option>
742
754
  # # <option value="us">United States</option>
743
755
  # # </select>
744
- def select(name, values, attributes = {})
745
- options = attributes.delete(:options) || {}
756
+ #
757
+ # @example Prompt option
758
+ # <%=
759
+ # # ...
760
+ # values = Hash['it' => 'Italy', 'us' => 'United States']
761
+ # select :stores, values, options: {prompt: 'Select a store'}
762
+ # %>
763
+ #
764
+ # # Output:
765
+ # # <select name="book[store]" id="book-store">
766
+ # # <option>Select a store</option>
767
+ # # <option value="it">Italy</option>
768
+ # # <option value="us">United States</option>
769
+ # # </select>
770
+ #
771
+ # @example Selected option
772
+ # <%=
773
+ # # ...
774
+ # values = Hash['it' => 'Italy', 'us' => 'United States']
775
+ # select :stores, values, options: {selected: book.store}
776
+ # %>
777
+ #
778
+ # # Output:
779
+ # # <select name="book[store]" id="book-store">
780
+ # # <option value="it" selected="selected">Italy</option>
781
+ # # <option value="us">United States</option>
782
+ # # </select>
783
+ def select(name, values, attributes = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
784
+ options = attributes.delete(:options) { {} }
746
785
  attributes = { name: _input_name(name), id: _input_id(name) }.merge(attributes)
786
+ prompt = options.delete(:prompt)
787
+ selected = options.delete(:selected)
747
788
 
748
789
  super(attributes) do
749
- values.each do |value, content|
750
- if _value(name) == value
751
- option(content, {value: value, selected: SELECTED}.merge(options))
790
+ option(prompt) unless prompt.nil?
791
+
792
+ values.each do |content, value|
793
+ if selected == value || _value(name) == value
794
+ option(content, { value: value, selected: SELECTED }.merge(options))
752
795
  else
753
- option(content, {value: value}.merge(options))
796
+ option(content, { value: value }.merge(options))
754
797
  end
755
798
  end
756
799
  end
757
800
  end
758
801
 
802
+ # Datalist input
803
+ #
804
+ # @param name [Symbol] the input name
805
+ # @param values [Array,Hash] a collection that is transformed into <tt><option></tt> tags.
806
+ # @param list [String] the name of list for the text input, it's also the id of datalist
807
+ # @param attributes [Hash] HTML attributes to pass to the input tag
808
+ #
809
+ # @since 0.4.0
810
+ #
811
+ # @example Basic Usage
812
+ # <%=
813
+ # # ...
814
+ # values = ['Italy', 'United States']
815
+ # datalist :stores, values, 'books'
816
+ # %>
817
+ #
818
+ # # Output:
819
+ # # <input type="text" name="book[store]" id="book-store" value="" list="books">
820
+ # # <datalist id="books">
821
+ # # <option value="Italy"></option>
822
+ # # <option value="United States"></option>
823
+ # # </datalist>
824
+ #
825
+ # @example Options As Hash
826
+ # <%=
827
+ # # ...
828
+ # values = Hash['Italy' => 'it', 'United States' => 'us']
829
+ # datalist :stores, values, 'books'
830
+ # %>
831
+ #
832
+ # # Output:
833
+ # # <input type="text" name="book[store]" id="book-store" value="" list="books">
834
+ # # <datalist id="books">
835
+ # # <option value="Italy">it</option>
836
+ # # <option value="United States">us</option>
837
+ # # </datalist>
838
+ #
839
+ # @example Specify Custom Attributes For Datalist Input
840
+ # <%=
841
+ # # ...
842
+ # values = ['Italy', 'United States']
843
+ # datalist :stores, values, 'books', datalist: { class: 'form-control' }
844
+ # %>
845
+ #
846
+ # # Output:
847
+ # # <input type="text" name="book[store]" id="book-store" value="" list="books">
848
+ # # <datalist id="books" class="form-control">
849
+ # # <option value="Italy"></option>
850
+ # # <option value="United States"></option>
851
+ # # </datalist>
852
+ #
853
+ # @example Specify Custom Attributes For Options List
854
+ # <%=
855
+ # # ...
856
+ # values = ['Italy', 'United States']
857
+ # datalist :stores, values, 'books', options: { class: 'form-control' }
858
+ # %>
859
+ #
860
+ # # Output:
861
+ # # <input type="text" name="book[store]" id="book-store" value="" list="books">
862
+ # # <datalist id="books">
863
+ # # <option value="Italy" class="form-control"></option>
864
+ # # <option value="United States" class="form-control"></option>
865
+ # # </datalist>
866
+ def datalist(name, values, list, attributes = {}) # rubocop:disable Metrics/MethodLength
867
+ attrs = attributes.dup
868
+ options = attrs.delete(:options) || {}
869
+ datalist = attrs.delete(:datalist) || {}
870
+
871
+ attrs[:list] = list
872
+ datalist[:id] = list
873
+
874
+ text_field(name, attrs)
875
+ super(datalist) do
876
+ values.each do |value, content|
877
+ option(content, { value: value }.merge(options))
878
+ end
879
+ end
880
+ end
881
+
759
882
  # Submit button
760
883
  #
761
884
  # @param content [String] The content
@@ -777,6 +900,7 @@ module Hanami
777
900
  end
778
901
 
779
902
  protected
903
+
780
904
  # A set of options to pass to the sub form helpers.
781
905
  #
782
906
  # @api private
@@ -786,6 +910,7 @@ module Hanami
786
910
  end
787
911
 
788
912
  private
913
+
789
914
  # Check the current builder is top-level
790
915
  #
791
916
  # @api private
@@ -835,7 +960,7 @@ module Hanami
835
960
  # @api private
836
961
  # @since 0.2.0
837
962
  def _input_name(name)
838
- "#{ @name }[#{ name }]"
963
+ "#{@name}[#{name}]"
839
964
  end
840
965
 
841
966
  # Input <tt>id</tt> HTML attribute
@@ -877,11 +1002,11 @@ module Hanami
877
1002
  # @see Hanami::Helpers::FormHelper::FormBuilder#check_box
878
1003
  def _hidden_field_for_check_box(name, attributes)
879
1004
  if attributes[:value].nil? || !attributes[:unchecked_value].nil?
880
- input({
1005
+ input(
881
1006
  type: :hidden,
882
1007
  name: attributes[:name] || _input_name(name),
883
1008
  value: attributes.delete(:unchecked_value) || DEFAULT_UNCHECKED_VALUE
884
- })
1009
+ )
885
1010
  end
886
1011
  end
887
1012
 
@@ -900,8 +1025,8 @@ module Hanami
900
1025
  }.merge(attributes)
901
1026
 
902
1027
  value = _value(name)
903
- attributes[:checked] = CHECKED if value &&
904
- ( value == attributes[:value] || value.include?(attributes[:value]) )
1028
+ attributes[:checked] = CHECKED if !value.nil? &&
1029
+ (value == attributes[:value] || value.include?(attributes[:value]))
905
1030
 
906
1031
  attributes
907
1032
  end
@@ -34,6 +34,7 @@ module Hanami
34
34
  end
35
35
 
36
36
  private
37
+
37
38
  # Resolve the (nested) content
38
39
  #
39
40
  # @return [String] the content
@@ -68,9 +69,9 @@ module Hanami
68
69
  def _csrf_protection!
69
70
  return if @csrf_token.nil?
70
71
 
71
- _csrf_token = @csrf_token
72
+ csrf_token = @csrf_token
72
73
  @builder.resolve do
73
- input(type: :hidden, name: FormHelper::CSRF_TOKEN, value: _csrf_token)
74
+ input(type: :hidden, name: FormHelper::CSRF_TOKEN, value: csrf_token)
74
75
  end
75
76
  end
76
77
  end
@@ -3,19 +3,37 @@ require 'hanami/utils/hash'
3
3
  module Hanami
4
4
  module Helpers
5
5
  module FormHelper
6
+ # Values from params and form helpers.
7
+ #
8
+ # It's responsible to populate input values with data coming from params
9
+ # and inline values specified via form helpers like `text_field`.
10
+ #
11
+ # @since 0.2.0
12
+ # @api private
6
13
  class Values
14
+ # @since 0.2.0
15
+ # @api private
7
16
  GET_SEPARATOR = '.'.freeze
8
17
 
18
+ # @since 0.2.0
19
+ # @api private
9
20
  def initialize(values, params)
10
21
  @values = Utils::Hash.new(values).stringify!
11
22
  @params = params
12
23
  end
13
24
 
25
+ # Returns the value for the given key, if present
26
+ #
27
+ # @since 0.2.0
28
+ # @api private
14
29
  def get(key)
15
30
  @params.get(key) || _get_from_values(key)
16
31
  end
17
32
 
18
33
  private
34
+
35
+ # @since 0.2.0
36
+ # @api private
19
37
  def _get_from_values(key)
20
38
  initial_key, *keys = key.to_s.split(GET_SEPARATOR)
21
39
  result = @values[initial_key]
@@ -23,11 +41,9 @@ module Hanami
23
41
  Array(keys).each do |k|
24
42
  break if result.nil?
25
43
 
26
- result = if result.respond_to?(k)
27
- result.public_send(k)
28
- else
29
- nil
30
- end
44
+ result = if result.respond_to?(k) # rubocop:disable Style/IfUnlessModifier
45
+ result.public_send(k)
46
+ end
31
47
  end
32
48
 
33
49
  result
@@ -185,6 +185,7 @@ module Hanami
185
185
  # # </div>
186
186
  module HtmlHelper
187
187
  private
188
+
188
189
  # Instantiate an HTML builder
189
190
  #
190
191
  # @param blk [Proc,Hanami::Helpers::HtmlHelper::HtmlBuilder,NilClass] the optional content block
@@ -12,15 +12,54 @@ module Hanami
12
12
  # @api private
13
13
  #
14
14
  # @see http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#boolean-attribute
15
- BOOLEAN_ATTRIBUTES = %w{allowfullscreen async autobuffer autofocus
16
- autoplay checked compact controls declare default defaultchecked
17
- defaultmuted defaultselected defer disabled draggable enabled
18
- formnovalidate hidden indeterminate inert ismap itemscope loop
19
- multiple muted nohref noresize noshade novalidate nowrap open
20
- pauseonexit pubdate readonly required reversed scoped seamless
21
- selected sortable spellcheck translate truespeed typemustmatch
15
+ BOOLEAN_ATTRIBUTES = %w(
16
+ allowfullscreen
17
+ async
18
+ autobuffer
19
+ autofocus
20
+ autoplay
21
+ checked
22
+ compact
23
+ controls
24
+ declare
25
+ default
26
+ defaultchecked
27
+ defaultmuted
28
+ defaultselected
29
+ defer
30
+ disabled
31
+ draggable
32
+ enabled
33
+ formnovalidate
34
+ hidden
35
+ indeterminate
36
+ inert
37
+ ismap
38
+ itemscope
39
+ loop
40
+ multiple
41
+ muted
42
+ nohref
43
+ noresize
44
+ noshade
45
+ novalidate
46
+ nowrap
47
+ open
48
+ pauseonexit
49
+ pubdate
50
+ readonly
51
+ required
52
+ reversed
53
+ scoped
54
+ seamless
55
+ selected
56
+ sortable
57
+ spellcheck
58
+ translate
59
+ truespeed
60
+ typemustmatch
22
61
  visible
23
- }.freeze
62
+ ).freeze
24
63
 
25
64
  # Attributes separator
26
65
  #
@@ -49,10 +88,11 @@ module Hanami
49
88
  # @since 0.1.0
50
89
  # @api private
51
90
  def to_s
52
- %(<#{ @name }#{attributes}>)
91
+ %(<#{@name}#{attributes}>)
53
92
  end
54
93
 
55
94
  private
95
+
56
96
  # Resolve the attributes
57
97
  #
58
98
  # @return [String,NilClass] the tag attributes
@@ -60,7 +100,7 @@ module Hanami
60
100
  # @since 0.1.0
61
101
  # @api private
62
102
  def attributes
63
- return if @attributes.nil?
103
+ return unless defined?(@attributes) && !@attributes.nil?
64
104
  result = ''
65
105
 
66
106
  @attributes.each do |attribute_name, value|
@@ -79,12 +119,12 @@ module Hanami
79
119
  end
80
120
 
81
121
  # Do not render boolean attributes when their value is _false_.
82
- def boolean_attribute(attribute_name, value)
83
- %(#{ATTRIBUTES_SEPARATOR}#{ attribute_name }="#{ attribute_name }")
122
+ def boolean_attribute(attribute_name, _value)
123
+ %(#{ATTRIBUTES_SEPARATOR}#{attribute_name}="#{attribute_name}")
84
124
  end
85
125
 
86
126
  def attribute(attribute_name, value)
87
- %(#{ATTRIBUTES_SEPARATOR}#{ attribute_name }="#{ value }")
127
+ %(#{ATTRIBUTES_SEPARATOR}#{attribute_name}="#{value}")
88
128
  end
89
129
  end
90
130
  end
@@ -12,7 +12,7 @@ module Hanami
12
12
  # HTML Builder
13
13
  #
14
14
  # @since 0.1.0
15
- class HtmlBuilder
15
+ class HtmlBuilder # rubocop:disable Metrics/ClassLength
16
16
  # HTML5 content tags
17
17
  #
18
18
  # @since 0.1.0
@@ -20,103 +20,103 @@ module Hanami
20
20
  #
21
21
  # @see Hanami::Helpers::HtmlHelper::HtmlNode
22
22
  # @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element
23
- CONTENT_TAGS = [
24
- 'a',
25
- 'abbr',
26
- 'address',
27
- 'article',
28
- 'aside',
29
- 'audio',
30
- 'b',
31
- 'bdi',
32
- 'bdo',
33
- 'blockquote',
34
- 'body',
35
- 'button',
36
- 'canvas',
37
- 'caption',
38
- 'cite',
39
- 'code',
40
- 'colgroup',
41
- 'data',
42
- 'datalist',
43
- 'del',
44
- 'details',
45
- 'dfn',
46
- 'div',
47
- 'dl',
48
- 'dt',
49
- 'dd',
50
- 'em',
51
- 'fieldset',
52
- 'figcaption',
53
- 'figure',
54
- 'footer',
55
- 'form',
56
- 'h1',
57
- 'h2',
58
- 'h3',
59
- 'h4',
60
- 'h5',
61
- 'h6',
62
- 'head',
63
- 'header',
64
- 'i',
65
- 'iframe',
66
- 'ins',
67
- 'kbd',
68
- 'label',
69
- 'legend',
70
- 'li',
71
- 'link',
72
- 'main',
73
- 'map',
74
- 'mark',
75
- 'math',
76
- 'menu',
77
- 'meter',
78
- 'nav',
79
- 'noscript',
80
- 'object',
81
- 'ol',
82
- 'optgroup',
83
- 'option',
84
- 'output',
85
- 'p',
86
- 'pre',
87
- 'progress',
88
- 'q',
89
- 'rp',
90
- 'rt',
91
- 'ruby',
92
- 's',
93
- 'samp',
94
- 'script',
95
- 'section',
96
- 'select',
97
- 'small',
98
- 'span',
99
- 'strong',
100
- 'style',
101
- 'sub',
102
- 'summary',
103
- 'sup',
104
- 'svg',
105
- 'table',
106
- 'tbody',
107
- 'td',
108
- 'template',
109
- 'textarea',
110
- 'tfoot',
111
- 'th',
112
- 'thead',
113
- 'time',
114
- 'title',
115
- 'tr',
116
- 'u',
117
- 'ul',
118
- 'video',
119
- ].freeze
23
+ CONTENT_TAGS = %w(
24
+ a
25
+ abbr
26
+ address
27
+ article
28
+ aside
29
+ audio
30
+ b
31
+ bdi
32
+ bdo
33
+ blockquote
34
+ body
35
+ button
36
+ canvas
37
+ caption
38
+ cite
39
+ code
40
+ colgroup
41
+ data
42
+ datalist
43
+ del
44
+ details
45
+ dfn
46
+ div
47
+ dl
48
+ dt
49
+ dd
50
+ em
51
+ fieldset
52
+ figcaption
53
+ figure
54
+ footer
55
+ form
56
+ h1
57
+ h2
58
+ h3
59
+ h4
60
+ h5
61
+ h6
62
+ head
63
+ header
64
+ i
65
+ iframe
66
+ ins
67
+ kbd
68
+ label
69
+ legend
70
+ li
71
+ link
72
+ main
73
+ map
74
+ mark
75
+ math
76
+ menu
77
+ meter
78
+ nav
79
+ noscript
80
+ object
81
+ ol
82
+ optgroup
83
+ option
84
+ output
85
+ p
86
+ pre
87
+ progress
88
+ q
89
+ rp
90
+ rt
91
+ ruby
92
+ s
93
+ samp
94
+ script
95
+ section
96
+ select
97
+ small
98
+ span
99
+ strong
100
+ style
101
+ sub
102
+ summary
103
+ sup
104
+ svg
105
+ table
106
+ tbody
107
+ td
108
+ template
109
+ textarea
110
+ tfoot
111
+ th
112
+ thead
113
+ time
114
+ title
115
+ tr
116
+ u
117
+ ul
118
+ video
119
+ ).freeze
120
120
 
121
121
  # HTML5 empty tags
122
122
  #
@@ -125,24 +125,24 @@ module Hanami
125
125
  #
126
126
  # @see Hanami::Helpers::HtmlHelper::EmptyHtmlNode
127
127
  # @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element
128
- EMPTY_TAGS = [
129
- 'area',
130
- 'base',
131
- 'br',
132
- 'col',
133
- 'embed',
134
- 'hr',
135
- 'img',
136
- 'input',
137
- 'keygen',
138
- 'link',
139
- 'menuitem',
140
- 'meta',
141
- 'param',
142
- 'source',
143
- 'track',
144
- 'wbr',
145
- ].freeze
128
+ EMPTY_TAGS = %w(
129
+ area
130
+ base
131
+ br
132
+ col
133
+ embed
134
+ hr
135
+ img
136
+ input
137
+ keygen
138
+ link
139
+ menuitem
140
+ meta
141
+ param
142
+ source
143
+ track
144
+ wbr
145
+ ).freeze
146
146
 
147
147
  # New line separator
148
148
  #
@@ -152,8 +152,8 @@ module Hanami
152
152
 
153
153
  CONTENT_TAGS.each do |tag|
154
154
  class_eval %{
155
- def #{ tag }(content = nil, attributes = nil, &blk)
156
- @nodes << self.class.html_node.new(:#{ tag }, blk || content, attributes || content, options)
155
+ def #{tag}(content = nil, attributes = nil, &blk)
156
+ @nodes << self.class.html_node.new(:#{tag}, blk || content, attributes || content, options)
157
157
  self
158
158
  end
159
159
  }
@@ -161,8 +161,8 @@ module Hanami
161
161
 
162
162
  EMPTY_TAGS.each do |tag|
163
163
  class_eval %{
164
- def #{ tag }(attributes = nil)
165
- @nodes << EmptyHtmlNode.new(:#{ tag }, attributes)
164
+ def #{tag}(attributes = nil)
165
+ @nodes << EmptyHtmlNode.new(:#{tag}, attributes)
166
166
  self
167
167
  end
168
168
  }
@@ -310,7 +310,7 @@ module Hanami
310
310
 
311
311
  # @since 0.2.5
312
312
  # @api private
313
- alias_method :+, :text
313
+ alias + text
314
314
 
315
315
  # Resolves all the nodes and generates the markup
316
316
  #
@@ -1,3 +1,5 @@
1
+ require 'hanami/utils/escape'
2
+
1
3
  module Hanami
2
4
  module Helpers
3
5
  module HtmlHelper
@@ -36,7 +38,7 @@ module Hanami
36
38
  if @builder.nested?
37
39
  @builder.to_s
38
40
  else
39
- "#{ Utils::Escape.html(result) }"
41
+ Utils::Escape.html(result)
40
42
  end
41
43
  end
42
44
  end
@@ -1,4 +1,5 @@
1
1
  require 'hanami/helpers/html_helper/empty_html_node'
2
+ require 'hanami/utils/escape'
2
3
 
3
4
  module Hanami
4
5
  module Helpers
@@ -15,10 +16,10 @@ module Hanami
15
16
  # @param name [Symbol,String] the name of the tag
16
17
  # @param content [String,Proc,Hanami::Helpers::HtmlHelper::HtmlBuilder,NilClass] the optional content
17
18
  # @param attributes [Hash,NilClass] the optional tag attributes
18
- # @param options [Hash] a optional set of data
19
+ # @param _options [Hash] a optional set of data
19
20
  #
20
21
  # @return [Hanami::Helpers::HtmlHelper::HtmlNode]
21
- def initialize(name, content, attributes, options = {})
22
+ def initialize(name, content, attributes, _options = {})
22
23
  @builder = HtmlBuilder.new
23
24
  @name = name
24
25
  @content = case content
@@ -40,25 +41,26 @@ module Hanami
40
41
  #
41
42
  # @see Hanami::Helpers::HtmlHelper::EmptyHtmlNode#to_s
42
43
  def to_s
43
- %(#{ super }#{ content }</#{ @name }>)
44
+ %(#{super}#{content}</#{@name}>)
44
45
  end
45
46
 
46
47
  private
48
+
47
49
  # Resolve the (nested) content
48
50
  #
49
51
  # @return [String] the content
50
52
  #
51
53
  # @since 0.1.0
52
54
  # @api private
53
- def content
55
+ def content # rubocop:disable Metrics/MethodLength
54
56
  case @content
55
57
  when Proc
56
58
  result = @builder.resolve(&@content)
57
59
 
58
60
  if @builder.nested?
59
- "\n#{ @builder }\n"
61
+ "\n#{@builder}\n"
60
62
  else
61
- "\n#{ Utils::Escape.html(result) }\n"
63
+ "\n#{Utils::Escape.html(result)}\n"
62
64
  end
63
65
  else
64
66
  Utils::Escape.html(@content)
@@ -1,3 +1,5 @@
1
+ require 'hanami/utils/escape'
2
+
1
3
  module Hanami
2
4
  module Helpers
3
5
  module HtmlHelper
@@ -115,7 +115,7 @@ module Hanami
115
115
  # @example With only content
116
116
  # <%= link_to 'Home' %>
117
117
  # # => ArgumentError
118
- def link_to(content, url = nil, options = {}, &blk)
118
+ def link_to(content, url = nil, options = {}, &blk) # rubocop:disable Metrics/MethodLength
119
119
  if block_given?
120
120
  options = url || {}
121
121
  url = content
@@ -128,7 +128,7 @@ module Hanami
128
128
  raise ArgumentError
129
129
  end
130
130
 
131
- html.a(blk || content, options).to_s
131
+ html.a(blk || content, options)
132
132
  end
133
133
  end
134
134
  end
@@ -1,3 +1,5 @@
1
+ require 'hanami/utils/kernel'
2
+
1
3
  module Hanami
2
4
  module Helpers
3
5
  # Number formatter
@@ -11,6 +13,7 @@ module Hanami
11
13
  # @since 0.2.0
12
14
  module NumberFormattingHelper
13
15
  private
16
+
14
17
  # Format the given number, according to the options
15
18
  #
16
19
  # It accepts a number (<tt>Numeric</tt>) or a string representation.
@@ -1,3 +1,5 @@
1
+ require 'hanami/utils/string'
2
+
1
3
  module Hanami
2
4
  module Helpers
3
5
  # Routing helper for full stack Hanami web applications.
@@ -39,11 +41,11 @@ module Hanami
39
41
  # # <%= link_to_home %>
40
42
  module RoutingHelper
41
43
  def self.included(base)
42
- factory = "#{ Utils::String.new(base).namespace }::Routes"
44
+ factory = "#{Utils::String.new(base).namespace}::Routes"
43
45
 
44
46
  base.class_eval <<-END_EVAL, __FILE__, __LINE__
45
47
  def routes
46
- #{ factory }
48
+ #{factory}
47
49
  end
48
50
  END_EVAL
49
51
  end
@@ -3,6 +3,6 @@ module Hanami
3
3
  # Define version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '0.3.0'.freeze
6
+ VERSION = '0.4.0'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-01-22 00:00:00.000000000 Z
13
+ date: 2016-07-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: hanami-utils
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: '0.7'
21
+ version: '0.8'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: '0.7'
28
+ version: '0.8'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: bundler
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -46,14 +46,14 @@ dependencies:
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '10.0'
49
+ version: '11'
50
50
  type: :development
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: '10.0'
56
+ version: '11'
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: minitest
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -110,7 +110,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
110
  requirements:
111
111
  - - ">="
112
112
  - !ruby/object:Gem::Version
113
- version: 2.0.0
113
+ version: 2.2.0
114
114
  required_rubygems_version: !ruby/object:Gem::Requirement
115
115
  requirements:
116
116
  - - ">="
@@ -118,9 +118,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
118
  version: '0'
119
119
  requirements: []
120
120
  rubyforge_project:
121
- rubygems_version: 2.5.1
121
+ rubygems_version: 2.6.4
122
122
  signing_key:
123
123
  specification_version: 4
124
124
  summary: Hanami helpers
125
125
  test_files: []
126
- has_rdoc: