1use std::path::Path;
5
6#[must_use]
8pub fn page_front_matter(title: &str, weight: u32, body: &str) -> String {
9 format!(
10 "+++\ntitle = \"{title}\"\nweight = {weight}\ntemplate = \"docs/page.html\"\n+++\n\n{body}"
11 )
12}
13
14#[must_use]
20pub fn page_front_matter_with_extra(
21 title: &str,
22 weight: u32,
23 extra_toml: &str,
24 body: &str,
25) -> String {
26 format!(
27 "+++\ntitle = \"{title}\"\nweight = {weight}\ntemplate = \"docs/page.html\"\n\n[extra]\n{extra_toml}\n+++\n\n{body}"
28 )
29}
30
31#[must_use]
34pub fn section_front_matter(title: &str, weight: u32, body: &str) -> String {
35 format!(
36 "+++\ntitle = \"{title}\"\nweight = {weight}\nsort_by = \"weight\"\ntemplate = \"docs/section.html\"\n+++\n\n{body}"
37 )
38}
39
40pub fn write_reference_tree(out_dir: &Path) -> anyhow::Result<()> {
52 use {
53 crate::{broker, scenarios},
54 std::fs,
55 };
56 let br_dir = out_dir.join("broker");
57 let concepts_dir = out_dir.join("concepts");
58 fs::create_dir_all(&br_dir)?;
59 fs::create_dir_all(&concepts_dir)?;
60 fs::write(
61 out_dir.join("_index.md"),
62 section_front_matter(
63 "Reference",
64 40,
65 "Auto-generated API reference for the Krabka broker.",
66 ),
67 )?;
68 fs::write(
69 br_dir.join("_index.md"),
70 section_front_matter(
71 "Broker",
72 20,
73 "Broker server config, topic configs, and the Kafka protocol API surface.",
74 ),
75 )?;
76 fs::write(
77 br_dir.join("server-config.md"),
78 page_front_matter("Server Configuration", 10, &broker::server_config_md()),
79 )?;
80 fs::write(
81 br_dir.join("topic-configs.md"),
82 page_front_matter("Topic Configs", 20, &broker::topic_configs_md()),
83 )?;
84 fs::write(
85 br_dir.join("protocol-apis.md"),
86 page_front_matter("Protocol APIs", 30, &broker::protocol_apis_md()),
87 )?;
88 fs::write(
89 concepts_dir.join("_index.md"),
90 section_front_matter(
91 "Concepts",
92 40,
93 "How Krabka's consensus core behaves under failures, illustrated with \
94 diagrams generated from the simulator itself.",
95 ),
96 )?;
97 fs::write(
98 concepts_dir.join("failure-scenarios.md"),
99 page_front_matter_with_extra(
100 "Failure Scenarios",
101 10,
102 "mermaid = true",
103 &scenarios::failure_scenarios_md(),
104 ),
105 )?;
106 Ok(())
107}
108
109#[cfg(test)]
110mod tests {
111
112 use {super::*, std::fs, tempfile::tempdir};
113 #[test]
114 fn page_front_matter_wraps_body() {
115 let s = page_front_matter("Kafka", 10, "hello");
116 assert2::assert!(s.starts_with(
117 "+++\ntitle = \"Kafka\"\nweight = 10\ntemplate = \"docs/page.html\"\n+++\n"
118 ));
119 assert2::assert!(s.contains("hello"));
120 }
121 #[test]
122 fn writes_full_tree() {
123 let dir = tempdir().unwrap();
124 write_reference_tree(dir.path()).unwrap();
125 for page in [
126 "broker/protocol-apis.md",
127 "broker/server-config.md",
128 "broker/topic-configs.md",
129 "concepts/failure-scenarios.md",
130 ] {
131 assert2::assert!(dir.path().join(page).exists());
132 }
133 let apis = fs::read_to_string(dir.path().join("broker/protocol-apis.md")).unwrap();
134 assert2::assert!(apis.contains("template = \"docs/page.html\""));
135 let idx = fs::read_to_string(dir.path().join("_index.md")).unwrap();
136 assert2::assert!(idx.contains("template = \"docs/section.html\""));
137 }
138}