<(common.inc.plp)><: use 5.010; Html({ title => 'browser compatibility cheat sheet', version => 'v1.0', description => "caniuse.", keywords => [qw'html css browser feature'], stylesheet => [qw'light dark circus mono red'], data => ['caniuse.js'], }); :>

Browser compatibility

Alternate view of Fyrd's when can I use... site.

<: use JSON; use File::Slurp 'read_file'; my $source = read_file('caniuse.js'); for ($source) { # cleanup # convert seperate variables to hash keys s/\A/{/; s/^caniuse\.(\w+) = /"$1":/gm; s/;$/,/gm; s/,\s*\Z/\n}/; # fractions not supported by barekey s/(?<=[,{]) (\d*\.\d) (?=:')/"$1"/gx; # escapes not supported in singlequote s{'((?:[^\\']+|\\.)*)'}{ my $_ = $1; s/"/\\"/g; s/\\'/'/g; qq("$_"); }ge; } my $caniuse = from_json($source, { # allow_singlequote => 1, allow_barekey => 1, }); my %CSTATS = ( n => 'di-b', y => 'di-aa', a => 'di-d', j => 'di-prop', p => 'di-prop', 'y x' => 'di-a', ); my %CSTATUS = ( unoff => 'di-rare', # unofficial wd => 'di-b', # draft pr => 'di-prop', # proposed cr => 'di-d', # candidate rec => 'di-a', # recommendation ietf => 'di-aa', # standard ); my @browsers = qw(trident gecko webkit_saf webkit_chr presto); my %versions; if (my ($somerow) = values %{ $caniuse->{data} }) { while (my ($browser, $row) = each %{ $somerow->{stats} }) { $versions{$browser} = [ sort { paddedver($a) cmp paddedver($b) } keys %$row ]; } } print ''; print '' x 3; printf '', scalar @{ $versions{$_} } for @browsers; print "\n"; print ''; print ''; print '\n"; sub featurescore { # relative amount of support for given feature state $statspts = { y=>10, 'y x'=>9, a=>5, j=>2, p=>1 }; my $rank = 0; if (my $row = shift) { while (my ($browser, $vercols) = each %versions) { my $div = 0; # multiplier exponent (decreased to lower value) my @vers = map { $row->{$browser}->{$_} } @$vercols; if (my $current = $caniuse->{agents}->{$browser}->{versions}->[-3]) { my @future; # find upcoming releases (after current) for (reverse @$vercols) { last if $_ eq $current; push @future, pop @vers; $_ eq 'u' and $_ = $vers[-1] for $future[-1]; # inherit latest value if unknown } splice @vers, -1, 0, @future; # move ahead to decrease precedence } $rank += $statspts->{$_} * 2**($div--) for reverse @vers; } } return $rank; } for my $id (sort { featurescore($caniuse->{data}->{$b}->{stats}) <=> featurescore($caniuse->{data}->{$a}->{stats}) } keys %{ $caniuse->{data} }) { my $row = $caniuse->{data}->{$id}; my $data = $row->{stats} or next; # skip metadata [summary] printf '', $id; for ($row->{categories}) { my $cell = $_ ? lc $_->[0] : '-'; print '
feature'; printf '%s', scalar @{ $versions{$_} }, $caniuse->{agents}->{$_}->{browser} for @browsers; # preceding row without any colspan to work around gecko bug print '
' x $_ for 3, (map { scalar @{ $versions{$_} } } @browsers), 1; print "
', $cell; } printf '%s', $row->{description}, $row->{title}; for ($row->{status}) { my $cell = $_ // '-'; $cell = sprintf '%s', $_, $cell for $row->{spec} // (); printf '%s', $caniuse->{statuses}->{$_}, $CSTATUS{$_} // '', $cell; } for my $browser (@browsers) { my ($prev, @span); for my $ver (@{ $versions{$browser} }, undef) { unless (!defined $prev or $data->{$browser}->{$prev} ~~ $data->{$browser}->{$ver}) { printf '%s', $CSTATS{ $data->{$browser}->{$prev} }, scalar @span, join('‒', $span[0], @span > 1 ? $span[-1] : ()); undef $prev; @span = (); } push @span, $ver; $prev = $ver; } } state $maxscore = featurescore({ # yes for every possible version map { $_ => { map {$_ => 'y'} @{$versions{$_}} } } keys %versions }); print '', int featurescore($caniuse->{data}->{$id}->{stats}) / $maxscore * 100; } print '
'; sub paddedver { # normalised version number comparable as string (cmp) shift =~ /^(\d*)(.*)/; return sprintf('%02d', $1) . $2; } :>
supported prefixed partial external (js/plugin) missing