panache_parser/parser/blocks/
paragraphs.rs1use crate::options::ParserOptions;
7use crate::syntax::SyntaxKind;
8use rowan::GreenNodeBuilder;
9
10use crate::parser::blocks::raw_blocks::{extract_environment_name, is_inline_math_environment};
11use crate::parser::utils::container_stack::{Container, ContainerStack};
12use crate::parser::utils::text_buffer::ParagraphBuffer;
13
14fn extract_end_environment_name(line: &str) -> Option<&str> {
15 let trimmed = line.trim_start();
16 if !trimmed.starts_with("\\end{") {
17 return None;
18 }
19 let rest = &trimmed[5..];
20 let close = rest.find('}')?;
21 let name = &rest[..close];
22 if name.is_empty() {
23 return None;
24 }
25 Some(name)
26}
27
28pub(in crate::parser) fn start_paragraph_if_needed(
30 containers: &mut ContainerStack,
31 builder: &mut GreenNodeBuilder<'static>,
32) {
33 if !matches!(containers.last(), Some(Container::Paragraph { .. })) {
34 builder.start_node(SyntaxKind::PARAGRAPH.into());
35 containers.push(Container::Paragraph {
36 buffer: ParagraphBuffer::new(),
37 open_inline_math_envs: Vec::new(),
38 });
39 }
40}
41
42pub(in crate::parser) fn append_paragraph_line(
44 containers: &mut ContainerStack,
45 _builder: &mut GreenNodeBuilder<'static>,
46 line: &str,
47 _config: &ParserOptions,
48) {
49 if let Some(Container::Paragraph {
52 buffer,
53 open_inline_math_envs,
54 }) = containers.stack.last_mut()
55 {
56 buffer.push_text(line);
57
58 let line_no_newline = line.trim_end_matches(&['\r', '\n'][..]);
59 if let Some(env_name) = extract_environment_name(line_no_newline)
60 && is_inline_math_environment(&env_name)
61 {
62 open_inline_math_envs.push(env_name);
63 return;
64 }
65
66 if let Some(end_name) = extract_end_environment_name(line_no_newline)
67 && open_inline_math_envs
68 .last()
69 .is_some_and(|open| open == end_name)
70 {
71 open_inline_math_envs.pop();
72 }
73 }
74}
75
76pub(in crate::parser) fn append_paragraph_marker(
82 containers: &mut ContainerStack,
83 leading_spaces: usize,
84 has_trailing_space: bool,
85) {
86 if let Some(Container::Paragraph { buffer, .. }) = containers.stack.last_mut() {
87 buffer.push_marker(leading_spaces, has_trailing_space);
88 }
89}
90
91pub(in crate::parser) fn has_open_inline_math_environment(containers: &ContainerStack) -> bool {
92 matches!(
93 containers.last(),
94 Some(Container::Paragraph {
95 open_inline_math_envs,
96 ..
97 }) if !open_inline_math_envs.is_empty()
98 )
99}
100
101pub(in crate::parser) fn current_content_col(containers: &ContainerStack) -> usize {
103 containers
104 .stack
105 .iter()
106 .rev()
107 .find_map(|c| match c {
108 Container::ListItem { content_col, .. } => Some(*content_col),
109 Container::FootnoteDefinition { content_col, .. } => Some(*content_col),
110 _ => None,
111 })
112 .unwrap_or(0)
113}