#![allow(dead_code)]
#![allow(clippy::type_complexity)]
use crate::parser::asciidoc::adoc_label2dest_link;
use crate::parser::asciidoc::adoc_text2dest_link;
use crate::parser::asciidoc::adoc_text2label_link;
use crate::parser::html::html_text2dest_link;
use crate::parser::markdown::md_label2dest_link;
use crate::parser::markdown::md_text2dest_link;
use crate::parser::markdown::md_text2label_link;
use crate::parser::restructured_text::rst_label2dest_link;
use crate::parser::restructured_text::rst_label2label_link;
use crate::parser::restructured_text::rst_text2dest_link;
use crate::parser::restructured_text::rst_text2label_link;
use crate::parser::restructured_text::rst_text_label2dest_link;
use crate::parser::wikitext::wikitext_text2dest_link;
use crate::parser::Link;
use nom::branch::alt;
use nom::bytes::complete::take_till;
use nom::character::complete::anychar;
use std::borrow::Cow;
pub const LABEL_LEN_MAX: usize = 999;
pub fn take_text2dest_label2dest(i: &str) -> nom::IResult<&str, (Cow<str>, Cow<str>, Cow<str>)> {
let mut j = i;
loop {
match take_link(j) {
Ok((j, (_, Link::Text2Dest(lte, ld, lti)))) => return Ok((j, (lte, ld, lti))),
Ok((j, (_, Link::TextLabel2Dest(lte, ld, lti)))) => return Ok((j, (lte, ld, lti))),
Ok((j, (_, Link::Label2Dest(ll, ld, lti)))) => return Ok((j, (ll, ld, lti))),
Ok((k, _)) => {
j = k;
continue;
}
Err(e) => return Err(e),
};
}
}
pub fn take_link(i: &str) -> nom::IResult<&str, (&str, Link)> {
let mut j = i;
let mut skip_count = 0;
let mut input_start = true;
let mut line_start;
let mut whitespace;
let res = loop {
line_start = false;
let (k, count) = nom::multi::many0_count(nom::character::complete::newline)(j)?;
debug_assert_eq!(j.len() - k.len(), count);
if count > 0 {
skip_count += j.len() - k.len();
j = k;
line_start = true;
};
if line_start || input_start {
if let Ok((k, r)) = alt((
rst_label2label_link,
rst_label2dest_link,
))(j)
{
break (k, r);
};
};
whitespace = false;
if let (k, Some(_)) = nom::combinator::opt(nom::character::complete::space1)(j)? {
skip_count += j.len() - k.len();
j = k;
whitespace = true;
}
if line_start || input_start {
if let Ok((k, r)) = alt((
wikitext_text2dest_link,
md_label2dest_link,
adoc_label2dest_link,
))(j)
{
break (k, r);
};
};
if let Ok((k, r)) = alt((
wikitext_text2dest_link,
md_text2dest_link,
rst_text2dest_link,
rst_text_label2dest_link,
adoc_text2label_link,
html_text2dest_link,
))(j)
{
break (k, r);
};
if whitespace || line_start || input_start {
let k = if let (k, Some(_)) =
nom::combinator::opt(nom::character::complete::one_of("([<'\""))(j)?
{
k
} else {
j
};
if let Ok((l, r)) = alt((rst_text2label_link, adoc_text2dest_link))(k) {
skip_count += j.len() - k.len();
break (l, r);
};
};
if let Ok((k, r)) = md_text2label_link(j) {
break (k, r);
};
let (k, _) = anychar(j)?;
skip_count += j.len() - k.len();
j = k;
let (k, _) = take_till(|c|
c == '\n'
|| c == ' ' || c == '\t'
|| c == '`'
|| c == '['
|| c == '{'
|| c == '<')(j)?;
skip_count += j.len() - k.len();
j = k;
input_start = false;
};
let (mut l, link) = res;
match link {
Link::Label2Dest(_, _, _) | Link::Label2Label(_, _) => {}
_ => {
let (m, _) = nom::combinator::opt(alt((rst_label2dest_link, md_label2dest_link)))(l)?;
l = m;
}
};
let skipped_input = &i[0..skip_count];
Ok((l, (skipped_input, link)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_take_link() {
let expected = nom::Err::Error(nom::error::Error::new("", nom::error::ErrorKind::Eof));
let err = take_link("").unwrap_err();
assert_eq!(err, expected);
let i = r#"[md label1]: md_destination1 "md title1"
abc [md text2](md_destination2 "md title2")[md text3]: abc[md text4]: abc
[md label5]: md_destination5 "md title5"
abc `rst text1 <rst_destination1>`__abc
abc `rst text2 <rst_label2_>`_ .. _norst: no .. _norst: no
.. _rst label3: rst_destination3
.. _rst label4: rst_d
estination4
__ rst_label5_
abc `rst text_label6 <rst_destination6>`_abc
<a href="html_destination1"
title="html title1">html text1</a>
abc https://adoc_destination1[adoc text1] abc
abc {adoc-label2}abc {adoc-label3}[adoc text3]abc
:adoc-label4: https://adoc_destination4
abc{adoc-label5}abc https://adoc_destination6 abc
abc[https://wikitext.link Wikitext Testlink]abc
"#;
let expected = Link::Label2Dest(
Cow::from("md label1"),
Cow::from("md_destination1"),
Cow::from("md title1"),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Dest(
Cow::from("md text2"),
Cow::from("md_destination2"),
Cow::from("md title2"),
);
let (i, (skipped, res)) = take_link(i).unwrap();
assert_eq!(skipped, "\nabc ");
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from("md text3"), Cow::from("md text3"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from("md text4"), Cow::from("md text4"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Dest(
Cow::from("md label5"),
Cow::from("md_destination5"),
Cow::from("md title5"),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Dest(
Cow::from("rst text1"),
Cow::from("rst_destination1"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from("rst text2"), Cow::from("rst_label2"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Dest(
Cow::from("rst label3"),
Cow::from("rst_destination3"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Dest(
Cow::from("rst label4"),
Cow::from("rst_destination4"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Label(Cow::from("_"), Cow::from("rst_label5"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::TextLabel2Dest(
Cow::from("rst text_label6"),
Cow::from("rst_destination6"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Dest(
Cow::from("html text1"),
Cow::from("html_destination1"),
Cow::from("html title1"),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Dest(
Cow::from("adoc text1"),
Cow::from("https://adoc_destination1"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from(""), Cow::from("adoc-label2"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from("adoc text3"), Cow::from("adoc-label3"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Dest(
Cow::from("adoc-label4"),
Cow::from("https://adoc_destination4"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from(""), Cow::from("adoc-label5"));
let (i, (skipped, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
assert_eq!(skipped, "\nabc");
let expected = Link::Text2Dest(
Cow::from("https://adoc_destination6"),
Cow::from("https://adoc_destination6"),
Cow::from(""),
);
let (i, (skipped, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
assert_eq!(skipped, "abc ");
let expected = Link::Text2Dest(
Cow::from("Wikitext Testlink"),
Cow::from("https://wikitext.link"),
Cow::from(""),
);
let (_i, (skipped, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
assert_eq!(skipped, " abc\nabc");
}
#[test]
fn test_take_link2() {
let i = ".. _`My: home page`: http://getreu.net\nabc";
let expected = Link::Label2Dest(
Cow::from("My: home page"),
Cow::from("http://getreu.net"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
assert_eq!(i, "\nabc");
let i = "https://adoc_link_destination[adoc link text]abc";
let expected = Link::Text2Dest(
Cow::from("adoc link text"),
Cow::from("https://adoc_link_destination"),
Cow::from(""),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
assert_eq!(i, "abc");
}
#[test]
fn test_take_link3() {
let i = r#" [md label3]: md_destination3 "md title3"
[md label1]: md_destination1 "md title1"
[md label2]: md_destination2 "md title2"
abc[md text_label3]abc[md text_label4]
"#;
let expected = Link::Label2Dest(
Cow::from("md label3"),
Cow::from("md_destination3"),
Cow::from("md title3"),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Dest(
Cow::from("md label1"),
Cow::from("md_destination1"),
Cow::from("md title1"),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Dest(
Cow::from("md label2"),
Cow::from("md_destination2"),
Cow::from("md title2"),
);
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from("md text_label3"), Cow::from("md text_label3"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from("md text_label4"), Cow::from("md text_label4"));
let (_i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
}
#[test]
fn test_take_link4() {
let i = r#"
.. _label4: label3_
label2__
__ label5
"#;
let expected = Link::Label2Label(Cow::from("label4"), Cow::from("label3"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Text2Label(Cow::from("label2"), Cow::from("_"));
let (i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
let expected = Link::Label2Dest(Cow::from("_"), Cow::from("label5"), Cow::from(""));
let (_i, (_, res)) = take_link(i).unwrap();
assert_eq!(res, expected);
}
}