actionview 6.1.3.2 → 7.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionview might be problematic. Click here for more details.

Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -262
  3. data/MIT-LICENSE +1 -1
  4. data/lib/action_view/base.rb +3 -3
  5. data/lib/action_view/buffers.rb +2 -2
  6. data/lib/action_view/cache_expiry.rb +46 -32
  7. data/lib/action_view/dependency_tracker/erb_tracker.rb +154 -0
  8. data/lib/action_view/dependency_tracker/ripper_tracker.rb +59 -0
  9. data/lib/action_view/dependency_tracker.rb +6 -147
  10. data/lib/action_view/digestor.rb +7 -4
  11. data/lib/action_view/flows.rb +4 -4
  12. data/lib/action_view/gem_version.rb +4 -4
  13. data/lib/action_view/helpers/active_model_helper.rb +1 -1
  14. data/lib/action_view/helpers/asset_tag_helper.rb +85 -30
  15. data/lib/action_view/helpers/asset_url_helper.rb +7 -7
  16. data/lib/action_view/helpers/atom_feed_helper.rb +3 -4
  17. data/lib/action_view/helpers/cache_helper.rb +51 -3
  18. data/lib/action_view/helpers/capture_helper.rb +2 -2
  19. data/lib/action_view/helpers/controller_helper.rb +2 -2
  20. data/lib/action_view/helpers/csp_helper.rb +1 -1
  21. data/lib/action_view/helpers/csrf_helper.rb +1 -1
  22. data/lib/action_view/helpers/date_helper.rb +5 -5
  23. data/lib/action_view/helpers/debug_helper.rb +3 -1
  24. data/lib/action_view/helpers/form_helper.rb +72 -12
  25. data/lib/action_view/helpers/form_options_helper.rb +65 -33
  26. data/lib/action_view/helpers/form_tag_helper.rb +73 -30
  27. data/lib/action_view/helpers/javascript_helper.rb +3 -5
  28. data/lib/action_view/helpers/number_helper.rb +3 -4
  29. data/lib/action_view/helpers/output_safety_helper.rb +2 -2
  30. data/lib/action_view/helpers/rendering_helper.rb +1 -1
  31. data/lib/action_view/helpers/sanitize_helper.rb +2 -2
  32. data/lib/action_view/helpers/tag_helper.rb +17 -4
  33. data/lib/action_view/helpers/tags/base.rb +2 -14
  34. data/lib/action_view/helpers/tags/check_box.rb +1 -1
  35. data/lib/action_view/helpers/tags/collection_select.rb +1 -1
  36. data/lib/action_view/helpers/tags/time_field.rb +10 -1
  37. data/lib/action_view/helpers/tags/weekday_select.rb +27 -0
  38. data/lib/action_view/helpers/tags.rb +3 -2
  39. data/lib/action_view/helpers/text_helper.rb +24 -13
  40. data/lib/action_view/helpers/translation_helper.rb +4 -3
  41. data/lib/action_view/helpers/url_helper.rb +122 -80
  42. data/lib/action_view/helpers.rb +25 -25
  43. data/lib/action_view/lookup_context.rb +33 -52
  44. data/lib/action_view/model_naming.rb +1 -1
  45. data/lib/action_view/path_set.rb +16 -22
  46. data/lib/action_view/railtie.rb +15 -2
  47. data/lib/action_view/render_parser.rb +188 -0
  48. data/lib/action_view/renderer/abstract_renderer.rb +2 -2
  49. data/lib/action_view/renderer/partial_renderer.rb +0 -34
  50. data/lib/action_view/renderer/renderer.rb +4 -4
  51. data/lib/action_view/renderer/streaming_template_renderer.rb +3 -3
  52. data/lib/action_view/renderer/template_renderer.rb +6 -2
  53. data/lib/action_view/rendering.rb +2 -2
  54. data/lib/action_view/ripper_ast_parser.rb +198 -0
  55. data/lib/action_view/routing_url_for.rb +1 -1
  56. data/lib/action_view/template/error.rb +108 -13
  57. data/lib/action_view/template/handlers/erb.rb +6 -0
  58. data/lib/action_view/template/handlers.rb +3 -3
  59. data/lib/action_view/template/html.rb +3 -3
  60. data/lib/action_view/template/inline.rb +3 -3
  61. data/lib/action_view/template/raw_file.rb +3 -3
  62. data/lib/action_view/template/resolver.rb +84 -311
  63. data/lib/action_view/template/text.rb +3 -3
  64. data/lib/action_view/template/types.rb +14 -12
  65. data/lib/action_view/template.rb +10 -1
  66. data/lib/action_view/template_details.rb +66 -0
  67. data/lib/action_view/template_path.rb +64 -0
  68. data/lib/action_view/test_case.rb +6 -2
  69. data/lib/action_view/testing/resolvers.rb +11 -12
  70. data/lib/action_view/unbound_template.rb +33 -7
  71. data/lib/action_view.rb +3 -4
  72. data/lib/assets/compiled/rails-ujs.js +2 -2
  73. metadata +25 -18
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cgi"
4
- require "action_view/helpers/tag_helper"
4
+ require "action_view/helpers/url_helper"
5
+ require "action_view/helpers/text_helper"
5
6
  require "active_support/core_ext/string/output_safety"
6
7
  require "active_support/core_ext/module/attribute_accessors"
7
- require "active_support/core_ext/symbol/starts_ends_with"
8
8
 
9
9
  module ActionView
10
10
  # = Action View Form Tag Helpers
11
- module Helpers #:nodoc:
11
+ module Helpers # :nodoc:
12
12
  # Provides a number of methods for creating form tags that don't rely on an Active Record object assigned to the template like
13
13
  # FormHelper does. Instead, you provide the names and values manually.
14
14
  #
@@ -78,6 +78,42 @@ module ActionView
78
78
  end
79
79
  end
80
80
 
81
+ # Generate an HTML <tt>id</tt> attribute value for the given name and
82
+ # field combination
83
+ #
84
+ # Return the value generated by the <tt>FormBuilder</tt> for the given
85
+ # attribute name.
86
+ #
87
+ # <%= label_tag :post, :title %>
88
+ # <%= text_field_tag :post, :title, aria: { describedby: field_id(:post, :title, :error) } %>
89
+ # <%= tag.span("is blank", id: field_id(:post, :title, :error) %>
90
+ #
91
+ # In the example above, the <tt><input type="text"></tt> element built by
92
+ # the call to <tt>text_field_tag</tt> declares an
93
+ # <tt>aria-describedby</tt> attribute referencing the <tt><span></tt>
94
+ # element, sharing a common <tt>id</tt> root (<tt>post_title</tt>, in this
95
+ # case).
96
+ def field_id(object_name, method_name, *suffixes, index: nil)
97
+ if object_name.respond_to?(:model_name)
98
+ object_name = object_name.model_name.singular
99
+ end
100
+
101
+ sanitized_object_name = object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").delete_suffix("_")
102
+
103
+ sanitized_method_name = method_name.to_s.delete_suffix("?")
104
+
105
+ # a little duplication to construct fewer strings
106
+ if sanitized_object_name.empty?
107
+ sanitized_method_name
108
+ elsif suffixes.any?
109
+ [sanitized_object_name, index, sanitized_method_name, *suffixes].compact.join("_")
110
+ elsif index
111
+ "#{sanitized_object_name}_#{index}_#{sanitized_method_name}"
112
+ else
113
+ "#{sanitized_object_name}_#{sanitized_method_name}"
114
+ end
115
+ end
116
+
81
117
  # Creates a dropdown selection box, or if the <tt>:multiple</tt> option is set to true, a multiple
82
118
  # choice selection box.
83
119
  #
@@ -167,8 +203,8 @@ module ActionView
167
203
  # * <tt>:size</tt> - The number of visible characters that will fit in the input.
168
204
  # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
169
205
  # * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
170
- # If set to true, use a translation is found in the current I18n locale
171
- # (through helpers.placeholders.<modelname>.<attribute>).
206
+ # If set to true, use the translation found in the current I18n locale
207
+ # (through helpers.placeholder.<modelname>.<attribute>).
172
208
  # * Any other key creates standard HTML attributes for the tag.
173
209
  #
174
210
  # ==== Examples
@@ -417,16 +453,6 @@ module ActionView
417
453
  # * <tt>:disabled</tt> - If true, the user will not be able to use this input.
418
454
  # * Any other key creates standard HTML options for the tag.
419
455
  #
420
- # ==== Data attributes
421
- #
422
- # * <tt>confirm: 'question?'</tt> - If present the unobtrusive JavaScript
423
- # drivers will provide a prompt with the question specified. If the user accepts,
424
- # the form is processed normally, otherwise no action is taken.
425
- # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
426
- # disabled version of the submit button when the form is submitted. This feature is
427
- # provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
428
- # pass <tt>:data => { disable_with: false }</tt> Defaults to value attribute.
429
- #
430
456
  # ==== Examples
431
457
  # submit_tag
432
458
  # # => <input name="commit" data-disable-with="Save changes" type="submit" value="Save changes" />
@@ -437,15 +463,28 @@ module ActionView
437
463
  # submit_tag "Save edits", disabled: true
438
464
  # # => <input disabled="disabled" name="commit" data-disable-with="Save edits" type="submit" value="Save edits" />
439
465
  #
440
- # submit_tag "Complete sale", data: { disable_with: "Submitting..." }
441
- # # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
442
- #
443
466
  # submit_tag nil, class: "form_submit"
444
467
  # # => <input class="form_submit" name="commit" type="submit" />
445
468
  #
446
469
  # submit_tag "Edit", class: "edit_button"
447
470
  # # => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
448
471
  #
472
+ # ==== Deprecated: Rails UJS attributes
473
+ #
474
+ # Prior to Rails 7, Rails shipped with the JavaScript library called @rails/ujs on by default. Following Rails 7,
475
+ # this library is no longer on by default. This library integrated with the following options:
476
+ #
477
+ # * <tt>confirm: 'question?'</tt> - If present the unobtrusive JavaScript
478
+ # drivers will provide a prompt with the question specified. If the user accepts,
479
+ # the form is processed normally, otherwise no action is taken.
480
+ # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a
481
+ # disabled version of the submit button when the form is submitted. This feature is
482
+ # provided by the unobtrusive JavaScript driver. To disable this feature for a single submit tag
483
+ # pass <tt>:data => { disable_with: false }</tt> Defaults to value attribute.
484
+ #
485
+ # submit_tag "Complete sale", data: { disable_with: "Submitting..." }
486
+ # # => <input name="commit" data-disable-with="Submitting..." type="submit" value="Complete sale" />
487
+ #
449
488
  # submit_tag "Save", data: { confirm: "Are you sure?" }
450
489
  # # => <input name='commit' type='submit' value='Save' data-disable-with="Save" data-confirm="Are you sure?" />
451
490
  #
@@ -470,17 +509,6 @@ module ActionView
470
509
  # use this input.
471
510
  # * Any other key creates standard HTML options for the tag.
472
511
  #
473
- # ==== Data attributes
474
- #
475
- # * <tt>confirm: 'question?'</tt> - If present, the
476
- # unobtrusive JavaScript drivers will provide a prompt with
477
- # the question specified. If the user accepts, the form is
478
- # processed normally, otherwise no action is taken.
479
- # * <tt>:disable_with</tt> - Value of this parameter will be
480
- # used as the value for a disabled version of the submit
481
- # button when the form is submitted. This feature is provided
482
- # by the unobtrusive JavaScript driver.
483
- #
484
512
  # ==== Examples
485
513
  # button_tag
486
514
  # # => <button name="button" type="submit">Button</button>
@@ -501,6 +529,20 @@ module ActionView
501
529
  # # <strong>Ask me!</strong>
502
530
  # # </button>
503
531
  #
532
+ # ==== Deprecated: Rails UJS attributes
533
+ #
534
+ # Prior to Rails 7, Rails shipped with a JavaScript library called @rails/ujs on by default. Following Rails 7,
535
+ # this library is no longer on by default. This library integrated with the following options:
536
+ #
537
+ # * <tt>confirm: 'question?'</tt> - If present, the
538
+ # unobtrusive JavaScript drivers will provide a prompt with
539
+ # the question specified. If the user accepts, the form is
540
+ # processed normally, otherwise no action is taken.
541
+ # * <tt>:disable_with</tt> - Value of this parameter will be
542
+ # used as the value for a disabled version of the submit
543
+ # button when the form is submitted. This feature is provided
544
+ # by the unobtrusive JavaScript driver.
545
+ #
504
546
  # button_tag "Save", data: { confirm: "Are you sure?" }
505
547
  # # => <button name="button" type="submit" data-confirm="Are you sure?">Save</button>
506
548
  #
@@ -677,6 +719,7 @@ module ActionView
677
719
  # * <tt>:min</tt> - The minimum acceptable value.
678
720
  # * <tt>:max</tt> - The maximum acceptable value.
679
721
  # * <tt>:step</tt> - The acceptable value granularity.
722
+ # * <tt>:include_seconds</tt> - Include seconds and ms in the output timestamp format (true by default).
680
723
  # * Otherwise accepts the same options as text_field_tag.
681
724
  def time_field_tag(name, value = nil, options = {})
682
725
  text_field_tag(name, value, options.merge(type: :time))
@@ -887,7 +930,7 @@ module ActionView
887
930
 
888
931
  def form_tag_with_body(html_options, content)
889
932
  output = form_tag_html(html_options)
890
- output << content
933
+ output << content.to_s if content
891
934
  output.safe_concat("</form>")
892
935
  end
893
936
 
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "action_view/helpers/tag_helper"
4
-
5
3
  module ActionView
6
- module Helpers #:nodoc:
4
+ module Helpers # :nodoc:
7
5
  module JavaScriptHelper
8
6
  JS_ESCAPE_MAP = {
9
- '\\' => '\\\\',
7
+ "\\" => "\\\\",
10
8
  "</" => '<\/',
11
9
  "\r\n" => '\n',
12
10
  "\n" => '\n',
@@ -89,7 +87,7 @@ module ActionView
89
87
  content_tag("script", javascript_cdata_section(content), html_options)
90
88
  end
91
89
 
92
- def javascript_cdata_section(content) #:nodoc:
90
+ def javascript_cdata_section(content) # :nodoc:
93
91
  "\n//#{cdata_section("\n#{content}\n//")}\n".html_safe
94
92
  end
95
93
  end
@@ -6,7 +6,7 @@ require "active_support/number_helper"
6
6
 
7
7
  module ActionView
8
8
  # = Action View Number Helpers
9
- module Helpers #:nodoc:
9
+ module Helpers # :nodoc:
10
10
  # Provides methods for converting numbers into formatted strings.
11
11
  # Methods are provided for phone numbers, currency, percentage,
12
12
  # precision, positional notation, file size and pretty printing.
@@ -448,9 +448,8 @@ module ActionView
448
448
  end
449
449
 
450
450
  def parse_float(number, raise_error)
451
- Float(number)
452
- rescue ArgumentError, TypeError
453
- raise InvalidNumberError, number if raise_error
451
+ result = Float(number, exception: false)
452
+ raise InvalidNumberError, number if result.nil? && raise_error
454
453
  end
455
454
  end
456
455
  end
@@ -2,9 +2,9 @@
2
2
 
3
3
  require "active_support/core_ext/string/output_safety"
4
4
 
5
- module ActionView #:nodoc:
5
+ module ActionView # :nodoc:
6
6
  # = Action View Raw Output Helper
7
- module Helpers #:nodoc:
7
+ module Helpers # :nodoc:
8
8
  module OutputSafetyHelper
9
9
  # This method outputs without escaping a string. Since escaping tags is
10
10
  # now default, this can be used when you don't want Rails to automatically
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionView
4
- module Helpers #:nodoc:
4
+ module Helpers # :nodoc:
5
5
  # = Action View Rendering
6
6
  #
7
7
  # Implements methods that allow rendering from a view context.
@@ -4,7 +4,7 @@ require "rails-html-sanitizer"
4
4
 
5
5
  module ActionView
6
6
  # = Action View Sanitize Helpers
7
- module Helpers #:nodoc:
7
+ module Helpers # :nodoc:
8
8
  # The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements.
9
9
  # These helper methods extend Action View making them callable within your template files.
10
10
  module SanitizeHelper
@@ -121,7 +121,7 @@ module ActionView
121
121
  self.class.link_sanitizer.sanitize(html)
122
122
  end
123
123
 
124
- module ClassMethods #:nodoc:
124
+ module ClassMethods # :nodoc:
125
125
  attr_writer :full_sanitizer, :link_sanitizer, :safe_list_sanitizer
126
126
 
127
127
  def sanitizer_vendor
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/enumerable"
3
4
  require "active_support/core_ext/string/output_safety"
4
5
  require "set"
6
+ require "action_view/helpers/capture_helper"
7
+ require "action_view/helpers/output_safety_helper"
5
8
 
6
9
  module ActionView
7
10
  # = Action View Tag Helpers
8
- module Helpers #:nodoc:
11
+ module Helpers # :nodoc:
9
12
  # Provides methods to generate HTML tags programmatically both as a modern
10
13
  # HTML5 compliant builder style and legacy XHTML compliant tags.
11
14
  module TagHelper
12
- extend ActiveSupport::Concern
13
15
  include CaptureHelper
14
16
  include OutputSafetyHelper
15
17
 
@@ -39,7 +41,7 @@ module ActionView
39
41
  PRE_CONTENT_STRINGS[:textarea] = "\n"
40
42
  PRE_CONTENT_STRINGS["textarea"] = "\n"
41
43
 
42
- class TagBuilder #:nodoc:
44
+ class TagBuilder # :nodoc:
43
45
  include CaptureHelper
44
46
  include OutputSafetyHelper
45
47
 
@@ -49,6 +51,15 @@ module ActionView
49
51
  @view_context = view_context
50
52
  end
51
53
 
54
+ # Transforms a Hash into HTML Attributes, ready to be interpolated into
55
+ # ERB.
56
+ #
57
+ # <input <%= tag.attributes(type: :text, aria: { label: "Search" }) %> >
58
+ # # => <input type="text" aria-label="Search">
59
+ def attributes(attributes)
60
+ tag_options(attributes.to_h).to_s.strip.html_safe
61
+ end
62
+
52
63
  def p(*arguments, **options, &block)
53
64
  tag_string(:p, *arguments, **options, &block)
54
65
  end
@@ -119,6 +130,8 @@ module ActionView
119
130
  when Array, Hash
120
131
  value = TagHelper.build_tag_values(value) if key.to_s == "class"
121
132
  value = escape ? safe_join(value, " ") : value.join(" ")
133
+ when Regexp
134
+ value = escape ? ERB::Util.unwrapped_html_escape(value.source) : value.source
122
135
  else
123
136
  value = escape ? ERB::Util.unwrapped_html_escape(value) : value.to_s
124
137
  end
@@ -345,7 +358,7 @@ module ActionView
345
358
  # cdata_section("hello]]>world")
346
359
  # # => <![CDATA[hello]]]]><![CDATA[>world]]>
347
360
  def cdata_section(content)
348
- splitted = content.to_s.gsub(/\]\]\>/, "]]]]><![CDATA[>")
361
+ splitted = content.to_s.gsub(/\]\]>/, "]]]]><![CDATA[>")
349
362
  "<![CDATA[#{splitted}]]>".html_safe
350
363
  end
351
364
 
@@ -117,19 +117,7 @@ module ActionView
117
117
  end
118
118
 
119
119
  def tag_id(index = nil)
120
- # a little duplication to construct fewer strings
121
- case
122
- when @object_name.empty?
123
- sanitized_method_name.dup
124
- when index
125
- "#{sanitized_object_name}_#{index}_#{sanitized_method_name}"
126
- else
127
- "#{sanitized_object_name}_#{sanitized_method_name}"
128
- end
129
- end
130
-
131
- def sanitized_object_name
132
- @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").delete_suffix("_")
120
+ @template_object.field_id(@object_name, @method_name, index: index)
133
121
  end
134
122
 
135
123
  def sanitized_method_name
@@ -137,7 +125,7 @@ module ActionView
137
125
  end
138
126
 
139
127
  def sanitized_value(value)
140
- value.to_s.gsub(/[\s\.]/, "_").gsub(/[^-[[:word:]]]/, "").downcase
128
+ value.to_s.gsub(/[\s.]/, "_").gsub(/[^-[[:word:]]]/, "").downcase
141
129
  end
142
130
 
143
131
  def select_content_tag(option_tags, options, html_options)
@@ -5,7 +5,7 @@ require "action_view/helpers/tags/checkable"
5
5
  module ActionView
6
6
  module Helpers
7
7
  module Tags # :nodoc:
8
- class CheckBox < Base #:nodoc:
8
+ class CheckBox < Base # :nodoc:
9
9
  include Checkable
10
10
 
11
11
  def initialize(object_name, method_name, template_object, checked_value, unchecked_value, options)
@@ -3,7 +3,7 @@
3
3
  module ActionView
4
4
  module Helpers
5
5
  module Tags # :nodoc:
6
- class CollectionSelect < Base #:nodoc:
6
+ class CollectionSelect < Base # :nodoc:
7
7
  def initialize(object_name, method_name, template_object, collection, value_method, text_method, options, html_options)
8
8
  @collection = collection
9
9
  @value_method = value_method
@@ -4,9 +4,18 @@ module ActionView
4
4
  module Helpers
5
5
  module Tags # :nodoc:
6
6
  class TimeField < DatetimeField # :nodoc:
7
+ def initialize(object_name, method_name, template_object, options = {})
8
+ @include_seconds = options.delete(:include_seconds) { true }
9
+ super
10
+ end
11
+
7
12
  private
8
13
  def format_date(value)
9
- value&.strftime("%T.%L")
14
+ if @include_seconds
15
+ value&.strftime("%T.%L")
16
+ else
17
+ value&.strftime("%H:%M")
18
+ end
10
19
  end
11
20
  end
12
21
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module Helpers
5
+ module Tags # :nodoc:
6
+ class WeekdaySelect < Base # :nodoc:
7
+ def initialize(object_name, method_name, template_object, options, html_options)
8
+ @html_options = html_options
9
+
10
+ super(object_name, method_name, template_object, options)
11
+ end
12
+
13
+ def render
14
+ select_content_tag(
15
+ weekday_options_for_select(
16
+ value || @options[:selected],
17
+ index_as_value: @options.fetch(:index_as_value, false),
18
+ day_format: @options.fetch(:day_format, :day_names)
19
+ ),
20
+ @options,
21
+ @html_options
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionView
4
- module Helpers #:nodoc:
5
- module Tags #:nodoc:
4
+ module Helpers # :nodoc:
5
+ module Tags # :nodoc:
6
6
  extend ActiveSupport::Autoload
7
7
 
8
8
  eager_autoload do
@@ -38,6 +38,7 @@ module ActionView
38
38
  autoload :TimeZoneSelect
39
39
  autoload :UrlField
40
40
  autoload :WeekField
41
+ autoload :WeekdaySelect
41
42
  end
42
43
  end
43
44
  end
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/string/filters"
4
+ require "active_support/core_ext/string/access"
4
5
  require "active_support/core_ext/array/extract_options"
6
+ require "action_view/helpers/sanitize_helper"
7
+ require "action_view/helpers/tag_helper"
8
+ require "action_view/helpers/output_safety_helper"
5
9
 
6
10
  module ActionView
7
11
  # = Action View Text Helpers
8
- module Helpers #:nodoc:
12
+ module Helpers # :nodoc:
9
13
  # The TextHelper module provides a set of methods for filtering, formatting
10
14
  # and transforming strings, which can reduce the amount of inline Ruby code in
11
15
  # your views. These helper methods extend Action View making them callable
@@ -129,7 +133,7 @@ module ActionView
129
133
  #
130
134
  # highlight('<a href="javascript:alert(\'no!\')">ruby</a> on rails', 'rails', sanitize: false)
131
135
  # # => <a href="javascript:alert('no!')">ruby</a> on <mark>rails</mark>
132
- def highlight(text, phrases, options = {})
136
+ def highlight(text, phrases, options = {}, &block)
133
137
  text = sanitize(text) if options.fetch(:sanitize, true)
134
138
 
135
139
  if text.blank? || phrases.blank?
@@ -140,7 +144,7 @@ module ActionView
140
144
  end.join("|")
141
145
 
142
146
  if block_given?
143
- text.gsub(/(#{match})(?![^<]*?>)/i) { |found| yield found }
147
+ text.gsub(/(#{match})(?![^<]*?>)/i, &block)
144
148
  else
145
149
  highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
146
150
  text.gsub(/(#{match})(?![^<]*?>)/i, highlighter)
@@ -403,7 +407,7 @@ module ActionView
403
407
  cycle.reset if cycle
404
408
  end
405
409
 
406
- class Cycle #:nodoc:
410
+ class Cycle # :nodoc:
407
411
  attr_reader :values
408
412
 
409
413
  def initialize(first_value, *values)
@@ -467,18 +471,25 @@ module ActionView
467
471
  radius = options.fetch(:radius, 100)
468
472
  omission = options.fetch(:omission, "...")
469
473
 
470
- part = part.split(separator)
471
- part.delete("")
472
- affix = part.size > radius ? omission : ""
474
+ if separator != ""
475
+ part = part.split(separator)
476
+ part.delete("")
477
+ end
473
478
 
474
- part = if part_position == :first
475
- drop_index = [part.length - radius, 0].max
476
- part.drop(drop_index)
477
- else
478
- part.first(radius)
479
+ affix = part.length > radius ? omission : ""
480
+
481
+ part =
482
+ if part_position == :first
483
+ part.last(radius)
484
+ else
485
+ part.first(radius)
486
+ end
487
+
488
+ if separator != ""
489
+ part = part.join(separator)
479
490
  end
480
491
 
481
- return affix, part.join(separator)
492
+ return affix, part
482
493
  end
483
494
  end
484
495
  end