rainbow 3.1.0 → 3.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a63baad6cad3bf3127e8dfbfb9393f05b6a92122af6f1fd7b3cf5ffe44b4e05
4
- data.tar.gz: 8db71093ce37873fa8b009981488cce3ee63cfad85365dd96f416dc4790d4d97
3
+ metadata.gz: 7367f9386ef2460491f123bd207091956c6dcce6300dcf3957a48c126a1ec900
4
+ data.tar.gz: 1c123ecd4c6ee30422ff9df560df3ec4f5d4c8bcb6010e3a0c5be4435848894a
5
5
  SHA512:
6
- metadata.gz: c5d8c29b3d25fcc2a85919143a628e2de3250beb08ec10c228c5fe2b759af567b962e9c78b65bc9fc39db33b643af4556cb05565e45027f25695e2ee1275a115
7
- data.tar.gz: 2872ac2c71afebbfb362b86e93f03b3b7b0fe376497fdcd4ce4ce296fa03be4521ca0ed84de3ef24228783842bdff17f4ce3c2f79ad4cfe6faa9896b25e229af
6
+ metadata.gz: 64ddf54fa7edd4f0f05301270503025bfb63cbca6db7e940b4cf6c62cbd860b3cf939c885f5e69becd1f4faf39c9d2fe1e8a35597dd28fe1b30df26e52f334f0
7
+ data.tar.gz: 74550a67235dcca95dbd6404023576843e626e0ec00e557c0e38fbd145f778983b6c63136008d39da958a4fc83dc73e7a62758a40c8ead76c24066e968b66b6e
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rainbow
4
+ class Color
5
+ attr_reader :ground
6
+
7
+ def self.build(ground, values)
8
+ unless [1, 3].include?(values.size)
9
+ raise ArgumentError,
10
+ "Wrong number of arguments for color definition, should be 1 or 3"
11
+ end
12
+
13
+ color = values.size == 1 ? values.first : values
14
+
15
+ case color
16
+ # NOTE: Properly handle versions before/after Ruby 2.4.0.
17
+ # Ruby 2.4+ unifies Fixnum & Bignum into Integer.
18
+ # However previous versions would still use Fixnum.
19
+ # To avoid missing `Fixnum` input, call `0.class` which would
20
+ # return either `Integer` or `Fixnum`.
21
+ when 0.class
22
+ Indexed.new(ground, color)
23
+ when Symbol
24
+ if Named.color_names.include?(color)
25
+ Named.new(ground, color)
26
+ elsif X11Named.color_names.include?(color)
27
+ X11Named.new(ground, color)
28
+ else
29
+ raise ArgumentError,
30
+ "Unknown color name, valid names: " +
31
+ (Named.color_names + X11Named.color_names).join(', ')
32
+ end
33
+ when Array
34
+ RGB.new(ground, *color)
35
+ when String
36
+ RGB.new(ground, *parse_hex_color(color))
37
+ end
38
+ end
39
+
40
+ def self.parse_hex_color(hex)
41
+ unless hex =~ /^#?[a-f0-9]{6}/i
42
+ raise ArgumentError,
43
+ "Invalid hexadecimal RGB triplet. Valid format: /^#?[a-f0-9]{6}/i"
44
+ end
45
+
46
+ hex = hex.sub(/^#/, '')
47
+ r = hex[0..1].to_i(16)
48
+ g = hex[2..3].to_i(16)
49
+ b = hex[4..5].to_i(16)
50
+
51
+ [r, g, b]
52
+ end
53
+
54
+ class Indexed < Color
55
+ attr_reader :num
56
+
57
+ def initialize(ground, num)
58
+ @ground = ground
59
+ @num = num
60
+ end
61
+
62
+ def codes
63
+ code = num + (ground == :foreground ? 30 : 40)
64
+
65
+ [code]
66
+ end
67
+ end
68
+
69
+ class Named < Indexed
70
+ NAMES = {
71
+ black: 0,
72
+ red: 1,
73
+ green: 2,
74
+ yellow: 3,
75
+ blue: 4,
76
+ magenta: 5,
77
+ cyan: 6,
78
+ white: 7,
79
+ default: 9
80
+ }.freeze
81
+
82
+ def self.color_names
83
+ NAMES.keys
84
+ end
85
+
86
+ def self.valid_names
87
+ color_names.join(', ')
88
+ end
89
+
90
+ def initialize(ground, name)
91
+ unless Named.color_names.include?(name)
92
+ raise ArgumentError,
93
+ "Unknown color name, valid names: #{self.class.valid_names}"
94
+ end
95
+
96
+ super(ground, NAMES[name])
97
+ end
98
+ end
99
+
100
+ class RGB < Indexed
101
+ attr_reader :r, :g, :b
102
+
103
+ def self.to_ansi_domain(value)
104
+ (6 * (value / 256.0)).to_i
105
+ end
106
+
107
+ def initialize(ground, *values)
108
+ if values.min.negative? || values.max > 255
109
+ raise ArgumentError, "RGB value outside 0-255 range"
110
+ end
111
+
112
+ super(ground, 8)
113
+ @r, @g, @b = values
114
+ end
115
+
116
+ def codes
117
+ super + [5, code_from_rgb]
118
+ end
119
+
120
+ private
121
+
122
+ def code_from_rgb
123
+ 16 + self.class.to_ansi_domain(r) * 36 +
124
+ self.class.to_ansi_domain(g) * 6 +
125
+ self.class.to_ansi_domain(b)
126
+ end
127
+ end
128
+
129
+ class X11Named < RGB
130
+ include X11ColorNames
131
+
132
+ def self.color_names
133
+ NAMES.keys
134
+ end
135
+
136
+ def self.valid_names
137
+ color_names.join(', ')
138
+ end
139
+
140
+ def initialize(ground, name)
141
+ unless X11Named.color_names.include?(name)
142
+ raise ArgumentError,
143
+ "Unknown color name, valid names: #{self.class.valid_names}"
144
+ end
145
+
146
+ super(ground, *NAMES[name])
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rainbow'
4
+
5
+ module Rainbow
6
+ module Ext
7
+ module String
8
+ module InstanceMethods
9
+ def foreground(*color)
10
+ Rainbow(self).foreground(*color)
11
+ end
12
+
13
+ alias color foreground
14
+ alias colour foreground
15
+
16
+ def background(*color)
17
+ Rainbow(self).background(*color)
18
+ end
19
+
20
+ def reset
21
+ Rainbow(self).reset
22
+ end
23
+
24
+ def bright
25
+ Rainbow(self).bright
26
+ end
27
+
28
+ def faint
29
+ Rainbow(self).faint
30
+ end
31
+
32
+ def italic
33
+ Rainbow(self).italic
34
+ end
35
+
36
+ def underline
37
+ Rainbow(self).underline
38
+ end
39
+
40
+ def blink
41
+ Rainbow(self).blink
42
+ end
43
+
44
+ def inverse
45
+ Rainbow(self).inverse
46
+ end
47
+
48
+ def hide
49
+ Rainbow(self).hide
50
+ end
51
+
52
+ def cross_out
53
+ Rainbow(self).cross_out
54
+ end
55
+
56
+ alias strike cross_out
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ class String
63
+ include Rainbow::Ext::String::InstanceMethods
64
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'wrapper'
4
+
5
+ module Rainbow
6
+ def self.global
7
+ @global ||= Wrapper.new
8
+ end
9
+
10
+ def self.enabled
11
+ global.enabled
12
+ end
13
+
14
+ def self.enabled=(value)
15
+ global.enabled = value
16
+ end
17
+
18
+ def self.uncolor(string)
19
+ StringUtils.uncolor(string)
20
+ end
21
+ end
22
+
23
+ def Rainbow(string)
24
+ Rainbow.global.wrap(string.to_s)
25
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rainbow
4
+ class NullPresenter < ::String
5
+ def color(*_values)
6
+ self
7
+ end
8
+
9
+ def background(*_values)
10
+ self
11
+ end
12
+
13
+ def reset
14
+ self
15
+ end
16
+
17
+ def bright
18
+ self
19
+ end
20
+
21
+ def faint
22
+ self
23
+ end
24
+
25
+ def italic
26
+ self
27
+ end
28
+
29
+ def underline
30
+ self
31
+ end
32
+
33
+ def blink
34
+ self
35
+ end
36
+
37
+ def inverse
38
+ self
39
+ end
40
+
41
+ def hide
42
+ self
43
+ end
44
+
45
+ def cross_out
46
+ self
47
+ end
48
+
49
+ def black
50
+ self
51
+ end
52
+
53
+ def red
54
+ self
55
+ end
56
+
57
+ def green
58
+ self
59
+ end
60
+
61
+ def yellow
62
+ self
63
+ end
64
+
65
+ def blue
66
+ self
67
+ end
68
+
69
+ def magenta
70
+ self
71
+ end
72
+
73
+ def cyan
74
+ self
75
+ end
76
+
77
+ def white
78
+ self
79
+ end
80
+
81
+ def method_missing(method_name, *args)
82
+ if Color::X11Named.color_names.include?(method_name) && args.empty?
83
+ self
84
+ else
85
+ super
86
+ end
87
+ end
88
+
89
+ def respond_to_missing?(method_name, *args)
90
+ Color::X11Named.color_names.include?(method_name) && args.empty? || super
91
+ end
92
+
93
+ alias foreground color
94
+ alias fg color
95
+ alias bg background
96
+ alias bold bright
97
+ alias dark faint
98
+ alias strike cross_out
99
+ end
100
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'string_utils'
4
+ require_relative 'x11_color_names'
5
+ require_relative 'color'
6
+
7
+ module Rainbow
8
+ class Presenter < ::String
9
+ TERM_EFFECTS = {
10
+ reset: 0,
11
+ bright: 1,
12
+ faint: 2,
13
+ italic: 3,
14
+ underline: 4,
15
+ blink: 5,
16
+ inverse: 7,
17
+ hide: 8,
18
+ cross_out: 9
19
+ }.freeze
20
+
21
+ # Sets color of this text.
22
+ def color(*values)
23
+ wrap_with_sgr(Color.build(:foreground, values).codes)
24
+ end
25
+
26
+ alias foreground color
27
+ alias fg color
28
+
29
+ # Sets background color of this text.
30
+ def background(*values)
31
+ wrap_with_sgr(Color.build(:background, values).codes)
32
+ end
33
+
34
+ alias bg background
35
+
36
+ # Resets terminal to default colors/backgrounds.
37
+ #
38
+ # It shouldn't be needed to use this method because all methods
39
+ # append terminal reset code to end of string.
40
+ def reset
41
+ wrap_with_sgr(TERM_EFFECTS[:reset])
42
+ end
43
+
44
+ # Turns on bright/bold for this text.
45
+ def bright
46
+ wrap_with_sgr(TERM_EFFECTS[:bright])
47
+ end
48
+
49
+ alias bold bright
50
+
51
+ # Turns on faint/dark for this text (not well supported by terminal
52
+ # emulators).
53
+ def faint
54
+ wrap_with_sgr(TERM_EFFECTS[:faint])
55
+ end
56
+
57
+ alias dark faint
58
+
59
+ # Turns on italic style for this text (not well supported by terminal
60
+ # emulators).
61
+ def italic
62
+ wrap_with_sgr(TERM_EFFECTS[:italic])
63
+ end
64
+
65
+ # Turns on underline decoration for this text.
66
+ def underline
67
+ wrap_with_sgr(TERM_EFFECTS[:underline])
68
+ end
69
+
70
+ # Turns on blinking attribute for this text (not well supported by terminal
71
+ # emulators).
72
+ def blink
73
+ wrap_with_sgr(TERM_EFFECTS[:blink])
74
+ end
75
+
76
+ # Inverses current foreground/background colors.
77
+ def inverse
78
+ wrap_with_sgr(TERM_EFFECTS[:inverse])
79
+ end
80
+
81
+ # Hides this text (set its color to the same as background).
82
+ def hide
83
+ wrap_with_sgr(TERM_EFFECTS[:hide])
84
+ end
85
+
86
+ def cross_out
87
+ wrap_with_sgr(TERM_EFFECTS[:cross_out])
88
+ end
89
+
90
+ alias strike cross_out
91
+
92
+ def black
93
+ color(:black)
94
+ end
95
+
96
+ def red
97
+ color(:red)
98
+ end
99
+
100
+ def green
101
+ color(:green)
102
+ end
103
+
104
+ def yellow
105
+ color(:yellow)
106
+ end
107
+
108
+ def blue
109
+ color(:blue)
110
+ end
111
+
112
+ def magenta
113
+ color(:magenta)
114
+ end
115
+
116
+ def cyan
117
+ color(:cyan)
118
+ end
119
+
120
+ def white
121
+ color(:white)
122
+ end
123
+
124
+ # We take care of X11 color method call here.
125
+ # Such as #aqua, #ghostwhite.
126
+ def method_missing(method_name, *args)
127
+ if Color::X11Named.color_names.include?(method_name) && args.empty?
128
+ color(method_name)
129
+ else
130
+ super
131
+ end
132
+ end
133
+
134
+ def respond_to_missing?(method_name, *args)
135
+ Color::X11Named.color_names.include?(method_name) && args.empty? || super
136
+ end
137
+
138
+ private
139
+
140
+ def wrap_with_sgr(codes) #:nodoc:
141
+ self.class.new(StringUtils.wrap_with_sgr(self, [*codes]))
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'presenter'
4
+ require_relative 'global'
5
+
6
+ module Rainbow
7
+ refine String do
8
+ Presenter.instance_methods(false).each do |method_name|
9
+ define_method(method_name) do |*args|
10
+ ::Rainbow.global.wrap(self).send(method_name, *args)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rainbow
4
+ class StringUtils
5
+ def self.wrap_with_sgr(string, codes)
6
+ return string if codes.empty?
7
+
8
+ seq = "\e[" + codes.join(";") + "m"
9
+
10
+ string = string.sub(/^(\e\[([\d;]+)m)*/) { |m| m + seq }
11
+
12
+ return string if string.end_with? "\e[0m"
13
+
14
+ string + "\e[0m"
15
+ end
16
+
17
+ def self.uncolor(string)
18
+ # See http://www.commandlinefu.com/commands/view/3584/remove-color-codes-special-characters-with-sed
19
+ string.gsub(/\e\[[0-9;]*m/, '')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rainbow
4
+ VERSION = "3.1.1"
5
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'presenter'
4
+ require_relative 'null_presenter'
5
+
6
+ module Rainbow
7
+ class Wrapper
8
+ attr_accessor :enabled
9
+
10
+ def initialize(enabled = true)
11
+ @enabled = enabled
12
+ end
13
+
14
+ def wrap(string)
15
+ if enabled
16
+ Presenter.new(string.to_s)
17
+ else
18
+ NullPresenter.new(string.to_s)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rainbow
4
+ module X11ColorNames
5
+ NAMES = {
6
+ aqua: [0, 255, 255],
7
+ aquamarine: [127, 255, 212],
8
+ mediumaquamarine: [102, 205, 170],
9
+ azure: [240, 255, 255],
10
+ beige: [245, 245, 220],
11
+ bisque: [255, 228, 196],
12
+ black: [0, 0, 0],
13
+ blanchedalmond: [255, 235, 205],
14
+ blue: [0, 0, 255],
15
+ darkblue: [0, 0, 139],
16
+ lightblue: [173, 216, 230],
17
+ mediumblue: [0, 0, 205],
18
+ aliceblue: [240, 248, 255],
19
+ cadetblue: [95, 158, 160],
20
+ dodgerblue: [30, 144, 255],
21
+ midnightblue: [25, 25, 112],
22
+ navyblue: [0, 0, 128],
23
+ powderblue: [176, 224, 230],
24
+ royalblue: [65, 105, 225],
25
+ skyblue: [135, 206, 235],
26
+ deepskyblue: [0, 191, 255],
27
+ lightskyblue: [135, 206, 250],
28
+ slateblue: [106, 90, 205],
29
+ darkslateblue: [72, 61, 139],
30
+ mediumslateblue: [123, 104, 238],
31
+ steelblue: [70, 130, 180],
32
+ lightsteelblue: [176, 196, 222],
33
+ brown: [165, 42, 42],
34
+ rosybrown: [188, 143, 143],
35
+ saddlebrown: [139, 69, 19],
36
+ sandybrown: [244, 164, 96],
37
+ burlywood: [222, 184, 135],
38
+ chartreuse: [127, 255, 0],
39
+ chocolate: [210, 105, 30],
40
+ coral: [255, 127, 80],
41
+ lightcoral: [240, 128, 128],
42
+ cornflower: [100, 149, 237],
43
+ cornsilk: [255, 248, 220],
44
+ crimson: [220, 20, 60],
45
+ cyan: [0, 255, 255],
46
+ darkcyan: [0, 139, 139],
47
+ lightcyan: [224, 255, 255],
48
+ firebrick: [178, 34, 34],
49
+ fuchsia: [255, 0, 255],
50
+ gainsboro: [220, 220, 220],
51
+ gold: [255, 215, 0],
52
+ goldenrod: [218, 165, 32],
53
+ darkgoldenrod: [184, 134, 11],
54
+ lightgoldenrod: [250, 250, 210],
55
+ palegoldenrod: [238, 232, 170],
56
+ gray: [190, 190, 190],
57
+ darkgray: [169, 169, 169],
58
+ dimgray: [105, 105, 105],
59
+ lightgray: [211, 211, 211],
60
+ slategray: [112, 128, 144],
61
+ lightslategray: [119, 136, 153],
62
+ webgray: [128, 128, 128],
63
+ green: [0, 255, 0],
64
+ darkgreen: [0, 100, 0],
65
+ lightgreen: [144, 238, 144],
66
+ palegreen: [152, 251, 152],
67
+ darkolivegreen: [85, 107, 47],
68
+ yellowgreen: [154, 205, 50],
69
+ forestgreen: [34, 139, 34],
70
+ lawngreen: [124, 252, 0],
71
+ limegreen: [50, 205, 50],
72
+ seagreen: [46, 139, 87],
73
+ darkseagreen: [143, 188, 143],
74
+ lightseagreen: [32, 178, 170],
75
+ mediumseagreen: [60, 179, 113],
76
+ springgreen: [0, 255, 127],
77
+ mediumspringgreen: [0, 250, 154],
78
+ webgreen: [0, 128, 0],
79
+ honeydew: [240, 255, 240],
80
+ indianred: [205, 92, 92],
81
+ indigo: [75, 0, 130],
82
+ ivory: [255, 255, 240],
83
+ khaki: [240, 230, 140],
84
+ darkkhaki: [189, 183, 107],
85
+ lavender: [230, 230, 250],
86
+ lavenderblush: [255, 240, 245],
87
+ lemonchiffon: [255, 250, 205],
88
+ lime: [0, 255, 0],
89
+ linen: [250, 240, 230],
90
+ magenta: [255, 0, 255],
91
+ darkmagenta: [139, 0, 139],
92
+ maroon: [176, 48, 96],
93
+ webmaroon: [127, 0, 0],
94
+ mintcream: [245, 255, 250],
95
+ mistyrose: [255, 228, 225],
96
+ moccasin: [255, 228, 181],
97
+ oldlace: [253, 245, 230],
98
+ olive: [128, 128, 0],
99
+ olivedrab: [107, 142, 35],
100
+ orange: [255, 165, 0],
101
+ darkorange: [255, 140, 0],
102
+ orchid: [218, 112, 214],
103
+ darkorchid: [153, 50, 204],
104
+ mediumorchid: [186, 85, 211],
105
+ papayawhip: [255, 239, 213],
106
+ peachpuff: [255, 218, 185],
107
+ peru: [205, 133, 63],
108
+ pink: [255, 192, 203],
109
+ deeppink: [255, 20, 147],
110
+ lightpink: [255, 182, 193],
111
+ hotpink: [255, 105, 180],
112
+ plum: [221, 160, 221],
113
+ purple: [160, 32, 240],
114
+ mediumpurple: [147, 112, 219],
115
+ rebeccapurple: [102, 51, 153],
116
+ webpurple: [127, 0, 127],
117
+ red: [255, 0, 0],
118
+ darkred: [139, 0, 0],
119
+ orangered: [255, 69, 0],
120
+ mediumvioletred: [199, 21, 133],
121
+ palevioletred: [219, 112, 147],
122
+ salmon: [250, 128, 114],
123
+ darksalmon: [233, 150, 122],
124
+ lightsalmon: [255, 160, 122],
125
+ seashell: [255, 245, 238],
126
+ sienna: [160, 82, 45],
127
+ silver: [192, 192, 192],
128
+ darkslategray: [47, 79, 79],
129
+ snow: [255, 250, 250],
130
+ tan: [210, 180, 140],
131
+ teal: [0, 128, 128],
132
+ thistle: [216, 191, 216],
133
+ tomato: [255, 99, 71],
134
+ turquoise: [64, 224, 208],
135
+ darkturquoise: [0, 206, 209],
136
+ mediumturquoise: [72, 209, 204],
137
+ paleturquoise: [175, 238, 238],
138
+ violet: [238, 130, 238],
139
+ darkviolet: [148, 0, 211],
140
+ blueviolet: [138, 43, 226],
141
+ wheat: [245, 222, 179],
142
+ white: [255, 255, 255],
143
+ antiquewhite: [250, 235, 215],
144
+ floralwhite: [255, 250, 240],
145
+ ghostwhite: [248, 248, 255],
146
+ navajowhite: [255, 222, 173],
147
+ whitesmoke: [245, 245, 245],
148
+ yellow: [255, 255, 0],
149
+ lightyellow: [255, 255, 224],
150
+ greenyellow: [173, 255, 47]
151
+ }.freeze
152
+ end
153
+ end
data/lib/rainbow.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'rainbow/global'
4
+
5
+ module Rainbow
6
+ def self.new
7
+ Wrapper.new(global.enabled)
8
+ end
9
+
10
+ self.enabled = false unless STDOUT.tty? && STDERR.tty?
11
+ self.enabled = false if ENV['TERM'] == 'dumb'
12
+ self.enabled = true if ENV['CLICOLOR_FORCE'] == '1'
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rainbow
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcin Kulik
@@ -41,6 +41,17 @@ files:
41
41
  - Changelog.md
42
42
  - LICENSE
43
43
  - README.markdown
44
+ - lib/rainbow.rb
45
+ - lib/rainbow/color.rb
46
+ - lib/rainbow/ext/string.rb
47
+ - lib/rainbow/global.rb
48
+ - lib/rainbow/null_presenter.rb
49
+ - lib/rainbow/presenter.rb
50
+ - lib/rainbow/refinement.rb
51
+ - lib/rainbow/string_utils.rb
52
+ - lib/rainbow/version.rb
53
+ - lib/rainbow/wrapper.rb
54
+ - lib/rainbow/x11_color_names.rb
44
55
  homepage: https://github.com/sickill/rainbow
45
56
  licenses:
46
57
  - MIT