Skip to content

Commit

Permalink
Merge pull request #462 from kivikakk/bw-description-lists
Browse files Browse the repository at this point in the history
Enhance description lists
  • Loading branch information
digitalmoksha authored Nov 26, 2024
2 parents 8b369e5 + fbd8de1 commit dca0e13
Show file tree
Hide file tree
Showing 9 changed files with 628 additions and 152 deletions.
98 changes: 54 additions & 44 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions script/cibuild
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/wikilink
|| failed=1
python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/wikilinks_title_before_pipe.md "$PROGRAM_ARG -e wikilinks-title-before-pipe" \
|| failed=1
python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/description_lists.md "$PROGRAM_ARG -e description-lists" \
|| failed=1

python3 spec_tests.py --no-normalize --spec regression.txt "$PROGRAM_ARG" \
|| failed=1
Expand Down
3 changes: 2 additions & 1 deletion src/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ impl<'o> HtmlFormatter<'o> {
self.cr()?;
self.output.write_all(b"<dl")?;
self.render_sourcepos(node)?;
self.output.write_all(b">")?;
self.output.write_all(b">\n")?;
} else {
self.output.write_all(b"</dl>\n")?;
}
Expand Down Expand Up @@ -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,
};

Expand Down
4 changes: 4 additions & 0 deletions src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<p>` tags when formatted as HTML.
pub tight: bool,
}

/// The type of list.
Expand Down
63 changes: 55 additions & 8 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ pub struct ExtensionOptions {
/// let mut options = Options::default();
/// options.extension.description_lists = true;
/// assert_eq!(markdown_to_html("Term\n\n: Definition", &options),
/// "<dl><dt>Term</dt>\n<dd>\n<p>Definition</p>\n</dd>\n</dl>\n");
/// "<dl>\n<dt>Term</dt>\n<dd>\n<p>Definition</p>\n</dd>\n</dl>\n");
/// ```
#[builder(default)]
pub description_lists: bool,
Expand Down Expand Up @@ -1636,10 +1636,13 @@ impl<'a, 'o> Parser<'a, 'o> {
container.data.borrow_mut().internal_offset = matched;
} else if !indented
&& self.options.extension.description_lists
&& line[self.first_nonspace] == b':'
&& self.parse_desc_list_details(container)
&& unwrap_into(
scanners::description_item_start(&line[self.first_nonspace..]),
&mut matched,
)
&& self.parse_desc_list_details(container, matched)
{
let offset = self.first_nonspace + 1 - self.offset;
let offset = self.first_nonspace + matched - self.offset;
self.advance_offset(line, offset, false);
if strings::is_space_or_tab(line[self.offset]) {
self.advance_offset(line, 1, true);
Expand Down Expand Up @@ -1881,10 +1884,28 @@ impl<'a, 'o> Parser<'a, 'o> {
}
}

fn parse_desc_list_details(&mut self, container: &mut &'a AstNode<'a>) -> bool {
fn parse_desc_list_details(&mut self, container: &mut &'a AstNode<'a>, matched: usize) -> bool {
let mut tight = false;
let last_child = match container.last_child() {
Some(lc) => lc,
None => return false,
None => {
// Happens when the detail line is directly after the term,
// without a blank line between.
if !node_matches!(container, NodeValue::Paragraph) {
// If the container is not a paragraph, then this can't
// be a description list item.
return false;
}

let parent = container.parent();
if parent.is_none() {
return false;
}

tight = true;
*container = parent.unwrap();
container.last_child().unwrap()
}
};

if node_matches!(last_child, NodeValue::Paragraph) {
Expand All @@ -1908,7 +1929,7 @@ impl<'a, 'o> Parser<'a, 'o> {
// All are incorrect; they all give the start line/col of
// the DescriptionDetails, and the end line/col is completely off.
//
// descriptionDetails:
// DescriptionDetails:
// Same as the DescriptionItem. All but last, the end line/col
// is (l+1):0.
//
Expand All @@ -1931,7 +1952,8 @@ impl<'a, 'o> Parser<'a, 'o> {

let metadata = NodeDescriptionItem {
marker_offset: self.indent,
padding: 2,
padding: matched,
tight,
};

let item = self.add_child(
Expand All @@ -1948,6 +1970,31 @@ impl<'a, 'o> Parser<'a, 'o> {

*container = details;

true
} else if node_matches!(last_child, NodeValue::DescriptionItem(..)) {
let parent = last_child.parent().unwrap();
let tight = match last_child.data.borrow().value {
NodeValue::DescriptionItem(ref ndi) => ndi.tight,
_ => false,
};

let metadata = NodeDescriptionItem {
marker_offset: self.indent,
padding: matched,
tight,
};

let item = self.add_child(
parent,
NodeValue::DescriptionItem(metadata),
self.first_nonspace + 1,
);

let details =
self.add_child(item, NodeValue::DescriptionDetails, self.first_nonspace + 1);

*container = details;

true
} else {
false
Expand Down
9 changes: 9 additions & 0 deletions src/scanners.re
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,13 @@ pub fn tasklist(s: &[u8]) -> Option<(usize, u8)> {
*/
}

pub fn description_item_start(s: &[u8]) -> Option<usize> {
let mut cursor = 0;
let len = s.len();
/*!re2c
[:~] ([ \t]+) { return Some(cursor); }
* { return None; }
*/
}

// vim: set ft=rust:
Loading

0 comments on commit dca0e13

Please sign in to comment.