diff options
Diffstat (limited to 'actionview')
-rw-r--r-- | actionview/CHANGELOG.md | 8 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/asset_url_helper.rb | 24 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/date_helper.rb | 4 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/form_helper.rb | 50 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/form_tag_helper.rb | 10 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/tags/datetime_field.rb | 12 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/text_helper.rb | 2 | ||||
-rw-r--r-- | actionview/test/template/erb_util_test.rb | 1 | ||||
-rw-r--r-- | actionview/test/template/form_helper_test.rb | 64 | ||||
-rw-r--r-- | actionview/test/template/tag_helper_test.rb | 1 | ||||
-rw-r--r-- | actionview/test/template/text_helper_test.rb | 10 |
11 files changed, 158 insertions, 28 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 03ac155848..185f420472 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,11 @@ +* Fix `html_escape_once` to properly handle hex escape sequences (e.g. ᨫ) + + *John F. Douthat* + +* Added String support for min and max properties for date field helpers. + + *Todd Bealmear* + * The `highlight` helper now accepts a block to be used instead of the `highlighter` option. diff --git a/actionview/lib/action_view/helpers/asset_url_helper.rb b/actionview/lib/action_view/helpers/asset_url_helper.rb index 006b15be91..469f7c16bd 100644 --- a/actionview/lib/action_view/helpers/asset_url_helper.rb +++ b/actionview/lib/action_view/helpers/asset_url_helper.rb @@ -7,10 +7,10 @@ module ActionView # urls. # # image_path("rails.png") - # # => "/images/rails.png" + # # => "/assets/rails.png" # # image_url("rails.png") - # # => "http://www.example.com/images/rails.png" + # # => "http://www.example.com/assets/rails.png" # # === Using asset hosts # @@ -155,7 +155,7 @@ module ActionView # # All other options provided are forwarded to +asset_path+ call. # - # asset_url "application.js" # => http://example.com/application.js + # asset_url "application.js" # => http://example.com/assets/application.js # asset_url "application.js", host: "http://cdn.example.com" # => http://cdn.example.com/assets/application.js # def asset_url(source, options = {}) @@ -231,13 +231,13 @@ module ActionView end end - # Computes the path to a javascript asset in the public javascripts directory. + # Computes the path to a JavaScript asset in the public javascripts directory. # If the +source+ filename has no extension, .js will be appended (except for explicit URIs) # Full paths from the document root will be passed through. # Used internally by +javascript_include_tag+ to build the script path. # - # javascript_path "xmlhr" # => /javascripts/xmlhr.js - # javascript_path "dir/xmlhr.js" # => /javascripts/dir/xmlhr.js + # javascript_path "xmlhr" # => /assets/xmlhr.js + # javascript_path "dir/xmlhr.js" # => /assets/dir/xmlhr.js # javascript_path "/dir/xmlhr" # => /dir/xmlhr.js # javascript_path "http://www.example.com/js/xmlhr" # => http://www.example.com/js/xmlhr # javascript_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js @@ -246,7 +246,7 @@ module ActionView end alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route - # Computes the full URL to a javascript asset in the public javascripts directory. + # Computes the full URL to a JavaScript asset in the public javascripts directory. # This will use +javascript_path+ internally, so most of their behaviors will be the same. def javascript_url(source, options = {}) url_to_asset(source, {type: :javascript}.merge!(options)) @@ -258,8 +258,8 @@ module ActionView # Full paths from the document root will be passed through. # Used internally by +stylesheet_link_tag+ to build the stylesheet path. # - # stylesheet_path "style" # => /stylesheets/style.css - # stylesheet_path "dir/style.css" # => /stylesheets/dir/style.css + # stylesheet_path "style" # => /assets/style.css + # stylesheet_path "dir/style.css" # => /assets/dir/style.css # stylesheet_path "/dir/style.css" # => /dir/style.css # stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style # stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css @@ -279,9 +279,9 @@ module ActionView # Full paths from the document root will be passed through. # Used internally by +image_tag+ to build the image path: # - # image_path("edit") # => "/images/edit" - # image_path("edit.png") # => "/images/edit.png" - # image_path("icons/edit.png") # => "/images/icons/edit.png" + # image_path("edit") # => "/assets/edit" + # image_path("edit.png") # => "/assets/edit.png" + # image_path("icons/edit.png") # => "/assets/icons/edit.png" # image_path("/icons/edit.png") # => "/icons/edit.png" # image_path("http://www.example.com/img/edit.png") # => "http://www.example.com/img/edit.png" # diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb index 2efb9612ac..27c7a26098 100644 --- a/actionview/lib/action_view/helpers/date_helper.rb +++ b/actionview/lib/action_view/helpers/date_helper.rb @@ -153,8 +153,8 @@ module ActionView # # Note that you cannot pass a <tt>Numeric</tt> value to <tt>time_ago_in_words</tt>. # - def time_ago_in_words(from_time, include_seconds_or_options = {}) - distance_of_time_in_words(from_time, Time.now, include_seconds_or_options) + def time_ago_in_words(from_time, options = {}) + distance_of_time_in_words(from_time, Time.now, options) end alias_method :distance_of_time_in_words_to_now, :time_ago_in_words diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb index 789a413c8d..c6bc0c9e38 100644 --- a/actionview/lib/action_view/helpers/form_helper.rb +++ b/actionview/lib/action_view/helpers/form_helper.rb @@ -482,7 +482,7 @@ module ActionView # Admin? : <%= permission_fields.check_box :admin %> # <% end %> # - # <%= f.submit %> + # <%= person_form.submit %> # <% end %> # # In this case, the checkbox field will be represented by an HTML +input+ @@ -1013,6 +1013,18 @@ module ActionView # date_field("user", "born_on", value: "1984-05-12") # # => <input id="user_born_on" name="user[born_on]" type="date" value="1984-05-12" /> # + # You can create values for the "min" and "max" attributes by passing + # instances of Date or Time to the options hash. + # + # date_field("user", "born_on", min: Date.today) + # # => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" /> + # + # Alternatively, you can pass a String formatted as an ISO8601 date as the + # values for "min" and "max." + # + # date_field("user", "born_on", min: "2014-05-20") + # # => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" /> + # def date_field(object_name, method, options = {}) Tags::DateField.new(object_name, method, self, options).render end @@ -1030,6 +1042,18 @@ module ActionView # time_field("task", "started_at") # # => <input id="task_started_at" name="task[started_at]" type="time" /> # + # You can create values for the "min" and "max" attributes by passing + # instances of Date or Time to the options hash. + # + # time_field("task", "started_at", min: Time.now) + # # => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" /> + # + # Alternatively, you can pass a String formatted as an ISO8601 time as the + # values for "min" and "max." + # + # time_field("task", "started_at", min: "01:00:00") + # # => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" /> + # def time_field(object_name, method, options = {}) Tags::TimeField.new(object_name, method, self, options).render end @@ -1047,6 +1071,18 @@ module ActionView # datetime_field("user", "born_on") # # => <input id="user_born_on" name="user[born_on]" type="datetime" value="1984-01-12T00:00:00.000+0000" /> # + # You can create values for the "min" and "max" attributes by passing + # instances of Date or Time to the options hash. + # + # datetime_field("user", "born_on", min: Date.today) + # # => <input id="user_born_on" name="user[born_on]" type="datetime" min="2014-05-20T00:00:00.000+0000" /> + # + # Alternatively, you can pass a String formatted as an ISO8601 datetime + # with UTC offset as the values for "min" and "max." + # + # datetime_field("user", "born_on", min: "2014-05-20T00:00:00+0000") + # # => <input id="user_born_on" name="user[born_on]" type="datetime" min="2014-05-20T00:00:00.000+0000" /> + # def datetime_field(object_name, method, options = {}) Tags::DatetimeField.new(object_name, method, self, options).render end @@ -1064,6 +1100,18 @@ module ActionView # datetime_local_field("user", "born_on") # # => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="1984-01-12T00:00:00" /> # + # You can create values for the "min" and "max" attributes by passing + # instances of Date or Time to the options hash. + # + # datetime_local_field("user", "born_on", min: Date.today) + # # => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" /> + # + # Alternatively, you can pass a String formatted as an ISO8601 datetime as + # the values for "min" and "max." + # + # datetime_local_field("user", "born_on", min: "2014-05-20T00:00:00") + # # => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" /> + # def datetime_local_field(object_name, method, options = {}) Tags::DatetimeLocalField.new(object_name, method, self, options).render end diff --git a/actionview/lib/action_view/helpers/form_tag_helper.rb b/actionview/lib/action_view/helpers/form_tag_helper.rb index 9c0c43d096..b18f578183 100644 --- a/actionview/lib/action_view/helpers/form_tag_helper.rb +++ b/actionview/lib/action_view/helpers/form_tag_helper.rb @@ -508,19 +508,19 @@ module ActionView # # ==== Examples # image_submit_tag("login.png") - # # => <input alt="Login" src="/images/login.png" type="image" /> + # # => <input alt="Login" src="/assets/login.png" type="image" /> # # image_submit_tag("purchase.png", disabled: true) - # # => <input alt="Purchase" disabled="disabled" src="/images/purchase.png" type="image" /> + # # => <input alt="Purchase" disabled="disabled" src="/assets/purchase.png" type="image" /> # # image_submit_tag("search.png", class: 'search_button', alt: 'Find') - # # => <input alt="Find" class="search_button" src="/images/search.png" type="image" /> + # # => <input alt="Find" class="search_button" src="/assets/search.png" type="image" /> # # image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button") - # # => <input alt="Agree" class="agree_disagree_button" disabled="disabled" src="/images/agree.png" type="image" /> + # # => <input alt="Agree" class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" /> # # image_submit_tag("save.png", data: { confirm: "Are you sure?" }) - # # => <input alt="Save" src="/images/save.png" data-confirm="Are you sure?" type="image" /> + # # => <input alt="Save" src="/assets/save.png" data-confirm="Are you sure?" type="image" /> def image_submit_tag(source, options = {}) options = options.stringify_keys tag :input, { "alt" => image_alt(source), "type" => "image", "src" => path_to_image(source) }.update(options) diff --git a/actionview/lib/action_view/helpers/tags/datetime_field.rb b/actionview/lib/action_view/helpers/tags/datetime_field.rb index 25e7e05ec6..b2cee9d198 100644 --- a/actionview/lib/action_view/helpers/tags/datetime_field.rb +++ b/actionview/lib/action_view/helpers/tags/datetime_field.rb @@ -5,8 +5,8 @@ module ActionView def render options = @options.stringify_keys options["value"] ||= format_date(value(object)) - options["min"] = format_date(options["min"]) - options["max"] = format_date(options["max"]) + options["min"] = format_date(datetime_value(options["min"])) + options["max"] = format_date(datetime_value(options["max"])) @options = options super end @@ -16,6 +16,14 @@ module ActionView def format_date(value) value.try(:strftime, "%Y-%m-%dT%T.%L%z") end + + def datetime_value(value) + if value.is_a? String + DateTime.parse(value) rescue nil + else + value + end + end end end end diff --git a/actionview/lib/action_view/helpers/text_helper.rb b/actionview/lib/action_view/helpers/text_helper.rb index cf5c1b0e81..b859653bc9 100644 --- a/actionview/lib/action_view/helpers/text_helper.rb +++ b/actionview/lib/action_view/helpers/text_helper.rb @@ -188,7 +188,7 @@ module ActionView end end - first_part, second_part = text.split(regex, 2) + first_part, second_part = text.split(phrase, 2) prefix, first_part = cut_excerpt_part(:first, first_part, separator, options) postfix, second_part = cut_excerpt_part(:second, second_part, separator, options) diff --git a/actionview/test/template/erb_util_test.rb b/actionview/test/template/erb_util_test.rb index 9bacbba908..3bb84cbc50 100644 --- a/actionview/test/template/erb_util_test.rb +++ b/actionview/test/template/erb_util_test.rb @@ -92,6 +92,7 @@ class ErbUtilTest < ActiveSupport::TestCase def test_html_escape_once assert_equal '1 <>&"' 2 & 3', html_escape_once('1 <>&"\' 2 & 3') + assert_equal " ' ' λ λ " ' < > ", html_escape_once(" ' ' λ λ \" ' < > ") end def test_html_escape_once_returns_unsafe_strings_when_passed_unsafe_strings diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb index 48073225cb..3e39dadcf1 100644 --- a/actionview/test/template/form_helper_test.rb +++ b/actionview/test/template/form_helper_test.rb @@ -776,6 +776,22 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal(expected, date_field("post", "written_on")) end + def test_date_field_with_string_values_for_min_and_max + expected = %{<input id="post_written_on" max="2010-08-15" min="2000-06-15" name="post[written_on]" type="date" value="2004-06-15" />} + @post.written_on = DateTime.new(2004, 6, 15) + min_value = "2000-06-15" + max_value = "2010-08-15" + assert_dom_equal(expected, date_field("post", "written_on", min: min_value, max: max_value)) + end + + def test_date_field_with_invalid_string_values_for_min_and_max + expected = %{<input id="post_written_on" name="post[written_on]" type="date" value="2004-06-15" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = "foo" + max_value = "bar" + assert_dom_equal(expected, date_field("post", "written_on", min: min_value, max: max_value)) + end + def test_time_field expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="00:00:00.000" />} assert_dom_equal(expected, time_field("post", "written_on")) @@ -811,6 +827,22 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal(expected, time_field("post", "written_on")) end + def test_time_field_with_string_values_for_min_and_max + expected = %{<input id="post_written_on" max="10:25:00.000" min="20:45:30.000" name="post[written_on]" type="time" value="01:02:03.000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = "20:45:30.000" + max_value = "10:25:00.000" + assert_dom_equal(expected, time_field("post", "written_on", min: min_value, max: max_value)) + end + + def test_time_field_with_invalid_string_values_for_min_and_max + expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="01:02:03.000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = "foo" + max_value = "bar" + assert_dom_equal(expected, time_field("post", "written_on", min: min_value, max: max_value)) + end + def test_datetime_field expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T00:00:00.000+0000" />} assert_dom_equal(expected, datetime_field("post", "written_on")) @@ -852,6 +884,22 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal(expected, datetime_field("post", "written_on")) end + def test_datetime_field_with_string_values_for_min_and_max + expected = %{<input id="post_written_on" max="2010-08-15T10:25:00.000+0000" min="2000-06-15T20:45:30.000+0000" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = "2000-06-15T20:45:30.000+0000" + max_value = "2010-08-15T10:25:00.000+0000" + assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value)) + end + + def test_datetime_field_with_invalid_string_values_for_min_and_max + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = "foo" + max_value = "bar" + assert_dom_equal(expected, datetime_field("post", "written_on", min: min_value, max: max_value)) + end + def test_datetime_local_field expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T00:00:00" />} assert_dom_equal(expected, datetime_local_field("post", "written_on")) @@ -887,6 +935,22 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal(expected, datetime_local_field("post", "written_on")) end + def test_datetime_local_field_with_string_values_for_min_and_max + expected = %{<input id="post_written_on" max="2010-08-15T10:25:00" min="2000-06-15T20:45:30" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = "2000-06-15T20:45:30" + max_value = "2010-08-15T10:25:00" + assert_dom_equal(expected, datetime_local_field("post", "written_on", min: min_value, max: max_value)) + end + + def test_datetime_local_field_with_invalid_string_values_for_min_and_max + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = "foo" + max_value = "bar" + assert_dom_equal(expected, datetime_local_field("post", "written_on", min: min_value, max: max_value)) + end + def test_month_field expected = %{<input id="post_written_on" name="post[written_on]" type="month" value="2004-06" />} assert_dom_equal(expected, month_field("post", "written_on")) diff --git a/actionview/test/template/tag_helper_test.rb b/actionview/test/template/tag_helper_test.rb index c78b6450f2..0ea669b3d0 100644 --- a/actionview/test/template/tag_helper_test.rb +++ b/actionview/test/template/tag_helper_test.rb @@ -123,6 +123,7 @@ class TagHelperTest < ActionView::TestCase def test_escape_once assert_equal '1 < 2 & 3', escape_once('1 < 2 & 3') + assert_equal " ' ' λ λ " ' < > ", escape_once(" ' ' λ λ \" ' < > ") end def test_tag_honors_html_safe_for_param_values diff --git a/actionview/test/template/text_helper_test.rb b/actionview/test/template/text_helper_test.rb index 858232a2b9..db416a8de4 100644 --- a/actionview/test/template/text_helper_test.rb +++ b/actionview/test/template/text_helper_test.rb @@ -280,8 +280,13 @@ class TextHelperTest < ActionView::TestCase end def test_excerpt_with_regex + assert_equal('...is a beautiful! mor...', excerpt('This is a beautiful! morning', 'beautiful', :radius => 5)) + assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', 'beautiful', :radius => 5)) + assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', /\bbeau\w*\b/i, :radius => 5)) + assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', /\b(beau\w*)\b/i, :radius => 5)) assert_equal("...udge Allen and...", excerpt("This day was challenging for judge Allen and his colleagues.", /\ballen\b/i, :radius => 5)) assert_equal("...judge Allen and...", excerpt("This day was challenging for judge Allen and his colleagues.", /\ballen\b/i, :radius => 1, :separator => ' ')) + assert_equal("...was challenging for...", excerpt("This day was challenging for judge Allen and his colleagues.", /\b(\w*allen\w*)\b/i, :radius => 5)) end def test_excerpt_should_not_be_html_safe @@ -305,11 +310,6 @@ class TextHelperTest < ActionView::TestCase assert_equal("...abc...", excerpt("z abc d", "b", :radius => 1)) end - def test_excerpt_with_regex - assert_equal('...is a beautiful! mor...', excerpt('This is a beautiful! morning', 'beautiful', :radius => 5)) - assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', 'beautiful', :radius => 5)) - end - def test_excerpt_with_omission assert_equal("[...]is a beautiful morn[...]", excerpt("This is a beautiful morning", "beautiful", :omission => "[...]",:radius => 5)) assert_equal( |