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 },
40 FootnoteDefinition {
41 content_col: usize,
42 },
43}
44
45pub(crate) struct ContainerStack {
46 pub(crate) stack: Vec<Container>,
47}
48
49const TAB_STOP: usize = 4;
50
51impl ContainerStack {
52 pub(crate) fn new() -> Self {
53 Self { stack: Vec::new() }
54 }
55
56 pub(crate) fn depth(&self) -> usize {
57 self.stack.len()
58 }
59
60 pub(crate) fn last(&self) -> Option<&Container> {
61 self.stack.last()
62 }
63
64 pub(crate) fn push(&mut self, c: Container) {
65 self.stack.push(c);
66 }
67}
68
69pub(crate) fn leading_indent(line: &str) -> (usize, usize) {
71 let mut cols = 0usize;
72 let mut bytes = 0usize;
73 for b in line.bytes() {
74 match b {
75 b' ' => {
76 cols += 1;
77 bytes += 1;
78 }
79 b'\t' => {
80 cols += TAB_STOP - (cols % TAB_STOP);
81 bytes += 1;
82 }
83 _ => break,
84 }
85 }
86 (cols, bytes)
87}
88
89pub(crate) fn byte_index_at_column(line: &str, target_col: usize) -> usize {
91 let mut col = 0usize;
92 let mut idx = 0usize;
93 for (i, b) in line.bytes().enumerate() {
94 if col >= target_col {
95 return idx;
96 }
97 match b {
98 b' ' => {
99 col += 1;
100 idx = i + 1;
101 }
102 b'\t' => {
103 col += TAB_STOP - (col % TAB_STOP);
104 idx = i + 1;
105 }
106 _ => break,
107 }
108 }
109 idx
110}