actionpack 1.13.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +1400 -20
- data/MIT-LICENSE +1 -1
- data/README +5 -5
- data/RUNNING_UNIT_TESTS +4 -5
- data/Rakefile +5 -6
- data/install.rb +2 -2
- data/lib/action_controller.rb +11 -15
- data/lib/action_controller/assertions.rb +12 -25
- data/lib/action_controller/assertions/dom_assertions.rb +18 -4
- data/lib/action_controller/assertions/model_assertions.rb +8 -1
- data/lib/action_controller/assertions/response_assertions.rb +35 -12
- data/lib/action_controller/assertions/routing_assertions.rb +56 -12
- data/lib/action_controller/assertions/selector_assertions.rb +105 -38
- data/lib/action_controller/assertions/tag_assertions.rb +28 -15
- data/lib/action_controller/base.rb +318 -250
- data/lib/action_controller/benchmarking.rb +33 -29
- data/lib/action_controller/caching.rb +130 -64
- data/lib/action_controller/cgi_ext.rb +16 -0
- data/lib/action_controller/cgi_ext/{cookie_performance_fix.rb → cookie.rb} +25 -40
- data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
- data/lib/action_controller/cgi_ext/session.rb +73 -0
- data/lib/action_controller/cgi_ext/stdinput.rb +23 -0
- data/lib/action_controller/cgi_process.rb +34 -57
- data/lib/action_controller/components.rb +19 -36
- data/lib/action_controller/cookies.rb +10 -9
- data/lib/action_controller/dispatcher.rb +195 -0
- data/lib/action_controller/filters.rb +35 -34
- data/lib/action_controller/flash.rb +30 -35
- data/lib/action_controller/helpers.rb +121 -47
- data/lib/action_controller/http_authentication.rb +126 -0
- data/lib/action_controller/integration.rb +105 -101
- data/lib/action_controller/layout.rb +59 -47
- data/lib/action_controller/mime_responds.rb +57 -68
- data/lib/action_controller/mime_type.rb +43 -80
- data/lib/action_controller/mime_types.rb +20 -0
- data/lib/action_controller/polymorphic_routes.rb +88 -0
- data/lib/action_controller/record_identifier.rb +91 -0
- data/lib/action_controller/request.rb +553 -88
- data/lib/action_controller/request_forgery_protection.rb +126 -0
- data/lib/action_controller/request_profiler.rb +138 -0
- data/lib/action_controller/rescue.rb +185 -69
- data/lib/action_controller/resources.rb +211 -172
- data/lib/action_controller/response.rb +49 -8
- data/lib/action_controller/routing.rb +359 -236
- data/lib/action_controller/routing_optimisation.rb +119 -0
- data/lib/action_controller/session/active_record_store.rb +3 -2
- data/lib/action_controller/session/cookie_store.rb +161 -0
- data/lib/action_controller/session/mem_cache_store.rb +9 -16
- data/lib/action_controller/session_management.rb +17 -8
- data/lib/action_controller/streaming.rb +6 -3
- data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
- data/lib/action_controller/templates/rescues/{_trace.rhtml → _trace.erb} +0 -0
- data/lib/action_controller/templates/rescues/{diagnostics.rhtml → diagnostics.erb} +2 -2
- data/lib/action_controller/templates/rescues/{layout.rhtml → layout.erb} +0 -0
- data/lib/action_controller/templates/rescues/{missing_template.rhtml → missing_template.erb} +0 -0
- data/lib/action_controller/templates/rescues/{routing_error.rhtml → routing_error.erb} +0 -0
- data/lib/action_controller/templates/rescues/{template_error.rhtml → template_error.erb} +2 -2
- data/lib/action_controller/templates/rescues/{unknown_action.rhtml → unknown_action.erb} +0 -0
- data/lib/action_controller/test_case.rb +53 -0
- data/lib/action_controller/test_process.rb +59 -46
- data/lib/action_controller/url_rewriter.rb +48 -24
- data/lib/action_controller/vendor/html-scanner/html/document.rb +7 -4
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +11 -6
- data/lib/action_controller/verification.rb +27 -21
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +4 -4
- data/lib/action_view.rb +2 -3
- data/lib/action_view/base.rb +218 -63
- data/lib/action_view/compiled_templates.rb +1 -2
- data/lib/action_view/helpers/active_record_helper.rb +35 -17
- data/lib/action_view/helpers/asset_tag_helper.rb +395 -87
- data/lib/action_view/helpers/atom_feed_helper.rb +111 -0
- data/lib/action_view/helpers/benchmark_helper.rb +12 -5
- data/lib/action_view/helpers/cache_helper.rb +29 -0
- data/lib/action_view/helpers/capture_helper.rb +97 -63
- data/lib/action_view/helpers/date_helper.rb +295 -35
- data/lib/action_view/helpers/debug_helper.rb +6 -2
- data/lib/action_view/helpers/form_helper.rb +354 -111
- data/lib/action_view/helpers/form_options_helper.rb +171 -109
- data/lib/action_view/helpers/form_tag_helper.rb +332 -76
- data/lib/action_view/helpers/javascript_helper.rb +35 -11
- data/lib/action_view/helpers/javascripts/controls.js +484 -354
- data/lib/action_view/helpers/javascripts/dragdrop.js +88 -58
- data/lib/action_view/helpers/javascripts/effects.js +396 -364
- data/lib/action_view/helpers/javascripts/prototype.js +2817 -1107
- data/lib/action_view/helpers/number_helper.rb +84 -60
- data/lib/action_view/helpers/prototype_helper.rb +419 -43
- data/lib/action_view/helpers/record_identification_helper.rb +20 -0
- data/lib/action_view/helpers/record_tag_helper.rb +59 -0
- data/lib/action_view/helpers/sanitize_helper.rb +223 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +63 -4
- data/lib/action_view/helpers/tag_helper.rb +69 -39
- data/lib/action_view/helpers/text_helper.rb +221 -148
- data/lib/action_view/helpers/url_helper.rb +283 -165
- data/lib/action_view/partials.rb +134 -62
- data/lib/action_view/template_error.rb +4 -12
- data/lib/actionpack.rb +1 -0
- data/test/abstract_unit.rb +21 -1
- data/test/action_view_test.rb +26 -0
- data/test/active_record_unit.rb +12 -20
- data/test/activerecord/active_record_store_test.rb +2 -2
- data/test/activerecord/render_partial_with_record_identification_test.rb +74 -0
- data/test/controller/action_pack_assertions_test.rb +21 -152
- data/test/controller/addresses_render_test.rb +2 -7
- data/test/controller/assert_select_test.rb +120 -14
- data/test/controller/base_test.rb +11 -13
- data/test/controller/caching_test.rb +125 -5
- data/test/controller/capture_test.rb +23 -16
- data/test/controller/cgi_test.rb +66 -391
- data/test/controller/components_test.rb +31 -42
- data/test/controller/content_type_test.rb +1 -1
- data/test/controller/cookie_test.rb +42 -14
- data/test/controller/deprecation/deprecated_base_methods_test.rb +1 -42
- data/test/controller/dispatcher_test.rb +123 -0
- data/test/controller/fake_models.rb +5 -0
- data/test/controller/filters_test.rb +44 -7
- data/test/controller/flash_test.rb +46 -2
- data/test/controller/fragment_store_setting_test.rb +10 -8
- data/test/controller/helper_test.rb +19 -2
- data/test/controller/html-scanner/document_test.rb +124 -0
- data/test/controller/html-scanner/node_test.rb +69 -0
- data/test/controller/html-scanner/sanitizer_test.rb +250 -0
- data/test/controller/html-scanner/tag_node_test.rb +239 -0
- data/test/controller/html-scanner/text_node_test.rb +51 -0
- data/test/controller/html-scanner/tokenizer_test.rb +125 -0
- data/test/controller/http_authentication_test.rb +54 -0
- data/test/controller/integration_test.rb +12 -26
- data/test/controller/layout_test.rb +64 -12
- data/test/controller/mime_responds_test.rb +193 -38
- data/test/controller/mime_type_test.rb +30 -8
- data/test/controller/new_render_test.rb +104 -22
- data/test/controller/polymorphic_routes_test.rb +98 -0
- data/test/controller/record_identifier_test.rb +103 -0
- data/test/controller/redirect_test.rb +120 -18
- data/test/controller/render_test.rb +195 -45
- data/test/controller/request_forgery_protection_test.rb +217 -0
- data/test/controller/request_test.rb +545 -27
- data/test/controller/rescue_test.rb +501 -0
- data/test/controller/resources_test.rb +258 -132
- data/test/controller/routing_test.rb +502 -106
- data/test/controller/selector_test.rb +5 -5
- data/test/controller/send_file_test.rb +17 -7
- data/test/controller/session/cookie_store_test.rb +246 -0
- data/test/controller/session/mem_cache_store_test.rb +182 -0
- data/test/controller/session_fixation_test.rb +8 -11
- data/test/controller/session_management_test.rb +7 -7
- data/test/controller/test_test.rb +150 -38
- data/test/controller/url_rewriter_test.rb +87 -12
- data/test/controller/verification_test.rb +11 -0
- data/test/controller/view_paths_test.rb +137 -0
- data/test/controller/webservice_test.rb +11 -75
- data/test/fixtures/addresses/{list.rhtml → list.erb} +0 -0
- data/test/fixtures/db_definitions/sqlite.sql +2 -1
- data/test/fixtures/developer.rb +2 -0
- data/test/fixtures/fun/games/{hello_world.rhtml → hello_world.erb} +0 -0
- data/test/fixtures/helpers/fun/pdf_helper.rb +1 -1
- data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
- data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
- data/test/fixtures/layouts/{builder.rxml → builder.builder} +0 -0
- data/test/fixtures/layouts/{standard.rhtml → standard.erb} +0 -0
- data/test/fixtures/layouts/{talk_from_action.rhtml → talk_from_action.erb} +0 -0
- data/test/fixtures/layouts/{yield.rhtml → yield.erb} +0 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/multipart/bracketed_param +5 -0
- data/test/fixtures/override/test/hello_world.erb +1 -0
- data/test/fixtures/override2/layouts/test/sub.erb +1 -0
- data/test/fixtures/post_test/layouts/post.html.erb +1 -0
- data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
- data/test/fixtures/post_test/post/index.html.erb +1 -0
- data/test/fixtures/post_test/post/index.iphone.erb +1 -0
- data/test/fixtures/post_test/super_post/index.html.erb +1 -0
- data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
- data/test/fixtures/public/404.html +1 -0
- data/test/fixtures/public/500.html +1 -0
- data/test/fixtures/public/javascripts/application.js +0 -1
- data/test/fixtures/public/javascripts/bank.js +1 -0
- data/test/fixtures/public/javascripts/robber.js +1 -0
- data/test/fixtures/public/stylesheets/bank.css +1 -0
- data/test/fixtures/public/stylesheets/robber.css +1 -0
- data/test/fixtures/replies.yml +2 -0
- data/test/fixtures/reply.rb +2 -1
- data/test/fixtures/respond_to/{all_types_with_layout.rhtml → all_types_with_layout.html.erb} +0 -0
- data/test/fixtures/respond_to/{all_types_with_layout.rjs → all_types_with_layout.js.rjs} +0 -0
- data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
- data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
- data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
- data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
- data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
- data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
- data/test/fixtures/respond_to/{using_defaults.rhtml → using_defaults.html.erb} +0 -0
- data/test/fixtures/respond_to/{using_defaults.rjs → using_defaults.js.rjs} +0 -0
- data/test/fixtures/respond_to/{using_defaults.rxml → using_defaults.xml.builder} +0 -0
- data/test/fixtures/respond_to/{using_defaults_with_type_list.rhtml → using_defaults_with_type_list.html.erb} +0 -0
- data/test/fixtures/respond_to/{using_defaults_with_type_list.rjs → using_defaults_with_type_list.js.rjs} +0 -0
- data/test/fixtures/respond_to/{using_defaults_with_type_list.rxml → using_defaults_with_type_list.xml.builder} +0 -0
- data/test/fixtures/scope/test/{modgreet.rhtml → modgreet.erb} +0 -0
- data/test/fixtures/test/{_customer.rhtml → _customer.erb} +0 -0
- data/test/fixtures/test/{_customer_greeting.rhtml → _customer_greeting.erb} +0 -0
- data/test/fixtures/test/_hash_greeting.erb +1 -0
- data/test/fixtures/test/_hash_object.erb +2 -0
- data/test/fixtures/test/{_hello.rxml → _hello.builder} +0 -0
- data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
- data/test/fixtures/test/_partial.erb +1 -0
- data/test/fixtures/test/_partial.html.erb +1 -0
- data/test/fixtures/test/_partial.js.erb +1 -0
- data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
- data/test/fixtures/test/{_partial_only.rhtml → _partial_only.erb} +0 -0
- data/test/fixtures/test/{_person.rhtml → _person.erb} +0 -0
- data/test/fixtures/test/{action_talk_to_layout.rhtml → action_talk_to_layout.erb} +0 -0
- data/test/fixtures/test/{block_content_for.rhtml → block_content_for.erb} +0 -0
- data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
- data/test/fixtures/test/{capturing.rhtml → capturing.erb} +0 -0
- data/test/fixtures/test/{content_for.rhtml → content_for.erb} +0 -0
- data/test/fixtures/test/content_for_concatenated.erb +3 -0
- data/test/fixtures/test/content_for_with_parameter.erb +2 -0
- data/test/fixtures/test/dot.directory/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
- data/test/fixtures/test/{erb_content_for.rhtml → erb_content_for.erb} +0 -0
- data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
- data/test/fixtures/test/formatted_xml_erb.builder +1 -0
- data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
- data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
- data/test/fixtures/test/{greeting.rhtml → greeting.erb} +0 -0
- data/test/fixtures/test/{hello.rxml → hello.builder} +0 -0
- data/test/fixtures/test/{hello_world.rxml → hello_world.builder} +0 -0
- data/test/fixtures/test/{hello_world.rhtml → hello_world.erb} +0 -0
- data/test/fixtures/test/{hello_world_container.rxml → hello_world_container.builder} +0 -0
- data/test/fixtures/test/{hello_world_with_layout_false.rhtml → hello_world_with_layout_false.erb} +0 -0
- data/test/fixtures/test/{hello_xml_world.rxml → hello_xml_world.builder} +0 -0
- data/test/fixtures/test/list.erb +1 -0
- data/test/fixtures/test/{non_erb_block_content_for.rxml → non_erb_block_content_for.builder} +0 -0
- data/test/fixtures/test/{potential_conflicts.rhtml → potential_conflicts.erb} +0 -0
- data/test/fixtures/test/{render_file_with_ivar.rhtml → render_file_with_ivar.erb} +0 -0
- data/test/fixtures/test/{render_file_with_locals.rhtml → render_file_with_locals.erb} +0 -0
- data/test/fixtures/test/{render_to_string_test.rhtml → render_to_string_test.erb} +0 -0
- data/test/fixtures/test/{update_element_with_capture.rhtml → update_element_with_capture.erb} +0 -0
- data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
- data/test/fixtures/topic.rb +1 -1
- data/test/template/active_record_helper_test.rb +67 -20
- data/test/template/asset_tag_helper_test.rb +222 -54
- data/test/template/atom_feed_helper_test.rb +101 -0
- data/test/template/benchmark_helper_test.rb +2 -2
- data/test/template/compiled_templates_test.rb +76 -32
- data/test/template/date_helper_test.rb +125 -9
- data/test/template/form_helper_test.rb +326 -33
- data/test/template/form_options_helper_test.rb +822 -15
- data/test/template/form_tag_helper_test.rb +96 -30
- data/test/template/javascript_helper_test.rb +61 -13
- data/test/template/number_helper_test.rb +12 -11
- data/test/template/prototype_helper_test.rb +185 -24
- data/test/template/sanitize_helper_test.rb +49 -0
- data/test/template/scriptaculous_helper_test.rb +9 -3
- data/test/template/tag_helper_test.rb +13 -2
- data/test/template/text_helper_test.rb +38 -52
- data/test/template/url_helper_test.rb +216 -46
- metadata +144 -116
- data/examples/.htaccess +0 -24
- data/examples/address_book/index.rhtml +0 -33
- data/examples/address_book/layout.rhtml +0 -8
- data/examples/address_book_controller.cgi +0 -9
- data/examples/address_book_controller.fcgi +0 -6
- data/examples/address_book_controller.rb +0 -52
- data/examples/address_book_controller.rbx +0 -4
- data/examples/benchmark.rb +0 -52
- data/examples/benchmark_with_ar.fcgi +0 -89
- data/examples/blog_controller.cgi +0 -53
- data/examples/debate/index.rhtml +0 -14
- data/examples/debate/new_topic.rhtml +0 -22
- data/examples/debate/topic.rhtml +0 -32
- data/examples/debate_controller.cgi +0 -57
- data/lib/action_controller/assertions/deprecated_assertions.rb +0 -228
- data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -36
- data/lib/action_controller/cgi_ext/cgi_methods.rb +0 -211
- data/lib/action_controller/cgi_ext/pstore_performance_fix.rb +0 -30
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +0 -95
- data/lib/action_controller/cgi_ext/session_performance_fix.rb +0 -30
- data/lib/action_controller/deprecated_dependencies.rb +0 -65
- data/lib/action_controller/deprecated_redirects.rb +0 -17
- data/lib/action_controller/deprecated_request_methods.rb +0 -34
- data/lib/action_controller/macros/auto_complete.rb +0 -53
- data/lib/action_controller/macros/in_place_editing.rb +0 -33
- data/lib/action_controller/pagination.rb +0 -408
- data/lib/action_controller/scaffolding.rb +0 -189
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -44
- data/lib/action_controller/templates/scaffolds/edit.rhtml +0 -7
- data/lib/action_controller/templates/scaffolds/layout.rhtml +0 -69
- data/lib/action_controller/templates/scaffolds/list.rhtml +0 -27
- data/lib/action_controller/templates/scaffolds/new.rhtml +0 -6
- data/lib/action_controller/templates/scaffolds/show.rhtml +0 -9
- data/lib/action_controller/vendor/xml_node.rb +0 -97
- data/lib/action_view/helpers/deprecated_helper.rb +0 -37
- data/lib/action_view/helpers/java_script_macros_helper.rb +0 -233
- data/lib/action_view/helpers/pagination_helper.rb +0 -86
- data/test/activerecord/active_record_assertions_test.rb +0 -92
- data/test/activerecord/pagination_test.rb +0 -165
- data/test/controller/deprecated_instance_variables_test.rb +0 -48
- data/test/controller/raw_post_test.rb +0 -68
- data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +0 -1
- data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +0 -1
- data/test/fixtures/respond_to/layouts/standard.rhtml +0 -1
- data/test/fixtures/test/_hash_object.rhtml +0 -1
- data/test/fixtures/test/list.rhtml +0 -1
- data/test/template/deprecated_helper_test.rb +0 -36
- data/test/template/deprecated_instance_variables_test.rb +0 -43
- data/test/template/java_script_macros_helper_test.rb +0 -109
@@ -0,0 +1,20 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
module RecordIdentificationHelper
|
4
|
+
# See ActionController::RecordIdentifier.partial_path -- this is just a delegate to that for convenient access in the view.
|
5
|
+
def partial_path(*args, &block)
|
6
|
+
ActionController::RecordIdentifier.partial_path(*args, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
# See ActionController::RecordIdentifier.dom_class -- this is just a delegate to that for convenient access in the view.
|
10
|
+
def dom_class(*args, &block)
|
11
|
+
ActionController::RecordIdentifier.dom_class(*args, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
# See ActionController::RecordIdentifier.dom_id -- this is just a delegate to that for convenient access in the view.
|
15
|
+
def dom_id(*args, &block)
|
16
|
+
ActionController::RecordIdentifier.dom_id(*args, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
module RecordTagHelper
|
4
|
+
# Produces a wrapper DIV element with id and class parameters that
|
5
|
+
# relate to the specified ActiveRecord object. Usage example:
|
6
|
+
#
|
7
|
+
# <% div_for(@person, :class => "foo") do %>
|
8
|
+
# <%=h @person.name %>
|
9
|
+
# <% end %>
|
10
|
+
#
|
11
|
+
# produces:
|
12
|
+
#
|
13
|
+
# <div id="person_123" class="person foo"> Joe Bloggs </div>
|
14
|
+
#
|
15
|
+
def div_for(record, *args, &block)
|
16
|
+
content_tag_for(:div, record, *args, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
# content_tag_for creates an HTML element with id and class parameters
|
20
|
+
# that relate to the specified ActiveRecord object. For example:
|
21
|
+
#
|
22
|
+
# <% content_tag_for(:tr, @person) do %>
|
23
|
+
# <td><%=h @person.first_name %></td>
|
24
|
+
# <td><%=h @person.last_name %></td>
|
25
|
+
# <% end %>
|
26
|
+
#
|
27
|
+
# would produce hthe following HTML (assuming @person is an instance of
|
28
|
+
# a Person object, with an id value of 123):
|
29
|
+
#
|
30
|
+
# <tr id="person_123" class="person">....</tr>
|
31
|
+
#
|
32
|
+
# If you require the HTML id attribute to have a prefix, you can specify it:
|
33
|
+
#
|
34
|
+
# <% content_tag_for(:tr, @person, :foo) do %> ...
|
35
|
+
#
|
36
|
+
# produces:
|
37
|
+
#
|
38
|
+
# <tr id="foo_person_123" class="person">...
|
39
|
+
#
|
40
|
+
# content_tag_for also accepts a hash of options, which will be converted to
|
41
|
+
# additional HTML attributes. If you specify a <tt>:class</tt> value, it will be combined
|
42
|
+
# with the default class name for your object. For example:
|
43
|
+
#
|
44
|
+
# <% content_tag_for(:li, @person, :class => "bar") %>...
|
45
|
+
#
|
46
|
+
# produces:
|
47
|
+
#
|
48
|
+
# <li id="person_123" class="person bar">...
|
49
|
+
#
|
50
|
+
def content_tag_for(tag_name, record, *args, &block)
|
51
|
+
prefix = args.first.is_a?(Hash) ? nil : args.shift
|
52
|
+
options = args.first.is_a?(Hash) ? args.shift : {}
|
53
|
+
concat content_tag(tag_name, capture(&block),
|
54
|
+
options.merge({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) })),
|
55
|
+
block.binding
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require 'action_view/helpers/tag_helper'
|
2
|
+
require 'html/document'
|
3
|
+
|
4
|
+
module ActionView
|
5
|
+
module Helpers #:nodoc:
|
6
|
+
# The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements.
|
7
|
+
# These helper methods extend ActionView making them callable within your template files.
|
8
|
+
module SanitizeHelper
|
9
|
+
def self.included(base)
|
10
|
+
base.extend(ClassMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
# This #sanitize helper will html encode all tags and strip all attributes that aren't specifically allowed.
|
14
|
+
# It also strips href/src tags with invalid protocols, like javascript: especially. It does its best to counter any
|
15
|
+
# tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters. Check out
|
16
|
+
# the extensive test suite.
|
17
|
+
#
|
18
|
+
# <%= sanitize @article.body %>
|
19
|
+
#
|
20
|
+
# You can add or remove tags/attributes if you want to customize it a bit. See ActionView::Base for full docs on the
|
21
|
+
# available options. You can add tags/attributes for single uses of #sanitize by passing either the :attributes or :tags options:
|
22
|
+
#
|
23
|
+
# Normal Use
|
24
|
+
#
|
25
|
+
# <%= sanitize @article.body %>
|
26
|
+
#
|
27
|
+
# Custom Use (only the mentioned tags and attributes are allowed, nothing else)
|
28
|
+
#
|
29
|
+
# <%= sanitize @article.body, :tags => %w(table tr td), :attributes => %w(id class style)
|
30
|
+
#
|
31
|
+
# Add table tags to the default allowed tags
|
32
|
+
#
|
33
|
+
# Rails::Initializer.run do |config|
|
34
|
+
# config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# Remove tags to the default allowed tags
|
38
|
+
#
|
39
|
+
# Rails::Initializer.run do |config|
|
40
|
+
# config.after_initialize do
|
41
|
+
# ActionView::Base.sanitized_allowed_tags.delete 'div'
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# Change allowed default attributes
|
46
|
+
#
|
47
|
+
# Rails::Initializer.run do |config|
|
48
|
+
# config.action_view.sanitized_allowed_attributes = 'id', 'class', 'style'
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
def sanitize(html, options = {})
|
52
|
+
self.class.white_list_sanitizer.sanitize(html, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sanitizes a block of css code. Used by #sanitize when it comes across a style attribute
|
56
|
+
def sanitize_css(style)
|
57
|
+
self.class.white_list_sanitizer.sanitize_css(style)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Strips all HTML tags from the +html+, including comments. This uses the
|
61
|
+
# html-scanner tokenizer and so its HTML parsing ability is limited by
|
62
|
+
# that of html-scanner.
|
63
|
+
#
|
64
|
+
# ==== Examples
|
65
|
+
#
|
66
|
+
# strip_tags("Strip <i>these</i> tags!")
|
67
|
+
# # => Strip these tags!
|
68
|
+
#
|
69
|
+
# strip_tags("<b>Bold</b> no more! <a href='more.html'>See more here</a>...")
|
70
|
+
# # => Bold no more! See more here...
|
71
|
+
#
|
72
|
+
# strip_tags("<div id='top-bar'>Welcome to my website!</div>")
|
73
|
+
# # => Welcome to my website!
|
74
|
+
def strip_tags(html)
|
75
|
+
self.class.full_sanitizer.sanitize(html)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Strips all link tags from +text+ leaving just the link text.
|
79
|
+
#
|
80
|
+
# ==== Examples
|
81
|
+
# strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
|
82
|
+
# # => Ruby on Rails
|
83
|
+
#
|
84
|
+
# strip_links('Please e-mail me at <a href="mailto:me@email.com">me@email.com</a>.')
|
85
|
+
# # => Please e-mail me at me@email.com.
|
86
|
+
#
|
87
|
+
# strip_links('Blog: <a href="http://www.myblog.com/" class="nav" target=\"_blank\">Visit</a>.')
|
88
|
+
# # => Blog: Visit
|
89
|
+
def strip_links(html)
|
90
|
+
self.class.link_sanitizer.sanitize(html)
|
91
|
+
end
|
92
|
+
|
93
|
+
module ClassMethods #:nodoc:
|
94
|
+
def self.extended(base)
|
95
|
+
class << base
|
96
|
+
attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer
|
97
|
+
|
98
|
+
# we want these to be class methods on ActionView::Base, they'll get mattr_readers for these below.
|
99
|
+
helper_def = [:sanitized_protocol_separator, :sanitized_uri_attributes, :sanitized_bad_tags, :sanitized_allowed_tags,
|
100
|
+
:sanitized_allowed_attributes, :sanitized_allowed_css_properties, :sanitized_allowed_css_keywords,
|
101
|
+
:sanitized_shorthand_css_properties, :sanitized_allowed_protocols, :sanitized_protocol_separator=].collect! do |prop|
|
102
|
+
prop = prop.to_s
|
103
|
+
"def #{prop}(#{:value if prop =~ /=$/}) white_list_sanitizer.#{prop.sub /sanitized_/, ''} #{:value if prop =~ /=$/} end"
|
104
|
+
end.join("\n")
|
105
|
+
eval helper_def
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Gets the HTML::FullSanitizer instance used by strip_tags. Replace with
|
110
|
+
# any object that responds to #sanitize
|
111
|
+
#
|
112
|
+
# Rails::Initializer.run do |config|
|
113
|
+
# config.action_view.full_sanitizer = MySpecialSanitizer.new
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
def full_sanitizer
|
117
|
+
@full_sanitizer ||= HTML::FullSanitizer.new
|
118
|
+
end
|
119
|
+
|
120
|
+
# Gets the HTML::LinkSanitizer instance used by strip_links. Replace with
|
121
|
+
# any object that responds to #sanitize
|
122
|
+
#
|
123
|
+
# Rails::Initializer.run do |config|
|
124
|
+
# config.action_view.link_sanitizer = MySpecialSanitizer.new
|
125
|
+
# end
|
126
|
+
#
|
127
|
+
def link_sanitizer
|
128
|
+
@link_sanitizer ||= HTML::LinkSanitizer.new
|
129
|
+
end
|
130
|
+
|
131
|
+
# Gets the HTML::WhiteListSanitizer instance used by sanitize and sanitize_css.
|
132
|
+
# Replace with any object that responds to #sanitize
|
133
|
+
#
|
134
|
+
# Rails::Initializer.run do |config|
|
135
|
+
# config.action_view.white_list_sanitizer = MySpecialSanitizer.new
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
def white_list_sanitizer
|
139
|
+
@white_list_sanitizer ||= HTML::WhiteListSanitizer.new
|
140
|
+
end
|
141
|
+
|
142
|
+
# Adds valid HTML attributes that the #sanitize helper checks for URIs.
|
143
|
+
#
|
144
|
+
# Rails::Initializer.run do |config|
|
145
|
+
# config.action_view.sanitized_uri_attributes = 'lowsrc', 'target'
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
def sanitized_uri_attributes=(attributes)
|
149
|
+
HTML::WhiteListSanitizer.uri_attributes.merge(attributes)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Adds to the Set of 'bad' tags for the #sanitize helper.
|
153
|
+
#
|
154
|
+
# Rails::Initializer.run do |config|
|
155
|
+
# config.action_view.sanitized_bad_tags = 'embed', 'object'
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
def sanitized_bad_tags=(attributes)
|
159
|
+
HTML::WhiteListSanitizer.bad_tags.merge(attributes)
|
160
|
+
end
|
161
|
+
# Adds to the Set of allowed tags for the #sanitize helper.
|
162
|
+
#
|
163
|
+
# Rails::Initializer.run do |config|
|
164
|
+
# config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td'
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
def sanitized_allowed_tags=(attributes)
|
168
|
+
HTML::WhiteListSanitizer.allowed_tags.merge(attributes)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Adds to the Set of allowed html attributes for the #sanitize helper.
|
172
|
+
#
|
173
|
+
# Rails::Initializer.run do |config|
|
174
|
+
# config.action_view.sanitized_allowed_attributes = 'onclick', 'longdesc'
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
def sanitized_allowed_attributes=(attributes)
|
178
|
+
HTML::WhiteListSanitizer.allowed_attributes.merge(attributes)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Adds to the Set of allowed css properties for the #sanitize and #sanitize_css heleprs.
|
182
|
+
#
|
183
|
+
# Rails::Initializer.run do |config|
|
184
|
+
# config.action_view.sanitized_allowed_css_properties = 'expression'
|
185
|
+
# end
|
186
|
+
#
|
187
|
+
def sanitized_allowed_css_properties=(attributes)
|
188
|
+
HTML::WhiteListSanitizer.allowed_css_properties.merge(attributes)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Adds to the Set of allowed css keywords for the #sanitize and #sanitize_css helpers.
|
192
|
+
#
|
193
|
+
# Rails::Initializer.run do |config|
|
194
|
+
# config.action_view.sanitized_allowed_css_keywords = 'expression'
|
195
|
+
# end
|
196
|
+
#
|
197
|
+
def sanitized_allowed_css_keywords=(attributes)
|
198
|
+
HTML::WhiteListSanitizer.allowed_css_keywords.merge(attributes)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Adds to the Set of allowed shorthand css properties for the #sanitize and #sanitize_css helpers.
|
202
|
+
#
|
203
|
+
# Rails::Initializer.run do |config|
|
204
|
+
# config.action_view.sanitized_shorthand_css_properties = 'expression'
|
205
|
+
# end
|
206
|
+
#
|
207
|
+
def sanitized_shorthand_css_properties=(attributes)
|
208
|
+
HTML::WhiteListSanitizer.shorthand_css_properties.merge(attributes)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Adds to the Set of allowed protocols for the #sanitize helper.
|
212
|
+
#
|
213
|
+
# Rails::Initializer.run do |config|
|
214
|
+
# config.action_view.sanitized_allowed_protocols = 'ssh', 'feed'
|
215
|
+
# end
|
216
|
+
#
|
217
|
+
def sanitized_allowed_protocols=(attributes)
|
218
|
+
HTML::WhiteListSanitizer.allowed_protocols.merge(attributes)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'action_view/helpers/javascript_helper'
|
2
2
|
|
3
3
|
module ActionView
|
4
4
|
module Helpers
|
@@ -30,7 +30,7 @@ module ActionView
|
|
30
30
|
# variable in the generated JavaScript execution context. This can be
|
31
31
|
# used for example with drop_receiving_element:
|
32
32
|
#
|
33
|
-
# <%=
|
33
|
+
# <%= drop_receiving_element (...), :loading => visual_effect(:fade) %>
|
34
34
|
#
|
35
35
|
# This would fade the element that was dropped on the drop receiving
|
36
36
|
# element.
|
@@ -50,6 +50,10 @@ module ActionView
|
|
50
50
|
"'#{js_options[:queue]}'"
|
51
51
|
end if js_options[:queue]
|
52
52
|
|
53
|
+
[:endcolor, :direction, :startcolor, :scaleMode, :restorecolor].each do |option|
|
54
|
+
js_options[option] = "'#{js_options[option]}'" if js_options[option]
|
55
|
+
end
|
56
|
+
|
53
57
|
if TOGGLE_EFFECTS.include? name.to_sym
|
54
58
|
"Effect.toggle(#{element},'#{name.to_s.gsub(/^toggle_/,'')}',#{options_for_javascript(js_options)});"
|
55
59
|
else
|
@@ -72,10 +76,65 @@ module ActionView
|
|
72
76
|
# Important: For this to work, the sortable elements must have id
|
73
77
|
# attributes in the form "string_identifier". For example, "item_1". Only
|
74
78
|
# the identifier part of the id attribute will be serialized.
|
79
|
+
#
|
80
|
+
# Additional +options+ are:
|
75
81
|
#
|
82
|
+
# <tt>:format</tt>:: A regular expression to determine what to send
|
83
|
+
# as the serialized id to the server (the default
|
84
|
+
# is <tt>/^[^_]*_(.*)$/</tt>).
|
85
|
+
#
|
86
|
+
# <tt>:constraint</tt>:: Whether to constrain the dragging to either <tt>:horizontal</tt>
|
87
|
+
# or <tt>:vertical</tt> (or false to make it unconstrained).
|
88
|
+
#
|
89
|
+
# <tt>:overlap</tt>:: Calculate the item overlap in the <tt>:horizontal</tt> or
|
90
|
+
# <tt>:vertical</tt> direction.
|
91
|
+
#
|
92
|
+
# <tt>:tag</tt>:: Which children of the container element to treat as
|
93
|
+
# sortable (default is <tt>li</tt>).
|
94
|
+
#
|
95
|
+
# <tt>:containment</tt>:: Takes an element or array of elements to treat as
|
96
|
+
# potential drop targets (defaults to the original
|
97
|
+
# target element).
|
98
|
+
#
|
99
|
+
# <tt>:only</tt>:: A CSS class name or arry of class names used to filter
|
100
|
+
# out child elements as candidates.
|
101
|
+
#
|
102
|
+
# <tt>:scroll</tt>:: Determines whether to scroll the list during drag
|
103
|
+
# operationsif the list runs past the visual border.
|
104
|
+
#
|
105
|
+
# <tt>:tree</tt>:: Determines whether to treat nested lists as part of the
|
106
|
+
# main sortable list. This means that you can create multi-
|
107
|
+
# layer lists, and not only sort items at the same level,
|
108
|
+
# but drag and sort items between levels.
|
109
|
+
#
|
110
|
+
# <tt>:hoverclass</tt>:: If set, the Droppable will have this additional CSS class
|
111
|
+
# when an accepted Draggable is hovered over it.
|
112
|
+
#
|
113
|
+
# <tt>:handle</tt>:: Sets whether the element should only be draggable by an
|
114
|
+
# embedded handle. The value may be a string referencing a
|
115
|
+
# CSS class value (as of script.aculo.us V1.5). The first
|
116
|
+
# child/grandchild/etc. element found within the element
|
117
|
+
# that has this CSS class value will be used as the handle.
|
76
118
|
#
|
77
|
-
#
|
78
|
-
#
|
119
|
+
# <tt>:ghosting</tt>:: Clones the element and drags the clone, leaving the original
|
120
|
+
# in place until the clone is dropped (defaut is <tt>false</tt>).
|
121
|
+
#
|
122
|
+
# <tt>:dropOnEmpty</tt>:: If set to true, the Sortable container will be made into
|
123
|
+
# a Droppable, that can receive a Draggable (as according to
|
124
|
+
# the containment rules) as a child element when there are no
|
125
|
+
# more elements inside (defaut is <tt>false</tt>).
|
126
|
+
#
|
127
|
+
# <tt>:onChange</tt>:: Called whenever the sort order changes while dragging. When
|
128
|
+
# dragging from one Sortable to another, the callback is
|
129
|
+
# called once on each Sortable. Gets the affected element as
|
130
|
+
# its parameter.
|
131
|
+
#
|
132
|
+
# <tt>:onUpdate</tt>:: Called when the drag ends and the Sortable's order is
|
133
|
+
# changed in any way. When dragging from one Sortable to
|
134
|
+
# another, the callback is called once on each Sortable. Gets
|
135
|
+
# the container as its parameter.
|
136
|
+
#
|
137
|
+
# See http://script.aculo.us for more documentation.
|
79
138
|
def sortable_element(element_id, options = {})
|
80
139
|
javascript_tag(sortable_element_js(element_id, options).chop!)
|
81
140
|
end
|
@@ -3,33 +3,55 @@ require 'erb'
|
|
3
3
|
|
4
4
|
module ActionView
|
5
5
|
module Helpers #:nodoc:
|
6
|
-
#
|
6
|
+
# Provides methods to generate HTML tags programmatically when you can't use
|
7
7
|
# a Builder. By default, they output XHTML compliant tags.
|
8
8
|
module TagHelper
|
9
9
|
include ERB::Util
|
10
10
|
|
11
|
+
BOOLEAN_ATTRIBUTES = Set.new(%w(disabled readonly multiple))
|
12
|
+
|
11
13
|
# Returns an empty HTML tag of type +name+ which by default is XHTML
|
12
|
-
# compliant.
|
14
|
+
# compliant. Set +open+ to true to create an open tag compatible
|
13
15
|
# with HTML 4.0 and below. Add HTML attributes by passing an attributes
|
14
|
-
# hash to +options+.
|
15
|
-
#
|
16
|
+
# hash to +options+. Set +escape+ to false to disable attribute value
|
17
|
+
# escaping.
|
18
|
+
#
|
19
|
+
# ==== Options
|
20
|
+
# The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
|
21
|
+
# <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
|
16
22
|
# symbols or strings for the attribute names.
|
17
23
|
#
|
24
|
+
# ==== Examples
|
18
25
|
# tag("br")
|
19
|
-
#
|
26
|
+
# # => <br />
|
27
|
+
#
|
20
28
|
# tag("br", nil, true)
|
21
|
-
#
|
29
|
+
# # => <br>
|
30
|
+
#
|
22
31
|
# tag("input", { :type => 'text', :disabled => true })
|
23
|
-
#
|
24
|
-
|
25
|
-
|
32
|
+
# # => <input type="text" disabled="disabled" />
|
33
|
+
#
|
34
|
+
# tag("img", { :src => "open & shut.png" })
|
35
|
+
# # => <img src="open & shut.png" />
|
36
|
+
#
|
37
|
+
# tag("img", { :src => "open & shut.png" }, false, false)
|
38
|
+
# # => <img src="open & shut.png" />
|
39
|
+
def tag(name, options = nil, open = false, escape = true)
|
40
|
+
"<#{name}#{tag_options(options, escape) if options}" + (open ? ">" : " />")
|
26
41
|
end
|
27
42
|
|
28
43
|
# Returns an HTML block tag of type +name+ surrounding the +content+. Add
|
29
|
-
# HTML attributes by passing an attributes hash to +options+.
|
30
|
-
#
|
31
|
-
#
|
44
|
+
# HTML attributes by passing an attributes hash to +options+.
|
45
|
+
# Instead of passing the content as an argument, you can also use a block
|
46
|
+
# in which case, you pass your +options+ as the second parameter.
|
47
|
+
# Set escape to false to disable attribute value escaping.
|
32
48
|
#
|
49
|
+
# ==== Options
|
50
|
+
# The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
|
51
|
+
# <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
|
52
|
+
# symbols or strings for the attribute names.
|
53
|
+
#
|
54
|
+
# ==== Examples
|
33
55
|
# content_tag(:p, "Hello world!")
|
34
56
|
# # => <p>Hello world!</p>
|
35
57
|
# content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
|
@@ -37,21 +59,19 @@ module ActionView
|
|
37
59
|
# content_tag("select", options, :multiple => true)
|
38
60
|
# # => <select multiple="multiple">...options...</select>
|
39
61
|
#
|
40
|
-
# Instead of passing the content as an argument, you can also use a block
|
41
|
-
# in which case, you pass your +options+ as the second parameter.
|
42
|
-
#
|
43
62
|
# <% content_tag :div, :class => "strong" do -%>
|
44
63
|
# Hello world!
|
45
64
|
# <% end -%>
|
46
65
|
# # => <div class="strong"><p>Hello world!</p></div>
|
47
|
-
def content_tag(name, content_or_options_with_block = nil, options = nil, &block)
|
66
|
+
def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
|
48
67
|
if block_given?
|
49
68
|
options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
|
50
69
|
content = capture(&block)
|
51
|
-
|
70
|
+
content_tag = content_tag_string(name, content, options, escape)
|
71
|
+
block_is_within_action_view?(block) ? concat(content_tag, block.binding) : content_tag
|
52
72
|
else
|
53
73
|
content = content_or_options_with_block
|
54
|
-
content_tag_string(name, content, options)
|
74
|
+
content_tag_string(name, content, options, escape)
|
55
75
|
end
|
56
76
|
end
|
57
77
|
|
@@ -60,43 +80,53 @@ module ActionView
|
|
60
80
|
# otherwise be recognized as markup. CDATA sections begin with the string
|
61
81
|
# <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
|
62
82
|
#
|
83
|
+
# ==== Examples
|
63
84
|
# cdata_section("<hello world>")
|
64
|
-
#
|
85
|
+
# # => <![CDATA[<hello world>]]>
|
86
|
+
#
|
87
|
+
# cdata_section(File.read("hello_world.txt"))
|
88
|
+
# # => <![CDATA[<hello from a text file]]>
|
65
89
|
def cdata_section(content)
|
66
90
|
"<![CDATA[#{content}]]>"
|
67
91
|
end
|
68
92
|
|
69
|
-
# Returns
|
93
|
+
# Returns an escaped version of +html+ without affecting existing escaped entities.
|
70
94
|
#
|
95
|
+
# ==== Examples
|
71
96
|
# escape_once("1 > 2 & 3")
|
72
|
-
#
|
97
|
+
# # => "1 < 2 & 3"
|
98
|
+
#
|
99
|
+
# escape_once("<< Accept & Checkout")
|
100
|
+
# # => "<< Accept & Checkout"
|
73
101
|
def escape_once(html)
|
74
|
-
|
102
|
+
html.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] }
|
75
103
|
end
|
76
104
|
|
77
105
|
private
|
78
|
-
def content_tag_string(name, content, options)
|
79
|
-
tag_options =
|
106
|
+
def content_tag_string(name, content, options, escape = true)
|
107
|
+
tag_options = tag_options(options, escape) if options
|
80
108
|
"<#{name}#{tag_options}>#{content}</#{name}>"
|
81
109
|
end
|
82
|
-
|
83
|
-
def tag_options(options)
|
84
|
-
cleaned_options = convert_booleans(options.stringify_keys.reject {|key, value| value.nil?})
|
85
|
-
' ' + cleaned_options.map {|key, value| %(#{key}="#{escape_once(value)}")}.sort * ' ' unless cleaned_options.empty?
|
86
|
-
end
|
87
110
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
111
|
+
def tag_options(options, escape = true)
|
112
|
+
unless options.blank?
|
113
|
+
attrs = []
|
114
|
+
if escape
|
115
|
+
options.each do |key, value|
|
116
|
+
next unless value
|
117
|
+
key = key.to_s
|
118
|
+
value = BOOLEAN_ATTRIBUTES.include?(key) ? key : escape_once(value)
|
119
|
+
attrs << %(#{key}="#{value}")
|
120
|
+
end
|
121
|
+
else
|
122
|
+
attrs = options.map { |key, value| %(#{key}="#{value}") }
|
123
|
+
end
|
124
|
+
" #{attrs.sort * ' '}" unless attrs.empty?
|
125
|
+
end
|
91
126
|
end
|
92
127
|
|
93
|
-
def
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
# Fix double-escaped entities, such as &amp;, &#123;, etc.
|
98
|
-
def fix_double_escape(escaped)
|
99
|
-
escaped.gsub(/&([a-z]+|(#\d+));/i) { "&#{$1};" }
|
128
|
+
def block_is_within_action_view?(block)
|
129
|
+
eval("defined? _erbout", block.binding)
|
100
130
|
end
|
101
131
|
end
|
102
132
|
end
|