parse_hyperlinks/parser/
markdown_img.rs

1//! This module implements parsers for HTML image elements.
2#![allow(dead_code)]
3
4use super::markdown::md_link_destination;
5use crate::parser::markdown::md_link_destination_enclosed;
6use crate::parser::markdown::md_link_text;
7use crate::parser::Link;
8use crate::take_until_unbalanced;
9use html_escape::decode_html_entities;
10use nom::combinator::*;
11use nom::{bytes::complete::tag, sequence::tuple};
12use std::borrow::Cow;
13
14/// Wrapper around `md_img()` that packs the result in
15/// `Link::Image`.
16pub fn md_img_link(i: &str) -> nom::IResult<&str, Link> {
17    let (i, (alt, src)) = md_img(i)?;
18    Ok((i, Link::Image(alt, src)))
19}
20
21/// Parse a Markdown image.
22///
23/// It returns either `Ok((i, (img_alt, img_src)))` or some error.
24///
25/// The parser expects to start at the link start (`!`) to succeed.
26/// ```
27/// use parse_hyperlinks;
28/// use parse_hyperlinks::parser::markdown_img::md_img;
29/// use std::borrow::Cow;
30///
31/// assert_eq!(
32///   md_img("![my Dog](/images/my&dog.png)abc"),
33///   Ok(("abc", (Cow::from("my Dog"), Cow::from("/images/my&dog.png"))))
34/// );
35/// ```
36pub fn md_img(i: &str) -> nom::IResult<&str, (Cow<str>, Cow<str>)> {
37    nom::sequence::preceded(
38        tag("!"),
39        // Parse inline link.
40        nom::sequence::tuple((md_link_text, md_img_link_destination_enclosed)),
41    )(i)
42}
43
44/// Matches `md_link_destination` in parenthesis.
45fn md_img_link_destination_enclosed(i: &str) -> nom::IResult<&str, Cow<str>> {
46    map_parser(
47        nom::sequence::delimited(tag("("), take_until_unbalanced('(', ')'), tag(")")),
48        md_link_destination,
49    )(i)
50}
51
52/// Wrapper around `md_img()` that packs the result in
53/// `Link::Image`.
54pub fn md_img2dest_link(i: &str) -> nom::IResult<&str, Link> {
55    let (i, (text1, img_alt, img_src, text2, dest, title)) = md_img2dest(i)?;
56    Ok((
57        i,
58        Link::Image2Dest(text1, img_alt, img_src, text2, dest, title),
59    ))
60}
61
62/// Parse a Markdown link with an embedded image.
63///
64/// It returns either
65// `Ok((i, (text1, img_alt, img_src, text2, dest, title)))` or some error.
66///
67/// The parser expects to start at the link start (`!`) to succeed.
68/// ```
69/// use parse_hyperlinks;
70/// use parse_hyperlinks::parser::markdown_img::md_img2dest;
71/// use std::borrow::Cow;
72///
73/// assert_eq!(
74///   md_img2dest("[111![my dog](/my&dog.png)222]\
75///                (<http://page.com> \"my title\")abc"),
76///   Ok(("abc",
77///    (Cow::from("111"), Cow::from("my dog"), Cow::from("/my&dog.png"),
78///     Cow::from("222"), Cow::from("http://page.com"), Cow::from("my title"),
79/// ))));
80/// ```
81pub fn md_img2dest(
82    i: &str,
83) -> nom::IResult<&str, (Cow<str>, Cow<str>, Cow<str>, Cow<str>, Cow<str>, Cow<str>)> {
84    map(
85        nom::sequence::tuple((
86            map_parser(
87                nom::sequence::delimited(tag("["), take_until_unbalanced('[', ']'), tag("]")),
88                tuple((
89                    nom::bytes::complete::take_until("!["),
90                    md_img,
91                    nom::combinator::rest,
92                )),
93            ),
94            md_link_destination_enclosed,
95        )),
96        // ((&str, (Cow<'_, str>, Cow<'_, str>), &str), (Cow<'_, str>, Cow<'_, str>)
97        |((a, (b, c), d), (e, f))| (decode_html_entities(a), b, c, decode_html_entities(d), e, f),
98    )(i)
99}