aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-13 10:40:11 +0200
committerLibravatar Titus Wormer <tituswormer@gmail.com>2022-07-13 10:40:11 +0200
commitad8eac98c1468b30c17c339e79b84c37a7b15517 (patch)
treedaffac5b46b474787ebe6e886061510249f37cab
parent86834a02b301bba48c2bd568beb156e604470167 (diff)
downloadmarkdown-rs-ad8eac98c1468b30c17c339e79b84c37a7b15517.tar.gz
markdown-rs-ad8eac98c1468b30c17c339e79b84c37a7b15517.tar.bz2
markdown-rs-ad8eac98c1468b30c17c339e79b84c37a7b15517.zip
Fix to close containers before several (blank) line endings
-rw-r--r--src/compiler.rs23
-rw-r--r--src/content/document.rs24
-rw-r--r--tests/block_quote.rs11
-rw-r--r--tests/code_fenced.rs22
-rw-r--r--tests/list.rs48
5 files changed, 66 insertions, 62 deletions
diff --git a/src/compiler.rs b/src/compiler.rs
index 2d42011..4b38c8d 100644
--- a/src/compiler.rs
+++ b/src/compiler.rs
@@ -241,6 +241,7 @@ struct CompileContext<'a> {
pub tight_stack: Vec<bool>,
/// Fields used to influance the current compilation.
pub slurp_one_line_ending: bool,
+ pub slurp_all_line_endings: bool,
pub tags: bool,
pub ignore_encode: bool,
pub last_was_tag: bool,
@@ -275,6 +276,7 @@ impl<'a> CompileContext<'a> {
definitions: HashMap::new(),
tight_stack: vec![],
slurp_one_line_ending: false,
+ slurp_all_line_endings: false,
tags: true,
ignore_encode: false,
last_was_tag: false,
@@ -381,7 +383,6 @@ impl<'a> CompileContext<'a> {
/// Turn events and codes into a string of HTML.
#[allow(clippy::too_many_lines)]
pub fn compile(events: &[Event], codes: &[Code], options: &Options) -> String {
- // let slurp_all_line_endings = false;
let mut index = 0;
let mut line_ending_inferred: Option<LineEnding> = None;
@@ -718,7 +719,7 @@ fn on_enter_paragraph(context: &mut CompileContext) {
context.tag("<p>".to_string());
}
- // context.slurp_all_line_endings = false;
+ context.slurp_all_line_endings = false;
}
/// Handle [`Enter`][EventType::Enter]:[`Resource`][Token::Resource].
@@ -784,7 +785,7 @@ fn on_exit_block_quote(context: &mut CompileContext) {
context.tight_stack.pop();
context.line_ending_if_needed();
context.tag("</blockquote>".to_string());
- // context.slurp_all_line_endings = false;
+ context.slurp_all_line_endings = false;
}
/// Handle [`Exit`][EventType::Exit]:[`CharacterReferenceMarker`][Token::CharacterReferenceMarker].
@@ -1074,10 +1075,9 @@ fn on_exit_label_text(context: &mut CompileContext) {
/// Handle [`Exit`][EventType::Exit]:[`LineEnding`][Token::LineEnding].
fn on_exit_line_ending(context: &mut CompileContext) {
- // if context.slurp_all_line_endings {
- // // Empty.
- // } else
- if context.slurp_one_line_ending {
+ if context.slurp_all_line_endings {
+ // Empty.
+ } else if context.slurp_one_line_ending {
context.slurp_one_line_ending = false;
} else {
context.push(context.encode_opt(&serialize(
@@ -1156,7 +1156,9 @@ fn on_exit_media(context: &mut CompileContext) {
fn on_exit_paragraph(context: &mut CompileContext) {
let tight = context.tight_stack.last().unwrap_or(&false);
- if !tight {
+ if *tight {
+ context.slurp_all_line_endings = true;
+ } else {
context.tag("</p>".to_string());
}
}
@@ -1281,13 +1283,12 @@ fn on_exit_list_item_value(context: &mut CompileContext) {
/// To do.
fn on_exit_list_item(context: &mut CompileContext) {
- // && !context.slurp_all_line_endings
- if context.last_was_tag {
+ if context.last_was_tag && !context.slurp_all_line_endings {
context.line_ending_if_needed();
}
context.tag("</li>".to_string());
- // context.slurp_all_line_endings = false;
+ context.slurp_all_line_endings = false;
}
/// To do.
diff --git a/src/content/document.rs b/src/content/document.rs
index 27fb73d..7f8a116 100644
--- a/src/content/document.rs
+++ b/src/content/document.rs
@@ -410,6 +410,7 @@ fn flow_end(
let mut index = 0;
let add = info.inject[line_index].0.clone();
+ let mut first_line_ending_in_run: Option<usize> = None;
map.add(0, 0, add);
while index < tokenizer.events.len() {
@@ -419,19 +420,28 @@ fn flow_end(
|| event.token_type == Token::BlankLineEnding
{
if event.event_type == EventType::Enter {
+ first_line_ending_in_run = first_line_ending_in_run.or(Some(index));
let mut add = info.inject[line_index].1.clone();
- let mut deep_index = 0;
- while deep_index < add.len() {
- add[deep_index].point = event.point.clone();
- add[deep_index].index = event.index;
- deep_index += 1;
+ let mut index = 0;
+ while index < add.len() {
+ add[index].point = event.point.clone();
+ add[index].index = event.index;
+ index += 1;
+ }
+ if !add.is_empty() {
+ map.add(first_line_ending_in_run.unwrap(), 0, add);
}
- map.add(index, 0, add);
} else {
line_index += 1;
let add = info.inject[line_index].0.clone();
- map.add(index + 1, 0, add);
+ if !add.is_empty() {
+ map.add(index + 1, 0, add);
+ }
}
+ } else if event.token_type == Token::SpaceOrTab {
+ // Empty to allow whitespace in blank lines.
+ } else {
+ first_line_ending_in_run = None;
}
index += 1;
diff --git a/tests/block_quote.rs b/tests/block_quote.rs
index 8fb4e61..782104f 100644
--- a/tests/block_quote.rs
+++ b/tests/block_quote.rs
@@ -143,12 +143,11 @@ fn block_quote() {
"should support interrupting block quotes w/ blank lines"
);
- // To do: some container bug introduces due to lists?
- // assert_eq!(
- // micromark("> a\n>\nb"),
- // "<blockquote>\n<p>a</p>\n</blockquote>\n<p>b</p>",
- // "should not support interrupting a blank line in a block quotes w/ paragraphs"
- // );
+ assert_eq!(
+ micromark("> a\n>\nb"),
+ "<blockquote>\n<p>a</p>\n</blockquote>\n<p>b</p>",
+ "should not support interrupting a blank line in a block quotes w/ paragraphs"
+ );
assert_eq!(
micromark("> > > a\nb"),
diff --git a/tests/code_fenced.rs b/tests/code_fenced.rs
index b7bfd79..fa9ed5f 100644
--- a/tests/code_fenced.rs
+++ b/tests/code_fenced.rs
@@ -57,12 +57,11 @@ fn code_fenced() {
"should support an eof somewhere in content"
);
- // To do: container exits before (blank) line endings.
- // assert_eq!(
- // micromark("> ```\n> aaa\n\nbbb"),
- // "<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>",
- // "should support no closing sequence in a block quote"
- // );
+ assert_eq!(
+ micromark("> ```\n> aaa\n\nbbb"),
+ "<blockquote>\n<pre><code>aaa\n</code></pre>\n</blockquote>\n<p>bbb</p>",
+ "should support no closing sequence in a block quote"
+ );
assert_eq!(
micromark("```\n\n \n```"),
@@ -227,12 +226,11 @@ fn code_fenced() {
"should not support a closing sequence w/ too much indent, regardless of opening sequence (1)"
);
- // To do: container exits before (blank) line endings.
- // assert_eq!(
- // micromark("> ```\n>\n>\n>\n\na"),
- // "<blockquote>\n<pre><code>\n\n\n</code></pre>\n</blockquote>\n<p>a</p>",
- // "should not support a closing sequence w/ too much indent, regardless of opening sequence (2)"
- // );
+ assert_eq!(
+ micromark("> ```\n>\n>\n>\n\na"),
+ "<blockquote>\n<pre><code>\n\n\n</code></pre>\n</blockquote>\n<p>a</p>",
+ "should not support a closing sequence w/ too much indent, regardless of opening sequence (2)"
+ );
assert_eq!(
micromark("> ```a\nb"),
diff --git a/tests/list.rs b/tests/list.rs
index e45c31d..1eee72a 100644
--- a/tests/list.rs
+++ b/tests/list.rs
@@ -383,19 +383,17 @@ fn list() {
// "should support blank lines between items (2)"
// );
- // To do: list (for some weird reason seen as one list?).
- // assert_eq!(
- // micromark_with_options("- foo\n- bar\n\n<!-- -->\n\n- baz\n- bim", DANGER),
- // "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<!-- -->\n<ul>\n<li>baz</li>\n<li>bim</li>\n</ul>",
- // "should support HTML comments between lists"
- // );
+ assert_eq!(
+ micromark_with_options("- foo\n- bar\n\n<!-- -->\n\n- baz\n- bim", DANGER),
+ "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>\n<!-- -->\n<ul>\n<li>baz</li>\n<li>bim</li>\n</ul>",
+ "should support HTML comments between lists"
+ );
- // To do: list (for some weird reason the HTML is in the list?).
- // assert_eq!(
- // micromark_with_options("- foo\n\n notcode\n\n- foo\n\n<!-- -->\n\n code", DANGER),
- // "<ul>\n<li>\n<p>foo</p>\n<p>notcode</p>\n</li>\n<li>\n<p>foo</p>\n</li>\n</ul>\n<!-- -->\n<pre><code>code\n</code></pre>",
- // "should support HTML comments between lists and indented code"
- // );
+ assert_eq!(
+ micromark_with_options("- foo\n\n notcode\n\n- foo\n\n<!-- -->\n\n code", DANGER),
+ "<ul>\n<li>\n<p>foo</p>\n<p>notcode</p>\n</li>\n<li>\n<p>foo</p>\n</li>\n</ul>\n<!-- -->\n<pre><code>code\n</code></pre>",
+ "should support HTML comments between lists and indented code"
+ );
// To do: list (indent).
// assert_eq!(
@@ -529,14 +527,13 @@ fn list() {
// "should support blank lines in code after an initial blank line"
// );
- // To do: list (blank lines).
- // assert_eq!(
- // micromark(
- // "* a tight item that ends with an html element: `x`\n\nParagraph"
- // ),
- // "<ul>\n<li>a tight item that ends with an html element: <code>x</code></li>\n</ul>\n<p>Paragraph</p>",
- // "should ignore line endings after tight items ending in tags"
- // );
+ assert_eq!(
+ micromark(
+ "* a tight item that ends with an html element: `x`\n\nParagraph"
+ ),
+ "<ul>\n<li>a tight item that ends with an html element: <code>x</code></li>\n</ul>\n<p>Paragraph</p>",
+ "should ignore line endings after tight items ending in tags"
+ );
// To do: list (empty).
// assert_eq!(
@@ -608,12 +605,11 @@ fn list() {
// "should support complex nested and empty lists (3)"
// );
- // To do: list (blank lines in lists?).
- // assert_eq!(
- // micromark_with_options("* a\n\n<!---->\n\n* b", DANGER),
- // "<ul>\n<li>a</li>\n</ul>\n<!---->\n<ul>\n<li>b</li>\n</ul>",
- // "should support the common list breaking comment method"
- // );
+ assert_eq!(
+ micromark_with_options("* a\n\n<!---->\n\n* b", DANGER),
+ "<ul>\n<li>a</li>\n</ul>\n<!---->\n<ul>\n<li>b</li>\n</ul>",
+ "should support the common list breaking comment method"
+ );
// To do: turning things off.
// assert_eq!(