#!/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('

library

'.format(id + '-lib')) write_feature_list(f, id + '-lib', features['lib_features']) def write_feature_list(f, id, features): f.write('') 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('

Unstable features

') write_features(f, 'unstable', unstable_features) after_beta = False for version, data in versions.items(): f.write('
'.format(version)) f.write('

{}'.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('

') if 'blog_post_path' in data: f.write( '{}'.format( data['blog_post_path'], 'release notes' ) ) f.write('
') if 'features' in data: write_features(f, version, data['features']) # TODO: generate HTML