html-native 0.1.0 → 0.2.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/lib/html-native.rb +4 -7
- data/lib/html-native/collections.rb +247 -60
- data/lib/html-native/constants.rb +7 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4e5910254a0afad80152339f40b75051ac6045ab51b95f3a0cfd44c6d9d9c81
|
4
|
+
data.tar.gz: a291bbadcb69cb44f067c7c17c01a39b542f8f9bfaebceb95f1b76731c6bbbef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27da9d8f7a378e0a2eff7b989fae29f8ab04b000715542f87906ecda76cae0b4dd31a82fd3fab4e3dd50ca64954efd64727ac3d4bdbda13d497d6c3cffcba7d4
|
7
|
+
data.tar.gz: 846abdea65fb7711610a9a22a5b80c85527fc67c34af386924af7b4092bd32e41a0b1587eef4ff26a8d13c1949801dd4e4e18274ba99f8a7b5aea046b06a1658
|
data/lib/html-native.rb
CHANGED
@@ -3,13 +3,6 @@ require "html-native/builder"
|
|
3
3
|
|
4
4
|
module HTMLComponent
|
5
5
|
|
6
|
-
# Excluded currently because it makes checking in `Builder` ugly
|
7
|
-
# Makes `include` and `extend` work exactly the same.
|
8
|
-
# It's a dirty hack based on laziness, and strict use of `extend` is preferred.
|
9
|
-
# def self.included(base)
|
10
|
-
# base.extend(self)
|
11
|
-
# end
|
12
|
-
|
13
6
|
# Generates generation methods for each HTML5-valid tag. These methods have the
|
14
7
|
# name of the tag. Note that this interferes with the builtin `p` method.
|
15
8
|
TAG_LIST.each do |tag|
|
@@ -24,6 +17,10 @@ module HTMLComponent
|
|
24
17
|
end
|
25
18
|
end
|
26
19
|
|
20
|
+
# Creates a module that encompasses the given block in an HTMLComponent
|
21
|
+
# context. This gives access to methods in the block as though the block was
|
22
|
+
# declared as the `render` function in a module extending HTMLComponent
|
23
|
+
# (pretty much because it is).
|
27
24
|
def self.singleton(&block)
|
28
25
|
Module.new do
|
29
26
|
extend HTMLComponent
|
@@ -2,6 +2,11 @@ require "html-native"
|
|
2
2
|
require "html-native/builder"
|
3
3
|
|
4
4
|
module Enumerable
|
5
|
+
# Maps the given block to each element of *enum*. The result of each iteration
|
6
|
+
# is added to an HTMLComponent::Builder instance, which is returned after the
|
7
|
+
# final iteration.
|
8
|
+
#
|
9
|
+
# If no block is given, an enumerator is returned instead.
|
5
10
|
def component_map
|
6
11
|
if block_given?
|
7
12
|
result = HTMLComponent::Builder.new
|
@@ -14,134 +19,276 @@ module Enumerable
|
|
14
19
|
end
|
15
20
|
end
|
16
21
|
|
22
|
+
# Returns an OrderedListComponent representing the *enum*.
|
23
|
+
#
|
24
|
+
# See OrderedListComponent#new for details on how to apply attributes.
|
17
25
|
def to_ol(attributes: {})
|
18
26
|
OrderedListComponent.new(self, attributes: attributes)
|
19
27
|
end
|
20
28
|
|
29
|
+
# Returns an UnorderedListComponent representing the *enum*.
|
30
|
+
#
|
31
|
+
# See UnorderedListComponent#new for details on how to apply attributes.
|
21
32
|
def to_ul(attributes: {})
|
22
33
|
UnorderedListComponent.new(self, attributes: attributes)
|
23
34
|
end
|
24
35
|
end
|
25
36
|
|
37
|
+
# OrderedListComponent represents an HTML ordered list based on an Enumerable
|
38
|
+
# collection.
|
39
|
+
#
|
40
|
+
# Attributes in an OrderedListComponent are separated into multiple groups since
|
41
|
+
# there are multiple kinds of tags. These groups are:
|
42
|
+
# - list - The attributes associated with the <ol> element
|
43
|
+
# - item - The attributes associated with <li> elements
|
44
|
+
#
|
45
|
+
# For example, to have a list with 20px padding and the class of "list-item"
|
46
|
+
# given to each item, you could write:
|
47
|
+
# ```
|
48
|
+
# OrderedListComponent.new(data, attributes:
|
49
|
+
# {list: {style: "padding: 20px"}, item: {class: "list-item"}})
|
50
|
+
#
|
51
|
+
# ```
|
52
|
+
# which is equivalent to
|
53
|
+
# ```
|
54
|
+
# <ol style="padding: 20px">
|
55
|
+
# <li class="list-item">...</li>
|
56
|
+
# <li class="list-item">...</li>
|
57
|
+
# ...
|
58
|
+
# </ol>
|
59
|
+
# ```
|
26
60
|
class OrderedListComponent
|
27
61
|
include HTMLComponent
|
28
62
|
|
29
|
-
|
63
|
+
# Creates a new instance of OrderedListComponent from the values of *data*.
|
64
|
+
#
|
65
|
+
# If a block is given, each item in *data* is passed to it to render the list
|
66
|
+
# items. If no block is given, *data* are used directly.
|
67
|
+
def initialize(data, attributes: {}, &block)
|
30
68
|
@list_data = data
|
31
69
|
@list_attributes = attributes[:list] || {}
|
32
70
|
@item_attributes = attributes[:item] || {}
|
71
|
+
@block = block
|
33
72
|
end
|
34
73
|
|
35
|
-
|
74
|
+
# Converts the OrderedListComponent instance to the equivalent HTML.
|
75
|
+
#
|
76
|
+
# *render* can be called directly, but that usually isn't necessary.
|
77
|
+
# HTMLComponent::Builder handles this automatically, so it only needs to be
|
78
|
+
# done if there is no prior instance of one.
|
79
|
+
def render
|
36
80
|
ol(@list_attributes) do
|
37
81
|
@list_data.component_map do |l|
|
38
82
|
li(@item_attributes) do
|
39
|
-
|
83
|
+
@block ? @block.call(l) : l
|
40
84
|
end
|
41
85
|
end
|
42
86
|
end
|
43
87
|
end
|
44
88
|
end
|
45
89
|
|
90
|
+
# UnorderedListComponent represents an HTML unordered list generated from an
|
91
|
+
# Enumerable collection.
|
92
|
+
#
|
93
|
+
# Attributes in an UnorderedListComponent are separated into multiple groups since
|
94
|
+
# there are multiple kinds of tags. These groups are:
|
95
|
+
# - list - The attributes associated with the <ul> element
|
96
|
+
# - item - The attributes associated with <li> elements
|
97
|
+
#
|
98
|
+
# For example, to have a list with 20px padding and the class of "list-item"
|
99
|
+
# given to each item, you could write:
|
100
|
+
# ```
|
101
|
+
# UnorderedListComponent.new(data, attributes:
|
102
|
+
# {list: {style: "padding: 20px"}, item: {class: "list-item"}})
|
103
|
+
#
|
104
|
+
# ```
|
105
|
+
# which is equivalent to
|
106
|
+
# ```
|
107
|
+
# <ul style="padding: 20px">
|
108
|
+
# <li class="list-item">...</li>
|
109
|
+
# <li class="list-item">...</li>
|
110
|
+
# ...
|
111
|
+
# </ul>
|
112
|
+
# ```
|
46
113
|
class UnorderedListComponent
|
47
114
|
include HTMLComponent
|
48
115
|
|
49
|
-
|
116
|
+
# Creates a new instance of UnorderedListComponent from the values of *data*.
|
117
|
+
#
|
118
|
+
# If a block is given, each item in *data* is passed to it to render the list
|
119
|
+
# items. If no block is given, *data* are used directly.
|
120
|
+
def initialize(data, attributes: {}, &block)
|
50
121
|
@list_data = data
|
51
122
|
@list_attributes = attributes[:list] || {}
|
52
123
|
@item_attributes = attributes[:item] || {}
|
124
|
+
@block = block
|
53
125
|
end
|
54
126
|
|
55
|
-
|
127
|
+
# Converts the UnorderedListComponent instance to the equivalent HTML.
|
128
|
+
#
|
129
|
+
# *render* can be called directly, but that usually isn't necessary.
|
130
|
+
# HTMLComponent::Builder handles this automatically, so it only needs to be
|
131
|
+
# done if there is no prior instance of one.
|
132
|
+
def render
|
56
133
|
ul(@list_attributes) do
|
57
134
|
@list_data.component_map do |l|
|
58
135
|
li(@item_attributes) do
|
59
|
-
|
136
|
+
@block ? @block.call(l) : l
|
60
137
|
end
|
61
138
|
end
|
62
139
|
end
|
63
140
|
end
|
64
141
|
end
|
65
142
|
|
143
|
+
# ListComponent represents an HTML list based on an Enumerable collection.
|
144
|
+
#
|
145
|
+
# Attributes in an ListComponent are separated into multiple groups since
|
146
|
+
# there are multiple kinds of tags. These groups are:
|
147
|
+
# - list - The attributes associated with the <ul> element
|
148
|
+
# - item - The attributes associated with <li> elements
|
149
|
+
#
|
150
|
+
# For example, to have an ordered list with 20px padding and the class of
|
151
|
+
# "list-item" given to each item, you could write:
|
152
|
+
# ```
|
153
|
+
# ListComponent.new(data, ordered: true, attributes:
|
154
|
+
# {list: {style: "padding: 20px"}, item: {class: "list-item"}})
|
155
|
+
#
|
156
|
+
# ```
|
157
|
+
# which is equivalent to
|
158
|
+
# ```
|
159
|
+
# <ol style="padding: 20px">
|
160
|
+
# <li class="list-item">...</li>
|
161
|
+
# <li class="list-item">...</li>
|
162
|
+
# ...
|
163
|
+
# </ol>
|
164
|
+
# ```
|
66
165
|
class ListComponent
|
67
|
-
|
68
|
-
|
69
|
-
|
166
|
+
# Creates a new instance of ListComponent from the values of *data*.
|
167
|
+
#
|
168
|
+
# This list can be either ordered or unordered, depending on *ordered* parameter.
|
169
|
+
# If *ordered* is true, the list will be ordered, otherwise it will be unordered.
|
170
|
+
# *ordered* is false by default.
|
171
|
+
#
|
172
|
+
# If a block is given, each item in *data* is passed to it to render the list
|
173
|
+
# items. If no block is given, *data* are used directly.
|
174
|
+
def initialize(data, attributes: {}, ordered: false, &block)
|
175
|
+
@list = ordered ? OrderedListComponent.new(data, attributes, &block) :
|
176
|
+
UnorderedListComponent.new(data, attributes, &block)
|
70
177
|
end
|
71
178
|
|
72
|
-
|
73
|
-
|
179
|
+
# Converts the ListComponent instance to the equivalent HTML.
|
180
|
+
#
|
181
|
+
# *render* can be called directly, but that usually isn't necessary.
|
182
|
+
# HTMLComponent::Builder handles this automatically, so it only needs to be
|
183
|
+
# done if there is no prior instance of one.
|
184
|
+
def render
|
185
|
+
@list.render
|
74
186
|
end
|
75
187
|
end
|
76
188
|
|
189
|
+
# TableRowComponent represents an HTML table row generated from an
|
190
|
+
# Enumerable collection.
|
191
|
+
#
|
192
|
+
# Attributes in an TableRowComponent are separated into multiple groups since
|
193
|
+
# there are multiple kinds of tags. These groups are:
|
194
|
+
# - row - The attributes associated with the <tr> element
|
195
|
+
# - cell - The attributes associated with <td> elements
|
196
|
+
#
|
197
|
+
# For example, to have a row with 20px padding and the class of "table-cell"
|
198
|
+
# given to each cell, you could write:
|
199
|
+
# ```
|
200
|
+
# TableRowComponent.new(data, attributes:
|
201
|
+
# {row: {style: "padding: 20px"}, cell: {class: "list-item"}})
|
202
|
+
#
|
203
|
+
# ```
|
204
|
+
# which is equivalent to
|
205
|
+
# ```
|
206
|
+
# <tr style="padding: 20px">
|
207
|
+
# <td class="list-item">...</td>
|
208
|
+
# <td class="list-item">...</td>
|
209
|
+
# ...
|
210
|
+
# </tr>
|
211
|
+
# ```
|
77
212
|
class TableRowComponent
|
78
213
|
include HTMLComponent
|
79
214
|
|
80
|
-
|
215
|
+
# Creates a new instance of TableRowComponent from the values of *data*.
|
216
|
+
#
|
217
|
+
# If a block is given, each item in *data* is passed to it to render the row
|
218
|
+
# cells. If no block is given, *data* are used directly.
|
219
|
+
def initialize(data, attributes: {}, &block)
|
81
220
|
@data = data
|
82
221
|
@row_attributes = attributes[:row] || {}
|
83
222
|
@cell_attributes = attributes[:cell] || {}
|
223
|
+
@block = block
|
84
224
|
end
|
85
225
|
|
86
|
-
|
226
|
+
# Converts the TableRowComponent instance to the equivalent HTML.
|
227
|
+
#
|
228
|
+
# *render* can be called directly, but that usually isn't necessary.
|
229
|
+
# HTMLComponent::Builder handles this automatically, so it only needs to be
|
230
|
+
# done if there is no prior instance of one.
|
231
|
+
def render
|
87
232
|
tr(@row_attributes) do
|
88
233
|
@data.component_map do |c|
|
89
|
-
td(@cell_attributes) {
|
234
|
+
td(@cell_attributes) {@block ? @block.call(c) : c}
|
90
235
|
end
|
91
236
|
end
|
92
237
|
end
|
93
238
|
end
|
94
239
|
|
95
|
-
#
|
240
|
+
# TableComponent represents an HTML table generated from an Enumerable
|
241
|
+
# collection.
|
242
|
+
#
|
243
|
+
# Attributes in an TableComponent are separated into multiple groups since
|
244
|
+
# there are multiple kinds of tags. These groups are:
|
245
|
+
# - table - The attributes associated with the <table> element.
|
246
|
+
# - header - The attributes associated with <tr> element representing the header.
|
247
|
+
# - header_cell - The attributes associated with <th> elements.
|
248
|
+
# - row - The attributes associated with all <tr> elements, including the header.
|
249
|
+
# - cell - The attributes associated with <td> and <th> elements.
|
250
|
+
#
|
251
|
+
# Refer to other components for the format for applying attributes.
|
96
252
|
class TableComponent
|
97
253
|
include HTMLComponent
|
98
254
|
|
99
|
-
|
100
|
-
|
101
|
-
|
255
|
+
# Creates a new instance of TableComponent from the values of *rows*.
|
256
|
+
#
|
257
|
+
# *rows* is an Enumerable collection of Enumerable objects.
|
258
|
+
#
|
259
|
+
# If a block is given, each item in *rows* is passed to it to render the table
|
260
|
+
# cells, not including the header. If no block is given, *rows* is used directly.
|
261
|
+
def initialize(rows, col_names: [], row_names: [], attributes: {}, &block)
|
262
|
+
@rows = rows.map(&:to_a)
|
263
|
+
@header = col_names.to_a
|
264
|
+
row_names = row_names.to_a
|
265
|
+
unless row_names.empty?
|
266
|
+
row_names.each_with_index do |name, i|
|
267
|
+
if i < @rows.size
|
268
|
+
@rows[i].prepend(name)
|
269
|
+
else
|
270
|
+
@rows << [name]
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
@header.prepend("") unless row_names.empty? || @header.empty?
|
275
|
+
|
102
276
|
@table_attributes = attributes[:table] || {}
|
103
277
|
@header_attributes = attributes[:header] || {}
|
104
278
|
@header_cell_attributes = attributes[:header_cell] || {}
|
105
279
|
@row_attributes = attributes[:row] || {}
|
106
280
|
@cell_attributes = attributes[:cell] || {}
|
281
|
+
@block = block
|
107
282
|
end
|
108
283
|
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
head = data[0]
|
116
|
-
rows = data[1..]
|
117
|
-
else
|
118
|
-
head = header.kind_of?(Array) ? header : nil
|
119
|
-
rows = data
|
120
|
-
end
|
121
|
-
new(head, rows, attributes: attributes)
|
122
|
-
end
|
123
|
-
|
124
|
-
def self.from_hash(data, attributes: {}, vertical: true)
|
125
|
-
if vertical
|
126
|
-
rowcount = data.values.map(&:length).max
|
127
|
-
rows = [] * rowcount
|
128
|
-
data.each do |k,col|
|
129
|
-
rowcount.times do |i|
|
130
|
-
rows[i] << (i < col.size ? col[i] : nil)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
new(data.keys, rows, attributes: attributes)
|
134
|
-
else
|
135
|
-
rows = data.map do |k, v|
|
136
|
-
[k] + v
|
137
|
-
end
|
138
|
-
new(nil, rows, attributes: attributes)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def render(&block)
|
284
|
+
# Converts the TableComponent instance to the equivalent HTML.
|
285
|
+
#
|
286
|
+
# *render* can be called directly, but that usually isn't necessary.
|
287
|
+
# HTMLComponent::Builder handles this automatically, so it only needs to be
|
288
|
+
# done if there is no prior instance of one.
|
289
|
+
def render
|
143
290
|
table(@table_attributes) do
|
144
|
-
|
291
|
+
unless @header.empty?
|
145
292
|
tr(@row_attributes.merge(@header_attributes)) do
|
146
293
|
@header.component_map do |h|
|
147
294
|
th(@cell_attributes.merge(@header_cell_attributes)) {h}
|
@@ -151,47 +298,87 @@ class TableComponent
|
|
151
298
|
Builder.new
|
152
299
|
end +
|
153
300
|
@rows.component_map do |row|
|
154
|
-
|
301
|
+
attributes = {row: @row_attributes, cell: @cell_attributes}
|
302
|
+
TableRowComponent.new(row, attributes: attributes, &@block)
|
155
303
|
end
|
156
304
|
end
|
157
305
|
end
|
158
306
|
end
|
159
307
|
|
308
|
+
# DropdownComponent represents an HTML table row generated from an
|
309
|
+
# Enumerable collection.
|
310
|
+
#
|
311
|
+
# Attributes in an DropdownComponent are separated into multiple groups since
|
312
|
+
# there are multiple kinds of tags. These groups are:
|
313
|
+
# - menu - The attributes associated with the <select> element
|
314
|
+
# - item - The attributes associated with <option> elements
|
160
315
|
class DropdownComponent
|
161
316
|
include HTMLComponent
|
162
317
|
|
163
|
-
|
318
|
+
# Creates a new instance of DropdownComponent from the values of *choices*.
|
319
|
+
#
|
320
|
+
# If a block is given, each item in *choices* is passed to it to render the
|
321
|
+
# item. If no block is given, *choices* is used directly.
|
322
|
+
def initialize(choices, name, attributes: {}, &block)
|
164
323
|
@choices = choices
|
165
324
|
@name = name
|
166
325
|
@menu_attributes = attributes[:menu]
|
167
326
|
@item_attributes = attributes[:item]
|
327
|
+
@block = block
|
168
328
|
end
|
169
329
|
|
170
|
-
|
330
|
+
# Converts the DropdownComponent instance to the equivalent HTML.
|
331
|
+
#
|
332
|
+
# *render* can be called directly, but that usually isn't necessary.
|
333
|
+
# HTMLComponent::Builder handles this automatically, so it only needs to be
|
334
|
+
# done if there is no prior instance of one.
|
335
|
+
def render
|
171
336
|
select(@menu_attributes.merge({name: @name, id: "#{@name}-dropdown"})) do
|
172
337
|
@choices.component_map do |c|
|
173
|
-
option(@item_attributes.merge({value: c})) {
|
338
|
+
option(@item_attributes.merge({value: c})) {@block ? @block.call(c) : c}
|
174
339
|
end
|
175
340
|
end
|
176
341
|
end
|
177
342
|
end
|
178
343
|
|
344
|
+
# RadioGroupComponent represents an HTML radio button group generated from an
|
345
|
+
# Enumerable collection.
|
346
|
+
#
|
347
|
+
# Each item has a unique id of the form of `"#{name}-{choice}"`, where name is
|
348
|
+
# the provided *name* option, and choice is value of that button.
|
349
|
+
#
|
350
|
+
# Each item produces a button and a label.
|
351
|
+
#
|
352
|
+
# Attributes in an RadioGroupComponent are separated into multiple groups since
|
353
|
+
# there are multiple kinds of tags. These groups are:
|
354
|
+
# - button - The attributes associated with the <input type: "radio"> elements.
|
355
|
+
# - label - The attributes associated with <label> elements.
|
179
356
|
class RadioGroupComponent
|
180
357
|
include HTMLComponent
|
181
358
|
|
182
|
-
|
359
|
+
# Creates a new instance of RadioGroupComponent from the values of *choices*.
|
360
|
+
#
|
361
|
+
# If a block is given, each item in *choices* is passed to it to render the
|
362
|
+
# label. If no block is given, *choices* is used directly.
|
363
|
+
def initialize(choices, name, attributes: {}, labelled: true, &block)
|
183
364
|
@choices = choices
|
184
365
|
@name = name
|
185
366
|
@button_attributes = attributes[:button]
|
186
367
|
@label_attributes = attributes[:label]
|
187
368
|
@labelled = labelled
|
369
|
+
@block = block
|
188
370
|
end
|
189
371
|
|
190
|
-
|
372
|
+
# Converts the RadioGroupComponent instance to the equivalent HTML.
|
373
|
+
#
|
374
|
+
# *render* can be called directly, but that usually isn't necessary.
|
375
|
+
# HTMLComponent::Builder handles this automatically, so it only needs to be
|
376
|
+
# done if there is no prior instance of one.
|
377
|
+
def render
|
191
378
|
@choices.component_map do |c|
|
192
379
|
id = "#{@name}-#{c}"
|
193
380
|
input({type: "radio", id: id, name: @name, value: c}) +
|
194
|
-
(@labelled ? (label({for: id}) {
|
381
|
+
(@labelled ? (label({for: id}) {@block ? @block.call(c) : c}) : nil)
|
195
382
|
end
|
196
383
|
end
|
197
384
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module HTMLComponent
|
2
|
+
# A list of all valid HTML5 elements. These are used to generate generator
|
3
|
+
# methods within HTMLComponent contexts.
|
2
4
|
TAG_LIST = [
|
3
5
|
:html,
|
4
6
|
:base, :head, :link, :meta, :style, :title,
|
@@ -19,12 +21,12 @@ module HTMLComponent
|
|
19
21
|
:option, :output, :progress, :select, :textarea,
|
20
22
|
:details, :dialog, :menu, :summary,
|
21
23
|
:slot, :template
|
22
|
-
]
|
23
|
-
|
24
|
-
def self.tags
|
25
|
-
TAG_LIST.dup
|
26
|
-
end
|
24
|
+
]
|
27
25
|
|
26
|
+
# A list of all limited attributes in HTML5. Any attribute not listed here are
|
27
|
+
# free to use in any element, as long as it is not in FORBIDDEN_ATTRIBUTES.
|
28
|
+
#
|
29
|
+
# Any attributes listed here will only be allowed in the associated elements.
|
28
30
|
LIMITED_ATTRIBUTES = {
|
29
31
|
accept: [:form, :input],
|
30
32
|
"accept-charset": [:form],
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html-native
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kellen Watt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: An html generation DSL designed for fluid code creation.
|
14
14
|
email:
|