<(common.inc.plp)><:
use List::Util qw(sum max first);
-no if $] >= 5.018, warnings => 'experimental::smartmatch';
Html({
title => 'browser compatibility cheat sheet',
- version => '1.5',
+ version => '1.6',
description => [
"Compatibility table of new web features (HTML5, CSS3, SVG, Javascript)",
"comparing support and usage share for all popular browser versions.",
html html5 css css3 svg javascript js dom mobile
ie internet explorer firefox chrome safari webkit opera
'],
- stylesheet => [qw'circus dark mono red light'],
data => ['data/browser/support.inc.pl'],
});
say "<h1>Browser compatibility</h1>\n";
-my $caniuse = do 'data/browser/support.inc.pl' or die $@ || $!;
-$_->{verrelease} = {
- # mark last three (future) versions as unreleased, ensure current isn't
- map {
- $_->[-1] => 0, $_->[-2] => 0, $_->[-3] => 0,
- $_->[-4] => undef,
- } $_->{versions}
-} for values %{ $caniuse->{agents} };
+my $caniuse = Data('data/browser/support');
my %CSTATS = (
'n' => 'l1',
'p d' => 'l2',
'a d' => 'l2',
'y' => 'l5',
+ 'y #' => 'l4',
'y x' => 'l5 ex',
+ 'y x #' => 'l4 ex',
'a' => 'l3',
'a x' => 'l3 ex',
'p' => 'l2',
'u' => 'l0',
+ 'u d' => 'l2',
);
my %DSTATS = (
u => 'unknown',
join(' ',
'with prefix',
map {"-$_-"}
- ($caniuse->{agents}->{$_[0]}->{prefix_exceptions} // {})->{$_[1]}
+ $caniuse->{agents}->{$_[0]}->{version_list}->{$_[1]}->{prefix}
// $caniuse->{agents}->{$_[0]}->{prefix} // (),
);
},
);
my %versions;
while (my ($browser, $row) = each %{ $caniuse->{agents} }) {
- $versions{$browser} = [
- sort { paddedver($a) cmp paddedver($b) } grep { defined }
- @{ $row->{versions} }
- ];
+ $versions{$browser} = [@{ $row->{versions} }];
}
my $ref = showlink('Can I use', 'https://caniuse.com/');
my ($canihas, $usage);
my $minusage = $get{threshold} // 1;
-given ($get{usage} // 'wm') {
- when (!$_) {
- # none
- }
- when (!m{ \A [a-z]\w+ (?:/\d[\d-]*\d)? \z }x) {
+for ($get{usage} // 'wm') {
+ $_ or next; # none
+ unless (m{ \A [a-z]\w+ (?:/\d[\d-]*\d)? \z }x) {
Alert([
'Invalid browser usage data request',
'Identifier must be alphanumeric name or <q>0</q>.',
]);
+ next;
}
- $canihas = do "data/browser/usage-$_.inc.pl" or do {
- Alert('Browser usage data not found', $@ || $!);
- break;
+
+ $canihas = eval { Data("data/browser/usage-$_") } or do {
+ Alert('Browser usage data not found', ref $@ ? @{$@} : $@);
+ next;
};
$usage = $_;
my $ref = $canihas->{-title} || 'unknown';
# score multiplier for percentage of all browser versions
my $usagepct = 99.99 / sum(
- map { $_->{-total} // values %{$_} } values %{$canihas}
+ map { $_->{-total} // values %{$_} }
+ map { $canihas->{$_} }
+ grep { !/^-/ }
+ keys %{$canihas}
);
$_->{usage} = featurescore($_->{stats}) * $usagepct
for my $browser (@browsers) {
for my $span (@{ $versions{$browser} }) {
my $lastver = first {
- !defined $caniuse->{agents}->{$browser}->{verrelease}->{$_} # stable
+ $caniuse->{agents}->{$browser}->{version_list}->{$_}->{release_date} # stable
} reverse @{$span};
printf('<td title="%s"%s>%s',
join(' ',
sprintf('%.1f%%', sum(@{ $canihas->{$browser} }{ @{$span} }) * $usagepct),
'version ' . showversions(@{$span}, undef),
- $span->[-1] eq $lastver ? () : '(development)',
+ (map {
+ $_ ? sprintf('(released %d)', $_/3600/24/365.25 + 1970) : '(development)'
+ } $caniuse->{agents}->{$browser}->{version_list}->{$lastver}->{release_date}),
),
!defined $lastver && ' class="ex"',
showversions($lastver // $span->[0]),
if ($canihas) {
while (my ($browser, $versions) = each %$row) {
ref $versions eq 'HASH' or next;
- while (my ($version, $status) = each %$versions) {
+ my $prev;
+ for my $version (@{ $caniuse->{agents}->{$browser}->{versions} }) {
+ my $status = $versions->{$version} // $prev;
$status =~ s/\h\#\d+//g;
$rank += ($canihas->{$browser}->{$version} || .001) * $PSTATS{$status};
+ $prev = $status;
}
}
return $rank;
s/(?<= [^.\n]) $/./gmx; # consistently end each line by a period
Entity($_);
s{ ` ([^`]*) ` }{<code>$1</code>}gx;
+ s{ \(\K (?: \Qhttps://caniuse.com\E )? (?: /? \#feat= | / ) }{#}gx;
s{ \[ ([^]]*) \] \( ([^)]*) \) }{<a href="$2">$1</a>}gx;
}
return @html;
my $data = $feature->{stats}->{$browser};
if (ref $data eq 'ARRAY') {
# special case for unsupported
- my $release = $caniuse->{agents}->{$browser}->{verrelease};
$data = {
- map { $_ => defined $release->{$_} ? 'u' : 'n' } keys %$release
+ map { $_ => 'n' }
+ keys %{ $caniuse->{agents}->{$browser}->{version_list} }
};
}
my $compare = (
!defined $ver ? undef : # last column if nameless
ref $data ne 'HASH' ? '' : # unclassified if no support hash
- $data->{ $ver->[-1] } // $prev # known or inherit from predecessor
- // (grep { defined } @{$data}{ map { $_->[0] } @{ $versions{$browser} } })[0]
- ~~ 'n' && 'n' # first known version is unsupported
+ (first { defined } @{$data}{ reverse @{$ver} }) # last known version
+ // $prev # inherit from predecessor
|| 'u' # unsure
);
- unless (!defined $prev or $prev ~~ $compare) {
- my @vercover = (map { @{$_} } @span);
+ if (defined $prev and not (defined $compare and $prev eq $compare)) {
+ # different columns
+ my @vercover = (map { @{$_} } @span); # accumulated conforming versions
for ($ver ? @{$ver} : ()) {
- $data->{$_} eq $data->{$vercover[-1]} or last;
+ last if defined $data->{$_}; # until different
push @vercover, $_; # matches from next span start
}
my $usage = sum(@{ $canihas->{$browser} }{@vercover});
));
$title .= "\n$_" for notestotitle(@notes);
+ $prev .= ' #' if @notes and $prev =~ /^y/;
printf('<td class="%s" colspan="%d" title="%s">%s',
join(' ',
X => $CSTATS{$prev},
undef $prev;
@span = ();
}
- push @span, $ver && [ grep { $data->{ $_ } eq $data->{ $ver->[-1] } } @{$ver} ];
+ if ($ver) {
+ my $startversion = first { defined $data->{ $ver->[$_] } }
+ reverse 0 .. $#{$ver}; # compare index
+ push @span, [ @{$ver}[ $startversion .. $#{$ver} ] ];
+ }
$prev = $compare;
}
}
# normalised version number comparable as string (cmp)
$_[0] =~ m/(?:.*-|^)(\d*)(.*)/;
# matched (major)(.minor) of last value in range (a-B)
- return sprintf('%02d', length $1 ? $1 : 99) . $2;
+ return sprintf('%03d', length $1 ? $1 : 999) . $2;
}
sub showversions {
<div class="legend">
<table class="glyphs"><tr>
<td class="X l5">supported
+ <td class="X l4">annotated
<td class="X l3">partial
<td class="X l2">optional
<td class="X l1">missing