1use crate::parser::Parser;
2use crate::support::{RawListLine, list_marker_at};
3use crate::{Item, ListItem};
4
5impl Parser<'_> {
6 pub(crate) fn parse_list(&mut self) {
10 let raw = self.collect_list_lines();
11 if raw.is_empty() {
12 return;
13 }
14 let mut i = 0;
15 while i < raw.len() {
16 let (item, new_i) = self.build_list_at(&raw, i);
17 self.items.push(item);
18 i = new_i;
19 }
20 }
21
22 fn collect_list_lines(&mut self) -> Vec<RawListLine> {
23 let bytes = self.src.as_bytes();
24 let mut out: Vec<RawListLine> = Vec::new();
25 while self.pos < bytes.len() {
26 if self.at_blank_line() {
27 break;
28 }
29 let Some((indent, ordered, content_start)) = list_marker_at(bytes, self.pos) else {
30 break;
31 };
32 let (line_start, content_end, line_end) = self.current_line_bounds();
33 out.push(RawListLine {
34 indent,
35 ordered,
36 content_start,
37 content_end,
38 line_start,
39 });
40 self.pos = line_end;
41 }
42 out
43 }
44
45 fn build_list_at(&mut self, raw: &[RawListLine], start: usize) -> (Item, usize) {
47 let base_indent = raw[start].indent;
48 let base_ordered = raw[start].ordered;
49 let mut items: Vec<ListItem> = Vec::new();
50 let mut last_end = raw[start].content_end;
51 let mut i = start;
52 while i < raw.len() {
53 let cur = &raw[i];
54 if cur.indent != base_indent || cur.ordered != base_ordered {
55 break;
56 }
57 let slice = &self.src[cur.content_start..cur.content_end];
58 let inlines = self.parse_inlines(slice, cur.content_start);
59 let item_span = self.span(cur.line_start, cur.content_end);
60 let mut item = ListItem {
61 inlines,
62 children: Vec::new(),
63 span: item_span,
64 };
65 last_end = last_end.max(cur.content_end);
66 i += 1;
67 while i < raw.len() && raw[i].indent > base_indent {
68 let (nested, new_i) = self.build_list_at(raw, i);
69 if let Item::List { span, .. } = &nested {
70 last_end = last_end.max(span.end());
71 }
72 item.children.push(nested);
73 i = new_i;
74 }
75 items.push(item);
76 }
77 let span = self.span(raw[start].line_start, last_end);
78 (
79 Item::List {
80 ordered: base_ordered,
81 items,
82 span,
83 },
84 i,
85 )
86 }
87}