Skip to content

Commit ecdf21d

Browse files
committed
cm: count ol items from start of each list.
Fixes #323; this fixes OL tasklists incidentally.
1 parent ef4fc35 commit ecdf21d

File tree

2 files changed

+54
-17
lines changed

2 files changed

+54
-17
lines changed

src/cm.rs

+33-12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::ctype::{isalpha, isdigit, ispunct, isspace};
2-
use crate::nodes::TableAlignment;
32
use crate::nodes::{
43
AstNode, ListDelimType, ListType, NodeCodeBlock, NodeHeading, NodeHtmlBlock, NodeLink,
54
NodeMath, NodeTable, NodeValue, NodeWikiLink,
65
};
6+
use crate::nodes::{NodeList, TableAlignment};
77
#[cfg(feature = "shortcodes")]
88
use crate::parser::shortcodes::NodeShortCode;
99
use crate::parser::Options;
@@ -61,6 +61,7 @@ struct CommonMarkFormatter<'a, 'o> {
6161
in_tight_list_item: bool,
6262
custom_escape: Option<fn(&'a AstNode<'a>, u8) -> bool>,
6363
footnote_ix: u32,
64+
ol_stack: Vec<usize>,
6465
}
6566

6667
#[derive(PartialEq, Clone, Copy)]
@@ -98,6 +99,7 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
9899
in_tight_list_item: false,
99100
custom_escape: None,
100101
footnote_ix: 0,
102+
ol_stack: vec![],
101103
}
102104
}
103105

@@ -420,18 +422,37 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
420422
}
421423

422424
fn format_list(&mut self, node: &'a AstNode<'a>, entering: bool) {
423-
if !entering
424-
&& match node.next_sibling() {
425+
let ol_start = match node.data.borrow().value {
426+
NodeValue::List(NodeList {
427+
list_type: ListType::Ordered,
428+
start,
429+
..
430+
}) => Some(start),
431+
_ => None,
432+
};
433+
434+
if entering {
435+
if let Some(start) = ol_start {
436+
println!("pushing {:?} onto ol_stack {:?}", start, self.ol_stack);
437+
self.ol_stack.push(start);
438+
}
439+
} else {
440+
if ol_start.is_some() {
441+
println!("popping ol_stack {:?}", self.ol_stack);
442+
self.ol_stack.pop();
443+
}
444+
445+
if match node.next_sibling() {
425446
Some(next_sibling) => matches!(
426447
next_sibling.data.borrow().value,
427448
NodeValue::CodeBlock(..) | NodeValue::List(..)
428449
),
429450
_ => false,
451+
} {
452+
self.cr();
453+
write!(self, "<!-- end list -->").unwrap();
454+
self.blankline();
430455
}
431-
{
432-
self.cr();
433-
write!(self, "<!-- end list -->").unwrap();
434-
self.blankline();
435456
}
436457
}
437458

@@ -446,11 +467,11 @@ impl<'a, 'o> CommonMarkFormatter<'a, 'o> {
446467
let marker_width = if parent.list_type == ListType::Bullet {
447468
2
448469
} else {
449-
let list_number = match node.data.borrow().value {
450-
NodeValue::Item(ref ni) => ni.start,
451-
NodeValue::TaskItem(_) => parent.start,
452-
_ => unreachable!(),
453-
};
470+
let last_stack = self.ol_stack.last_mut().unwrap();
471+
let list_number = *last_stack;
472+
if entering {
473+
*last_stack += 1;
474+
}
454475
let list_delim = parent.delimiter;
455476
write!(
456477
listmarker,

src/tests/commonmark.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@ use ntest::test_case;
77

88
#[test]
99
fn commonmark_removes_redundant_strong() {
10-
let options = Options::default();
11-
1210
let input = "This is **something **even** better**";
1311
let output = "This is **something even better**\n";
14-
15-
commonmark(input, output, Some(&options));
12+
commonmark(input, output, None);
1613
}
1714

1815
#[test]
@@ -52,7 +49,7 @@ fn math(markdown: &str, cm: &str) {
5249
options.extension.math_dollars = true;
5350
options.extension.math_code = true;
5451

55-
commonmark(markdown, cm, Some(&options));
52+
commonmark(markdown, cm, None);
5653
}
5754

5855
#[test_case("This [[url]] that", "This [[url|url]] that\n")]
@@ -63,3 +60,22 @@ fn wikilinks(markdown: &str, cm: &str) {
6360

6461
commonmark(markdown, cm, Some(&options));
6562
}
63+
#[test]
64+
fn commonmark_relist() {
65+
commonmark(
66+
concat!("3. one\n", "5. two\n",),
67+
// Note that right now we always include enough room for up to two
68+
// digits. TODO: Ideally we determine the maximum digit length before
69+
// getting this far.
70+
concat!("3. one\n", "4. two\n",),
71+
None,
72+
);
73+
74+
let mut options = Options::default();
75+
options.extension.tasklist = true;
76+
commonmark(
77+
concat!("3. [ ] one\n", "5. [ ] two\n",),
78+
concat!("3. [ ] one\n", "4. [ ] two\n",),
79+
Some(&options),
80+
);
81+
}

0 commit comments

Comments
 (0)