From 6a3f210dfc66efd878421c83ab83b72b0f2b03b8 Mon Sep 17 00:00:00 2001 From: KITAITI Makoto Date: Sun, 3 May 2020 21:50:32 +0900 Subject: [PATCH] Keep atmarks and hashes in link (#765) * [REFACTORING]Use DocumentContext during parsing Markdown * Add test case for hash in link * Make DocumentContext derive Debug * Add in_link field in DocumentContext * Don't make hash words tags in link * Add test for atmark in link * Don't make atmark words in link mentions --- plume-common/src/utils.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/plume-common/src/utils.rs b/plume-common/src/utils.rs index 0c5b9ea7..d60db844 100644 --- a/plume-common/src/utils.rs +++ b/plume-common/src/utils.rs @@ -201,6 +201,12 @@ fn process_image<'a, 'b>( } } +#[derive(Default, Debug)] +struct DocumentContext { + in_code: bool, + in_link: bool, +} + /// Returns (HTML, mentions, hashtags) pub fn md_to_html<'a>( md: &str, @@ -224,13 +230,21 @@ pub fn md_to_html<'a>( .map(|evt| process_image(evt, inline, &media_processor)) // Ignore headings, images, and tables if inline = true .scan((vec![], inline), inline_tags) - .scan(false, |in_code, evt| match evt { + .scan(&mut DocumentContext::default(), |ctx, evt| match evt { Event::Start(Tag::CodeBlock(_)) | Event::Start(Tag::Code) => { - *in_code = true; + ctx.in_code = true; Some((vec![evt], vec![], vec![])) } Event::End(Tag::CodeBlock(_)) | Event::End(Tag::Code) => { - *in_code = false; + ctx.in_code = false; + Some((vec![evt], vec![], vec![])) + } + Event::Start(Tag::Link(_, _)) => { + ctx.in_link = true; + Some((vec![evt], vec![], vec![])) + } + Event::End(Tag::Link(_, _)) => { + ctx.in_link = false; Some((vec![evt], vec![], vec![])) } Event::Text(txt) => { @@ -301,7 +315,7 @@ pub fn md_to_html<'a>( } } State::Ready => { - if !*in_code && c == '@' { + if !ctx.in_code && !ctx.in_link && c == '@' { events.push(Event::Text(text_acc.into())); ( events, @@ -311,7 +325,7 @@ pub fn md_to_html<'a>( mentions, hashtags, ) - } else if !*in_code && c == '#' { + } else if !ctx.in_code && !ctx.in_link && c == '#' { events.push(Event::Text(text_acc.into())); ( events, @@ -400,6 +414,7 @@ mod tests { ("not_a@mention", vec![]), ("`@helo`", vec![]), ("```\n@hello\n```", vec![]), + ("[@atmark in link](https://example.org/)", vec![]), ]; for (md, mentions) in tests { @@ -426,6 +441,7 @@ mod tests { (" #spaces ", vec!["spaces"]), ("not_a#hashtag", vec![]), ("#نرم‌افزار_آزاد", vec!["نرم‌افزار_آزاد"]), + ("[#hash in link](https://example.org/)", vec![]), ]; for (md, mentions) in tests {