forme 2.1.0 → 2.3.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 +16 -0
- data/README.rdoc +10 -5
- data/lib/forme/bs3.rb +7 -7
- data/lib/forme/bs5.rb +213 -0
- data/lib/forme/form.rb +2 -0
- data/lib/forme/transformers/error_handler.rb +10 -10
- data/lib/forme/transformers/formatter.rb +32 -34
- data/lib/forme/version.rb +1 -1
- data/lib/forme.rb +2 -1
- data/lib/roda/plugins/forme_set.rb +5 -3
- data/lib/sequel/plugins/forme.rb +8 -6
- data/lib/sequel/plugins/forme_set.rb +4 -4
- metadata +7 -24
- data/Rakefile +0 -82
- data/spec/all.rb +0 -2
- data/spec/bs3_reference_spec.rb +0 -358
- data/spec/bs3_sequel_plugin_spec.rb +0 -523
- data/spec/bs3_spec.rb +0 -722
- data/spec/erb_helper.rb +0 -198
- data/spec/erubi_capture_helper.rb +0 -198
- data/spec/forme_coverage.rb +0 -13
- data/spec/forme_spec.rb +0 -1216
- data/spec/rails_integration_spec.rb +0 -274
- data/spec/roda_integration_spec.rb +0 -523
- data/spec/sequel_helper.rb +0 -101
- data/spec/sequel_i18n_helper.rb +0 -40
- data/spec/sequel_i18n_plugin_spec.rb +0 -31
- data/spec/sequel_plugin_spec.rb +0 -600
- data/spec/sequel_set_plugin_spec.rb +0 -232
- data/spec/shared_erb_specs.rb +0 -71
- data/spec/sinatra_integration_spec.rb +0 -45
- data/spec/spec_helper.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13efa41ba160d80619b779cda0ad94581b37695e9fb8caedc696d26c91c92d87
|
4
|
+
data.tar.gz: 6558cf408b4573b3822c566c8e48b856de47009c6293831e0cdcc3fed7f4ebc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42d8dd057d905a8cb44610c9b3c20c9d055d0f0495b8ec94b020a637d0b10f5c1919ebc697e0b4f8970a29fcb511661cc56d622dc1d91eb8f347ab62fe36d7c4
|
7
|
+
data.tar.gz: 10beb8c2109850be4c1fb5d0c46d13218269c8b65f604cda930024eab8ff3838f32ab70256696d93f5c17f3e011d5dad0450511051a6abda40e75e37c1bbf2eb
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
=== 2.3.0 (2022-11-15)
|
2
|
+
|
3
|
+
* Add forme/bs5 for Bootstrap 5 support (janko) (#106)
|
4
|
+
|
5
|
+
* Raise exception if attempting to load Roda forme_set plugin without setting :secret option (janko) (#104)
|
6
|
+
|
7
|
+
=== 2.2.0 (2022-06-28)
|
8
|
+
|
9
|
+
* Use inputmode and pattern attributes instead of type=number for integer fields in the Sequel forme plugin (jeremyevans)
|
10
|
+
|
11
|
+
* Respect explicit nil/false :value option for boolean inputs in the Sequel forme plugin (jeremyevans)
|
12
|
+
|
13
|
+
* In bs3 support, make sure error spans have id referenced by aria-describedby (jeremyevans)
|
14
|
+
|
15
|
+
* Set aria-describedby attribute automatically even if :error_id is given manually (jeremyevans)
|
16
|
+
|
1
17
|
=== 2.1.0 (2022-05-25)
|
2
18
|
|
3
19
|
* Avoid hidden inputs inside tbody tags in subform in the Sequel::Model support, since that results in invalid HTML (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -49,7 +49,7 @@ This results in the following HTML:
|
|
49
49
|
<input id="album_name" name="album[name]" type="text" value="Rising Force"/>
|
50
50
|
</label>
|
51
51
|
<label>Copies Sold:
|
52
|
-
<input id="album_copies_sold" name="album[copies_sold]" type="
|
52
|
+
<input id="album_copies_sold" inputmode="numeric" name="album[copies_sold]" pattern="-?[0-9]*" type="text" value="100000"/>
|
53
53
|
</label>
|
54
54
|
</form>
|
55
55
|
|
@@ -443,12 +443,12 @@ form similar to:
|
|
443
443
|
|
444
444
|
<input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/>
|
445
445
|
<fieldset class="inputs"><legend>Track #1</legend>
|
446
|
-
<label>Number: <input id="album_tracks_attributes_0_number" name="album[tracks_attributes][0][number]" type="
|
446
|
+
<label>Number: <input id="album_tracks_attributes_0_number" inputmode="numeric" name="album[tracks_attributes][0][number]" pattern="-?[0-9]*" type="text" value="1"/></label>
|
447
447
|
<label>Name: <input id="album_tracks_attributes_0_name" name="album[tracks_attributes][0][name]" type="text" value="Blue Hawaii"/></label>
|
448
448
|
</fieldset>
|
449
449
|
<input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/>
|
450
450
|
<fieldset class="inputs"><legend>Track #2</legend>
|
451
|
-
<label>Number: <input id="album_tracks_attributes_1_number" name="album[tracks_attributes][1][number]" type="
|
451
|
+
<label>Number: <input id="album_tracks_attributes_1_number" inputmode="numeric" name="album[tracks_attributes][1][number]" pattern="-?[0-9]*" type="text" value="2"/></label>
|
452
452
|
<label>Name: <input id="album_tracks_attributes_1_name" name="album[tracks_attributes][1][name]" type="text" value="Almost Always True"/></label>
|
453
453
|
</fieldset>
|
454
454
|
|
@@ -1264,12 +1264,17 @@ You can mark a configuration as the default using:
|
|
1264
1264
|
|
1265
1265
|
Forme.default_config = :mine
|
1266
1266
|
|
1267
|
-
=== Bootstrap
|
1267
|
+
=== Bootstrap Support
|
1268
1268
|
|
1269
|
-
Forme ships with support for Bootstrap
|
1269
|
+
Forme ships with support for Bootstrap 5 HTML formatting. This support is shipped in
|
1270
1270
|
it's own file, so if you don't use it, you don't pay the memory penalty for loading
|
1271
1271
|
it.
|
1272
1272
|
|
1273
|
+
require 'forme/bs5'
|
1274
|
+
Forme.default_config = :bs5
|
1275
|
+
|
1276
|
+
There is also support for Bootstrap versions 3-4:
|
1277
|
+
|
1273
1278
|
require 'forme/bs3'
|
1274
1279
|
Forme.default_config = :bs3
|
1275
1280
|
|
data/lib/forme/bs3.rb
CHANGED
@@ -24,6 +24,7 @@ module Forme
|
|
24
24
|
attr = attr ? attr.dup : {}
|
25
25
|
Forme.attr_classes(attr, 'help-block with-errors')
|
26
26
|
return [tag] if input.opts[:skip_error_message]
|
27
|
+
attr[:id] ||= input.opts[:error_id]
|
27
28
|
|
28
29
|
case input.type
|
29
30
|
when :submit, :reset
|
@@ -84,11 +85,13 @@ module Forme
|
|
84
85
|
|
85
86
|
Forme.attr_classes(@attr, @opts[:class]) if @opts.has_key?(:class)
|
86
87
|
|
87
|
-
if @opts[:error]
|
88
|
+
if @opts[:error] && input.type != :submit && input.type != :reset
|
88
89
|
# Forme.attr_classes(@attr, 'error')
|
89
90
|
@attr["aria-invalid"] = "true"
|
90
91
|
if @opts.fetch(:error_handler, true)
|
91
|
-
|
92
|
+
if @opts[:error_id]
|
93
|
+
@attr['aria-describedby'] ||= @opts[:error_id]
|
94
|
+
else
|
92
95
|
if id = @attr[:id] || @attr['id']
|
93
96
|
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
94
97
|
@opts[:error_id] = error_id
|
@@ -127,7 +130,7 @@ module Forme
|
|
127
130
|
end
|
128
131
|
|
129
132
|
def _format_set(type, tag_attrs={})
|
130
|
-
raise Error, "can't have radioset with no options" unless @opts[:optgroups] || @opts[:options]
|
133
|
+
raise Error, "can't have radioset or checkboxset with no options" unless @opts[:optgroups] || @opts[:options]
|
131
134
|
key = @opts[:key]
|
132
135
|
name = @opts[:name]
|
133
136
|
id = @opts[:id]
|
@@ -282,7 +285,7 @@ module Forme
|
|
282
285
|
label_attr = input.opts[:label_attr]
|
283
286
|
label_attr = label_attr ? label_attr.dup : {}
|
284
287
|
|
285
|
-
label_attr[:for] = label_attr[:for]
|
288
|
+
label_attr[:for] = label_attr[:for] == false ? nil : input.opts.fetch(:label_for, id)
|
286
289
|
label = input.opts[:label]
|
287
290
|
lpos = input.opts[:label_position] || ([:radio, :checkbox].include?(input.type) ? :after : :before)
|
288
291
|
|
@@ -317,9 +320,6 @@ module Forme
|
|
317
320
|
|
318
321
|
case input.type
|
319
322
|
when :submit, :reset
|
320
|
-
klass.delete('form-group')
|
321
|
-
attr[:class] = klass.sort.uniq.join(' ').strip
|
322
|
-
attr.delete(:class) if attr[:class].empty?
|
323
323
|
[tag]
|
324
324
|
when :radio, :checkbox
|
325
325
|
klass.delete('form-group')
|
data/lib/forme/bs5.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Forme
|
4
|
+
register_config(:bs5, formatter: :bs5, wrapper: :bs5, error_handler: :bs5, serializer: :bs5, labeler: :bs5, helper: :bs5, tag_wrapper: :bs5, set_wrapper: :div)
|
5
|
+
|
6
|
+
# Update the <tt>:class</tt> entry in the +attr+ hash with the given +classes+,
|
7
|
+
# adding the classes before any existing classes.
|
8
|
+
def self.attr_classes_after(attr, *classes)
|
9
|
+
attr[:class] = merge_classes(*classes, attr[:class])
|
10
|
+
end
|
11
|
+
|
12
|
+
class ErrorHandler::Bootstrap5
|
13
|
+
Forme.register_transformer(:error_handler, :bs5, new)
|
14
|
+
|
15
|
+
def call(tags, input)
|
16
|
+
attr = input.opts[:error_attr]
|
17
|
+
attr = attr ? attr.dup : {}
|
18
|
+
|
19
|
+
unless attr[:class] && attr[:class].include?("invalid-tooltip")
|
20
|
+
Forme.attr_classes(attr, "invalid-feedback")
|
21
|
+
end
|
22
|
+
|
23
|
+
attr[:id] ||= input.opts[:error_id]
|
24
|
+
|
25
|
+
[tags, input.tag(:div, attr, input.opts[:error])]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Formatter::Bootstrap5 < Formatter
|
30
|
+
Forme.register_transformer(:formatter, :bs5, self)
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def normalize_options
|
35
|
+
super
|
36
|
+
|
37
|
+
if @opts[:error]
|
38
|
+
# remove "error" class
|
39
|
+
@attr[:class] = @attr[:class].to_s.sub(/\s*error$/,'')
|
40
|
+
@attr.delete(:class) if @attr[:class].to_s == ''
|
41
|
+
|
42
|
+
Forme.attr_classes(@attr, "is-invalid")
|
43
|
+
end
|
44
|
+
|
45
|
+
if @opts[:help]
|
46
|
+
if @opts[:helper_attr] && @opts[:helper_attr][:id]
|
47
|
+
@attr["aria-describedby"] ||= @opts[:helper_attr][:id]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Formatter that adds "readonly" for most input types,
|
54
|
+
# and disables select/radio/checkbox inputs.
|
55
|
+
#
|
56
|
+
# Registered as :bs5_readonly.
|
57
|
+
class Formatter::Bs5ReadOnly < Formatter
|
58
|
+
Forme.register_transformer(:formatter, :bs5_readonly, self)
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# Disabled checkbox inputs.
|
63
|
+
def format_checkbox
|
64
|
+
@attr[:disabled] = :disabled
|
65
|
+
super
|
66
|
+
end
|
67
|
+
|
68
|
+
# Use a span with text instead of an input field.
|
69
|
+
def _format_input(type)
|
70
|
+
@attr[:readonly] = :readonly
|
71
|
+
super
|
72
|
+
end
|
73
|
+
|
74
|
+
# Disabled radio button inputs.
|
75
|
+
def format_radio
|
76
|
+
@attr[:disabled] = :disabled
|
77
|
+
super
|
78
|
+
end
|
79
|
+
|
80
|
+
# Use a span with text of the selected values instead of a select box.
|
81
|
+
def format_select
|
82
|
+
@attr[:disabled] = :disabled
|
83
|
+
super
|
84
|
+
end
|
85
|
+
|
86
|
+
# Use a span with text instead of a text area.
|
87
|
+
def format_textarea
|
88
|
+
@attr[:readonly] = :readonly
|
89
|
+
super
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Use a <table class="table"> tag to wrap the inputs.
|
94
|
+
#
|
95
|
+
# Registered as :bs5_table.
|
96
|
+
class InputsWrapper::Bs5Table
|
97
|
+
Forme.register_transformer(:inputs_wrapper, :bs5_table, new)
|
98
|
+
|
99
|
+
# Wrap the inputs in a <table> tag.
|
100
|
+
def call(form, opts, &block)
|
101
|
+
attr = opts[:attr] ? opts[:attr].dup : { :class=>'table table-bordered'}
|
102
|
+
form.tag(:table, attr) do
|
103
|
+
if legend = opts[:legend]
|
104
|
+
form.tag(:caption, opts[:legend_attr], legend)
|
105
|
+
end
|
106
|
+
|
107
|
+
if (labels = opts[:labels]) && !labels.empty?
|
108
|
+
form.tag(:tr, {}, labels.map{|l| form._tag(:th, {}, l)})
|
109
|
+
end
|
110
|
+
|
111
|
+
yield
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Labeler::Bootstrap5 < Labeler::Explicit
|
117
|
+
Forme.register_transformer(:labeler, :bs5, new)
|
118
|
+
|
119
|
+
def call(tag, input)
|
120
|
+
floating_label = (input.opts[:wrapper_attr] || {})[:class].to_s.include?("form-floating")
|
121
|
+
input.opts[:label_position] ||= :after if floating_label
|
122
|
+
|
123
|
+
tags = super
|
124
|
+
return tags if floating_label
|
125
|
+
|
126
|
+
attr = tags.find { |tag| tag.is_a?(Tag) && tag.type == :label }.attr
|
127
|
+
|
128
|
+
label_class = case input.type
|
129
|
+
when :radio, :checkbox
|
130
|
+
"form-check-label"
|
131
|
+
else
|
132
|
+
"form-label"
|
133
|
+
end
|
134
|
+
Forme.attr_classes_after(attr, label_class)
|
135
|
+
|
136
|
+
tags
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class Helper::Bootstrap5
|
141
|
+
Forme.register_transformer(:helper, :bs5, new)
|
142
|
+
|
143
|
+
def call(tag, input)
|
144
|
+
attr = input.opts[:helper_attr]
|
145
|
+
attr = attr ? attr.dup : {}
|
146
|
+
Forme.attr_classes(attr, 'form-text')
|
147
|
+
[tag, input.tag(:div, attr, input.opts[:help])]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class Wrapper::Bootstrap5 < Wrapper
|
152
|
+
Forme.register_transformer(:wrapper, :bs5, new)
|
153
|
+
|
154
|
+
def call(tag, input)
|
155
|
+
attr = input.opts[:wrapper_attr] ? input.opts[:wrapper_attr].dup : { }
|
156
|
+
|
157
|
+
case input.type
|
158
|
+
when :submit, :reset, :hidden
|
159
|
+
super
|
160
|
+
when :radio, :checkbox
|
161
|
+
Forme.attr_classes_after(attr, "form-check")
|
162
|
+
input.tag(:div, attr, super)
|
163
|
+
else
|
164
|
+
input.tag(:div, attr, super)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
class Serializer::Bootstrap5 < Serializer
|
170
|
+
Forme.register_transformer(:serializer, :bs5, new)
|
171
|
+
|
172
|
+
BUTTON_STYLES = %w[
|
173
|
+
btn-primary btn-secondary btn-success btn-danger btn-warning btn-info btn-light btn-dark btn-link
|
174
|
+
btn-outline-primary btn-outline-secondary btn-outline-success btn-outline-danger btn-outline-warning btn-outline-info btn-outline-light btn-outline-dark
|
175
|
+
].freeze
|
176
|
+
|
177
|
+
def call(tag)
|
178
|
+
return super unless tag.is_a?(Tag)
|
179
|
+
|
180
|
+
attr_class = case tag.type
|
181
|
+
when :input
|
182
|
+
# default to <input type="text"...> if not set
|
183
|
+
tag.attr[:type] = :text if tag.attr[:type].nil?
|
184
|
+
|
185
|
+
case tag.attr[:type].to_sym
|
186
|
+
when :checkbox, :radio
|
187
|
+
"form-check-input"
|
188
|
+
when :range
|
189
|
+
"form-range"
|
190
|
+
when :color
|
191
|
+
%w"form-control form-control-color"
|
192
|
+
when :submit, :reset
|
193
|
+
classes = ["btn"]
|
194
|
+
classes << "btn-primary" if (tag.attr[:class].to_s.split(" ") & BUTTON_STYLES).empty?
|
195
|
+
classes
|
196
|
+
when :hidden
|
197
|
+
# nothing
|
198
|
+
else
|
199
|
+
unless tag.attr[:class] && tag.attr[:class].include?("form-control-plaintext")
|
200
|
+
"form-control"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
when :textarea
|
204
|
+
"form-control"
|
205
|
+
when :select
|
206
|
+
"form-select"
|
207
|
+
end
|
208
|
+
Forme.attr_classes_after(tag.attr, *attr_class) if attr_class
|
209
|
+
|
210
|
+
super
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
data/lib/forme/form.rb
CHANGED
@@ -49,17 +49,17 @@ module Forme
|
|
49
49
|
Forme.register_transformer(:error_handler, :after_legend, new)
|
50
50
|
|
51
51
|
def call(tag, input)
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
if tag.is_a?(Array) && tag.first.is_a?(Tag) && tag.first.type == :legend
|
53
|
+
first_input = input.opts[:first_input]
|
54
|
+
attr = first_input.opts[:attr] ||= {}
|
55
|
+
Forme.attr_classes(attr, 'error')
|
56
|
+
attr['aria-invalid'] = 'true'
|
57
|
+
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
61
|
-
|
62
|
-
tag.insert(1, error_tag(input))
|
59
|
+
tag.insert(1, error_tag(input))
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -220,7 +220,7 @@ module Forme
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def _format_set(type, tag_attrs={})
|
223
|
-
raise Error, "can't have radioset with no options" unless @opts[:optgroups] || @opts[:options]
|
223
|
+
raise Error, "can't have radioset or checkboxset with no options" unless @opts[:optgroups] || @opts[:options]
|
224
224
|
key = @opts[:key]
|
225
225
|
name = @opts[:name]
|
226
226
|
id = @opts[:id]
|
@@ -312,7 +312,9 @@ module Forme
|
|
312
312
|
Forme.attr_classes(@attr, 'error')
|
313
313
|
@attr["aria-invalid"] = "true"
|
314
314
|
if @opts.fetch(:error_handler, true)
|
315
|
-
|
315
|
+
if @opts[:error_id]
|
316
|
+
@attr['aria-describedby'] ||= @opts[:error_id]
|
317
|
+
else
|
316
318
|
if id = @attr[:id] || @attr['id']
|
317
319
|
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
318
320
|
@opts[:error_id] = error_id
|
@@ -397,9 +399,7 @@ module Forme
|
|
397
399
|
|
398
400
|
def set_error_from_namespaced_errors(namespaces, errors, key)
|
399
401
|
namespaces.each do |ns|
|
400
|
-
|
401
|
-
return unless e
|
402
|
-
errors = e
|
402
|
+
return unless errors = errors[ns] || errors[ns.to_s]
|
403
403
|
end
|
404
404
|
|
405
405
|
@opts[:error] = errors.fetch(key){errors.fetch(key.to_s){return}}
|
@@ -432,38 +432,36 @@ module Forme
|
|
432
432
|
# Iterate over the given options, yielding the option text, value, whether it is selected, and any attributes.
|
433
433
|
# The block should return an appropriate tag object.
|
434
434
|
def process_select_options(os)
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
sel = @opts[:selected] || @attr.delete(:value)
|
439
|
-
|
440
|
-
if @opts[:multiple]
|
441
|
-
sel = Array(sel)
|
442
|
-
cmp = lambda{|v| sel.include?(v)}
|
443
|
-
else
|
444
|
-
cmp = lambda{|v| v == sel}
|
445
|
-
end
|
435
|
+
vm = @opts[:value_method]
|
436
|
+
tm = @opts[:text_method]
|
437
|
+
sel = @opts[:selected] || @attr.delete(:value)
|
446
438
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
text = x.first
|
454
|
-
val = x.last
|
455
|
-
|
456
|
-
if val.is_a?(Hash)
|
457
|
-
value = val[:value]
|
458
|
-
attr.merge!(val)
|
459
|
-
val = value
|
460
|
-
end
|
461
|
-
else
|
462
|
-
text = x
|
463
|
-
end
|
439
|
+
if @opts[:multiple]
|
440
|
+
sel = Array(sel)
|
441
|
+
cmp = lambda{|v| sel.include?(v)}
|
442
|
+
else
|
443
|
+
cmp = lambda{|v| v == sel}
|
444
|
+
end
|
464
445
|
|
465
|
-
|
446
|
+
os.map do |x|
|
447
|
+
attr = {}
|
448
|
+
if tm
|
449
|
+
text = x.send(tm)
|
450
|
+
val = x.send(vm) if vm
|
451
|
+
elsif x.is_a?(Array)
|
452
|
+
text = x.first
|
453
|
+
val = x.last
|
454
|
+
|
455
|
+
if val.is_a?(Hash)
|
456
|
+
value = val[:value]
|
457
|
+
attr.merge!(val)
|
458
|
+
val = value
|
459
|
+
end
|
460
|
+
else
|
461
|
+
text = x
|
466
462
|
end
|
463
|
+
|
464
|
+
yield [text, val, !val.nil? ? cmp.call(val) : cmp.call(text), attr]
|
467
465
|
end
|
468
466
|
end
|
469
467
|
|
data/lib/forme/version.rb
CHANGED
data/lib/forme.rb
CHANGED
@@ -96,7 +96,8 @@ module Forme
|
|
96
96
|
Form.form(*a, &block)
|
97
97
|
end
|
98
98
|
|
99
|
-
# Update the <tt>:class</tt> entry in the +attr+ hash with the given +classes
|
99
|
+
# Update the <tt>:class</tt> entry in the +attr+ hash with the given +classes+,
|
100
|
+
# adding the classes after any existing classes.
|
100
101
|
def self.attr_classes(attr, *classes)
|
101
102
|
attr[:class] = merge_classes(attr[:class], *classes)
|
102
103
|
end
|
@@ -13,7 +13,9 @@ class Roda
|
|
13
13
|
|
14
14
|
# Set the HMAC secret.
|
15
15
|
def self.configure(app, opts = OPTS, &block)
|
16
|
-
app.opts[:forme_set_hmac_secret] = opts[:secret] || app.opts[:forme_set_hmac_secret]
|
16
|
+
unless app.opts[:forme_set_hmac_secret] = opts[:secret] || app.opts[:forme_set_hmac_secret]
|
17
|
+
raise RodaError, "must provide :secret option to forme_set plugin"
|
18
|
+
end
|
17
19
|
|
18
20
|
if block
|
19
21
|
app.send(:define_method, :_forme_set_handle_error, &block)
|
@@ -27,8 +29,8 @@ class Roda
|
|
27
29
|
|
28
30
|
# Map of error types to error messages
|
29
31
|
ERROR_MESSAGES = {
|
30
|
-
:missing_data=>"_forme_set_data parameter not submitted",
|
31
|
-
:missing_hmac=>"_forme_set_data_hmac parameter not submitted",
|
32
|
+
:missing_data=>"_forme_set_data parameter not submitted, make sure the forme_set Sequel plugin is loaded",
|
33
|
+
:missing_hmac=>"_forme_set_data_hmac parameter not submitted, make sure the forme_set Sequel plugin is loaded",
|
32
34
|
:hmac_mismatch=>"_forme_set_data_hmac does not match _forme_set_data",
|
33
35
|
:csrf_mismatch=>"_forme_set_data CSRF token does not match submitted CSRF token",
|
34
36
|
:missing_namespace=>"no content in expected namespace"
|
data/lib/sequel/plugins/forme.rb
CHANGED
@@ -95,7 +95,7 @@ module Sequel # :nodoc:
|
|
95
95
|
end
|
96
96
|
|
97
97
|
if grid
|
98
|
-
labels = opts.fetch(:labels){opts[:inputs].map{|l
|
98
|
+
labels = opts.fetch(:labels){opts[:inputs].map{|l,| humanize(l)} if opts[:inputs]}
|
99
99
|
legend = opts.fetch(:legend){humanize(association)}
|
100
100
|
inputs_opts = opts[:inputs_opts] || {}
|
101
101
|
inputs(inputs_opts.merge(:inputs_wrapper=>:table, :nested_inputs_wrapper=>:tr, :wrapper=>:td, :labeler=>nil, :labels=>labels, :legend=>legend), &contents)
|
@@ -363,9 +363,10 @@ module Sequel # :nodoc:
|
|
363
363
|
opts[:as] = (sch[:allow_null] || opts[:required] == false) ? :select : :checkbox
|
364
364
|
end
|
365
365
|
|
366
|
+
v = opts.has_key?(:value) ? opts[:value] : obj.send(field)
|
367
|
+
|
366
368
|
case opts[:as]
|
367
369
|
when :radio
|
368
|
-
v = opts.has_key?(:value) ? opts[:value] : obj.send(field)
|
369
370
|
true_value = opts[:true_value]||'t'
|
370
371
|
false_value = opts[:false_value]||'f'
|
371
372
|
opts[:options] = [[opts[:true_label]||'Yes', {:value=>true_value, :key_id=>'yes'}], [opts[:false_label]||'No', {:value=>false_value, :key_id=>'no'}]]
|
@@ -374,13 +375,12 @@ module Sequel # :nodoc:
|
|
374
375
|
end
|
375
376
|
_input(:radioset, opts)
|
376
377
|
when :select
|
377
|
-
v = opts[:value] || obj.send(field)
|
378
378
|
opts[:value] = (v ? 't' : 'f') unless v.nil?
|
379
379
|
opts[:add_blank] = true unless opts.has_key?(:add_blank)
|
380
380
|
opts[:options] = [[opts[:true_label]||'True', opts[:true_value]||'t'], [opts[:false_label]||'False', opts[:false_value]||'f']]
|
381
381
|
_input(:select, opts)
|
382
382
|
else
|
383
|
-
opts[:checked] =
|
383
|
+
opts[:checked] = v
|
384
384
|
opts[:value] = 't'
|
385
385
|
_input(:checkbox, opts)
|
386
386
|
end
|
@@ -424,9 +424,11 @@ module Sequel # :nodoc:
|
|
424
424
|
end
|
425
425
|
end
|
426
426
|
|
427
|
-
# Use
|
427
|
+
# Use inputmode and pattern attributes for integers.
|
428
428
|
def input_integer(sch)
|
429
|
-
|
429
|
+
opts[:attr][:inputmode] ||= 'numeric'
|
430
|
+
opts[:attr][:pattern] ||= '-?[0-9]*'
|
431
|
+
standard_input(:text)
|
430
432
|
end
|
431
433
|
|
432
434
|
# Use date inputs for dates.
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
|
+
require_relative '../../forme'
|
4
|
+
|
3
5
|
module Sequel # :nodoc:
|
4
6
|
module Plugins # :nodoc:
|
5
7
|
# The forme_set plugin makes the model instance keep track of which form
|
@@ -105,10 +107,8 @@ module Sequel # :nodoc:
|
|
105
107
|
opts = input.opts
|
106
108
|
return if SKIP_FORMATTERS.include?(opts.fetch(:formatter){input.form_opts[:formatter]})
|
107
109
|
|
108
|
-
|
109
|
-
|
110
|
-
end
|
111
|
-
return unless name ||= opts[:name] || opts[:key]
|
110
|
+
attr = opts[:attr] || {}
|
111
|
+
return unless name ||= attr[:name] || attr['name'] || opts[:name] || opts[:key]
|
112
112
|
|
113
113
|
# Pull out last component of the name if there is one
|
114
114
|
column = name.to_s.chomp('[]')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -157,6 +157,7 @@ description: |
|
|
157
157
|
2) Have a simple API
|
158
158
|
3) Support forms both with and without related objects
|
159
159
|
4) Allow compiling down to different types of output
|
160
|
+
5) Integrate easily into web frameworks
|
160
161
|
email: code@jeremyevans.net
|
161
162
|
executables: []
|
162
163
|
extensions: []
|
@@ -168,9 +169,9 @@ files:
|
|
168
169
|
- CHANGELOG
|
169
170
|
- MIT-LICENSE
|
170
171
|
- README.rdoc
|
171
|
-
- Rakefile
|
172
172
|
- lib/forme.rb
|
173
173
|
- lib/forme/bs3.rb
|
174
|
+
- lib/forme/bs5.rb
|
174
175
|
- lib/forme/erb.rb
|
175
176
|
- lib/forme/form.rb
|
176
177
|
- lib/forme/input.rb
|
@@ -193,24 +194,6 @@ files:
|
|
193
194
|
- lib/sequel/plugins/forme.rb
|
194
195
|
- lib/sequel/plugins/forme_i18n.rb
|
195
196
|
- lib/sequel/plugins/forme_set.rb
|
196
|
-
- spec/all.rb
|
197
|
-
- spec/bs3_reference_spec.rb
|
198
|
-
- spec/bs3_sequel_plugin_spec.rb
|
199
|
-
- spec/bs3_spec.rb
|
200
|
-
- spec/erb_helper.rb
|
201
|
-
- spec/erubi_capture_helper.rb
|
202
|
-
- spec/forme_coverage.rb
|
203
|
-
- spec/forme_spec.rb
|
204
|
-
- spec/rails_integration_spec.rb
|
205
|
-
- spec/roda_integration_spec.rb
|
206
|
-
- spec/sequel_helper.rb
|
207
|
-
- spec/sequel_i18n_helper.rb
|
208
|
-
- spec/sequel_i18n_plugin_spec.rb
|
209
|
-
- spec/sequel_plugin_spec.rb
|
210
|
-
- spec/sequel_set_plugin_spec.rb
|
211
|
-
- spec/shared_erb_specs.rb
|
212
|
-
- spec/sinatra_integration_spec.rb
|
213
|
-
- spec/spec_helper.rb
|
214
197
|
homepage: http://github.com/jeremyevans/forme
|
215
198
|
licenses:
|
216
199
|
- MIT
|
@@ -220,7 +203,7 @@ metadata:
|
|
220
203
|
documentation_uri: http://forme.jeremyevans.net
|
221
204
|
mailing_list_uri: https://github.com/jeremyevans/forme/discussions
|
222
205
|
source_code_uri: https://github.com/jeremyevans/forme
|
223
|
-
post_install_message:
|
206
|
+
post_install_message:
|
224
207
|
rdoc_options:
|
225
208
|
- "--quiet"
|
226
209
|
- "--line-numbers"
|
@@ -243,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
226
|
version: '0'
|
244
227
|
requirements: []
|
245
228
|
rubygems_version: 3.3.7
|
246
|
-
signing_key:
|
229
|
+
signing_key:
|
247
230
|
specification_version: 4
|
248
231
|
summary: HTML forms library
|
249
232
|
test_files: []
|