panache_parser/parser/utils/
container_stack.rs1use super::list_item_buffer::ListItemBuffer;
2use super::text_buffer::{ParagraphBuffer, TextBuffer};
3use crate::parser::blocks::lists::ListMarker;
4
5#[derive(Debug, Clone)]
6pub(crate) enum Container {
7 BlockQuote {
8 },
10 Alert {
11 blockquote_depth: usize,
12 },
13 FencedDiv {
14 },
16 List {
17 marker: ListMarker,
18 base_indent_cols: usize,
19 has_blank_between_items: bool, },
21 ListItem {
22 content_col: usize,
23 buffer: ListItemBuffer, },
25 DefinitionList {
26 },
28 DefinitionItem {
29 },
31 Definition {
32 content_col: usize,
33 plain_open: bool,
34 plain_buffer: TextBuffer, },
36 Paragraph {
37 buffer: ParagraphBuffer, open_inline_math_envs: Vec<String>,
39 open_display_math_dollar_count: Option<usize>,
40 },
41 FootnoteDefinition {
42 content_col: usize,
43 },
44}
45
46pub(crate) struct ContainerStack {
47 pub(crate) stack: Vec<Container>,
48}
49
50const TAB_STOP: usize = 4;
51
52impl ContainerStack {
53 pub(crate) fn new() -> Self {
54 Self { stack: Vec::new() }
55 }
56
57 pub(crate) fn depth(&self) -> usize {
58 self.stack.len()
59 }
60
61 pub(crate) fn last(&self) -> Option<&Container> {
62 self.stack.last()
63 }
64
65 pub(crate) fn push(&mut self, c: Container) {
66 self.stack.push(c);
67 }
68}
69
70pub(crate) fn leading_indent(line: &str) -> (usize, usize) {
72 let mut cols = 0usize;
73 let mut bytes = 0usize;
74 for b in line.bytes() {
75 match b {
76 b' ' => {
77 cols += 1;
78 bytes += 1;
79 }
80 b'\t' => {
81 cols += TAB_STOP - (cols % TAB_STOP);
82 bytes += 1;
83 }
84 _ => break,
85 }
86 }
87 (cols, bytes)
88}
89
90pub(crate) fn byte_index_at_column(line: &str, target_col: usize) -> usize {
92 let mut col = 0usize;
93 let mut idx = 0usize;
94 for (i, b) in line.bytes().enumerate() {
95 if col >= target_col {
96 return idx;
97 }
98 match b {
99 b' ' => {
100 col += 1;
101 idx = i + 1;
102 }
103 b'\t' => {
104 col += TAB_STOP - (col % TAB_STOP);
105 idx = i + 1;
106 }
107 _ => break,
108 }
109 }
110 idx
111}