diff --git a/src/html.rs b/src/html.rs index b759711c..0d633c6b 100644 --- a/src/html.rs +++ b/src/html.rs @@ -663,6 +663,7 @@ impl<'o> HtmlFormatter<'o> { .map(|n| n.data.borrow().value.clone()) { Some(NodeValue::List(nl)) => nl.tight, + Some(NodeValue::DescriptionItem(nd)) => nd.tight, _ => false, }; diff --git a/src/nodes.rs b/src/nodes.rs index ec6e549c..85407a7a 100644 --- a/src/nodes.rs +++ b/src/nodes.rs @@ -313,6 +313,10 @@ pub struct NodeDescriptionItem { /// Number of characters between the start of the list marker and the item text (including the list marker(s)). pub padding: usize, + + /// Whether the list is [tight](https://github.github.com/gfm/#tight), i.e. whether the + /// paragraphs are wrapped in `
` tags when formatted as HTML. + pub tight: bool, } /// The type of list. diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 03b8d5de..d2af15d0 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1640,7 +1640,7 @@ impl<'a, 'o> Parser<'a, 'o> { scanners::description_item_start(&line[self.first_nonspace..]), &mut matched, ) - && self.parse_desc_list_details(container) + && self.parse_desc_list_details(container, matched) { let offset = self.first_nonspace + matched - self.offset; self.advance_offset(line, offset, false); @@ -1884,14 +1884,15 @@ impl<'a, 'o> Parser<'a, 'o> { } } - fn parse_desc_list_details(&mut self, node: &mut &'a AstNode<'a>) -> bool { + fn parse_desc_list_details(&mut self, node: &mut &'a AstNode<'a>, matched: usize) -> bool { let container = node; - + let mut tight = false; let last_child = match container.last_child() { Some(lc) => lc, None => { // Happens when the detail line is directly after the term, // without a blank line between. + tight = true; *container = container.parent().unwrap(); container.last_child().unwrap() } @@ -1941,7 +1942,8 @@ impl<'a, 'o> Parser<'a, 'o> { let metadata = NodeDescriptionItem { marker_offset: self.indent, - padding: 2, + padding: matched, + tight, }; let item = self.add_child( @@ -1961,11 +1963,15 @@ impl<'a, 'o> Parser<'a, 'o> { true } else if node_matches!(last_child, NodeValue::DescriptionItem(..)) { let parent = last_child.parent().unwrap(); - reopen_ast_nodes(parent); + let tight = match last_child.data.borrow().value { + NodeValue::DescriptionItem(ref ncb) => ncb.tight, + _ => false, + }; let metadata = NodeDescriptionItem { marker_offset: self.indent, - padding: 2, + padding: matched, + tight, }; let item = self.add_child( diff --git a/src/tests/description_lists.rs b/src/tests/description_lists.rs index 13f11e9f..f555e5cb 100644 --- a/src/tests/description_lists.rs +++ b/src/tests/description_lists.rs @@ -1,7 +1,7 @@ use super::*; #[test] -fn description_lists() { +fn description_lists_loose() { html_opts!( [extension.description_lists], concat!( diff --git a/src/tests/fixtures/description_lists.md b/src/tests/fixtures/description_lists.md index a9ca0fc4..5f689014 100644 --- a/src/tests/fixtures/description_lists.md +++ b/src/tests/fixtures/description_lists.md @@ -11,9 +11,8 @@ with `:` (after 0-2 spaces); subsequent lines must be indented unless they are lazy paragraph continuations. -There is no distinction between a "tight" list or a -"loose" list. Definitions are always wrapped in `
` -tags. +The list is tight if there is no blank line between +the term and the first definition, otherwise loose. ```````````````````````````````` example apple @@ -24,13 +23,9 @@ orange .
red fruit
-orange fruit
-red fruit
-orange fruit
-red fruit
-computer company
-orange fruit
-telecom company
-red fruit
-orange fruit
-Foo
baz
-bor
-