Do not consume whitespace in the final plain list item.
This commit is contained in:
parent
56281633f3
commit
7fafbfb6bb
@ -42,18 +42,27 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
|
||||
class: ExitClass::Beta,
|
||||
exit_matcher: &plain_list_end,
|
||||
}));
|
||||
// children stores tuple of (input string, parsed object) so we can re-parse the final item
|
||||
let mut children = Vec::new();
|
||||
let mut first_item_indentation: Option<usize> = None;
|
||||
let mut remaining = input;
|
||||
|
||||
// The final list item does not consume trailing blank lines (which instead get consumed by the list). We have three options here:
|
||||
//
|
||||
// 1. Parse all items while consuming trailing whitespace, then edit the final item to remove trailing whitespace.
|
||||
// 2. Parse all items without consuming trailing whitespace, then edit all but the final one to add in the trailing whitespace.
|
||||
// 3. Re-parse the final item with consume trailing whitespace disabled.
|
||||
//
|
||||
// While #3 is the most slow, it also seems to cleanest and involves the least manual mutation of already-parsed objects so I am going with #3 for now, but we should revisit #1 or #2 when the parser is more developed.
|
||||
|
||||
loop {
|
||||
let list_item = parser_with_context!(plain_list_item)(&parser_context)(remaining);
|
||||
match list_item {
|
||||
Ok((remain, item))
|
||||
if item.indentation == *first_item_indentation.get_or_insert(item.indentation) =>
|
||||
{
|
||||
children.push((remaining, item));
|
||||
remaining = remain;
|
||||
children.push(item);
|
||||
}
|
||||
Ok(_) | Err(_) => {
|
||||
break;
|
||||
@ -66,16 +75,31 @@ pub fn plain_list<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s s
|
||||
}
|
||||
}
|
||||
|
||||
if children.is_empty() {
|
||||
let (final_child_start, _final_item_first_parse) = match children.pop() {
|
||||
Some(final_child) => final_child,
|
||||
None => {
|
||||
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||
"Plain lists require at least one element.",
|
||||
))));
|
||||
}
|
||||
};
|
||||
let final_item_context =
|
||||
parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
|
||||
let (remaining, reparsed_final_item) =
|
||||
parser_with_context!(plain_list_item)(&final_item_context)(final_child_start)?;
|
||||
children.push((final_child_start, reparsed_final_item));
|
||||
|
||||
// TODO: trailing whitespace
|
||||
let (remaining, _trailing_ws) =
|
||||
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||
|
||||
let source = get_consumed(input, remaining);
|
||||
Ok((remaining, PlainList { source, children }))
|
||||
Ok((
|
||||
remaining,
|
||||
PlainList {
|
||||
source,
|
||||
children: children.into_iter().map(|(_start, item)| item).collect(),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
@ -109,6 +133,7 @@ pub fn plain_list_item<'r, 's>(
|
||||
|
||||
let (remaining, _ws) = space1(remaining)?;
|
||||
let parser_context = context
|
||||
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
|
||||
.with_additional_node(ContextElement::ListItem(indent_level))
|
||||
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||
class: ExitClass::Beta,
|
||||
|
Loading…
Reference in New Issue
Block a user