padrino-helpers 0.11.4 → 0.12.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +6 -6
- data/lib/padrino-helpers/asset_tag_helpers.rb +26 -33
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +16 -17
- data/lib/padrino-helpers/form_helpers.rb +121 -129
- data/lib/padrino-helpers/format_helpers.rb +1 -1
- data/lib/padrino-helpers/output_helpers/abstract_handler.rb +25 -60
- data/lib/padrino-helpers/output_helpers/erb_handler.rb +7 -58
- data/lib/padrino-helpers/output_helpers/haml_handler.rb +5 -43
- data/lib/padrino-helpers/output_helpers/slim_handler.rb +5 -65
- data/lib/padrino-helpers/output_helpers.rb +26 -13
- data/lib/padrino-helpers/render_helpers.rb +21 -18
- data/lib/padrino-helpers.rb +1 -0
- data/padrino-helpers.gemspec +2 -1
- data/test/fixtures/markup_app/app.rb +14 -10
- data/test/fixtures/markup_app/views/button_to.haml +2 -2
- data/test/fixtures/markup_app/views/capture_concat.haml +3 -3
- data/test/fixtures/markup_app/views/capture_concat.slim +3 -3
- data/test/fixtures/markup_app/views/content_for.erb +10 -1
- data/test/fixtures/markup_app/views/content_for.haml +7 -0
- data/test/fixtures/markup_app/views/content_for.slim +8 -1
- data/test/fixtures/markup_app/views/content_tag.erb +2 -0
- data/test/fixtures/markup_app/views/content_tag.haml +4 -2
- data/test/fixtures/markup_app/views/content_tag.slim +3 -1
- data/test/fixtures/markup_app/views/fields_for.haml +4 -4
- data/test/fixtures/markup_app/views/form_for.haml +3 -3
- data/test/fixtures/markup_app/views/form_tag.haml +6 -6
- data/test/fixtures/markup_app/views/link_to.haml +1 -1
- data/test/fixtures/markup_app/views/simple_partial.slim +1 -1
- data/test/fixtures/render_app/app.rb +16 -4
- data/test/fixtures/render_app/views/_deep.erb +3 -0
- data/test/fixtures/render_app/views/_deep.haml +2 -0
- data/test/fixtures/render_app/views/_deep.slim +2 -0
- data/test/fixtures/render_app/views/_partial_block_erb.erb +10 -0
- data/test/fixtures/render_app/views/_partial_block_haml.haml +7 -0
- data/test/fixtures/render_app/views/_partial_block_slim.slim +7 -0
- data/test/fixtures/render_app/views/double_capture_erb.erb +2 -2
- data/test/fixtures/render_app/views/double_capture_haml.haml +1 -1
- data/test/fixtures/render_app/views/double_capture_slim.slim +1 -1
- data/test/fixtures/render_app/views/render_block_erb.erb +5 -0
- data/test/fixtures/render_app/views/render_block_haml.haml +4 -0
- data/test/fixtures/render_app/views/render_block_slim.slim +4 -0
- data/test/fixtures/render_app/views/wrong_capture_erb.erb +3 -0
- data/test/fixtures/render_app/views/wrong_capture_haml.haml +2 -0
- data/test/fixtures/render_app/views/wrong_capture_slim.slim +2 -0
- data/test/test_asset_tag_helpers.rb +34 -0
- data/test/test_form_builder.rb +10 -0
- data/test/test_form_helpers.rb +18 -18
- data/test/test_format_helpers.rb +10 -0
- data/test/test_output_helpers.rb +25 -22
- data/test/test_render_helpers.rb +67 -0
- data/test/test_tag_helpers.rb +9 -0
- metadata +38 -7
@@ -19,6 +19,8 @@ module Padrino
|
|
19
19
|
# Also accepts HTML options.
|
20
20
|
# @option settings [String] :builder ("StandardFormBuilder")
|
21
21
|
# The FormBuilder class to use such as StandardFormBuilder.
|
22
|
+
# @option settings [Symbol] :as
|
23
|
+
# Sets custom form object name.
|
22
24
|
# @param [Proc] block
|
23
25
|
# The fields and content inside this form.
|
24
26
|
#
|
@@ -29,12 +31,14 @@ module Padrino
|
|
29
31
|
# @example
|
30
32
|
# form_for :user, '/register' do |f| ... end
|
31
33
|
# form_for @user, '/register', :id => 'register' do |f| ... end
|
34
|
+
# form_for @user, '/register', :as => :customer do |f| ... end
|
32
35
|
#
|
33
36
|
def form_for(object, url, settings={}, &block)
|
34
37
|
instance = builder_instance(object, settings)
|
35
38
|
html = capture_html(instance, &block)
|
36
39
|
settings[:multipart] = instance.multipart unless settings.include?(:multipart)
|
37
40
|
settings.delete(:namespace)
|
41
|
+
settings.delete(:as)
|
38
42
|
form_tag(url, settings) { html }
|
39
43
|
end
|
40
44
|
|
@@ -78,6 +82,7 @@ module Padrino
|
|
78
82
|
# form_tag '/register', :class => "registration_form" do ... end
|
79
83
|
#
|
80
84
|
def form_tag(url, options={}, &block)
|
85
|
+
options = options.dup
|
81
86
|
desired_method = options[:method].to_s
|
82
87
|
options.delete(:method) unless desired_method =~ /get|post/i
|
83
88
|
options.reverse_merge!(:method => 'post',
|
@@ -90,9 +95,7 @@ module Padrino
|
|
90
95
|
inner_form_html << csrf_token_field
|
91
96
|
end
|
92
97
|
inner_form_html << mark_safe(capture_html(&block))
|
93
|
-
|
94
|
-
form_html = content_tag(:form, inner_form_html, options)
|
95
|
-
not_concat ? form_html : concat_content(form_html)
|
98
|
+
concat_content content_tag(:form, inner_form_html, options)
|
96
99
|
end
|
97
100
|
|
98
101
|
##
|
@@ -172,50 +175,45 @@ module Padrino
|
|
172
175
|
#
|
173
176
|
def error_messages_for(*objects)
|
174
177
|
options = objects.extract_options!.symbolize_keys
|
175
|
-
objects = objects.map
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
178
|
+
objects = objects.map{ |obj| resolve_object(obj) }.compact
|
179
|
+
count = objects.inject(0){ |sum, object| sum + object.errors.count }
|
180
|
+
return ''.html_safe if count.zero?
|
181
|
+
|
182
|
+
html_options = {}
|
183
|
+
[:id, :class, :style].each do |key|
|
184
|
+
if options.include?(key)
|
185
|
+
value = options[key]
|
186
|
+
html_options[key] = value unless value.blank?
|
187
|
+
else
|
188
|
+
html_options[key] = 'field-errors' unless key == :style
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
|
193
|
+
object_name = options[:object_name] || objects.first.class.to_s.underscore.gsub(/\//, ' ')
|
194
|
+
|
195
|
+
header_message = if options.include?(:header_message)
|
196
|
+
options[:header_message]
|
197
|
+
else
|
198
|
+
model_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
|
199
|
+
locale.t :header, :count => count, :model => model_name
|
189
200
|
end
|
190
201
|
|
191
|
-
options[:
|
202
|
+
body_message = options[:message] || locale.t(:body)
|
192
203
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
object_name = options[:object_name]
|
198
|
-
object_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
|
199
|
-
locale.t :header, :count => count, :model => object_name
|
204
|
+
error_messages = objects.inject(''.html_safe) do |text, object|
|
205
|
+
object.errors.each do |field, message|
|
206
|
+
field_name = I18n.t(field, :default => field.to_s.humanize, :scope => [:models, object_name, :attributes])
|
207
|
+
text << content_tag(:li, "#{field_name} #{message}")
|
200
208
|
end
|
201
|
-
|
202
|
-
error_messages = objects.map { |object|
|
203
|
-
object_name = options[:object_name]
|
204
|
-
object.errors.map { |f, msg|
|
205
|
-
field = I18n.t(f, :default => f.to_s.humanize, :scope => [:models, object_name, :attributes])
|
206
|
-
content_tag(:li, "%s %s" % [field, msg])
|
207
|
-
}
|
208
|
-
}.join
|
209
|
-
|
210
|
-
contents = ActiveSupport::SafeBuffer.new
|
211
|
-
contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
|
212
|
-
contents << content_tag(:p, message) unless message.blank?
|
213
|
-
contents << safe_content_tag(:ul, error_messages)
|
214
|
-
|
215
|
-
content_tag(:div, contents, html)
|
209
|
+
text
|
216
210
|
end
|
217
|
-
|
218
|
-
|
211
|
+
|
212
|
+
contents = ActiveSupport::SafeBuffer.new
|
213
|
+
contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
|
214
|
+
contents << content_tag(:p, body_message) unless body_message.blank?
|
215
|
+
contents << content_tag(:ul, error_messages)
|
216
|
+
content_tag(:div, contents, html_options)
|
219
217
|
end
|
220
218
|
end
|
221
219
|
|
@@ -251,24 +249,12 @@ module Padrino
|
|
251
249
|
#
|
252
250
|
# @api public
|
253
251
|
def error_message_on(object, field, options={})
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
# give us an array others directly a value.
|
261
|
-
Array(error)[0]
|
262
|
-
end
|
263
|
-
|
264
|
-
if error = Array(error)[0]
|
265
|
-
options.reverse_merge!(:tag => :span, :class => :error)
|
266
|
-
tag = options.delete(:tag)
|
267
|
-
error = [options.delete(:prepend), error, options.delete(:append)].compact.join(" ")
|
268
|
-
content_tag(tag, error, options)
|
269
|
-
else
|
270
|
-
''
|
271
|
-
end
|
252
|
+
error = Array(resolve_object(object).errors[field]).first
|
253
|
+
return ''.html_safe unless error
|
254
|
+
options = options.reverse_merge(:tag => :span, :class => :error)
|
255
|
+
tag = options.delete(:tag)
|
256
|
+
error = [options.delete(:prepend), error, options.delete(:append)].compact.join(" ")
|
257
|
+
content_tag(tag, error, options)
|
272
258
|
end
|
273
259
|
|
274
260
|
##
|
@@ -290,14 +276,15 @@ module Padrino
|
|
290
276
|
# label_tag :username, :class => 'long-label' do ... end
|
291
277
|
#
|
292
278
|
def label_tag(name, options={}, &block)
|
293
|
-
options.reverse_merge
|
294
|
-
caption_text =
|
279
|
+
options = options.reverse_merge(:caption => "#{name.to_s.humanize}: ", :for => name)
|
280
|
+
caption_text = ''.html_safe
|
281
|
+
caption_text.concat options.delete(:caption)
|
295
282
|
caption_text.safe_concat "<span class='required'>*</span> " if options.delete(:required)
|
296
283
|
|
297
|
-
if block_given?
|
284
|
+
if block_given?
|
298
285
|
label_content = caption_text.concat capture_html(&block)
|
299
286
|
concat_content(content_tag(:label, label_content, options))
|
300
|
-
else
|
287
|
+
else
|
301
288
|
content_tag(:label, caption_text, options)
|
302
289
|
end
|
303
290
|
end
|
@@ -360,7 +347,7 @@ module Padrino
|
|
360
347
|
# # => <input name="username" placeholder="Your Username" type="text" />
|
361
348
|
#
|
362
349
|
def text_field_tag(name, options={})
|
363
|
-
input_tag(:text, options.reverse_merge
|
350
|
+
input_tag(:text, options.reverse_merge(:name => name))
|
364
351
|
end
|
365
352
|
|
366
353
|
##
|
@@ -510,8 +497,7 @@ module Padrino
|
|
510
497
|
# hidden_field_tag :session_key, :value => "__secret__"
|
511
498
|
#
|
512
499
|
def hidden_field_tag(name, options={})
|
513
|
-
options.reverse_merge
|
514
|
-
input_tag(:hidden, options)
|
500
|
+
input_tag(:hidden, options.reverse_merge(:name => name))
|
515
501
|
end
|
516
502
|
|
517
503
|
##
|
@@ -521,7 +507,7 @@ module Padrino
|
|
521
507
|
# text_area_tag :username, :class => 'long', :value => "Demo?"
|
522
508
|
#
|
523
509
|
def text_area_tag(name, options={})
|
524
|
-
options.reverse_merge
|
510
|
+
options = options.reverse_merge(:name => name, :rows => "", :cols => "")
|
525
511
|
content_tag(:textarea, options.delete(:value).to_s, options)
|
526
512
|
end
|
527
513
|
|
@@ -533,8 +519,7 @@ module Padrino
|
|
533
519
|
#
|
534
520
|
# @api public
|
535
521
|
def password_field_tag(name, options={})
|
536
|
-
options.reverse_merge
|
537
|
-
input_tag(:password, options)
|
522
|
+
input_tag(:password, options.reverse_merge(:name => name))
|
538
523
|
end
|
539
524
|
|
540
525
|
##
|
@@ -544,8 +529,7 @@ module Padrino
|
|
544
529
|
# check_box_tag :remember_me, :value => 'Yes'
|
545
530
|
#
|
546
531
|
def check_box_tag(name, options={})
|
547
|
-
options.reverse_merge
|
548
|
-
input_tag(:checkbox, options)
|
532
|
+
input_tag(:checkbox, options.reverse_merge(:name => name, :value => '1'))
|
549
533
|
end
|
550
534
|
|
551
535
|
##
|
@@ -555,8 +539,7 @@ module Padrino
|
|
555
539
|
# radio_button_tag :remember_me, :value => 'true'
|
556
540
|
#
|
557
541
|
def radio_button_tag(name, options={})
|
558
|
-
options.reverse_merge
|
559
|
-
input_tag(:radio, options)
|
542
|
+
input_tag(:radio, options.reverse_merge(:name => name))
|
560
543
|
end
|
561
544
|
|
562
545
|
##
|
@@ -568,8 +551,7 @@ module Padrino
|
|
568
551
|
# @api public
|
569
552
|
def file_field_tag(name, options={})
|
570
553
|
name = "#{name}[]" if options[:multiple]
|
571
|
-
options.reverse_merge
|
572
|
-
input_tag(:file, options)
|
554
|
+
input_tag(:file, options.reverse_merge(:name => name))
|
573
555
|
end
|
574
556
|
|
575
557
|
##
|
@@ -613,18 +595,12 @@ module Padrino
|
|
613
595
|
# @return [String] The HTML input field based on the +options+ specified.
|
614
596
|
#
|
615
597
|
def select_tag(name, options={})
|
616
|
-
options.reverse_merge
|
598
|
+
options = options.reverse_merge(:name => name)
|
599
|
+
options[:name] = "#{options[:name]}[]" if options[:multiple]
|
617
600
|
collection, fields = options.delete(:collection), options.delete(:fields)
|
618
601
|
options[:options] = options_from_collection(collection, fields) if collection
|
619
|
-
|
620
|
-
|
621
|
-
options_for_select(options.delete(:options), options.delete(:selected))
|
622
|
-
elsif options[:grouped_options]
|
623
|
-
grouped_options_for_select(options.delete(:grouped_options), options.delete(:selected), prompt)
|
624
|
-
end
|
625
|
-
select_options_html = select_options_html.unshift(blank_option(prompt)) if select_options_html.is_a?(Array)
|
626
|
-
options.merge!(:name => "#{options[:name]}[]") if options[:multiple]
|
627
|
-
safe_content_tag(:select, select_options_html, options)
|
602
|
+
options_tags = extract_option_tags!(options)
|
603
|
+
content_tag(:select, options_tags, options)
|
628
604
|
end
|
629
605
|
|
630
606
|
##
|
@@ -641,8 +617,7 @@ module Padrino
|
|
641
617
|
# button_tag "Cancel", :class => 'clear'
|
642
618
|
#
|
643
619
|
def button_tag(caption, options = {})
|
644
|
-
options.reverse_merge
|
645
|
-
input_tag(:button, options)
|
620
|
+
input_tag(:button, options.reverse_merge(:value => caption))
|
646
621
|
end
|
647
622
|
|
648
623
|
##
|
@@ -660,10 +635,9 @@ module Padrino
|
|
660
635
|
# submit_tag :class => 'btn'
|
661
636
|
#
|
662
637
|
def submit_tag(*args)
|
663
|
-
options = args
|
664
|
-
caption = args.length >= 1 ? args.
|
665
|
-
options.reverse_merge
|
666
|
-
input_tag(:submit, options)
|
638
|
+
options = args.extract_options!
|
639
|
+
caption = args.length >= 1 ? args.first : "Submit"
|
640
|
+
input_tag(:submit, options.reverse_merge(:value => caption))
|
667
641
|
end
|
668
642
|
|
669
643
|
##
|
@@ -677,11 +651,10 @@ module Padrino
|
|
677
651
|
# @return [String] The html image button based on the +options+ specified.
|
678
652
|
#
|
679
653
|
# @example
|
680
|
-
#
|
654
|
+
# image_submit_tag 'form/submit.png'
|
681
655
|
#
|
682
656
|
def image_submit_tag(source, options={})
|
683
|
-
options.reverse_merge
|
684
|
-
input_tag(:image, options)
|
657
|
+
input_tag(:image, options.reverse_merge(:src => image_path(source)))
|
685
658
|
end
|
686
659
|
|
687
660
|
##
|
@@ -747,14 +720,14 @@ module Padrino
|
|
747
720
|
# # </form>
|
748
721
|
#
|
749
722
|
def button_to(*args, &block)
|
723
|
+
options = args.extract_options!.dup
|
750
724
|
name, url = args[0], args[1]
|
751
|
-
options = args.extract_options!
|
752
725
|
options['data-remote'] = 'true' if options.delete(:remote)
|
753
726
|
submit_options = options.delete(:submit_options) || {}
|
754
727
|
if block_given?
|
755
|
-
form_tag(url, options, &block)
|
728
|
+
form_tag(url || name, options, &block)
|
756
729
|
else
|
757
|
-
form_tag(url, options
|
730
|
+
form_tag(url, options) do
|
758
731
|
submit_tag(name, submit_options)
|
759
732
|
end
|
760
733
|
end
|
@@ -780,7 +753,7 @@ module Padrino
|
|
780
753
|
# @return [String] The html range field
|
781
754
|
#
|
782
755
|
def range_field_tag(name, options = {})
|
783
|
-
options.reverse_merge
|
756
|
+
options = options.reverse_merge(:name => name)
|
784
757
|
if range = options.delete(:range)
|
785
758
|
options[:min], options[:max] = range.min, range.max
|
786
759
|
end
|
@@ -802,39 +775,27 @@ module Padrino
|
|
802
775
|
##
|
803
776
|
# Returns the options tags for a select based on the given option items.
|
804
777
|
#
|
805
|
-
def options_for_select(option_items,
|
778
|
+
def options_for_select(option_items, state = {})
|
806
779
|
return [] if option_items.blank?
|
807
|
-
option_items.map do |caption, value,
|
808
|
-
value
|
809
|
-
|
810
|
-
|
780
|
+
option_items.map do |caption, value, attributes|
|
781
|
+
html_attributes = { :value => value || caption }.merge(attributes||{})
|
782
|
+
html_attributes[:selected] ||= option_is_selected?(value, caption, state[:selected])
|
783
|
+
html_attributes[:disabled] ||= option_is_selected?(value, caption, state[:disabled])
|
784
|
+
content_tag(:option, caption, html_attributes)
|
811
785
|
end
|
812
786
|
end
|
813
787
|
|
814
788
|
##
|
815
789
|
# Returns the optgroups with options tags for a select based on the given :grouped_options items.
|
816
790
|
#
|
817
|
-
def grouped_options_for_select(collection,
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
disabled ||= attributes_hash && attributes_hash.include?(:disabled) ? attributes_hash[:disabled] : false
|
826
|
-
content_tag :optgroup, options_for_select(value, selected), :label => key, :disabled => disabled
|
827
|
-
end
|
828
|
-
elsif collection.is_a?(Array)
|
829
|
-
# Array format:
|
830
|
-
# ["Option Label", [:option1, :option2, ...]]
|
831
|
-
# or:
|
832
|
-
# ["Option Label", [:option1, :option2, ...], true]
|
833
|
-
# the last item tells if it is disabled or not. This is keeps it backwards compatible.
|
834
|
-
collection.map do |optgroup|
|
835
|
-
disabled ||= optgroup.count > 2 ? optgroup.pop : false
|
836
|
-
content_tag :optgroup, options_for_select(optgroup.last, selected), :label => optgroup.first, :disabled => disabled
|
837
|
-
end
|
791
|
+
def grouped_options_for_select(collection, state = {})
|
792
|
+
collection.map do |item|
|
793
|
+
caption = item.shift
|
794
|
+
attributes = item.last.kind_of?(Hash) ? item.pop : {}
|
795
|
+
value = item.flatten(1)
|
796
|
+
attributes = value.pop if value.last.kind_of?(Hash)
|
797
|
+
html_attributes = { :label => caption }.merge(attributes||{})
|
798
|
+
content_tag(:optgroup, options_for_select(value, state), html_attributes)
|
838
799
|
end
|
839
800
|
end
|
840
801
|
|
@@ -842,11 +803,15 @@ module Padrino
|
|
842
803
|
# Returns the blank option serving as a prompt if passed.
|
843
804
|
#
|
844
805
|
def blank_option(prompt)
|
845
|
-
return unless prompt
|
846
806
|
case prompt
|
847
|
-
|
848
|
-
|
849
|
-
|
807
|
+
when nil, false
|
808
|
+
nil
|
809
|
+
when String
|
810
|
+
content_tag(:option, prompt, :value => '')
|
811
|
+
when Array
|
812
|
+
content_tag(:option, prompt.first, :value => prompt.last)
|
813
|
+
else
|
814
|
+
content_tag(:option, '', :value => '')
|
850
815
|
end
|
851
816
|
end
|
852
817
|
|
@@ -877,6 +842,7 @@ module Padrino
|
|
877
842
|
end
|
878
843
|
|
879
844
|
private
|
845
|
+
|
880
846
|
##
|
881
847
|
# Returns the FormBuilder class to use based on all available setting sources
|
882
848
|
# If explicitly defined, returns that, otherwise returns defaults.
|
@@ -914,6 +880,32 @@ module Padrino
|
|
914
880
|
[value.to_s, caption.to_s].include?(selected.to_s)
|
915
881
|
end
|
916
882
|
end
|
883
|
+
|
884
|
+
def extract_option_state!(options)
|
885
|
+
{
|
886
|
+
:selected => Array(options.delete(:selected))|Array(options.delete(:selected_options)),
|
887
|
+
:disabled => Array(options.delete(:disabled_options))
|
888
|
+
}
|
889
|
+
end
|
890
|
+
|
891
|
+
def extract_option_tags!(options)
|
892
|
+
state = extract_option_state!(options)
|
893
|
+
option_tags = case
|
894
|
+
when options[:options]
|
895
|
+
options_for_select(options.delete(:options), state)
|
896
|
+
when options[:grouped_options]
|
897
|
+
grouped_options_for_select(options.delete(:grouped_options), state)
|
898
|
+
else
|
899
|
+
[]
|
900
|
+
end
|
901
|
+
prompt = options.delete(:include_blank)
|
902
|
+
option_tags.unshift(blank_option(prompt)) if prompt
|
903
|
+
option_tags
|
904
|
+
end
|
905
|
+
|
906
|
+
def resolve_object(object)
|
907
|
+
object.is_a?(Symbol) ? instance_variable_get("@#{object}") : object
|
908
|
+
end
|
917
909
|
end
|
918
910
|
end
|
919
911
|
end
|
@@ -78,7 +78,7 @@ module Padrino
|
|
78
78
|
def simple_format(text, options={})
|
79
79
|
t = options.delete(:tag) || :p
|
80
80
|
start_tag = tag(t, options, true)
|
81
|
-
text = escape_html(text.to_s.dup)
|
81
|
+
text = escape_html(text.to_s.dup) unless text.html_safe?
|
82
82
|
text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
|
83
83
|
text.gsub!(/\n\n+/, "</#{t}>\n\n#{start_tag}") # 2+ newline -> paragraph
|
84
84
|
text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
|
@@ -1,94 +1,59 @@
|
|
1
1
|
module Padrino
|
2
2
|
module Helpers
|
3
3
|
module OutputHelpers
|
4
|
-
##
|
5
|
-
# Returns the list of all available template handlers.
|
6
|
-
#
|
7
|
-
# @example
|
8
|
-
# OutputHelpers.handlers => [<OutputHelpers::HamlHandler>, <OutputHelpers::ErbHandler>]
|
9
|
-
#
|
10
|
-
def self.handlers
|
11
|
-
@_template_handlers ||= []
|
12
|
-
end
|
13
|
-
|
14
|
-
##
|
15
|
-
# Registers a new handler as available to the output helpers.
|
16
|
-
#
|
17
|
-
# @example
|
18
|
-
# OutputHelpers.register(OutputHelpers::HamlHandler)
|
19
|
-
#
|
20
|
-
def self.register(handler)
|
21
|
-
handlers << handler
|
22
|
-
end
|
23
|
-
|
24
|
-
# @abstract Extend this to create a template handler.
|
25
4
|
class AbstractHandler
|
26
|
-
attr_reader :template
|
5
|
+
attr_reader :template, :output_buffer
|
27
6
|
|
28
7
|
def initialize(template)
|
29
8
|
@template = template
|
30
|
-
|
31
|
-
|
32
|
-
##
|
33
|
-
# Returns extension of the template.
|
34
|
-
#
|
35
|
-
# @example
|
36
|
-
# @handler.template_extension => "erb"
|
37
|
-
#
|
38
|
-
def template_extension
|
39
|
-
caller.find { |c| c =~ /\/views\// }[/\.([\w]*?)\:/, 1] rescue nil
|
40
|
-
# "/some/path/app/views/posts/foo.html.erb:3:in `evaluate_source'"
|
41
|
-
# => "erb"
|
42
|
-
end
|
43
|
-
|
44
|
-
##
|
45
|
-
# Returns an array of engines used for the template.
|
46
|
-
#
|
47
|
-
# @example
|
48
|
-
# @handler.engines => [:erb, :erubis]
|
49
|
-
#
|
50
|
-
def engines
|
51
|
-
# Implemented in subclass.
|
52
|
-
end
|
53
|
-
|
54
|
-
##
|
55
|
-
# Returns true if the current template type is same as this handlers; false otherwise.
|
56
|
-
#
|
57
|
-
# @example
|
58
|
-
# @handler.is_type? => true
|
59
|
-
#
|
60
|
-
def is_type?
|
61
|
-
# Implemented in subclass.
|
9
|
+
@output_buffer = template.instance_variable_get(:@_out_buf)
|
62
10
|
end
|
63
11
|
|
64
12
|
##
|
65
13
|
# Returns true if the block given is of the handler's template type; false otherwise.
|
66
14
|
#
|
67
15
|
# @example
|
68
|
-
# @handler.
|
16
|
+
# @handler.engine_matches?(block) => true
|
69
17
|
#
|
70
|
-
def
|
71
|
-
# Implemented in subclass.
|
18
|
+
def engine_matches?(block)
|
72
19
|
end
|
73
20
|
|
74
21
|
##
|
75
22
|
# Captures the html from a block of template code for this handler.
|
76
23
|
#
|
24
|
+
# This method is called to capture content of a block-loving helpers in templates.
|
25
|
+
# Haml has a special method to do this, for Erb and Slim we save original buffer,
|
26
|
+
# call the block and then restore the buffer.
|
27
|
+
#
|
77
28
|
# @example
|
78
29
|
# @handler.capture_from_template(&block) => "...html..."
|
79
30
|
#
|
80
31
|
def capture_from_template(*args, &block)
|
81
|
-
|
32
|
+
self.output_buffer, _buf_was = ActiveSupport::SafeBuffer.new, self.output_buffer
|
33
|
+
raw = block.call(*args)
|
34
|
+
captured = template.instance_variable_get(:@_out_buf)
|
35
|
+
self.output_buffer = _buf_was
|
36
|
+
engine_matches?(block) ? captured : raw
|
82
37
|
end
|
83
38
|
|
84
39
|
##
|
85
|
-
# Outputs the given text to the
|
40
|
+
# Outputs the given text to the template.
|
41
|
+
#
|
42
|
+
# This method is called when template uses block-aware helpers. For Slim and Haml such
|
43
|
+
# helpers just return output to use with `=`. For Erb this method is implemented in
|
44
|
+
# ErbHandler by concatenating given text to output buffer.
|
86
45
|
#
|
87
46
|
# @example
|
88
47
|
# @handler.concat_to_template("This will be output to the template buffer")
|
89
48
|
#
|
90
49
|
def concat_to_template(text="")
|
91
|
-
|
50
|
+
text
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def output_buffer=(val)
|
56
|
+
template.instance_variable_set(:@_out_buf, val)
|
92
57
|
end
|
93
58
|
end
|
94
59
|
end
|
@@ -2,77 +2,26 @@ module Padrino
|
|
2
2
|
module Helpers
|
3
3
|
module OutputHelpers
|
4
4
|
##
|
5
|
-
# Handler for
|
5
|
+
# Handler for Erb template.
|
6
6
|
#
|
7
7
|
class ErbHandler < AbstractHandler
|
8
|
-
attr_reader :output_buffer
|
9
|
-
|
10
|
-
def initialize(template)
|
11
|
-
super
|
12
|
-
@output_buffer = template.instance_variable_get(:@_out_buf)
|
13
|
-
end
|
14
|
-
|
15
|
-
##
|
16
|
-
# Returns true if the current template type is same as this handlers; false otherwise.
|
17
|
-
#
|
18
|
-
# @example
|
19
|
-
# @handler.is_type? => true
|
20
|
-
#
|
21
|
-
def is_type?
|
22
|
-
!self.output_buffer.nil?
|
23
|
-
end
|
24
|
-
|
25
|
-
##
|
26
|
-
# Captures the html from a block of template code for this handler.
|
27
|
-
#
|
28
|
-
# @example
|
29
|
-
# @handler.capture_from_template(&block) => "...html..."
|
30
|
-
#
|
31
|
-
def capture_from_template(*args, &block)
|
32
|
-
self.output_buffer, _buf_was = ActiveSupport::SafeBuffer.new, self.output_buffer
|
33
|
-
captured_block = block.call(*args)
|
34
|
-
ret = eval("@_out_buf", block.binding)
|
35
|
-
self.output_buffer = _buf_was
|
36
|
-
[ ret, captured_block ]
|
37
|
-
end
|
38
|
-
|
39
8
|
##
|
40
9
|
# Outputs the given text to the templates buffer directly.
|
41
10
|
#
|
42
|
-
# @example
|
43
|
-
# @handler.concat_to_template("This will be output to the template buffer")
|
44
|
-
#
|
45
11
|
def concat_to_template(text="")
|
46
|
-
|
12
|
+
output_buffer << text
|
47
13
|
nil
|
48
14
|
end
|
49
15
|
|
50
16
|
##
|
51
|
-
# Returns true if the block
|
17
|
+
# Returns true if the block is Erb.
|
52
18
|
#
|
53
|
-
|
54
|
-
|
55
|
-
#
|
56
|
-
def block_is_type?(block)
|
57
|
-
is_type? || (block && eval('defined?(__in_erb_template)', block.binding))
|
58
|
-
end
|
59
|
-
|
60
|
-
##
|
61
|
-
# Returns an array of engines used for the template.
|
62
|
-
#
|
63
|
-
# @example
|
64
|
-
# @handler.engines => [:erb, :erubis]
|
65
|
-
#
|
66
|
-
def engines
|
67
|
-
@_engines ||= [:erb, :erubis]
|
68
|
-
end
|
69
|
-
|
70
|
-
protected
|
71
|
-
def output_buffer=(val)
|
72
|
-
template.instance_variable_set(:@_out_buf, val)
|
19
|
+
def engine_matches?(block)
|
20
|
+
block.binding.eval('defined? __in_erb_template')
|
73
21
|
end
|
74
22
|
end
|
75
|
-
OutputHelpers.register(ErbHandler)
|
23
|
+
OutputHelpers.register(:erb, ErbHandler)
|
24
|
+
OutputHelpers.register(:erubis, ErbHandler)
|
76
25
|
end
|
77
26
|
end
|
78
27
|
end
|