forme 2.2.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 +6 -0
- data/README.rdoc +7 -2
- data/lib/forme/bs5.rb +213 -0
- 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_set.rb +2 -0
- metadata +7 -24
- data/Rakefile +0 -82
- data/spec/all.rb +0 -2
- data/spec/bs3_reference_spec.rb +0 -335
- data/spec/bs3_sequel_plugin_spec.rb +0 -523
- data/spec/bs3_spec.rb +0 -751
- data/spec/erb_helper.rb +0 -198
- data/spec/erubi_capture_helper.rb +0 -198
- data/spec/forme_coverage.rb +0 -14
- data/spec/forme_spec.rb +0 -1292
- data/spec/rails_integration_spec.rb +0 -286
- data/spec/roda_integration_spec.rb +0 -541
- data/spec/sequel_helper.rb +0 -103
- data/spec/sequel_i18n_helper.rb +0 -40
- data/spec/sequel_i18n_plugin_spec.rb +0 -31
- data/spec/sequel_plugin_spec.rb +0 -703
- data/spec/sequel_set_plugin_spec.rb +0 -238
- data/spec/shared_erb_specs.rb +0 -71
- data/spec/sinatra_integration_spec.rb +0 -71
- 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,9 @@
|
|
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
|
+
|
1
7
|
=== 2.2.0 (2022-06-28)
|
2
8
|
|
3
9
|
* Use inputmode and pattern attributes instead of type=number for integer fields in the Sequel forme plugin (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -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/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/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"
|
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: []
|
data/Rakefile
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
require "rake"
|
2
|
-
require "rake/clean"
|
3
|
-
|
4
|
-
NAME = 'forme'
|
5
|
-
VERS = lambda do
|
6
|
-
require File.expand_path("../lib/forme/version", __FILE__)
|
7
|
-
Forme.version
|
8
|
-
end
|
9
|
-
CLEAN.include ["#{NAME}-*.gem", "rdoc", "coverage", '**/*.rbc']
|
10
|
-
|
11
|
-
# Gem Packaging and Release
|
12
|
-
|
13
|
-
desc "Packages #{NAME}"
|
14
|
-
task :package=>[:clean] do |p|
|
15
|
-
sh %{gem build #{NAME}.gemspec}
|
16
|
-
end
|
17
|
-
|
18
|
-
desc "Upload #{NAME} gem to rubygems"
|
19
|
-
task :release=>[:package] do
|
20
|
-
sh %{gem push ./#{NAME}-#{VERS.call}.gem}
|
21
|
-
end
|
22
|
-
|
23
|
-
### RDoc
|
24
|
-
|
25
|
-
RDOC_DEFAULT_OPTS = ["--line-numbers", "--inline-source", '--title', 'Forme']
|
26
|
-
|
27
|
-
begin
|
28
|
-
gem 'hanna-nouveau'
|
29
|
-
RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
|
30
|
-
rescue Gem::LoadError
|
31
|
-
end
|
32
|
-
|
33
|
-
rdoc_task_class = begin
|
34
|
-
require "rdoc/task"
|
35
|
-
RDoc::Task
|
36
|
-
rescue LoadError
|
37
|
-
require "rake/rdoctask"
|
38
|
-
Rake::RDocTask
|
39
|
-
end
|
40
|
-
|
41
|
-
RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
|
42
|
-
|
43
|
-
rdoc_task_class.new do |rdoc|
|
44
|
-
rdoc.rdoc_dir = "rdoc"
|
45
|
-
rdoc.options += RDOC_OPTS
|
46
|
-
rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb"
|
47
|
-
end
|
48
|
-
|
49
|
-
### Specs
|
50
|
-
|
51
|
-
desc "Run specs"
|
52
|
-
task :spec do
|
53
|
-
sh "#{FileUtils::RUBY} #{'-w' if RUBY_VERSION >= '3'} spec/all.rb"
|
54
|
-
end
|
55
|
-
task :default => :spec
|
56
|
-
|
57
|
-
desc "Run specs with coverage"
|
58
|
-
task :spec_cov do
|
59
|
-
ENV['COVERAGE'] = '1'
|
60
|
-
sh "#{FileUtils::RUBY} spec/all.rb"
|
61
|
-
end
|
62
|
-
|
63
|
-
### Other
|
64
|
-
|
65
|
-
desc "Print #{NAME} version"
|
66
|
-
task :version do
|
67
|
-
puts VERS.call
|
68
|
-
end
|
69
|
-
|
70
|
-
desc "Check syntax of all .rb files"
|
71
|
-
task :check_syntax do
|
72
|
-
Dir['**/*.rb'].each{|file| print `#{ENV['RUBY'] || :ruby} -c #{file} | fgrep -v "Syntax OK"`}
|
73
|
-
end
|
74
|
-
|
75
|
-
desc "Start an IRB shell using the extension"
|
76
|
-
task :irb do
|
77
|
-
require 'rbconfig'
|
78
|
-
ruby = ENV['RUBY'] || File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
79
|
-
irb = ENV['IRB'] || File.join(RbConfig::CONFIG['bindir'], File.basename(ruby).sub('ruby', 'irb'))
|
80
|
-
sh %{#{irb} -I lib -r forme}
|
81
|
-
end
|
82
|
-
|
data/spec/all.rb
DELETED