1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
#!/usr/bin/env python3
import glob
import html
import json
import os
import re
import shutil
import tomllib
def get_features(dirname):
feature_data = {}
for feature in sorted(os.listdir('caniuse.rs/data/' + dirname)):
with open('caniuse.rs/data/' + dirname + '/' + feature, 'rb') as f:
name = feature.split('.')[0]
feature_data[name] = tomllib.load(f)
# new dict because we want to deduplicate features
features = {}
# caniuse.rs sometimes has several .toml files for one feature flag e.g.
# For the const_io feature flag it has 6 .toml files, all with the same
# tracking_issue_id but different titles.
#
# That makes sense for a search-centric application. Not so much for a
# static-site generator since showing the same link 6 times is confusing.
for feat, data in feature_data.items():
key = data['flag'] if 'flag' in data else feat
url = None
if 'tracking_issue_id' in data:
url = 'https://github.com/rust-lang/rust/issues/{}'.format(
data['tracking_issue_id']
)
elif 'impl_pr_id' in data:
url = 'https://github.com/rust-lang/rust/pull/{}'.format(data['impl_pr_id'])
elif 'stabilization_pr_id' in data:
url = 'https://github.com/rust-lang/rust/pull/{}'.format(
data['stabilization_pr_id']
)
data['url'] = url
data['filename'] = feat
if data['title'].startswith('the '):
data['title'] = data['title'][len('the ') :]
data['title'] = data['title'].replace('implementation', 'impl')
if key in features:
data['title'] = data['flag'].replace('_', ' ')
if key in features and features[key]['url'] != url:
print(
'different urls for feature {}:\n* {}: {}\n* {}: {}'.format(
key,
data['filename'],
data['url'],
features[key]['filename'],
features[key]['url'],
)
)
features[key] = data
features = dict(
sorted(features.items(), key=lambda t: t[1]['title'].replace('`', '').lower())
)
lib_features = {}
non_lib_features = {}
for key, data in features.items():
if ('flag' in data and data['flag'] in library_flags) or 'impl for' in data[
'title'
]:
lib_features[key] = data
else:
non_lib_features[key] = data
return dict(lib_features=lib_features, non_lib_features=non_lib_features)
with open('lib_feats.txt') as f:
library_flags = set([l.strip() for l in f])
with open('caniuse.rs/data/versions.toml', 'rb') as f:
versions = tomllib.load(f)
for version, data in versions.items():
try:
data['features'] = get_features(version)
except FileNotFoundError:
pass
versions = dict(reversed(list(versions.items())))
unstable_features = get_features('unstable')
os.makedirs('target', exist_ok=True)
shutil.copy('style.css', 'target')
shutil.copy('script.js', 'target')
with open('target/data.json', 'w') as f:
data = dict(unstable=dict(features=unstable_features), **versions)
json.dump(data, f)
def write_features(f, id, features):
if features['non_lib_features']:
write_feature_list(f, id + '-non-lib', features['non_lib_features'])
if features['lib_features']:
f.write('<h3 id="{}">library</h3>'.format(id + '-lib'))
write_feature_list(f, id + '-lib', features['lib_features'])
def write_feature_list(f, id, features):
f.write('<ul id={}-list'.format(id))
if len(features) > 5:
f.write(' class=columns')
f.write('>')
for feat, data in features.items():
f.write('<li><a')
if 'flag' in data:
f.write(' title="{}"'.format(data['flag']))
url = data['url']
if url:
f.write(f' href="{url}"')
f.write('>')
title = html.escape(data['title'])
title = re.sub('`(.+?)`', lambda m: '<code>{}</code>'.format(m.group(1)), title)
f.write(title)
f.write('</a></li>')
f.write('</ul>')
with open('target/index.html', 'w') as f:
with open('head.html') as h:
f.write(h.read())
# TODO: sort by T-lang and T-lib
f.write('<h2 id=unstable>Unstable features</h2>')
write_features(f, 'unstable', unstable_features)
after_beta = False
for version, data in versions.items():
f.write('<div id={0} class=release>'.format(version))
f.write('<h2>{}'.format(version))
channel = data.get('channel')
if after_beta:
channel = 'stable'
after_beta = False
if channel:
if channel == 'nightly':
channel = 'stabilized'
elif channel == 'beta':
after_beta = True
f.write(' [{}]'.format(channel))
f.write('</h2>')
if 'blog_post_path' in data:
f.write(
'<a class=release-notes href="https://blog.rust-lang.org/{}">{}</a>'.format(
data['blog_post_path'], 'release notes'
)
)
f.write('</div>')
if 'features' in data:
write_features(f, version, data['features'])
# TODO: generate HTML
|