Factor out common module prefix when all modules are under a same namespace.

This commit is contained in:
KtorZ 2022-12-17 00:57:49 +01:00
parent 600c7747da
commit 5c0920d6bb
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
3 changed files with 119 additions and 16 deletions

View File

@ -34,6 +34,7 @@ struct ModuleTemplate<'a> {
project_name: &'a str, project_name: &'a str,
project_version: &'a str, project_version: &'a str,
links: &'a Vec<DocLink>, links: &'a Vec<DocLink>,
modules_prefix: String,
modules: &'a Vec<DocLink>, modules: &'a Vec<DocLink>,
functions: Vec<DocFunction>, functions: Vec<DocFunction>,
types: Vec<DocType>, types: Vec<DocType>,
@ -51,6 +52,7 @@ struct PageTemplate<'a> {
project_name: &'a str, project_name: &'a str,
project_version: &'a str, project_version: &'a str,
links: &'a Vec<DocLink>, links: &'a Vec<DocLink>,
modules_prefix: String,
modules: &'a Vec<DocLink>, modules: &'a Vec<DocLink>,
content: String, content: String,
timestamp: &'a str, timestamp: &'a str,
@ -69,26 +71,37 @@ struct DocLink {
/// across multiple modules. /// across multiple modules.
pub fn generate_all(root: &Path, config: &Config, modules: Vec<&CheckedModule>) -> Vec<DocFile> { pub fn generate_all(root: &Path, config: &Config, modules: Vec<&CheckedModule>) -> Vec<DocFile> {
let timestamp = new_timestamp(); let timestamp = new_timestamp();
let modules_links = generate_modules_links(&modules); let (modules_prefix, modules_links) = generate_modules_links(&modules);
let mut output_files: Vec<DocFile> = vec![]; let mut output_files: Vec<DocFile> = vec![];
let mut search_indexes: Vec<SearchIndex> = vec![]; let mut search_indexes: Vec<SearchIndex> = vec![];
for module in &modules { for module in &modules {
let (indexes, file) = generate_module(config, module, &modules_links, &timestamp); let (indexes, file) = generate_module(
config,
module,
(&modules_prefix, &modules_links),
&timestamp,
);
search_indexes.extend(indexes); search_indexes.extend(indexes);
output_files.push(file); output_files.push(file);
} }
output_files.extend(generate_static_assets(search_indexes)); output_files.extend(generate_static_assets(search_indexes));
output_files.push(generate_readme(root, config, &modules_links, &timestamp)); output_files.push(generate_readme(
root,
config,
(&modules_prefix, &modules_links),
&timestamp,
));
output_files output_files
} }
fn generate_module( fn generate_module(
config: &Config, config: &Config,
module: &CheckedModule, module: &CheckedModule,
modules: &Vec<DocLink>, (modules_prefix, modules): (&str, &Vec<DocLink>),
timestamp: &Duration, timestamp: &Duration,
) -> (Vec<SearchIndex>, DocFile) { ) -> (Vec<SearchIndex>, DocFile) {
let mut search_indexes = vec![]; let mut search_indexes = vec![];
@ -101,7 +114,6 @@ fn generate_module(
.flat_map(DocFunction::from_definition) .flat_map(DocFunction::from_definition)
.sorted() .sorted()
.collect(); .collect();
functions functions
.iter() .iter()
.for_each(|function| search_indexes.push(SearchIndex::from_function(module, function))); .for_each(|function| search_indexes.push(SearchIndex::from_function(module, function)));
@ -114,7 +126,6 @@ fn generate_module(
.flat_map(DocType::from_definition) .flat_map(DocType::from_definition)
.sorted() .sorted()
.collect(); .collect();
types types
.iter() .iter()
.for_each(|type_info| search_indexes.push(SearchIndex::from_type(module, type_info))); .for_each(|type_info| search_indexes.push(SearchIndex::from_type(module, type_info)));
@ -133,12 +144,12 @@ fn generate_module(
// Module // Module
search_indexes.push(SearchIndex::from_module(module)); search_indexes.push(SearchIndex::from_module(module));
let module = ModuleTemplate {
let template = ModuleTemplate {
aiken_version: VERSION, aiken_version: VERSION,
breadcrumbs: to_breadcrumbs(&module.name), breadcrumbs: to_breadcrumbs(&module.name),
links: &vec![], links: &vec![],
documentation: render_markdown(&module.ast.docs.iter().join("\n")), documentation: render_markdown(&module.ast.docs.iter().join("\n")),
modules_prefix: modules_prefix.to_string(),
modules, modules,
project_name: &config.name, project_name: &config.name,
page_title: &format!("{} - {}", module.name, config.name), page_title: &format!("{} - {}", module.name, config.name),
@ -153,8 +164,8 @@ fn generate_module(
( (
search_indexes, search_indexes,
DocFile { DocFile {
path: PathBuf::from(format!("{}.html", module.name)), path: PathBuf::from(format!("{}.html", module.module_name)),
content: template content: module
.render() .render()
.expect("Module documentation template rendering"), .expect("Module documentation template rendering"),
}, },
@ -214,7 +225,7 @@ fn generate_static_assets(search_indexes: Vec<SearchIndex>) -> Vec<DocFile> {
fn generate_readme( fn generate_readme(
root: &Path, root: &Path,
config: &Config, config: &Config,
modules: &Vec<DocLink>, (modules_prefix, modules): (&str, &Vec<DocLink>),
timestamp: &Duration, timestamp: &Duration,
) -> DocFile { ) -> DocFile {
let path = PathBuf::from("index.html"); let path = PathBuf::from("index.html");
@ -225,6 +236,7 @@ fn generate_readme(
aiken_version: VERSION, aiken_version: VERSION,
breadcrumbs: ".", breadcrumbs: ".",
links: &vec![], links: &vec![],
modules_prefix: modules_prefix.to_string(),
modules, modules,
project_name: &config.name, project_name: &config.name,
page_title: &config.name, page_title: &config.name,
@ -239,7 +251,7 @@ fn generate_readme(
} }
} }
fn generate_modules_links(modules: &Vec<&CheckedModule>) -> Vec<DocLink> { fn generate_modules_links(modules: &Vec<&CheckedModule>) -> (String, Vec<DocLink>) {
let mut modules_links = vec![]; let mut modules_links = vec![];
for module in modules { for module in modules {
let module_path = [&module.name.clone(), ".html"].concat(); let module_path = [&module.name.clone(), ".html"].concat();
@ -249,7 +261,18 @@ fn generate_modules_links(modules: &Vec<&CheckedModule>) -> Vec<DocLink> {
}); });
} }
modules_links.sort(); modules_links.sort();
modules_links
let prefix = find_modules_prefix(&modules_links);
for module in &mut modules_links {
let name = module.name.strip_prefix(&prefix).unwrap_or_default();
module.name = name.strip_prefix('/').unwrap_or(name).to_string();
if module.name == String::new() {
module.name = "/".to_string()
}
}
(prefix, modules_links)
} }
#[derive(Serialize, PartialEq, Eq, PartialOrd, Ord, Clone)] #[derive(Serialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
@ -510,18 +533,86 @@ fn new_timestamp() -> Duration {
.expect("get current timestamp") .expect("get current timestamp")
} }
fn find_modules_prefix(modules: &[DocLink]) -> String {
modules
.iter()
.fold(None, |previous_prefix, module| {
let prefix = module
.name
.split('/')
.next()
.unwrap_or_default()
.to_string();
match previous_prefix {
None if prefix != module.name => Some(prefix),
Some(..) if Some(prefix) == previous_prefix => previous_prefix,
_ => Some(String::new()),
}
})
.unwrap_or_default()
}
#[test]
fn find_modules_prefix_test() {
assert_eq!(find_modules_prefix(&vec![]), "".to_string());
assert_eq!(
find_modules_prefix(&vec![DocLink {
name: "aiken/list".to_string(),
path: String::new()
}]),
"aiken".to_string()
);
assert_eq!(
find_modules_prefix(&vec![DocLink {
name: "my_module".to_string(),
path: String::new()
}]),
"".to_string()
);
assert_eq!(
find_modules_prefix(&vec![
DocLink {
name: "aiken/list".to_string(),
path: String::new()
},
DocLink {
name: "aiken/byte_array".to_string(),
path: String::new(),
}
]),
"aiken".to_string()
);
assert_eq!(
find_modules_prefix(&vec![
DocLink {
name: "aiken/list".to_string(),
path: String::new()
},
DocLink {
name: "foo/byte_array".to_string(),
path: String::new(),
}
]),
"".to_string()
);
}
fn to_breadcrumbs(path: &str) -> String { fn to_breadcrumbs(path: &str) -> String {
let unnest = path let breadcrumbs = path
.strip_prefix('/') .strip_prefix('/')
.unwrap_or(path) .unwrap_or(path)
.split('/') .split('/')
.skip(1) .skip(1)
.map(|_| "..") .map(|_| "..")
.join("/"); .join("/");
if unnest.is_empty() { if breadcrumbs.is_empty() {
".".to_string() ".".to_string()
} else { } else {
unnest breadcrumbs
} }
} }

View File

@ -185,6 +185,9 @@
{% endif %} {% endif %}
<h2>Modules</h2> <h2>Modules</h2>
{% if !modules_prefix.is_empty() %}
<h3 class="modules-prefix">{{ modules_prefix }}/</h3>
{% endif %}
<ul> <ul>
{% for module in modules %} {% for module in modules %}
<li><a href="{{ breadcrumbs }}/{{ module.path }}">{{ module.name }}</a></li> <li><a href="{{ breadcrumbs }}/{{ module.path }}">{{ module.name }}</a></li>

View File

@ -305,12 +305,21 @@ p code {
margin: 0; margin: 0;
} }
.sidebar h3.modules-prefix {
color: var(--pink);
margin-bottom: 0;
}
.sidebar ul { .sidebar ul {
list-style: none; list-style: none;
margin: var(--small-gap) 0; margin: var(--small-gap) 0;
padding: 0; padding: 0;
} }
.sidebar h3.modules-prefix + ul {
margin-left: var(--tiny-gap);
}
.sidebar li { .sidebar li {
line-height: 1.2; line-height: 1.2;
margin-bottom: 4px; margin-bottom: 4px;