#![allow(dead_code)]
use nom::branch::alt;
use nom::bytes::complete::is_not;
use nom::bytes::complete::tag;
use nom::error::Error;
use nom::error::ErrorKind;
use parse_hyperlinks::parser::html::attribute_list;
use parse_hyperlinks::parser::Link;
use std::borrow::Cow;
pub fn html_img_link(i: &str) -> nom::IResult<&str, Link> {
let (i, (alt, src)) = html_img(i)?;
Ok((i, Link::Image(alt, src)))
}
pub fn html_img(i: &str) -> nom::IResult<&str, (Cow<str>, Cow<str>)> {
tag_img(i)
}
#[inline]
fn tag_img(i: &str) -> nom::IResult<&str, (Cow<str>, Cow<str>)> {
nom::sequence::delimited(
alt((tag("<img "), tag("<IMG "))),
nom::combinator::map_parser(is_not(">"), parse_attributes),
tag(">"),
)(i)
}
fn parse_attributes(i: &str) -> nom::IResult<&str, (Cow<str>, Cow<str>)> {
let (i, attributes) = attribute_list(i)?;
let mut src = Cow::Borrowed("");
let mut alt = Cow::Borrowed("");
for (name, value) in attributes {
if name == "src" {
if !(&*src).is_empty() {
return Err(nom::Err::Error(Error::new(name, ErrorKind::ManyMN)));
}
src = value;
} else if name == "alt" {
if !(&*alt).is_empty() {
return Err(nom::Err::Error(Error::new(name, ErrorKind::ManyMN)));
}
alt = value;
}
}
if (&*src).is_empty() {
return Err(nom::Err::Error(Error::new(i, ErrorKind::Eof)));
};
Ok((i, (alt, src)))
}
#[cfg(test)]
mod tests {
use super::*;
use parse_hyperlinks::parser::html::attribute_list;
#[test]
fn test_tag_img() {
let expected = (
"abc",
(
Cow::from("My dog"),
Cow::from("http://getreu.net/my&dog.png"),
),
);
assert_eq!(
tag_img(r#"<img src="http://getreu.net/my&dog.png" alt="My dog">abc"#).unwrap(),
expected
);
assert_eq!(
tag_img(r#"<IMG src="http://getreu.net/my&dog.png" alt="My dog">abc"#).unwrap(),
expected
);
}
#[test]
fn test_parse_attributes() {
let expected = (
"",
(
Cow::from("My dog"),
Cow::from("http://getreu.net/my&dog.png"),
),
);
assert_eq!(
parse_attributes(r#"abc src="http://getreu.net/my&dog.png" abc alt="My dog" abc"#)
.unwrap(),
expected
);
let expected =
nom::Err::Error(nom::error::Error::new("src", nom::error::ErrorKind::ManyMN));
assert_eq!(
parse_attributes(r#" src="http://getreu.net" src="http://blog.getreu.net" "#)
.unwrap_err(),
expected
);
let expected =
nom::Err::Error(nom::error::Error::new("alt", nom::error::ErrorKind::ManyMN));
assert_eq!(
parse_attributes(r#" src="http://getreu.net" alt="a" alt="b" "#).unwrap_err(),
expected
);
let expected = nom::Err::Error(nom::error::Error::new("", nom::error::ErrorKind::Eof));
assert_eq!(
parse_attributes(r#" title="title" "#).unwrap_err(),
expected
);
}
#[test]
fn test_attribute_list() {
let expected = (
"",
vec![
("", Cow::from("")),
("src", Cow::from("http://getreu.net/my&dog.png")),
("", Cow::from("")),
("alt", Cow::from("My dog")),
("", Cow::from("")),
],
);
assert_eq!(
attribute_list(r#"abc src="http://getreu.net/my&dog.png" abc alt="My dog" abc"#)
.unwrap(),
expected
);
}
}