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