From 9968aedd7412e9987d100cecf1c61d058432fc51 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 22 Apr 2023 22:34:37 -0400 Subject: [PATCH] Make sure text markup doesn't have interior spaces. --- src/parser/text_markup.rs | 6 ++++++ src/parser/util.rs | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/parser/text_markup.rs b/src/parser/text_markup.rs index db3ce057..1c36c51f 100644 --- a/src/parser/text_markup.rs +++ b/src/parser/text_markup.rs @@ -2,9 +2,11 @@ use nom::branch::alt; use nom::bytes::complete::tag; use nom::character::complete::anychar; use nom::character::complete::line_ending; +use nom::character::complete::multispace1; use nom::character::complete::one_of; use nom::character::complete::space0; use nom::combinator::map; +use nom::combinator::not; use nom::combinator::peek; use nom::combinator::recognize; use nom::combinator::verify; @@ -30,6 +32,7 @@ use crate::parser::Object; use crate::parser::StrikeThrough; use crate::parser::Underline; use crate::parser::Verbatim; +use crate::parser::util::preceded_by_whitespace; #[tracing::instrument(ret, level = "debug")] pub fn text_markup<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Object<'s>> { @@ -112,6 +115,7 @@ fn _text_markup_object<'r, 's, 'x>( ) -> Res<&'s str, Vec>> { let (remaining, _) = pre(context, input)?; let (remaining, open) = tag(marker_symbol)(remaining)?; + let (remaining, _peek_not_whitespace) = peek(not(multispace1))(remaining)?; let text_markup_end_specialized = text_markup_end(open); let parser_context = context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { @@ -148,6 +152,7 @@ fn _text_markup_string<'r, 's, 'x>( ) -> Res<&'s str, &'s str> { let (remaining, _) = pre(context, input)?; let (remaining, open) = tag(marker_symbol)(remaining)?; + let (remaining, _peek_not_whitespace) = peek(not(multispace1))(remaining)?; let text_markup_end_specialized = text_markup_end(open); let parser_context = context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { @@ -208,6 +213,7 @@ fn _text_markup_end<'r, 's, 'x>( input: &'s str, marker_symbol: &'x str, ) -> Res<&'s str, &'s str> { + not(parser_with_context!(preceded_by_whitespace)(context))(input)?; let (remaining, _marker) = terminated( tag(marker_symbol), peek(parser_with_context!(post)(context)), diff --git a/src/parser/util.rs b/src/parser/util.rs index b5847f2e..fe1169ef 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -151,6 +151,28 @@ pub fn start_of_line<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&' Ok((input, ())) } +/// Check that we are at the start of a line +#[tracing::instrument(ret, level = "debug")] +pub fn preceded_by_whitespace<'r, 's>( + context: Context<'r, 's>, + input: &'s str, +) -> Res<&'s str, ()> { + let document_root = context.get_document_root().unwrap(); + let preceding_character = get_one_before(document_root, input) + .map(|slice| slice.chars().next()) + .flatten(); + match preceding_character { + Some('\n') | Some('\r') | Some(' ') | Some('\t') => {} + // If None, we are at the start of the file which is not allowed + None | Some(_) => { + return Err(nom::Err::Error(CustomError::MyError(MyError( + "Not preceded by whitespace.", + )))); + } + }; + Ok((input, ())) +} + /// Pull one non-whitespace character. /// /// This function only operates on spaces, tabs, carriage returns, and line feeds. It does not handle fancy unicode whitespace.