cani 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/cani/api/feature.rb +9 -4
- data/lib/cani/api/feature/viewer.rb +145 -56
- data/lib/cani/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: 1df7e81ecfee9fcb8dde134bf7d3c6db8ae21520c3185b28055bfdefbf2f2f94
|
4
|
+
data.tar.gz: c3c2eb816e5ea8fb0707db1a49c19f5fbdd8ac9122f4e8678713e5a9d184b3d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5ca259ccc81e38e8646feb058863231439831a1fbc1f6adc06d32240286cf19cb68bbccefd0d9b3275f9d05a7d495472c11a7570056fddafb03a51307c8d3a8
|
7
|
+
data.tar.gz: a77833ff65dd10cfe9f71ba665d5979acf7d95dcb45042b0083afd023e979bdaebc98846bcc0a8a54682b54ee0595de4a92b03e4643cc746a2bbac1d06f3115a
|
data/Gemfile.lock
CHANGED
data/lib/cani/api/feature.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Cani
|
2
2
|
class Api
|
3
3
|
class Feature
|
4
|
-
attr_reader :title, :status, :spec, :stats, :percent, :name
|
4
|
+
attr_reader :title, :status, :spec, :stats, :percent, :name, :browser_note_nums, :notes, :notes_by_num
|
5
5
|
|
6
6
|
STATUSES = {
|
7
7
|
'rec' => 'rc',
|
@@ -25,9 +25,14 @@ module Cani
|
|
25
25
|
@status = STATUSES.fetch attributes['status'], attributes['status']
|
26
26
|
@spec = attributes['spec']
|
27
27
|
@percent = attributes['usage_perc_y']
|
28
|
-
@
|
29
|
-
|
30
|
-
|
28
|
+
@notes = attributes['notes'].split "\n"
|
29
|
+
@notes_by_num = attributes['notes_by_num']
|
30
|
+
@stats, @browser_note_nums = attributes['stats'].each_with_object([{}, {}]) do |(browser, info), (stts, notes)|
|
31
|
+
stts[browser], notes[browser] = info.each_with_object([{}, {}]) do |(version, stat), (st, nt)|
|
32
|
+
version.split('-').each do |v|
|
33
|
+
nt[v] = stat.scan(/#(\d+)/).flatten
|
34
|
+
st[v] = stat[' d '] ? 'd' : stat[0]
|
35
|
+
end
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
@@ -7,31 +7,43 @@ module Cani
|
|
7
7
|
COLOR_PAIRS = {
|
8
8
|
# foreground colors
|
9
9
|
69 => [70, -1], # green on default (legend supported, feature status, percentage counter)
|
10
|
-
213 => [
|
11
|
-
195 => [
|
12
|
-
133 => [
|
10
|
+
213 => [208, -1], # orange on default (legend partial, percentage counter)
|
11
|
+
195 => [160, -1], # red on default (legend unsupported, percentage counter)
|
12
|
+
133 => [134, -1], # magenta on default (legend flag, current feature status)
|
13
13
|
12 => [75, -1], # blue on default (legend prefix)
|
14
14
|
204 => [205, -1], # pink on default (legend polyfill)
|
15
|
-
99 => [
|
15
|
+
99 => [239, -1], # gray on default (legend unknown)
|
16
16
|
|
17
|
+
# note background + foreground colors
|
18
|
+
71 => [22, 70], # dark green on green (supported feature)
|
19
|
+
209 => [130, 208], # dark orange on orange (partial feature)
|
20
|
+
197 => [88, 160], # dark red on red (unsupported feature)
|
21
|
+
135 => [91, 134], # dark magenta on magenta (flag features)
|
22
|
+
13 => [27, 75], # dark blue on blue (prefix feature)
|
23
|
+
101 => [235, 239], # dark gray on gray (unknown features)
|
24
|
+
206 => [127, 205], # dark pink on pink (polyfill features)
|
17
25
|
|
18
26
|
# background colors
|
19
27
|
70 => [7, 70], # white on green (supported feature)
|
20
|
-
208 => [7,
|
21
|
-
196 => [7,
|
22
|
-
134 => [7,
|
28
|
+
208 => [7, 208], # white on orange (partial feature)
|
29
|
+
196 => [7, 160], # white on red (unsupported feature)
|
30
|
+
134 => [7, 134], # white on magenta (flag features)
|
23
31
|
11 => [7, 75], # white on blue (prefix feature)
|
24
|
-
100 => [7,
|
32
|
+
100 => [7, 239], # white on gray (unknown features)
|
25
33
|
205 => [7, 205], # white on pink (polyfill features)
|
26
34
|
|
27
35
|
# misc / one-off
|
28
36
|
254 => [238, 255], # black on light gray (browser names, legend title)
|
37
|
+
239 => [232, 236]
|
29
38
|
}.freeze
|
30
39
|
|
31
40
|
COLORS = {
|
32
41
|
# table headers
|
33
42
|
header: {fg: Curses.color_pair(254), bg: Curses.color_pair(254)},
|
34
43
|
|
44
|
+
# current era border
|
45
|
+
era_border: {fg: Curses.color_pair(239), bg: Curses.color_pair(239)},
|
46
|
+
|
35
47
|
# support types
|
36
48
|
default: {fg: Curses.color_pair(69), bg: Curses.color_pair(70)},
|
37
49
|
partial: {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
|
@@ -46,6 +58,16 @@ module Cani
|
|
46
58
|
ot: {fg: Curses.color_pair(133), bg: Curses.color_pair(134)}
|
47
59
|
}.freeze
|
48
60
|
|
61
|
+
NOTE_COLORS = {
|
62
|
+
default: {fg: Curses.color_pair(71), bg: Curses.color_pair(70)},
|
63
|
+
partial: {fg: Curses.color_pair(209), bg: Curses.color_pair(208)},
|
64
|
+
prefix: {fg: Curses.color_pair(13), bg: Curses.color_pair(11)},
|
65
|
+
polyfill: {fg: Curses.color_pair(206), bg: Curses.color_pair(205)},
|
66
|
+
flag: {fg: Curses.color_pair(135), bg: Curses.color_pair(134)},
|
67
|
+
unsupported: {fg: Curses.color_pair(197), bg: Curses.color_pair(196)},
|
68
|
+
unknown: {fg: Curses.color_pair(101), bg: Curses.color_pair(100)},
|
69
|
+
}
|
70
|
+
|
49
71
|
PERCENT_COLORS = {
|
50
72
|
70..101 => {fg: Curses.color_pair(69), bg: Curses.color_pair(70)},
|
51
73
|
40..70 => {fg: Curses.color_pair(213), bg: Curses.color_pair(208)},
|
@@ -67,7 +89,6 @@ module Cani
|
|
67
89
|
Curses.init_screen
|
68
90
|
Curses.curs_set 0
|
69
91
|
Curses.noecho
|
70
|
-
Curses.cbreak
|
71
92
|
|
72
93
|
if Curses.has_colors?
|
73
94
|
Curses.use_default_colors
|
@@ -93,14 +114,10 @@ module Cani
|
|
93
114
|
status_format = "[#{feature.status}]"
|
94
115
|
percent_label = compact? ? '' : 'support: '
|
95
116
|
legend_format = 'legend'.center table_width
|
117
|
+
notes_format = 'notes'.center table_width
|
96
118
|
|
97
|
-
title_size = [table_width - percent_num.size - percent_label.size - status_format.size - 3, 1].max
|
98
|
-
title_size += status_format.size if compact?
|
99
|
-
title_chunks = feature.title.chars.each_slice(title_size).map { |chrs| chrs.compact.join }
|
100
|
-
|
101
|
-
type_count = Feature::TYPES.keys.size
|
102
119
|
offset_x = ((width - table_width) / 2.0).floor
|
103
|
-
offset_y =
|
120
|
+
offset_y = 1
|
104
121
|
cy = 0
|
105
122
|
|
106
123
|
# positioning and drawing of percentage
|
@@ -119,6 +136,10 @@ module Cani
|
|
119
136
|
end
|
120
137
|
|
121
138
|
# draw possibly multi-line feature title
|
139
|
+
title_size = [table_width - percent_num.size - percent_label.size - status_format.size - 3, 1].max
|
140
|
+
title_size += status_format.size if compact?
|
141
|
+
title_chunks = feature.title.chars.each_slice(title_size).map(&:join)
|
142
|
+
|
122
143
|
title_chunks.each do |part|
|
123
144
|
Curses.setpos offset_y + cy, offset_x
|
124
145
|
Curses.addstr part
|
@@ -138,6 +159,8 @@ module Cani
|
|
138
159
|
Curses.addstr status_format
|
139
160
|
end
|
140
161
|
|
162
|
+
compact_height = height <= 40
|
163
|
+
|
141
164
|
# meaty part, loop through browsers to create
|
142
165
|
# the final feature table
|
143
166
|
browsers[0...viewable].each.with_index do |browser, x|
|
@@ -156,39 +179,51 @@ module Cani
|
|
156
179
|
|
157
180
|
# accordingly increment current browser y for the table header (browser names)
|
158
181
|
# and an additional empty line below the table header
|
159
|
-
by +=
|
182
|
+
by += 3
|
160
183
|
|
161
184
|
# draw era's for the current browser
|
162
185
|
era_range.each.with_index do |cur_era, y|
|
163
|
-
era
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
186
|
+
era = browser.eras[cur_era].to_s
|
187
|
+
supp_type = feature.support_in(browser.name, era)
|
188
|
+
colr = color supp_type
|
189
|
+
is_current = cur_era == era_idx
|
190
|
+
past_curr = cur_era > era_idx
|
191
|
+
top_pad = 1
|
192
|
+
bot_pad = compact_height ? 0 : 1
|
193
|
+
ey = by + (y * (2 + top_pad + bot_pad)) + (bot_pad.zero? && past_curr ? 1 : 0)
|
194
|
+
note_nums = feature.browser_note_nums.fetch(browser.name, {})
|
195
|
+
.fetch(era, [])
|
196
|
+
|
197
|
+
if is_current
|
198
|
+
Curses.setpos ey - top_pad - 1, bx - 1
|
199
|
+
Curses.attron(color(:era_border)) { Curses.addstr ' ' * (col_width + 2) }
|
200
|
+
|
201
|
+
Curses.setpos ey + (is_current ? 1 : bot_pad) + 1, bx - 1
|
202
|
+
Curses.attron(color(:era_border)) { Curses.addstr ' ' * (col_width + 2) }
|
203
|
+
end
|
172
204
|
|
173
|
-
# only show relevant browsers
|
205
|
+
# only show visible / relevant browsers
|
174
206
|
if browser.usage[era].to_i >= 0.5 || (!era.empty? && cur_era >= era_idx)
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
207
|
+
((ey - top_pad)..(ey + (is_current ? 1 : bot_pad))).each do |ry|
|
208
|
+
txt = (bot_pad.zero? && !is_current) ? (ry >= ey + (is_current ? 1 : bot_pad) ? era.to_s : ' ')
|
209
|
+
: (ry == ey ? era.to_s : ' ')
|
210
|
+
|
211
|
+
Curses.setpos ry, bx
|
212
|
+
Curses.attron(colr) { Curses.addstr txt.center(col_width) }
|
213
|
+
|
214
|
+
if is_current
|
215
|
+
Curses.setpos ry, bx - 1
|
216
|
+
Curses.attron(color(:era_border)) { Curses.addstr ' ' }
|
179
217
|
|
180
|
-
|
181
|
-
|
182
|
-
# this snippet fills the line before and after the current era
|
183
|
-
# with the same color that the era has for that browser / feature
|
184
|
-
if cur_era == era_idx
|
185
|
-
[-1, 1].each do |relative_y|
|
186
|
-
Curses.setpos ey - relative_y, bx
|
187
|
-
Curses.attron colr do
|
188
|
-
Curses.addstr ' ' * col_width
|
189
|
-
end
|
218
|
+
Curses.setpos ry, offset_x + table_width + 2
|
219
|
+
Curses.attron(color(:era_border)) { Curses.addstr ' ' }
|
190
220
|
end
|
191
221
|
end
|
222
|
+
|
223
|
+
if note_nums.any?
|
224
|
+
Curses.setpos ey - top_pad, bx
|
225
|
+
Curses.attron(note_color(supp_type)) { Curses.addstr ' ' + note_nums.join(' ') }
|
226
|
+
end
|
192
227
|
end
|
193
228
|
end
|
194
229
|
end
|
@@ -197,12 +232,14 @@ module Cani
|
|
197
232
|
# plus the 4 lines around the current era
|
198
233
|
# plus the 1 line of browser names
|
199
234
|
# plus the 2 blank lines above and below the eras
|
200
|
-
cy += ERAS +
|
235
|
+
cy += (ERAS - 1) * (compact_height ? 3 : 4) + ERAS
|
201
236
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
Curses.
|
237
|
+
if height > cy + 3
|
238
|
+
# print legend header
|
239
|
+
Curses.setpos offset_y + cy, offset_x
|
240
|
+
Curses.attron color(:header) do
|
241
|
+
Curses.addstr legend_format
|
242
|
+
end
|
206
243
|
end
|
207
244
|
|
208
245
|
# increment current y by 2
|
@@ -212,16 +249,64 @@ module Cani
|
|
212
249
|
|
213
250
|
# loop through all features to create a legend
|
214
251
|
# showing which label belongs to which color
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
Curses.
|
252
|
+
if height > cy + 1
|
253
|
+
Feature::TYPES.values.each_slice viewable do |group|
|
254
|
+
group.compact.each.with_index do |type, lx|
|
255
|
+
Curses.setpos offset_y + cy, offset_x + lx * col_width + lx
|
256
|
+
Curses.attron color(type[:name], :fg) do
|
257
|
+
Curses.addstr "#{type[:short]}(#{type[:symbol]})".center(col_width)
|
258
|
+
end
|
220
259
|
end
|
260
|
+
|
261
|
+
# if there is more than one group, print the next
|
262
|
+
# group on a new line
|
263
|
+
cy += 1
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# add extra empty line after legend
|
268
|
+
cy += 1
|
269
|
+
|
270
|
+
notes_chunked = feature.notes.map { |nt| nt.chars.each_slice(table_width).map(&:join).map(&:strip) }
|
271
|
+
num_chunked = feature.notes_by_num.each_with_object({}) { |(k, nt), h| h[k] = nt.chars.each_slice(table_width - 5).map(&:join).map(&:strip) }
|
272
|
+
notes_total = notes_chunked.map(&:size).sum + num_chunked.map(&:size).sum
|
273
|
+
|
274
|
+
if height > cy + 2 && (notes_chunked.any? || num_chunked.any?)
|
275
|
+
# print notes header
|
276
|
+
Curses.setpos offset_y + cy, offset_x
|
277
|
+
Curses.attron color(:header) do
|
278
|
+
Curses.addstr notes_format
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
# add two new lines, one for the notes header
|
283
|
+
# and one empty line below it
|
284
|
+
cy += 2
|
285
|
+
|
286
|
+
notes_chunked.each do |chunks|
|
287
|
+
break if cy + 1 + chunks.size > height
|
288
|
+
chunks.each do |part|
|
289
|
+
Curses.setpos offset_y + cy, offset_x
|
290
|
+
Curses.addstr part
|
291
|
+
cy += 1
|
292
|
+
end
|
293
|
+
|
294
|
+
cy += 1
|
295
|
+
end
|
296
|
+
|
297
|
+
num_chunked.each do |num, chunks|
|
298
|
+
break if cy + 1 + chunks.size > height
|
299
|
+
Curses.setpos offset_y + cy, offset_x
|
300
|
+
Curses.attron color(:header) do
|
301
|
+
Curses.addstr num.center(3)
|
302
|
+
end
|
303
|
+
|
304
|
+
chunks.each do |part|
|
305
|
+
Curses.setpos offset_y + cy, offset_x + 5
|
306
|
+
Curses.addstr part
|
307
|
+
cy += 1
|
221
308
|
end
|
222
309
|
|
223
|
-
# if there is more than one group, print the next
|
224
|
-
# group on a new line
|
225
310
|
cy += 1
|
226
311
|
end
|
227
312
|
|
@@ -262,20 +347,24 @@ module Cani
|
|
262
347
|
end
|
263
348
|
|
264
349
|
@col_width = [colw, Feature::TYPES.map { |(_, h)| h[:short].size }.max + 3].max
|
265
|
-
@table_width = tablew
|
350
|
+
@table_width = tablew - 2 # vertical padding at start and end of current era line
|
266
351
|
end
|
267
352
|
|
268
353
|
def compact?
|
269
354
|
width < COMPACT
|
270
355
|
end
|
271
356
|
|
272
|
-
def color(key, type = :bg)
|
357
|
+
def color(key, type = :bg, source = COLORS)
|
273
358
|
target = key.to_s.downcase.to_sym
|
274
359
|
type = type.to_sym
|
275
360
|
|
276
|
-
|
361
|
+
source.find { |(k, _)| k == target }.to_a
|
277
362
|
.fetch(1, {})
|
278
|
-
.fetch(type,
|
363
|
+
.fetch(type, source[:default][type])
|
364
|
+
end
|
365
|
+
|
366
|
+
def note_color(status)
|
367
|
+
color status, :fg, NOTE_COLORS
|
279
368
|
end
|
280
369
|
|
281
370
|
def status_color(status)
|
data/lib/cani/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cani
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sidney Liebrand
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|