use pulldown_cmark::{Options, Parser};
use pulldown_cmark_to_cmark::cmark_with_options;
use crate::error::Result;
pub fn format_markdown(input: &str) -> Result<String> {
let mut options = Options::empty();
options.insert(Options::ENABLE_TABLES);
options.insert(Options::ENABLE_STRIKETHROUGH);
options.insert(Options::ENABLE_TASKLISTS);
options.insert(Options::ENABLE_FOOTNOTES);
options.insert(Options::ENABLE_GFM);
let parser = Parser::new_ext(input, options);
let mut formatted = String::with_capacity(input.len());
let format_options = pulldown_cmark_to_cmark::Options {
list_token: '-',
..Default::default()
};
cmark_with_options(parser, &mut formatted, format_options)?;
if input.ends_with('\n') && !formatted.ends_with('\n') {
formatted.push('\n');
}
Ok(formatted)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn normalizes_messy_markdown() -> Result<()> {
let input = "\
Changelog
=========
## 1.0.0
### Features
- first change
- second change
some text
";
let formatted = format_markdown(input)?;
let expected = "\
# Changelog
## 1.0.0
### Features
- first change
- second change
some text
";
assert_eq!(expected, formatted);
assert_eq!(formatted, format_markdown(&formatted)?);
Ok(())
}
#[test]
fn keeps_clean_markdown_stable() -> Result<()> {
let input = "\
# Changelog
## 1.0.0
### Features
- add a thing
### Bug Fixes
- fix a thing
";
assert_eq!(input, format_markdown(input)?);
Ok(())
}
}