diff options
author | Titus Wormer <tituswormer@gmail.com> | 2022-07-13 11:26:22 +0200 |
---|---|---|
committer | Titus Wormer <tituswormer@gmail.com> | 2022-07-13 11:26:22 +0200 |
commit | fb185e801e7d2002948d0b4e91ee06767e13ed00 (patch) | |
tree | 8e0ea5d1b92e794cfa7efbcab7b98d81e13b862f | |
parent | ad8eac98c1468b30c17c339e79b84c37a7b15517 (diff) | |
download | markdown-rs-fb185e801e7d2002948d0b4e91ee06767e13ed00.tar.gz markdown-rs-fb185e801e7d2002948d0b4e91ee06767e13ed00.tar.bz2 markdown-rs-fb185e801e7d2002948d0b4e91ee06767e13ed00.zip |
Fix lists in lists and some other bugs
-rw-r--r-- | src/construct/list.rs | 52 | ||||
-rw-r--r-- | src/content/document.rs | 8 | ||||
-rw-r--r-- | src/util/skip.rs | 6 | ||||
-rw-r--r-- | tests/list.rs | 80 |
4 files changed, 68 insertions, 78 deletions
diff --git a/src/construct/list.rs b/src/construct/list.rs index 27180a8..960c0eb 100644 --- a/src/construct/list.rs +++ b/src/construct/list.rs @@ -155,7 +155,6 @@ fn marker(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { tokenizer.enter(Token::ListItemMarker); tokenizer.consume(code); tokenizer.exit(Token::ListItemMarker); - println!("check:blank_line:before"); (State::Fn(Box::new(marker_after)), None) } @@ -187,7 +186,6 @@ fn on_blank(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { /// To do. fn marker_after_after(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { - println!("marker:after:before"); let interrupt = tokenizer.interrupt; tokenizer.attempt(list_item_prefix_whitespace, move |ok| { println!("marker:after:after: {:?} {:?}", ok, interrupt); @@ -240,7 +238,6 @@ fn nok(_tokenizer: &mut Tokenizer, _code: Code) -> StateFnResult { /// To do. pub fn cont(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { - println!("cont:check:blank:before"); tokenizer.check(blank_line, |ok| { println!("cont:check:blank:after: {:?}", ok); let func = if ok { blank_cont } else { not_blank_cont }; @@ -270,14 +267,13 @@ pub fn not_blank_cont(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { index > 0 && tokenizer.events[index - 1].token_type == Token::BlankLineEnding; let mut further_blank = false; - if currently_blank { + if currently_blank && index > 3 { let before = skip::opt_back(&tokenizer.events, index - 3, &[Token::SpaceOrTab]); further_blank = tokenizer.events[before].token_type == Token::BlankLineEnding; } if further_blank || !matches!(code, Code::VirtualSpace | Code::Char('\t' | ' ')) { println!("cont: not blank after further blank, or not blank w/o whitespace"); - println!("cont:nok:1"); (State::Nok, None) } else { println!("cont: not blank"); @@ -313,7 +309,8 @@ pub fn resolve(tokenizer: &mut Tokenizer) -> Vec<Event> { let mut index = 0; let mut balance = 0; - let mut list_items: Vec<(Kind, usize, usize, usize)> = vec![]; + let mut lists_wip: Vec<(Kind, usize, usize, usize)> = vec![]; + let mut lists: Vec<(Kind, usize, usize, usize)> = vec![]; // To do: track balance? Or, check what’s between them? while index < tokenizer.events.len() { @@ -330,12 +327,12 @@ pub fn resolve(tokenizer: &mut Tokenizer) -> Vec<Event> { let kind = Kind::from_code(codes[0]); let current = (kind, balance, index, end); - let previous = list_items.last(); + let mut list_index = lists_wip.len(); let mut matched = false; - // There’s a previous list item. - if let Some(previous) = previous { - // …with the same marker and depth, and with only (blank) line endings between them. + while list_index > 0 { + list_index -= 1; + let previous = &lists_wip[list_index]; if previous.0 == current.0 && previous.1 == current.1 && skip::opt( @@ -344,21 +341,24 @@ pub fn resolve(tokenizer: &mut Tokenizer) -> Vec<Event> { &[Token::LineEnding, Token::BlankLineEnding], ) == current.2 { + println!("prev:match {:?} {:?}", previous, current); + let previous_mut = &mut lists_wip[list_index]; + previous_mut.3 = current.3; + let mut remainder = lists_wip.drain((list_index + 1)..).collect::<Vec<_>>(); + lists.append(&mut remainder); matched = true; + break; } + + println!( + "todo: move them over to `lists` at some point? {:?}", + previous + ); } - if matched { - let previous = list_items.last_mut().unwrap(); - previous.3 = current.3; - } else { - // let previous = list_items.pop(); - // if let Some(previous) = previous { - // lists.push(previous); - // } - - println!("prev:!match {:?} {:?}", previous, current); - list_items.push(current); + if !matched { + println!("prev:!match {:?} {:?}", lists_wip, current); + lists_wip.push(current); } println!("enter: {:?}", event.token_type); @@ -372,9 +372,11 @@ pub fn resolve(tokenizer: &mut Tokenizer) -> Vec<Event> { index += 1; } + lists.append(&mut lists_wip); + let mut index = 0; - while index < list_items.len() { - let list_item = &list_items[index]; + while index < lists.len() { + let list_item = &lists[index]; let mut list_start = tokenizer.events[list_item.2].clone(); let token_type = if matches!(list_item.0, Kind::Paren | Kind::Dot) { Token::ListOrdered @@ -384,7 +386,7 @@ pub fn resolve(tokenizer: &mut Tokenizer) -> Vec<Event> { list_start.token_type = token_type.clone(); let mut list_end = tokenizer.events[list_item.3].clone(); list_end.token_type = token_type; - println!("inject: {:?} {:?}", list_start, list_end); + println!("inject:list: {:?} {:?}", list_start, list_end); edit_map.add(list_item.2, 0, vec![list_start]); edit_map.add(list_item.3 + 1, 0, vec![list_end]); @@ -392,7 +394,7 @@ pub fn resolve(tokenizer: &mut Tokenizer) -> Vec<Event> { index += 1; } - println!("list items: {:#?}", list_items); + println!("list items: {:#?}", lists); let events = edit_map.consume(&mut tokenizer.events); diff --git a/src/content/document.rs b/src/content/document.rs index 7f8a116..b29e4b9 100644 --- a/src/content/document.rs +++ b/src/content/document.rs @@ -275,7 +275,6 @@ fn exit_containers( let mut index = 0; while index < token_types.len() { let token_type = &token_types[index]; - println!("creating exit: {:?}", token_type); exits.push(Event { event_type: EventType::Exit, @@ -295,14 +294,13 @@ fn exit_containers( if !exits.is_empty() { let before = if before { 1 } else { 0 }; let mut index = info.inject.len() - 1; - println!("inject: {:?} {:?}", info.inject.len() - 1, before); - if before >= index { + if before > index { // To do: maybe, if this branch happens, it’s a bug? println!("inject:0: {:?}", index); index = 0; } else { index -= before; - println!("set: {:?}", index); + println!("inject:set: {:?}", index); } info.inject[index].1.append(&mut exits); } @@ -435,6 +433,8 @@ fn flow_end( line_index += 1; let add = info.inject[line_index].0.clone(); if !add.is_empty() { + // No longer empty. + first_line_ending_in_run = None; map.add(index + 1, 0, add); } } diff --git a/src/util/skip.rs b/src/util/skip.rs index d7b3896..10ba364 100644 --- a/src/util/skip.rs +++ b/src/util/skip.rs @@ -59,17 +59,11 @@ fn skip_opt_with_direction( }; if events[index].token_type == *current && balance == 0 { - println!( - "close:it! {:?} {:?} {:?}", - events[index].token_type, balance, index - ); index = if forward { index + 1 } else { index - 1 }; - println!("index:break: {:?}", index); break; } index = if forward { index + 1 } else { index - 1 }; - println!("index:loop: {:?}", index); } } diff --git a/tests/list.rs b/tests/list.rs index 1eee72a..fd511db 100644 --- a/tests/list.rs +++ b/tests/list.rs @@ -416,7 +416,7 @@ fn list() { // "should not support lists in lists w/ too few spaces (3)" // ); - // To do: list (seen as seeveral lists?). + // To do: list (seen as several lists?). // assert_eq!( // micromark("1. a\n\n 2. b\n\n 3. c"), // "<ol>\n<li>\n<p>a</p>\n</li>\n<li>\n<p>b</p>\n</li>\n</ol>\n<pre><code>3. c\n</code></pre>", @@ -429,12 +429,11 @@ fn list() { "should support loose lists w/ a blank line between (1)" ); - // To do: list (multiple blank lines). - // assert_eq!( - // micromark("* a\n*\n\n* c"), - // "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>c</p>\n</li>\n</ul>", - // "should support loose lists w/ a blank line between (2)" - // ); + assert_eq!( + micromark("* a\n*\n\n* c"), + "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>c</p>\n</li>\n</ul>", + "should support loose lists w/ a blank line between (2)" + ); // To do: list (indent). // assert_eq!( @@ -513,12 +512,11 @@ fn list() { // ); // Extra. - // To do: list (empty). - // assert_eq!( - // micromark("* a\n*\n\n \n\t\n* b"), - // "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>b</p>\n</li>\n</ul>", - // "should support continued list items after an empty list item w/ many blank lines" - // ); + assert_eq!( + micromark("* a\n*\n\n \n\t\n* b"), + "<ul>\n<li>\n<p>a</p>\n</li>\n<li></li>\n<li>\n<p>b</p>\n</li>\n</ul>", + "should support continued list items after an empty list item w/ many blank lines" + ); // To do: list (indent). // assert_eq!( @@ -535,75 +533,71 @@ fn list() { "should ignore line endings after tight items ending in tags" ); - // To do: list (empty). - // assert_eq!( - // micromark("* foo\n\n*\n\n* bar"), - // "<ul>\n<li>\n<p>foo</p>\n</li>\n<li></li>\n<li>\n<p>bar</p>\n</li>\n</ul>", - // "should support empty items in a spread list" - // ); + assert_eq!( + micromark("* foo\n\n*\n\n* bar"), + "<ul>\n<li>\n<p>foo</p>\n</li>\n<li></li>\n<li>\n<p>bar</p>\n</li>\n</ul>", + "should support empty items in a spread list" + ); - // To do: list (slurp?). + // To do: list (indent). // assert_eq!( // micromark("- ```\n\n ```"), // "<ul>\n<li>\n<pre><code>\n</code></pre>\n</li>\n</ul>", // "should remove indent of code (fenced) in list (0 space)" // ); - // To do: list (slurp?). + // To do: list (indent, slurp?). // assert_eq!( // micromark("- ```\n \n ```"), // "<ul>\n<li>\n<pre><code>\n</code></pre>\n</li>\n</ul>", // "should remove indent of code (fenced) in list (1 space)" // ); - // To do: list (slurp?). + // To do: list (indent, slurp?). // assert_eq!( // micromark("- ```\n \n ```"), // "<ul>\n<li>\n<pre><code>\n</code></pre>\n</li>\n</ul>", // "should remove indent of code (fenced) in list (2 spaces)" // ); - // To do: list (slurp?). + // To do: list (indent, slurp?). // assert_eq!( // micromark("- ```\n \n ```"), // "<ul>\n<li>\n<pre><code> \n</code></pre>\n</li>\n</ul>", // "should remove indent of code (fenced) in list (3 spaces)" // ); - // To do: list (slurp?). + // To do: list (indent, slurp?). // assert_eq!( // micromark("- ```\n \n ```"), // "<ul>\n<li>\n<pre><code> \n</code></pre>\n</li>\n</ul>", // "should remove indent of code (fenced) in list (4 spaces)" // ); - // To do: list (slurp?). + // To do: list (indent, slurp?). // assert_eq!( // micromark("- ```\n\t\n ```"), // "<ul>\n<li>\n<pre><code> \n</code></pre>\n</li>\n</ul>", // "should remove indent of code (fenced) in list (1 tab)" // ); - // To do: list (empty). - // assert_eq!( - // micromark("- +\n-"), - // "<ul>\n<li>\n<ul>\n<li></li>\n</ul>\n</li>\n<li></li>\n</ul>", - // "should support complex nested and empty lists (1)" - // ); + assert_eq!( + micromark("- +\n-"), + "<ul>\n<li>\n<ul>\n<li></li>\n</ul>\n</li>\n<li></li>\n</ul>", + "should support complex nested and empty lists (1)" + ); - // To do: list (empty). - // assert_eq!( - // micromark("- 1.\n-"), - // "<ul>\n<li>\n<ol>\n<li></li>\n</ol>\n</li>\n<li></li>\n</ul>", - // "should support complex nested and empty lists (2)" - // ); + assert_eq!( + micromark("- 1.\n-"), + "<ul>\n<li>\n<ol>\n<li></li>\n</ol>\n</li>\n<li></li>\n</ul>", + "should support complex nested and empty lists (2)" + ); - // To do: list (empty). - // assert_eq!( - // micromark("* - +\n* -"), - // "<ul>\n<li>\n<ul>\n<li>\n<ul>\n<li></li>\n</ul>\n</li>\n</ul>\n</li>\n<li>\n<ul>\n<li></li>\n</ul>\n</li>\n</ul>", - // "should support complex nested and empty lists (3)" - // ); + assert_eq!( + micromark("* - +\n* -"), + "<ul>\n<li>\n<ul>\n<li>\n<ul>\n<li></li>\n</ul>\n</li>\n</ul>\n</li>\n<li>\n<ul>\n<li></li>\n</ul>\n</li>\n</ul>", + "should support complex nested and empty lists (3)" + ); assert_eq!( micromark_with_options("* a\n\n<!---->\n\n* b", DANGER), |