forme 1.9.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +70 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +396 -202
- data/lib/forme/bs3.rb +19 -5
- data/lib/forme/erb.rb +18 -16
- data/lib/forme/form.rb +151 -118
- data/lib/forme/input.rb +1 -1
- data/lib/forme/rails.rb +41 -72
- data/lib/forme/raw.rb +2 -2
- data/lib/forme/sinatra.rb +6 -2
- data/lib/forme/tag.rb +3 -12
- data/lib/forme/template.rb +118 -0
- data/lib/forme/transformers/error_handler.rb +46 -1
- data/lib/forme/transformers/formatter.rb +36 -35
- data/lib/forme/transformers/helper.rb +0 -1
- data/lib/forme/transformers/inputs_wrapper.rb +6 -6
- data/lib/forme/transformers/labeler.rb +19 -0
- data/lib/forme/transformers/wrapper.rb +1 -1
- data/lib/forme/version.rb +2 -2
- data/lib/forme.rb +15 -2
- data/lib/roda/plugins/forme.rb +1 -1
- data/lib/roda/plugins/forme_erubi_capture.rb +62 -0
- data/lib/roda/plugins/forme_route_csrf.rb +16 -20
- data/lib/roda/plugins/forme_set.rb +177 -0
- data/lib/sequel/plugins/forme.rb +42 -55
- data/lib/sequel/plugins/forme_i18n.rb +3 -1
- data/lib/sequel/plugins/forme_set.rb +50 -28
- data/spec/all.rb +1 -1
- data/spec/bs3_reference_spec.rb +18 -18
- data/spec/bs3_sequel_plugin_spec.rb +7 -7
- data/spec/bs3_spec.rb +23 -11
- data/spec/erb_helper.rb +73 -58
- data/spec/erubi_capture_helper.rb +202 -0
- data/spec/forme_spec.rb +80 -29
- data/spec/rails_integration_spec.rb +47 -24
- data/spec/roda_integration_spec.rb +459 -48
- data/spec/sequel_helper.rb +0 -1
- data/spec/sequel_i18n_helper.rb +1 -1
- data/spec/sequel_i18n_plugin_spec.rb +3 -2
- data/spec/sequel_plugin_spec.rb +25 -8
- data/spec/sequel_set_plugin_spec.rb +10 -3
- data/spec/shared_erb_specs.rb +75 -0
- data/spec/sinatra_integration_spec.rb +5 -6
- data/spec/spec_helper.rb +23 -5
- metadata +30 -8
- data/lib/forme/erb_form.rb +0 -74
data/lib/forme/sinatra.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
|
3
|
+
if RUBY_VERSION >= '2'
|
4
|
+
warn('forme/sinatra and Forme::Sinatra::ERB are deprecated and will be removed in a future version, switch to forme/erb and Forme::ERB::Helper', :uplevel=>1)
|
5
|
+
end
|
6
|
+
|
7
|
+
require_relative 'erb'
|
4
8
|
|
5
9
|
module Forme
|
6
10
|
# For backwards compatibility only. New code should
|
@@ -11,7 +15,7 @@ module Forme
|
|
11
15
|
module Sinatra
|
12
16
|
ERB = Forme::ERB::Helper
|
13
17
|
Erubis = ERB
|
14
|
-
Form = Forme::
|
18
|
+
Form = Forme::Template::Form
|
15
19
|
HIDDEN_TAGS = Forme::ERB::HIDDEN_TAGS
|
16
20
|
end
|
17
21
|
end
|
data/lib/forme/tag.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
3
|
module Forme
|
4
|
-
# Low level abstract tag form, where each instance represents
|
5
|
-
#
|
4
|
+
# Low level abstract tag form, where each instance represents an
|
5
|
+
# HTML tag with attributes and children.
|
6
6
|
class Tag
|
7
7
|
# The +Form+ object related to the receiver.
|
8
8
|
attr_reader :form
|
@@ -23,15 +23,6 @@ module Forme
|
|
23
23
|
@children = parse_children(children)
|
24
24
|
end
|
25
25
|
|
26
|
-
# Adds a child to the array of receiver's children.
|
27
|
-
def <<(child)
|
28
|
-
if children
|
29
|
-
children << child
|
30
|
-
else
|
31
|
-
@children = [child]
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
26
|
# Create a new +Tag+ instance with the given arguments and block
|
36
27
|
# related to the receiver's +form+.
|
37
28
|
def tag(*a, &block)
|
@@ -40,7 +31,7 @@ module Forme
|
|
40
31
|
|
41
32
|
# Return a string containing the serialized content of the receiver.
|
42
33
|
def to_s
|
43
|
-
|
34
|
+
Forme.transform(:serializer, @opts, @form.opts, self)
|
44
35
|
end
|
45
36
|
|
46
37
|
private
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../forme'
|
4
|
+
|
5
|
+
module Forme
|
6
|
+
module Template
|
7
|
+
class Form
|
8
|
+
def initialize(form, scope)
|
9
|
+
@form = form
|
10
|
+
@scope = scope
|
11
|
+
end
|
12
|
+
|
13
|
+
# Delegate calls by default to the wrapped form
|
14
|
+
def method_missing(*a, &block)
|
15
|
+
@form.public_send(*a, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
# If a block is given to inputs, tag, or subform,
|
19
|
+
# emit the already generated HTML for the form before yielding
|
20
|
+
# to the block, and after returning, emit any HTML generated
|
21
|
+
# after returning from the block.
|
22
|
+
%w'inputs tag subform'.each do |meth|
|
23
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
24
|
+
def #{meth}(*a, &block)
|
25
|
+
return @form.#{meth}(*a) unless block
|
26
|
+
|
27
|
+
buffer = @form.to_s
|
28
|
+
offset = buffer.length
|
29
|
+
@form.#{meth}(*a) do
|
30
|
+
emit(buffer[offset, buffer.length])
|
31
|
+
yield self
|
32
|
+
offset = buffer.length
|
33
|
+
end
|
34
|
+
emit(buffer[offset, buffer.length])
|
35
|
+
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
END
|
39
|
+
end
|
40
|
+
|
41
|
+
# Serialize the tag and inject it into the output.
|
42
|
+
def emit(tag)
|
43
|
+
return unless output = output()
|
44
|
+
output << tag
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def output
|
50
|
+
@scope.instance_variable_get(:@_out_buf)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# This is the module used to add the Forme integration
|
55
|
+
# to ERB.
|
56
|
+
module Helper
|
57
|
+
# Create a +Form+ object tied to the current output buffer,
|
58
|
+
# using the standard ERB hidden tags.
|
59
|
+
def form(obj=nil, attr={}, opts={}, &block)
|
60
|
+
if obj.is_a?(Hash)
|
61
|
+
attribs = obj
|
62
|
+
options = attr = attr.dup
|
63
|
+
else
|
64
|
+
attribs = attr
|
65
|
+
options = opts = opts.dup
|
66
|
+
end
|
67
|
+
|
68
|
+
_forme_form_options(obj, attribs, options)
|
69
|
+
_forme_form(obj, attr, opts, &block)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def _forme_form(obj, attr, opts, &block)
|
75
|
+
if block_given?
|
76
|
+
erb_form = buffer = offset = nil
|
77
|
+
block = proc do
|
78
|
+
wrapped_form = erb_form.instance_variable_get(:@form)
|
79
|
+
buffer = wrapped_form.to_s
|
80
|
+
offset = buffer.length
|
81
|
+
erb_form.emit(buffer[0, buffer.length])
|
82
|
+
yield erb_form
|
83
|
+
offset = buffer.length
|
84
|
+
end
|
85
|
+
|
86
|
+
f, attr, block = _forme_wrapped_form_class.form_args(obj, attr, opts, &block)
|
87
|
+
erb_form = _forme_form_class.new(f, self)
|
88
|
+
erb_form.form(attr, &block)
|
89
|
+
erb_form.emit(buffer[offset, buffer.length])
|
90
|
+
else
|
91
|
+
_forme_wrapped_form_class.form(obj, attr, opts, &block)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def _forme_wrapped_form_class
|
96
|
+
::Forme::Form
|
97
|
+
end
|
98
|
+
|
99
|
+
# The class to use for forms
|
100
|
+
def _forme_form_class
|
101
|
+
Form
|
102
|
+
end
|
103
|
+
|
104
|
+
# The options to use for forms. Any changes should mutate this hash to set options.
|
105
|
+
def _forme_form_options(obj, attr, opts)
|
106
|
+
if hidden_tags = _forme_form_hidden_tags
|
107
|
+
opts[:hidden_tags] ||= []
|
108
|
+
opts[:hidden_tags] += hidden_tags
|
109
|
+
end
|
110
|
+
opts[:hidden_tags_uplevel] = 1
|
111
|
+
end
|
112
|
+
|
113
|
+
def _forme_form_hidden_tags
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -11,10 +11,55 @@ module Forme
|
|
11
11
|
|
12
12
|
# Return tag with error message span tag after it.
|
13
13
|
def call(tag, input)
|
14
|
+
[tag, error_tag(input)]
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def error_tag(input)
|
14
20
|
attr = input.opts[:error_attr]
|
15
21
|
attr = attr ? attr.dup : {}
|
16
22
|
Forme.attr_classes(attr, 'error_message')
|
17
|
-
|
23
|
+
|
24
|
+
if id = input.opts[:error_id]
|
25
|
+
unless attr['id'] || attr[:id]
|
26
|
+
attr['id'] = id
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
input.tag(:span, attr, input.opts[:error])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class ErrorHandler::Set < ErrorHandler
|
35
|
+
Forme.register_transformer(:error_handler, :set, new)
|
36
|
+
|
37
|
+
def call(tag, input)
|
38
|
+
return super unless last_input = input.opts[:last_input]
|
39
|
+
|
40
|
+
last_input.opts[:error] = input.opts[:error]
|
41
|
+
last_input.opts[:error_attr] = input.opts[:error_attr] if input.opts[:error_attr]
|
42
|
+
last_input.opts[:error_handler] = :default
|
43
|
+
|
44
|
+
tag
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class ErrorHandler::AfterLegend < ErrorHandler
|
49
|
+
Forme.register_transformer(:error_handler, :after_legend, new)
|
50
|
+
|
51
|
+
def call(tag, input)
|
52
|
+
return super unless tag.is_a?(Array)
|
53
|
+
return super unless tag.first.is_a?(Tag)
|
54
|
+
return super unless tag.first.type == :legend
|
55
|
+
|
56
|
+
first_input = input.opts[:first_input]
|
57
|
+
attr = first_input.opts[:attr] ||= {}
|
58
|
+
Forme.attr_classes(attr, 'error')
|
59
|
+
attr['aria-invalid'] = 'true'
|
60
|
+
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
61
|
+
|
62
|
+
tag.insert(1, error_tag(input))
|
18
63
|
end
|
19
64
|
end
|
20
65
|
end
|
@@ -61,7 +61,6 @@ module Forme
|
|
61
61
|
@attr = attr ? attr.dup : {}
|
62
62
|
@opts = input.opts
|
63
63
|
normalize_options
|
64
|
-
|
65
64
|
tag = if html = input.opts[:html]
|
66
65
|
html = html.call(input) if html.respond_to?(:call)
|
67
66
|
form.raw(html)
|
@@ -158,9 +157,13 @@ module Forme
|
|
158
157
|
ops = ops.merge(@opts[:select_options]) if @opts[:select_options]
|
159
158
|
first_input = true
|
160
159
|
format = DATE_SELECT_FORMAT
|
160
|
+
@opts[:select_labels] ||= {}
|
161
161
|
order.map do |x|
|
162
162
|
next x if x.is_a?(String)
|
163
|
-
|
163
|
+
options = ops[x].map do |value, text|
|
164
|
+
[text || sprintf(format, value), value]
|
165
|
+
end
|
166
|
+
opts = @opts.merge(:label=>@opts[:select_labels][x], :wrapper=>nil, :error=>nil, :name=>"#{name}[#{x}]", :value=>values[x], :options=>options)
|
164
167
|
opts[:id] = if first_input
|
165
168
|
first_input = false
|
166
169
|
id
|
@@ -221,23 +224,22 @@ module Forme
|
|
221
224
|
key = @opts[:key]
|
222
225
|
name = @opts[:name]
|
223
226
|
id = @opts[:id]
|
224
|
-
|
225
|
-
|
226
|
-
end
|
227
|
-
if @opts[:label]
|
228
|
-
@opts[:set_label] = @opts.delete(:label)
|
229
|
-
end
|
227
|
+
@opts[:labeler] ||= :span
|
228
|
+
@opts[:error_handler] ||= :set
|
230
229
|
|
231
230
|
tag_wrapper = Forme.transformer(:tag_wrapper, @opts.delete(:tag_wrapper), @input.form_opts) || :default
|
232
231
|
tag_labeler = Forme.transformer(:labeler, @opts.delete(:tag_labeler), @input.form_opts) || :default
|
233
232
|
wrapper = @opts.fetch(:wrapper){@opts[:wrapper] = @input.form_opts[:set_wrapper] || @input.form_opts[:wrapper]}
|
234
233
|
wrapper = Forme.transformer(:wrapper, wrapper)
|
234
|
+
tag_label_attr = @opts[:tag_label_attr] || @opts[:label_attr]
|
235
235
|
|
236
|
-
|
236
|
+
first_input = nil
|
237
|
+
last_input = nil
|
238
|
+
ret = process_select_optgroups(:_format_set_optgroup) do |label, value, sel, attrs|
|
237
239
|
value = label if value.nil?
|
238
240
|
label_attr = {:class=>:option}
|
239
|
-
label_attr.merge!(
|
240
|
-
r_opts = attrs.merge(tag_attrs).merge(:label=>label||value, :label_attr=>label_attr, :wrapper=>tag_wrapper, :labeler=>tag_labeler)
|
241
|
+
label_attr.merge!(tag_label_attr) if tag_label_attr
|
242
|
+
r_opts = attrs.merge(tag_attrs).merge(:label=>label||value, :label_attr=>label_attr, :wrapper=>tag_wrapper, :labeler=>tag_labeler, :error=>nil, :error_attr=>nil)
|
241
243
|
if r_opts[:value].nil?
|
242
244
|
r_opts[:value] = value unless value.nil?
|
243
245
|
end
|
@@ -255,31 +257,15 @@ module Forme
|
|
255
257
|
r_opts[:key_id] ||= value
|
256
258
|
end
|
257
259
|
|
258
|
-
form._input(type, r_opts)
|
260
|
+
input = form._input(type, r_opts)
|
261
|
+
first_input ||= input
|
262
|
+
last_input = input
|
259
263
|
end
|
260
264
|
|
261
|
-
|
262
|
-
|
263
|
-
end
|
264
|
-
|
265
|
-
tags.unshift(set_label) if @opts[:set_label]
|
266
|
-
|
267
|
-
tags
|
268
|
-
end
|
269
|
-
|
270
|
-
def set_label
|
271
|
-
form._tag(:span, {:class=>:label}, @opts[:set_label])
|
272
|
-
end
|
265
|
+
@opts[:first_input] = first_input
|
266
|
+
@opts[:last_input] = last_input
|
273
267
|
|
274
|
-
|
275
|
-
if (last_input = tags.last) && last_input.is_a?(Input)
|
276
|
-
last_input.opts[:error] = @opts[:set_error]
|
277
|
-
last_input.opts[:error_attr] = @opts[:error_attr] if @opts[:error_attr]
|
278
|
-
else
|
279
|
-
attr = @opts[:error_attr] || {}
|
280
|
-
Forme.attr_classes(attr, 'error_message')
|
281
|
-
tags << form._tag(:span, attr, [@opts[:set_error]])
|
282
|
-
end
|
268
|
+
ret
|
283
269
|
end
|
284
270
|
|
285
271
|
# Formats a textarea. Respects the following options:
|
@@ -321,7 +307,19 @@ module Forme
|
|
321
307
|
handle_errors_option
|
322
308
|
|
323
309
|
Forme.attr_classes(@attr, @opts[:class]) if @opts.has_key?(:class)
|
324
|
-
|
310
|
+
|
311
|
+
if @opts[:error]
|
312
|
+
Forme.attr_classes(@attr, 'error')
|
313
|
+
@attr["aria-invalid"] = "true"
|
314
|
+
if @opts.fetch(:error_handler, true)
|
315
|
+
unless @opts[:error_id]
|
316
|
+
if id = @attr[:id] || @attr['id']
|
317
|
+
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
318
|
+
@opts[:error_id] = error_id
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
325
323
|
|
326
324
|
if data = opts[:data]
|
327
325
|
data.each do |k, v|
|
@@ -540,8 +538,11 @@ module Forme
|
|
540
538
|
end
|
541
539
|
|
542
540
|
# Use a span with text instead of an input field.
|
541
|
+
# For hidden inputs, do not show anything
|
543
542
|
def _format_input(type)
|
544
|
-
|
543
|
+
unless type.to_s == 'hidden'
|
544
|
+
tag(:span, {'class'=>'readonly-text'}, @attr[:value])
|
545
|
+
end
|
545
546
|
end
|
546
547
|
|
547
548
|
# Disabled radio button inputs.
|
@@ -10,16 +10,16 @@ module Forme
|
|
10
10
|
# Wrap the inputs in a <fieldset>. If the :legend
|
11
11
|
# option is given, add a <legend> tag as the first
|
12
12
|
# child of the fieldset.
|
13
|
-
def call(form, opts)
|
13
|
+
def call(form, opts, &block)
|
14
14
|
attr = opts[:attr] ? opts[:attr].dup : {}
|
15
15
|
Forme.attr_classes(attr, 'inputs')
|
16
16
|
if legend = opts[:legend]
|
17
17
|
form.tag(:fieldset, attr) do
|
18
|
-
form.
|
18
|
+
form.tag(:legend, opts[:legend_attr], legend)
|
19
19
|
yield
|
20
20
|
end
|
21
21
|
else
|
22
|
-
form.tag(:fieldset, attr, &
|
22
|
+
form.tag(:fieldset, attr, &block)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -32,7 +32,7 @@ module Forme
|
|
32
32
|
|
33
33
|
# Wrap the inputs in a <fieldset> and a <ol> tag.
|
34
34
|
def call(form, opts)
|
35
|
-
super(form, opts){form.
|
35
|
+
super(form, opts){form.tag(:ol){yield}}
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -83,12 +83,12 @@ module Forme
|
|
83
83
|
attr = opts[:attr] ? opts[:attr].dup : {}
|
84
84
|
form.tag(:table, attr) do
|
85
85
|
if legend = opts[:legend]
|
86
|
-
form.
|
86
|
+
form.tag(:caption, opts[:legend_attr], legend)
|
87
87
|
end
|
88
88
|
|
89
89
|
if (labels = opts[:labels]) && !labels.empty?
|
90
90
|
form.tag(:thead) do
|
91
|
-
form.
|
91
|
+
form.tag(:tr, {}, labels.map{|l| form._tag(:th, {}, l)})
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -77,4 +77,23 @@ module Forme
|
|
77
77
|
t
|
78
78
|
end
|
79
79
|
end
|
80
|
+
|
81
|
+
class Labeler::Span
|
82
|
+
Forme.register_transformer(:labeler, :span, new)
|
83
|
+
|
84
|
+
def call(tag, input)
|
85
|
+
label_attr = input.opts[:label_attr]
|
86
|
+
label_attr = label_attr ? label_attr.dup : {}
|
87
|
+
Forme.attr_classes(label_attr, "label")
|
88
|
+
[input.tag(:span, label_attr, input.opts[:label]), tag]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Labeler::Legend
|
93
|
+
Forme.register_transformer(:labeler, :legend, new)
|
94
|
+
|
95
|
+
def call(tag, input)
|
96
|
+
[input.tag(:legend, input.opts[:label_attr], input.opts[:label]), tag]
|
97
|
+
end
|
98
|
+
end
|
80
99
|
end
|
data/lib/forme/version.rb
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
module Forme
|
4
4
|
# The major version of Forme, updated only for major changes that are
|
5
5
|
# likely to require modification to apps using Forme.
|
6
|
-
MAJOR =
|
6
|
+
MAJOR = 2
|
7
7
|
|
8
8
|
# The minor version of Forme, updated for new feature releases of Forme.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 0
|
10
10
|
|
11
11
|
# The patch version of Forme, updated only for bug fixes from the last
|
12
12
|
# feature release.
|
data/lib/forme.rb
CHANGED
@@ -10,6 +10,7 @@ module Forme
|
|
10
10
|
|
11
11
|
begin
|
12
12
|
require 'cgi/escape'
|
13
|
+
# :nocov:
|
13
14
|
unless CGI.respond_to?(:escapeHTML) # work around for JRuby 9.1
|
14
15
|
CGI = Object.new
|
15
16
|
CGI.extend(defined?(::CGI::Escape) ? ::CGI::Escape : ::CGI::Util)
|
@@ -32,6 +33,7 @@ module Forme
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
36
|
+
# :nocov:
|
35
37
|
|
36
38
|
@default_add_blank_prompt = nil
|
37
39
|
@default_config = :default
|
@@ -160,5 +162,16 @@ module Forme
|
|
160
162
|
end
|
161
163
|
end
|
162
164
|
|
163
|
-
|
164
|
-
|
165
|
+
require_relative 'forme/form'
|
166
|
+
require_relative 'forme/input'
|
167
|
+
require_relative 'forme/tag'
|
168
|
+
require_relative 'forme/raw'
|
169
|
+
require_relative 'forme/version'
|
170
|
+
|
171
|
+
require_relative 'forme/transformers/error_handler'
|
172
|
+
require_relative 'forme/transformers/formatter'
|
173
|
+
require_relative 'forme/transformers/helper'
|
174
|
+
require_relative 'forme/transformers/inputs_wrapper'
|
175
|
+
require_relative 'forme/transformers/labeler'
|
176
|
+
require_relative 'forme/transformers/serializer'
|
177
|
+
require_relative 'forme/transformers/wrapper'
|
data/lib/roda/plugins/forme.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative '../../forme/template'
|
4
|
+
|
5
|
+
class Roda
|
6
|
+
module RodaPlugins
|
7
|
+
module FormeErubiCapture
|
8
|
+
def self.load_dependencies(app)
|
9
|
+
app.plugin :forme_route_csrf
|
10
|
+
app.plugin :capture_erb
|
11
|
+
app.plugin :inject_erb
|
12
|
+
end
|
13
|
+
|
14
|
+
class Form < ::Forme::Template::Form
|
15
|
+
%w'inputs tag subform'.each do |meth|
|
16
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
17
|
+
def #{meth}(*)
|
18
|
+
if block_given?
|
19
|
+
@scope.capture_erb do
|
20
|
+
super
|
21
|
+
@scope.instance_variable_get(@scope.render_opts[:template_opts][:outvar])
|
22
|
+
end
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
END
|
28
|
+
end
|
29
|
+
|
30
|
+
def emit(tag)
|
31
|
+
@scope.inject_erb(tag)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module InstanceMethods
|
36
|
+
def form(*)
|
37
|
+
if block_given?
|
38
|
+
capture_erb do
|
39
|
+
super
|
40
|
+
instance_variable_get(render_opts[:template_opts][:outvar])
|
41
|
+
end
|
42
|
+
else
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def _forme_form_class
|
50
|
+
Form
|
51
|
+
end
|
52
|
+
|
53
|
+
def _forme_form_options(obj, attr, opts)
|
54
|
+
super
|
55
|
+
opts[:hidden_tags_uplevel] = 2
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
register_plugin(:forme_erubi_capture, FormeErubiCapture)
|
61
|
+
end
|
62
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative '../../forme/template'
|
4
4
|
|
5
5
|
class Roda
|
6
6
|
module RodaPlugins
|
@@ -13,21 +13,18 @@ class Roda
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module InstanceMethods
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
attribs = attr
|
24
|
-
options = opts = opts.dup
|
25
|
-
end
|
16
|
+
include ::Forme::Template::Helper
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Add the csrf and hidden tags options if needed.
|
21
|
+
def _forme_form_options(obj, attr, opts)
|
22
|
+
super
|
26
23
|
|
27
|
-
apply_csrf =
|
24
|
+
apply_csrf = opts[:csrf]
|
28
25
|
|
29
26
|
if apply_csrf || apply_csrf.nil?
|
30
|
-
unless method =
|
27
|
+
unless method = attr[:method] || attr['method']
|
31
28
|
if obj && !obj.is_a?(Hash) && obj.respond_to?(:forme_default_request_method)
|
32
29
|
method = obj.forme_default_request_method
|
33
30
|
end
|
@@ -39,18 +36,17 @@ class Roda
|
|
39
36
|
end
|
40
37
|
|
41
38
|
if apply_csrf
|
42
|
-
token = if
|
43
|
-
csrf_token(csrf_path(
|
39
|
+
token = if opts.fetch(:use_request_specific_token){use_request_specific_csrf_tokens?}
|
40
|
+
csrf_token(csrf_path(attr[:action]), method)
|
44
41
|
else
|
45
42
|
csrf_token
|
46
43
|
end
|
47
44
|
|
48
|
-
|
49
|
-
|
45
|
+
opts[:csrf] = [csrf_field, token]
|
46
|
+
opts[:_before] = lambda do |form|
|
47
|
+
form.tag(:input, :type=>:hidden, :name=>csrf_field, :value=>token)
|
48
|
+
end
|
50
49
|
end
|
51
|
-
|
52
|
-
options[:output] = @_out_buf if block
|
53
|
-
::Forme::ERB::Form.form(obj, attr, opts, &block)
|
54
50
|
end
|
55
51
|
end
|
56
52
|
end
|