#![deny(missing_docs)]
const MARKDOWN_CODE_FENCES: &str = "```";
pub fn parse_about(content: &str) -> String {
content
.lines()
.skip_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
.skip(1)
.skip_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
.skip(1)
.take_while(|l| !l.starts_with('#'))
.collect::<Vec<_>>()
.join("\n")
.trim()
.to_string()
}
pub fn parse_usage(content: &str) -> String {
content
.lines()
.skip_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
.skip(1)
.take_while(|l| !l.starts_with(MARKDOWN_CODE_FENCES))
.map(|l| {
if let Some((_util, args)) = l.split_once(' ') {
format!("{{}} {args}\n")
} else {
"{}\n".to_string()
}
})
.collect::<String>()
.trim()
.to_string()
}
pub fn parse_section(section: &str, content: &str) -> Option<String> {
fn is_section_header(line: &str, section: &str) -> bool {
line.strip_prefix("##")
.is_some_and(|l| l.trim().to_lowercase() == section)
}
let section = §ion.to_lowercase();
if content.lines().all(|l| !is_section_header(l, section)) {
return None;
}
let section_header_prefix = "## ";
Some(
content
.lines()
.skip_while(|&l| !is_section_header(l, section))
.skip(1)
.take_while(|l| !l.starts_with(section_header_prefix))
.collect::<Vec<_>>()
.join("\n")
.trim()
.to_string(),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_section() {
let input = "\
# ls\n\
## some section\n\
This is some section\n\
\n\
## ANOTHER SECTION
This is the other section\n\
with multiple lines\n";
assert_eq!(
parse_section("some section", input).unwrap(),
"This is some section"
);
assert_eq!(
parse_section("SOME SECTION", input).unwrap(),
"This is some section"
);
assert_eq!(
parse_section("another section", input).unwrap(),
"This is the other section\nwith multiple lines"
);
}
#[test]
fn test_parse_section_with_sub_headers() {
let input = "\
# ls\n\
## after section\n\
This is some section\n\
\n\
### level 3 header\n\
\n\
Additional text under the section.\n\
\n\
#### level 4 header\n\
\n\
Yet another paragraph\n";
assert_eq!(
parse_section("after section", input).unwrap(),
"This is some section\n\n\
### level 3 header\n\n\
Additional text under the section.\n\n\
#### level 4 header\n\n\
Yet another paragraph"
);
}
#[test]
fn test_parse_non_existing_section() {
let input = "\
# ls\n\
## some section\n\
This is some section\n\
\n\
## ANOTHER SECTION
This is the other section\n\
with multiple lines\n";
assert!(parse_section("non-existing section", input).is_none());
}
#[test]
fn test_parse_usage() {
let input = "\
# ls\n\
```\n\
ls -l\n\
```\n\
## some section\n\
This is some section\n\
\n\
## ANOTHER SECTION
This is the other section\n\
with multiple lines\n";
assert_eq!(parse_usage(input), "{} -l");
}
#[test]
fn test_parse_multi_line_usage() {
let input = "\
# ls\n\
```\n\
ls -a\n\
ls -b\n\
ls -c\n\
```\n\
## some section\n\
This is some section\n";
assert_eq!(parse_usage(input), "{} -a\n{} -b\n{} -c");
}
#[test]
fn test_parse_about() {
let input = "\
# ls\n\
```\n\
ls -l\n\
```\n\
\n\
This is the about section\n\
\n\
## some section\n\
This is some section\n";
assert_eq!(parse_about(input), "This is the about section");
}
#[test]
fn test_parse_multi_line_about() {
let input = "\
# ls\n\
```\n\
ls -l\n\
```\n\
\n\
about a\n\
\n\
about b\n\
\n\
## some section\n\
This is some section\n";
assert_eq!(parse_about(input), "about a\n\nabout b");
}
}