docstring/
lib.rs

1//! Utilities for manipulating and parsing documentation strings.
2
3/// Removes leading indentation and trailing whitespace from a string, returning `None` if the string is empty.
4pub fn normalize_doc_string(s: &str) -> Option<String> {
5    let trimmed = s.trim();
6    if trimmed.is_empty() {
7        None
8    } else {
9        Some(
10            remove_asterisks_if_asterisk_docs(&normalize_indentation(s))
11                .trim()
12                .to_string(),
13        )
14    }
15}
16
17/// Removes leading indentation and trailing whitespace from a string.
18pub fn normalize_indentation(string: &str) -> String {
19    let lines = string.lines();
20    if lines.count() == 1 {
21        string.trim().to_string()
22    } else {
23        let num_leading = string
24            .lines()
25            .filter_map(|l| l.chars().position(|c| !c.is_whitespace()))
26            .min()
27            .unwrap_or(0);
28        string
29            .lines()
30            .map(|line| {
31                if line.len() > num_leading {
32                    &line[num_leading..]
33                } else {
34                    line
35                }
36            })
37            .map(|l| l.trim_end())
38            .collect::<Vec<_>>()
39            .join("\n")
40    }
41}
42
43/// Remove asterisks if the doc string is formatted with asterisks.
44pub fn remove_asterisks_if_asterisk_docs(s: &str) -> String {
45    let should_remove_asterisks = s
46        .lines()
47        .all(|l| l.is_empty() || l.starts_with("* ") || l == "*");
48    if should_remove_asterisks {
49        s.lines()
50            .map(|line| {
51                if let Some(fmt) = line.strip_prefix("* ") {
52                    fmt
53                } else if line == "*" {
54                    ""
55                } else {
56                    line
57                }
58            })
59            .collect::<Vec<_>>()
60            .join("\n")
61    } else {
62        s.to_string()
63    }
64}