#[cfg(feature = "parsers")]
mod parse {
use nom::{
bytes::complete::{is_not, tag, take},
character::complete::{line_ending, not_line_ending, space1},
combinator::{map, map_res, opt, peek},
sequence::{pair, preceded, terminated},
IResult,
};
use super::*;
fn line(input: &str) -> IResult<&str, &str> {
terminated(not_line_ending, line_ending)(input)
}
pub fn text(input: &str) -> IResult<&str, Doc> {
map(line, |s: &str| {
if s.is_empty() {
Doc::Blank
} else {
Doc::Text(s.to_string())
}
})(input)
}
pub fn link(input: &str) -> IResult<&str, Doc> {
let body = pair(is_not(" \t\r\n"), opt(preceded(space1, is_not(" \t\r\n"))));
map(
preceded(pair(tag("=>"), space1), terminated(body, line_ending)),
|(to, name): (&str, Option<&str>)| Doc::Link {
to: to.to_string(),
name: name.map(|s| s.to_string()),
},
)(input)
}
fn level(input: &str) -> IResult<&str, Level> {
map_res(peek(take(3usize)), |s| {
Ok(match s {
"###" => Level::Three,
_ if s.starts_with("##") => Level::Two,
_ if s.starts_with("#") => Level::One,
_ => return Err(()),
})
})(input)
}
pub fn heading(input: &str) -> IResult<&str, Doc> {
map(
terminated(pair(level, not_line_ending), line_ending),
|(lvl, s)| Doc::Heading(lvl, s.to_string()),
)(input)
}
pub fn list_item(input: &str) -> IResult<&str, Doc> {
todo!()
}
pub fn quote(input: &str) -> IResult<&str, Doc> {
todo!()
}
pub fn preformatted(input: &str) -> IResult<&str, Doc> {
todo!()
}
pub fn document(input: &str) -> IResult<&str, Builder> {
todo!()
}
}