Skip to content

Commit 2c79cc1

Browse files
authored
Foldable sidebar (#1468)
1 parent 4a48c38 commit 2c79cc1

20 files changed

+333
-170
lines changed

extensions/scarb-doc/src/docs_generation.rs

+24-20
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,19 @@ impl TopLevelDocItem for TypeAlias {}
106106

107107
// Wrapper trait over a documentable item to hide implementation details of the item type.
108108
trait DocItem {
109+
const HEADER: &'static str;
110+
109111
fn name(&self) -> &str;
110112
fn doc(&self) -> &Option<String>;
111113
fn signature(&self) -> &Option<String>;
112114
fn full_path(&self) -> &str;
113115
}
114116

115117
macro_rules! impl_doc_item {
116-
($t:ty) => {
118+
($t:ty, $name:expr) => {
117119
impl DocItem for $t {
120+
const HEADER: &'static str = $name;
121+
118122
fn name(&self) -> &str {
119123
&self.item_data.name
120124
}
@@ -134,22 +138,22 @@ macro_rules! impl_doc_item {
134138
};
135139
}
136140

137-
impl_doc_item!(Constant);
138-
impl_doc_item!(Enum);
139-
impl_doc_item!(ExternFunction);
140-
impl_doc_item!(ExternType);
141-
impl_doc_item!(FreeFunction);
142-
impl_doc_item!(Impl);
143-
impl_doc_item!(ImplAlias);
144-
impl_doc_item!(ImplConstant);
145-
impl_doc_item!(ImplFunction);
146-
impl_doc_item!(ImplType);
147-
impl_doc_item!(Member);
148-
impl_doc_item!(Module);
149-
impl_doc_item!(Struct);
150-
impl_doc_item!(Trait);
151-
impl_doc_item!(TraitConstant);
152-
impl_doc_item!(TraitType);
153-
impl_doc_item!(TraitFunction);
154-
impl_doc_item!(TypeAlias);
155-
impl_doc_item!(Variant);
141+
impl_doc_item!(Constant, "Constants");
142+
impl_doc_item!(Enum, "Enums");
143+
impl_doc_item!(ExternFunction, "Extern functions");
144+
impl_doc_item!(ExternType, "Extern types");
145+
impl_doc_item!(FreeFunction, "Free functions");
146+
impl_doc_item!(Impl, "Impls");
147+
impl_doc_item!(ImplAlias, "Impl aliases");
148+
impl_doc_item!(ImplConstant, "Impl constants");
149+
impl_doc_item!(ImplFunction, "Impl functions");
150+
impl_doc_item!(ImplType, "Impl types");
151+
impl_doc_item!(Member, "Members");
152+
impl_doc_item!(Module, "Modules");
153+
impl_doc_item!(Struct, "Structs");
154+
impl_doc_item!(Trait, "Traits");
155+
impl_doc_item!(TraitConstant, "Trait constants");
156+
impl_doc_item!(TraitType, "Trait types");
157+
impl_doc_item!(TraitFunction, "Trait functions");
158+
impl_doc_item!(TypeAlias, "Type aliases");
159+
impl_doc_item!(Variant, "Variants");
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
use anyhow::{Context, Result};
22
use camino::Utf8Path;
3-
use itertools::chain;
3+
use itertools::{chain, Itertools};
44
use std::fs;
55

66
use crate::docs_generation::markdown::book_toml::generate_book_toml_content;
77
use crate::docs_generation::markdown::summary::generate_summary_file_content;
8-
use crate::docs_generation::markdown::traits::TopLevelMarkdownDocItem;
8+
use crate::docs_generation::markdown::traits::{
9+
generate_markdown_list_for_top_level_subitems, TopLevelMarkdownDocItem,
10+
};
911
use crate::docs_generation::{collect_all_top_level_items, TopLevelItems};
12+
use crate::types::{
13+
Constant, Enum, ExternFunction, ExternType, FreeFunction, Impl, ImplAlias, Module, Struct,
14+
Trait, TypeAlias,
15+
};
1016
use crate::PackageInformation;
1117

1218
mod book_toml;
@@ -18,49 +24,102 @@ const SOURCE_DIRECTORY: &str = "src";
1824
const BOOK_TOML_FILENAME: &str = "book.toml";
1925
const SUMMARY_FILENAME: &str = "SUMMARY.md";
2026

21-
pub struct MarkdownContent<'a> {
27+
type Filename = String;
28+
29+
pub struct MarkdownContent {
2230
book_toml: String,
2331
summary: String,
24-
top_level_docs: Vec<(&'a dyn TopLevelMarkdownDocItem, String)>,
32+
doc_files: Vec<(Filename, String)>,
2533
}
2634

27-
impl<'a> MarkdownContent<'a> {
28-
pub fn from_crate(package_information: &'a PackageInformation) -> Self {
35+
impl MarkdownContent {
36+
pub fn from_crate(package_information: &PackageInformation) -> Self {
2937
let top_level_items = collect_all_top_level_items(&package_information.crate_);
3038

39+
let summary_file_content = generate_summary_file_content(&top_level_items);
3140
let TopLevelItems {
32-
ref modules,
33-
ref constants,
34-
ref free_functions,
35-
ref structs,
36-
ref enums,
37-
ref type_aliases,
38-
ref impl_aliases,
39-
ref traits,
40-
ref impls,
41-
ref extern_types,
42-
ref extern_functions,
41+
modules,
42+
constants,
43+
free_functions,
44+
structs,
45+
enums,
46+
type_aliases,
47+
impl_aliases,
48+
traits,
49+
impls,
50+
extern_types,
51+
extern_functions,
4352
} = top_level_items;
4453

45-
let top_level_docs = chain!(
46-
generate_top_level_docs_contents(modules),
47-
generate_top_level_docs_contents(constants),
48-
generate_top_level_docs_contents(free_functions),
49-
generate_top_level_docs_contents(structs),
50-
generate_top_level_docs_contents(enums),
51-
generate_top_level_docs_contents(type_aliases),
52-
generate_top_level_docs_contents(impl_aliases),
53-
generate_top_level_docs_contents(traits),
54-
generate_top_level_docs_contents(impls),
55-
generate_top_level_docs_contents(extern_types),
56-
generate_top_level_docs_contents(extern_functions),
54+
let docs_for_top_level_items = chain!(
55+
generate_top_level_docs_contents(&modules),
56+
generate_top_level_docs_contents(&constants),
57+
generate_top_level_docs_contents(&free_functions),
58+
generate_top_level_docs_contents(&structs),
59+
generate_top_level_docs_contents(&enums),
60+
generate_top_level_docs_contents(&type_aliases),
61+
generate_top_level_docs_contents(&impl_aliases),
62+
generate_top_level_docs_contents(&traits),
63+
generate_top_level_docs_contents(&impls),
64+
generate_top_level_docs_contents(&extern_types),
65+
generate_top_level_docs_contents(&extern_functions),
5766
)
58-
.collect();
67+
.collect_vec();
68+
69+
let summaries_for_top_level_items = vec![
70+
(
71+
Module::ITEMS_SUMMARY_FILENAME.to_string(),
72+
generate_markdown_list_for_top_level_subitems(&modules, BASE_HEADER_LEVEL),
73+
),
74+
(
75+
Constant::ITEMS_SUMMARY_FILENAME.to_string(),
76+
generate_markdown_list_for_top_level_subitems(&constants, BASE_HEADER_LEVEL),
77+
),
78+
(
79+
FreeFunction::ITEMS_SUMMARY_FILENAME.to_string(),
80+
generate_markdown_list_for_top_level_subitems(&free_functions, BASE_HEADER_LEVEL),
81+
),
82+
(
83+
Struct::ITEMS_SUMMARY_FILENAME.to_string(),
84+
generate_markdown_list_for_top_level_subitems(&structs, BASE_HEADER_LEVEL),
85+
),
86+
(
87+
Enum::ITEMS_SUMMARY_FILENAME.to_string(),
88+
generate_markdown_list_for_top_level_subitems(&enums, BASE_HEADER_LEVEL),
89+
),
90+
(
91+
TypeAlias::ITEMS_SUMMARY_FILENAME.to_string(),
92+
generate_markdown_list_for_top_level_subitems(&type_aliases, BASE_HEADER_LEVEL),
93+
),
94+
(
95+
ImplAlias::ITEMS_SUMMARY_FILENAME.to_string(),
96+
generate_markdown_list_for_top_level_subitems(&impl_aliases, BASE_HEADER_LEVEL),
97+
),
98+
(
99+
Trait::ITEMS_SUMMARY_FILENAME.to_string(),
100+
generate_markdown_list_for_top_level_subitems(&traits, BASE_HEADER_LEVEL),
101+
),
102+
(
103+
Impl::ITEMS_SUMMARY_FILENAME.to_string(),
104+
generate_markdown_list_for_top_level_subitems(&impls, BASE_HEADER_LEVEL),
105+
),
106+
(
107+
ExternType::ITEMS_SUMMARY_FILENAME.to_string(),
108+
generate_markdown_list_for_top_level_subitems(&extern_types, BASE_HEADER_LEVEL),
109+
),
110+
(
111+
ExternFunction::ITEMS_SUMMARY_FILENAME.to_string(),
112+
generate_markdown_list_for_top_level_subitems(&extern_functions, BASE_HEADER_LEVEL),
113+
),
114+
]
115+
.into_iter()
116+
.filter(|(_filename, content)| !content.is_empty())
117+
.collect_vec();
59118

60119
Self {
61120
book_toml: generate_book_toml_content(&package_information.metadata),
62-
summary: generate_summary_file_content(&top_level_items),
63-
top_level_docs,
121+
summary: summary_file_content,
122+
doc_files: chain!(docs_for_top_level_items, summaries_for_top_level_items).collect(),
64123
}
65124
}
66125

@@ -75,25 +134,20 @@ impl<'a> MarkdownContent<'a> {
75134
fs::write(source_directory_path.join(SUMMARY_FILENAME), self.summary)
76135
.context("failed to write summary content to a file")?;
77136

78-
for (item, file_content) in self.top_level_docs {
79-
fs::write(source_directory_path.join(item.filename()), file_content)
80-
.context("failed to write content to a file")?;
137+
for (filename, file_content) in self.doc_files {
138+
fs::write(source_directory_path.join(filename), file_content)
139+
.context("failed to write content to a doc file")?;
81140
}
82141

83142
Ok(())
84143
}
85144
}
86145

87-
fn generate_top_level_docs_contents<'a>(
88-
items: &[&'a impl TopLevelMarkdownDocItem],
89-
) -> Vec<(&'a dyn TopLevelMarkdownDocItem, String)> {
146+
fn generate_top_level_docs_contents(
147+
items: &[&impl TopLevelMarkdownDocItem],
148+
) -> Vec<(Filename, String)> {
90149
items
91150
.iter()
92-
.map(|item| {
93-
(
94-
*item as &dyn TopLevelMarkdownDocItem,
95-
item.generate_markdown(BASE_HEADER_LEVEL),
96-
)
97-
})
151+
.map(|item| (item.filename(), item.generate_markdown(BASE_HEADER_LEVEL)))
98152
.collect()
99153
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::docs_generation::markdown::traits::generate_markdown_list_for_top_level_subitems;
1+
use std::fmt::Write;
2+
3+
use crate::docs_generation::markdown::traits::TopLevelMarkdownDocItem;
24
use crate::docs_generation::markdown::BASE_HEADER_LEVEL;
35
use crate::docs_generation::TopLevelItems;
46

@@ -21,40 +23,38 @@ pub fn generate_summary_file_content(top_level_items: &TopLevelItems) -> String
2123
extern_functions,
2224
} = top_level_items;
2325

24-
markdown +=
25-
&generate_markdown_list_for_top_level_subitems(modules, "Modules", BASE_HEADER_LEVEL);
26-
markdown +=
27-
&generate_markdown_list_for_top_level_subitems(constants, "Constants", BASE_HEADER_LEVEL);
28-
markdown += &generate_markdown_list_for_top_level_subitems(
29-
free_functions,
30-
"Free functions",
31-
BASE_HEADER_LEVEL,
32-
);
33-
markdown +=
34-
&generate_markdown_list_for_top_level_subitems(structs, "Structs", BASE_HEADER_LEVEL);
35-
markdown += &generate_markdown_list_for_top_level_subitems(enums, "Enums", BASE_HEADER_LEVEL);
36-
markdown += &generate_markdown_list_for_top_level_subitems(
37-
type_aliases,
38-
"Type Aliases",
39-
BASE_HEADER_LEVEL,
40-
);
41-
markdown += &generate_markdown_list_for_top_level_subitems(
42-
impl_aliases,
43-
"Impl Aliases",
44-
BASE_HEADER_LEVEL,
45-
);
46-
markdown += &generate_markdown_list_for_top_level_subitems(traits, "Traits", BASE_HEADER_LEVEL);
47-
markdown += &generate_markdown_list_for_top_level_subitems(impls, "Impls", BASE_HEADER_LEVEL);
48-
markdown += &generate_markdown_list_for_top_level_subitems(
49-
extern_types,
50-
"Extern types",
51-
BASE_HEADER_LEVEL,
52-
);
53-
markdown += &generate_markdown_list_for_top_level_subitems(
54-
extern_functions,
55-
"Extern functions",
56-
BASE_HEADER_LEVEL,
57-
);
26+
markdown += &generate_markdown_list_summary_for_top_level_subitems(modules);
27+
markdown += &generate_markdown_list_summary_for_top_level_subitems(constants);
28+
markdown += &generate_markdown_list_summary_for_top_level_subitems(free_functions);
29+
markdown += &generate_markdown_list_summary_for_top_level_subitems(structs);
30+
markdown += &generate_markdown_list_summary_for_top_level_subitems(enums);
31+
markdown += &generate_markdown_list_summary_for_top_level_subitems(type_aliases);
32+
markdown += &generate_markdown_list_summary_for_top_level_subitems(impl_aliases);
33+
markdown += &generate_markdown_list_summary_for_top_level_subitems(traits);
34+
markdown += &generate_markdown_list_summary_for_top_level_subitems(impls);
35+
markdown += &generate_markdown_list_summary_for_top_level_subitems(extern_types);
36+
markdown += &generate_markdown_list_summary_for_top_level_subitems(extern_functions);
37+
38+
markdown
39+
}
40+
41+
fn generate_markdown_list_summary_for_top_level_subitems<T: TopLevelMarkdownDocItem>(
42+
subitems: &[&T],
43+
) -> String {
44+
let mut markdown = String::new();
45+
46+
if !subitems.is_empty() {
47+
writeln!(
48+
&mut markdown,
49+
"- [{}](./{})\n",
50+
T::HEADER,
51+
T::ITEMS_SUMMARY_FILENAME
52+
)
53+
.unwrap();
54+
for item in subitems {
55+
writeln!(&mut markdown, " {}", item.generate_markdown_list_item()).unwrap();
56+
}
57+
}
5858

5959
markdown
6060
}

0 commit comments

Comments
 (0)