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/bs3.rb
CHANGED
@@ -80,12 +80,26 @@ module Forme
|
|
80
80
|
copy_options_to_attributes(ATTRIBUTE_OPTIONS)
|
81
81
|
copy_boolean_options_to_attributes(ATTRIBUTE_BOOLEAN_OPTIONS)
|
82
82
|
handle_key_option
|
83
|
+
handle_errors_option
|
83
84
|
|
84
85
|
Forme.attr_classes(@attr, @opts[:class]) if @opts.has_key?(:class)
|
85
|
-
|
86
|
+
|
87
|
+
if @opts[:error]
|
88
|
+
# Forme.attr_classes(@attr, 'error')
|
89
|
+
@attr["aria-invalid"] = "true"
|
90
|
+
if @opts.fetch(:error_handler, true)
|
91
|
+
unless @opts[:error_id]
|
92
|
+
if id = @attr[:id] || @attr['id']
|
93
|
+
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
94
|
+
@opts[:error_id] = error_id
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
86
99
|
|
87
100
|
if data = opts[:data]
|
88
101
|
data.each do |k, v|
|
102
|
+
k = k.to_s.tr("_", "-") if k.is_a?(Symbol) && input.opts[:dasherize_data]
|
89
103
|
sym = :"data-#{k}"
|
90
104
|
@attr[sym] = v unless @attr.has_key?(sym)
|
91
105
|
end
|
@@ -210,11 +224,11 @@ module Forme
|
|
210
224
|
Forme.attr_classes(attr, 'inputs')
|
211
225
|
if legend = opts[:legend]
|
212
226
|
form.tag(:fieldset, attr) do
|
213
|
-
form.
|
227
|
+
form.tag(:legend, opts[:legend_attr], legend)
|
214
228
|
yield
|
215
229
|
end
|
216
230
|
else
|
217
|
-
form.tag(:fieldset, attr, &
|
231
|
+
form.tag(:fieldset, attr, &block)
|
218
232
|
end
|
219
233
|
end
|
220
234
|
end
|
@@ -230,11 +244,11 @@ module Forme
|
|
230
244
|
attr = opts[:attr] ? opts[:attr].dup : { :class=>'table table-bordered'}
|
231
245
|
form.tag(:table, attr) do
|
232
246
|
if legend = opts[:legend]
|
233
|
-
form.
|
247
|
+
form.tag(:caption, opts[:legend_attr], legend)
|
234
248
|
end
|
235
249
|
|
236
250
|
if (labels = opts[:labels]) && !labels.empty?
|
237
|
-
form.
|
251
|
+
form.tag(:tr, {}, labels.map{|l| form._tag(:th, {}, l)})
|
238
252
|
end
|
239
253
|
|
240
254
|
yield
|
data/lib/forme/erb.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'template'
|
4
4
|
|
5
5
|
module Forme
|
6
6
|
module ERB
|
@@ -14,23 +14,25 @@ module Forme
|
|
14
14
|
HIDDEN_TAGS << block
|
15
15
|
end
|
16
16
|
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
# This is the module used to add the Forme integration to ERB templates, with optional support for
|
18
|
+
# rack_csrf for CSRF handling.
|
19
|
+
module Helper
|
20
|
+
include Template::Helper
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def _forme_form_options(obj, attr, opts)
|
25
|
+
super
|
26
|
+
|
27
|
+
if defined?(::Rack::Csrf) && env['rack.session']
|
28
|
+
opts[:_before_post] = lambda do |form|
|
29
|
+
form.tag(:input, :type=>:hidden, :name=>::Rack::Csrf.field, :value=>::Rack::Csrf.token(env))
|
30
|
+
end
|
31
|
+
end
|
21
32
|
end
|
22
|
-
end
|
23
33
|
|
24
|
-
|
25
|
-
|
26
|
-
module Helper
|
27
|
-
# Create a +Form+ object tied to the current output buffer,
|
28
|
-
# using the standard ERB hidden tags.
|
29
|
-
def form(obj=nil, attr={}, opts={}, &block)
|
30
|
-
h = {:hidden_tags=>Forme::ERB::HIDDEN_TAGS, :env=>env}
|
31
|
-
h[:output] = @_out_buf if block
|
32
|
-
(obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
|
33
|
-
Form.form(obj, attr, opts, &block)
|
34
|
+
def _forme_form_hidden_tags
|
35
|
+
HIDDEN_TAGS
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
data/lib/forme/form.rb
CHANGED
@@ -2,9 +2,8 @@
|
|
2
2
|
|
3
3
|
module Forme
|
4
4
|
# The +Form+ class is the main entry point to the library.
|
5
|
-
# Using the +form+, +input+, +tag+, and +inputs+ methods, one can
|
6
|
-
#
|
7
|
-
# to a string using +to_s+.
|
5
|
+
# Using the +form+, +input+, +tag+, and +inputs+ methods, one can return HTML
|
6
|
+
# form tag string (or fragments of an HTML form tag).
|
8
7
|
class Form
|
9
8
|
# A hash of options for the form.
|
10
9
|
attr_reader :opts
|
@@ -16,10 +15,17 @@ module Forme
|
|
16
15
|
# The hidden tags to automatically add to the form.
|
17
16
|
attr_reader :hidden_tags
|
18
17
|
|
18
|
+
# The attributes used for the form tag for this form.
|
19
|
+
attr_reader :form_tag_attributes
|
20
|
+
|
19
21
|
# The +serializer+ determines how +Tag+ objects are transformed into strings.
|
20
22
|
# Must respond to +call+ or be a registered symbol.
|
21
23
|
attr_reader :serializer
|
22
24
|
|
25
|
+
# The contents of the form as a string. This should not be mutated by
|
26
|
+
# external code.
|
27
|
+
attr_reader :to_s
|
28
|
+
|
23
29
|
# Use appropriate Form subclass for object based on the current class, if the
|
24
30
|
# object responds to +forme_form_class+.
|
25
31
|
def self.new(obj=nil, opts={})
|
@@ -30,23 +36,9 @@ module Forme
|
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
33
|
-
#
|
34
|
-
#
|
35
|
-
|
36
|
-
#
|
37
|
-
# Argument Handling:
|
38
|
-
# No args :: Creates a +Form+ object with no options and not associated
|
39
|
-
# to an +obj+, and with no attributes in the opening tag.
|
40
|
-
# 1 hash arg :: Treated as opening form tag attributes, creating a
|
41
|
-
# +Form+ object with no options.
|
42
|
-
# 1 non-hash arg :: Treated as the +Form+'s +obj+, with empty options
|
43
|
-
# and no attributes in the opening tag.
|
44
|
-
# 2 hash args :: First hash is opening attributes, second hash is +Form+
|
45
|
-
# options.
|
46
|
-
# 1 non-hash arg, 1-2 hash args :: First argument is +Form+'s obj, second is
|
47
|
-
# opening attributes, third if provided is
|
48
|
-
# +Form+'s options.
|
49
|
-
def self.form(obj=nil, attr={}, opts={}, &block)
|
39
|
+
# Parse the args given to #form and return Form instance, form tag attributes,
|
40
|
+
# and block for form.
|
41
|
+
def self.form_args(obj, attr, opts, &block)
|
50
42
|
f = if obj.is_a?(Hash)
|
51
43
|
raise Error, "Can't provide 3 hash arguments to form" unless opts.empty?
|
52
44
|
opts = attr
|
@@ -59,13 +51,33 @@ module Forme
|
|
59
51
|
ins = opts[:inputs]
|
60
52
|
button = opts[:button]
|
61
53
|
if ins || button
|
62
|
-
block =
|
63
|
-
form.
|
54
|
+
block = proc do |form|
|
55
|
+
form.inputs(ins, opts) if ins
|
64
56
|
yield form if block_given?
|
65
|
-
form.
|
57
|
+
form.button(button) if button
|
66
58
|
end
|
67
59
|
end
|
68
60
|
|
61
|
+
[f, attr, block]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Create a +Form+ instance and yield it to the block. Returns an HTML string
|
65
|
+
# for the form tag.
|
66
|
+
#
|
67
|
+
# Argument Handling:
|
68
|
+
# No args :: Creates a +Form+ object with no options and not associated
|
69
|
+
# to an +obj+, and with no attributes in the opening tag.
|
70
|
+
# 1 hash arg :: Treated as opening form tag attributes, creating a
|
71
|
+
# +Form+ object with no options.
|
72
|
+
# 1 non-hash arg :: Treated as the +Form+'s +obj+, with empty options
|
73
|
+
# and no attributes in the opening tag.
|
74
|
+
# 2 hash args :: First hash is opening attributes, second hash is +Form+
|
75
|
+
# options.
|
76
|
+
# 1 non-hash arg, 1-2 hash args :: First argument is +Form+'s obj, second is
|
77
|
+
# opening attributes, third if provided is
|
78
|
+
# +Form+'s options.
|
79
|
+
def self.form(obj=nil, attr={}, opts={}, &block)
|
80
|
+
f, attr, block = form_args(obj, attr, opts, &block)
|
69
81
|
f.form(attr, &block)
|
70
82
|
end
|
71
83
|
|
@@ -98,26 +110,38 @@ module Forme
|
|
98
110
|
@serializer = @opts[:serializer]
|
99
111
|
@input_defaults = @opts[:input_defaults] || {}
|
100
112
|
@hidden_tags = @opts[:hidden_tags]
|
101
|
-
@
|
113
|
+
if @hidden_tags && !@hidden_tags.empty? && RUBY_VERSION >= '2'
|
114
|
+
uplevel = 6
|
115
|
+
uplevel += @opts[:hidden_tags_uplevel] if @opts[:hidden_tags_uplevel]
|
116
|
+
warn("The Forme::Form :hidden_tags option is deprecated, please switch to using the :before option", :uplevel=>uplevel)
|
117
|
+
end
|
118
|
+
@to_s = String.new
|
102
119
|
end
|
103
120
|
|
104
|
-
# Create a form tag with the given attributes.
|
105
|
-
|
121
|
+
# Create a form tag with the given attributes. Returns an HTML string for
|
122
|
+
# the generated form tag.
|
123
|
+
def form(attr={})
|
106
124
|
if obj && !attr[:method] && !attr['method'] && obj.respond_to?(:forme_default_request_method)
|
107
|
-
attr = attr
|
125
|
+
attr = Hash[attr]
|
126
|
+
attr['method'] = obj.forme_default_request_method
|
127
|
+
end
|
128
|
+
@form_tag_attributes = attr
|
129
|
+
|
130
|
+
tag(:form, attr, method(:hidden_form_tags)) do
|
131
|
+
before_form_yield
|
132
|
+
yield self if block_given?
|
133
|
+
after_form_yield
|
108
134
|
end
|
109
|
-
tag(:form, attr, method(:hidden_form_tags), &block)
|
110
135
|
end
|
111
136
|
|
112
|
-
#
|
113
|
-
#
|
114
|
-
|
115
|
-
|
137
|
+
# Whether the method for this form is POST. Only callable after calling
|
138
|
+
# #form.
|
139
|
+
def post?
|
140
|
+
(form_tag_attributes[:method] || form_tag_attributes['method']).to_s.upcase == 'POST'
|
116
141
|
end
|
117
142
|
|
118
143
|
# Creates an +Input+ with the given +field+ and +opts+ associated with
|
119
|
-
# the receiver
|
120
|
-
# open tag.
|
144
|
+
# the receiver. Returns the HTML generated by the given input.
|
121
145
|
#
|
122
146
|
# If the form is associated with an +obj+, or the :obj key exists in
|
123
147
|
# the +opts+ argument, treats the +field+ as a call to the +obj+. If
|
@@ -129,36 +153,39 @@ module Forme
|
|
129
153
|
# type (e.g. <tt>:text</tt>, <tt>:textarea</tt>, <tt>:select</tt>), and
|
130
154
|
# an input is created directly with the +field+ and +opts+.
|
131
155
|
def input(field, opts={})
|
132
|
-
|
133
|
-
|
134
|
-
obj = opts.delete(:obj)
|
135
|
-
else
|
136
|
-
obj = self.obj
|
137
|
-
end
|
138
|
-
input = if obj
|
139
|
-
if obj.respond_to?(:forme_input)
|
140
|
-
obj.forme_input(self, field, opts.dup)
|
141
|
-
else
|
156
|
+
content_added do
|
157
|
+
if opts.has_key?(:obj)
|
142
158
|
opts = opts.dup
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
159
|
+
obj = opts.delete(:obj)
|
160
|
+
else
|
161
|
+
obj = self.obj
|
162
|
+
end
|
163
|
+
|
164
|
+
input = if obj
|
165
|
+
if obj.respond_to?(:forme_input)
|
166
|
+
obj.forme_input(self, field, opts.dup)
|
167
|
+
else
|
168
|
+
opts = opts.dup
|
169
|
+
opts[:key] = field unless opts.has_key?(:key)
|
170
|
+
type = opts.delete(:type) || :text
|
171
|
+
unless opts.has_key?(:value) || type == :file
|
172
|
+
opts[:value] = if obj.is_a?(Hash)
|
173
|
+
obj[field]
|
174
|
+
else
|
175
|
+
obj.send(field)
|
176
|
+
end
|
150
177
|
end
|
178
|
+
_input(type, opts)
|
151
179
|
end
|
152
|
-
|
180
|
+
else
|
181
|
+
_input(field, opts)
|
153
182
|
end
|
154
|
-
|
155
|
-
|
183
|
+
|
184
|
+
self << input
|
156
185
|
end
|
157
|
-
self << input
|
158
|
-
input
|
159
186
|
end
|
160
187
|
|
161
|
-
#
|
188
|
+
# Return a new +Input+ associated with the receiver with the given
|
162
189
|
# arguments, doing no other processing.
|
163
190
|
def _input(*a)
|
164
191
|
Input.new(self, *a)
|
@@ -182,6 +209,8 @@ module Forme
|
|
182
209
|
# wrapper to use for this inputs call. You can use the :nested_inputs_wrapper
|
183
210
|
# option to set the default :inputs_wrapper option for the duration of the block.
|
184
211
|
#
|
212
|
+
# Returns the HTML generated by the inputs added to the form.
|
213
|
+
#
|
185
214
|
# This can also be called with a single hash argument to just use an options hash:
|
186
215
|
#
|
187
216
|
# f.inputs(:legend=>'Foo') do
|
@@ -193,32 +222,28 @@ module Forme
|
|
193
222
|
# f.inputs do
|
194
223
|
# # ...
|
195
224
|
# end
|
196
|
-
def inputs(inputs=[], opts={}
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
def _inputs(inputs=[], opts={}) # :nodoc:
|
203
|
-
if inputs.is_a?(Hash)
|
204
|
-
opts = inputs.merge(opts)
|
205
|
-
inputs = []
|
206
|
-
end
|
225
|
+
def inputs(inputs=[], opts={})
|
226
|
+
content_added do
|
227
|
+
if inputs.is_a?(Hash)
|
228
|
+
opts = inputs.merge(opts)
|
229
|
+
inputs = []
|
230
|
+
end
|
207
231
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
232
|
+
form_opts = {}
|
233
|
+
form_opts[:inputs_wrapper] = opts[:nested_inputs_wrapper] if opts[:nested_inputs_wrapper]
|
234
|
+
TRANSFORMER_TYPES.each do |t|
|
235
|
+
if opts.has_key?(t) && t != :inputs_wrapper
|
236
|
+
form_opts[t] = opts[t]
|
237
|
+
end
|
213
238
|
end
|
214
|
-
end
|
215
239
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
240
|
+
Forme.transform(:inputs_wrapper, opts, @opts, self, opts) do
|
241
|
+
with_opts(form_opts) do
|
242
|
+
inputs.each do |i|
|
243
|
+
input(*i)
|
244
|
+
end
|
245
|
+
yield if block_given?
|
220
246
|
end
|
221
|
-
yield if block_given?
|
222
247
|
end
|
223
248
|
end
|
224
249
|
end
|
@@ -255,35 +280,34 @@ module Forme
|
|
255
280
|
end
|
256
281
|
|
257
282
|
# Creates a +Tag+ associated to the receiver with the given arguments.
|
258
|
-
#
|
259
|
-
#
|
260
|
-
# the block.
|
283
|
+
# If a block is given, yield to the block inside the generated tag.
|
284
|
+
# Returns the HTML added to the form by the addition of this tag.
|
261
285
|
def tag(*a, &block)
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
286
|
+
content_added do
|
287
|
+
tag = _tag(*a)
|
288
|
+
if block
|
289
|
+
self << serialize_open(tag)
|
290
|
+
if children = tag.children
|
291
|
+
children.each{|child| self << child}
|
292
|
+
end
|
293
|
+
yield self
|
294
|
+
self << serialize_close(tag)
|
295
|
+
else
|
296
|
+
self << tag
|
297
|
+
end
|
298
|
+
end
|
271
299
|
end
|
272
300
|
|
273
|
-
# Creates a :submit +Input+ with the given opts
|
274
|
-
#
|
301
|
+
# Creates a :submit +Input+ with the given opts. Returns the generated
|
302
|
+
# HTML for the input.
|
275
303
|
def button(opts={})
|
276
304
|
opts = {:value=>opts} if opts.is_a?(String)
|
277
|
-
|
278
|
-
self << input
|
279
|
-
input
|
305
|
+
content_added{self << _input(:submit, opts)}
|
280
306
|
end
|
281
307
|
|
282
|
-
# Add the +Input+/+Tag+ instance
|
308
|
+
# Add the +Input+/+Tag+ instance to the HTML buffer.
|
283
309
|
def <<(tag)
|
284
|
-
|
285
|
-
n << tag
|
286
|
-
end
|
310
|
+
@to_s << tag.to_s
|
287
311
|
end
|
288
312
|
|
289
313
|
# Calls the block for each object in objs, using with_obj with the given namespace
|
@@ -296,18 +320,11 @@ module Forme
|
|
296
320
|
end
|
297
321
|
end
|
298
322
|
|
299
|
-
# Return a new string that will not be
|
323
|
+
# Return a new string that will not be HTML escaped by the default serializer.
|
300
324
|
def raw(s)
|
301
325
|
Forme.raw(s)
|
302
326
|
end
|
303
327
|
|
304
|
-
# Marks the string as containing already escaped output. Returns string given
|
305
|
-
# by default, but subclasses for specific web frameworks can handle automatic
|
306
|
-
# html escaping by overriding this.
|
307
|
-
def raw_output(s)
|
308
|
-
s
|
309
|
-
end
|
310
|
-
|
311
328
|
# Temporarily override the given object and namespace for the form. Any given
|
312
329
|
# namespaces are appended to the form's current namespace.
|
313
330
|
def with_obj(obj, namespace=nil)
|
@@ -367,24 +384,40 @@ module Forme
|
|
367
384
|
end
|
368
385
|
end
|
369
386
|
|
370
|
-
#
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
@
|
375
|
-
yield self
|
376
|
-
ensure
|
377
|
-
@nesting.pop
|
387
|
+
# Return the HTML content added by the block.
|
388
|
+
def content_added
|
389
|
+
offset = @to_s.length
|
390
|
+
yield
|
391
|
+
@to_s[offset, @to_s.length]
|
378
392
|
end
|
379
393
|
|
380
394
|
# Return a serialized opening tag for the given tag.
|
381
395
|
def serialize_open(tag)
|
382
|
-
|
396
|
+
serializer.serialize_open(tag) if serializer.respond_to?(:serialize_open)
|
383
397
|
end
|
384
398
|
|
385
399
|
# Return a serialized closing tag for the given tag.
|
386
400
|
def serialize_close(tag)
|
387
|
-
|
401
|
+
serializer.serialize_close(tag) if serializer.respond_to?(:serialize_close)
|
402
|
+
end
|
403
|
+
|
404
|
+
# Call before hooks if defined.
|
405
|
+
def before_form_yield
|
406
|
+
# _before_post and _before hooks are only for internal use
|
407
|
+
opts[:_before_post].call(self) if opts[:_before_post] && post?
|
408
|
+
opts[:_before].call(self) if opts[:_before]
|
409
|
+
|
410
|
+
# before hook is for external use
|
411
|
+
opts[:before].call(self) if opts[:before]
|
412
|
+
end
|
413
|
+
|
414
|
+
# Call after hooks if defined.
|
415
|
+
def after_form_yield
|
416
|
+
# after hook is for external use
|
417
|
+
opts[:after].call(self) if opts[:after]
|
418
|
+
|
419
|
+
# _after hook is only for internal use
|
420
|
+
opts[:_after].call(self) if opts[:_after]
|
388
421
|
end
|
389
422
|
end
|
390
423
|
end
|
data/lib/forme/input.rb
CHANGED
@@ -32,7 +32,7 @@ module Forme
|
|
32
32
|
|
33
33
|
# Return a string containing the serialized content of the receiver.
|
34
34
|
def to_s
|
35
|
-
|
35
|
+
Forme.transform(:serializer, @opts, @form_opts, self)
|
36
36
|
end
|
37
37
|
|
38
38
|
# Transform the receiver into a lower level +Tag+ form (or an array
|
data/lib/forme/rails.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'template'
|
4
4
|
|
5
5
|
class ActiveSupport::SafeBuffer
|
6
6
|
include Forme::Raw
|
@@ -18,94 +18,63 @@ module Forme
|
|
18
18
|
HIDDEN_TAGS << block
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
class TemplateForm < ::Forme::Template::Form
|
22
|
+
%w'inputs tag subform'.each do |meth|
|
23
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
24
|
+
def #{meth}(*)
|
25
|
+
if block_given?
|
26
|
+
@scope.send(:with_output_buffer){super}
|
27
|
+
else
|
28
|
+
@scope.raw(super)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
END
|
25
32
|
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Subclass used when using Forme/Rails ERB integration,
|
29
|
-
# handling integration with the view template.
|
30
|
-
class Form < ::Forme::Form
|
31
|
-
# The Rails template that created this form.
|
32
|
-
attr_reader :template
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
%w'button input'.each do |meth|
|
35
|
+
class_eval(<<-END, __FILE__, __LINE__+1)
|
36
|
+
def #{meth}(*)
|
37
|
+
@scope.raw(super)
|
38
|
+
end
|
39
|
+
END
|
38
40
|
end
|
39
41
|
|
40
|
-
# Serialize and mark as already escaped the string version of
|
41
|
-
# the input.
|
42
42
|
def emit(tag)
|
43
|
-
|
43
|
+
@scope.output_buffer << @scope.raw(tag)
|
44
44
|
end
|
45
|
+
end
|
46
|
+
|
47
|
+
ERB = Template::Helper.clone
|
48
|
+
module ERB
|
49
|
+
alias _forme form
|
50
|
+
remove_method :form
|
45
51
|
|
46
|
-
|
47
|
-
# the buffer if not given a block
|
48
|
-
def inputs(*)
|
52
|
+
def forme(*a, &block)
|
49
53
|
if block_given?
|
50
|
-
|
54
|
+
with_output_buffer{_forme(*a, &block)}
|
51
55
|
else
|
52
|
-
|
56
|
+
raw(_forme(*a, &block))
|
53
57
|
end
|
54
58
|
end
|
55
|
-
|
56
|
-
# If a block is not given, emit the inputs into the current output
|
57
|
-
# buffer.
|
58
|
-
def _inputs(inputs=[], opts={}) # :nodoc:
|
59
|
-
if block_given? && !opts[:subform]
|
60
|
-
super
|
61
|
-
else
|
62
|
-
emit(super)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Return a string version of the input that is already marked as safe.
|
67
|
-
def input(*)
|
68
|
-
super.to_s
|
69
|
-
end
|
70
59
|
|
71
|
-
|
72
|
-
def button(*)
|
73
|
-
super.to_s
|
74
|
-
end
|
60
|
+
private
|
75
61
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
# If a block is given, create a new output buffer and make sure all the
|
82
|
-
# output of the tag goes into that buffer, and return the buffer.
|
83
|
-
# Otherwise, just return a string version of the tag that is already
|
84
|
-
# marked as safe.
|
85
|
-
def tag(type, attr={}, children=[], &block)
|
86
|
-
if block_given?
|
87
|
-
template.send(:with_output_buffer){tag_(type, attr, children, &block)}
|
88
|
-
else
|
89
|
-
_tag(type, attr, children).to_s
|
62
|
+
def _forme_form_options(obj, attr, opts)
|
63
|
+
if protect_against_forgery?
|
64
|
+
opts[:_before_post] = lambda do |form|
|
65
|
+
form.tag(:input, :type=>:hidden, :name=>request_forgery_protection_token, :value=>form_authenticity_token)
|
66
|
+
end
|
90
67
|
end
|
68
|
+
opts[:hidden_tags_uplevel] = 2
|
91
69
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
Array(tag.children).each{|c| emit(c)}
|
97
|
-
yield self if block_given?
|
98
|
-
emit(serialize_close(tag))
|
70
|
+
|
71
|
+
# The class to use for forms
|
72
|
+
def _forme_form_class
|
73
|
+
TemplateForm
|
99
74
|
end
|
100
|
-
end
|
101
75
|
|
102
|
-
|
103
|
-
|
104
|
-
# Rails hidden tags.
|
105
|
-
def forme(obj=nil, attr={}, opts={}, &block)
|
106
|
-
h = {:template=>self, :hidden_tags=>Forme::Rails::HIDDEN_TAGS}
|
107
|
-
(obj.is_a?(Hash) ? attr = attr.merge(h) : opts = opts.merge(h))
|
108
|
-
Form.form(obj, attr, opts, &block)
|
76
|
+
def _forme_form_hidden_tags
|
77
|
+
Forme::Rails::HIDDEN_TAGS
|
109
78
|
end
|
110
79
|
end
|
111
80
|
end
|
data/lib/forme/raw.rb
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Forme
|
4
4
|
# Empty module for marking objects as "raw", where they will no longer
|
5
|
-
#
|
5
|
+
# HTML escaped by the default serializer.
|
6
6
|
module Raw
|
7
7
|
end
|
8
8
|
|
9
9
|
# A String subclass that includes Raw, which will cause the default
|
10
|
-
# serializer to no longer
|
10
|
+
# serializer to no longer HTML escape the string.
|
11
11
|
class RawString < ::String
|
12
12
|
include Raw
|
13
13
|
end
|