#![allow(dead_code)]
pub mod markdown;
pub mod restructured_text;
use crate::parser::markdown::md_link;
use crate::parser::markdown::md_link_ref;
use crate::parser::restructured_text::rst_link;
use crate::parser::restructured_text::rst_link_ref;
use nom::branch::alt;
use nom::bytes::complete::take_till;
use nom::character::complete::anychar;
use nom::combinator::*;
pub fn take_hyperlink(mut i: &str) -> nom::IResult<&str, (String, String, String)> {
let mut input_start = true;
let res = loop {
i = if input_start {
take_till(|c|
c == '\n' || c == ' ' || c == '.'
|| c == '`' || c == '[')(i)?
.0
} else {
take_till(|c|
c == '\n'
|| c == '`' || c == '[')(i)?
.0
};
let mut line_start = false;
if peek(anychar)(i)?.1 == '\n' {
line_start = true;
let (j, _) = anychar(i)?;
i = j;
};
if line_start || input_start {
if let Ok(r) = alt((
map(md_link_ref, |(ln, lta, lti)| {
(ln.to_string(), lta.to_string(), lti.to_string())
}),
map(rst_link_ref, |(ln, lt)| (ln, lt, "".to_string())),
))(i)
{
break r;
};
};
input_start = false;
if let Ok(r) = alt((
map(rst_link, |(ln, lt)| (ln, lt, "".to_string())),
map(md_link, |(ln, lta, lti)| {
(ln.to_string(), lta.to_string(), lti.to_string())
}),
))(i)
{
break r;
};
let (j, _) = anychar(i)?;
i = j;
};
if let Ok((i, _)) = alt((
map(rst_link_ref, |(ln, lt)| (ln, lt, "".to_string())),
map(md_link_ref, |(ln, lta, lti)| {
(ln.to_string(), lta.to_string(), lti.to_string())
}),
))(res.0)
{
Ok((i, res.1))
} else {
Ok(res)
}
}
pub fn first_hyperlink(i: &str) -> Option<(String, String, String)> {
if let Ok((_, result)) = take_hyperlink(i) {
Some(result)
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_take_hyperlink() {
let expected = nom::Err::Error(nom::error::Error::new("", nom::error::ErrorKind::Eof));
let err = take_hyperlink("").unwrap_err();
assert_eq!(err, expected);
let i = r#"[md link name]: md_link_destination "md link title"
abc [md link name](md_link_destination "md link title")abc
[md link name]: md_link_destination "md link title"[nomd]: no[nomd]: no
abc`rst link name <rst_link_destination>`_abc
abc`rst link name <rst_link_destination>`_ .. _norst: no .. _norst: no
.. _rst link name: rst_link_destination
.. _rst link name: rst_link_d
estination
"#;
let expected = (
"md link name".to_string(),
"md_link_destination".to_string(),
"md link title".to_string(),
);
let (i, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
let (i, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
let (i, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
let expected = (
"rst link name".to_string(),
"rst_link_destination".to_string(),
"".to_string(),
);
let (i, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
let (i, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
let (i, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
let (_, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
let i = " .. _`My: home page`: http://getreu.net\nabc";
let expected = (
"My: home page".to_string(),
"http://getreu.net".to_string(),
"".to_string(),
);
let (_, res) = take_hyperlink(i).unwrap();
assert_eq!(res, expected);
}
#[test]
fn test_first_hyperlink() {
let i = "abc\n [md link name]: md_link_destination \"md link title\"abc";
let expected = (
"md link name".to_string(),
"md_link_destination".to_string(),
"md link title".to_string(),
);
let res = first_hyperlink(i).unwrap();
assert_eq!(res, expected);
let err = first_hyperlink("no link here");
assert_eq!(err, None);
let err = first_hyperlink("");
assert_eq!(err, None);
}
}