From 2e3b7abaa9877b658fa4f8f2612acc617dff60bb Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 12 Jul 2022 17:47:08 +0200 Subject: Fix a lot of list things * Add `ListItem`, `ListOrdered`, and `ListUnordered` tokens * Add support for multiline list items * Add support for tight lists * Fix bug where 10 digit long list item values worked * Fix skip bug when skipping over nested events --- src/compiler.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 20 deletions(-) (limited to 'src/compiler.rs') diff --git a/src/compiler.rs b/src/compiler.rs index 753d85f..2d42011 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -447,7 +447,8 @@ pub fn compile(events: &[Event], codes: &[Code], options: &Options) -> String { // To do: sort. enter_map.insert(Token::ListItemMarker, on_enter_list_item_marker); - enter_map.insert(Token::List, on_enter_list); + enter_map.insert(Token::ListOrdered, on_enter_list); + enter_map.insert(Token::ListUnordered, on_enter_list); let mut exit_map: Map = HashMap::new(); exit_map.insert(Token::AutolinkEmail, on_exit_autolink_email); @@ -525,8 +526,10 @@ pub fn compile(events: &[Event], codes: &[Code], options: &Options) -> String { exit_map.insert(Token::ThematicBreak, on_exit_thematic_break); // To do: sort. - exit_map.insert(Token::List, on_exit_list); exit_map.insert(Token::ListItemValue, on_exit_list_item_value); + exit_map.insert(Token::ListItem, on_exit_list_item); + exit_map.insert(Token::ListOrdered, on_exit_list); + exit_map.insert(Token::ListUnordered, on_exit_list); // Handle one event. let handle = |context: &mut CompileContext, index: usize| { @@ -708,8 +711,14 @@ fn on_enter_link(context: &mut CompileContext) { /// Handle [`Enter`][EventType::Enter]:[`Paragraph`][Token::Paragraph]. fn on_enter_paragraph(context: &mut CompileContext) { - context.line_ending_if_needed(); - context.tag("

".to_string()); + let tight = context.tight_stack.last().unwrap_or(&false); + + if !tight { + context.line_ending_if_needed(); + context.tag("

".to_string()); + } + + // context.slurp_all_line_endings = false; } /// Handle [`Enter`][EventType::Enter]:[`Resource`][Token::Resource]. @@ -1145,7 +1154,11 @@ fn on_exit_media(context: &mut CompileContext) { /// Handle [`Exit`][EventType::Exit]:[`Paragraph`][Token::Paragraph]. fn on_exit_paragraph(context: &mut CompileContext) { - context.tag("

".to_string()); + let tight = context.tight_stack.last().unwrap_or(&false); + + if !tight { + context.tag("

".to_string()); + } } /// Handle [`Exit`][EventType::Exit]:[`ReferenceString`][Token::ReferenceString]. @@ -1187,14 +1200,58 @@ fn on_exit_thematic_break(context: &mut CompileContext) { } // To do: sort. +/// To do (onenterlist{un,}ordered) +fn on_enter_list(context: &mut CompileContext) { + let events = &context.events; + let mut index = context.index; + let mut balance = 0; + let mut loose = false; + let token_type = &events[index].token_type; + + while index < events.len() { + let event = &events[index]; + + if event.event_type == EventType::Enter { + balance += 1; + } else { + balance -= 1; + + // Blank line directly in list or directly in list item. + if balance < 3 && event.token_type == Token::BlankLineEnding { + loose = true; + break; + } + + // Done. + if balance == 0 && event.token_type == *token_type { + break; + } + } + + index += 1; + } + + println!("list: {:?} {:?}", token_type, loose); + context.tight_stack.push(!loose); + context.line_ending_if_needed(); + // Note: no `>`. + context.tag(format!( + "<{}", + if *token_type == Token::ListOrdered { + "ol" + } else { + "ul" + } + )); + context.expect_first_item = Some(true); +} + /// To do fn on_enter_list_item_marker(context: &mut CompileContext) { let expect_first_item = context.expect_first_item.take().unwrap(); if expect_first_item { context.tag(">".to_string()); - } else { - on_exit_list_item(context); } context.line_ending_if_needed(); @@ -1204,15 +1261,6 @@ fn on_enter_list_item_marker(context: &mut CompileContext) { context.last_was_tag = false; } -/// To do (onenterlist{un,}ordered) -fn on_enter_list(context: &mut CompileContext) { - // To do: !token._loose - context.tight_stack.push(false); - context.line_ending_if_needed(); - context.tag("".to_string()); // To do: `ol` / `ul`. + context.tag("".to_string()); // context.slurp_all_line_endings = false; } /// To do. fn on_exit_list(context: &mut CompileContext) { - on_exit_list_item(context); + let tag_name = if context.events[context.index].token_type == Token::ListOrdered { + "ol" + } else { + "ul" + }; context.tight_stack.pop(); context.line_ending(); - context.tag("".to_string()); // To do: `ol` / `ul`. + context.tag(format!("", tag_name)); } -- cgit