forme 1.9.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|