Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/tools/build-templated-pages/src/examples.rs
6595 views
1
use core::cmp::Ordering;
2
use std::fs::File;
3
4
use hashbrown::HashMap;
5
use serde::Serialize;
6
use tera::{Context, Tera};
7
use toml_edit::{DocumentMut, Item};
8
9
use crate::Command;
10
11
#[derive(Debug, Serialize, PartialEq, Eq)]
12
struct Category {
13
description: Option<String>,
14
examples: Vec<Example>,
15
}
16
17
#[derive(Debug, Serialize, PartialEq, Eq)]
18
struct Example {
19
technical_name: String,
20
path: String,
21
name: String,
22
description: String,
23
category: String,
24
wasm: bool,
25
}
26
27
impl Ord for Example {
28
fn cmp(&self, other: &Self) -> Ordering {
29
(&self.category, &self.name).cmp(&(&other.category, &other.name))
30
}
31
}
32
33
impl PartialOrd for Example {
34
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
35
Some(self.cmp(other))
36
}
37
}
38
39
fn parse_examples(panic_on_missing: bool) -> Vec<Example> {
40
let manifest_file = std::fs::read_to_string("Cargo.toml").unwrap();
41
let manifest = manifest_file.parse::<DocumentMut>().unwrap();
42
let metadatas = manifest
43
.get("package")
44
.unwrap()
45
.get("metadata")
46
.as_ref()
47
.unwrap()["example"]
48
.clone();
49
50
manifest["example"]
51
.as_array_of_tables()
52
.unwrap()
53
.iter()
54
.flat_map(|val| {
55
let technical_name = val.get("name").unwrap().as_str().unwrap().to_string();
56
if panic_on_missing && metadatas.get(&technical_name).is_none() {
57
panic!("Missing metadata for example {technical_name}");
58
}
59
if panic_on_missing && val.get("doc-scrape-examples").is_none() {
60
panic!("Example {technical_name} is missing doc-scrape-examples");
61
}
62
63
if metadatas
64
.get(&technical_name)
65
.and_then(|metadata| metadata.get("hidden"))
66
.and_then(Item::as_bool)
67
.unwrap_or(false)
68
{
69
return None;
70
}
71
72
metadatas.get(&technical_name).map(|metadata| Example {
73
technical_name,
74
path: val["path"].as_str().unwrap().to_string(),
75
name: metadata["name"].as_str().unwrap().to_string(),
76
description: metadata["description"].as_str().unwrap().to_string(),
77
category: metadata["category"].as_str().unwrap().to_string(),
78
wasm: metadata["wasm"].as_bool().unwrap(),
79
})
80
})
81
.collect()
82
}
83
84
fn parse_categories() -> HashMap<Box<str>, String> {
85
let manifest_file = std::fs::read_to_string("Cargo.toml").unwrap();
86
let manifest = manifest_file.parse::<DocumentMut>().unwrap();
87
manifest
88
.get("package")
89
.unwrap()
90
.get("metadata")
91
.as_ref()
92
.unwrap()["example_category"]
93
.clone()
94
.as_array_of_tables()
95
.unwrap()
96
.iter()
97
.map(|v| {
98
(
99
v.get("name").unwrap().as_str().unwrap().into(),
100
v.get("description").unwrap().as_str().unwrap().to_string(),
101
)
102
})
103
.collect()
104
}
105
106
pub(crate) fn check(what_to_run: Command) {
107
let examples = parse_examples(what_to_run.contains(Command::CHECK_MISSING));
108
109
if what_to_run.contains(Command::UPDATE) {
110
let categories = parse_categories();
111
let examples_by_category: HashMap<Box<str>, Category> = examples
112
.into_iter()
113
.fold(HashMap::<Box<str>, Vec<Example>>::new(), |mut v, ex| {
114
v.entry_ref(ex.category.as_str()).or_default().push(ex);
115
v
116
})
117
.into_iter()
118
.map(|(key, mut examples)| {
119
examples.sort();
120
let description = categories.get(&key).cloned();
121
(
122
key,
123
Category {
124
description,
125
examples,
126
},
127
)
128
})
129
.collect();
130
131
let mut context = Context::new();
132
context.insert("all_examples", &examples_by_category);
133
Tera::new("docs-template/*.md.tpl")
134
.expect("error parsing template")
135
.render_to(
136
"EXAMPLE_README.md.tpl",
137
&context,
138
File::create("examples/README.md").expect("error creating file"),
139
)
140
.expect("error rendering template");
141
}
142
}
143
144