customization 1.0.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 +7 -0
- data/lib/customization.rb +320 -0
- data/lib/errors.rb +61 -0
- metadata +46 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b5964699612cdc7dd15e9a0675e07875216e03db10720f389325d93fdd88e9ab
|
|
4
|
+
data.tar.gz: b88e61a0bac781d682726e482bdc1a35e8aee9c5bb0257e69c88f4fb0b22de8f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e76e80e2f95ef60d55e81b7d9097069fe49c842994d1d8d90ceb3c3f59f843fb1ef4e9b0aa23e56a51611745485eceadd11ef79d242399656670875164a51d5d
|
|
7
|
+
data.tar.gz: e7a2dcd6e4807a43db69a2686ccf4ede439bfc4099b741a81db38d7081b955e8be5a6fddc4d3daef8fedaf7773cca8e89fcc4db2d2751ef90aee39de2654643f
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# customization.rb
|
|
2
|
+
|
|
3
|
+
module Customization
|
|
4
|
+
COLORS = {
|
|
5
|
+
black: "\e[30m",
|
|
6
|
+
red: "\e[31m",
|
|
7
|
+
green: "\e[32m",
|
|
8
|
+
yellow: "\e[33m",
|
|
9
|
+
blue: "\e[34m",
|
|
10
|
+
magenta: "\e[35m",
|
|
11
|
+
cyan: "\e[36m",
|
|
12
|
+
white: "\e[37m",
|
|
13
|
+
bright_black: "\e[90m",
|
|
14
|
+
bright_red: "\e[91m",
|
|
15
|
+
bright_green: "\e[92m",
|
|
16
|
+
bright_yellow: "\e[93m",
|
|
17
|
+
bright_blue: "\e[94m",
|
|
18
|
+
bright_magenta: "\e[95m",
|
|
19
|
+
bright_cyan: "\e[96m",
|
|
20
|
+
bright_white: "\e[97m",
|
|
21
|
+
gray: "\e[38;5;236m",
|
|
22
|
+
light_red: "\e[38;5;196m",
|
|
23
|
+
light_green: "\e[38;5;118m",
|
|
24
|
+
light_yellow: "\e[38;5;226m",
|
|
25
|
+
light_blue: "\e[38;5;69m",
|
|
26
|
+
light_magenta: "\e[38;5;201m",
|
|
27
|
+
light_cyan: "\e[38;5;87m",
|
|
28
|
+
light_gray: "\e[38;5;248m",
|
|
29
|
+
dark_gray: "\e[38;5;235m",
|
|
30
|
+
purple: "\e[38;5;141m",
|
|
31
|
+
orange: "\e[38;5;208m",
|
|
32
|
+
pink: "\e[38;5;200m",
|
|
33
|
+
teal: "\e[38;5;30m",
|
|
34
|
+
lime: "\e[38;5;154m",
|
|
35
|
+
brown: "\e[38;5;130m",
|
|
36
|
+
navy: "\e[38;5;18m",
|
|
37
|
+
olive: "\e[38;5;100m",
|
|
38
|
+
maroon: "\e[38;5;52m",
|
|
39
|
+
indigo: "\e[38;5;54m",
|
|
40
|
+
violet: "\e[38;5;92m",
|
|
41
|
+
turquoise: "\e[38;5;45m",
|
|
42
|
+
gold: "\e[38;5;178m",
|
|
43
|
+
silver: "\e[38;5;249m",
|
|
44
|
+
lavender: "\e[38;5;183m",
|
|
45
|
+
plum: "\e[38;5;182m",
|
|
46
|
+
rose: "\e[38;5;197m",
|
|
47
|
+
coral: "\e[38;5;210m",
|
|
48
|
+
peach: "\e[38;5;203m",
|
|
49
|
+
salmon: "\e[38;5;204m",
|
|
50
|
+
apricot: "\e[38;5;222m",
|
|
51
|
+
tangerine: "\e[38;5;214m",
|
|
52
|
+
pumpkin: "\e[38;5;166m",
|
|
53
|
+
cinnamon: "\e[38;5;166m",
|
|
54
|
+
chocolate: "\e[38;5;52m",
|
|
55
|
+
coffee: "\e[38;5;130m",
|
|
56
|
+
mahogany: "\e[38;5;94m",
|
|
57
|
+
olive_green: "\e[38;5;107m",
|
|
58
|
+
forest_green: "\e[38;5;28m",
|
|
59
|
+
emerald: "\e[38;5;46m",
|
|
60
|
+
mint: "\e[38;5;121m",
|
|
61
|
+
turquoise_blue: "\e[38;5;45m",
|
|
62
|
+
aqua: "\e[38;5;51m",
|
|
63
|
+
sky_blue: "\e[38;5;111m",
|
|
64
|
+
baby_blue: "\e[38;5;153m",
|
|
65
|
+
lavender_blue: "\e[38;5;105m",
|
|
66
|
+
periwinkle: "\e[38;5;182m",
|
|
67
|
+
steel_blue: "\e[38;5;67m",
|
|
68
|
+
royal_blue: "\e[38;5;21m",
|
|
69
|
+
navy_blue: "\e[38;5;18m",
|
|
70
|
+
sapphire: "\e[38;5;20m",
|
|
71
|
+
cobalt: "\e[38;5;18m",
|
|
72
|
+
iris: "\e[38;5;135m",
|
|
73
|
+
orchid: "\e[38;5;170m",
|
|
74
|
+
fuchsia: "\e[38;5;13m",
|
|
75
|
+
raspberry: "\e[38;5;161m",
|
|
76
|
+
cherry: "\e[38;5;160m",
|
|
77
|
+
wine: "\e[38;5;88m",
|
|
78
|
+
scarlet: "\e[38;5;196m",
|
|
79
|
+
brick_red: "\e[38;5;124m",
|
|
80
|
+
rust: "\e[38;5;166m",
|
|
81
|
+
sienna: "\e[38;5;95m",
|
|
82
|
+
sepia: "\e[38;5;130m",
|
|
83
|
+
taupe: "\e[38;5;101m",
|
|
84
|
+
stone: "\e[38;5;102m",
|
|
85
|
+
charcoal: "\e[38;5;236m",
|
|
86
|
+
ruby: "\e[38;5;196m",
|
|
87
|
+
onyx: "\e[38;5;16m",
|
|
88
|
+
opal: "\e[38;5;155m",
|
|
89
|
+
peridot: "\e[38;5;112m",
|
|
90
|
+
citrine: "\e[38;5;172m",
|
|
91
|
+
topaz: "\e[38;5;220m",
|
|
92
|
+
aquamarine: "\e[38;5;87m",
|
|
93
|
+
bronze: "\e[38;5;101m",
|
|
94
|
+
platinum: "\e[38;5;238m",
|
|
95
|
+
pewter: "\e[38;5;245m",
|
|
96
|
+
brass: "\e[38;5;180m",
|
|
97
|
+
lavender_purple: "\e[38;5;183m",
|
|
98
|
+
lilac: "\e[38;5;208m",
|
|
99
|
+
amaranth: "\e[38;5;203m",
|
|
100
|
+
marigold: "\e[38;5;204m",
|
|
101
|
+
olive_drab: "\e[38;5;222m",
|
|
102
|
+
chartreuse: "\e[38;5;214m",
|
|
103
|
+
butterscotch: "\e[38;5;166m",
|
|
104
|
+
caramel: "\e[38;5;166m",
|
|
105
|
+
hazelnut: "\e[38;5;52m",
|
|
106
|
+
espresso: "\e[38;5;130m",
|
|
107
|
+
walnut: "\e[38;5;94m",
|
|
108
|
+
moss_green: "\e[38;5;107m",
|
|
109
|
+
pine_green: "\e[38;5;28m",
|
|
110
|
+
jade: "\e[38;5;46m",
|
|
111
|
+
pistachio: "\e[38;5;121m",
|
|
112
|
+
teal_green: "\e[38;5;45m",
|
|
113
|
+
ocean_blue: "\e[38;5;51m",
|
|
114
|
+
azure: "\e[38;5;111m",
|
|
115
|
+
powder_blue: "\e[38;5;153m",
|
|
116
|
+
periwinkle_blue: "\e[38;5;105m",
|
|
117
|
+
lavender_mist: "\e[38;5;182m",
|
|
118
|
+
slate_blue: "\e[38;5;67m",
|
|
119
|
+
midnight_blue: "\e[38;5;21m",
|
|
120
|
+
deep_navy: "\e[38;5;18m",
|
|
121
|
+
cobalt_blue: "\e[38;5;20m",
|
|
122
|
+
sapphire_blue: "\e[38;5;18m",
|
|
123
|
+
cerulean: "\e[38;5;54m",
|
|
124
|
+
amethyst: "\e[38;5;135m",
|
|
125
|
+
raspberry_pink: "\e[38;5;161m",
|
|
126
|
+
cherry_red: "\e[38;5;160m",
|
|
127
|
+
wine_red: "\e[38;5;88m",
|
|
128
|
+
scarlet_red: "\e[38;5;196m",
|
|
129
|
+
brick_orange: "\e[38;5;124m",
|
|
130
|
+
rust_brown: "\e[38;5;166m",
|
|
131
|
+
sienna_brown: "\e[38;5;95m",
|
|
132
|
+
sepia_brown: "\e[38;5;130m",
|
|
133
|
+
taupe_brown: "\e[38;5;101m",
|
|
134
|
+
stone_gray: "\e[38;5;102m",
|
|
135
|
+
charcoal_gray: "\e[38;5;236m",
|
|
136
|
+
ruby_red: "\e[38;5;196m",
|
|
137
|
+
emerald_green: "\e[38;5;46m",
|
|
138
|
+
garnet_red: "\e[38;5;52m",
|
|
139
|
+
onyx_black: "\e[38;5;16m",
|
|
140
|
+
opal_white: "\e[38;5;155m",
|
|
141
|
+
amethyst_purple: "\e[38;5;127m",
|
|
142
|
+
peridot_green: "\e[38;5;112m",
|
|
143
|
+
citrine_yellow: "\e[38;5;172m",
|
|
144
|
+
topaz_yellow: "\e[38;5;220m",
|
|
145
|
+
aquamarine_blue: "\e[38;5;87m",
|
|
146
|
+
bronze_brown: "\e[38;5;101m",
|
|
147
|
+
platinum_gray: "\e[38;5;238m",
|
|
148
|
+
pewter_gray: "\e[38;5;245m",
|
|
149
|
+
brass_gold: "\e[38;5;180m"
|
|
150
|
+
}.freeze
|
|
151
|
+
|
|
152
|
+
FORMATS = {
|
|
153
|
+
bold: "\e[1m",
|
|
154
|
+
italic: "\e[3m",
|
|
155
|
+
underline: "\e[4m",
|
|
156
|
+
strikethrough: "\e[9m",
|
|
157
|
+
reset: "\e[0m",
|
|
158
|
+
reverse: "\e[7m", # Reverse video (swap foreground and background colors)
|
|
159
|
+
invisible: "\e[8m", # Make text invisible (usually not visible, but can be used for certain effects)
|
|
160
|
+
blink_fast: "\e[6m", # Fast blinking text effect
|
|
161
|
+
conceal: "\e[8m", # Conceal text (hide it)
|
|
162
|
+
blink_slow: "\e[5m", # Slow blinking text effect
|
|
163
|
+
double_underline: "\e[21m", # Double underline
|
|
164
|
+
}.freeze
|
|
165
|
+
|
|
166
|
+
BORDERS = {
|
|
167
|
+
single: "\u2500" * 30, # Single horizontal line
|
|
168
|
+
double: "\u2550" * 30, # Double horizontal line
|
|
169
|
+
thick: "\u2501" * 30, # Thick horizontal line
|
|
170
|
+
rounded: "\u256D" * 30, # Rounded border
|
|
171
|
+
dashed: "\u2504" * 30, # Dashed border
|
|
172
|
+
dotted: "\u2508" * 30, # Dotted border
|
|
173
|
+
heavy_rounded: "\u256E" * 30, # Another rounded border style
|
|
174
|
+
wave: "\u223D" * 30, # Wave border
|
|
175
|
+
zigzag: "\u224B" * 30, # Zigzag border
|
|
176
|
+
stars: "\u272D" * 30, # Stars border
|
|
177
|
+
arrows: "\u2192" * 30, # Arrows border
|
|
178
|
+
double_line: "\u2551" * 30, # Double vertical line
|
|
179
|
+
}.freeze
|
|
180
|
+
|
|
181
|
+
TEXT_EFFECTS = {
|
|
182
|
+
shadow: "\e[2m", # Text shadow effect
|
|
183
|
+
blink: "\e[5m", # Blinking text effect
|
|
184
|
+
opacity: "\e[30;40m", # Adjust text opacity (foreground and background colors)
|
|
185
|
+
}.freeze
|
|
186
|
+
|
|
187
|
+
def self.color_text(text, color)
|
|
188
|
+
unless COLORS.key?(color)
|
|
189
|
+
raise InvalidColorError.new(color)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
"#{COLORS[color]}#{text}#{FORMATS[:reset]}"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def self.format_text(text, format)
|
|
196
|
+
unless FORMATS.key?(format)
|
|
197
|
+
raise InvalidFormatError.new(format)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
"#{FORMATS[format]}#{text}#{FORMATS[:reset]}"
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def self.visible_length(text)
|
|
204
|
+
text.gsub(/\e\[\d+(;\d+)*m/, '').length
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def self.center_text(text, width)
|
|
208
|
+
padding = [(width - visible_length(text)) / 2, 0].max
|
|
209
|
+
' ' * padding + text + ' ' * padding
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def self.left_align(text, width)
|
|
213
|
+
text + ' ' * [width - visible_length(text), 0].max
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def self.right_align(text, width)
|
|
217
|
+
' ' * [width - visible_length(text), 0].max + text
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def self.justify_text(text, width)
|
|
221
|
+
words = text.split
|
|
222
|
+
return text if words.length == 1
|
|
223
|
+
|
|
224
|
+
total_space = width - visible_length(text)
|
|
225
|
+
space_between_words = (total_space / (words.length - 1)).to_i
|
|
226
|
+
|
|
227
|
+
justified_text = words.join(" " * space_between_words)
|
|
228
|
+
extra_space = total_space % (words.length - 1)
|
|
229
|
+
|
|
230
|
+
justified_text + ' ' * extra_space
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def self.set_text_border(text, border)
|
|
234
|
+
unless BORDERS.key?(border)
|
|
235
|
+
raise InvalidBorderError.new(border)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
"#{BORDERS[border]}#{text}#{BORDERS[border]}"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def self.underline_text(text)
|
|
242
|
+
"#{FORMATS[:underline]}#{text}#{FORMATS[:reset]}"
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def self.strikethrough_text(text)
|
|
246
|
+
"#{FORMATS[:strikethrough]}#{text}#{FORMATS[:reset]}"
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def self.apply_text_shadow(text)
|
|
250
|
+
"#{TEXT_EFFECTS[:shadow]}#{text}#{FORMATS[:reset]}"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def self.apply_blinking_effect(text)
|
|
254
|
+
"#{TEXT_EFFECTS[:blink]}#{text}#{FORMATS[:reset]}"
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def self.color_text(text, color, custom_code = nil)
|
|
258
|
+
if COLORS.key?(color)
|
|
259
|
+
"#{COLORS[color]}#{text}#{FORMATS[:reset]}"
|
|
260
|
+
elsif custom_code
|
|
261
|
+
"#{custom_code}#{text}#{FORMATS[:reset]}"
|
|
262
|
+
else
|
|
263
|
+
raise InvalidColorError.new(color)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def self.adjust_text_opacity(text)
|
|
268
|
+
"#{TEXT_EFFECTS[:opacity]}#{text}#{FORMATS[:reset]}"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def self.gradient_text(text, colors)
|
|
272
|
+
unless colors.is_a?(Array) && colors.length >= 2
|
|
273
|
+
raise ArgumentError, "Gradient text requires at least two colors"
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
color_count = colors.length
|
|
277
|
+
step_size = 100.0 / (color_count - 1)
|
|
278
|
+
gradient = ""
|
|
279
|
+
|
|
280
|
+
text.each_char.with_index do |char, index|
|
|
281
|
+
color_index = (step_size * index / 100).round
|
|
282
|
+
color = colors[color_index]
|
|
283
|
+
gradient += "#{COLORS[color]}#{char}"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
gradient + FORMATS[:reset]
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def self.set_text_border(text, border)
|
|
290
|
+
unless BORDERS.key?(border)
|
|
291
|
+
raise InvalidBorderError.new(border)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
"#{BORDERS[border]}#{text}#{BORDERS[border]}"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def self.text_with_shadow(text, shadow_color, blur_radius, x_offset, y_offset)
|
|
298
|
+
shadow = "\e[38;2;#{shadow_color[:r]};#{shadow_color[:g]};#{shadow_color[:b]};48;2;#{shadow_color[:r]};#{shadow_color[:g]};#{shadow_color[:b]}m"
|
|
299
|
+
"#{shadow}#{text}#{FORMATS[:reset]}"
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def self.wrap_text(text, width)
|
|
303
|
+
lines = []
|
|
304
|
+
current_line = ''
|
|
305
|
+
|
|
306
|
+
words = text.split(/\s+/)
|
|
307
|
+
|
|
308
|
+
words.each do |word|
|
|
309
|
+
if visible_length(current_line + word) <= width
|
|
310
|
+
current_line += word + ' '
|
|
311
|
+
else
|
|
312
|
+
lines << current_line.rstrip
|
|
313
|
+
current_line = word + ' '
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
lines << current_line.rstrip if current_line != ''
|
|
318
|
+
lines.join("\n")
|
|
319
|
+
end
|
|
320
|
+
end
|
data/lib/errors.rb
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# errors.rb
|
|
2
|
+
|
|
3
|
+
module Customization
|
|
4
|
+
class InvalidColorError < StandardError
|
|
5
|
+
def initialize(color)
|
|
6
|
+
super("Invalid color: #{color}")
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class InvalidFormatError < StandardError
|
|
11
|
+
def initialize(format)
|
|
12
|
+
super("Invalid format: #{format}")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class InvalidFontSizeError < StandardError
|
|
17
|
+
def initialize(size)
|
|
18
|
+
super("Invalid font size: #{size}")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class InvalidBorderError < StandardError
|
|
23
|
+
def initialize(border)
|
|
24
|
+
super("Invalid text border style: #{border}")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class InvalidTextEffectError < StandardError
|
|
29
|
+
def initialize(effect)
|
|
30
|
+
super("Invalid text effect: #{effect}")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class InvalidLetterSpacingError < StandardError
|
|
35
|
+
def initialize(spacing)
|
|
36
|
+
super("Invalid letter spacing value: #{spacing}")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class InvalidLineSpacingError < StandardError
|
|
41
|
+
def initialize(spacing)
|
|
42
|
+
super("Invalid line spacing value: #{spacing}")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class InvalidTextShadowError < StandardError
|
|
47
|
+
def initialize(shadow)
|
|
48
|
+
super("Invalid text shadow: #{shadow}")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class InvalidBlinkingEffectError < StandardError
|
|
53
|
+
def initialize
|
|
54
|
+
super("Blinking effect is not supported in some environments.")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class InvalidTextOpacityError < StandardError
|
|
59
|
+
def initialize(opacity)
|
|
60
|
+
super("Invalid text opacity value: #{opacity}")
|
|
61
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: customization
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ThatAlecs
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2023-10-11 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Customization is a library for customizing text with various effects
|
|
14
|
+
and colors.
|
|
15
|
+
email:
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- lib/customization.rb
|
|
21
|
+
- lib/errors.rb
|
|
22
|
+
homepage: https://github.com/thatalecs/customizationrb
|
|
23
|
+
licenses:
|
|
24
|
+
- MIT
|
|
25
|
+
metadata:
|
|
26
|
+
source_code_uri: https://github.com/thatalecs/customizationrb
|
|
27
|
+
post_install_message:
|
|
28
|
+
rdoc_options: []
|
|
29
|
+
require_paths:
|
|
30
|
+
- test
|
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
32
|
+
requirements:
|
|
33
|
+
- - ">="
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: '0'
|
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
requirements: []
|
|
42
|
+
rubygems_version: 3.4.20
|
|
43
|
+
signing_key:
|
|
44
|
+
specification_version: 4
|
|
45
|
+
summary: A Ruby library for text customization using ANSI escape codes
|
|
46
|
+
test_files: []
|