tty-box 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/LICENSE.txt +1 -1
- data/README.md +18 -4
- data/lib/tty-box.rb +1 -1
- data/lib/tty/box.rb +142 -58
- data/lib/tty/box/border.rb +20 -14
- data/lib/tty/box/version.rb +1 -1
- 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: b9509817a402d4b790c91be69e5d9c11947ba1374a32ba0df8a06a18c333d371
|
4
|
+
data.tar.gz: ea1322ac1cedabf28d34c52fb666386b97013feffc6319cd9c24356039831597
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78d7164d16610ae4fc585977880845b3bd83c2be04e5c417ec08ce1aa00d0a56d6ff90efa5a3229742e97ea4836faadd140d59aca936ed545dd3606d85bf27d4
|
7
|
+
data.tar.gz: 8c7af2b0bf020d0208065a6afdd2ad8a28edfe3ed731582fbf20f4f8b301b574ebd54b5f0c7d9f05db853a7f9e35a507e5092f8a18ab62feefcc0a84851472bb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.7.0] - 2020-12-20
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add :enable_color configuration to allow control over colouring
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
* Change to ensure non-negative space filler size
|
10
|
+
* Change to enforce private visibility for the private module methods
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
* Fix box width calculation to ignore colored text by @LainLayer
|
14
|
+
* Fix drawing frame around multiline colored content
|
15
|
+
|
3
16
|
## [v0.6.0] - 2020-08-11
|
4
17
|
|
5
18
|
### Changed
|
@@ -62,6 +75,7 @@
|
|
62
75
|
|
63
76
|
* Initial implementation and release
|
64
77
|
|
78
|
+
[v0.7.0]: https://github.com/piotrmurach/tty-box/compare/v0.6.0...v0.7.0
|
65
79
|
[v0.6.0]: https://github.com/piotrmurach/tty-box/compare/v0.5.0...v0.6.0
|
66
80
|
[v0.5.0]: https://github.com/piotrmurach/tty-box/compare/v0.4.1...v0.5.0
|
67
81
|
[v0.4.1]: https://github.com/piotrmurach/tty-box/compare/v0.4.0...v0.4.1
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2018 Piotr Murach
|
3
|
+
Copyright (c) 2018 Piotr Murach (https://piotrmurach.com)
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
<div align="center">
|
2
|
-
<a href="https://
|
2
|
+
<a href="https://ttytoolkit.org"><img width="130" src="https://github.com/piotrmurach/tty/blob/master/images/tty.png" alt="TTY Toolkit logo" /></a>
|
3
3
|
</div>
|
4
4
|
|
5
5
|
# TTY::Box [![Gitter](https://badges.gitter.im/Join%20Chat.svg)][gitter]
|
6
6
|
|
7
7
|
[![Gem Version](https://badge.fury.io/rb/tty-box.svg)][gem]
|
8
|
-
[![
|
8
|
+
[![Actions CI](https://github.com/piotrmurach/tty-box/workflows/CI/badge.svg?branch=master)][gh_actions_ci]
|
9
9
|
[![Build status](https://ci.appveyor.com/api/projects/status/h9b88fk5xpya3fh1?svg=true)][appveyor]
|
10
10
|
[![Maintainability](https://api.codeclimate.com/v1/badges/dfac05073e1549e9dbb6/maintainability)][codeclimate]
|
11
11
|
[![Coverage Status](https://coveralls.io/repos/github/piotrmurach/tty-box/badge.svg)][coverage]
|
@@ -13,7 +13,7 @@
|
|
13
13
|
|
14
14
|
[gitter]: https://gitter.im/piotrmurach/tty
|
15
15
|
[gem]: http://badge.fury.io/rb/tty-box
|
16
|
-
[
|
16
|
+
[gh_actions_ci]: https://github.com/piotrmurach/tty-box/actions?query=workflow%3ACI
|
17
17
|
[appveyor]: https://ci.appveyor.com/project/piotrmurach/tty-box
|
18
18
|
[codeclimate]: https://codeclimate.com/github/piotrmurach/tty-box/maintainability
|
19
19
|
[coverage]: https://coveralls.io/github/piotrmurach/tty-box
|
@@ -310,7 +310,7 @@ print box
|
|
310
310
|
If you want to remove a given border element as a value use `false`. For example to remove bottom border do:
|
311
311
|
|
312
312
|
```ruby
|
313
|
-
TTY::Box.
|
313
|
+
TTY::Box.frame(
|
314
314
|
width: 30, height: 10,
|
315
315
|
border: {
|
316
316
|
type: :thick,
|
@@ -335,6 +335,20 @@ style: {
|
|
335
335
|
|
336
336
|
The above style configuration will produce the result similar to the top demo, a MS-DOS look & feel window.
|
337
337
|
|
338
|
+
You can disable or force output styling regardless of the terminal using the `enable_color` keyword. By default, the color support is automatically detected.
|
339
|
+
|
340
|
+
```ruby
|
341
|
+
TTY::Box.frame({
|
342
|
+
enable_color: true, # force to always color output
|
343
|
+
style: {
|
344
|
+
border: {
|
345
|
+
fg: :bright_yellow,
|
346
|
+
bg: :blue
|
347
|
+
}
|
348
|
+
}
|
349
|
+
})
|
350
|
+
```
|
351
|
+
|
338
352
|
### 2.7 formatting
|
339
353
|
|
340
354
|
You can use `:align` keyword to format content either to be `:left`, `:center` or `:right` aligned:
|
data/lib/tty-box.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative "tty/box"
|
data/lib/tty/box.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "strings"
|
4
|
+
require "pastel"
|
5
|
+
require "tty-cursor"
|
6
6
|
|
7
|
-
require_relative
|
8
|
-
require_relative
|
7
|
+
require_relative "box/border"
|
8
|
+
require_relative "box/version"
|
9
9
|
|
10
10
|
module TTY
|
11
11
|
module Box
|
12
12
|
module_function
|
13
13
|
|
14
14
|
NEWLINE = "\n"
|
15
|
+
SPACE = " "
|
15
16
|
|
16
17
|
LINE_BREAK = %r{\r\n|\r|\n}.freeze
|
17
18
|
|
@@ -69,8 +70,8 @@ module TTY
|
|
69
70
|
TTY::Cursor
|
70
71
|
end
|
71
72
|
|
72
|
-
def color
|
73
|
-
@color ||= Pastel.new
|
73
|
+
def color(enabled: nil)
|
74
|
+
@color ||= Pastel.new(enabled: enabled)
|
74
75
|
end
|
75
76
|
|
76
77
|
# A frame for info type message
|
@@ -135,7 +136,7 @@ module TTY
|
|
135
136
|
bg: :bright_green,
|
136
137
|
border: {
|
137
138
|
fg: :black,
|
138
|
-
bg: :bright_green
|
139
|
+
bg: :bright_green
|
139
140
|
}
|
140
141
|
}
|
141
142
|
}.merge(opts)
|
@@ -187,37 +188,36 @@ module TTY
|
|
187
188
|
# the styling for the front and background
|
188
189
|
#
|
189
190
|
# @api public
|
190
|
-
def frame(*content, top: nil, left: nil, width: nil, height: nil,
|
191
|
-
padding: 0, title: {}, border: :light, style: {}
|
191
|
+
def frame(*content, top: nil, left: nil, width: nil, height: nil,
|
192
|
+
align: :left, padding: 0, title: {}, border: :light, style: {},
|
193
|
+
enable_color: nil)
|
194
|
+
@color = nil
|
195
|
+
color(enabled: enable_color)
|
192
196
|
output = []
|
193
197
|
sep = NEWLINE
|
194
198
|
position = top && left
|
195
199
|
|
196
200
|
border = Border.parse(border)
|
197
|
-
top_size = border.top? ? 1: 0
|
198
|
-
bottom_size = border.bottom? ? 1: 0
|
201
|
+
top_size = border.top? ? 1 : 0
|
202
|
+
bottom_size = border.bottom? ? 1 : 0
|
199
203
|
left_size = border.left? ? 1 : 0
|
200
204
|
right_size = border.right ? 1 : 0
|
201
205
|
|
202
|
-
|
203
|
-
str = yield
|
204
|
-
else
|
205
|
-
str = case content.size
|
206
|
-
when 0 then ""
|
207
|
-
when 1 then content[0]
|
208
|
-
else content.join(NEWLINE)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
206
|
+
str = block_given? ? yield : content_to_str(content)
|
212
207
|
sep = str[LINE_BREAK] || NEWLINE # infer line break
|
213
|
-
|
208
|
+
content_lines = str.split(sep)
|
209
|
+
|
214
210
|
# infer dimensions
|
215
|
-
dimensions = infer_dimensions(
|
211
|
+
dimensions = infer_dimensions(content_lines, padding)
|
216
212
|
width ||= left_size + dimensions[0] + right_size
|
217
|
-
width = [width,
|
218
|
-
|
213
|
+
width = [width,
|
214
|
+
top_space_taken(title, border),
|
215
|
+
bottom_space_taken(title, border)].max
|
219
216
|
height ||= top_size + dimensions[1] + bottom_size
|
220
|
-
|
217
|
+
|
218
|
+
# apply formatting to content
|
219
|
+
formatted_lines = format(content_lines, width, padding, align, sep)
|
220
|
+
|
221
221
|
# infer styling
|
222
222
|
fg, bg = *extract_style(style)
|
223
223
|
border_fg, border_bg = *extract_style(style[:border] || {})
|
@@ -234,19 +234,22 @@ module TTY
|
|
234
234
|
output << border_bg.(border_fg.(pipe_char(border.type)))
|
235
235
|
end
|
236
236
|
|
237
|
-
|
238
|
-
|
239
|
-
output << bg.(fg.(
|
240
|
-
|
241
|
-
|
237
|
+
filler_size = width - left_size - right_size
|
238
|
+
if formatted_line = formatted_lines[i]
|
239
|
+
output << bg.(fg.(formatted_line))
|
240
|
+
line_content_size = Strings::ANSI.sanitize(formatted_line)
|
241
|
+
.scan(/[[:print:]]/).join.size
|
242
|
+
filler_size = [filler_size - line_content_size, 0].max
|
242
243
|
end
|
244
|
+
|
243
245
|
if style[:fg] || style[:bg] || !position # something to color
|
244
|
-
output << bg.(fg.(
|
246
|
+
output << bg.(fg.(SPACE * filler_size))
|
245
247
|
end
|
246
248
|
|
247
249
|
if border.right?
|
248
250
|
if position
|
249
|
-
output << cursor.move_to(left + width - right_size,
|
251
|
+
output << cursor.move_to(left + width - right_size,
|
252
|
+
top + i + top_size)
|
250
253
|
end
|
251
254
|
output << border_bg.(border_fg.(pipe_char(border.type)))
|
252
255
|
end
|
@@ -262,6 +265,22 @@ module TTY
|
|
262
265
|
output.join
|
263
266
|
end
|
264
267
|
|
268
|
+
# Convert content array to string
|
269
|
+
#
|
270
|
+
# @param [Array<String>] content
|
271
|
+
#
|
272
|
+
# @return [String]
|
273
|
+
#
|
274
|
+
# @api private
|
275
|
+
def content_to_str(content)
|
276
|
+
case content.size
|
277
|
+
when 0 then ""
|
278
|
+
when 1 then content[0]
|
279
|
+
else content.join(NEWLINE)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
private_class_method :content_to_str
|
283
|
+
|
265
284
|
# Infer box dimensions based on content lines and padding
|
266
285
|
#
|
267
286
|
# @param [Array[String]] lines
|
@@ -272,30 +291,59 @@ module TTY
|
|
272
291
|
# @api private
|
273
292
|
def infer_dimensions(lines, padding)
|
274
293
|
pad = Strings::Padder.parse(padding)
|
275
|
-
|
276
|
-
|
277
|
-
width = pad.left + content_width + pad.right
|
278
|
-
height = pad.top + content_height + pad.bottom
|
294
|
+
width = pad.left + content_width(lines) + pad.right
|
295
|
+
height = pad.top + lines.size + pad.bottom
|
279
296
|
[width, height]
|
280
297
|
end
|
298
|
+
private_class_method :infer_dimensions
|
281
299
|
|
282
|
-
#
|
300
|
+
# The maximum content width for all the lines
|
301
|
+
#
|
302
|
+
# @param [Array<String>] lines
|
303
|
+
#
|
304
|
+
# @return [Integer]
|
305
|
+
#
|
306
|
+
# @api private
|
307
|
+
def content_width(lines)
|
308
|
+
return 1 if lines.empty?
|
309
|
+
|
310
|
+
lines.map(&Strings::ANSI.method(:sanitize)).max_by(&:length).length
|
311
|
+
end
|
312
|
+
private_class_method :content_width
|
313
|
+
|
314
|
+
# Format content by wrapping, aligning and padding out
|
315
|
+
#
|
316
|
+
# @param [Array<String>] lines
|
317
|
+
# the lines to format
|
318
|
+
# @param [Integer] width
|
319
|
+
# the maximum width
|
320
|
+
# @param [Integer, Array<Integer>] padding
|
321
|
+
# the amount of padding
|
322
|
+
# @param [Symbol] align
|
323
|
+
# the type of alignment
|
324
|
+
# @param [String] separator
|
325
|
+
# the newline separator
|
283
326
|
#
|
284
327
|
# @return [Array[String]]
|
285
328
|
#
|
286
329
|
# @api private
|
287
|
-
def format(
|
288
|
-
return
|
330
|
+
def format(lines, width, padding, align, separator)
|
331
|
+
return [] if lines.empty?
|
289
332
|
|
290
333
|
pad = Strings::Padder.parse(padding)
|
291
334
|
total_width = width - 2 - (pad.left + pad.right)
|
292
|
-
sep = content[LINE_BREAK] || NEWLINE # infer line break
|
293
335
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
336
|
+
formatted = lines.each_with_object([]) do |line, acc|
|
337
|
+
wrapped = Strings::Wrap.wrap(line, total_width, separator: separator)
|
338
|
+
acc << Strings::Align.align(wrapped, total_width,
|
339
|
+
direction: align,
|
340
|
+
separator: separator)
|
341
|
+
end.join(separator)
|
342
|
+
|
343
|
+
Strings::Pad.pad(formatted, padding, separator: separator)
|
344
|
+
.split(separator)
|
298
345
|
end
|
346
|
+
private_class_method :format
|
299
347
|
|
300
348
|
# Convert style keywords into styling
|
301
349
|
#
|
@@ -303,10 +351,11 @@ module TTY
|
|
303
351
|
#
|
304
352
|
# @api private
|
305
353
|
def extract_style(style)
|
306
|
-
fg = style[:fg] ? color.send(style[:fg]).detach : ->
|
307
|
-
bg = style[:bg] ? color.send(:"on_#{style[:bg]}").detach : ->
|
354
|
+
fg = style[:fg] ? color.send(style[:fg]).detach : ->(c) { c }
|
355
|
+
bg = style[:bg] ? color.send(:"on_#{style[:bg]}").detach : ->(c) { c }
|
308
356
|
[fg, bg]
|
309
357
|
end
|
358
|
+
private_class_method :extract_style
|
310
359
|
|
311
360
|
# Top space taken by titles and corners
|
312
361
|
#
|
@@ -314,26 +363,39 @@ module TTY
|
|
314
363
|
#
|
315
364
|
# @api private
|
316
365
|
def top_space_taken(title, border)
|
317
|
-
top_titles_size(title) +
|
366
|
+
top_titles_size(title) +
|
367
|
+
top_left_corner(border).size +
|
368
|
+
top_right_corner(border).size
|
318
369
|
end
|
370
|
+
private_class_method :top_space_taken
|
319
371
|
|
320
372
|
# Top left corner
|
321
373
|
#
|
374
|
+
# @param [Border] border
|
375
|
+
#
|
322
376
|
# @return [String]
|
323
377
|
#
|
324
378
|
# @api private
|
325
379
|
def top_left_corner(border)
|
326
|
-
border.top_left? && border.left?
|
380
|
+
return "" unless border.top_left? && border.left?
|
381
|
+
|
382
|
+
send(:"#{border.top_left}_char", border.type)
|
327
383
|
end
|
384
|
+
private_class_method :top_left_corner
|
328
385
|
|
329
386
|
# Top right corner
|
330
387
|
#
|
388
|
+
# @param [Border] border
|
389
|
+
#
|
331
390
|
# @return [String]
|
332
391
|
#
|
333
392
|
# @api private
|
334
393
|
def top_right_corner(border)
|
335
|
-
border.top_right? && border.right?
|
394
|
+
return "" unless border.top_right? && border.right?
|
395
|
+
|
396
|
+
send(:"#{border.top_right}_char", border.type)
|
336
397
|
end
|
398
|
+
private_class_method :top_right_corner
|
337
399
|
|
338
400
|
# Top titles size
|
339
401
|
#
|
@@ -341,8 +403,11 @@ module TTY
|
|
341
403
|
#
|
342
404
|
# @api private
|
343
405
|
def top_titles_size(title)
|
344
|
-
title[:top_left].to_s.size +
|
406
|
+
color.strip(title[:top_left].to_s).size +
|
407
|
+
color.strip(title[:top_center].to_s).size +
|
408
|
+
color.strip(title[:top_right].to_s).size
|
345
409
|
end
|
410
|
+
private_class_method :top_titles_size
|
346
411
|
|
347
412
|
# Top border
|
348
413
|
#
|
@@ -364,34 +429,49 @@ module TTY
|
|
364
429
|
bg.(fg.(line_char(border.type) * top_space_after)),
|
365
430
|
bg.(fg.(title[:top_right].to_s)),
|
366
431
|
bg.(fg.(top_right_corner(border)))
|
367
|
-
].join
|
432
|
+
].join
|
368
433
|
end
|
434
|
+
private_class_method :top_border
|
435
|
+
|
369
436
|
# Bottom space taken by titles and corners
|
370
437
|
#
|
371
438
|
# @return [Integer]
|
372
439
|
#
|
373
440
|
# @api private
|
374
441
|
def bottom_space_taken(title, border)
|
375
|
-
bottom_titles_size(title) +
|
442
|
+
bottom_titles_size(title) +
|
443
|
+
bottom_left_corner(border).size +
|
444
|
+
bottom_right_corner(border).size
|
376
445
|
end
|
446
|
+
private_class_method :bottom_space_taken
|
377
447
|
|
378
448
|
# Bottom left corner
|
379
449
|
#
|
450
|
+
# @param [Border] border
|
451
|
+
#
|
380
452
|
# @return [String]
|
381
453
|
#
|
382
454
|
# @api private
|
383
455
|
def bottom_left_corner(border)
|
384
|
-
border.bottom_left? && border.left?
|
456
|
+
return "" unless border.bottom_left? && border.left?
|
457
|
+
|
458
|
+
send(:"#{border.bottom_left}_char", border.type)
|
385
459
|
end
|
460
|
+
private_class_method :bottom_left_corner
|
386
461
|
|
387
462
|
# Bottom right corner
|
388
463
|
#
|
464
|
+
# @param [Border] border
|
465
|
+
#
|
389
466
|
# @return [String]
|
390
467
|
#
|
391
468
|
# @api private
|
392
469
|
def bottom_right_corner(border)
|
393
|
-
border.bottom_right? && border.right?
|
470
|
+
return "" unless border.bottom_right? && border.right?
|
471
|
+
|
472
|
+
send(:"#{border.bottom_right}_char", border.type)
|
394
473
|
end
|
474
|
+
private_class_method :bottom_right_corner
|
395
475
|
|
396
476
|
# Bottom titles size
|
397
477
|
#
|
@@ -399,8 +479,11 @@ module TTY
|
|
399
479
|
#
|
400
480
|
# @api private
|
401
481
|
def bottom_titles_size(title)
|
402
|
-
title[:bottom_left].to_s.size +
|
482
|
+
color.strip(title[:bottom_left].to_s).size +
|
483
|
+
color.strip(title[:bottom_center].to_s).size +
|
484
|
+
color.strip(title[:bottom_right].to_s).size
|
403
485
|
end
|
486
|
+
private_class_method :bottom_titles_size
|
404
487
|
|
405
488
|
# Bottom border
|
406
489
|
#
|
@@ -422,7 +505,8 @@ module TTY
|
|
422
505
|
bg.(fg.(line_char(border.type) * bottom_space_after)),
|
423
506
|
bg.(fg.(title[:bottom_right].to_s)),
|
424
507
|
bg.(fg.(bottom_right_corner(border)))
|
425
|
-
].join
|
508
|
+
].join
|
426
509
|
end
|
510
|
+
private_class_method :bottom_border
|
427
511
|
end # TTY
|
428
512
|
end # Box
|
data/lib/tty/box/border.rb
CHANGED
@@ -6,18 +6,18 @@ module TTY
|
|
6
6
|
#
|
7
7
|
# @api private
|
8
8
|
class Border
|
9
|
-
BORDER_VALUES = [
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
9
|
+
BORDER_VALUES = %i[
|
10
|
+
corner_bottom_right
|
11
|
+
corner_top_right
|
12
|
+
corner_top_left
|
13
|
+
corner_bottom_left
|
14
|
+
divider_left
|
15
|
+
divider_up
|
16
|
+
divider_down
|
17
|
+
divider_right
|
18
|
+
line
|
19
|
+
pipe
|
20
|
+
cross
|
21
21
|
].freeze
|
22
22
|
|
23
23
|
def self.parse(border)
|
@@ -68,11 +68,17 @@ module TTY
|
|
68
68
|
private
|
69
69
|
|
70
70
|
# Check if border values name is allowed
|
71
|
+
#
|
72
|
+
# @raise [ArgumentError]
|
73
|
+
#
|
71
74
|
# @api private
|
72
75
|
def check_name(key, value)
|
73
|
-
unless
|
74
|
-
|
76
|
+
unless BORDER_VALUES.include?(:"#{value}") ||
|
77
|
+
[true, false].include?(value)
|
78
|
+
raise ArgumentError, "invalid #{key.inspect} border value: " \
|
79
|
+
"#{value.inspect}"
|
75
80
|
end
|
81
|
+
|
76
82
|
value
|
77
83
|
end
|
78
84
|
end # Border
|
data/lib/tty/box/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tty-box
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pastel
|