browser: automatic retrieval of caniuse data
[sheet.git] / tools / convert-caniuse.pl
1 #!/usr/bin/env perl
2 use 5.010;
3 use strict;
4 use warnings;
5
6 use Data::Dump 'pp';
7 use JSON;
8
9 if (@ARGV) {
10         require Time::Piece;
11         require LWP::UserAgent;
12         require File::stat;
13
14         my $target = 'browser-support.inc.pl';
15         my $source = 'http://caniuse.com/data.json';
16
17         my $ua = LWP::UserAgent->new;
18         $ua->agent('sheet.shiar.nl/browser');
19         $ua->default_header('If-Modified-Since' => scalar gmtime $_->mtime)
20                 for File::stat::stat($target);
21
22         my $res = $ua->get($source) or die "No data from $source\n";
23         !$res->is_error or die $res->status_line;
24         say $res->status_line;
25
26         exit 0 if $res->code == 304;  # unmodified
27
28         my $data = decode_json($res->decoded_content) or die "Parse error: $!";
29         my $updated = eval {
30                 s/ GMT$//,
31                 return Time::Piece->strptime($_)->ymd for $res->header('Last-Modified')
32         } || time;
33
34         open my $save, '>', (my $download = "browser-support-$updated.inc.pl");
35         print {$save} pp($data);
36         close $save;
37
38         symlink $download, "$target.new" and rename "$target.new", $target
39                 or die "New data at $download not linked: $!";
40         exit 0;
41 }
42
43 local $/;  # slurp
44 my $source = readline;
45
46 for ($source) { # cleanup
47         s/\A\(// and s/\);?\s*\Z//;  # empty callback
48         next if /^\{/;  # valid json
49
50         # convert seperate variables to hash keys
51         s/\A/{\n/;
52         s/^caniuse\.(\w+) *= */"$1":/gm;
53         s/;$/,/gm;
54         s/,\s*\Z/\n}/;
55         # fractions not supported by barekey
56         s/(?<=[,{\n]) (\d*\.\d) (?=:['"])/"$1"/gx;
57         # escapes not supported in singlequote
58         s{: *\K'((?:[^\\']+|\\.)*)'}{
59                 my $_ = $1;
60                 s/"/\\"/g;
61                 s/\\'/'/g;
62                 qq("$_");
63         }ge;
64 }
65
66 my $data = from_json($source, {
67         allow_singlequote => 1,
68         allow_barekey => 1,
69 });
70
71 print pp($data);
72
73 __END__
74
75 =head1 NAME
76
77 convert-caniuse - Turn Javascript data into an equivalent Perl structure
78
79 =head1 SYNOPSIS
80
81         curl http://caniuse.com/data.json |
82         tools/convert-caniuse.pl > browser-support.inc.pl
83
84         tools/convert-caniuse.pl auto
85