diff --git a/src/parser/footnote_definition.rs b/src/parser/footnote_definition.rs index be8b0e3f..9d5d79a6 100644 --- a/src/parser/footnote_definition.rs +++ b/src/parser/footnote_definition.rs @@ -13,6 +13,7 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::OrgSource; +use super::util::include_input; use super::util::WORD_CONSTITUENT_CHARACTERS; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -63,11 +64,22 @@ pub fn footnote_definition<'b, 'g, 'r, 's>( let parser_context = context.with_additional_node(&contexts[0]); let parser_context = parser_context.with_additional_node(&contexts[1]); let parser_context = parser_context.with_additional_node(&contexts[2]); - // TODO: The problem is we are not accounting for trailing whitespace like we do in section. Maybe it would be easier if we passed down whether or not to parse trailing whitespace into the element matcher similar to how tag takes in parameters. let element_matcher = parser_with_context!(element(true))(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); - let (remaining, (children, _exit_contents)) = - many_till(element_matcher, exit_matcher)(remaining)?; + let (mut remaining, (mut children, _exit_contents)) = + many_till(include_input(element_matcher), exit_matcher)(remaining)?; + + // Re-parse the last element of the footnote definition with consume trailing whitespace off because the trailing whitespace needs to belong to the footnote definition, not the contents. + if context.should_consume_trailing_whitespace() { + if let Some((final_item_input, _)) = children.pop() { + let final_item_context = ContextElement::ConsumeTrailingWhitespace(false); + let final_item_context = parser_context.with_additional_node(&final_item_context); + let (remain, reparsed_final_item) = + parser_with_context!(element(true))(&final_item_context)(final_item_input)?; + children.push((final_item_input, reparsed_final_item)); + remaining = remain; + } + } let source = get_consumed(input, remaining); Ok(( @@ -75,7 +87,7 @@ pub fn footnote_definition<'b, 'g, 'r, 's>( FootnoteDefinition { source: source.into(), label: lbl.into(), - children, + children: children.into_iter().map(|(_, item)| item).collect(), }, )) } diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index bc3a4fec..4f4bc498 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -19,6 +19,7 @@ use nom::sequence::tuple; use super::element_parser::element; use super::object_parser::standard_set_object; use super::org_source::OrgSource; +use super::util::include_input; use super::util::non_whitespace_character; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -225,18 +226,6 @@ pub fn plain_list_item<'b, 'g, 'r, 's>( )); } -fn include_input<'s, F, O>( - mut inner: F, -) -> impl FnMut(OrgSource<'s>) -> Res, (OrgSource<'s>, O)> -where - F: FnMut(OrgSource<'s>) -> Res, O>, -{ - move |input: OrgSource<'_>| { - let (remaining, output) = inner(input)?; - Ok((remaining, (input, output))) - } -} - #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn bullet<'s>(i: OrgSource<'s>) -> Res, OrgSource<'s>> { alt(( diff --git a/src/parser/util.rs b/src/parser/util.rs index e521079c..53deb7c2 100644 --- a/src/parser/util.rs +++ b/src/parser/util.rs @@ -211,3 +211,15 @@ pub fn text_until_eol<'r, 's>( .map(|(_remaining, line)| Into::<&str>::into(line))?; Ok(line.trim()) } + +pub fn include_input<'s, F, O>( + mut inner: F, +) -> impl FnMut(OrgSource<'s>) -> Res, (OrgSource<'s>, O)> +where + F: FnMut(OrgSource<'s>) -> Res, O>, +{ + move |input: OrgSource<'_>| { + let (remaining, output) = inner(input)?; + Ok((remaining, (input, output))) + } +}