Generate CSS feature data as a Rust source file
(web_features: &WebFeaturesData, popularity_map: &HashMap<String, f64>)
| 821 | |
| 822 | /// Generate CSS feature data as a Rust source file |
| 823 | pub fn generate_feature_data(web_features: &WebFeaturesData, popularity_map: &HashMap<String, f64>) -> String { |
| 824 | let mut all_groups: HashMap<String, HashSet<String>> = HashMap::new(); |
| 825 | let mut all_specs: HashMap<String, HashSet<String>> = HashMap::new(); |
| 826 | let mut feature_entries: Vec<(String, TokenStream)> = Vec::new(); |
| 827 | |
| 828 | // Collect all features |
| 829 | for (feature_id, feature) in &web_features.features { |
| 830 | if let Some(status) = &feature.status |
| 831 | && let Some(by_compat_key) = &status.by_compat_key |
| 832 | { |
| 833 | for (id, compat_status) in by_compat_key { |
| 834 | if id.starts_with("css.") { |
| 835 | let entry = generate_feature_entry_tokens( |
| 836 | id, |
| 837 | feature_id, |
| 838 | feature, |
| 839 | compat_status, |
| 840 | popularity_map, |
| 841 | &mut all_groups, |
| 842 | &mut all_specs, |
| 843 | ); |
| 844 | feature_entries.push((id.to_string(), entry)); |
| 845 | } |
| 846 | } |
| 847 | } |
| 848 | } |
| 849 | |
| 850 | feature_entries.sort_by(|a, b| a.0.cmp(&b.0)); |
| 851 | let feature_entries: Vec<TokenStream> = feature_entries.into_iter().map(|(_, tokens)| tokens).collect(); |
| 852 | |
| 853 | let mut sorted_groups: Vec<_> = all_groups.into_iter().collect(); |
| 854 | sorted_groups.sort_by(|a, b| a.0.cmp(&b.0)); |
| 855 | let group_entries: Vec<TokenStream> = sorted_groups |
| 856 | .into_iter() |
| 857 | .filter(|(group, _)| !group.is_empty()) |
| 858 | .map(|(group, members)| { |
| 859 | let mut sorted_members: Vec<_> = members.into_iter().collect(); |
| 860 | sorted_members.sort(); |
| 861 | let member_strs = sorted_members.iter().map(|m| m.as_str()); |
| 862 | quote! { |
| 863 | #group => &[#(#member_strs),*] |
| 864 | } |
| 865 | }) |
| 866 | .collect(); |
| 867 | |
| 868 | let mut sorted_specs: Vec<_> = all_specs.into_iter().collect(); |
| 869 | sorted_specs.sort_by(|a, b| a.0.cmp(&b.0)); |
| 870 | let spec_entries: Vec<TokenStream> = sorted_specs |
| 871 | .into_iter() |
| 872 | .filter(|(spec, _)| !spec.is_empty()) |
| 873 | .map(|(spec, members)| { |
| 874 | let mut sorted_members: Vec<_> = members.into_iter().collect(); |
| 875 | sorted_members.sort(); |
| 876 | let member_strs = sorted_members.iter().map(|m| m.as_str()); |
| 877 | quote! { |
| 878 | #spec => &[#(#member_strs),*] |
| 879 | } |
| 880 | }) |