xrb-formatters 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +1 -0
- data/lib/xrb/formatters/formatter.rb +100 -0
- data/lib/xrb/formatters/html/accept_checkbox.rb +48 -0
- data/lib/xrb/formatters/html/definition_list_form.rb +131 -0
- data/lib/xrb/formatters/html/form_formatter.rb +222 -0
- data/lib/xrb/formatters/html/label_form.rb +129 -0
- data/lib/xrb/formatters/html/option_select.rb +131 -0
- data/lib/xrb/formatters/html/radio_select.rb +104 -0
- data/lib/xrb/formatters/markdown.rb +23 -0
- data/lib/xrb/formatters/relative_time.rb +26 -0
- data/lib/xrb/formatters/truncated_text.rb +39 -0
- data/lib/xrb/formatters/version.rb +10 -0
- data/lib/xrb/formatters.rb +6 -0
- data/license.md +21 -0
- data/readme.md +63 -0
- data.tar.gz.sig +0 -0
- metadata +115 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7c7d3c4882fa5d1766266d11516647193f2edb6a414aa3901cd2280da98b219e
|
4
|
+
data.tar.gz: 82609011a18a1ebf7848c8b92654b75ed9721d2f27640b2687fdb4d89e03cec7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: af17a0f56086a82b143d69d5b02ec070126a8182bd1a6ecb8ce628d10b6063ac6a689e15d69c059e298128202165c9b15ed382ce27f7147a387bb5eb7933bf99
|
7
|
+
data.tar.gz: 836b7440bf8623edf869c929172c32c4613a89c6ff18b68aff2a3f26fc68bd62da3e2f0d0a123940f6bf28051b3d1aac54f6d0083988b01e36887041ba368e9d
|
checksums.yaml.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
<���3S-q�Aa�G�"hsiǯ���S����g^^]C_�1���v�������XT����TZܼXc��������c�Hr��'~&� $aK�廰��L���t������!y����Г<�O�b�_lgu�i�NX�S�n�=���Eh<�Lv�8x`V��{gP����5
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2012-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/strings'
|
7
|
+
require 'mapping/model'
|
8
|
+
require 'mapping/descendants'
|
9
|
+
|
10
|
+
module XRB
|
11
|
+
module Formatters
|
12
|
+
class Formatter < Mapping::Model
|
13
|
+
def self.for(object, **options)
|
14
|
+
self.new(object: object, **options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(**options)
|
18
|
+
@options = options
|
19
|
+
|
20
|
+
@object = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# The target object of the form.
|
24
|
+
def object
|
25
|
+
@object ||= @options[:object]
|
26
|
+
end
|
27
|
+
|
28
|
+
def nested_name(**options)
|
29
|
+
options[:nested_name] || @options[:nested_name]
|
30
|
+
end
|
31
|
+
|
32
|
+
# The name of the field, used for the name attribute of an input.
|
33
|
+
def name_for(**options)
|
34
|
+
name = options[:name] || options[:field]
|
35
|
+
|
36
|
+
if suffix = options[:suffix]
|
37
|
+
name = "#{name}#{suffix}"
|
38
|
+
end
|
39
|
+
|
40
|
+
if nested_name = self.nested_name(**options)
|
41
|
+
"#{nested_name}[#{name}]"
|
42
|
+
else
|
43
|
+
name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def nested_name_for(**options)
|
48
|
+
name_for(**options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def nested(name, key = name, klass: self.class)
|
52
|
+
options = @options.dup
|
53
|
+
target = self.object.send(name)
|
54
|
+
|
55
|
+
options[:object] = target
|
56
|
+
options[:nested_name] = nested_name_for(name: key)
|
57
|
+
|
58
|
+
formatter = klass.new(**options)
|
59
|
+
|
60
|
+
return formatter unless block_given?
|
61
|
+
|
62
|
+
yield formatter
|
63
|
+
end
|
64
|
+
|
65
|
+
attr :options
|
66
|
+
|
67
|
+
def format_unspecified(object, **options)
|
68
|
+
object.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
def format(object, **options)
|
72
|
+
method_name = self.method_for_mapping(object)
|
73
|
+
|
74
|
+
if self.respond_to?(method_name)
|
75
|
+
self.send(method_name, object, **options)
|
76
|
+
else
|
77
|
+
format_unspecified(object, **options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
alias text format
|
82
|
+
|
83
|
+
def [] key
|
84
|
+
@options[key]
|
85
|
+
end
|
86
|
+
|
87
|
+
map(String) do |object, **options|
|
88
|
+
object
|
89
|
+
end
|
90
|
+
|
91
|
+
map(NilClass) do |object, **options|
|
92
|
+
options[:blank] || @options[:blank] || ""
|
93
|
+
end
|
94
|
+
|
95
|
+
map(TrueClass, FalseClass, *Mapping.lookup_descendants(Numeric)) do |object, **options|
|
96
|
+
object.to_s
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2020-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/builder'
|
7
|
+
|
8
|
+
module XRB
|
9
|
+
module Formatters
|
10
|
+
module HTML
|
11
|
+
class AcceptCheckbox
|
12
|
+
def self.call(formatter, builder, **options, &block)
|
13
|
+
instance = self.new(formatter, builder, **options)
|
14
|
+
|
15
|
+
instance.call(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(formatter, builder, **options)
|
19
|
+
@formatter = formatter
|
20
|
+
@builder = builder
|
21
|
+
@options = options
|
22
|
+
end
|
23
|
+
|
24
|
+
def name_for(**options)
|
25
|
+
@formatter.name_for(**options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def checkbox_attributes_for(**options)
|
29
|
+
@formatter.checkbox_attributes_for(**options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(&block)
|
33
|
+
Builder.fragment(@builder) do |builder|
|
34
|
+
builder.inline('span') do
|
35
|
+
builder.inline :input, type: :hidden, name: name_for(**@options), value: 'false'
|
36
|
+
|
37
|
+
builder.tag :input, checkbox_attributes_for(**@options)
|
38
|
+
|
39
|
+
builder.text " "
|
40
|
+
|
41
|
+
builder.capture(self, &block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2012-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/builder'
|
7
|
+
require 'xrb/template'
|
8
|
+
|
9
|
+
require_relative 'form_formatter'
|
10
|
+
|
11
|
+
module XRB
|
12
|
+
module Formatters
|
13
|
+
module HTML
|
14
|
+
module DefinitionListForm
|
15
|
+
include FormFormatter
|
16
|
+
|
17
|
+
# An input field (single line text).
|
18
|
+
def input(**options)
|
19
|
+
options = @options.merge(**options)
|
20
|
+
|
21
|
+
Builder.fragment do |builder|
|
22
|
+
builder.inline(:dt) do
|
23
|
+
builder.text title_for(**options)
|
24
|
+
end
|
25
|
+
|
26
|
+
builder.inline(:dd) do
|
27
|
+
builder.tag :input, input_attributes_for(**options)
|
28
|
+
|
29
|
+
if details = details_for(**options)
|
30
|
+
builder.inline(:small, class: 'details') {builder.text details}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# An output field for the result of a computation.
|
37
|
+
def output(**options)
|
38
|
+
options = @options.merge(**options)
|
39
|
+
|
40
|
+
Builder.fragment do |builder|
|
41
|
+
builder.inline(:dt) {builder.text title_for(**options)}
|
42
|
+
|
43
|
+
builder.inline(:dd) do
|
44
|
+
builder.inline :output, output_attributes_for(**options) do
|
45
|
+
builder.text value_for(**options)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# A textarea field (multi-line text).
|
52
|
+
def textarea(**options)
|
53
|
+
options = @options.merge(**options)
|
54
|
+
|
55
|
+
Builder.fragment do |builder|
|
56
|
+
builder.tag(:dt) do
|
57
|
+
builder.text title_for(**options)
|
58
|
+
|
59
|
+
if details = details_for(**options)
|
60
|
+
builder.inline(:small, class: 'details') {builder.text details}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
builder.inline(:dd) do
|
65
|
+
builder.tag :textarea, textarea_attributes_for(**options) do
|
66
|
+
builder.text value_for(**options)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# A checkbox field.
|
73
|
+
def checkbox(**options)
|
74
|
+
options = @options.merge(**options)
|
75
|
+
|
76
|
+
Builder.fragment do |builder|
|
77
|
+
builder.tag(:dd) do
|
78
|
+
builder.tag :input, :type => :hidden, :name => name_for(**options), :value => 'false'
|
79
|
+
|
80
|
+
builder.inline(:label) do
|
81
|
+
builder.tag :input, checkbox_attributes_for(**options)
|
82
|
+
# We would like a little bit of whitespace between the checkbox and the title.
|
83
|
+
builder.text " " + title_for(**options)
|
84
|
+
end
|
85
|
+
|
86
|
+
if details = details_for(**options)
|
87
|
+
builder.inline(:small, class: 'details') {builder.text details}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# A submission button
|
94
|
+
def submit(**options)
|
95
|
+
options = @options.merge(**options)
|
96
|
+
options[:title] ||= submit_title_for(**options)
|
97
|
+
|
98
|
+
Builder.fragment do |builder|
|
99
|
+
builder.tag :input, submit_attributes_for(**options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def element(klass, **options, &block)
|
104
|
+
options = @options.merge(**options)
|
105
|
+
|
106
|
+
Builder.fragment(block&.binding) do |builder|
|
107
|
+
builder.inline(:dt) do
|
108
|
+
builder.text title_for(**options)
|
109
|
+
end
|
110
|
+
|
111
|
+
builder.tag(:dd) do
|
112
|
+
klass.call(self, builder, **options, &block)
|
113
|
+
|
114
|
+
if details = details_for(**options)
|
115
|
+
builder.inline(:small, class: 'details') {builder.text details}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def fieldset(**options, &block)
|
122
|
+
super do |builder|
|
123
|
+
builder.tag(:dl) do
|
124
|
+
yield(builder)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2014-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/builder'
|
7
|
+
|
8
|
+
module XRB
|
9
|
+
module Formatters
|
10
|
+
module HTML
|
11
|
+
module FormFormatter
|
12
|
+
# Return true if the object is begin created or false if it is being updated.
|
13
|
+
def new_record?
|
14
|
+
object.new_record?
|
15
|
+
end
|
16
|
+
|
17
|
+
# Any additional details relating to a field (e.g. explanation text)
|
18
|
+
def details_for(**options)
|
19
|
+
options[:details]
|
20
|
+
end
|
21
|
+
|
22
|
+
def field_for(**options)
|
23
|
+
options[:field]
|
24
|
+
end
|
25
|
+
|
26
|
+
# A title is a text string that will be displayed next to or on top of the control to describe it or its value:
|
27
|
+
def title_for(**options)
|
28
|
+
if title = options[:title]
|
29
|
+
return title
|
30
|
+
end
|
31
|
+
|
32
|
+
# Generate a title from a field name:
|
33
|
+
if field_name = field_for(**options)
|
34
|
+
# Remove postfix "_id" or "_ids":
|
35
|
+
return Strings::to_title(field_name.to_s.sub(/_ids?/, ''))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def object_value_for(**options)
|
40
|
+
if object = options[:object] and field = field_for(**options)
|
41
|
+
object.send(field)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def raw_value_for(**options)
|
46
|
+
value = options.fetch(:value) {object_value_for(**options)}
|
47
|
+
|
48
|
+
# Allow to specify a default value if the value given, usually from an object, is nil.
|
49
|
+
value || options[:default]
|
50
|
+
end
|
51
|
+
|
52
|
+
# The value of the field.
|
53
|
+
def value_for(**options)
|
54
|
+
if value = raw_value_for(**options)
|
55
|
+
self.format(value, **options)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def pattern_for(**options)
|
60
|
+
options[:pattern]
|
61
|
+
end
|
62
|
+
|
63
|
+
def placeholder_for(**options)
|
64
|
+
options[:placeholder]
|
65
|
+
end
|
66
|
+
|
67
|
+
def input_attributes_for(**options)
|
68
|
+
attributes = {
|
69
|
+
:type => options[:type],
|
70
|
+
:name => name_for(**options),
|
71
|
+
:id => options[:id],
|
72
|
+
:class => options[:class],
|
73
|
+
:value => value_for(**options),
|
74
|
+
:required => options[:required],
|
75
|
+
:disabled => options[:disabled],
|
76
|
+
:readonly => options[:readonly],
|
77
|
+
:pattern => pattern_for(**options),
|
78
|
+
:placeholder => placeholder_for(**options),
|
79
|
+
# for <input type="range|number">
|
80
|
+
:min => options[:minimum] || options[:min],
|
81
|
+
:max => options[:maximum] || options[:max],
|
82
|
+
:step => options[:step],
|
83
|
+
# for <input type="text">
|
84
|
+
:minlength => options[:minimum] || options[:minlength],
|
85
|
+
:maxlength => options[:maximum] || options[:maxlength],
|
86
|
+
:data => options[:data],
|
87
|
+
}
|
88
|
+
|
89
|
+
return attributes
|
90
|
+
end
|
91
|
+
|
92
|
+
def output_attributes_for(**options)
|
93
|
+
attributes = {
|
94
|
+
:name => name_for(**options),
|
95
|
+
:id => options[:id],
|
96
|
+
:class => options[:class],
|
97
|
+
:for => options[:for],
|
98
|
+
:form => options[:form],
|
99
|
+
:data => options[:data],
|
100
|
+
}
|
101
|
+
|
102
|
+
return attributes
|
103
|
+
end
|
104
|
+
|
105
|
+
def textarea_attributes_for(**options)
|
106
|
+
return {
|
107
|
+
:name => name_for(**options),
|
108
|
+
:id => options[:id],
|
109
|
+
:class => options[:class],
|
110
|
+
:required => options[:required],
|
111
|
+
:disabled => options[:disabled],
|
112
|
+
:readonly => options[:readonly],
|
113
|
+
:pattern => pattern_for(**options),
|
114
|
+
:placeholder => placeholder_for(**options),
|
115
|
+
:minlength => options[:minlength],
|
116
|
+
:maxlength => options[:maxlength],
|
117
|
+
:data => options[:data],
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def checkbox_attributes_for(**options)
|
122
|
+
return {
|
123
|
+
:type => options[:type] || 'checkbox',
|
124
|
+
:id => options[:id],
|
125
|
+
:class => options[:class],
|
126
|
+
:name => name_for(**options),
|
127
|
+
:value => 'true',
|
128
|
+
:checked => raw_value_for(**options),
|
129
|
+
:required => options[:required],
|
130
|
+
:disabled => options[:disabled],
|
131
|
+
:readonly => options[:readonly],
|
132
|
+
:data => options[:data],
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
def submit_attributes_for(**options)
|
137
|
+
return {
|
138
|
+
:type => options[:type] || 'submit',
|
139
|
+
:name => name_for(**options),
|
140
|
+
:id => options[:id],
|
141
|
+
:class => options[:class],
|
142
|
+
:disabled => options[:disabled],
|
143
|
+
:value => title_for(**options),
|
144
|
+
:data => options[:data],
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
def submit_title_for(**options)
|
149
|
+
title_for(**options) || (new_record? ? 'Create' : 'Update')
|
150
|
+
end
|
151
|
+
|
152
|
+
def hidden_attributes_for(**options)
|
153
|
+
return {
|
154
|
+
:type => options[:type] || 'hidden',
|
155
|
+
:id => options[:id],
|
156
|
+
:class => options[:class],
|
157
|
+
:name => name_for(**options),
|
158
|
+
:value => value_for(**options),
|
159
|
+
:data => options[:data],
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
# A hidden field.
|
164
|
+
def hidden(**options)
|
165
|
+
options = @options.merge(**options)
|
166
|
+
|
167
|
+
Builder.fragment do |builder|
|
168
|
+
builder.tag :input, hidden_attributes_for(**options)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def button_attributes_for(**options)
|
173
|
+
return {
|
174
|
+
:type => options[:type] || 'submit',
|
175
|
+
:name => name_for(**options),
|
176
|
+
:id => options[:id],
|
177
|
+
:class => options[:class],
|
178
|
+
:disabled => options[:disabled],
|
179
|
+
:value => value_for(**options),
|
180
|
+
:data => options[:data],
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
def button_title_for(**options)
|
185
|
+
type = options.fetch(:type, 'submit').to_sym
|
186
|
+
|
187
|
+
if type == :submit
|
188
|
+
submit_title_for(**options)
|
189
|
+
else
|
190
|
+
title_for(**options) || Strings::to_title(type.to_s)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# A hidden field.
|
195
|
+
def button(**options)
|
196
|
+
options = @options.merge(**options)
|
197
|
+
|
198
|
+
Builder.fragment do |builder|
|
199
|
+
builder.inline :button, button_attributes_for(**options) do
|
200
|
+
builder.text button_title_for(**options)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def fieldset(**options, &block)
|
206
|
+
options = @options.merge(**options)
|
207
|
+
buffer = XRB::Template.buffer(block.binding)
|
208
|
+
|
209
|
+
Builder.fragment(buffer) do |builder|
|
210
|
+
builder.tag('fieldset') do
|
211
|
+
builder.inline('legend') do
|
212
|
+
builder.text title_for(**options)
|
213
|
+
end
|
214
|
+
|
215
|
+
yield(builder)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2020-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/builder'
|
7
|
+
require 'xrb/template'
|
8
|
+
|
9
|
+
require_relative 'form_formatter'
|
10
|
+
|
11
|
+
module XRB
|
12
|
+
module Formatters
|
13
|
+
module HTML
|
14
|
+
module LabelForm
|
15
|
+
include FormFormatter
|
16
|
+
|
17
|
+
# An input field (single line text).
|
18
|
+
def input(**options)
|
19
|
+
options = @options.merge(**options)
|
20
|
+
|
21
|
+
Builder.fragment do |builder|
|
22
|
+
builder.inline(:label) do
|
23
|
+
builder.inline(:span) do
|
24
|
+
builder.text title_for(**options)
|
25
|
+
|
26
|
+
if details = details_for(**options)
|
27
|
+
builder.inline(:small) {builder.text details}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
builder.inline :input, input_attributes_for(**options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# An output field for the result of a computation.
|
37
|
+
def output(**options)
|
38
|
+
options = @options.merge(**options)
|
39
|
+
|
40
|
+
builder.inline(:label) do
|
41
|
+
builder.inline(:span) do
|
42
|
+
builder.text title_for(**options)
|
43
|
+
|
44
|
+
if details = details_for(**options)
|
45
|
+
builder.inline(:small) {builder.text details}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
builder.inline :output, output_attributes_for(**options) do
|
50
|
+
builder.text value_for(**options)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# A textarea field (multi-line text).
|
56
|
+
def textarea(**options)
|
57
|
+
options = @options.merge(**options)
|
58
|
+
|
59
|
+
Builder.fragment do |builder|
|
60
|
+
builder.inline(:label) do
|
61
|
+
builder.inline(:span) do
|
62
|
+
builder.text title_for(**options)
|
63
|
+
|
64
|
+
if details = details_for(**options)
|
65
|
+
builder.inline(:small) {builder.text details}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
builder.tag :textarea, textarea_attributes_for(**options) do
|
70
|
+
builder.text value_for(**options)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# A checkbox field.
|
77
|
+
def checkbox(**options)
|
78
|
+
options = @options.merge(**options)
|
79
|
+
|
80
|
+
Builder.fragment do |builder|
|
81
|
+
builder.inline(:label) do
|
82
|
+
builder.inline :input, :type => :hidden, :name => name_for(**options), :value => 'false'
|
83
|
+
|
84
|
+
builder.inline(:span) do
|
85
|
+
if details = details_for(**options)
|
86
|
+
builder.inline(:small) {builder.text details}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
builder.tag :input, checkbox_attributes_for(**options)
|
91
|
+
|
92
|
+
# We would like a little bit of whitespace between the checkbox and the title:
|
93
|
+
builder.text " " + title_for(**options)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# A submission button
|
99
|
+
def submit(**options)
|
100
|
+
options = @options.merge(**options)
|
101
|
+
options[:title] ||= submit_title_for(**options)
|
102
|
+
|
103
|
+
Builder.fragment do |builder|
|
104
|
+
builder.inline :input, submit_attributes_for(**options)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def element(klass, **options, &block)
|
109
|
+
options = @options.merge(**options)
|
110
|
+
buffer = XRB::Template.buffer(block.binding)
|
111
|
+
|
112
|
+
Builder.fragment(buffer) do |builder|
|
113
|
+
builder.inline(:label) do
|
114
|
+
builder.inline(:span) do
|
115
|
+
builder.text title_for(**options)
|
116
|
+
|
117
|
+
if details = details_for(**options)
|
118
|
+
builder.inline(:small) {builder.text details}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
klass.call(self, builder, **options, &block)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2012-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/builder'
|
7
|
+
|
8
|
+
module XRB
|
9
|
+
module Formatters
|
10
|
+
module HTML
|
11
|
+
# Standard drop-down select box:
|
12
|
+
class OptionSelect
|
13
|
+
def self.call(formatter, builder, **options, &block)
|
14
|
+
instance = self.new(formatter, builder, **options)
|
15
|
+
|
16
|
+
instance.call(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(formatter, builder, **options)
|
20
|
+
@formatter = formatter
|
21
|
+
@builder = builder
|
22
|
+
@options = options
|
23
|
+
end
|
24
|
+
|
25
|
+
def name_for(**options)
|
26
|
+
if name = @formatter.name_for(**options)
|
27
|
+
if options[:multiple]
|
28
|
+
name = "#{name}[]"
|
29
|
+
end
|
30
|
+
|
31
|
+
return name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def raw_value_for(**options)
|
36
|
+
@formatter.raw_value_for(**options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def raw_value
|
40
|
+
@raw_value ||= raw_value_for(**@options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def value_for(**options)
|
44
|
+
@formatter.value_for(**options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def title_for(**options)
|
48
|
+
@formatter.title_for(**options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def option_attributes_for(**options)
|
52
|
+
return {
|
53
|
+
:value => value_for(**options),
|
54
|
+
:selected => options.fetch(:selected) {raw_value == raw_value_for(**options)},
|
55
|
+
:id => options[:id],
|
56
|
+
:class => options[:class],
|
57
|
+
:data => options[:data],
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def item(**options, &block)
|
62
|
+
options[:field] ||= 'id'
|
63
|
+
|
64
|
+
Builder.fragment(block&.binding || @builder) do |builder|
|
65
|
+
builder.inline(:option, option_attributes_for(**options)) do
|
66
|
+
if block_given?
|
67
|
+
builder.capture(self, &block)
|
68
|
+
else
|
69
|
+
builder.text title_for(**options)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def optional_title_for(**options)
|
76
|
+
if options[:optional] == true
|
77
|
+
options[:blank] || ''
|
78
|
+
else
|
79
|
+
options[:optional]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def group_attributes_for(**options)
|
84
|
+
return {
|
85
|
+
:label => title_for(**options),
|
86
|
+
:id => options[:id],
|
87
|
+
:class => options[:class],
|
88
|
+
:data => options[:data],
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def group(**options, &block)
|
93
|
+
@builder.tag :optgroup, group_attributes_for(**options) do
|
94
|
+
if options[:optional]
|
95
|
+
item(title: optional_title_for(**options), value: nil)
|
96
|
+
end
|
97
|
+
|
98
|
+
@builder.capture(&block)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def select_attributes_for(**options)
|
103
|
+
return {
|
104
|
+
:name => name_for(**options),
|
105
|
+
:id => options[:id],
|
106
|
+
:class => options[:class],
|
107
|
+
:multiple => options[:multiple],
|
108
|
+
:data => options[:data],
|
109
|
+
:required => options[:required],
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def optional?
|
114
|
+
@options[:optional]
|
115
|
+
end
|
116
|
+
|
117
|
+
def call(&block)
|
118
|
+
Builder.fragment(@builder) do |builder|
|
119
|
+
builder.tag :select, select_attributes_for(**@options) do
|
120
|
+
if self.optional?
|
121
|
+
builder << item(title: optional_title_for(**@options), value: nil)
|
122
|
+
end
|
123
|
+
|
124
|
+
builder.capture(self, &block)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2012-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/builder'
|
7
|
+
|
8
|
+
module XRB
|
9
|
+
module Formatters
|
10
|
+
module HTML
|
11
|
+
# Table based select boxes using per-row checkboxes.
|
12
|
+
class RadioSelect
|
13
|
+
def self.call(formatter, builder, **options, &block)
|
14
|
+
instance = self.new(formatter, builder, **options)
|
15
|
+
|
16
|
+
instance.call(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(formatter, builder, **options)
|
20
|
+
@formatter = formatter
|
21
|
+
@builder = builder
|
22
|
+
@options = options
|
23
|
+
|
24
|
+
@field = options[:field]
|
25
|
+
end
|
26
|
+
|
27
|
+
def name_for(**options)
|
28
|
+
@formatter.name_for(**options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def raw_value_for(**options)
|
32
|
+
@formatter.raw_value_for(**options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def raw_value
|
36
|
+
@raw_value ||= raw_value_for(**@options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def value_for(**options)
|
40
|
+
@formatter.value_for(**options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def title_for(**options)
|
44
|
+
@formatter.title_for(**options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def radio_attributes_for(**options)
|
48
|
+
return {
|
49
|
+
:type => :radio,
|
50
|
+
:name => @field,
|
51
|
+
# We set a default value to empty string, otherwise it becomes "on".
|
52
|
+
:value => value_for(**options) || "",
|
53
|
+
:checked => options.fetch(:selected) {raw_value == raw_value_for(**options)},
|
54
|
+
:data => options[:data],
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def item(**options, &block)
|
59
|
+
Builder.fragment(block&.binding || @builder) do |builder|
|
60
|
+
builder.tag :tr do
|
61
|
+
builder.inline(:td, :class => :handle) do
|
62
|
+
builder.tag :input, radio_attributes_for(**options)
|
63
|
+
end
|
64
|
+
|
65
|
+
builder.inline(:td, :class => :item) do
|
66
|
+
if block_given?
|
67
|
+
builder.capture(self, &block)
|
68
|
+
else
|
69
|
+
builder.text title_for(**options)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def optional_title_for(**options)
|
77
|
+
if options[:optional] == true
|
78
|
+
options[:blank] || ''
|
79
|
+
else
|
80
|
+
options[:optional]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def optional?
|
85
|
+
@options[:optional]
|
86
|
+
end
|
87
|
+
|
88
|
+
def call(&block)
|
89
|
+
Builder.fragment(@builder) do |builder|
|
90
|
+
builder.tag :table do
|
91
|
+
builder.tag :tbody do
|
92
|
+
if self.optional?
|
93
|
+
builder << item(title: optional_title_for(**@options), value: nil)
|
94
|
+
end
|
95
|
+
|
96
|
+
builder.capture(self, &block)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2016-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'markly'
|
7
|
+
|
8
|
+
require 'xrb/markup'
|
9
|
+
require 'xrb/sanitize/fragment'
|
10
|
+
|
11
|
+
module XRB
|
12
|
+
module Formatters
|
13
|
+
module Markdown
|
14
|
+
def markdown(text, filter = XRB::Sanitize::Fragment, **options)
|
15
|
+
root = Markly.parse(text, **options)
|
16
|
+
|
17
|
+
html = filter.parse(root.to_html).output
|
18
|
+
|
19
|
+
return MarkupString.raw(html)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2016-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/strings'
|
7
|
+
require 'mapping/model'
|
8
|
+
|
9
|
+
module XRB
|
10
|
+
module Formatters
|
11
|
+
module RelativeTime
|
12
|
+
def self.included(base)
|
13
|
+
base.map(Time) do |object, **options|
|
14
|
+
current_time = options.fetch(:current_time) {Time.now}
|
15
|
+
|
16
|
+
# Ensure we display the time in localtime, and show the year if it is different:
|
17
|
+
if object.localtime.year != current_time.year
|
18
|
+
object.localtime.strftime("%B %-d, %-l:%M%P, %Y")
|
19
|
+
else
|
20
|
+
object.localtime.strftime("%B %-d, %-l:%M%P")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2016-2024, by Samuel Williams.
|
5
|
+
|
6
|
+
require 'xrb/strings'
|
7
|
+
require 'mapping/model'
|
8
|
+
|
9
|
+
module XRB
|
10
|
+
module Formatters
|
11
|
+
module TruncatedText
|
12
|
+
def truncated_text(content, length: 30, **options)
|
13
|
+
if content
|
14
|
+
content = TruncatedText.truncate_text(content, length, **options)
|
15
|
+
|
16
|
+
return self.format(content)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.truncate_text(text, truncate_at, omission: nil, separator: nil, **options)
|
21
|
+
return text.dup unless text.length > truncate_at
|
22
|
+
|
23
|
+
omission ||= '...'
|
24
|
+
|
25
|
+
length_with_room_for_omission = truncate_at - omission.length
|
26
|
+
|
27
|
+
stop = nil
|
28
|
+
|
29
|
+
if separator
|
30
|
+
stop = text.rindex(separator, length_with_room_for_omission)
|
31
|
+
end
|
32
|
+
|
33
|
+
stop ||= length_with_room_for_omission
|
34
|
+
|
35
|
+
"#{text[0...stop]}#{omission}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/license.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# MIT License
|
2
|
+
|
3
|
+
Copyright, 2012-2024, by Samuel Williams.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/readme.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# XRB::Formatters
|
2
|
+
|
3
|
+
XRB is a templating system, and these formatters assist with the development
|
4
|
+
of typical view and form based web interface. A formatter is a high-level
|
5
|
+
adapter that turns model data into presentation text.
|
6
|
+
|
7
|
+
Formatters are designed to be customised, typically per-project, for specific
|
8
|
+
formatting needs.
|
9
|
+
|
10
|
+
[![Development Status](https://github.com/socketry/xrb-formatters/workflows/Test/badge.svg)](https://github.com/socketry/xrb-formatters/actions?workflow=Test)
|
11
|
+
|
12
|
+
## Motivation
|
13
|
+
|
14
|
+
`XRB::Formatters` was a library extracted from [Financier](https://github.com/ioquatix/financier), an small business management app, itself, derived from an old Rails app. I was a bit envious of `form_for` in terms of the ease of generating forms, but found that it wasn't very extendable. I also found myself generating code to format model data as rich HTML. `XRB::Formatters` attempts to be an easily extendable formatting module which can generate rich text, links and HTML.
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
Add this line to your application's Gemfile:
|
19
|
+
|
20
|
+
gem 'xrb-formatters'
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install xrb-formatters
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
The most basic usage involves converting model data into presentation text by
|
33
|
+
a mapping corresponding to the objects type:
|
34
|
+
|
35
|
+
``` ruby
|
36
|
+
formatter = XRB::Formatters::Formatter.new
|
37
|
+
|
38
|
+
formatter.for(String) do |value, **options|
|
39
|
+
"String: #{value}"
|
40
|
+
end
|
41
|
+
|
42
|
+
expect(formatter.format("foobar")).to be == "String: foobar"
|
43
|
+
```
|
44
|
+
|
45
|
+
For more examples please see `spec/`.
|
46
|
+
|
47
|
+
## Contributing
|
48
|
+
|
49
|
+
We welcome contributions to this project.
|
50
|
+
|
51
|
+
1. Fork it.
|
52
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
53
|
+
3. Commit your changes (`git commit -am 'Add some feature'`).
|
54
|
+
4. Push to the branch (`git push origin my-new-feature`).
|
55
|
+
5. Create new Pull Request.
|
56
|
+
|
57
|
+
### Developer Certificate of Origin
|
58
|
+
|
59
|
+
This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted.
|
60
|
+
|
61
|
+
### Contributor Covenant
|
62
|
+
|
63
|
+
This project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.
|
data.tar.gz.sig
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xrb-formatters
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samuel Williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
|
14
|
+
ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
|
15
|
+
CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
|
16
|
+
MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
|
17
|
+
MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
|
18
|
+
bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
|
19
|
+
igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
|
20
|
+
9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
|
21
|
+
sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
|
22
|
+
e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
|
23
|
+
XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
|
24
|
+
RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
|
25
|
+
tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
|
26
|
+
zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
|
27
|
+
xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
|
28
|
+
BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
|
29
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
|
30
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
|
31
|
+
cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
|
32
|
+
xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
|
33
|
+
c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
|
34
|
+
8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
|
35
|
+
JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
|
36
|
+
eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
|
37
|
+
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
38
|
+
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
39
|
+
-----END CERTIFICATE-----
|
40
|
+
date: 2024-05-08 00:00:00.000000000 Z
|
41
|
+
dependencies:
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: mapping
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.1'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.1'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: xrb
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0.6'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.6'
|
70
|
+
description:
|
71
|
+
email:
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- lib/xrb/formatters.rb
|
77
|
+
- lib/xrb/formatters/formatter.rb
|
78
|
+
- lib/xrb/formatters/html/accept_checkbox.rb
|
79
|
+
- lib/xrb/formatters/html/definition_list_form.rb
|
80
|
+
- lib/xrb/formatters/html/form_formatter.rb
|
81
|
+
- lib/xrb/formatters/html/label_form.rb
|
82
|
+
- lib/xrb/formatters/html/option_select.rb
|
83
|
+
- lib/xrb/formatters/html/radio_select.rb
|
84
|
+
- lib/xrb/formatters/markdown.rb
|
85
|
+
- lib/xrb/formatters/relative_time.rb
|
86
|
+
- lib/xrb/formatters/truncated_text.rb
|
87
|
+
- lib/xrb/formatters/version.rb
|
88
|
+
- license.md
|
89
|
+
- readme.md
|
90
|
+
homepage: https://github.com/ioquatix/xrb-formatters
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata:
|
94
|
+
funding_uri: https://github.com/sponsors/ioquatix/
|
95
|
+
source_code_uri: https://github.com/ioquatix/xrb-formatters.git
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '3.1'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubygems_version: 3.5.3
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Formatters for XRB, to assist with typical views and form based interfaces.
|
115
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|